mirror of
https://gitlab.os-k.eu/os-k-team/kvisc.git
synced 2023-08-25 14:05:46 +02:00
include
This commit is contained in:
parent
b21b289c6d
commit
2ca9869233
10
Makefile
10
Makefile
@ -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
|
||||
|
246
as/k-as.py
246
as/k-as.py
@ -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
20
dos/dos.k
Normal 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"
|
||||
|
@ -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
0
out/.placeholder
Normal file
Loading…
Reference in New Issue
Block a user