1
0
mirror of https://gitlab.os-k.eu/os-k-team/kvisc.git synced 2023-08-25 14:05:46 +02:00
This commit is contained in:
julianb0 2019-05-30 12:19:38 +02:00
parent b21b289c6d
commit 2ca9869233
No known key found for this signature in database
GPG Key ID: DDF8325C95299A62
6 changed files with 178 additions and 117 deletions

View File

@ -5,16 +5,18 @@ all: kas
kpc:
@cd pc && make --no-print-directory
@mv pc/k.exe out/k.exe
kas: kpc as/k-as.py as/regs.lst
@cp pc/instrs/instrs.lst as
@rm -f pc/instrs/instrs.lst
asm: os/dos.k
@cd os && ../as/k-as.py dos.k 0x100000 a.out
asm: dos/dos.k dos/print.k
@as/k-as.py dos/dos.k 0x100000 out/a.out
test: kas asm
@pc/k.exe os/a.out > os/stdout.txt
@out/k.exe out/a.out > out/stdout.txt
disasm: kas asm
@pc/k.exe os/a.out -d
@out/k.exe os/a.out -d
@mv fwprog.dis out

View File

@ -14,24 +14,26 @@ if len(sys.argv) != 4:
.format(sys.argv[0]))
sys.exit(1)
instrs = open(".{}.instr".format(sys.argv[3]), "w+")
b_data = open(".{}.data".format(sys.argv[3]), "w+b")
b_text = open(".{}.text".format(sys.argv[3]), "w+b")
source = TemporaryFile(mode="w+")
instrs = TemporaryFile(mode="w+")
b_data = TemporaryFile(mode="w+b")
b_text = TemporaryFile(mode="w+b")
lst_regs = open(os.path.join(sys.path[0], "regs.lst"))
lst_instrs = open(os.path.join(sys.path[0], "instrs.lst"))
fi = open(sys.argv[1])
main_src = open(sys.argv[1])
b_out = open(sys.argv[3], "wb")
start_addr = int(sys.argv[2], base=0)
def leave():
fi.close()
source.close()
instrs.close()
b_out.close()
b_data.close()
b_text.close()
main_src.close()
lst_regs.close()
lst_instrs.close()
@ -95,88 +97,51 @@ def parse_lst_instrs():
#-------------------------------------------------------------------------------
def parse_preproc(line):
global pdata
inc_depth = 0
inc_depth_max = 16
tok = line.split(' ', 2)
# Quickly goes through source file and resolves "include" directives ONLY
def do_includes(fi):
global inc_depth
for _, line in enumerate(fi):
line = line.rstrip()
tok = line.split(' ', 1)
#for word in tok:
# if not name_valid(word):
# print("Invalid token in line: {}".format(line))
# return
if len(tok) == 0:
continue
# preprocessor
if len(tok) > 1 and tok[1] == ':=':
if len(tok) < 3:
print("Invalid format: {}".format(line))
leave()
sys.exit(1)
pdefs[tok[0]] = tok[2]
return
# .data
if len(tok) > 1 and tok[1] == '=':
if len(tok) < 3:
print("Invalid format: {}".format(line))
leave()
sys.exit(1)
if tok[0] == "include":
if len(tok) == 1:
print("Missing parameter for include directive")
leave()
sys.exit(1)
if is_number(tok[2]):
plabels_data[tok[0]] = pdata
written = b_data.write(int(tok[2], base=0).to_bytes(8, byteorder='little', signed=False))
assert(written == 8)
pdata += written
if tok[1][0] not in "'\"" or tok[1][-1] != tok[1][0]:
print("Invalid format for include directive: {}".format(line))
leave()
sys.exit(1)
elif tok[2][0] in "'\"":
s = tok[2].strip()
assert(s[-1] == tok[2][0])
s = s[1:-1]
inc = tok[1][1:-1]
plabels_data[tok[0]] = pdata
try:
new_fi = open(inc, "r")
real_len = 0
escaping = False
except:
print("Couldn't open file: {}".format(line))
leave()
sys.exit(1)
for c in s:
# escape sequences
if c == '\\':
escaping = True
continue
inc_depth += 1
if inc_depth >= inc_depth_max:
print("Maximal include depth reached: {}".format(line))
leave()
sys.exit(1)
if escaping:
escaping = False
if c == 'n':
c = '\n'
elif c == 't':
c = '\t'
else:
print("Unrecognized escape sequence: {}".format(line))
leave()
sys.exit(1)
written = b_data.write(ord(c).to_bytes(1, byteorder='little', signed=False))
assert(written == 1)
real_len += 1
pdata += 1
# align
for i in range(8 - len(s) % 8):
written = b_data.write(int(0).to_bytes(1, byteorder='little', signed=False))
assert(written == 1)
pdata += 1
pdefs[tok[0] + "_len"] = str(real_len)
do_includes(new_fi)
else:
print("Invalid format: {}".format(line))
leave()
sys.exit(1)
source.write("{}\n".format(line))
return
print("Unrecognized directive: {}".format(line))
#-------------------------------------------------------------------------------
@ -184,7 +149,10 @@ def parse():
global ptext
global plastlabel
for count, line in enumerate(fi):
source.seek(0)
for count, line in enumerate(source):
print(line)
line = line.rstrip()
if len(line) == 0:
@ -204,7 +172,7 @@ def parse():
instrs.write("\n")
continue
# Preprocessor or label?
if line[-1] == ':':
if name_valid(line[:-1]):
@ -219,18 +187,103 @@ def parse():
leave()
sys.exit(1)
continue
# Preprocessor, .data, or invalid
parse_preproc(line)
#-------------------------------------------------------------------------------
def parse_preproc(line):
global pdata
tok = line.split(' ', 2)
#for word in tok:
# if not name_valid(word):
# print("Invalid token in line: {}".format(line))
# return
# preprocessor
if len(tok) > 1 and tok[1] == ':=':
if len(tok) < 3:
print("Invalid format: {}".format(line))
leave()
sys.exit(1)
pdefs[tok[0]] = tok[2]
return
# .data
if len(tok) > 1 and tok[1] == '=':
if len(tok) < 3:
print("Invalid format: {}".format(line))
leave()
sys.exit(1)
if is_number(tok[2]):
plabels_data[tok[0]] = pdata
written = b_data.write(int(tok[2], base=0).to_bytes(8, byteorder='little', signed=False))
assert(written == 8)
pdata += written
elif tok[2][0] in "'\"":
s = tok[2].strip()
assert(s[-1] == tok[2][0])
s = s[1:-1]
plabels_data[tok[0]] = pdata
real_len = 0
escaping = False
for c in s:
# escape sequences
if c == '\\':
escaping = True
continue
if escaping:
escaping = False
if c == 'n':
c = '\n'
elif c == 't':
c = '\t'
else:
print("Unrecognized escape sequence: {}".format(line))
leave()
sys.exit(1)
written = b_data.write(ord(c).to_bytes(1, byteorder='little', signed=False))
assert(written == 1)
real_len += 1
pdata += 1
# align
for i in range(8 - len(s) % 8):
written = b_data.write(int(0).to_bytes(1, byteorder='little', signed=False))
assert(written == 1)
pdata += 1
pdefs[tok[0] + "_len"] = str(real_len)
else:
print("Invalid format: {}".format(line))
leave()
sys.exit(1)
return
print("Unrecognized directive: {}".format(line))
#-------------------------------------------------------------------------------
def parse_instr(line):
if line == None or len(line) == 0:
return 0
tok = line.split(' ', 1)
instr = tok[0].strip()
if len(tok) > 1:
@ -251,7 +304,7 @@ def parse_instr(line):
instrs.write("%rep ")
instr, params = params.split(' ', 1)
size += 2
instr_name = instr
instr_args = ''
@ -304,17 +357,17 @@ def parse_instr(line):
# +2 for A_OFF, +2 for offset, +2 for register
size += 2 + 2 + 2
instr_args += "off "
assert(len(word) > 3)
reg, off = word.split('+', 1)
reg = reg.strip()
off = off.strip()
instr_args += "{} {}".format(off, reg)
continue
else:
# +2 for A_MEM
size += 2
@ -347,17 +400,17 @@ def parse_instr(line):
instr_args += word
fellthrough = False
continue
# it's a label (a 64-bit immediate)
# +2 for A_IMM64, +8 for immediate
size += 2 + 8
if not fellthrough:
instr_name += "_i"
instr_args += "%imm64 "
if word[0] == '.':
instr_args += plastlabel
instr_args += word
fellthrough = False
@ -371,16 +424,16 @@ special_syms = {
"%wmem": 0x7002,
"%lmem": 0x7004,
"%qmem": 0x7008,
"%boff": 0x7701,
"%woff": 0x7702,
"%loff": 0x7704,
"%qoff": 0x7708,
"%imm16": 0x7772,
"%imm32": 0x7774,
"%imm64": 0x7778,
"%rep": 0x8000
}
@ -392,7 +445,7 @@ def gentext():
for _, line in enumerate(instrs):
tok = line.strip().split(' ')
for word in tok:
if word in pregs:
idx = pregs.index(word)
@ -421,7 +474,7 @@ def gentext():
lastimm = 4
elif word == "%imm64":
lastimm = 8
if word[2:] == "off" and word[0] == '%':
lastimm = 2
isSigned = True
@ -430,7 +483,7 @@ def gentext():
b_text.write(special_syms[word].to_bytes(2, byteorder='little', signed=isSigned))
continue
if is_number(word):
if word[0] == '-':
isSigned = True
@ -438,7 +491,7 @@ def gentext():
isSigned = False
b_text.write(int(word, base=0).to_bytes(lastimm, byteorder='little', signed=isSigned))
continue
print("Assembly error, unknown token '{}' in line: {}".format(word, line))
leave()
sys.exit(1)
@ -451,7 +504,7 @@ def genout():
b_out.write(b_text.read())
data_align = (8 - ptext % 8)
for i in range(data_align):
b_out.write(int(0).to_bytes(1, byteorder='little', signed=False))
@ -461,6 +514,7 @@ def genout():
parse_lst_instrs()
parse_lst_regs()
do_includes(main_src)
parse()
gentext()
genout()

20
dos/dos.k Normal file
View File

@ -0,0 +1,20 @@
; The OS/K Team licences this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
hw = "Hello World\n:)"
;
; Entry point
;
main:
; Initializes the stack
mov rbp, 0x200000
mov rsp, rbp
mov ax0, hw
call print
stop
include "dos/print.k"

View File

@ -1,21 +1,6 @@
; The OS/K Team licences this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
hw = "Hello World\n:)"
;
; Entry point
;
main:
; Initializes the stack
mov rbp, 0x200000
mov rsp, rbp
mov ax0, hw
call print
stop
;
; Max amount of characters that print() will print
;
@ -44,7 +29,7 @@ print:
;
print_n:
enter
mov rcx, ax1 ; text
mov rcx, ax1
.1:
prn b[ax0]

0
out/.placeholder Normal file
View File

View File

@ -98,7 +98,7 @@ struct ctx_t
// Read next instruction
ushort (*get)(ctx_t *ctx);
// For disassembly
FILE *disf;
};