mirror of
https://gitlab.os-k.eu/os-k-team/kvisc.git
synced 2023-08-25 14:05:46 +02:00
ppc
This commit is contained in:
parent
8ec0bffa53
commit
aa192abe6d
100
as/k-as.py
100
as/k-as.py
@ -27,7 +27,7 @@ b_text = TemporaryFile(mode="w+b")
|
|||||||
|
|
||||||
lst_instrs = open(os.path.join(sys.path[0], "instrs.lst"))
|
lst_instrs = open(os.path.join(sys.path[0], "instrs.lst"))
|
||||||
|
|
||||||
main_src = open(sys.argv[1])
|
source = open(sys.argv[1])
|
||||||
b_out = open(sys.argv[3], "wb")
|
b_out = open(sys.argv[3], "wb")
|
||||||
b_sym = open(sys.argv[4], "w")
|
b_sym = open(sys.argv[4], "w")
|
||||||
|
|
||||||
@ -42,7 +42,6 @@ def leave(i):
|
|||||||
b_sym.close()
|
b_sym.close()
|
||||||
b_data.close()
|
b_data.close()
|
||||||
b_text.close()
|
b_text.close()
|
||||||
main_src.close()
|
|
||||||
lst_instrs.close()
|
lst_instrs.close()
|
||||||
sys.exit(i)
|
sys.exit(i)
|
||||||
|
|
||||||
@ -124,59 +123,6 @@ def arith_eval(s):
|
|||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
inc_depth = 0
|
|
||||||
inc_depth_max = 16
|
|
||||||
|
|
||||||
# Quickly goes through source file and resolves "include" directives ONLY
|
|
||||||
def do_includes(fi):
|
|
||||||
global inc_depth
|
|
||||||
global pcurfile
|
|
||||||
|
|
||||||
for _, line in enumerate(fi):
|
|
||||||
line = line.rstrip()
|
|
||||||
tok = line.split(None, 1)
|
|
||||||
|
|
||||||
if len(tok) == 0:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if tok[0] == "include":
|
|
||||||
if len(tok) == 1:
|
|
||||||
print("Missing parameter for include directive")
|
|
||||||
leave(1)
|
|
||||||
|
|
||||||
if tok[1][0] not in "'\"" or tok[1][-1] != tok[1][0]:
|
|
||||||
print("Invalid format for include directive: {}".format(line))
|
|
||||||
leave(1)
|
|
||||||
|
|
||||||
old_curf = pcurfile
|
|
||||||
pcurfile = tok[1][1:-1]
|
|
||||||
|
|
||||||
try:
|
|
||||||
new_fi = open(pcurfile, "r")
|
|
||||||
|
|
||||||
except:
|
|
||||||
print("Couldn't open file: {}".format(line))
|
|
||||||
leave(1)
|
|
||||||
|
|
||||||
inc_depth += 1
|
|
||||||
if inc_depth >= inc_depth_max:
|
|
||||||
print("Maximal include depth reached: {}".format(line))
|
|
||||||
leave(1)
|
|
||||||
|
|
||||||
source.write("$file: {}:\n".format(pcurfile.replace(' ', '')))
|
|
||||||
do_includes(new_fi)
|
|
||||||
pcurfile = old_curf
|
|
||||||
source.write("$file: {}:\n".format(pcurfile.replace(' ', '')))
|
|
||||||
|
|
||||||
|
|
||||||
else:
|
|
||||||
source.write("{}\n".format(line))
|
|
||||||
|
|
||||||
inc_depth -= 1
|
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
def parse():
|
def parse():
|
||||||
global ptext
|
global ptext
|
||||||
global pcurfile
|
global pcurfile
|
||||||
@ -191,10 +137,14 @@ def parse():
|
|||||||
if len(line) == 0:
|
if len(line) == 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# len("$file: ") == 7
|
if line[0] == '#':
|
||||||
if len(line) > 7 and line[:7] == "$file: ":
|
tok = line.split()
|
||||||
pcurfile = line[7:]
|
|
||||||
continue
|
if len(tok) < 3:
|
||||||
|
print("Invalid # directive: {}".format(line))
|
||||||
|
leave(-1)
|
||||||
|
|
||||||
|
pcurfile = tok[2][1:-1]
|
||||||
|
|
||||||
quote = False
|
quote = False
|
||||||
for i in range(len(line)):
|
for i in range(len(line)):
|
||||||
@ -371,31 +321,13 @@ def parse_preproc(line):
|
|||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
fmts = {
|
fmts = {
|
||||||
"r": 0b00000000,
|
"r": 0b00000000, "m_r": 0b00100000, "m_rr": 0b01000000,
|
||||||
"m_r": 0b00100000,
|
"m_rriw": 0b01100000, "m_rrid": 0b10000000, "m_rrii": 0b10100000,
|
||||||
"m_rr": 0b01000000,
|
"m_riq": 0b11000000, "imm8": 0b11100001, "imm16": 0b11100010,
|
||||||
"m_rriw": 0b01100000,
|
"imm32": 0b11100100, "imm64": 0b11101000,
|
||||||
"m_rrid": 0b10000000,
|
|
||||||
"m_rrii": 0b10100000,
|
|
||||||
"m_riq": 0b11000000,
|
|
||||||
"imm8": 0b11100001,
|
|
||||||
"imm16": 0b11100010,
|
|
||||||
"imm32": 0b11100100,
|
|
||||||
"imm64": 0b11101000,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pref2len = {
|
pref2len = { "b" : 1, "w" : 2, "d" : 4, "l" : 4, "q" : 8 }
|
||||||
"b" : 1,
|
|
||||||
"w" : 2,
|
|
||||||
"d" : 4,
|
|
||||||
"l" : 4,
|
|
||||||
"q" : 8,
|
|
||||||
}
|
|
||||||
|
|
||||||
i_aliases = {
|
|
||||||
"inc_2" : "add_2",
|
|
||||||
#"dec_2" : "sub_2",
|
|
||||||
}
|
|
||||||
|
|
||||||
def parse_instr(line):
|
def parse_instr(line):
|
||||||
if line == None or len(line) == 0:
|
if line == None or len(line) == 0:
|
||||||
@ -423,9 +355,6 @@ def parse_instr(line):
|
|||||||
|
|
||||||
instr_name += "_{}".format(len(tok))
|
instr_name += "_{}".format(len(tok))
|
||||||
|
|
||||||
if instr_name in i_aliases:
|
|
||||||
instr_name = i_aliases[instr_name]
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Parse operands
|
# Parse operands
|
||||||
#
|
#
|
||||||
@ -778,7 +707,6 @@ def genout():
|
|||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
parse_lst_instrs()
|
parse_lst_instrs()
|
||||||
do_includes(main_src)
|
|
||||||
parse()
|
parse()
|
||||||
gentext()
|
gentext()
|
||||||
genout()
|
genout()
|
||||||
|
@ -8,12 +8,11 @@ KSDIR=../vm/ob
|
|||||||
KPDIR=../vm/ob
|
KPDIR=../vm/ob
|
||||||
|
|
||||||
KSRC = $(shell ls *.k)
|
KSRC = $(shell ls *.k)
|
||||||
KPPC = $(patsubst %.k,$(KODIR)/%.ppc,$(KSRC))
|
|
||||||
KCOM = $(patsubst %.k,$(KODIR)/%.com,$(KSRC))
|
KCOM = $(patsubst %.k,$(KODIR)/%.com,$(KSRC))
|
||||||
|
|
||||||
$(KODIR)/%.com: %.k
|
$(KODIR)/%.com: %.k
|
||||||
@cpp -I. -x assembler-with-cpp $< > $(patsubst %.k,$(KODIR)/%.ppc,$<)
|
@cpp -I. -x assembler-with-cpp $< > $(KSDIR)/$<
|
||||||
@../as/k-as.py $(patsubst %.k,$(KODIR)/%.ppc,$<) 0x100000 $@ $(patsubst %.k,$(KSDIR)/%.sym,$<)
|
@../as/k-as.py $(KSDIR)/$< 0x100000 $@ $(patsubst %.k,$(KSDIR)/%.sym,$<)
|
||||||
|
|
||||||
dos: $(KCOM)
|
dos: $(KCOM)
|
||||||
|
|
||||||
|
16
ka/command.k
16
ka/command.k
@ -243,7 +243,7 @@ main:
|
|||||||
|
|
||||||
push b[rax+3], rcx, w[rax+6]
|
push b[rax+3], rcx, w[rax+6]
|
||||||
call printf, .datefmt
|
call printf, .datefmt
|
||||||
inc rsp, 40
|
add rsp, 40
|
||||||
|
|
||||||
jmp .print_prompt
|
jmp .print_prompt
|
||||||
|
|
||||||
@ -286,7 +286,7 @@ main:
|
|||||||
|
|
||||||
push b[rax], b[rax+1], b[rax+2]
|
push b[rax], b[rax+1], b[rax+2]
|
||||||
call printf, .timefmt
|
call printf, .timefmt
|
||||||
inc rsp, 24
|
add rsp, 24
|
||||||
|
|
||||||
jmp .print_prompt
|
jmp .print_prompt
|
||||||
|
|
||||||
@ -338,7 +338,7 @@ main:
|
|||||||
.exec_not_found:
|
.exec_not_found:
|
||||||
push argv0
|
push argv0
|
||||||
call printf, .enf_errmsg
|
call printf, .enf_errmsg
|
||||||
inc rsp, 8
|
add rsp, 8
|
||||||
|
|
||||||
jmp .print_prompt
|
jmp .print_prompt
|
||||||
|
|
||||||
@ -347,7 +347,7 @@ main:
|
|||||||
.file_not_found:
|
.file_not_found:
|
||||||
push q[argv1pos], argv0
|
push q[argv1pos], argv0
|
||||||
call printf, .fnf_errmsg
|
call printf, .fnf_errmsg
|
||||||
inc rsp, 16
|
add rsp, 16
|
||||||
|
|
||||||
jmp .print_prompt
|
jmp .print_prompt
|
||||||
|
|
||||||
@ -356,7 +356,7 @@ main:
|
|||||||
.empty_file:
|
.empty_file:
|
||||||
push q[argv1pos], argv0
|
push q[argv1pos], argv0
|
||||||
call printf, .ef_errmsg
|
call printf, .ef_errmsg
|
||||||
inc rsp, 16
|
add rsp, 16
|
||||||
|
|
||||||
jmp .print_prompt
|
jmp .print_prompt
|
||||||
|
|
||||||
@ -365,7 +365,7 @@ main:
|
|||||||
.couldnt_open:
|
.couldnt_open:
|
||||||
push q[argv1pos], argv0
|
push q[argv1pos], argv0
|
||||||
call printf, .cno_errmsg
|
call printf, .cno_errmsg
|
||||||
inc rsp, 16
|
add rsp, 16
|
||||||
|
|
||||||
jmp .print_prompt
|
jmp .print_prompt
|
||||||
|
|
||||||
@ -374,7 +374,7 @@ main:
|
|||||||
.couldnt_remove:
|
.couldnt_remove:
|
||||||
push q[argv1pos], argv0
|
push q[argv1pos], argv0
|
||||||
call printf, .cne_errmsg
|
call printf, .cne_errmsg
|
||||||
inc rsp, 16
|
add rsp, 16
|
||||||
|
|
||||||
jmp .print_prompt
|
jmp .print_prompt
|
||||||
|
|
||||||
@ -383,7 +383,7 @@ main:
|
|||||||
.couldnt_read:
|
.couldnt_read:
|
||||||
push q[argv1pos], argv0
|
push q[argv1pos], argv0
|
||||||
call printf, .cnr_errmsg
|
call printf, .cnr_errmsg
|
||||||
inc rsp, 16
|
add rsp, 16
|
||||||
|
|
||||||
jmp .print_prompt
|
jmp .print_prompt
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ doprnt:
|
|||||||
|
|
||||||
call .doput, b[r12]
|
call .doput, b[r12]
|
||||||
|
|
||||||
inc r12, 1
|
inc r12
|
||||||
jmp .print_regular
|
jmp .print_regular
|
||||||
|
|
||||||
.check_modf:
|
.check_modf:
|
||||||
@ -40,7 +40,7 @@ doprnt:
|
|||||||
|
|
||||||
; we did find a modifier / '%'
|
; we did find a modifier / '%'
|
||||||
mov rax, b[r12+1]
|
mov rax, b[r12+1]
|
||||||
inc r12, 2
|
add r12, 2
|
||||||
|
|
||||||
beq rax, 's', .modf_s
|
beq rax, 's', .modf_s
|
||||||
beq rax, 'c', .modf_c
|
beq rax, 'c', .modf_c
|
||||||
@ -57,7 +57,7 @@ doprnt:
|
|||||||
.modf_s:
|
.modf_s:
|
||||||
; get string address
|
; get string address
|
||||||
mov r13, q[r14]
|
mov r13, q[r14]
|
||||||
inc r14, 8
|
add r14, 8
|
||||||
|
|
||||||
bzr r13, .nullstring
|
bzr r13, .nullstring
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ doprnt:
|
|||||||
|
|
||||||
.modf_c:
|
.modf_c:
|
||||||
call .doput, q[r14]
|
call .doput, q[r14]
|
||||||
inc r14, 8
|
add r14, 8
|
||||||
|
|
||||||
jmp .main_loop
|
jmp .main_loop
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ doprnt:
|
|||||||
|
|
||||||
; assume modifier already set up ax2
|
; assume modifier already set up ax2
|
||||||
call itoa, rsp, q[r14]
|
call itoa, rsp, q[r14]
|
||||||
inc r14, 8
|
add r14, 8
|
||||||
|
|
||||||
.print_itoa_buf:
|
.print_itoa_buf:
|
||||||
movzx ax0, b[r13]
|
movzx ax0, b[r13]
|
||||||
@ -116,7 +116,7 @@ doprnt:
|
|||||||
jmp .print_itoa_buf
|
jmp .print_itoa_buf
|
||||||
|
|
||||||
.pib_end_loop:
|
.pib_end_loop:
|
||||||
inc rsp, 80
|
add rsp, 80
|
||||||
jmp .main_loop
|
jmp .main_loop
|
||||||
|
|
||||||
.modf_percent:
|
.modf_percent:
|
||||||
|
@ -47,11 +47,11 @@ ltostr:
|
|||||||
|
|
||||||
blt 9, rdx, .nondec ; rdx > 9 ?
|
blt 9, rdx, .nondec ; rdx > 9 ?
|
||||||
|
|
||||||
inc rdx, '0'
|
add rdx, '0'
|
||||||
jmp .next
|
jmp .next
|
||||||
|
|
||||||
.nondec:
|
.nondec:
|
||||||
inc rdx, 55 ; 'A' - 10
|
add rdx, 55 ; 'A' - 10
|
||||||
|
|
||||||
.next:
|
.next:
|
||||||
mov b[ax0], rdx
|
mov b[ax0], rdx
|
||||||
|
@ -80,7 +80,7 @@ strtoq:
|
|||||||
; if not, leave rax = 0 and *rdx = 'x'
|
; if not, leave rax = 0 and *rdx = 'x'
|
||||||
bne ax1, 16, .done
|
bne ax1, 16, .done
|
||||||
; else
|
; else
|
||||||
inc rdx, 1
|
inc rdx
|
||||||
jmp .main_loop
|
jmp .main_loop
|
||||||
|
|
||||||
.parsed_0b:
|
.parsed_0b:
|
||||||
@ -149,7 +149,7 @@ strtoq:
|
|||||||
blteu ax1, rcx, .done
|
blteu ax1, rcx, .done
|
||||||
|
|
||||||
mul rax, ax1
|
mul rax, ax1
|
||||||
inc rax, rcx
|
add rax, rcx
|
||||||
jmp .main_loop
|
jmp .main_loop
|
||||||
|
|
||||||
.done:
|
.done:
|
||||||
|
@ -36,7 +36,7 @@ DaysInYear:
|
|||||||
jrcxnz .end
|
jrcxnz .end
|
||||||
|
|
||||||
.leap:
|
.leap:
|
||||||
inc rax, 1
|
inc rax
|
||||||
|
|
||||||
.end:
|
.end:
|
||||||
ret
|
ret
|
||||||
|
@ -29,7 +29,7 @@ ScreenOfDeath:
|
|||||||
.do_print:
|
.do_print:
|
||||||
push r14, r12
|
push r14, r12
|
||||||
call printf, .scr2
|
call printf, .scr2
|
||||||
inc rsp, 24
|
add rsp, 24
|
||||||
|
|
||||||
call dumprf, r14
|
call dumprf, r14
|
||||||
prn 10
|
prn 10
|
||||||
|
@ -167,27 +167,27 @@ DefaultTrapHandler:
|
|||||||
; Disk API
|
; Disk API
|
||||||
;
|
;
|
||||||
.handle_FindFirst:
|
.handle_FindFirst:
|
||||||
inc ax0, r12
|
add ax0, r12
|
||||||
call DISK.FindFirst
|
call DISK.FindFirst
|
||||||
jmp .fini.savecx
|
jmp .fini.savecx
|
||||||
|
|
||||||
.handle_FindNext:
|
.handle_FindNext:
|
||||||
inc ax0, r12
|
add ax0, r12
|
||||||
call DISK.FindNext
|
call DISK.FindNext
|
||||||
jmp .fini.savecx
|
jmp .fini.savecx
|
||||||
|
|
||||||
.handle_OpenFile:
|
.handle_OpenFile:
|
||||||
inc ax0, r12
|
add ax0, r12
|
||||||
call DISK.OpenFile
|
call DISK.OpenFile
|
||||||
jmp .fini
|
jmp .fini
|
||||||
|
|
||||||
.handle_CreateFile:
|
.handle_CreateFile:
|
||||||
inc ax0, r12
|
add ax0, r12
|
||||||
call DISK.CreateFile
|
call DISK.CreateFile
|
||||||
jmp .fini
|
jmp .fini
|
||||||
|
|
||||||
.handle_RemoveFile:
|
.handle_RemoveFile:
|
||||||
inc ax0, r12
|
add ax0, r12
|
||||||
call DISK.RemoveFile
|
call DISK.RemoveFile
|
||||||
jmp .fini
|
jmp .fini
|
||||||
|
|
||||||
@ -196,7 +196,7 @@ DefaultTrapHandler:
|
|||||||
jmp .fini
|
jmp .fini
|
||||||
|
|
||||||
.handle_ReadFile:
|
.handle_ReadFile:
|
||||||
inc ax1, r12
|
add ax1, r12
|
||||||
call DISK.ReadFile
|
call DISK.ReadFile
|
||||||
jmp .fini
|
jmp .fini
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
; The OS/K Team licenses this file to you under the MIT license.
|
; The OS/K Team licenses this file to you under the MIT license.
|
||||||
; See the LICENSE file in the project root for more information.
|
; See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
N := 11
|
#define N 11
|
||||||
|
|
||||||
.handle_DIR:
|
.handle_DIR:
|
||||||
push rbp
|
push rbp
|
||||||
@ -34,7 +34,7 @@ N := 11
|
|||||||
jraxz .end
|
jraxz .end
|
||||||
|
|
||||||
mov r15, rcx ; file size
|
mov r15, rcx ; file size
|
||||||
inc r14, rcx
|
add r14, rcx
|
||||||
|
|
||||||
; directory?
|
; directory?
|
||||||
bnz rdx, .is_dir
|
bnz rdx, .is_dir
|
||||||
@ -102,7 +102,7 @@ N := 11
|
|||||||
|
|
||||||
push r15, rax
|
push r15, rax
|
||||||
call printf, .bytesstr
|
call printf, .bytesstr
|
||||||
inc rsp, 16
|
add rsp, 16
|
||||||
|
|
||||||
.prepare_next:
|
.prepare_next:
|
||||||
; go find next entry
|
; go find next entry
|
||||||
@ -117,11 +117,11 @@ N := 11
|
|||||||
|
|
||||||
push r14, rax, rdx
|
push r14, rax, rdx
|
||||||
call printf, .endstr0
|
call printf, .endstr0
|
||||||
inc rsp, 24
|
add rsp, 24
|
||||||
|
|
||||||
push r13, r12
|
push r13, r12
|
||||||
call printf, .endstr1
|
call printf, .endstr1
|
||||||
inc rsp, 16
|
add rsp, 16
|
||||||
|
|
||||||
pop r15, r14
|
pop r15, r14
|
||||||
pop r13, r12
|
pop r13, r12
|
||||||
@ -134,8 +134,8 @@ N := 11
|
|||||||
inc r13
|
inc r13
|
||||||
|
|
||||||
; use printf instead of print
|
; use printf instead of print
|
||||||
; because it returns # of printed
|
; because it returns the # of
|
||||||
; characters
|
; printed characters
|
||||||
call printf, .buf
|
call printf, .buf
|
||||||
|
|
||||||
blte N, rax, .dir_no_pad
|
blte N, rax, .dir_no_pad
|
||||||
@ -160,3 +160,5 @@ N := 11
|
|||||||
.bytesstr = "%d kilobytes + %d bytes"
|
.bytesstr = "%d kilobytes + %d bytes"
|
||||||
; .bytesstr = "%dMB + %dKB + %dB" # too soon
|
; .bytesstr = "%dMB + %dKB + %dB" # too soon
|
||||||
|
|
||||||
|
#undef N
|
||||||
|
|
||||||
|
1655
vm/ob/command.k
Normal file
1655
vm/ob/command.k
Normal file
File diff suppressed because it is too large
Load Diff
@ -1206,7 +1206,7 @@ main:
|
|||||||
; The OS/K Team licenses this file to you under the MIT license.
|
; The OS/K Team licenses this file to you under the MIT license.
|
||||||
; See the LICENSE file in the project root for more information.
|
; See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
N := 11
|
|
||||||
|
|
||||||
.handle_DIR:
|
.handle_DIR:
|
||||||
push rbp
|
push rbp
|
||||||
@ -1263,8 +1263,8 @@ N := 11
|
|||||||
dec rdi
|
dec rdi
|
||||||
|
|
||||||
.ext_pad:
|
.ext_pad:
|
||||||
; print at least N non-space characters before extension
|
; print at least 11 non-space characters before extension
|
||||||
blte N, rdi, .print_ext
|
blte 11, rdi, .print_ext
|
||||||
prn ' '
|
prn ' '
|
||||||
inc rdi
|
inc rdi
|
||||||
jmp .ext_pad
|
jmp .ext_pad
|
||||||
@ -1339,12 +1339,12 @@ N := 11
|
|||||||
inc r13
|
inc r13
|
||||||
|
|
||||||
; use printf instead of print
|
; use printf instead of print
|
||||||
; because it returns # of printed
|
; because it returns the # of
|
||||||
; characters
|
; printed characters
|
||||||
call printf, .buf
|
call printf, .buf
|
||||||
|
|
||||||
blte N, rax, .dir_no_pad
|
blte 11, rax, .dir_no_pad
|
||||||
sub rcx, N, rax
|
sub rcx, 11, rax
|
||||||
dec rcx
|
dec rcx
|
||||||
|
|
||||||
.dir.l:
|
.dir.l:
|
1629
vm/ob/doskrnl.k
Normal file
1629
vm/ob/doskrnl.k
Normal file
File diff suppressed because it is too large
Load Diff
995
vm/ob/hello.k
Normal file
995
vm/ob/hello.k
Normal file
@ -0,0 +1,995 @@
|
|||||||
|
# 1 "hello.k"
|
||||||
|
# 1 "<built-in>"
|
||||||
|
# 1 "<command-line>"
|
||||||
|
# 31 "<command-line>"
|
||||||
|
# 1 "/usr/include/stdc-predef.h" 1 3 4
|
||||||
|
# 32 "<command-line>" 2
|
||||||
|
# 1 "hello.k"
|
||||||
|
; The OS/K Team licenses this file to you under the MIT license.
|
||||||
|
; See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
start:
|
||||||
|
jmp main
|
||||||
|
|
||||||
|
# 1 "crt/crt.k" 1
|
||||||
|
; The OS/K Team licenses this file to you under the MIT license.
|
||||||
|
; See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
;
|
||||||
|
; Limits
|
||||||
|
;
|
||||||
|
# 31 "crt/crt.k"
|
||||||
|
;
|
||||||
|
; Magic numbers
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
; CRT librairies
|
||||||
|
;
|
||||||
|
|
||||||
|
# 1 "./crt/sys.k" 1
|
||||||
|
; The OS/K Team licenses this file to you under the MIT license.
|
||||||
|
; See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
;
|
||||||
|
; SHUTDOWN syscall
|
||||||
|
;
|
||||||
|
; End virtual machine
|
||||||
|
;
|
||||||
|
Sys.Shutdown := 0x00
|
||||||
|
|
||||||
|
;
|
||||||
|
; EXIT syscall
|
||||||
|
;
|
||||||
|
; Return to COMMAND.COM
|
||||||
|
;
|
||||||
|
Sys.Exit := 0x01
|
||||||
|
|
||||||
|
;
|
||||||
|
; EXEC syscall
|
||||||
|
;
|
||||||
|
; IN
|
||||||
|
; ax0 = new RIP to load
|
||||||
|
; ax1 = frame ID to switch to
|
||||||
|
;
|
||||||
|
; New frame ID must be higher than current
|
||||||
|
; frame ID, and cannot be below 5
|
||||||
|
;
|
||||||
|
; New CR1 is set so that new RIP corresponds to 1MB
|
||||||
|
;
|
||||||
|
Sys.ExecuteInFrame := 0x02
|
||||||
|
|
||||||
|
; FIND syscalls
|
||||||
|
;
|
||||||
|
; Find file on disk
|
||||||
|
;
|
||||||
|
; IN
|
||||||
|
; ax0 = address of name buffer
|
||||||
|
; ax1 = size of name buffer
|
||||||
|
;
|
||||||
|
; OUT
|
||||||
|
; rax = # of bytes written in name buffer
|
||||||
|
; rdx = size of file
|
||||||
|
;
|
||||||
|
;
|
||||||
|
Sys.FindFirst := 0x20
|
||||||
|
Sys.FindNext := 0x21
|
||||||
|
|
||||||
|
;
|
||||||
|
; OPEN syscall
|
||||||
|
;
|
||||||
|
; IN
|
||||||
|
; ax0 = name string
|
||||||
|
;
|
||||||
|
; OUT
|
||||||
|
; rax = handle of file, or <0 if couldn't open
|
||||||
|
;
|
||||||
|
Sys.OpenFile := 0x30
|
||||||
|
|
||||||
|
;
|
||||||
|
; CREATE syscall
|
||||||
|
;
|
||||||
|
; IN
|
||||||
|
; ax0 = name string
|
||||||
|
;
|
||||||
|
; OUT
|
||||||
|
; rax = 0 on success, or <0 if couldn't open
|
||||||
|
;
|
||||||
|
Sys.CreateFile := 0x31
|
||||||
|
|
||||||
|
;
|
||||||
|
; REMOVE syscall
|
||||||
|
;
|
||||||
|
; IN
|
||||||
|
; ax0 = name string
|
||||||
|
;
|
||||||
|
; OUT
|
||||||
|
; rax = 0 on success, or <0 if couldn't open
|
||||||
|
;
|
||||||
|
Sys.RemoveFile := 0x32
|
||||||
|
|
||||||
|
;
|
||||||
|
; CLOSE syscall
|
||||||
|
;
|
||||||
|
; IN
|
||||||
|
; ax0 = file handle
|
||||||
|
;
|
||||||
|
Sys.CloseFile := 0x35
|
||||||
|
|
||||||
|
;
|
||||||
|
; READ syscall
|
||||||
|
;
|
||||||
|
; IN
|
||||||
|
; ax0 = file handle
|
||||||
|
; ax1 = buffer address
|
||||||
|
; ax2 = buffer size
|
||||||
|
;
|
||||||
|
; OUT
|
||||||
|
; rax = number of bytes read, <0 on error
|
||||||
|
;
|
||||||
|
Sys.ReadFile := 0x38
|
||||||
|
|
||||||
|
; Halt mode
|
||||||
|
Sys.EnterHaltMode := 0x999
|
||||||
|
# 43 "crt/crt.k" 2
|
||||||
|
# 1 "./crt/str.k" 1
|
||||||
|
; The OS/K Team licenses this file to you under the MIT license.
|
||||||
|
; See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
;
|
||||||
|
; int strnlen(char *, int)
|
||||||
|
;
|
||||||
|
strnlen:
|
||||||
|
mov rcx, ax1
|
||||||
|
scasb ax0, zero
|
||||||
|
|
||||||
|
sub rax, ax1, rcx
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; int strlen(char *)
|
||||||
|
;
|
||||||
|
strlen:
|
||||||
|
mov rcx, 0x7AFFFFFF
|
||||||
|
mov rdx, rcx
|
||||||
|
scasb ax0, zero
|
||||||
|
|
||||||
|
sub rax, rdx, rcx
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; void strcpy(char *, const char *)
|
||||||
|
;
|
||||||
|
strcpy:
|
||||||
|
.l:
|
||||||
|
mov rcx, b[ax1]
|
||||||
|
mov b[ax0], rcx
|
||||||
|
|
||||||
|
jrcxz .r
|
||||||
|
|
||||||
|
inc ax0
|
||||||
|
inc ax1
|
||||||
|
|
||||||
|
jmp .l
|
||||||
|
|
||||||
|
.r:
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; void strncpy(char *, const char *, int)
|
||||||
|
;
|
||||||
|
strncpy:
|
||||||
|
mov rcx, ax2
|
||||||
|
jrcxz .r
|
||||||
|
|
||||||
|
.l:
|
||||||
|
mov b[ax0], b[ax1]
|
||||||
|
|
||||||
|
inc ax0
|
||||||
|
inc ax1
|
||||||
|
|
||||||
|
loop .l
|
||||||
|
|
||||||
|
.r:
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; void strnzcpy(char *, const char *, int)
|
||||||
|
;
|
||||||
|
strnzcpy:
|
||||||
|
mov rcx, ax2
|
||||||
|
jrcxz .r
|
||||||
|
|
||||||
|
.l:
|
||||||
|
mov rax, b[ax1]
|
||||||
|
mov b[ax0], rax
|
||||||
|
|
||||||
|
jraxz .r
|
||||||
|
|
||||||
|
inc ax0
|
||||||
|
inc ax1
|
||||||
|
|
||||||
|
loop .l
|
||||||
|
|
||||||
|
.z:
|
||||||
|
nul b[ax0]
|
||||||
|
|
||||||
|
.r:
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; int strcmp(const char *str1, const char *str2)
|
||||||
|
;
|
||||||
|
; Returns:
|
||||||
|
; 0 if the contents of both strings are equal
|
||||||
|
; >0 if the first character that does not match has a greater value in str1 than in str2
|
||||||
|
; <0 if the first character that does not match has a lower value in str1 than in str2
|
||||||
|
;
|
||||||
|
strcmp:
|
||||||
|
nul rsi
|
||||||
|
.l:
|
||||||
|
movzx rax, b[ax0+rsi]
|
||||||
|
movzx rdx, b[ax1+rsi]
|
||||||
|
|
||||||
|
bne rax, rdx, .r
|
||||||
|
|
||||||
|
; both zero?
|
||||||
|
add rcx, rax, rdx
|
||||||
|
jrcxz .r
|
||||||
|
|
||||||
|
inc rsi
|
||||||
|
jmp .l
|
||||||
|
|
||||||
|
.r:
|
||||||
|
sub rax, rdx
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; int strncmp(const char *str1, const char *str2, int maxn)
|
||||||
|
;
|
||||||
|
strncmp:
|
||||||
|
mov rcx, ax2
|
||||||
|
jrcxz .r
|
||||||
|
|
||||||
|
.l:
|
||||||
|
movzx rax, b[ax0]
|
||||||
|
movzx rdx, b[ax1]
|
||||||
|
|
||||||
|
bne rax, rdx, .r
|
||||||
|
|
||||||
|
inc ax0
|
||||||
|
inc ax1
|
||||||
|
loop .l
|
||||||
|
|
||||||
|
.r:
|
||||||
|
sub rax, rdx
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; char *strchrnul(const char *str, int ch)
|
||||||
|
;
|
||||||
|
strchrnul:
|
||||||
|
mov rcx, 0x7AFFFFFF
|
||||||
|
scasb ax0, ax1
|
||||||
|
|
||||||
|
mov rax, ax0
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; char *strchr(const char *str, int ch)
|
||||||
|
;
|
||||||
|
strchr:
|
||||||
|
mov rcx, 0x7AFFFFFF
|
||||||
|
scasb ax0, ax1
|
||||||
|
|
||||||
|
bnz b[ax0], .r
|
||||||
|
nul rax
|
||||||
|
ret
|
||||||
|
|
||||||
|
.r:
|
||||||
|
mov rax, ax0
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; void strrev(char *buf, const char *str)
|
||||||
|
;
|
||||||
|
; buf and src must NOT overlap
|
||||||
|
;
|
||||||
|
strrev:
|
||||||
|
bzr b[ax1], .z
|
||||||
|
|
||||||
|
; save str's location
|
||||||
|
mov rsi, ax1
|
||||||
|
|
||||||
|
; go to str's end, just before
|
||||||
|
; the null terminator
|
||||||
|
mov rcx, 0x7AFFFFFF
|
||||||
|
scasb ax1, zero
|
||||||
|
dec ax1
|
||||||
|
|
||||||
|
.l:
|
||||||
|
; copy, going backward though str
|
||||||
|
; and forward through buf
|
||||||
|
mov b[ax0], b[ax1]
|
||||||
|
|
||||||
|
beq ax1, rsi, .r
|
||||||
|
|
||||||
|
inc ax0
|
||||||
|
dec ax1
|
||||||
|
jmp .l
|
||||||
|
|
||||||
|
.r:
|
||||||
|
nul b[ax0+1]
|
||||||
|
ret
|
||||||
|
|
||||||
|
.z:
|
||||||
|
nul b[ax0]
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; void strrev2(char *str)
|
||||||
|
;
|
||||||
|
; Inverses str
|
||||||
|
;
|
||||||
|
strrev2:
|
||||||
|
bzr b[ax0], .r
|
||||||
|
|
||||||
|
mov ax1, ax0
|
||||||
|
|
||||||
|
; go to str's end, just before
|
||||||
|
; the null terminator
|
||||||
|
mov rcx, 0x7AFFFFFF
|
||||||
|
scasb ax1, zero
|
||||||
|
dec ax1
|
||||||
|
|
||||||
|
; increase ax0 while decreasing ax1, performing exchanges
|
||||||
|
.l:
|
||||||
|
blteu ax1, ax0, .r
|
||||||
|
|
||||||
|
xchg b[ax0], b[ax1]
|
||||||
|
|
||||||
|
inc ax0
|
||||||
|
dec ax1
|
||||||
|
jmp .l
|
||||||
|
|
||||||
|
.r:
|
||||||
|
ret
|
||||||
|
# 44 "crt/crt.k" 2
|
||||||
|
# 1 "./crt/mem.k" 1
|
||||||
|
; The OS/K Team licenses this file to you under the MIT license.
|
||||||
|
; See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
;
|
||||||
|
; void memcpy(void *, const void *, int)
|
||||||
|
;
|
||||||
|
memcpy:
|
||||||
|
mov rcx, ax2
|
||||||
|
jrcxz .r
|
||||||
|
|
||||||
|
.l:
|
||||||
|
sub rdx, ax2, rcx
|
||||||
|
mov b[ax0+rdx], b[ax1+rdx]
|
||||||
|
loop .l
|
||||||
|
|
||||||
|
.r:
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; void memzero(void *, int)
|
||||||
|
;
|
||||||
|
memzero:
|
||||||
|
mov rcx, ax1
|
||||||
|
jrcxz .r
|
||||||
|
|
||||||
|
.l:
|
||||||
|
nul b[ax0]
|
||||||
|
inc ax0
|
||||||
|
loop .l
|
||||||
|
|
||||||
|
.r:
|
||||||
|
ret
|
||||||
|
# 45 "crt/crt.k" 2
|
||||||
|
# 1 "./crt/time.k" 1
|
||||||
|
; The OS/K Team licenses this file to you under the MIT license.
|
||||||
|
; See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
;
|
||||||
|
; struct TIME
|
||||||
|
; {
|
||||||
|
; byte sec; +0 (0-59)
|
||||||
|
; byte min; +1 (0-59)
|
||||||
|
; byte hour; +2 (0-23)
|
||||||
|
; byte mday; +3 (0-31)
|
||||||
|
; byte month; +4 (0-11)
|
||||||
|
; byte; +5 (pad)
|
||||||
|
; word year; +6 (0-65536)
|
||||||
|
; word yday; +8 (0-365)
|
||||||
|
; word; +10 (pad)
|
||||||
|
; dword; +12 (pad)
|
||||||
|
; } 16 bytes
|
||||||
|
;
|
||||||
|
|
||||||
|
;
|
||||||
|
; int DaysInYear(int year)
|
||||||
|
;
|
||||||
|
DaysInYear:
|
||||||
|
mov rax, 365
|
||||||
|
|
||||||
|
; divisible by 4?
|
||||||
|
rem rcx, ax0, 4
|
||||||
|
jrcxnz .end
|
||||||
|
|
||||||
|
; divisible by 100?
|
||||||
|
rem rcx, ax0, 100
|
||||||
|
jrcxnz .leap
|
||||||
|
|
||||||
|
; divisible by 400?
|
||||||
|
rem rcx, ax0, 400
|
||||||
|
jrcxnz .end
|
||||||
|
|
||||||
|
.leap:
|
||||||
|
inc rax
|
||||||
|
|
||||||
|
.end:
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; TIME *GetTimeUTC(void)
|
||||||
|
;
|
||||||
|
GetTimeUTC:
|
||||||
|
ytime
|
||||||
|
|
||||||
|
mov rdi, .buf
|
||||||
|
|
||||||
|
; seconds
|
||||||
|
rem rsi, rax, 60
|
||||||
|
mov b[rdi], rsi
|
||||||
|
|
||||||
|
; minutes
|
||||||
|
div rsi, rax, 60
|
||||||
|
rem rsi, 60
|
||||||
|
mov b[rdi+1], rsi
|
||||||
|
|
||||||
|
; hours
|
||||||
|
div rsi, rax, 3600
|
||||||
|
rem rsi, 24
|
||||||
|
mov b[rdi+2], rsi
|
||||||
|
|
||||||
|
; month days
|
||||||
|
div rsi, rax, 3600*24
|
||||||
|
mov b[rdi+3], rsi
|
||||||
|
|
||||||
|
; month
|
||||||
|
mov b[rdi+4], rbx
|
||||||
|
|
||||||
|
; years
|
||||||
|
mov w[rdi+6], rcx
|
||||||
|
|
||||||
|
;
|
||||||
|
; ydays (TODO)
|
||||||
|
;
|
||||||
|
|
||||||
|
mov rax, .buf
|
||||||
|
ret
|
||||||
|
|
||||||
|
.buf = [24]
|
||||||
|
# 46 "crt/crt.k" 2
|
||||||
|
|
||||||
|
# 1 "./crt/fmt/ltostr.k" 1
|
||||||
|
; The OS/K Team licenses this file to you under the MIT license.
|
||||||
|
; See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
;
|
||||||
|
; void itoa(char *buf, int num, int base)
|
||||||
|
;
|
||||||
|
itoa:
|
||||||
|
mov ax3, 1
|
||||||
|
jmp ltostr
|
||||||
|
|
||||||
|
;
|
||||||
|
; void utoa(char *buf, int num, int base)
|
||||||
|
;
|
||||||
|
utoa:
|
||||||
|
nul ax3
|
||||||
|
jmp ltostr
|
||||||
|
|
||||||
|
;
|
||||||
|
; void ltostr(char *buf, int num, int base, bool signed)
|
||||||
|
;
|
||||||
|
ltostr:
|
||||||
|
mov rax, ax0
|
||||||
|
nul rcx
|
||||||
|
|
||||||
|
; make sure base is in [2, 32]
|
||||||
|
bltu ax2, 2, .bad
|
||||||
|
bltu 36, ax2, .bad
|
||||||
|
|
||||||
|
; deal with zero
|
||||||
|
bzr ax1, .is_zero
|
||||||
|
|
||||||
|
; deal with base 10 signedness
|
||||||
|
|
||||||
|
bzr ax3, .conv
|
||||||
|
bne ax2, 10, .conv ; base 10
|
||||||
|
|
||||||
|
shr rcx, ax1, 63 ; extract ax1 sign
|
||||||
|
jrcxz .conv
|
||||||
|
|
||||||
|
neg ax1 ; NEG if negative
|
||||||
|
|
||||||
|
; main loop
|
||||||
|
.conv:
|
||||||
|
bzr ax1, .fini
|
||||||
|
|
||||||
|
rem rdx, ax1, ax2 ; ax1 % base
|
||||||
|
|
||||||
|
blt 9, rdx, .nondec ; rdx > 9 ?
|
||||||
|
|
||||||
|
add rdx, '0'
|
||||||
|
jmp .next
|
||||||
|
|
||||||
|
.nondec:
|
||||||
|
add rdx, 55 ; 'A' - 10
|
||||||
|
|
||||||
|
.next:
|
||||||
|
mov b[ax0], rdx
|
||||||
|
|
||||||
|
inc ax0
|
||||||
|
|
||||||
|
div ax1, ax2
|
||||||
|
jmp .conv
|
||||||
|
|
||||||
|
; add minus flag, null-terminate and reverse
|
||||||
|
.fini:
|
||||||
|
jrcxz .cxz
|
||||||
|
mov b[ax0], '-'
|
||||||
|
inc ax0
|
||||||
|
|
||||||
|
.cxz:
|
||||||
|
nul b[ax0]
|
||||||
|
|
||||||
|
call strrev2, rax
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; exceptional cases
|
||||||
|
;
|
||||||
|
.bad:
|
||||||
|
mov b[ax0], 0
|
||||||
|
ret
|
||||||
|
|
||||||
|
.is_zero:
|
||||||
|
mov b[ax0], 48 ; '0'
|
||||||
|
mov b[ax0+1], 0
|
||||||
|
ret
|
||||||
|
# 48 "crt/crt.k" 2
|
||||||
|
# 1 "./crt/fmt/strtol.k" 1
|
||||||
|
; The OS/K Team licenses this file to you under the MIT license.
|
||||||
|
; See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
;
|
||||||
|
; int strtol(const char *str, int base)
|
||||||
|
;
|
||||||
|
; rax = integer extracted from str
|
||||||
|
; rdx = pointer to first invalid byte
|
||||||
|
;
|
||||||
|
strtol:
|
||||||
|
mov ax2, 1
|
||||||
|
jmp strtoq
|
||||||
|
|
||||||
|
;
|
||||||
|
; int strtoul(const char *str, int base)
|
||||||
|
;
|
||||||
|
; rax = integer extracted from str
|
||||||
|
; rdx = pointer to first invalid byte
|
||||||
|
;
|
||||||
|
strtoul:
|
||||||
|
nul ax2
|
||||||
|
jmp strtoq
|
||||||
|
|
||||||
|
;
|
||||||
|
; int strtoq(const char *str, int base, bool signed)
|
||||||
|
;
|
||||||
|
; guesses base when 'base'=0
|
||||||
|
;
|
||||||
|
strtoq:
|
||||||
|
nul rax, rsi
|
||||||
|
mov rdx, ax0
|
||||||
|
|
||||||
|
; make sure base is in [2, 32]
|
||||||
|
beq ax1, 1, .bad
|
||||||
|
bltu 36, ax1, .bad
|
||||||
|
|
||||||
|
; empty string?
|
||||||
|
bzr b[rdx], .done
|
||||||
|
|
||||||
|
.skip_spc:
|
||||||
|
bne b[rdx], ' ', .no_spc
|
||||||
|
inc rdx
|
||||||
|
jmp .skip_spc
|
||||||
|
|
||||||
|
.no_spc:
|
||||||
|
; skip +
|
||||||
|
bne b[rdx], '+', .no_plus
|
||||||
|
inc rdx
|
||||||
|
|
||||||
|
.no_plus:
|
||||||
|
; unsigned?
|
||||||
|
bzr ax2, .unsigned
|
||||||
|
|
||||||
|
; parse '-'
|
||||||
|
bne b[rdx], '-', .unsigned
|
||||||
|
inc rdx
|
||||||
|
mov rsi, 1
|
||||||
|
|
||||||
|
.unsigned:
|
||||||
|
; base 0
|
||||||
|
bzr ax1, .base_0
|
||||||
|
|
||||||
|
; base prefix?
|
||||||
|
bne b[rdx], '0', .main_loop
|
||||||
|
|
||||||
|
inc rdx
|
||||||
|
movzx rcx, b[rdx]
|
||||||
|
|
||||||
|
; "0x"/"0b" prefix
|
||||||
|
jrcxz .done ; "0"
|
||||||
|
beq rcx, 'x', .parsed_0x
|
||||||
|
beq rcx, 'b', .parsed_0b
|
||||||
|
|
||||||
|
; may be octal, but we don't care
|
||||||
|
; we accept "0110101010" (despite base=2) for instance
|
||||||
|
jmp .main_loop
|
||||||
|
|
||||||
|
.parsed_0x:
|
||||||
|
; are we in base 16?
|
||||||
|
; if not, leave rax = 0 and *rdx = 'x'
|
||||||
|
bne ax1, 16, .done
|
||||||
|
; else
|
||||||
|
inc rdx
|
||||||
|
jmp .main_loop
|
||||||
|
|
||||||
|
.parsed_0b:
|
||||||
|
; are we in base 2?
|
||||||
|
; if not, leave rax = 0 and *rdx = 'b'
|
||||||
|
bne ax1, 2, .done
|
||||||
|
; else
|
||||||
|
inc rdx
|
||||||
|
jmp .main_loop
|
||||||
|
|
||||||
|
.base_0:
|
||||||
|
; guess base
|
||||||
|
|
||||||
|
beq b[rdx], '0', .b0_not10
|
||||||
|
|
||||||
|
; must be base 10
|
||||||
|
mov ax1, 10
|
||||||
|
jmp .main_loop
|
||||||
|
|
||||||
|
.b0_not10:
|
||||||
|
inc rdx
|
||||||
|
|
||||||
|
bne b[rdx], 'x', .b0_not16
|
||||||
|
inc rdx
|
||||||
|
mov ax1, 16
|
||||||
|
jmp .main_loop
|
||||||
|
|
||||||
|
.b0_not16:
|
||||||
|
bne b[rdx], 'b', .b0_not2
|
||||||
|
inc rdx
|
||||||
|
mov ax1, 2
|
||||||
|
jmp .main_loop
|
||||||
|
|
||||||
|
.b0_not2:
|
||||||
|
; take octal by default
|
||||||
|
mov ax1, 8
|
||||||
|
|
||||||
|
.main_loop:
|
||||||
|
movzx rcx, b[rdx]
|
||||||
|
inc rdx
|
||||||
|
|
||||||
|
; between 0 and 9?
|
||||||
|
bltu rcx, '0', .done
|
||||||
|
bltu '9', rcx, .not_digit10
|
||||||
|
|
||||||
|
; yes
|
||||||
|
sub rcx, '0'
|
||||||
|
jmp .next
|
||||||
|
|
||||||
|
.not_digit10:
|
||||||
|
bltu rcx, 'A', .done
|
||||||
|
bltu 'Z', rcx, .not_digitAZ
|
||||||
|
|
||||||
|
sub rcx, 55 ; 'A' - 10
|
||||||
|
jmp .next
|
||||||
|
|
||||||
|
.not_digitAZ:
|
||||||
|
bltu rcx, 'a', .done
|
||||||
|
bltu 'z', rcx, .done
|
||||||
|
|
||||||
|
sub rcx, 87 ; 'a' - 10
|
||||||
|
jmp .next
|
||||||
|
|
||||||
|
.next:
|
||||||
|
; too large for base?
|
||||||
|
blteu ax1, rcx, .done
|
||||||
|
|
||||||
|
mul rax, ax1
|
||||||
|
add rax, rcx
|
||||||
|
jmp .main_loop
|
||||||
|
|
||||||
|
.done:
|
||||||
|
; negative?
|
||||||
|
bzr rsi, .r
|
||||||
|
|
||||||
|
; yes
|
||||||
|
neg rax
|
||||||
|
|
||||||
|
.r:
|
||||||
|
ret
|
||||||
|
|
||||||
|
.bad:
|
||||||
|
ret
|
||||||
|
# 49 "crt/crt.k" 2
|
||||||
|
# 1 "./crt/fmt/doprnt.k" 1
|
||||||
|
; The OS/K Team licenses this file to you under the MIT license.
|
||||||
|
; See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
;
|
||||||
|
; typedef int (*PUTC)(int ch)
|
||||||
|
; int doprnt(PUTC putc, int n, const char *fmt, va_list ap)
|
||||||
|
;
|
||||||
|
doprnt:
|
||||||
|
push rbp
|
||||||
|
mov rbp, rsp
|
||||||
|
|
||||||
|
push r12, r13, r14
|
||||||
|
push r15, r16, r17
|
||||||
|
|
||||||
|
mov r12, ax2 ; fmt
|
||||||
|
mov r14, ax3 ; va_list
|
||||||
|
mov r15, ax1 ; n
|
||||||
|
mov r17, ax0 ; putc
|
||||||
|
nul r16 ; return value
|
||||||
|
|
||||||
|
.main_loop:
|
||||||
|
; find '%' or null-terminator
|
||||||
|
mov rcx, 0x7AFFFFFF
|
||||||
|
mov r13, r12
|
||||||
|
scasb r13, '%'
|
||||||
|
|
||||||
|
; everything below r13 is a regular character; print it
|
||||||
|
.print_regular:
|
||||||
|
beq r12, r13, .check_modf
|
||||||
|
|
||||||
|
call .doput, b[r12]
|
||||||
|
|
||||||
|
inc r12
|
||||||
|
jmp .print_regular
|
||||||
|
|
||||||
|
.check_modf:
|
||||||
|
; did we find a '%' ?
|
||||||
|
; if not, then we found fmt's null-terminator; we're done
|
||||||
|
bne b[r12], '%', .epilogue
|
||||||
|
|
||||||
|
; we did find a modifier / '%'
|
||||||
|
mov rax, b[r12+1]
|
||||||
|
add r12, 2
|
||||||
|
|
||||||
|
beq rax, 's', .modf_s
|
||||||
|
beq rax, 'c', .modf_c
|
||||||
|
beq rax, 'p', .modf_p
|
||||||
|
beq rax, 'x', .modf_x
|
||||||
|
beq rax, 'd', .modf_d
|
||||||
|
beq rax, 'o', .modf_o
|
||||||
|
beq rax, 'b', .modf_b
|
||||||
|
beq rax, '%', .modf_percent
|
||||||
|
|
||||||
|
; unrecognized
|
||||||
|
jmp .bad_modifier
|
||||||
|
|
||||||
|
.modf_s:
|
||||||
|
; get string address
|
||||||
|
mov r13, q[r14]
|
||||||
|
add r14, 8
|
||||||
|
|
||||||
|
bzr r13, .nullstring
|
||||||
|
|
||||||
|
.print_string:
|
||||||
|
movzx ax0, b[r13]
|
||||||
|
bzr ax0, .main_loop
|
||||||
|
|
||||||
|
inc r13
|
||||||
|
call .doput
|
||||||
|
|
||||||
|
jmp .print_string
|
||||||
|
|
||||||
|
.modf_c:
|
||||||
|
call .doput, q[r14]
|
||||||
|
add r14, 8
|
||||||
|
|
||||||
|
jmp .main_loop
|
||||||
|
|
||||||
|
.modf_p:
|
||||||
|
call .doput, '0'
|
||||||
|
call .doput, 'x'
|
||||||
|
; Fallthrough
|
||||||
|
|
||||||
|
.modf_x:
|
||||||
|
mov ax2, 16
|
||||||
|
jmp .print_number
|
||||||
|
|
||||||
|
.modf_d:
|
||||||
|
mov ax2, 10
|
||||||
|
jmp .print_number
|
||||||
|
|
||||||
|
.modf_o:
|
||||||
|
mov ax2, 8
|
||||||
|
jmp .print_number
|
||||||
|
|
||||||
|
.modf_b:
|
||||||
|
mov ax2, 2
|
||||||
|
jmp .print_number
|
||||||
|
|
||||||
|
.print_number:
|
||||||
|
; allocate itoa conversion buffer
|
||||||
|
sub rsp, 80
|
||||||
|
mov r13, rsp
|
||||||
|
|
||||||
|
; assume modifier already set up ax2
|
||||||
|
call itoa, rsp, q[r14]
|
||||||
|
add r14, 8
|
||||||
|
|
||||||
|
.print_itoa_buf:
|
||||||
|
movzx ax0, b[r13]
|
||||||
|
|
||||||
|
bzr ax0, .pib_end_loop
|
||||||
|
inc r13
|
||||||
|
|
||||||
|
call .doput
|
||||||
|
jmp .print_itoa_buf
|
||||||
|
|
||||||
|
.pib_end_loop:
|
||||||
|
add rsp, 80
|
||||||
|
jmp .main_loop
|
||||||
|
|
||||||
|
.modf_percent:
|
||||||
|
call .doput, '%'
|
||||||
|
jmp .main_loop
|
||||||
|
|
||||||
|
.bad_modifier:
|
||||||
|
; print "%?" to clearly indicate that something is wrong
|
||||||
|
call .doput, '%'
|
||||||
|
call .doput, '?'
|
||||||
|
|
||||||
|
jmp .main_loop
|
||||||
|
|
||||||
|
.nullstring:
|
||||||
|
; %s was passed a NULL
|
||||||
|
call .doput, '('
|
||||||
|
call .doput, 'n'
|
||||||
|
call .doput, 'u'
|
||||||
|
call .doput, 'l'
|
||||||
|
call .doput, 'l'
|
||||||
|
call .doput, ')'
|
||||||
|
|
||||||
|
jmp .main_loop
|
||||||
|
|
||||||
|
.epilogue:
|
||||||
|
mov rax, r16
|
||||||
|
|
||||||
|
pop r17, r16
|
||||||
|
pop r15, r14
|
||||||
|
pop r13, r12
|
||||||
|
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
;
|
||||||
|
; prints ax0
|
||||||
|
;
|
||||||
|
.doput:
|
||||||
|
; update print count
|
||||||
|
inc r16
|
||||||
|
|
||||||
|
; if n==0, don't print
|
||||||
|
; we follow the C convention that sprintf()-like functions
|
||||||
|
; should return the number of characters that would have
|
||||||
|
; been printed/written if 'n' were big enough
|
||||||
|
bzr r15, .r
|
||||||
|
|
||||||
|
; decrement n and print
|
||||||
|
dec r15
|
||||||
|
call r17
|
||||||
|
|
||||||
|
; did putc fail?
|
||||||
|
jraxz .r
|
||||||
|
|
||||||
|
; yes, so artificially set n=0
|
||||||
|
nul r15
|
||||||
|
|
||||||
|
.r:
|
||||||
|
ret
|
||||||
|
# 50 "crt/crt.k" 2
|
||||||
|
# 1 "./crt/fmt/printf.k" 1
|
||||||
|
; The OS/K Team licenses this file to you under the MIT license.
|
||||||
|
; See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
;
|
||||||
|
; int putc(int ch)
|
||||||
|
;
|
||||||
|
putc:
|
||||||
|
prn ax0
|
||||||
|
nul rax
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; int printf(const char *fmt, ...)
|
||||||
|
;
|
||||||
|
printf:
|
||||||
|
mov ax2, ax0
|
||||||
|
mov ax0, putc
|
||||||
|
mov ax1, 0x7AFFFFFF
|
||||||
|
add ax3, rsp, 8
|
||||||
|
jmp doprnt
|
||||||
|
|
||||||
|
;
|
||||||
|
; int nprintf(const char *fmt, int n, ...)
|
||||||
|
;
|
||||||
|
nprintf:
|
||||||
|
mov ax2, ax0
|
||||||
|
mov ax0, putc
|
||||||
|
add ax3, rsp, 8
|
||||||
|
jmp doprnt
|
||||||
|
|
||||||
|
;
|
||||||
|
; Print a string
|
||||||
|
; Guaranteed to only affect rcx and ax0
|
||||||
|
;
|
||||||
|
print:
|
||||||
|
.l:
|
||||||
|
movzx rax, b[ax0]
|
||||||
|
jraxz .r
|
||||||
|
|
||||||
|
prn rax
|
||||||
|
inc ax0
|
||||||
|
|
||||||
|
jmp .l
|
||||||
|
|
||||||
|
.r:
|
||||||
|
ret
|
||||||
|
|
||||||
|
;
|
||||||
|
; Print exactly ax1 characters
|
||||||
|
;
|
||||||
|
nprint:
|
||||||
|
mov rcx, ax1
|
||||||
|
jrcxz .r
|
||||||
|
|
||||||
|
.l:
|
||||||
|
prn b[ax0]
|
||||||
|
inc ax0
|
||||||
|
loop .l
|
||||||
|
.r:
|
||||||
|
ret
|
||||||
|
# 51 "crt/crt.k" 2
|
||||||
|
|
||||||
|
exit:
|
||||||
|
mov rax, Sys.Exit
|
||||||
|
trap 0
|
||||||
|
|
||||||
|
abort:
|
||||||
|
crash
|
||||||
|
# 8 "hello.k" 2
|
||||||
|
|
||||||
|
main:
|
||||||
|
mov rsp, 0x104000
|
||||||
|
nul rbp
|
||||||
|
|
||||||
|
call print, .hellow
|
||||||
|
|
||||||
|
jmp exit
|
||||||
|
|
||||||
|
.hellow = "Hello World!\n"
|
Loading…
Reference in New Issue
Block a user