diff options
Diffstat (limited to '04a')
-rw-r--r-- | 04a/Makefile | 8 | ||||
-rw-r--r-- | 04a/in04 | 244 |
2 files changed, 247 insertions, 5 deletions
diff --git a/04a/Makefile b/04a/Makefile index f6b9915..610b054 100644 --- a/04a/Makefile +++ b/04a/Makefile @@ -1,8 +1,6 @@ -all: out03 out04a README.html -out03: in03 ../03/out02 - ../03/out02 -out04a: out03 in04a - ./out03 in04a out04a +all: out04 +out04: in04 ../04/out03 + ../04/out03 %.html: %.md ../markdown ../markdown $< clean: @@ -0,0 +1,244 @@ +; add 24 + 16 = 40 to the stack pointer to put argc, argv in the right place +byte 0x48 +byte 0x81 +byte 0xc4 +byte 40 +byte 0 +byte 0 +byte 0 + +global output_fd + +goto main + +function main + argument argv2 + argument argv1 + argument argv0 + argument argc + local input_filename + local output_filename + + if argc < 3 goto default_filenames + input_filename = argv1 + output_filename = argv2 + goto got_filenames + :default_filenames + input_filename = .str_default_input_filename + output_filename = .str_default_output_filename + :got_filenames + + output_fd = syscall(2, output_filename, 0x241, 420) ; 420 = octal 644 + if output_fd >= 0 goto output_file_good + file_error(output_filename) + :output_file_good + exit(0) + +:str_default_input_filename + string in04a + byte 0 + +:str_default_output_filename + string out04a + byte 0 + +function file_error + argument name + fputs(2, .str_file_error) + fputs(2, name) + fputc(2, 10) + exit(1) + +:str_file_error + string Error opening file: + byte 32 + byte 0 + + +; returns a pointer to a null-terminated string containing the number given +function itos + global 32 itos_string + argument x + local c + local p + p = &itos_string + p += 30 + :itos_loop + c = x % 10 + c += '0 + *1p = c + x /= 10 + if x == 0 goto itos_loop_end + p -= 1 + goto itos_loop + :itos_loop_end + return p + + +; returns the number at the start of the given string +function stoi + argument s + local p + local n + local c + n = 0 + p = s + :stoi_loop + c = *1p + if c < '0 goto stoi_loop_end + if c > '9 goto stoi_loop_end + n *= 10 + n += c - '0 + p += 1 + goto stoi_loop + :stoi_loop_end + return n + + +function strlen + argument s + local c + local p + p = s + :strlen_loop + c = *1p + if c == 0 goto strlen_loop_end + p += 1 + goto strlen_loop + :strlen_loop_end + return p - s + +function fputs + argument fd + argument s + local length + length = strlen(s) + syscall(1, fd, s, length) + return + +function puts + argument s + fputs(1, s) + return + +function fputn + argument fd + argument n + local s + s = itos(n) + fputs(fd, s) + return + +function fputc + argument fd + argument c + local p + p = &c + syscall(1, fd, p, 1) + return + +function putc + argument c + fputc(1, c) + return + +function exit + argument status_code + syscall(0x3c, status_code) + + +function syscall + ; I've done some testing, and this should be okay even if + ; rbp-56 goes beyond the end of the stack. + ; mov rax, [rbp-16] + byte 0x48 + byte 0x8b + byte 0x85 + byte 0xf0 + byte 0xff + byte 0xff + byte 0xff + ; mov rdi, rax + byte 0x48 + byte 0x89 + byte 0xc7 + + ; mov rax, [rbp-24] + byte 0x48 + byte 0x8b + byte 0x85 + byte 0xe8 + byte 0xff + byte 0xff + byte 0xff + ; mov rsi, rax + byte 0x48 + byte 0x89 + byte 0xc6 + + ; mov rax, [rbp-32] + byte 0x48 + byte 0x8b + byte 0x85 + byte 0xe0 + byte 0xff + byte 0xff + byte 0xff + ; mov rdx, rax + byte 0x48 + byte 0x89 + byte 0xc2 + + ; mov rax, [rbp-40] + byte 0x48 + byte 0x8b + byte 0x85 + byte 0xd8 + byte 0xff + byte 0xff + byte 0xff + ; mov r10, rax + byte 0x49 + byte 0x89 + byte 0xc2 + + ; mov rax, [rbp-48] + byte 0x48 + byte 0x8b + byte 0x85 + byte 0xd0 + byte 0xff + byte 0xff + byte 0xff + ; mov r8, rax + byte 0x49 + byte 0x89 + byte 0xc0 + + ; mov rax, [rbp-56] + byte 0x48 + byte 0x8b + byte 0x85 + byte 0xc8 + byte 0xff + byte 0xff + byte 0xff + ; mov r9, rax + byte 0x49 + byte 0x89 + byte 0xc1 + + ; mov rax, [rbp-8] + byte 0x48 + byte 0x8b + byte 0x85 + byte 0xf8 + byte 0xff + byte 0xff + byte 0xff + + ; syscall + byte 0x0f + byte 0x05 + + return |