updates to io.sl
This commit is contained in:
2
a.sl
2
a.sl
@@ -4,4 +4,4 @@ import stdlib/io.sl
|
||||
: main
|
||||
"hello world" puts
|
||||
;
|
||||
compile-time main
|
||||
compile-time main
|
||||
|
||||
596
build/a.asm
596
build/a.asm
@@ -1,596 +0,0 @@
|
||||
section .text
|
||||
%define DSTK_BYTES 65536
|
||||
%define RSTK_BYTES 65536
|
||||
%define PRINT_BUF_BYTES 128
|
||||
global _start
|
||||
_start:
|
||||
; initialize data/return stack pointers
|
||||
lea r12, [rel dstack_top]
|
||||
mov r15, r12
|
||||
lea r13, [rel rstack_top]
|
||||
call word_main
|
||||
mov rax, 0
|
||||
cmp r12, r15
|
||||
je .no_exit_value
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
.no_exit_value:
|
||||
mov rdi, rax
|
||||
mov rax, 60
|
||||
syscall
|
||||
word_c_40:
|
||||
mov rax, [r12]
|
||||
movzx rax, byte [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_c_21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rbx], al
|
||||
ret
|
||||
ret
|
||||
word_r_40:
|
||||
mov rax, [r13]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_dup:
|
||||
mov rax, [r12]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_drop:
|
||||
add r12, 8
|
||||
ret
|
||||
word_over:
|
||||
mov rax, [r12 + 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_swap:
|
||||
mov rax, [r12]
|
||||
mov rbx, [r12 + 8]
|
||||
mov [r12], rbx
|
||||
mov [r12 + 8], rax
|
||||
ret
|
||||
word_rot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rcx ; top = x1
|
||||
mov [r12 + 8], rax ; next = x3
|
||||
mov [r12 + 16], rbx ; third = x2
|
||||
ret
|
||||
word__2drot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rbx ; top = x2
|
||||
mov [r12 + 8], rcx ; next = x1
|
||||
mov [r12 + 16], rax ; third = x3
|
||||
ret
|
||||
word_nip:
|
||||
mov rax, [r12]
|
||||
add r12, 8 ; drop lower element
|
||||
mov [r12], rax ; keep original top
|
||||
ret
|
||||
word_tuck:
|
||||
mov rax, [r12] ; x2
|
||||
mov rbx, [r12 + 8] ; x1
|
||||
sub r12, 8 ; make room
|
||||
mov [r12], rax ; x2
|
||||
mov [r12 + 8], rbx ; x1
|
||||
mov [r12 + 16], rax ; x2
|
||||
ret
|
||||
word_2dup:
|
||||
mov rax, [r12] ; b
|
||||
mov rbx, [r12 + 8] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word_2drop:
|
||||
add r12, 16
|
||||
ret
|
||||
word_2swap:
|
||||
mov rax, [r12] ; d
|
||||
mov rbx, [r12 + 8] ; c
|
||||
mov rcx, [r12 + 16] ; b
|
||||
mov rdx, [r12 + 24] ; a
|
||||
mov [r12], rcx ; top = b
|
||||
mov [r12 + 8], rdx ; next = a
|
||||
mov [r12 + 16], rax ; third = d
|
||||
mov [r12 + 24], rbx ; fourth = c
|
||||
ret
|
||||
word_2over:
|
||||
mov rax, [r12 + 16] ; b
|
||||
mov rbx, [r12 + 24] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word__2b:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
add qword [r12], rax
|
||||
ret
|
||||
word__2d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub qword [r12], rax
|
||||
ret
|
||||
word__2a:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
imul qword [r12]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__2f:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__25:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rdx
|
||||
ret
|
||||
word__3d_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
sete bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__21_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setne bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setl bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setg bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setle bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setge bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__40:
|
||||
mov rax, [r12]
|
||||
mov rax, [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rax], rbx
|
||||
add r12, 8
|
||||
ret
|
||||
word_mmap:
|
||||
; Save rsp and align to 16 bytes for syscall ABI
|
||||
mov rax, rsp
|
||||
and rsp, -16
|
||||
mov rdi, [r12+40] ; addr
|
||||
mov rsi, [r12+32] ; length
|
||||
mov rdx, [r12+24] ; prot
|
||||
mov r10, [r12+16] ; flags
|
||||
mov r8, [r12+8] ; fd
|
||||
mov r9, [r12] ; offset
|
||||
add r12, 48 ; pop 6 args
|
||||
mov rax, 9 ; syscall: mmap
|
||||
syscall
|
||||
mov rsp, rax ; restore rsp
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push result
|
||||
ret
|
||||
ret
|
||||
word_munmap:
|
||||
mov rsi, [r12]
|
||||
add r12, 8
|
||||
mov rdi, [r12]
|
||||
mov rax, 11
|
||||
syscall
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_exit:
|
||||
mov rdi, [r12]
|
||||
add r12, 8
|
||||
mov rax, 60
|
||||
syscall
|
||||
ret
|
||||
word_and:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
and rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_or:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
or rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_not:
|
||||
mov rax, [r12]
|
||||
test rax, rax
|
||||
setz al
|
||||
movzx rax, al
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__3er:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub r13, 8
|
||||
mov [r13], rax
|
||||
ret
|
||||
word_r_3e:
|
||||
mov rax, [r13]
|
||||
add r13, 8
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rdrop:
|
||||
add r13, 8
|
||||
ret
|
||||
word_pick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rpick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r13 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_read_file:
|
||||
; stack: path_ptr (top), path_len (next)
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
add r12, 16 ; pop args
|
||||
|
||||
; open(path_ptr, O_RDONLY=0, mode=0)
|
||||
mov rax, 2 ; syscall: open
|
||||
mov rdi, rsi ; filename
|
||||
xor rsi, rsi ; flags = O_RDONLY
|
||||
xor rdx, rdx ; mode = 0
|
||||
syscall
|
||||
mov r10, rax ; save open() result
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r8, rax ; fd
|
||||
|
||||
; use lseek to determine file size: lseek(fd, 0, SEEK_END)
|
||||
mov rax, 8 ; syscall: lseek
|
||||
mov rdi, r8 ; fd
|
||||
xor rsi, rsi ; offset = 0
|
||||
mov rdx, 2 ; SEEK_END
|
||||
syscall
|
||||
mov r11, rax ; save lseek() result
|
||||
cmp rax, 0
|
||||
jl .close_fail_lseek
|
||||
mov rsi, rax ; length = size
|
||||
|
||||
; mmap(NULL, size, PROT_READ=1, MAP_PRIVATE=2, fd, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
; rsi already holds length
|
||||
mov rdx, 1 ; PROT_READ
|
||||
mov r10, 2 ; MAP_PRIVATE
|
||||
mov r8, r8 ; fd
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
mov rbx, rax ; addr
|
||||
mov r12, r12 ; (no-op, for debug)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r8 ; fd
|
||||
syscall
|
||||
cmp rbx, -4095
|
||||
jae .fail_mmap
|
||||
sub r12, 16
|
||||
mov [r12], rsi ; len (rsi held length across syscall)
|
||||
mov [r12 + 8], rbx ; addr
|
||||
ret
|
||||
|
||||
.close_fail_lseek:
|
||||
mov rax, 3
|
||||
mov rdi, r8
|
||||
syscall
|
||||
mov rax, r11 ; return lseek() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -1
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
mov rax, r10 ; return open() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -2
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
mov rax, -1 ; return mmap() error
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -3
|
||||
ret
|
||||
ret
|
||||
word_write_file:
|
||||
; stack: path_ptr (top), path_len, buf_ptr, buf_len
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
mov r15, [r12 + 16] ; buf_ptr (save in callee-saved r15)
|
||||
mov r13, [r12 + 24] ; buf_len (save in callee-saved r13)
|
||||
add r12, 32 ; pop 4 args (we saved buf info)
|
||||
|
||||
; open(path_ptr, O_WRONLY|O_CREAT|O_TRUNC, 0666)
|
||||
mov rdi, rsi ; filename
|
||||
mov rsi, 577 ; flags = O_WRONLY|O_CREAT|O_TRUNC
|
||||
mov rdx, 438 ; mode = 0o666
|
||||
mov rax, 2 ; syscall: open
|
||||
syscall
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r9, rax ; save fd
|
||||
|
||||
; write(fd, buf_ptr, buf_len) -- use preserved r15/r13 which survive syscalls
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, r9 ; fd
|
||||
mov rsi, r15 ; buf_ptr
|
||||
mov rdx, r13 ; buf_len
|
||||
syscall
|
||||
mov r10, rax ; save write result
|
||||
cmp r10, 0
|
||||
jl .fail_write
|
||||
|
||||
; close(fd)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r9
|
||||
syscall
|
||||
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_write:
|
||||
mov rax, 3
|
||||
mov rdi, r9
|
||||
syscall
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_read_stdin:
|
||||
; stack: max_len
|
||||
mov r14, [r12] ; max_len
|
||||
add r12, 8 ; pop max_len
|
||||
|
||||
; mmap(NULL, max_len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
mov rsi, r14 ; length
|
||||
mov rdx, 3 ; PROT_READ|PROT_WRITE
|
||||
mov r10, 34 ; MAP_PRIVATE|MAP_ANONYMOUS
|
||||
mov r8, -1 ; fd = -1
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
cmp rax, -4095
|
||||
jae .fail_mmap
|
||||
mov rbx, rax ; buffer addr
|
||||
xor r9, r9 ; bytes_read = 0
|
||||
|
||||
.read_loop:
|
||||
mov rax, 0 ; syscall: read
|
||||
mov rdi, 0 ; fd = stdin
|
||||
lea rsi, [rbx + r9] ; buf + offset
|
||||
mov rdx, r14
|
||||
sub rdx, r9 ; remaining = max_len - bytes_read
|
||||
syscall
|
||||
cmp rax, 0
|
||||
je .done_read
|
||||
js .read_error
|
||||
add r9, rax
|
||||
jl .read_loop
|
||||
|
||||
.done_read:
|
||||
; push len (rcx) then addr (rbx)
|
||||
cmp r9, r14
|
||||
je .done_no_null
|
||||
mov byte [rbx + r9], 0
|
||||
.done_no_null:
|
||||
sub r12, 16
|
||||
mov [r12], r9
|
||||
mov [r12 + 8], rbx
|
||||
ret
|
||||
|
||||
.read_error:
|
||||
; return negative errno in rax, addr = 0
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], 0
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
sub r12, 16
|
||||
mov qword [r12], -1
|
||||
mov qword [r12 + 8], 0
|
||||
ret
|
||||
ret
|
||||
word_puts:
|
||||
; detects string if top is len>=0 and next is a pointer in [data_start, data_end]
|
||||
mov rax, [r12] ; len or int value
|
||||
mov rbx, [r12 + 8] ; possible address
|
||||
cmp rax, 0
|
||||
jl puts_print_int
|
||||
lea r8, [rel data_start]
|
||||
lea r9, [rel data_end]
|
||||
cmp rbx, r8
|
||||
jl puts_print_int
|
||||
cmp rbx, r9
|
||||
jge puts_print_int
|
||||
; treat as string: (addr below len)
|
||||
mov rdx, rax ; len
|
||||
mov rsi, rbx ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
test rdx, rdx
|
||||
jz puts_str_newline_only
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
syscall
|
||||
puts_str_newline_only:
|
||||
mov byte [rel print_buf], 10
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
lea rsi, [rel print_buf]
|
||||
mov rdx, 1
|
||||
syscall
|
||||
ret
|
||||
puts_print_int:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, rax
|
||||
mov r8, 0
|
||||
cmp rbx, 0
|
||||
jge puts_abs
|
||||
neg rbx
|
||||
mov r8, 1
|
||||
puts_abs:
|
||||
lea rsi, [rel print_buf_end]
|
||||
mov rcx, 0
|
||||
mov r10, 10
|
||||
cmp rbx, 0
|
||||
jne puts_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '0'
|
||||
inc rcx
|
||||
jmp puts_sign
|
||||
puts_digits:
|
||||
puts_loop:
|
||||
xor rdx, rdx
|
||||
mov rax, rbx
|
||||
div r10
|
||||
add dl, '0'
|
||||
dec rsi
|
||||
mov [rsi], dl
|
||||
inc rcx
|
||||
mov rbx, rax
|
||||
test rbx, rbx
|
||||
jne puts_loop
|
||||
puts_sign:
|
||||
cmp r8, 0
|
||||
je puts_finish_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '-'
|
||||
inc rcx
|
||||
puts_finish_digits:
|
||||
mov byte [rsi + rcx], 10
|
||||
inc rcx
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
mov rdx, rcx
|
||||
mov r9, rsi
|
||||
mov rsi, r9
|
||||
syscall
|
||||
ret
|
||||
word_write_buf:
|
||||
mov rdx, [r12] ; len
|
||||
mov rsi, [r12 + 8] ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, 1 ; fd = stdout
|
||||
syscall
|
||||
ret
|
||||
ret
|
||||
word_main:
|
||||
; push str_0
|
||||
sub r12, 8
|
||||
mov qword [r12], str_0
|
||||
; push 11
|
||||
sub r12, 8
|
||||
mov qword [r12], 11
|
||||
call word_puts
|
||||
ret
|
||||
section .data
|
||||
data_start:
|
||||
str_0: db 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 0
|
||||
str_0_len equ 11
|
||||
data_end:
|
||||
section .bss
|
||||
align 16
|
||||
dstack: resb DSTK_BYTES
|
||||
dstack_top:
|
||||
align 16
|
||||
rstack: resb RSTK_BYTES
|
||||
rstack_top:
|
||||
align 16
|
||||
print_buf: resb PRINT_BUF_BYTES
|
||||
print_buf_end:
|
||||
@@ -1,621 +0,0 @@
|
||||
section .text
|
||||
%define DSTK_BYTES 65536
|
||||
%define RSTK_BYTES 65536
|
||||
%define PRINT_BUF_BYTES 128
|
||||
global _start
|
||||
_start:
|
||||
; initialize data/return stack pointers
|
||||
lea r12, [rel dstack_top]
|
||||
mov r15, r12
|
||||
lea r13, [rel rstack_top]
|
||||
call word_main
|
||||
mov rax, 0
|
||||
cmp r12, r15
|
||||
je .no_exit_value
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
.no_exit_value:
|
||||
mov rdi, rax
|
||||
mov rax, 60
|
||||
syscall
|
||||
word_c_40:
|
||||
mov rax, [r12]
|
||||
movzx rax, byte [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_c_21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rbx], al
|
||||
ret
|
||||
ret
|
||||
word_r_40:
|
||||
mov rax, [r13]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_dup:
|
||||
mov rax, [r12]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_drop:
|
||||
add r12, 8
|
||||
ret
|
||||
word_over:
|
||||
mov rax, [r12 + 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_swap:
|
||||
mov rax, [r12]
|
||||
mov rbx, [r12 + 8]
|
||||
mov [r12], rbx
|
||||
mov [r12 + 8], rax
|
||||
ret
|
||||
word_rot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rcx ; top = x1
|
||||
mov [r12 + 8], rax ; next = x3
|
||||
mov [r12 + 16], rbx ; third = x2
|
||||
ret
|
||||
word__2drot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rbx ; top = x2
|
||||
mov [r12 + 8], rcx ; next = x1
|
||||
mov [r12 + 16], rax ; third = x3
|
||||
ret
|
||||
word_nip:
|
||||
mov rax, [r12]
|
||||
add r12, 8 ; drop lower element
|
||||
mov [r12], rax ; keep original top
|
||||
ret
|
||||
word_tuck:
|
||||
mov rax, [r12] ; x2
|
||||
mov rbx, [r12 + 8] ; x1
|
||||
sub r12, 8 ; make room
|
||||
mov [r12], rax ; x2
|
||||
mov [r12 + 8], rbx ; x1
|
||||
mov [r12 + 16], rax ; x2
|
||||
ret
|
||||
word_2dup:
|
||||
mov rax, [r12] ; b
|
||||
mov rbx, [r12 + 8] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word_2drop:
|
||||
add r12, 16
|
||||
ret
|
||||
word_2swap:
|
||||
mov rax, [r12] ; d
|
||||
mov rbx, [r12 + 8] ; c
|
||||
mov rcx, [r12 + 16] ; b
|
||||
mov rdx, [r12 + 24] ; a
|
||||
mov [r12], rcx ; top = b
|
||||
mov [r12 + 8], rdx ; next = a
|
||||
mov [r12 + 16], rax ; third = d
|
||||
mov [r12 + 24], rbx ; fourth = c
|
||||
ret
|
||||
word_2over:
|
||||
mov rax, [r12 + 16] ; b
|
||||
mov rbx, [r12 + 24] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word__2b:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
add qword [r12], rax
|
||||
ret
|
||||
word__2d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub qword [r12], rax
|
||||
ret
|
||||
word__2a:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
imul qword [r12]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__2f:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__25:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rdx
|
||||
ret
|
||||
word__3d_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
sete bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__21_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setne bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setl bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setg bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setle bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setge bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__40:
|
||||
mov rax, [r12]
|
||||
mov rax, [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rax], rbx
|
||||
add r12, 8
|
||||
ret
|
||||
word_mmap:
|
||||
; Save rsp and align to 16 bytes for syscall ABI
|
||||
mov rax, rsp
|
||||
and rsp, -16
|
||||
mov rdi, [r12+40] ; addr
|
||||
mov rsi, [r12+32] ; length
|
||||
mov rdx, [r12+24] ; prot
|
||||
mov r10, [r12+16] ; flags
|
||||
mov r8, [r12+8] ; fd
|
||||
mov r9, [r12] ; offset
|
||||
add r12, 48 ; pop 6 args
|
||||
mov rax, 9 ; syscall: mmap
|
||||
syscall
|
||||
mov rsp, rax ; restore rsp
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push result
|
||||
ret
|
||||
ret
|
||||
word_munmap:
|
||||
mov rsi, [r12]
|
||||
add r12, 8
|
||||
mov rdi, [r12]
|
||||
mov rax, 11
|
||||
syscall
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_exit:
|
||||
mov rdi, [r12]
|
||||
add r12, 8
|
||||
mov rax, 60
|
||||
syscall
|
||||
ret
|
||||
word_and:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
and rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_or:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
or rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_not:
|
||||
mov rax, [r12]
|
||||
test rax, rax
|
||||
setz al
|
||||
movzx rax, al
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__3er:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub r13, 8
|
||||
mov [r13], rax
|
||||
ret
|
||||
word_r_3e:
|
||||
mov rax, [r13]
|
||||
add r13, 8
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rdrop:
|
||||
add r13, 8
|
||||
ret
|
||||
word_pick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rpick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r13 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_read_file:
|
||||
; stack: path_ptr (top), path_len (next)
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
add r12, 16 ; pop args
|
||||
|
||||
; open(path_ptr, O_RDONLY=0, mode=0)
|
||||
mov rax, 2 ; syscall: open
|
||||
mov rdi, rsi ; filename
|
||||
xor rsi, rsi ; flags = O_RDONLY
|
||||
xor rdx, rdx ; mode = 0
|
||||
syscall
|
||||
mov r10, rax ; save open() result
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r8, rax ; fd
|
||||
|
||||
; use lseek to determine file size: lseek(fd, 0, SEEK_END)
|
||||
mov rax, 8 ; syscall: lseek
|
||||
mov rdi, r8 ; fd
|
||||
xor rsi, rsi ; offset = 0
|
||||
mov rdx, 2 ; SEEK_END
|
||||
syscall
|
||||
mov r11, rax ; save lseek() result
|
||||
cmp rax, 0
|
||||
jl .close_fail_lseek
|
||||
mov rsi, rax ; length = size
|
||||
|
||||
; mmap(NULL, size, PROT_READ=1, MAP_PRIVATE=2, fd, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
; rsi already holds length
|
||||
mov rdx, 1 ; PROT_READ
|
||||
mov r10, 2 ; MAP_PRIVATE
|
||||
mov r8, r8 ; fd
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
mov rbx, rax ; addr
|
||||
mov r12, r12 ; (no-op, for debug)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r8 ; fd
|
||||
syscall
|
||||
cmp rbx, -4095
|
||||
jae .fail_mmap
|
||||
sub r12, 16
|
||||
mov [r12], rsi ; len (rsi held length across syscall)
|
||||
mov [r12 + 8], rbx ; addr
|
||||
ret
|
||||
|
||||
.close_fail_lseek:
|
||||
mov rax, 3
|
||||
mov rdi, r8
|
||||
syscall
|
||||
mov rax, r11 ; return lseek() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -1
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
mov rax, r10 ; return open() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -2
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
mov rax, -1 ; return mmap() error
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -3
|
||||
ret
|
||||
ret
|
||||
word_write_file:
|
||||
; stack: path_ptr (top), path_len, buf_ptr, buf_len
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
mov r15, [r12 + 16] ; buf_ptr (save in callee-saved r15)
|
||||
mov r13, [r12 + 24] ; buf_len (save in callee-saved r13)
|
||||
add r12, 32 ; pop 4 args (we saved buf info)
|
||||
|
||||
; open(path_ptr, O_WRONLY|O_CREAT|O_TRUNC, 0666)
|
||||
mov rdi, rsi ; filename
|
||||
mov rsi, 577 ; flags = O_WRONLY|O_CREAT|O_TRUNC
|
||||
mov rdx, 438 ; mode = 0o666
|
||||
mov rax, 2 ; syscall: open
|
||||
syscall
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r9, rax ; save fd
|
||||
|
||||
; write(fd, buf_ptr, buf_len) -- use preserved r15/r13 which survive syscalls
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, r9 ; fd
|
||||
mov rsi, r15 ; buf_ptr
|
||||
mov rdx, r13 ; buf_len
|
||||
syscall
|
||||
mov r10, rax ; save write result
|
||||
cmp r10, 0
|
||||
jl .fail_write
|
||||
|
||||
; close(fd)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r9
|
||||
syscall
|
||||
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_write:
|
||||
mov rax, 3
|
||||
mov rdi, r9
|
||||
syscall
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_read_stdin:
|
||||
; stack: max_len
|
||||
mov r14, [r12] ; max_len
|
||||
add r12, 8 ; pop max_len
|
||||
|
||||
; mmap(NULL, max_len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
mov rsi, r14 ; length
|
||||
mov rdx, 3 ; PROT_READ|PROT_WRITE
|
||||
mov r10, 34 ; MAP_PRIVATE|MAP_ANONYMOUS
|
||||
mov r8, -1 ; fd = -1
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
cmp rax, -4095
|
||||
jae .fail_mmap
|
||||
mov rbx, rax ; buffer addr
|
||||
xor r9, r9 ; bytes_read = 0
|
||||
|
||||
.read_loop:
|
||||
mov rax, 0 ; syscall: read
|
||||
mov rdi, 0 ; fd = stdin
|
||||
lea rsi, [rbx + r9] ; buf + offset
|
||||
mov rdx, r14
|
||||
sub rdx, r9 ; remaining = max_len - bytes_read
|
||||
syscall
|
||||
cmp rax, 0
|
||||
je .done_read
|
||||
js .read_error
|
||||
add r9, rax
|
||||
jl .read_loop
|
||||
|
||||
.done_read:
|
||||
; push len (rcx) then addr (rbx)
|
||||
cmp r9, r14
|
||||
je .done_no_null
|
||||
mov byte [rbx + r9], 0
|
||||
.done_no_null:
|
||||
sub r12, 16
|
||||
mov [r12], r9
|
||||
mov [r12 + 8], rbx
|
||||
ret
|
||||
|
||||
.read_error:
|
||||
; return negative errno in rax, addr = 0
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], 0
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
sub r12, 16
|
||||
mov qword [r12], -1
|
||||
mov qword [r12 + 8], 0
|
||||
ret
|
||||
ret
|
||||
word_puts:
|
||||
; detects string if top is len>=0 and next is a pointer in [data_start, data_end]
|
||||
mov rax, [r12] ; len or int value
|
||||
mov rbx, [r12 + 8] ; possible address
|
||||
cmp rax, 0
|
||||
jl puts_print_int
|
||||
lea r8, [rel data_start]
|
||||
lea r9, [rel data_end]
|
||||
cmp rbx, r8
|
||||
jl puts_print_int
|
||||
cmp rbx, r9
|
||||
jge puts_print_int
|
||||
; treat as string: (addr below len)
|
||||
mov rdx, rax ; len
|
||||
mov rsi, rbx ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
test rdx, rdx
|
||||
jz puts_str_newline_only
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
syscall
|
||||
puts_str_newline_only:
|
||||
mov byte [rel print_buf], 10
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
lea rsi, [rel print_buf]
|
||||
mov rdx, 1
|
||||
syscall
|
||||
ret
|
||||
puts_print_int:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, rax
|
||||
mov r8, 0
|
||||
cmp rbx, 0
|
||||
jge puts_abs
|
||||
neg rbx
|
||||
mov r8, 1
|
||||
puts_abs:
|
||||
lea rsi, [rel print_buf_end]
|
||||
mov rcx, 0
|
||||
mov r10, 10
|
||||
cmp rbx, 0
|
||||
jne puts_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '0'
|
||||
inc rcx
|
||||
jmp puts_sign
|
||||
puts_digits:
|
||||
puts_loop:
|
||||
xor rdx, rdx
|
||||
mov rax, rbx
|
||||
div r10
|
||||
add dl, '0'
|
||||
dec rsi
|
||||
mov [rsi], dl
|
||||
inc rcx
|
||||
mov rbx, rax
|
||||
test rbx, rbx
|
||||
jne puts_loop
|
||||
puts_sign:
|
||||
cmp r8, 0
|
||||
je puts_finish_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '-'
|
||||
inc rcx
|
||||
puts_finish_digits:
|
||||
mov byte [rsi + rcx], 10
|
||||
inc rcx
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
mov rdx, rcx
|
||||
mov r9, rsi
|
||||
mov rsi, r9
|
||||
syscall
|
||||
ret
|
||||
word_write_buf:
|
||||
mov rdx, [r12] ; len
|
||||
mov rsi, [r12 + 8] ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, 1 ; fd = stdout
|
||||
syscall
|
||||
ret
|
||||
ret
|
||||
word_main:
|
||||
; push 2
|
||||
sub r12, 8
|
||||
mov qword [r12], 2
|
||||
; push 40
|
||||
sub r12, 8
|
||||
mov qword [r12], 40
|
||||
call word__2b
|
||||
call word_puts
|
||||
; push 1
|
||||
sub r12, 8
|
||||
mov qword [r12], 1
|
||||
; push 2
|
||||
sub r12, 8
|
||||
mov qword [r12], 2
|
||||
call word_foo
|
||||
call word_puts
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
ret
|
||||
word_foo:
|
||||
call word__3er
|
||||
call word__3er
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
call word_rpick
|
||||
; push 1
|
||||
sub r12, 8
|
||||
mov qword [r12], 1
|
||||
call word_rpick
|
||||
call word__2b
|
||||
call word_rdrop
|
||||
call word_rdrop
|
||||
ret
|
||||
section .data
|
||||
data_start:
|
||||
data_end:
|
||||
section .bss
|
||||
align 16
|
||||
dstack: resb DSTK_BYTES
|
||||
dstack_top:
|
||||
align 16
|
||||
rstack: resb RSTK_BYTES
|
||||
rstack_top:
|
||||
align 16
|
||||
print_buf: resb PRINT_BUF_BYTES
|
||||
print_buf_end:
|
||||
Binary file not shown.
@@ -1,521 +0,0 @@
|
||||
section .text
|
||||
%define DSTK_BYTES 65536
|
||||
%define RSTK_BYTES 65536
|
||||
%define PRINT_BUF_BYTES 128
|
||||
global _start
|
||||
_start:
|
||||
; initialize data/return stack pointers
|
||||
lea r12, [rel dstack_top]
|
||||
mov r15, r12
|
||||
lea r13, [rel rstack_top]
|
||||
call word_main
|
||||
mov rax, 0
|
||||
cmp r12, r15
|
||||
je .no_exit_value
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
.no_exit_value:
|
||||
mov rdi, rax
|
||||
mov rax, 60
|
||||
syscall
|
||||
word_c_40:
|
||||
mov rax, [r12]
|
||||
movzx rax, byte [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_c_21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rbx], al
|
||||
ret
|
||||
ret
|
||||
word_r_40:
|
||||
mov rax, [r13]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_strlen:
|
||||
mov rax, [r12] ; addr
|
||||
mov rcx, [r12 + 8] ; len
|
||||
add r12, 16 ; pop len and addr
|
||||
mov [r12], rcx ; push len
|
||||
ret
|
||||
ret
|
||||
word_puts:
|
||||
; detects string if top is len>=0 and next is a pointer in [data_start, data_end]
|
||||
mov rax, [r12] ; len or int value
|
||||
mov rbx, [r12 + 8] ; possible address
|
||||
cmp rax, 0
|
||||
jl puts_print_int
|
||||
lea r8, [rel data_start]
|
||||
lea r9, [rel print_buf_end]
|
||||
cmp rbx, r8
|
||||
jl puts_print_int
|
||||
cmp rbx, r9
|
||||
jge puts_print_int
|
||||
; treat as string: (addr below len)
|
||||
mov rdx, rax ; len
|
||||
mov rsi, rbx ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
test rdx, rdx
|
||||
jz puts_str_newline_only
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
syscall
|
||||
puts_str_newline_only:
|
||||
mov byte [rel print_buf], 10
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
lea rsi, [rel print_buf]
|
||||
mov rdx, 1
|
||||
syscall
|
||||
ret
|
||||
|
||||
puts_print_int:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, rax
|
||||
mov r8, 0
|
||||
cmp rbx, 0
|
||||
jge puts_abs
|
||||
neg rbx
|
||||
mov r8, 1
|
||||
puts_abs:
|
||||
lea rsi, [rel print_buf_end]
|
||||
mov rcx, 0
|
||||
mov r10, 10
|
||||
cmp rbx, 0
|
||||
jne puts_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '0'
|
||||
inc rcx
|
||||
jmp puts_sign
|
||||
puts_digits:
|
||||
puts_loop:
|
||||
xor rdx, rdx
|
||||
mov rax, rbx
|
||||
div r10
|
||||
add dl, '0'
|
||||
dec rsi
|
||||
mov [rsi], dl
|
||||
inc rcx
|
||||
mov rbx, rax
|
||||
test rbx, rbx
|
||||
jne puts_loop
|
||||
puts_sign:
|
||||
cmp r8, 0
|
||||
je puts_finish_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '-'
|
||||
inc rcx
|
||||
puts_finish_digits:
|
||||
mov byte [rsi + rcx], 10
|
||||
inc rcx
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
mov rdx, rcx
|
||||
mov r9, rsi
|
||||
mov rsi, r9
|
||||
syscall
|
||||
ret
|
||||
word_print_int:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, rax
|
||||
mov r8, 0
|
||||
cmp rbx, 0
|
||||
jge .print_abs
|
||||
neg rbx
|
||||
mov r8, 1
|
||||
.print_abs:
|
||||
lea rsi, [rel print_buf_end]
|
||||
mov rcx, 0
|
||||
mov r10, 10
|
||||
cmp rbx, 0
|
||||
jne .print_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '0'
|
||||
inc rcx
|
||||
jmp .print_sign
|
||||
.print_digits:
|
||||
.print_loop:
|
||||
xor rdx, rdx
|
||||
mov rax, rbx
|
||||
div r10
|
||||
add dl, '0'
|
||||
dec rsi
|
||||
mov [rsi], dl
|
||||
inc rcx
|
||||
mov rbx, rax
|
||||
test rbx, rbx
|
||||
jne .print_loop
|
||||
.print_sign:
|
||||
cmp r8, 0
|
||||
je .print_finish
|
||||
dec rsi
|
||||
mov byte [rsi], '-'
|
||||
inc rcx
|
||||
.print_finish:
|
||||
mov byte [rsi + rcx], 10
|
||||
inc rcx
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
mov rdx, rcx
|
||||
mov r9, rsi
|
||||
mov rsi, r9
|
||||
syscall
|
||||
ret
|
||||
ret
|
||||
word_push_data_start:
|
||||
lea rax, [rel data_start]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_push_print_buf_addr:
|
||||
lea rax, [rel print_buf]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_dup:
|
||||
mov rax, [r12]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_write_buf:
|
||||
mov rdx, [r12] ; len
|
||||
mov rsi, [r12 + 8] ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, 1 ; fd = stdout
|
||||
syscall
|
||||
ret
|
||||
ret
|
||||
word_drop:
|
||||
add r12, 8
|
||||
ret
|
||||
word_over:
|
||||
mov rax, [r12 + 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_swap:
|
||||
mov rax, [r12]
|
||||
mov rbx, [r12 + 8]
|
||||
mov [r12], rbx
|
||||
mov [r12 + 8], rax
|
||||
ret
|
||||
word_mkstr:
|
||||
mov rax, [r12] ; ptr
|
||||
mov rbx, [r12 + 8] ; len
|
||||
mov [r12], rbx ; top = len
|
||||
mov [r12 + 8], rax ; next = ptr
|
||||
ret
|
||||
ret
|
||||
word_mkstr_copy:
|
||||
mov rdx, [r12] ; len
|
||||
mov rsi, [r12 + 8] ; addr (source)
|
||||
add r12, 16 ; pop len+addr
|
||||
|
||||
; compute cap = PRINT_BUF_BYTES - 1 (leave room for newline or NUL)
|
||||
lea rdi, [rel print_buf]
|
||||
mov rcx, 127 ; PRINT_BUF_BYTES-1 (PRINT_BUF_BYTES=128)
|
||||
cmp rdx, rcx
|
||||
cmova rdx, rcx ; rdx = min(len, cap)
|
||||
|
||||
; copy rdx bytes from rsi -> rdi using rep movsb
|
||||
test rdx, rdx
|
||||
jz .done_copy
|
||||
; save callee-saved r14, use it to hold base dest pointer
|
||||
push r14
|
||||
mov r14, rdi ; r14 = base dest (print_buf)
|
||||
mov rcx, rdx ; counter = copied length
|
||||
cld
|
||||
rep movsb
|
||||
mov rbx, r14 ; move saved base into rbx for return
|
||||
pop r14 ; restore original r14
|
||||
|
||||
.done_copy:
|
||||
; push copied length and pointer to print_buf (use saved rbx)
|
||||
sub r12, 8
|
||||
mov [r12], rdx ; len
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; addr -> print_buf base
|
||||
ret
|
||||
ret
|
||||
word_rot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rcx ; top = x1
|
||||
mov [r12 + 8], rax ; next = x3
|
||||
mov [r12 + 16], rbx ; third = x2
|
||||
ret
|
||||
word__2drot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rbx ; top = x2
|
||||
mov [r12 + 8], rcx ; next = x1
|
||||
mov [r12 + 16], rax ; third = x3
|
||||
ret
|
||||
word_nip:
|
||||
mov rax, [r12]
|
||||
add r12, 8 ; drop lower element
|
||||
mov [r12], rax ; keep original top
|
||||
ret
|
||||
word_tuck:
|
||||
mov rax, [r12] ; x2
|
||||
mov rbx, [r12 + 8] ; x1
|
||||
sub r12, 8 ; make room
|
||||
mov [r12], rax ; x2
|
||||
mov [r12 + 8], rbx ; x1
|
||||
mov [r12 + 16], rax ; x2
|
||||
ret
|
||||
word_2dup:
|
||||
mov rax, [r12] ; b
|
||||
mov rbx, [r12 + 8] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word_2drop:
|
||||
add r12, 16
|
||||
ret
|
||||
word_2swap:
|
||||
mov rax, [r12] ; d
|
||||
mov rbx, [r12 + 8] ; c
|
||||
mov rcx, [r12 + 16] ; b
|
||||
mov rdx, [r12 + 24] ; a
|
||||
mov [r12], rcx ; top = b
|
||||
mov [r12 + 8], rdx ; next = a
|
||||
mov [r12 + 16], rax ; third = d
|
||||
mov [r12 + 24], rbx ; fourth = c
|
||||
ret
|
||||
word_2over:
|
||||
mov rax, [r12 + 16] ; b
|
||||
mov rbx, [r12 + 24] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word__2b:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
add qword [r12], rax
|
||||
ret
|
||||
word__2d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub qword [r12], rax
|
||||
ret
|
||||
word__2a:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
imul qword [r12]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__2f:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__25:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rdx
|
||||
ret
|
||||
word__3d_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
sete bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__21_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setne bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setl bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setg bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setle bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setge bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__40:
|
||||
mov rax, [r12]
|
||||
mov rax, [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rax], rbx
|
||||
add r12, 8
|
||||
ret
|
||||
word_mmap:
|
||||
; Save rsp and align to 16 bytes for syscall ABI
|
||||
mov rax, rsp
|
||||
and rsp, -16
|
||||
mov rdi, [r12+40] ; addr
|
||||
mov rsi, [r12+32] ; length
|
||||
mov rdx, [r12+24] ; prot
|
||||
mov r10, [r12+16] ; flags
|
||||
mov r8, [r12+8] ; fd
|
||||
mov r9, [r12] ; offset
|
||||
add r12, 48 ; pop 6 args
|
||||
mov rax, 9 ; syscall: mmap
|
||||
syscall
|
||||
mov rsp, rax ; restore rsp
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push result
|
||||
ret
|
||||
ret
|
||||
word_munmap:
|
||||
mov rsi, [r12]
|
||||
add r12, 8
|
||||
mov rdi, [r12]
|
||||
mov rax, 11
|
||||
syscall
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_exit:
|
||||
mov rdi, [r12]
|
||||
add r12, 8
|
||||
mov rax, 60
|
||||
syscall
|
||||
ret
|
||||
word_and:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
and rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_or:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
or rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_not:
|
||||
mov rax, [r12]
|
||||
test rax, rax
|
||||
setz al
|
||||
movzx rax, al
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__3er:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub r13, 8
|
||||
mov [r13], rax
|
||||
ret
|
||||
word_r_3e:
|
||||
mov rax, [r13]
|
||||
add r13, 8
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rdrop:
|
||||
add r13, 8
|
||||
ret
|
||||
word_pick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rpick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r13 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_main:
|
||||
call word_push_print_buf_addr
|
||||
call word_print_int
|
||||
call word_push_data_start
|
||||
call word_print_int
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
ret
|
||||
section .data
|
||||
data_start:
|
||||
data_end:
|
||||
section .bss
|
||||
align 16
|
||||
dstack: resb DSTK_BYTES
|
||||
dstack_top:
|
||||
align 16
|
||||
rstack: resb RSTK_BYTES
|
||||
rstack_top:
|
||||
align 16
|
||||
print_buf: resb PRINT_BUF_BYTES
|
||||
print_buf_end:
|
||||
Binary file not shown.
596
build/hello.asm
596
build/hello.asm
@@ -1,596 +0,0 @@
|
||||
section .text
|
||||
%define DSTK_BYTES 65536
|
||||
%define RSTK_BYTES 65536
|
||||
%define PRINT_BUF_BYTES 128
|
||||
global _start
|
||||
_start:
|
||||
; initialize data/return stack pointers
|
||||
lea r12, [rel dstack_top]
|
||||
mov r15, r12
|
||||
lea r13, [rel rstack_top]
|
||||
call word_main
|
||||
mov rax, 0
|
||||
cmp r12, r15
|
||||
je .no_exit_value
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
.no_exit_value:
|
||||
mov rdi, rax
|
||||
mov rax, 60
|
||||
syscall
|
||||
word_c_40:
|
||||
mov rax, [r12]
|
||||
movzx rax, byte [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_c_21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rbx], al
|
||||
ret
|
||||
ret
|
||||
word_r_40:
|
||||
mov rax, [r13]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_dup:
|
||||
mov rax, [r12]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_drop:
|
||||
add r12, 8
|
||||
ret
|
||||
word_over:
|
||||
mov rax, [r12 + 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_swap:
|
||||
mov rax, [r12]
|
||||
mov rbx, [r12 + 8]
|
||||
mov [r12], rbx
|
||||
mov [r12 + 8], rax
|
||||
ret
|
||||
word_rot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rcx ; top = x1
|
||||
mov [r12 + 8], rax ; next = x3
|
||||
mov [r12 + 16], rbx ; third = x2
|
||||
ret
|
||||
word__2drot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rbx ; top = x2
|
||||
mov [r12 + 8], rcx ; next = x1
|
||||
mov [r12 + 16], rax ; third = x3
|
||||
ret
|
||||
word_nip:
|
||||
mov rax, [r12]
|
||||
add r12, 8 ; drop lower element
|
||||
mov [r12], rax ; keep original top
|
||||
ret
|
||||
word_tuck:
|
||||
mov rax, [r12] ; x2
|
||||
mov rbx, [r12 + 8] ; x1
|
||||
sub r12, 8 ; make room
|
||||
mov [r12], rax ; x2
|
||||
mov [r12 + 8], rbx ; x1
|
||||
mov [r12 + 16], rax ; x2
|
||||
ret
|
||||
word_2dup:
|
||||
mov rax, [r12] ; b
|
||||
mov rbx, [r12 + 8] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word_2drop:
|
||||
add r12, 16
|
||||
ret
|
||||
word_2swap:
|
||||
mov rax, [r12] ; d
|
||||
mov rbx, [r12 + 8] ; c
|
||||
mov rcx, [r12 + 16] ; b
|
||||
mov rdx, [r12 + 24] ; a
|
||||
mov [r12], rcx ; top = b
|
||||
mov [r12 + 8], rdx ; next = a
|
||||
mov [r12 + 16], rax ; third = d
|
||||
mov [r12 + 24], rbx ; fourth = c
|
||||
ret
|
||||
word_2over:
|
||||
mov rax, [r12 + 16] ; b
|
||||
mov rbx, [r12 + 24] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word__2b:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
add qword [r12], rax
|
||||
ret
|
||||
word__2d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub qword [r12], rax
|
||||
ret
|
||||
word__2a:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
imul qword [r12]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__2f:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__25:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rdx
|
||||
ret
|
||||
word__3d_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
sete bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__21_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setne bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setl bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setg bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setle bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setge bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__40:
|
||||
mov rax, [r12]
|
||||
mov rax, [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rax], rbx
|
||||
add r12, 8
|
||||
ret
|
||||
word_mmap:
|
||||
; Save rsp and align to 16 bytes for syscall ABI
|
||||
mov rax, rsp
|
||||
and rsp, -16
|
||||
mov rdi, [r12+40] ; addr
|
||||
mov rsi, [r12+32] ; length
|
||||
mov rdx, [r12+24] ; prot
|
||||
mov r10, [r12+16] ; flags
|
||||
mov r8, [r12+8] ; fd
|
||||
mov r9, [r12] ; offset
|
||||
add r12, 48 ; pop 6 args
|
||||
mov rax, 9 ; syscall: mmap
|
||||
syscall
|
||||
mov rsp, rax ; restore rsp
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push result
|
||||
ret
|
||||
ret
|
||||
word_munmap:
|
||||
mov rsi, [r12]
|
||||
add r12, 8
|
||||
mov rdi, [r12]
|
||||
mov rax, 11
|
||||
syscall
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_exit:
|
||||
mov rdi, [r12]
|
||||
add r12, 8
|
||||
mov rax, 60
|
||||
syscall
|
||||
ret
|
||||
word_and:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
and rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_or:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
or rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_not:
|
||||
mov rax, [r12]
|
||||
test rax, rax
|
||||
setz al
|
||||
movzx rax, al
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__3er:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub r13, 8
|
||||
mov [r13], rax
|
||||
ret
|
||||
word_r_3e:
|
||||
mov rax, [r13]
|
||||
add r13, 8
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rdrop:
|
||||
add r13, 8
|
||||
ret
|
||||
word_pick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rpick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r13 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_read_file:
|
||||
; stack: path_ptr (top), path_len (next)
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
add r12, 16 ; pop args
|
||||
|
||||
; open(path_ptr, O_RDONLY=0, mode=0)
|
||||
mov rax, 2 ; syscall: open
|
||||
mov rdi, rsi ; filename
|
||||
xor rsi, rsi ; flags = O_RDONLY
|
||||
xor rdx, rdx ; mode = 0
|
||||
syscall
|
||||
mov r10, rax ; save open() result
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r8, rax ; fd
|
||||
|
||||
; use lseek to determine file size: lseek(fd, 0, SEEK_END)
|
||||
mov rax, 8 ; syscall: lseek
|
||||
mov rdi, r8 ; fd
|
||||
xor rsi, rsi ; offset = 0
|
||||
mov rdx, 2 ; SEEK_END
|
||||
syscall
|
||||
mov r11, rax ; save lseek() result
|
||||
cmp rax, 0
|
||||
jl .close_fail_lseek
|
||||
mov rsi, rax ; length = size
|
||||
|
||||
; mmap(NULL, size, PROT_READ=1, MAP_PRIVATE=2, fd, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
; rsi already holds length
|
||||
mov rdx, 1 ; PROT_READ
|
||||
mov r10, 2 ; MAP_PRIVATE
|
||||
mov r8, r8 ; fd
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
mov rbx, rax ; addr
|
||||
mov r12, r12 ; (no-op, for debug)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r8 ; fd
|
||||
syscall
|
||||
cmp rbx, -4095
|
||||
jae .fail_mmap
|
||||
sub r12, 16
|
||||
mov [r12], rsi ; len (rsi held length across syscall)
|
||||
mov [r12 + 8], rbx ; addr
|
||||
ret
|
||||
|
||||
.close_fail_lseek:
|
||||
mov rax, 3
|
||||
mov rdi, r8
|
||||
syscall
|
||||
mov rax, r11 ; return lseek() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -1
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
mov rax, r10 ; return open() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -2
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
mov rax, -1 ; return mmap() error
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -3
|
||||
ret
|
||||
ret
|
||||
word_write_file:
|
||||
; stack: path_ptr (top), path_len, buf_ptr, buf_len
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
mov r15, [r12 + 16] ; buf_ptr (save in callee-saved r15)
|
||||
mov r13, [r12 + 24] ; buf_len (save in callee-saved r13)
|
||||
add r12, 32 ; pop 4 args (we saved buf info)
|
||||
|
||||
; open(path_ptr, O_WRONLY|O_CREAT|O_TRUNC, 0666)
|
||||
mov rdi, rsi ; filename
|
||||
mov rsi, 577 ; flags = O_WRONLY|O_CREAT|O_TRUNC
|
||||
mov rdx, 438 ; mode = 0o666
|
||||
mov rax, 2 ; syscall: open
|
||||
syscall
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r9, rax ; save fd
|
||||
|
||||
; write(fd, buf_ptr, buf_len) -- use preserved r15/r13 which survive syscalls
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, r9 ; fd
|
||||
mov rsi, r15 ; buf_ptr
|
||||
mov rdx, r13 ; buf_len
|
||||
syscall
|
||||
mov r10, rax ; save write result
|
||||
cmp r10, 0
|
||||
jl .fail_write
|
||||
|
||||
; close(fd)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r9
|
||||
syscall
|
||||
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_write:
|
||||
mov rax, 3
|
||||
mov rdi, r9
|
||||
syscall
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_read_stdin:
|
||||
; stack: max_len
|
||||
mov r14, [r12] ; max_len
|
||||
add r12, 8 ; pop max_len
|
||||
|
||||
; mmap(NULL, max_len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
mov rsi, r14 ; length
|
||||
mov rdx, 3 ; PROT_READ|PROT_WRITE
|
||||
mov r10, 34 ; MAP_PRIVATE|MAP_ANONYMOUS
|
||||
mov r8, -1 ; fd = -1
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
cmp rax, -4095
|
||||
jae .fail_mmap
|
||||
mov rbx, rax ; buffer addr
|
||||
xor r9, r9 ; bytes_read = 0
|
||||
|
||||
.read_loop:
|
||||
mov rax, 0 ; syscall: read
|
||||
mov rdi, 0 ; fd = stdin
|
||||
lea rsi, [rbx + r9] ; buf + offset
|
||||
mov rdx, r14
|
||||
sub rdx, r9 ; remaining = max_len - bytes_read
|
||||
syscall
|
||||
cmp rax, 0
|
||||
je .done_read
|
||||
js .read_error
|
||||
add r9, rax
|
||||
jl .read_loop
|
||||
|
||||
.done_read:
|
||||
; push len (rcx) then addr (rbx)
|
||||
cmp r9, r14
|
||||
je .done_no_null
|
||||
mov byte [rbx + r9], 0
|
||||
.done_no_null:
|
||||
sub r12, 16
|
||||
mov [r12], r9
|
||||
mov [r12 + 8], rbx
|
||||
ret
|
||||
|
||||
.read_error:
|
||||
; return negative errno in rax, addr = 0
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], 0
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
sub r12, 16
|
||||
mov qword [r12], -1
|
||||
mov qword [r12 + 8], 0
|
||||
ret
|
||||
ret
|
||||
word_puts:
|
||||
; detects string if top is len>=0 and next is a pointer in [data_start, data_end]
|
||||
mov rax, [r12] ; len or int value
|
||||
mov rbx, [r12 + 8] ; possible address
|
||||
cmp rax, 0
|
||||
jl puts_print_int
|
||||
lea r8, [rel data_start]
|
||||
lea r9, [rel data_end]
|
||||
cmp rbx, r8
|
||||
jl puts_print_int
|
||||
cmp rbx, r9
|
||||
jge puts_print_int
|
||||
; treat as string: (addr below len)
|
||||
mov rdx, rax ; len
|
||||
mov rsi, rbx ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
test rdx, rdx
|
||||
jz puts_str_newline_only
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
syscall
|
||||
puts_str_newline_only:
|
||||
mov byte [rel print_buf], 10
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
lea rsi, [rel print_buf]
|
||||
mov rdx, 1
|
||||
syscall
|
||||
ret
|
||||
puts_print_int:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, rax
|
||||
mov r8, 0
|
||||
cmp rbx, 0
|
||||
jge puts_abs
|
||||
neg rbx
|
||||
mov r8, 1
|
||||
puts_abs:
|
||||
lea rsi, [rel print_buf_end]
|
||||
mov rcx, 0
|
||||
mov r10, 10
|
||||
cmp rbx, 0
|
||||
jne puts_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '0'
|
||||
inc rcx
|
||||
jmp puts_sign
|
||||
puts_digits:
|
||||
puts_loop:
|
||||
xor rdx, rdx
|
||||
mov rax, rbx
|
||||
div r10
|
||||
add dl, '0'
|
||||
dec rsi
|
||||
mov [rsi], dl
|
||||
inc rcx
|
||||
mov rbx, rax
|
||||
test rbx, rbx
|
||||
jne puts_loop
|
||||
puts_sign:
|
||||
cmp r8, 0
|
||||
je puts_finish_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '-'
|
||||
inc rcx
|
||||
puts_finish_digits:
|
||||
mov byte [rsi + rcx], 10
|
||||
inc rcx
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
mov rdx, rcx
|
||||
mov r9, rsi
|
||||
mov rsi, r9
|
||||
syscall
|
||||
ret
|
||||
word_write_buf:
|
||||
mov rdx, [r12] ; len
|
||||
mov rsi, [r12 + 8] ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, 1 ; fd = stdout
|
||||
syscall
|
||||
ret
|
||||
ret
|
||||
word_main:
|
||||
; push str_0
|
||||
sub r12, 8
|
||||
mov qword [r12], str_0
|
||||
; push 11
|
||||
sub r12, 8
|
||||
mov qword [r12], 11
|
||||
call word_puts
|
||||
ret
|
||||
section .data
|
||||
data_start:
|
||||
str_0: db 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 0
|
||||
str_0_len equ 11
|
||||
data_end:
|
||||
section .bss
|
||||
align 16
|
||||
dstack: resb DSTK_BYTES
|
||||
dstack_top:
|
||||
align 16
|
||||
rstack: resb RSTK_BYTES
|
||||
rstack_top:
|
||||
align 16
|
||||
print_buf: resb PRINT_BUF_BYTES
|
||||
print_buf_end:
|
||||
BIN
build/hello.o
BIN
build/hello.o
Binary file not shown.
@@ -1,630 +0,0 @@
|
||||
section .text
|
||||
%define DSTK_BYTES 65536
|
||||
%define RSTK_BYTES 65536
|
||||
%define PRINT_BUF_BYTES 128
|
||||
global _start
|
||||
_start:
|
||||
; initialize data/return stack pointers
|
||||
lea r12, [rel dstack_top]
|
||||
mov r15, r12
|
||||
lea r13, [rel rstack_top]
|
||||
call word_main
|
||||
mov rax, 0
|
||||
cmp r12, r15
|
||||
je .no_exit_value
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
.no_exit_value:
|
||||
mov rdi, rax
|
||||
mov rax, 60
|
||||
syscall
|
||||
word_c_40:
|
||||
mov rax, [r12]
|
||||
movzx rax, byte [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_c_21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rbx], al
|
||||
ret
|
||||
ret
|
||||
word_r_40:
|
||||
mov rax, [r13]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_dup:
|
||||
mov rax, [r12]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_drop:
|
||||
add r12, 8
|
||||
ret
|
||||
word_over:
|
||||
mov rax, [r12 + 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_swap:
|
||||
mov rax, [r12]
|
||||
mov rbx, [r12 + 8]
|
||||
mov [r12], rbx
|
||||
mov [r12 + 8], rax
|
||||
ret
|
||||
word_rot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rcx ; top = x1
|
||||
mov [r12 + 8], rax ; next = x3
|
||||
mov [r12 + 16], rbx ; third = x2
|
||||
ret
|
||||
word__2drot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rbx ; top = x2
|
||||
mov [r12 + 8], rcx ; next = x1
|
||||
mov [r12 + 16], rax ; third = x3
|
||||
ret
|
||||
word_nip:
|
||||
mov rax, [r12]
|
||||
add r12, 8 ; drop lower element
|
||||
mov [r12], rax ; keep original top
|
||||
ret
|
||||
word_tuck:
|
||||
mov rax, [r12] ; x2
|
||||
mov rbx, [r12 + 8] ; x1
|
||||
sub r12, 8 ; make room
|
||||
mov [r12], rax ; x2
|
||||
mov [r12 + 8], rbx ; x1
|
||||
mov [r12 + 16], rax ; x2
|
||||
ret
|
||||
word_2dup:
|
||||
mov rax, [r12] ; b
|
||||
mov rbx, [r12 + 8] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word_2drop:
|
||||
add r12, 16
|
||||
ret
|
||||
word_2swap:
|
||||
mov rax, [r12] ; d
|
||||
mov rbx, [r12 + 8] ; c
|
||||
mov rcx, [r12 + 16] ; b
|
||||
mov rdx, [r12 + 24] ; a
|
||||
mov [r12], rcx ; top = b
|
||||
mov [r12 + 8], rdx ; next = a
|
||||
mov [r12 + 16], rax ; third = d
|
||||
mov [r12 + 24], rbx ; fourth = c
|
||||
ret
|
||||
word_2over:
|
||||
mov rax, [r12 + 16] ; b
|
||||
mov rbx, [r12 + 24] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word__2b:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
add qword [r12], rax
|
||||
ret
|
||||
word__2d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub qword [r12], rax
|
||||
ret
|
||||
word__2a:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
imul qword [r12]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__2f:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__25:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rdx
|
||||
ret
|
||||
word__3d_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
sete bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__21_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setne bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setl bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setg bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setle bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setge bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__40:
|
||||
mov rax, [r12]
|
||||
mov rax, [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rax], rbx
|
||||
add r12, 8
|
||||
ret
|
||||
word_mmap:
|
||||
; Save rsp and align to 16 bytes for syscall ABI
|
||||
mov rax, rsp
|
||||
and rsp, -16
|
||||
mov rdi, [r12+40] ; addr
|
||||
mov rsi, [r12+32] ; length
|
||||
mov rdx, [r12+24] ; prot
|
||||
mov r10, [r12+16] ; flags
|
||||
mov r8, [r12+8] ; fd
|
||||
mov r9, [r12] ; offset
|
||||
add r12, 48 ; pop 6 args
|
||||
mov rax, 9 ; syscall: mmap
|
||||
syscall
|
||||
mov rsp, rax ; restore rsp
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push result
|
||||
ret
|
||||
ret
|
||||
word_munmap:
|
||||
mov rsi, [r12]
|
||||
add r12, 8
|
||||
mov rdi, [r12]
|
||||
mov rax, 11
|
||||
syscall
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_exit:
|
||||
mov rdi, [r12]
|
||||
add r12, 8
|
||||
mov rax, 60
|
||||
syscall
|
||||
ret
|
||||
word_and:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
and rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_or:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
or rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_not:
|
||||
mov rax, [r12]
|
||||
test rax, rax
|
||||
setz al
|
||||
movzx rax, al
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__3er:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub r13, 8
|
||||
mov [r13], rax
|
||||
ret
|
||||
word_r_3e:
|
||||
mov rax, [r13]
|
||||
add r13, 8
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rdrop:
|
||||
add r13, 8
|
||||
ret
|
||||
word_pick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rpick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r13 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_read_file:
|
||||
; stack: path_ptr (top), path_len (next)
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
add r12, 16 ; pop args
|
||||
|
||||
; open(path_ptr, O_RDONLY=0, mode=0)
|
||||
mov rax, 2 ; syscall: open
|
||||
mov rdi, rsi ; filename
|
||||
xor rsi, rsi ; flags = O_RDONLY
|
||||
xor rdx, rdx ; mode = 0
|
||||
syscall
|
||||
mov r10, rax ; save open() result
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r8, rax ; fd
|
||||
|
||||
; use lseek to determine file size: lseek(fd, 0, SEEK_END)
|
||||
mov rax, 8 ; syscall: lseek
|
||||
mov rdi, r8 ; fd
|
||||
xor rsi, rsi ; offset = 0
|
||||
mov rdx, 2 ; SEEK_END
|
||||
syscall
|
||||
mov r11, rax ; save lseek() result
|
||||
cmp rax, 0
|
||||
jl .close_fail_lseek
|
||||
mov rsi, rax ; length = size
|
||||
|
||||
; mmap(NULL, size, PROT_READ=1, MAP_PRIVATE=2, fd, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
; rsi already holds length
|
||||
mov rdx, 1 ; PROT_READ
|
||||
mov r10, 2 ; MAP_PRIVATE
|
||||
mov r8, r8 ; fd
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
mov rbx, rax ; addr
|
||||
mov r12, r12 ; (no-op, for debug)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r8 ; fd
|
||||
syscall
|
||||
cmp rbx, -4095
|
||||
jae .fail_mmap
|
||||
sub r12, 16
|
||||
mov [r12], rsi ; len (rsi held length across syscall)
|
||||
mov [r12 + 8], rbx ; addr
|
||||
ret
|
||||
|
||||
.close_fail_lseek:
|
||||
mov rax, 3
|
||||
mov rdi, r8
|
||||
syscall
|
||||
mov rax, r11 ; return lseek() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -1
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
mov rax, r10 ; return open() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -2
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
mov rax, -1 ; return mmap() error
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -3
|
||||
ret
|
||||
ret
|
||||
word_write_file:
|
||||
; stack: path_ptr (top), path_len, buf_ptr, buf_len
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
mov r15, [r12 + 16] ; buf_ptr (save in callee-saved r15)
|
||||
mov r13, [r12 + 24] ; buf_len (save in callee-saved r13)
|
||||
add r12, 32 ; pop 4 args (we saved buf info)
|
||||
|
||||
; open(path_ptr, O_WRONLY|O_CREAT|O_TRUNC, 0666)
|
||||
mov rdi, rsi ; filename
|
||||
mov rsi, 577 ; flags = O_WRONLY|O_CREAT|O_TRUNC
|
||||
mov rdx, 438 ; mode = 0o666
|
||||
mov rax, 2 ; syscall: open
|
||||
syscall
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r9, rax ; save fd
|
||||
|
||||
; write(fd, buf_ptr, buf_len) -- use preserved r15/r13 which survive syscalls
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, r9 ; fd
|
||||
mov rsi, r15 ; buf_ptr
|
||||
mov rdx, r13 ; buf_len
|
||||
syscall
|
||||
mov r10, rax ; save write result
|
||||
cmp r10, 0
|
||||
jl .fail_write
|
||||
|
||||
; close(fd)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r9
|
||||
syscall
|
||||
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_write:
|
||||
mov rax, 3
|
||||
mov rdi, r9
|
||||
syscall
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_read_stdin:
|
||||
; stack: max_len
|
||||
mov r14, [r12] ; max_len
|
||||
add r12, 8 ; pop max_len
|
||||
|
||||
; mmap(NULL, max_len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
mov rsi, r14 ; length
|
||||
mov rdx, 3 ; PROT_READ|PROT_WRITE
|
||||
mov r10, 34 ; MAP_PRIVATE|MAP_ANONYMOUS
|
||||
mov r8, -1 ; fd = -1
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
cmp rax, -4095
|
||||
jae .fail_mmap
|
||||
mov rbx, rax ; buffer addr
|
||||
xor r9, r9 ; bytes_read = 0
|
||||
|
||||
.read_loop:
|
||||
mov rax, 0 ; syscall: read
|
||||
mov rdi, 0 ; fd = stdin
|
||||
lea rsi, [rbx + r9] ; buf + offset
|
||||
mov rdx, r14
|
||||
sub rdx, r9 ; remaining = max_len - bytes_read
|
||||
syscall
|
||||
cmp rax, 0
|
||||
je .done_read
|
||||
js .read_error
|
||||
add r9, rax
|
||||
jl .read_loop
|
||||
|
||||
.done_read:
|
||||
; push len (rcx) then addr (rbx)
|
||||
cmp r9, r14
|
||||
je .done_no_null
|
||||
mov byte [rbx + r9], 0
|
||||
.done_no_null:
|
||||
sub r12, 16
|
||||
mov [r12], r9
|
||||
mov [r12 + 8], rbx
|
||||
ret
|
||||
|
||||
.read_error:
|
||||
; return negative errno in rax, addr = 0
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], 0
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
sub r12, 16
|
||||
mov qword [r12], -1
|
||||
mov qword [r12 + 8], 0
|
||||
ret
|
||||
ret
|
||||
word_puts:
|
||||
; detects string if top is len>=0 and next is a pointer in [data_start, data_end]
|
||||
mov rax, [r12] ; len or int value
|
||||
mov rbx, [r12 + 8] ; possible address
|
||||
cmp rax, 0
|
||||
jl puts_print_int
|
||||
lea r8, [rel data_start]
|
||||
lea r9, [rel data_end]
|
||||
cmp rbx, r8
|
||||
jl puts_print_int
|
||||
cmp rbx, r9
|
||||
jge puts_print_int
|
||||
; treat as string: (addr below len)
|
||||
mov rdx, rax ; len
|
||||
mov rsi, rbx ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
test rdx, rdx
|
||||
jz puts_str_newline_only
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
syscall
|
||||
puts_str_newline_only:
|
||||
mov byte [rel print_buf], 10
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
lea rsi, [rel print_buf]
|
||||
mov rdx, 1
|
||||
syscall
|
||||
ret
|
||||
puts_print_int:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, rax
|
||||
mov r8, 0
|
||||
cmp rbx, 0
|
||||
jge puts_abs
|
||||
neg rbx
|
||||
mov r8, 1
|
||||
puts_abs:
|
||||
lea rsi, [rel print_buf_end]
|
||||
mov rcx, 0
|
||||
mov r10, 10
|
||||
cmp rbx, 0
|
||||
jne puts_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '0'
|
||||
inc rcx
|
||||
jmp puts_sign
|
||||
puts_digits:
|
||||
puts_loop:
|
||||
xor rdx, rdx
|
||||
mov rax, rbx
|
||||
div r10
|
||||
add dl, '0'
|
||||
dec rsi
|
||||
mov [rsi], dl
|
||||
inc rcx
|
||||
mov rbx, rax
|
||||
test rbx, rbx
|
||||
jne puts_loop
|
||||
puts_sign:
|
||||
cmp r8, 0
|
||||
je puts_finish_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '-'
|
||||
inc rcx
|
||||
puts_finish_digits:
|
||||
mov byte [rsi + rcx], 10
|
||||
inc rcx
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
mov rdx, rcx
|
||||
mov r9, rsi
|
||||
mov rsi, r9
|
||||
syscall
|
||||
ret
|
||||
word_write_buf:
|
||||
mov rdx, [r12] ; len
|
||||
mov rsi, [r12 + 8] ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, 1 ; fd = stdout
|
||||
syscall
|
||||
ret
|
||||
ret
|
||||
word_main:
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
cmp rax, 0
|
||||
jle L_for_end_1
|
||||
sub r13, 8
|
||||
mov [r13], rax
|
||||
L_for_loop_0:
|
||||
; push 1
|
||||
sub r12, 8
|
||||
mov qword [r12], 1
|
||||
call word__2b
|
||||
mov rax, [r13]
|
||||
dec rax
|
||||
mov [r13], rax
|
||||
jg L_for_loop_0
|
||||
add r13, 8
|
||||
L_for_end_1:
|
||||
call word_puts
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
call word__3d_3d
|
||||
call word_puts
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
; push 4
|
||||
sub r12, 8
|
||||
mov qword [r12], 4
|
||||
call word__3d_3d
|
||||
call word_puts
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
ret
|
||||
section .data
|
||||
data_start:
|
||||
data_end:
|
||||
section .bss
|
||||
align 16
|
||||
dstack: resb DSTK_BYTES
|
||||
dstack_top:
|
||||
align 16
|
||||
rstack: resb RSTK_BYTES
|
||||
rstack_top:
|
||||
align 16
|
||||
print_buf: resb PRINT_BUF_BYTES
|
||||
print_buf_end:
|
||||
Binary file not shown.
621
build/main.asm
621
build/main.asm
@@ -1,621 +0,0 @@
|
||||
section .text
|
||||
%define DSTK_BYTES 65536
|
||||
%define RSTK_BYTES 65536
|
||||
%define PRINT_BUF_BYTES 128
|
||||
global _start
|
||||
_start:
|
||||
; initialize data/return stack pointers
|
||||
lea r12, [rel dstack_top]
|
||||
mov r15, r12
|
||||
lea r13, [rel rstack_top]
|
||||
call word_main
|
||||
mov rax, 0
|
||||
cmp r12, r15
|
||||
je .no_exit_value
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
.no_exit_value:
|
||||
mov rdi, rax
|
||||
mov rax, 60
|
||||
syscall
|
||||
word_c_40:
|
||||
mov rax, [r12]
|
||||
movzx rax, byte [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_c_21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rbx], al
|
||||
ret
|
||||
ret
|
||||
word_r_40:
|
||||
mov rax, [r13]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_dup:
|
||||
mov rax, [r12]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_drop:
|
||||
add r12, 8
|
||||
ret
|
||||
word_over:
|
||||
mov rax, [r12 + 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_swap:
|
||||
mov rax, [r12]
|
||||
mov rbx, [r12 + 8]
|
||||
mov [r12], rbx
|
||||
mov [r12 + 8], rax
|
||||
ret
|
||||
word_rot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rcx ; top = x1
|
||||
mov [r12 + 8], rax ; next = x3
|
||||
mov [r12 + 16], rbx ; third = x2
|
||||
ret
|
||||
word__2drot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rbx ; top = x2
|
||||
mov [r12 + 8], rcx ; next = x1
|
||||
mov [r12 + 16], rax ; third = x3
|
||||
ret
|
||||
word_nip:
|
||||
mov rax, [r12]
|
||||
add r12, 8 ; drop lower element
|
||||
mov [r12], rax ; keep original top
|
||||
ret
|
||||
word_tuck:
|
||||
mov rax, [r12] ; x2
|
||||
mov rbx, [r12 + 8] ; x1
|
||||
sub r12, 8 ; make room
|
||||
mov [r12], rax ; x2
|
||||
mov [r12 + 8], rbx ; x1
|
||||
mov [r12 + 16], rax ; x2
|
||||
ret
|
||||
word_2dup:
|
||||
mov rax, [r12] ; b
|
||||
mov rbx, [r12 + 8] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word_2drop:
|
||||
add r12, 16
|
||||
ret
|
||||
word_2swap:
|
||||
mov rax, [r12] ; d
|
||||
mov rbx, [r12 + 8] ; c
|
||||
mov rcx, [r12 + 16] ; b
|
||||
mov rdx, [r12 + 24] ; a
|
||||
mov [r12], rcx ; top = b
|
||||
mov [r12 + 8], rdx ; next = a
|
||||
mov [r12 + 16], rax ; third = d
|
||||
mov [r12 + 24], rbx ; fourth = c
|
||||
ret
|
||||
word_2over:
|
||||
mov rax, [r12 + 16] ; b
|
||||
mov rbx, [r12 + 24] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word__2b:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
add qword [r12], rax
|
||||
ret
|
||||
word__2d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub qword [r12], rax
|
||||
ret
|
||||
word__2a:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
imul qword [r12]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__2f:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__25:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rdx
|
||||
ret
|
||||
word__3d_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
sete bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__21_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setne bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setl bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setg bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setle bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setge bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__40:
|
||||
mov rax, [r12]
|
||||
mov rax, [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rax], rbx
|
||||
add r12, 8
|
||||
ret
|
||||
word_mmap:
|
||||
; Save rsp and align to 16 bytes for syscall ABI
|
||||
mov rax, rsp
|
||||
and rsp, -16
|
||||
mov rdi, [r12+40] ; addr
|
||||
mov rsi, [r12+32] ; length
|
||||
mov rdx, [r12+24] ; prot
|
||||
mov r10, [r12+16] ; flags
|
||||
mov r8, [r12+8] ; fd
|
||||
mov r9, [r12] ; offset
|
||||
add r12, 48 ; pop 6 args
|
||||
mov rax, 9 ; syscall: mmap
|
||||
syscall
|
||||
mov rsp, rax ; restore rsp
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push result
|
||||
ret
|
||||
ret
|
||||
word_munmap:
|
||||
mov rsi, [r12]
|
||||
add r12, 8
|
||||
mov rdi, [r12]
|
||||
mov rax, 11
|
||||
syscall
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_exit:
|
||||
mov rdi, [r12]
|
||||
add r12, 8
|
||||
mov rax, 60
|
||||
syscall
|
||||
ret
|
||||
word_and:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
and rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_or:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
or rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_not:
|
||||
mov rax, [r12]
|
||||
test rax, rax
|
||||
setz al
|
||||
movzx rax, al
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__3er:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub r13, 8
|
||||
mov [r13], rax
|
||||
ret
|
||||
word_r_3e:
|
||||
mov rax, [r13]
|
||||
add r13, 8
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rdrop:
|
||||
add r13, 8
|
||||
ret
|
||||
word_pick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rpick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r13 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_read_file:
|
||||
; stack: path_ptr (top), path_len (next)
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
add r12, 16 ; pop args
|
||||
|
||||
; open(path_ptr, O_RDONLY=0, mode=0)
|
||||
mov rax, 2 ; syscall: open
|
||||
mov rdi, rsi ; filename
|
||||
xor rsi, rsi ; flags = O_RDONLY
|
||||
xor rdx, rdx ; mode = 0
|
||||
syscall
|
||||
mov r10, rax ; save open() result
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r8, rax ; fd
|
||||
|
||||
; use lseek to determine file size: lseek(fd, 0, SEEK_END)
|
||||
mov rax, 8 ; syscall: lseek
|
||||
mov rdi, r8 ; fd
|
||||
xor rsi, rsi ; offset = 0
|
||||
mov rdx, 2 ; SEEK_END
|
||||
syscall
|
||||
mov r11, rax ; save lseek() result
|
||||
cmp rax, 0
|
||||
jl .close_fail_lseek
|
||||
mov rsi, rax ; length = size
|
||||
|
||||
; mmap(NULL, size, PROT_READ=1, MAP_PRIVATE=2, fd, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
; rsi already holds length
|
||||
mov rdx, 1 ; PROT_READ
|
||||
mov r10, 2 ; MAP_PRIVATE
|
||||
mov r8, r8 ; fd
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
mov rbx, rax ; addr
|
||||
mov r12, r12 ; (no-op, for debug)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r8 ; fd
|
||||
syscall
|
||||
cmp rbx, -4095
|
||||
jae .fail_mmap
|
||||
sub r12, 16
|
||||
mov [r12], rsi ; len (rsi held length across syscall)
|
||||
mov [r12 + 8], rbx ; addr
|
||||
ret
|
||||
|
||||
.close_fail_lseek:
|
||||
mov rax, 3
|
||||
mov rdi, r8
|
||||
syscall
|
||||
mov rax, r11 ; return lseek() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -1
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
mov rax, r10 ; return open() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -2
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
mov rax, -1 ; return mmap() error
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -3
|
||||
ret
|
||||
ret
|
||||
word_write_file:
|
||||
; stack: path_ptr (top), path_len, buf_ptr, buf_len
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
mov r15, [r12 + 16] ; buf_ptr (save in callee-saved r15)
|
||||
mov r13, [r12 + 24] ; buf_len (save in callee-saved r13)
|
||||
add r12, 32 ; pop 4 args (we saved buf info)
|
||||
|
||||
; open(path_ptr, O_WRONLY|O_CREAT|O_TRUNC, 0666)
|
||||
mov rdi, rsi ; filename
|
||||
mov rsi, 577 ; flags = O_WRONLY|O_CREAT|O_TRUNC
|
||||
mov rdx, 438 ; mode = 0o666
|
||||
mov rax, 2 ; syscall: open
|
||||
syscall
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r9, rax ; save fd
|
||||
|
||||
; write(fd, buf_ptr, buf_len) -- use preserved r15/r13 which survive syscalls
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, r9 ; fd
|
||||
mov rsi, r15 ; buf_ptr
|
||||
mov rdx, r13 ; buf_len
|
||||
syscall
|
||||
mov r10, rax ; save write result
|
||||
cmp r10, 0
|
||||
jl .fail_write
|
||||
|
||||
; close(fd)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r9
|
||||
syscall
|
||||
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_write:
|
||||
mov rax, 3
|
||||
mov rdi, r9
|
||||
syscall
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_read_stdin:
|
||||
; stack: max_len
|
||||
mov r14, [r12] ; max_len
|
||||
add r12, 8 ; pop max_len
|
||||
|
||||
; mmap(NULL, max_len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
mov rsi, r14 ; length
|
||||
mov rdx, 3 ; PROT_READ|PROT_WRITE
|
||||
mov r10, 34 ; MAP_PRIVATE|MAP_ANONYMOUS
|
||||
mov r8, -1 ; fd = -1
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
cmp rax, -4095
|
||||
jae .fail_mmap
|
||||
mov rbx, rax ; buffer addr
|
||||
xor r9, r9 ; bytes_read = 0
|
||||
|
||||
.read_loop:
|
||||
mov rax, 0 ; syscall: read
|
||||
mov rdi, 0 ; fd = stdin
|
||||
lea rsi, [rbx + r9] ; buf + offset
|
||||
mov rdx, r14
|
||||
sub rdx, r9 ; remaining = max_len - bytes_read
|
||||
syscall
|
||||
cmp rax, 0
|
||||
je .done_read
|
||||
js .read_error
|
||||
add r9, rax
|
||||
jl .read_loop
|
||||
|
||||
.done_read:
|
||||
; push len (rcx) then addr (rbx)
|
||||
cmp r9, r14
|
||||
je .done_no_null
|
||||
mov byte [rbx + r9], 0
|
||||
.done_no_null:
|
||||
sub r12, 16
|
||||
mov [r12], r9
|
||||
mov [r12 + 8], rbx
|
||||
ret
|
||||
|
||||
.read_error:
|
||||
; return negative errno in rax, addr = 0
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], 0
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
sub r12, 16
|
||||
mov qword [r12], -1
|
||||
mov qword [r12 + 8], 0
|
||||
ret
|
||||
ret
|
||||
word_puts:
|
||||
; detects string if top is len>=0 and next is a pointer in [data_start, data_end]
|
||||
mov rax, [r12] ; len or int value
|
||||
mov rbx, [r12 + 8] ; possible address
|
||||
cmp rax, 0
|
||||
jl puts_print_int
|
||||
lea r8, [rel data_start]
|
||||
lea r9, [rel data_end]
|
||||
cmp rbx, r8
|
||||
jl puts_print_int
|
||||
cmp rbx, r9
|
||||
jge puts_print_int
|
||||
; treat as string: (addr below len)
|
||||
mov rdx, rax ; len
|
||||
mov rsi, rbx ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
test rdx, rdx
|
||||
jz puts_str_newline_only
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
syscall
|
||||
puts_str_newline_only:
|
||||
mov byte [rel print_buf], 10
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
lea rsi, [rel print_buf]
|
||||
mov rdx, 1
|
||||
syscall
|
||||
ret
|
||||
puts_print_int:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, rax
|
||||
mov r8, 0
|
||||
cmp rbx, 0
|
||||
jge puts_abs
|
||||
neg rbx
|
||||
mov r8, 1
|
||||
puts_abs:
|
||||
lea rsi, [rel print_buf_end]
|
||||
mov rcx, 0
|
||||
mov r10, 10
|
||||
cmp rbx, 0
|
||||
jne puts_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '0'
|
||||
inc rcx
|
||||
jmp puts_sign
|
||||
puts_digits:
|
||||
puts_loop:
|
||||
xor rdx, rdx
|
||||
mov rax, rbx
|
||||
div r10
|
||||
add dl, '0'
|
||||
dec rsi
|
||||
mov [rsi], dl
|
||||
inc rcx
|
||||
mov rbx, rax
|
||||
test rbx, rbx
|
||||
jne puts_loop
|
||||
puts_sign:
|
||||
cmp r8, 0
|
||||
je puts_finish_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '-'
|
||||
inc rcx
|
||||
puts_finish_digits:
|
||||
mov byte [rsi + rcx], 10
|
||||
inc rcx
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
mov rdx, rcx
|
||||
mov r9, rsi
|
||||
mov rsi, r9
|
||||
syscall
|
||||
ret
|
||||
word_write_buf:
|
||||
mov rdx, [r12] ; len
|
||||
mov rsi, [r12 + 8] ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, 1 ; fd = stdout
|
||||
syscall
|
||||
ret
|
||||
ret
|
||||
word_main:
|
||||
; push 2
|
||||
sub r12, 8
|
||||
mov qword [r12], 2
|
||||
; push 40
|
||||
sub r12, 8
|
||||
mov qword [r12], 40
|
||||
call word__2b
|
||||
call word_puts
|
||||
; push 1
|
||||
sub r12, 8
|
||||
mov qword [r12], 1
|
||||
; push 2
|
||||
sub r12, 8
|
||||
mov qword [r12], 2
|
||||
call word_foo
|
||||
call word_puts
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
ret
|
||||
word_foo:
|
||||
call word__3er
|
||||
call word__3er
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
call word_rpick
|
||||
; push 1
|
||||
sub r12, 8
|
||||
mov qword [r12], 1
|
||||
call word_rpick
|
||||
call word__2b
|
||||
call word_rdrop
|
||||
call word_rdrop
|
||||
ret
|
||||
section .data
|
||||
data_start:
|
||||
data_end:
|
||||
section .bss
|
||||
align 16
|
||||
dstack: resb DSTK_BYTES
|
||||
dstack_top:
|
||||
align 16
|
||||
rstack: resb RSTK_BYTES
|
||||
rstack_top:
|
||||
align 16
|
||||
print_buf: resb PRINT_BUF_BYTES
|
||||
print_buf_end:
|
||||
BIN
build/main.o
BIN
build/main.o
Binary file not shown.
@@ -1,594 +0,0 @@
|
||||
section .text
|
||||
%define DSTK_BYTES 65536
|
||||
%define RSTK_BYTES 65536
|
||||
%define PRINT_BUF_BYTES 128
|
||||
global _start
|
||||
_start:
|
||||
; initialize data/return stack pointers
|
||||
lea r12, [rel dstack_top]
|
||||
mov r15, r12
|
||||
lea r13, [rel rstack_top]
|
||||
call word_main
|
||||
mov rax, 0
|
||||
cmp r12, r15
|
||||
je .no_exit_value
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
.no_exit_value:
|
||||
mov rdi, rax
|
||||
mov rax, 60
|
||||
syscall
|
||||
word_c_40:
|
||||
mov rax, [r12]
|
||||
movzx rax, byte [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_c_21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rbx], al
|
||||
ret
|
||||
ret
|
||||
word_r_40:
|
||||
mov rax, [r13]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_dup:
|
||||
mov rax, [r12]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_drop:
|
||||
add r12, 8
|
||||
ret
|
||||
word_over:
|
||||
mov rax, [r12 + 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_swap:
|
||||
mov rax, [r12]
|
||||
mov rbx, [r12 + 8]
|
||||
mov [r12], rbx
|
||||
mov [r12 + 8], rax
|
||||
ret
|
||||
word_rot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rcx ; top = x1
|
||||
mov [r12 + 8], rax ; next = x3
|
||||
mov [r12 + 16], rbx ; third = x2
|
||||
ret
|
||||
word__2drot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rbx ; top = x2
|
||||
mov [r12 + 8], rcx ; next = x1
|
||||
mov [r12 + 16], rax ; third = x3
|
||||
ret
|
||||
word_nip:
|
||||
mov rax, [r12]
|
||||
add r12, 8 ; drop lower element
|
||||
mov [r12], rax ; keep original top
|
||||
ret
|
||||
word_tuck:
|
||||
mov rax, [r12] ; x2
|
||||
mov rbx, [r12 + 8] ; x1
|
||||
sub r12, 8 ; make room
|
||||
mov [r12], rax ; x2
|
||||
mov [r12 + 8], rbx ; x1
|
||||
mov [r12 + 16], rax ; x2
|
||||
ret
|
||||
word_2dup:
|
||||
mov rax, [r12] ; b
|
||||
mov rbx, [r12 + 8] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word_2drop:
|
||||
add r12, 16
|
||||
ret
|
||||
word_2swap:
|
||||
mov rax, [r12] ; d
|
||||
mov rbx, [r12 + 8] ; c
|
||||
mov rcx, [r12 + 16] ; b
|
||||
mov rdx, [r12 + 24] ; a
|
||||
mov [r12], rcx ; top = b
|
||||
mov [r12 + 8], rdx ; next = a
|
||||
mov [r12 + 16], rax ; third = d
|
||||
mov [r12 + 24], rbx ; fourth = c
|
||||
ret
|
||||
word_2over:
|
||||
mov rax, [r12 + 16] ; b
|
||||
mov rbx, [r12 + 24] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word__2b:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
add qword [r12], rax
|
||||
ret
|
||||
word__2d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub qword [r12], rax
|
||||
ret
|
||||
word__2a:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
imul qword [r12]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__2f:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__25:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rdx
|
||||
ret
|
||||
word__3d_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
sete bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__21_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setne bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setl bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setg bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setle bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setge bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__40:
|
||||
mov rax, [r12]
|
||||
mov rax, [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rax], rbx
|
||||
add r12, 8
|
||||
ret
|
||||
word_mmap:
|
||||
; Save rsp and align to 16 bytes for syscall ABI
|
||||
mov rax, rsp
|
||||
and rsp, -16
|
||||
mov rdi, [r12+40] ; addr
|
||||
mov rsi, [r12+32] ; length
|
||||
mov rdx, [r12+24] ; prot
|
||||
mov r10, [r12+16] ; flags
|
||||
mov r8, [r12+8] ; fd
|
||||
mov r9, [r12] ; offset
|
||||
add r12, 48 ; pop 6 args
|
||||
mov rax, 9 ; syscall: mmap
|
||||
syscall
|
||||
mov rsp, rax ; restore rsp
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push result
|
||||
ret
|
||||
ret
|
||||
word_munmap:
|
||||
mov rsi, [r12]
|
||||
add r12, 8
|
||||
mov rdi, [r12]
|
||||
mov rax, 11
|
||||
syscall
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_exit:
|
||||
mov rdi, [r12]
|
||||
add r12, 8
|
||||
mov rax, 60
|
||||
syscall
|
||||
ret
|
||||
word_and:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
and rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_or:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
or rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_not:
|
||||
mov rax, [r12]
|
||||
test rax, rax
|
||||
setz al
|
||||
movzx rax, al
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__3er:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub r13, 8
|
||||
mov [r13], rax
|
||||
ret
|
||||
word_r_3e:
|
||||
mov rax, [r13]
|
||||
add r13, 8
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rdrop:
|
||||
add r13, 8
|
||||
ret
|
||||
word_pick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rpick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r13 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_read_file:
|
||||
; stack: path_ptr (top), path_len (next)
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
add r12, 16 ; pop args
|
||||
|
||||
; open(path_ptr, O_RDONLY=0, mode=0)
|
||||
mov rax, 2 ; syscall: open
|
||||
mov rdi, rsi ; filename
|
||||
xor rsi, rsi ; flags = O_RDONLY
|
||||
xor rdx, rdx ; mode = 0
|
||||
syscall
|
||||
mov r10, rax ; save open() result
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r8, rax ; fd
|
||||
|
||||
; use lseek to determine file size: lseek(fd, 0, SEEK_END)
|
||||
mov rax, 8 ; syscall: lseek
|
||||
mov rdi, r8 ; fd
|
||||
xor rsi, rsi ; offset = 0
|
||||
mov rdx, 2 ; SEEK_END
|
||||
syscall
|
||||
mov r11, rax ; save lseek() result
|
||||
cmp rax, 0
|
||||
jl .close_fail_lseek
|
||||
mov rsi, rax ; length = size
|
||||
|
||||
; mmap(NULL, size, PROT_READ=1, MAP_PRIVATE=2, fd, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
; rsi already holds length
|
||||
mov rdx, 1 ; PROT_READ
|
||||
mov r10, 2 ; MAP_PRIVATE
|
||||
mov r8, r8 ; fd
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
mov rbx, rax ; addr
|
||||
mov r12, r12 ; (no-op, for debug)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r8 ; fd
|
||||
syscall
|
||||
cmp rbx, -4095
|
||||
jae .fail_mmap
|
||||
sub r12, 16
|
||||
mov [r12], rsi ; len (rsi held length across syscall)
|
||||
mov [r12 + 8], rbx ; addr
|
||||
ret
|
||||
|
||||
.close_fail_lseek:
|
||||
mov rax, 3
|
||||
mov rdi, r8
|
||||
syscall
|
||||
mov rax, r11 ; return lseek() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -1
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
mov rax, r10 ; return open() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -2
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
mov rax, -1 ; return mmap() error
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -3
|
||||
ret
|
||||
ret
|
||||
word_write_file:
|
||||
; stack: path_ptr (top), path_len, buf_ptr, buf_len
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
mov r15, [r12 + 16] ; buf_ptr (save in callee-saved r15)
|
||||
mov r13, [r12 + 24] ; buf_len (save in callee-saved r13)
|
||||
add r12, 32 ; pop 4 args (we saved buf info)
|
||||
|
||||
; open(path_ptr, O_WRONLY|O_CREAT|O_TRUNC, 0666)
|
||||
mov rdi, rsi ; filename
|
||||
mov rsi, 577 ; flags = O_WRONLY|O_CREAT|O_TRUNC
|
||||
mov rdx, 438 ; mode = 0o666
|
||||
mov rax, 2 ; syscall: open
|
||||
syscall
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r9, rax ; save fd
|
||||
|
||||
; write(fd, buf_ptr, buf_len) -- use preserved r15/r13 which survive syscalls
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, r9 ; fd
|
||||
mov rsi, r15 ; buf_ptr
|
||||
mov rdx, r13 ; buf_len
|
||||
syscall
|
||||
mov r10, rax ; save write result
|
||||
cmp r10, 0
|
||||
jl .fail_write
|
||||
|
||||
; close(fd)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r9
|
||||
syscall
|
||||
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_write:
|
||||
mov rax, 3
|
||||
mov rdi, r9
|
||||
syscall
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_read_stdin:
|
||||
; stack: max_len
|
||||
mov r14, [r12] ; max_len
|
||||
add r12, 8 ; pop max_len
|
||||
|
||||
; mmap(NULL, max_len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
mov rsi, r14 ; length
|
||||
mov rdx, 3 ; PROT_READ|PROT_WRITE
|
||||
mov r10, 34 ; MAP_PRIVATE|MAP_ANONYMOUS
|
||||
mov r8, -1 ; fd = -1
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
cmp rax, -4095
|
||||
jae .fail_mmap
|
||||
mov rbx, rax ; buffer addr
|
||||
xor r9, r9 ; bytes_read = 0
|
||||
|
||||
.read_loop:
|
||||
mov rax, 0 ; syscall: read
|
||||
mov rdi, 0 ; fd = stdin
|
||||
lea rsi, [rbx + r9] ; buf + offset
|
||||
mov rdx, r14
|
||||
sub rdx, r9 ; remaining = max_len - bytes_read
|
||||
syscall
|
||||
cmp rax, 0
|
||||
je .done_read
|
||||
js .read_error
|
||||
add r9, rax
|
||||
jl .read_loop
|
||||
|
||||
.done_read:
|
||||
; push len (rcx) then addr (rbx)
|
||||
cmp r9, r14
|
||||
je .done_no_null
|
||||
mov byte [rbx + r9], 0
|
||||
.done_no_null:
|
||||
sub r12, 16
|
||||
mov [r12], r9
|
||||
mov [r12 + 8], rbx
|
||||
ret
|
||||
|
||||
.read_error:
|
||||
; return negative errno in rax, addr = 0
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], 0
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
sub r12, 16
|
||||
mov qword [r12], -1
|
||||
mov qword [r12 + 8], 0
|
||||
ret
|
||||
ret
|
||||
word_puts:
|
||||
; detects string if top is len>=0 and next is a pointer in [data_start, data_end]
|
||||
mov rax, [r12] ; len or int value
|
||||
mov rbx, [r12 + 8] ; possible address
|
||||
cmp rax, 0
|
||||
jl puts_print_int
|
||||
lea r8, [rel data_start]
|
||||
lea r9, [rel data_end]
|
||||
cmp rbx, r8
|
||||
jl puts_print_int
|
||||
cmp rbx, r9
|
||||
jge puts_print_int
|
||||
; treat as string: (addr below len)
|
||||
mov rdx, rax ; len
|
||||
mov rsi, rbx ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
test rdx, rdx
|
||||
jz puts_str_newline_only
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
syscall
|
||||
puts_str_newline_only:
|
||||
mov byte [rel print_buf], 10
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
lea rsi, [rel print_buf]
|
||||
mov rdx, 1
|
||||
syscall
|
||||
ret
|
||||
puts_print_int:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, rax
|
||||
mov r8, 0
|
||||
cmp rbx, 0
|
||||
jge puts_abs
|
||||
neg rbx
|
||||
mov r8, 1
|
||||
puts_abs:
|
||||
lea rsi, [rel print_buf_end]
|
||||
mov rcx, 0
|
||||
mov r10, 10
|
||||
cmp rbx, 0
|
||||
jne puts_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '0'
|
||||
inc rcx
|
||||
jmp puts_sign
|
||||
puts_digits:
|
||||
puts_loop:
|
||||
xor rdx, rdx
|
||||
mov rax, rbx
|
||||
div r10
|
||||
add dl, '0'
|
||||
dec rsi
|
||||
mov [rsi], dl
|
||||
inc rcx
|
||||
mov rbx, rax
|
||||
test rbx, rbx
|
||||
jne puts_loop
|
||||
puts_sign:
|
||||
cmp r8, 0
|
||||
je puts_finish_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '-'
|
||||
inc rcx
|
||||
puts_finish_digits:
|
||||
mov byte [rsi + rcx], 10
|
||||
inc rcx
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
mov rdx, rcx
|
||||
mov r9, rsi
|
||||
mov rsi, r9
|
||||
syscall
|
||||
ret
|
||||
word_write_buf:
|
||||
mov rdx, [r12] ; len
|
||||
mov rsi, [r12 + 8] ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, 1 ; fd = stdout
|
||||
syscall
|
||||
ret
|
||||
ret
|
||||
word_main:
|
||||
; push 6
|
||||
sub r12, 8
|
||||
mov qword [r12], 6
|
||||
call word_puts
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
ret
|
||||
section .data
|
||||
data_start:
|
||||
data_end:
|
||||
section .bss
|
||||
align 16
|
||||
dstack: resb DSTK_BYTES
|
||||
dstack_top:
|
||||
align 16
|
||||
rstack: resb RSTK_BYTES
|
||||
rstack_top:
|
||||
align 16
|
||||
print_buf: resb PRINT_BUF_BYTES
|
||||
print_buf_end:
|
||||
Binary file not shown.
565
build/str.asm
565
build/str.asm
@@ -1,565 +0,0 @@
|
||||
section .text
|
||||
%define DSTK_BYTES 65536
|
||||
%define RSTK_BYTES 65536
|
||||
%define PRINT_BUF_BYTES 128
|
||||
global _start
|
||||
_start:
|
||||
; initialize data/return stack pointers
|
||||
lea r12, [rel dstack_top]
|
||||
mov r15, r12
|
||||
lea r13, [rel rstack_top]
|
||||
call word_main
|
||||
mov rax, 0
|
||||
cmp r12, r15
|
||||
je .no_exit_value
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
.no_exit_value:
|
||||
mov rdi, rax
|
||||
mov rax, 60
|
||||
syscall
|
||||
word_c_40:
|
||||
mov rax, [r12]
|
||||
movzx rax, byte [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_c_21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rbx], al
|
||||
ret
|
||||
ret
|
||||
word_r_40:
|
||||
mov rax, [r13]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_strlen:
|
||||
mov rax, [r12] ; addr
|
||||
mov rcx, [r12 + 8] ; len
|
||||
add r12, 16 ; pop len and addr
|
||||
mov [r12], rcx ; push len
|
||||
ret
|
||||
ret
|
||||
word_puts:
|
||||
; detects string if top is len>=0 and next is a pointer in [data_start, data_end]
|
||||
mov rax, [r12] ; len or int value
|
||||
mov rbx, [r12 + 8] ; possible address
|
||||
cmp rax, 0
|
||||
jl puts_print_int
|
||||
lea r8, [rel data_start]
|
||||
lea r9, [rel data_end]
|
||||
cmp rbx, r8
|
||||
jl puts_print_int
|
||||
cmp rbx, r9
|
||||
jge puts_print_int
|
||||
; treat as string: (addr below len)
|
||||
mov rdx, rax ; len
|
||||
mov rsi, rbx ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
test rdx, rdx
|
||||
jz puts_str_newline_only
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
syscall
|
||||
puts_str_newline_only:
|
||||
mov byte [rel print_buf], 10
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
lea rsi, [rel print_buf]
|
||||
mov rdx, 1
|
||||
syscall
|
||||
ret
|
||||
|
||||
puts_print_int:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, rax
|
||||
mov r8, 0
|
||||
cmp rbx, 0
|
||||
jge puts_abs
|
||||
neg rbx
|
||||
mov r8, 1
|
||||
puts_abs:
|
||||
lea rsi, [rel print_buf_end]
|
||||
mov rcx, 0
|
||||
mov r10, 10
|
||||
cmp rbx, 0
|
||||
jne puts_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '0'
|
||||
inc rcx
|
||||
jmp puts_sign
|
||||
puts_digits:
|
||||
puts_loop:
|
||||
xor rdx, rdx
|
||||
mov rax, rbx
|
||||
div r10
|
||||
add dl, '0'
|
||||
dec rsi
|
||||
mov [rsi], dl
|
||||
inc rcx
|
||||
mov rbx, rax
|
||||
test rbx, rbx
|
||||
jne puts_loop
|
||||
puts_sign:
|
||||
cmp r8, 0
|
||||
je puts_finish_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '-'
|
||||
inc rcx
|
||||
puts_finish_digits:
|
||||
mov byte [rsi + rcx], 10
|
||||
inc rcx
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
mov rdx, rcx
|
||||
mov r9, rsi
|
||||
mov rsi, r9
|
||||
syscall
|
||||
ret
|
||||
word_dup:
|
||||
mov rax, [r12]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_write_buf:
|
||||
mov rdx, [r12] ; len
|
||||
mov rsi, [r12 + 8] ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, 1 ; fd = stdout
|
||||
syscall
|
||||
ret
|
||||
ret
|
||||
word_drop:
|
||||
add r12, 8
|
||||
ret
|
||||
word_over:
|
||||
mov rax, [r12 + 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_swap:
|
||||
mov rax, [r12]
|
||||
mov rbx, [r12 + 8]
|
||||
mov [r12], rbx
|
||||
mov [r12 + 8], rax
|
||||
ret
|
||||
word_rot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rcx ; top = x1
|
||||
mov [r12 + 8], rax ; next = x3
|
||||
mov [r12 + 16], rbx ; third = x2
|
||||
ret
|
||||
word__2drot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rbx ; top = x2
|
||||
mov [r12 + 8], rcx ; next = x1
|
||||
mov [r12 + 16], rax ; third = x3
|
||||
ret
|
||||
word_nip:
|
||||
mov rax, [r12]
|
||||
add r12, 8 ; drop lower element
|
||||
mov [r12], rax ; keep original top
|
||||
ret
|
||||
word_tuck:
|
||||
mov rax, [r12] ; x2
|
||||
mov rbx, [r12 + 8] ; x1
|
||||
sub r12, 8 ; make room
|
||||
mov [r12], rax ; x2
|
||||
mov [r12 + 8], rbx ; x1
|
||||
mov [r12 + 16], rax ; x2
|
||||
ret
|
||||
word_2dup:
|
||||
mov rax, [r12] ; b
|
||||
mov rbx, [r12 + 8] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word_2drop:
|
||||
add r12, 16
|
||||
ret
|
||||
word_2swap:
|
||||
mov rax, [r12] ; d
|
||||
mov rbx, [r12 + 8] ; c
|
||||
mov rcx, [r12 + 16] ; b
|
||||
mov rdx, [r12 + 24] ; a
|
||||
mov [r12], rcx ; top = b
|
||||
mov [r12 + 8], rdx ; next = a
|
||||
mov [r12 + 16], rax ; third = d
|
||||
mov [r12 + 24], rbx ; fourth = c
|
||||
ret
|
||||
word_2over:
|
||||
mov rax, [r12 + 16] ; b
|
||||
mov rbx, [r12 + 24] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word__2b:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
add qword [r12], rax
|
||||
ret
|
||||
word__2d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub qword [r12], rax
|
||||
ret
|
||||
word__2a:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
imul qword [r12]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__2f:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__25:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rdx
|
||||
ret
|
||||
word__3d_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
sete bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__21_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setne bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setl bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setg bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setle bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setge bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__40:
|
||||
mov rax, [r12]
|
||||
mov rax, [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rax], rbx
|
||||
add r12, 8
|
||||
ret
|
||||
word_mmap:
|
||||
; Save rsp and align to 16 bytes for syscall ABI
|
||||
mov rax, rsp
|
||||
and rsp, -16
|
||||
mov rdi, [r12+40] ; addr
|
||||
mov rsi, [r12+32] ; length
|
||||
mov rdx, [r12+24] ; prot
|
||||
mov r10, [r12+16] ; flags
|
||||
mov r8, [r12+8] ; fd
|
||||
mov r9, [r12] ; offset
|
||||
add r12, 48 ; pop 6 args
|
||||
mov rax, 9 ; syscall: mmap
|
||||
syscall
|
||||
mov rsp, rax ; restore rsp
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push result
|
||||
ret
|
||||
ret
|
||||
word_munmap:
|
||||
mov rsi, [r12]
|
||||
add r12, 8
|
||||
mov rdi, [r12]
|
||||
mov rax, 11
|
||||
syscall
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_exit:
|
||||
mov rdi, [r12]
|
||||
add r12, 8
|
||||
mov rax, 60
|
||||
syscall
|
||||
ret
|
||||
word_and:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
and rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_or:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
or rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_not:
|
||||
mov rax, [r12]
|
||||
test rax, rax
|
||||
setz al
|
||||
movzx rax, al
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__3er:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub r13, 8
|
||||
mov [r13], rax
|
||||
ret
|
||||
word_r_3e:
|
||||
mov rax, [r13]
|
||||
add r13, 8
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rdrop:
|
||||
add r13, 8
|
||||
ret
|
||||
word_pick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rpick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r13 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_read_file:
|
||||
; stack: path_ptr (top), path_len (next)
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
add r12, 16 ; pop args
|
||||
|
||||
; open(path_ptr, O_RDONLY=0, mode=0)
|
||||
mov rax, 2 ; syscall: open
|
||||
mov rdi, rsi ; filename
|
||||
xor rsi, rsi ; flags = O_RDONLY
|
||||
xor rdx, rdx ; mode = 0
|
||||
syscall
|
||||
mov r10, rax ; save open() result
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r8, rax ; fd
|
||||
|
||||
; use lseek to determine file size: lseek(fd, 0, SEEK_END)
|
||||
mov rax, 8 ; syscall: lseek
|
||||
mov rdi, r8 ; fd
|
||||
xor rsi, rsi ; offset = 0
|
||||
mov rdx, 2 ; SEEK_END
|
||||
syscall
|
||||
mov r11, rax ; save lseek() result
|
||||
cmp rax, 0
|
||||
jl .close_fail_lseek
|
||||
mov rsi, rax ; length = size
|
||||
|
||||
; mmap(NULL, size, PROT_READ=1, MAP_PRIVATE=2, fd, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
; rsi already holds length
|
||||
mov rdx, 1 ; PROT_READ
|
||||
mov r10, 2 ; MAP_PRIVATE
|
||||
mov r8, r8 ; fd
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
mov rbx, rax ; addr
|
||||
mov r12, r12 ; (no-op, for debug)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r8 ; fd
|
||||
syscall
|
||||
cmp rbx, -4095
|
||||
jae .fail_mmap
|
||||
sub r12, 16
|
||||
mov [r12], rsi ; len (rsi held length across syscall)
|
||||
mov [r12 + 8], rbx ; addr
|
||||
ret
|
||||
|
||||
.close_fail_lseek:
|
||||
mov rax, 3
|
||||
mov rdi, r8
|
||||
syscall
|
||||
mov rax, r11 ; return lseek() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -1
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
mov rax, r10 ; return open() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -2
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
mov rax, -1 ; return mmap() error
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -3
|
||||
ret
|
||||
ret
|
||||
word_write_file:
|
||||
; stack: path_ptr (top), path_len, buf_ptr, buf_len
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
mov r15, [r12 + 16] ; buf_ptr (save in callee-saved r15)
|
||||
mov r13, [r12 + 24] ; buf_len (save in callee-saved r13)
|
||||
add r12, 32 ; pop 4 args (we saved buf info)
|
||||
|
||||
; open(path_ptr, O_WRONLY|O_CREAT|O_TRUNC, 0666)
|
||||
mov rdi, rsi ; filename
|
||||
mov rsi, 577 ; flags = O_WRONLY|O_CREAT|O_TRUNC
|
||||
mov rdx, 438 ; mode = 0o666
|
||||
mov rax, 2 ; syscall: open
|
||||
syscall
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r9, rax ; save fd
|
||||
|
||||
; write(fd, buf_ptr, buf_len) -- use preserved r15/r13 which survive syscalls
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, r9 ; fd
|
||||
mov rsi, r15 ; buf_ptr
|
||||
mov rdx, r13 ; buf_len
|
||||
syscall
|
||||
mov r10, rax ; save write result
|
||||
cmp r10, 0
|
||||
jl .fail_write
|
||||
|
||||
; close(fd)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r9
|
||||
syscall
|
||||
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_write:
|
||||
mov rax, 3
|
||||
mov rdi, r9
|
||||
syscall
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_main2:
|
||||
; push str_0
|
||||
sub r12, 8
|
||||
mov qword [r12], str_0
|
||||
; push 6
|
||||
sub r12, 8
|
||||
mov qword [r12], 6
|
||||
call word_swap
|
||||
call word_read_file
|
||||
call word_write_buf
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
ret
|
||||
word_main:
|
||||
; push str_1
|
||||
sub r12, 8
|
||||
mov qword [r12], str_1
|
||||
; push 7
|
||||
sub r12, 8
|
||||
mov qword [r12], 7
|
||||
call word_dup
|
||||
call word_puts
|
||||
ret
|
||||
section .data
|
||||
data_start:
|
||||
str_0: db 115, 116, 114, 46, 115, 108, 0
|
||||
str_0_len equ 6
|
||||
str_1: db 118, 99, 120, 122, 118, 103, 103, 0
|
||||
str_1_len equ 7
|
||||
data_end:
|
||||
section .bss
|
||||
align 16
|
||||
dstack: resb DSTK_BYTES
|
||||
dstack_top:
|
||||
align 16
|
||||
rstack: resb RSTK_BYTES
|
||||
rstack_top:
|
||||
align 16
|
||||
print_buf: resb PRINT_BUF_BYTES
|
||||
print_buf_end:
|
||||
BIN
build/str.o
BIN
build/str.o
Binary file not shown.
@@ -1,617 +0,0 @@
|
||||
section .text
|
||||
%define DSTK_BYTES 65536
|
||||
%define RSTK_BYTES 65536
|
||||
%define PRINT_BUF_BYTES 128
|
||||
global _start
|
||||
_start:
|
||||
; initialize data/return stack pointers
|
||||
lea r12, [rel dstack_top]
|
||||
mov r15, r12
|
||||
lea r13, [rel rstack_top]
|
||||
call word_main
|
||||
mov rax, 0
|
||||
cmp r12, r15
|
||||
je .no_exit_value
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
.no_exit_value:
|
||||
mov rdi, rax
|
||||
mov rax, 60
|
||||
syscall
|
||||
word_c_40:
|
||||
mov rax, [r12]
|
||||
movzx rax, byte [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_c_21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rbx], al
|
||||
ret
|
||||
ret
|
||||
word_r_40:
|
||||
mov rax, [r13]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_dup:
|
||||
mov rax, [r12]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_drop:
|
||||
add r12, 8
|
||||
ret
|
||||
word_over:
|
||||
mov rax, [r12 + 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_swap:
|
||||
mov rax, [r12]
|
||||
mov rbx, [r12 + 8]
|
||||
mov [r12], rbx
|
||||
mov [r12 + 8], rax
|
||||
ret
|
||||
word_rot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rcx ; top = x1
|
||||
mov [r12 + 8], rax ; next = x3
|
||||
mov [r12 + 16], rbx ; third = x2
|
||||
ret
|
||||
word__2drot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rbx ; top = x2
|
||||
mov [r12 + 8], rcx ; next = x1
|
||||
mov [r12 + 16], rax ; third = x3
|
||||
ret
|
||||
word_nip:
|
||||
mov rax, [r12]
|
||||
add r12, 8 ; drop lower element
|
||||
mov [r12], rax ; keep original top
|
||||
ret
|
||||
word_tuck:
|
||||
mov rax, [r12] ; x2
|
||||
mov rbx, [r12 + 8] ; x1
|
||||
sub r12, 8 ; make room
|
||||
mov [r12], rax ; x2
|
||||
mov [r12 + 8], rbx ; x1
|
||||
mov [r12 + 16], rax ; x2
|
||||
ret
|
||||
word_2dup:
|
||||
mov rax, [r12] ; b
|
||||
mov rbx, [r12 + 8] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word_2drop:
|
||||
add r12, 16
|
||||
ret
|
||||
word_2swap:
|
||||
mov rax, [r12] ; d
|
||||
mov rbx, [r12 + 8] ; c
|
||||
mov rcx, [r12 + 16] ; b
|
||||
mov rdx, [r12 + 24] ; a
|
||||
mov [r12], rcx ; top = b
|
||||
mov [r12 + 8], rdx ; next = a
|
||||
mov [r12 + 16], rax ; third = d
|
||||
mov [r12 + 24], rbx ; fourth = c
|
||||
ret
|
||||
word_2over:
|
||||
mov rax, [r12 + 16] ; b
|
||||
mov rbx, [r12 + 24] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word__2b:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
add qword [r12], rax
|
||||
ret
|
||||
word__2d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub qword [r12], rax
|
||||
ret
|
||||
word__2a:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
imul qword [r12]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__2f:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__25:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rdx
|
||||
ret
|
||||
word__3d_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
sete bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__21_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setne bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setl bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setg bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setle bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setge bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__40:
|
||||
mov rax, [r12]
|
||||
mov rax, [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rax], rbx
|
||||
add r12, 8
|
||||
ret
|
||||
word_mmap:
|
||||
; Save rsp and align to 16 bytes for syscall ABI
|
||||
mov rax, rsp
|
||||
and rsp, -16
|
||||
mov rdi, [r12+40] ; addr
|
||||
mov rsi, [r12+32] ; length
|
||||
mov rdx, [r12+24] ; prot
|
||||
mov r10, [r12+16] ; flags
|
||||
mov r8, [r12+8] ; fd
|
||||
mov r9, [r12] ; offset
|
||||
add r12, 48 ; pop 6 args
|
||||
mov rax, 9 ; syscall: mmap
|
||||
syscall
|
||||
mov rsp, rax ; restore rsp
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push result
|
||||
ret
|
||||
ret
|
||||
word_munmap:
|
||||
mov rsi, [r12]
|
||||
add r12, 8
|
||||
mov rdi, [r12]
|
||||
mov rax, 11
|
||||
syscall
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_exit:
|
||||
mov rdi, [r12]
|
||||
add r12, 8
|
||||
mov rax, 60
|
||||
syscall
|
||||
ret
|
||||
word_and:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
and rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_or:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
or rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_not:
|
||||
mov rax, [r12]
|
||||
test rax, rax
|
||||
setz al
|
||||
movzx rax, al
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__3er:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub r13, 8
|
||||
mov [r13], rax
|
||||
ret
|
||||
word_r_3e:
|
||||
mov rax, [r13]
|
||||
add r13, 8
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rdrop:
|
||||
add r13, 8
|
||||
ret
|
||||
word_pick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rpick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r13 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_read_file:
|
||||
; stack: path_ptr (top), path_len (next)
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
add r12, 16 ; pop args
|
||||
|
||||
; open(path_ptr, O_RDONLY=0, mode=0)
|
||||
mov rax, 2 ; syscall: open
|
||||
mov rdi, rsi ; filename
|
||||
xor rsi, rsi ; flags = O_RDONLY
|
||||
xor rdx, rdx ; mode = 0
|
||||
syscall
|
||||
mov r10, rax ; save open() result
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r8, rax ; fd
|
||||
|
||||
; use lseek to determine file size: lseek(fd, 0, SEEK_END)
|
||||
mov rax, 8 ; syscall: lseek
|
||||
mov rdi, r8 ; fd
|
||||
xor rsi, rsi ; offset = 0
|
||||
mov rdx, 2 ; SEEK_END
|
||||
syscall
|
||||
mov r11, rax ; save lseek() result
|
||||
cmp rax, 0
|
||||
jl .close_fail_lseek
|
||||
mov rsi, rax ; length = size
|
||||
|
||||
; mmap(NULL, size, PROT_READ=1, MAP_PRIVATE=2, fd, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
; rsi already holds length
|
||||
mov rdx, 1 ; PROT_READ
|
||||
mov r10, 2 ; MAP_PRIVATE
|
||||
mov r8, r8 ; fd
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
mov rbx, rax ; addr
|
||||
mov r12, r12 ; (no-op, for debug)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r8 ; fd
|
||||
syscall
|
||||
cmp rbx, -4095
|
||||
jae .fail_mmap
|
||||
sub r12, 16
|
||||
mov [r12], rsi ; len (rsi held length across syscall)
|
||||
mov [r12 + 8], rbx ; addr
|
||||
ret
|
||||
|
||||
.close_fail_lseek:
|
||||
mov rax, 3
|
||||
mov rdi, r8
|
||||
syscall
|
||||
mov rax, r11 ; return lseek() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -1
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
mov rax, r10 ; return open() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -2
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
mov rax, -1 ; return mmap() error
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -3
|
||||
ret
|
||||
ret
|
||||
word_write_file:
|
||||
; stack: path_ptr (top), path_len, buf_ptr, buf_len
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
mov r15, [r12 + 16] ; buf_ptr (save in callee-saved r15)
|
||||
mov r13, [r12 + 24] ; buf_len (save in callee-saved r13)
|
||||
add r12, 32 ; pop 4 args (we saved buf info)
|
||||
|
||||
; open(path_ptr, O_WRONLY|O_CREAT|O_TRUNC, 0666)
|
||||
mov rdi, rsi ; filename
|
||||
mov rsi, 577 ; flags = O_WRONLY|O_CREAT|O_TRUNC
|
||||
mov rdx, 438 ; mode = 0o666
|
||||
mov rax, 2 ; syscall: open
|
||||
syscall
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r9, rax ; save fd
|
||||
|
||||
; write(fd, buf_ptr, buf_len) -- use preserved r15/r13 which survive syscalls
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, r9 ; fd
|
||||
mov rsi, r15 ; buf_ptr
|
||||
mov rdx, r13 ; buf_len
|
||||
syscall
|
||||
mov r10, rax ; save write result
|
||||
cmp r10, 0
|
||||
jl .fail_write
|
||||
|
||||
; close(fd)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r9
|
||||
syscall
|
||||
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_write:
|
||||
mov rax, 3
|
||||
mov rdi, r9
|
||||
syscall
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_read_stdin:
|
||||
; stack: max_len
|
||||
mov r14, [r12] ; max_len
|
||||
add r12, 8 ; pop max_len
|
||||
|
||||
; mmap(NULL, max_len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
mov rsi, r14 ; length
|
||||
mov rdx, 3 ; PROT_READ|PROT_WRITE
|
||||
mov r10, 34 ; MAP_PRIVATE|MAP_ANONYMOUS
|
||||
mov r8, -1 ; fd = -1
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
cmp rax, -4095
|
||||
jae .fail_mmap
|
||||
mov rbx, rax ; buffer addr
|
||||
xor r9, r9 ; bytes_read = 0
|
||||
|
||||
.read_loop:
|
||||
mov rax, 0 ; syscall: read
|
||||
mov rdi, 0 ; fd = stdin
|
||||
lea rsi, [rbx + r9] ; buf + offset
|
||||
mov rdx, r14
|
||||
sub rdx, r9 ; remaining = max_len - bytes_read
|
||||
syscall
|
||||
cmp rax, 0
|
||||
je .done_read
|
||||
js .read_error
|
||||
add r9, rax
|
||||
jl .read_loop
|
||||
|
||||
.done_read:
|
||||
; push len (rcx) then addr (rbx)
|
||||
cmp r9, r14
|
||||
je .done_no_null
|
||||
mov byte [rbx + r9], 0
|
||||
.done_no_null:
|
||||
sub r12, 16
|
||||
mov [r12], r9
|
||||
mov [r12 + 8], rbx
|
||||
ret
|
||||
|
||||
.read_error:
|
||||
; return negative errno in rax, addr = 0
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], 0
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
sub r12, 16
|
||||
mov qword [r12], -1
|
||||
mov qword [r12 + 8], 0
|
||||
ret
|
||||
ret
|
||||
word_puts:
|
||||
; detects string if top is len>=0 and next is a pointer in [data_start, data_end]
|
||||
mov rax, [r12] ; len or int value
|
||||
mov rbx, [r12 + 8] ; possible address
|
||||
cmp rax, 0
|
||||
jl puts_print_int
|
||||
lea r8, [rel data_start]
|
||||
lea r9, [rel data_end]
|
||||
cmp rbx, r8
|
||||
jl puts_print_int
|
||||
cmp rbx, r9
|
||||
jge puts_print_int
|
||||
; treat as string: (addr below len)
|
||||
mov rdx, rax ; len
|
||||
mov rsi, rbx ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
test rdx, rdx
|
||||
jz puts_str_newline_only
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
syscall
|
||||
puts_str_newline_only:
|
||||
mov byte [rel print_buf], 10
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
lea rsi, [rel print_buf]
|
||||
mov rdx, 1
|
||||
syscall
|
||||
ret
|
||||
puts_print_int:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, rax
|
||||
mov r8, 0
|
||||
cmp rbx, 0
|
||||
jge puts_abs
|
||||
neg rbx
|
||||
mov r8, 1
|
||||
puts_abs:
|
||||
lea rsi, [rel print_buf_end]
|
||||
mov rcx, 0
|
||||
mov r10, 10
|
||||
cmp rbx, 0
|
||||
jne puts_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '0'
|
||||
inc rcx
|
||||
jmp puts_sign
|
||||
puts_digits:
|
||||
puts_loop:
|
||||
xor rdx, rdx
|
||||
mov rax, rbx
|
||||
div r10
|
||||
add dl, '0'
|
||||
dec rsi
|
||||
mov [rsi], dl
|
||||
inc rcx
|
||||
mov rbx, rax
|
||||
test rbx, rbx
|
||||
jne puts_loop
|
||||
puts_sign:
|
||||
cmp r8, 0
|
||||
je puts_finish_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '-'
|
||||
inc rcx
|
||||
puts_finish_digits:
|
||||
mov byte [rsi + rcx], 10
|
||||
inc rcx
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
mov rdx, rcx
|
||||
mov r9, rsi
|
||||
mov rsi, r9
|
||||
syscall
|
||||
ret
|
||||
word_write_buf:
|
||||
mov rdx, [r12] ; len
|
||||
mov rsi, [r12 + 8] ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, 1 ; fd = stdout
|
||||
syscall
|
||||
ret
|
||||
ret
|
||||
word_main:
|
||||
; push str_0
|
||||
sub r12, 8
|
||||
mov qword [r12], str_0
|
||||
; push 11
|
||||
sub r12, 8
|
||||
mov qword [r12], 11
|
||||
call word_puts
|
||||
; push str_1
|
||||
sub r12, 8
|
||||
mov qword [r12], str_1
|
||||
; push 11
|
||||
sub r12, 8
|
||||
mov qword [r12], 11
|
||||
call word_puts
|
||||
; push str_2
|
||||
sub r12, 8
|
||||
mov qword [r12], str_2
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
call word_puts
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
ret
|
||||
section .data
|
||||
data_start:
|
||||
str_0: db 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 0
|
||||
str_0_len equ 11
|
||||
str_1: db 108, 105, 110, 101, 49, 10, 108, 105, 110, 101, 50, 0
|
||||
str_1_len equ 11
|
||||
str_2: db 0
|
||||
str_2_len equ 0
|
||||
data_end:
|
||||
section .bss
|
||||
align 16
|
||||
dstack: resb DSTK_BYTES
|
||||
dstack_top:
|
||||
align 16
|
||||
rstack: resb RSTK_BYTES
|
||||
rstack_top:
|
||||
align 16
|
||||
print_buf: resb PRINT_BUF_BYTES
|
||||
print_buf_end:
|
||||
Binary file not shown.
409
build/t.asm
409
build/t.asm
@@ -1,409 +0,0 @@
|
||||
section .text
|
||||
%define DSTK_BYTES 65536
|
||||
%define RSTK_BYTES 65536
|
||||
%define PRINT_BUF_BYTES 128
|
||||
global _start
|
||||
_start:
|
||||
; initialize data/return stack pointers
|
||||
lea r12, [rel dstack_top]
|
||||
mov r15, r12
|
||||
lea r13, [rel rstack_top]
|
||||
call word_main
|
||||
mov rax, 0
|
||||
cmp r12, r15
|
||||
je .no_exit_value
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
.no_exit_value:
|
||||
mov rdi, rax
|
||||
mov rax, 60
|
||||
syscall
|
||||
word_puts:
|
||||
; detects string if top is len>=0 and next is a pointer in [data_start, data_end]
|
||||
mov rax, [r12] ; len or int value
|
||||
mov rbx, [r12 + 8] ; possible address
|
||||
cmp rax, 0
|
||||
jl puts_print_int
|
||||
lea r8, [rel data_start]
|
||||
lea r9, [rel data_end]
|
||||
cmp rbx, r8
|
||||
jl puts_print_int
|
||||
cmp rbx, r9
|
||||
jge puts_print_int
|
||||
; treat as string: (addr below len)
|
||||
mov rdx, rax ; len
|
||||
mov rsi, rbx ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
test rdx, rdx
|
||||
jz puts_str_newline_only
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
syscall
|
||||
puts_str_newline_only:
|
||||
mov byte [rel print_buf], 10
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
lea rsi, [rel print_buf]
|
||||
mov rdx, 1
|
||||
syscall
|
||||
ret
|
||||
|
||||
puts_print_int:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, rax
|
||||
mov r8, 0
|
||||
cmp rbx, 0
|
||||
jge puts_abs
|
||||
neg rbx
|
||||
mov r8, 1
|
||||
puts_abs:
|
||||
lea rsi, [rel print_buf_end]
|
||||
mov rcx, 0
|
||||
mov r10, 10
|
||||
cmp rbx, 0
|
||||
jne puts_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '0'
|
||||
inc rcx
|
||||
jmp puts_sign
|
||||
puts_digits:
|
||||
puts_loop:
|
||||
xor rdx, rdx
|
||||
mov rax, rbx
|
||||
div r10
|
||||
add dl, '0'
|
||||
dec rsi
|
||||
mov [rsi], dl
|
||||
inc rcx
|
||||
mov rbx, rax
|
||||
test rbx, rbx
|
||||
jne puts_loop
|
||||
puts_sign:
|
||||
cmp r8, 0
|
||||
je puts_finish_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '-'
|
||||
inc rcx
|
||||
puts_finish_digits:
|
||||
mov byte [rsi + rcx], 10
|
||||
inc rcx
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
mov rdx, rcx
|
||||
mov r9, rsi
|
||||
mov rsi, r9
|
||||
syscall
|
||||
ret
|
||||
word_dup:
|
||||
mov rax, [r12]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_drop:
|
||||
add r12, 8
|
||||
ret
|
||||
word_over:
|
||||
mov rax, [r12 + 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_swap:
|
||||
mov rax, [r12]
|
||||
mov rbx, [r12 + 8]
|
||||
mov [r12], rbx
|
||||
mov [r12 + 8], rax
|
||||
ret
|
||||
word_rot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rcx ; top = x1
|
||||
mov [r12 + 8], rax ; next = x3
|
||||
mov [r12 + 16], rbx ; third = x2
|
||||
ret
|
||||
word__2drot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rbx ; top = x2
|
||||
mov [r12 + 8], rcx ; next = x1
|
||||
mov [r12 + 16], rax ; third = x3
|
||||
ret
|
||||
word_nip:
|
||||
mov rax, [r12]
|
||||
add r12, 8 ; drop lower element
|
||||
mov [r12], rax ; keep original top
|
||||
ret
|
||||
word_tuck:
|
||||
mov rax, [r12] ; x2
|
||||
mov rbx, [r12 + 8] ; x1
|
||||
sub r12, 8 ; make room
|
||||
mov [r12], rax ; x2
|
||||
mov [r12 + 8], rbx ; x1
|
||||
mov [r12 + 16], rax ; x2
|
||||
ret
|
||||
word_2dup:
|
||||
mov rax, [r12] ; b
|
||||
mov rbx, [r12 + 8] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word_2drop:
|
||||
add r12, 16
|
||||
ret
|
||||
word_2swap:
|
||||
mov rax, [r12] ; d
|
||||
mov rbx, [r12 + 8] ; c
|
||||
mov rcx, [r12 + 16] ; b
|
||||
mov rdx, [r12 + 24] ; a
|
||||
mov [r12], rcx ; top = b
|
||||
mov [r12 + 8], rdx ; next = a
|
||||
mov [r12 + 16], rax ; third = d
|
||||
mov [r12 + 24], rbx ; fourth = c
|
||||
ret
|
||||
word_2over:
|
||||
mov rax, [r12 + 16] ; b
|
||||
mov rbx, [r12 + 24] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word__2b:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
add qword [r12], rax
|
||||
ret
|
||||
word__2d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub qword [r12], rax
|
||||
ret
|
||||
word__2a:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
imul qword [r12]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__2f:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__25:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rdx
|
||||
ret
|
||||
word__3d_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
sete bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__21_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setne bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setl bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setg bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setle bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setge bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__40:
|
||||
mov rax, [r12]
|
||||
mov rax, [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rax], rbx
|
||||
add r12, 8
|
||||
ret
|
||||
word_mmap:
|
||||
mov r9, [r12]
|
||||
add r12, 8
|
||||
mov r8, [r12]
|
||||
add r12, 8
|
||||
mov r10, [r12]
|
||||
add r12, 8
|
||||
mov rdx, [r12]
|
||||
add r12, 8
|
||||
mov rsi, [r12]
|
||||
add r12, 8
|
||||
mov rdi, [r12]
|
||||
mov rax, 9
|
||||
syscall
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_munmap:
|
||||
mov rsi, [r12]
|
||||
add r12, 8
|
||||
mov rdi, [r12]
|
||||
mov rax, 11
|
||||
syscall
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_exit:
|
||||
mov rdi, [r12]
|
||||
add r12, 8
|
||||
mov rax, 60
|
||||
syscall
|
||||
ret
|
||||
word_and:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
and rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_or:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
or rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_not:
|
||||
mov rax, [r12]
|
||||
test rax, rax
|
||||
setz al
|
||||
movzx rax, al
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__3er:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub r13, 8
|
||||
mov [r13], rax
|
||||
ret
|
||||
word_r_3e:
|
||||
mov rax, [r13]
|
||||
add r13, 8
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rdrop:
|
||||
add r13, 8
|
||||
ret
|
||||
word_pick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rpick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r13 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_foo:
|
||||
call word__3er
|
||||
call word__3er
|
||||
; push 1
|
||||
sub r12, 8
|
||||
mov qword [r12], 1
|
||||
call word_puts
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
call word_rpick
|
||||
; push 1
|
||||
sub r12, 8
|
||||
mov qword [r12], 1
|
||||
call word_rpick
|
||||
call word__2b
|
||||
call word_rdrop
|
||||
call word_rdrop
|
||||
ret
|
||||
word_main:
|
||||
; push 3
|
||||
sub r12, 8
|
||||
mov qword [r12], 3
|
||||
; push 2
|
||||
sub r12, 8
|
||||
mov qword [r12], 2
|
||||
call word_foo
|
||||
call word_puts
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
ret
|
||||
section .data
|
||||
data_start:
|
||||
data_end:
|
||||
section .bss
|
||||
align 16
|
||||
dstack: resb DSTK_BYTES
|
||||
dstack_top:
|
||||
align 16
|
||||
rstack: resb RSTK_BYTES
|
||||
rstack_top:
|
||||
align 16
|
||||
print_buf: resb PRINT_BUF_BYTES
|
||||
print_buf_end:
|
||||
866
build/test.asm
866
build/test.asm
@@ -1,866 +0,0 @@
|
||||
section .text
|
||||
%define DSTK_BYTES 65536
|
||||
%define RSTK_BYTES 65536
|
||||
%define PRINT_BUF_BYTES 128
|
||||
global _start
|
||||
_start:
|
||||
; initialize data/return stack pointers
|
||||
lea r12, [rel dstack_top]
|
||||
mov r15, r12
|
||||
lea r13, [rel rstack_top]
|
||||
call word_main
|
||||
mov rax, 0
|
||||
cmp r12, r15
|
||||
je .no_exit_value
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
.no_exit_value:
|
||||
mov rdi, rax
|
||||
mov rax, 60
|
||||
syscall
|
||||
word_puts:
|
||||
; detects string if top is len>=0 and next is a pointer in [data_start, data_end]
|
||||
mov rax, [r12] ; len or int value
|
||||
mov rbx, [r12 + 8] ; possible address
|
||||
cmp rax, 0
|
||||
jl puts_print_int
|
||||
lea r8, [rel data_start]
|
||||
lea r9, [rel data_end]
|
||||
cmp rbx, r8
|
||||
jl puts_print_int
|
||||
cmp rbx, r9
|
||||
jge puts_print_int
|
||||
; treat as string: (addr below len)
|
||||
mov rdx, rax ; len
|
||||
mov rsi, rbx ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
test rdx, rdx
|
||||
jz puts_str_newline_only
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
syscall
|
||||
puts_str_newline_only:
|
||||
mov byte [rel print_buf], 10
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
lea rsi, [rel print_buf]
|
||||
mov rdx, 1
|
||||
syscall
|
||||
ret
|
||||
|
||||
puts_print_int:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, rax
|
||||
mov r8, 0
|
||||
cmp rbx, 0
|
||||
jge puts_abs
|
||||
neg rbx
|
||||
mov r8, 1
|
||||
puts_abs:
|
||||
lea rsi, [rel print_buf_end]
|
||||
mov rcx, 0
|
||||
mov r10, 10
|
||||
cmp rbx, 0
|
||||
jne puts_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '0'
|
||||
inc rcx
|
||||
jmp puts_sign
|
||||
puts_digits:
|
||||
puts_loop:
|
||||
xor rdx, rdx
|
||||
mov rax, rbx
|
||||
div r10
|
||||
add dl, '0'
|
||||
dec rsi
|
||||
mov [rsi], dl
|
||||
inc rcx
|
||||
mov rbx, rax
|
||||
test rbx, rbx
|
||||
jne puts_loop
|
||||
puts_sign:
|
||||
cmp r8, 0
|
||||
je puts_finish_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '-'
|
||||
inc rcx
|
||||
puts_finish_digits:
|
||||
mov byte [rsi + rcx], 10
|
||||
inc rcx
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
mov rdx, rcx
|
||||
mov r9, rsi
|
||||
mov rsi, r9
|
||||
syscall
|
||||
ret
|
||||
word_dup:
|
||||
mov rax, [r12]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_drop:
|
||||
add r12, 8
|
||||
ret
|
||||
word_over:
|
||||
mov rax, [r12 + 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_swap:
|
||||
mov rax, [r12]
|
||||
mov rbx, [r12 + 8]
|
||||
mov [r12], rbx
|
||||
mov [r12 + 8], rax
|
||||
ret
|
||||
word_rot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rcx ; top = x1
|
||||
mov [r12 + 8], rax ; next = x3
|
||||
mov [r12 + 16], rbx ; third = x2
|
||||
ret
|
||||
word__2drot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rbx ; top = x2
|
||||
mov [r12 + 8], rcx ; next = x1
|
||||
mov [r12 + 16], rax ; third = x3
|
||||
ret
|
||||
word_nip:
|
||||
mov rax, [r12]
|
||||
add r12, 8 ; drop lower element
|
||||
mov [r12], rax ; keep original top
|
||||
ret
|
||||
word_tuck:
|
||||
mov rax, [r12] ; x2
|
||||
mov rbx, [r12 + 8] ; x1
|
||||
sub r12, 8 ; make room
|
||||
mov [r12], rax ; x2
|
||||
mov [r12 + 8], rbx ; x1
|
||||
mov [r12 + 16], rax ; x2
|
||||
ret
|
||||
word_2dup:
|
||||
mov rax, [r12] ; b
|
||||
mov rbx, [r12 + 8] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word_2drop:
|
||||
add r12, 16
|
||||
ret
|
||||
word_2swap:
|
||||
mov rax, [r12] ; d
|
||||
mov rbx, [r12 + 8] ; c
|
||||
mov rcx, [r12 + 16] ; b
|
||||
mov rdx, [r12 + 24] ; a
|
||||
mov [r12], rcx ; top = b
|
||||
mov [r12 + 8], rdx ; next = a
|
||||
mov [r12 + 16], rax ; third = d
|
||||
mov [r12 + 24], rbx ; fourth = c
|
||||
ret
|
||||
word_2over:
|
||||
mov rax, [r12 + 16] ; b
|
||||
mov rbx, [r12 + 24] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word__2b:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
add qword [r12], rax
|
||||
ret
|
||||
word__2d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub qword [r12], rax
|
||||
ret
|
||||
word__2a:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
imul qword [r12]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__2f:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__25:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rdx
|
||||
ret
|
||||
word__3d_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
sete bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__21_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setne bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setl bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setg bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setle bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setge bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__40:
|
||||
mov rax, [r12]
|
||||
mov rax, [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rax], rbx
|
||||
add r12, 8
|
||||
ret
|
||||
word_mmap:
|
||||
mov r9, [r12]
|
||||
add r12, 8
|
||||
mov r8, [r12]
|
||||
add r12, 8
|
||||
mov r10, [r12]
|
||||
add r12, 8
|
||||
mov rdx, [r12]
|
||||
add r12, 8
|
||||
mov rsi, [r12]
|
||||
add r12, 8
|
||||
mov rdi, [r12]
|
||||
mov rax, 9
|
||||
syscall
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_munmap:
|
||||
mov rsi, [r12]
|
||||
add r12, 8
|
||||
mov rdi, [r12]
|
||||
mov rax, 11
|
||||
syscall
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_exit:
|
||||
mov rdi, [r12]
|
||||
add r12, 8
|
||||
mov rax, 60
|
||||
syscall
|
||||
ret
|
||||
word_and:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
and rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_or:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
or rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_not:
|
||||
mov rax, [r12]
|
||||
test rax, rax
|
||||
setz al
|
||||
movzx rax, al
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__3er:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub r13, 8
|
||||
mov [r13], rax
|
||||
ret
|
||||
word_r_3e:
|
||||
mov rax, [r13]
|
||||
add r13, 8
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rdrop:
|
||||
add r13, 8
|
||||
ret
|
||||
word_pick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rpick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r13 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_mem_2dslot:
|
||||
lea rax, [rel print_buf]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_MAGIC:
|
||||
; push 99
|
||||
sub r12, 8
|
||||
mov qword [r12], 99
|
||||
ret
|
||||
word_add13:
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
; push 8
|
||||
sub r12, 8
|
||||
mov qword [r12], 8
|
||||
call word__2b
|
||||
ret
|
||||
word_Point_2esize:
|
||||
; push 16
|
||||
sub r12, 8
|
||||
mov qword [r12], 16
|
||||
ret
|
||||
word_Point_2ex_2esize:
|
||||
; push 8
|
||||
sub r12, 8
|
||||
mov qword [r12], 8
|
||||
ret
|
||||
word_Point_2ex_2eoffset:
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
ret
|
||||
word_Point_2ex_40:
|
||||
call word_Point_2ex_2eoffset
|
||||
call word__2b
|
||||
call word__40
|
||||
ret
|
||||
word_Point_2ex_21:
|
||||
call word_Point_2ex_2eoffset
|
||||
call word__2b
|
||||
call word__21
|
||||
ret
|
||||
word_Point_2ey_2esize:
|
||||
; push 8
|
||||
sub r12, 8
|
||||
mov qword [r12], 8
|
||||
ret
|
||||
word_Point_2ey_2eoffset:
|
||||
; push 8
|
||||
sub r12, 8
|
||||
mov qword [r12], 8
|
||||
ret
|
||||
word_Point_2ey_40:
|
||||
call word_Point_2ey_2eoffset
|
||||
call word__2b
|
||||
call word__40
|
||||
ret
|
||||
word_Point_2ey_21:
|
||||
call word_Point_2ey_2eoffset
|
||||
call word__2b
|
||||
call word__21
|
||||
ret
|
||||
word_fancy_add:
|
||||
call word__3er
|
||||
call word__3er
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
call word_rpick
|
||||
; push 1
|
||||
sub r12, 8
|
||||
mov qword [r12], 1
|
||||
call word_rpick
|
||||
call word__2b
|
||||
; push 1
|
||||
sub r12, 8
|
||||
mov qword [r12], 1
|
||||
call word_rpick
|
||||
call word__2a
|
||||
call word_rdrop
|
||||
call word_rdrop
|
||||
ret
|
||||
word_test_2dadd:
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
; push 7
|
||||
sub r12, 8
|
||||
mov qword [r12], 7
|
||||
call word__2b
|
||||
call word_puts
|
||||
ret
|
||||
word_test_2dsub:
|
||||
; push 10
|
||||
sub r12, 8
|
||||
mov qword [r12], 10
|
||||
; push 3
|
||||
sub r12, 8
|
||||
mov qword [r12], 3
|
||||
call word__2d
|
||||
call word_puts
|
||||
ret
|
||||
word_test_2dmul:
|
||||
; push 6
|
||||
sub r12, 8
|
||||
mov qword [r12], 6
|
||||
; push 7
|
||||
sub r12, 8
|
||||
mov qword [r12], 7
|
||||
call word__2a
|
||||
call word_puts
|
||||
ret
|
||||
word_test_2ddiv:
|
||||
; push 84
|
||||
sub r12, 8
|
||||
mov qword [r12], 84
|
||||
; push 7
|
||||
sub r12, 8
|
||||
mov qword [r12], 7
|
||||
call word__2f
|
||||
call word_puts
|
||||
ret
|
||||
word_test_2dmod:
|
||||
; push 85
|
||||
sub r12, 8
|
||||
mov qword [r12], 85
|
||||
; push 7
|
||||
sub r12, 8
|
||||
mov qword [r12], 7
|
||||
call word__25
|
||||
call word_puts
|
||||
ret
|
||||
word_test_2ddrop:
|
||||
; push 10
|
||||
sub r12, 8
|
||||
mov qword [r12], 10
|
||||
; push 20
|
||||
sub r12, 8
|
||||
mov qword [r12], 20
|
||||
call word_drop
|
||||
call word_puts
|
||||
ret
|
||||
word_test_2ddup:
|
||||
; push 11
|
||||
sub r12, 8
|
||||
mov qword [r12], 11
|
||||
call word_dup
|
||||
call word__2b
|
||||
call word_puts
|
||||
ret
|
||||
word_test_2dswap:
|
||||
; push 2
|
||||
sub r12, 8
|
||||
mov qword [r12], 2
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
call word_swap
|
||||
call word__2d
|
||||
call word_puts
|
||||
ret
|
||||
word_test_2dstore:
|
||||
call word_mem_2dslot
|
||||
call word_dup
|
||||
; push 123
|
||||
sub r12, 8
|
||||
mov qword [r12], 123
|
||||
call word_swap
|
||||
call word__21
|
||||
call word__40
|
||||
call word_puts
|
||||
ret
|
||||
word_test_2dmmap:
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
; push 4096
|
||||
sub r12, 8
|
||||
mov qword [r12], 4096
|
||||
; push 3
|
||||
sub r12, 8
|
||||
mov qword [r12], 3
|
||||
; push 34
|
||||
sub r12, 8
|
||||
mov qword [r12], 34
|
||||
; push -1
|
||||
sub r12, 8
|
||||
mov qword [r12], -1
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
call word_mmap
|
||||
call word_dup
|
||||
; push 1337
|
||||
sub r12, 8
|
||||
mov qword [r12], 1337
|
||||
call word_swap
|
||||
call word__21
|
||||
call word_dup
|
||||
call word__40
|
||||
call word_puts
|
||||
; push 4096
|
||||
sub r12, 8
|
||||
mov qword [r12], 4096
|
||||
call word_munmap
|
||||
call word_drop
|
||||
ret
|
||||
word_test_2dmacro:
|
||||
; push 9
|
||||
sub r12, 8
|
||||
mov qword [r12], 9
|
||||
call word_dup
|
||||
call word__2a
|
||||
call word_puts
|
||||
call word_MAGIC
|
||||
call word_puts
|
||||
call word_add13
|
||||
call word_puts
|
||||
ret
|
||||
word_test_2dif:
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
call word__3d_3d
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
test rax, rax
|
||||
jz L_if_false_40
|
||||
; push 111
|
||||
sub r12, 8
|
||||
mov qword [r12], 111
|
||||
call word_puts
|
||||
jmp L_if_end_41
|
||||
L_if_false_40:
|
||||
; push 222
|
||||
sub r12, 8
|
||||
mov qword [r12], 222
|
||||
call word_puts
|
||||
L_if_end_41:
|
||||
ret
|
||||
word_test_2delse_2dif:
|
||||
; push 2
|
||||
sub r12, 8
|
||||
mov qword [r12], 2
|
||||
call word_dup
|
||||
; push 1
|
||||
sub r12, 8
|
||||
mov qword [r12], 1
|
||||
call word__3d_3d
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
test rax, rax
|
||||
jz L_if_false_42
|
||||
; push 50
|
||||
sub r12, 8
|
||||
mov qword [r12], 50
|
||||
call word_puts
|
||||
jmp L_if_end_43
|
||||
L_if_false_42:
|
||||
call word_dup
|
||||
; push 2
|
||||
sub r12, 8
|
||||
mov qword [r12], 2
|
||||
call word__3d_3d
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
test rax, rax
|
||||
jz L_if_false_44
|
||||
; push 60
|
||||
sub r12, 8
|
||||
mov qword [r12], 60
|
||||
call word_puts
|
||||
jmp L_if_end_45
|
||||
L_if_false_44:
|
||||
; push 70
|
||||
sub r12, 8
|
||||
mov qword [r12], 70
|
||||
call word_puts
|
||||
L_if_end_45:
|
||||
L_if_end_43:
|
||||
call word_drop
|
||||
ret
|
||||
word_test_2dfor:
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
cmp rax, 0
|
||||
jle L_for_end_47
|
||||
sub r13, 8
|
||||
mov [r13], rax
|
||||
L_for_loop_46:
|
||||
; push 1
|
||||
sub r12, 8
|
||||
mov qword [r12], 1
|
||||
call word__2b
|
||||
mov rax, [r13]
|
||||
dec rax
|
||||
mov [r13], rax
|
||||
jg L_for_loop_46
|
||||
add r13, 8
|
||||
L_for_end_47:
|
||||
call word_puts
|
||||
ret
|
||||
word_test_2dfor_2dzero:
|
||||
; push 123
|
||||
sub r12, 8
|
||||
mov qword [r12], 123
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
cmp rax, 0
|
||||
jle L_for_end_49
|
||||
sub r13, 8
|
||||
mov [r13], rax
|
||||
L_for_loop_48:
|
||||
call word_drop
|
||||
mov rax, [r13]
|
||||
dec rax
|
||||
mov [r13], rax
|
||||
jg L_for_loop_48
|
||||
add r13, 8
|
||||
L_for_end_49:
|
||||
call word_puts
|
||||
ret
|
||||
word_test_2dstruct:
|
||||
call word_mem_2dslot
|
||||
call word_dup
|
||||
; push 111
|
||||
sub r12, 8
|
||||
mov qword [r12], 111
|
||||
call word_swap
|
||||
call word_Point_2ex_21
|
||||
call word_dup
|
||||
; push 222
|
||||
sub r12, 8
|
||||
mov qword [r12], 222
|
||||
call word_swap
|
||||
call word_Point_2ey_21
|
||||
call word_dup
|
||||
call word_Point_2ex_40
|
||||
call word_puts
|
||||
call word_Point_2ey_40
|
||||
call word_puts
|
||||
call word_Point_2esize
|
||||
call word_puts
|
||||
ret
|
||||
word_test_2dcmp:
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
call word__3d_3d
|
||||
call word_puts
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
; push 4
|
||||
sub r12, 8
|
||||
mov qword [r12], 4
|
||||
call word__3d_3d
|
||||
call word_puts
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
; push 4
|
||||
sub r12, 8
|
||||
mov qword [r12], 4
|
||||
call word__21_3d
|
||||
call word_puts
|
||||
; push 4
|
||||
sub r12, 8
|
||||
mov qword [r12], 4
|
||||
; push 4
|
||||
sub r12, 8
|
||||
mov qword [r12], 4
|
||||
call word__21_3d
|
||||
call word_puts
|
||||
; push 3
|
||||
sub r12, 8
|
||||
mov qword [r12], 3
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
call word__3c
|
||||
call word_puts
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
; push 3
|
||||
sub r12, 8
|
||||
mov qword [r12], 3
|
||||
call word__3c
|
||||
call word_puts
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
; push 3
|
||||
sub r12, 8
|
||||
mov qword [r12], 3
|
||||
call word__3e
|
||||
call word_puts
|
||||
; push 3
|
||||
sub r12, 8
|
||||
mov qword [r12], 3
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
call word__3e
|
||||
call word_puts
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
call word__3c_3d
|
||||
call word_puts
|
||||
; push 6
|
||||
sub r12, 8
|
||||
mov qword [r12], 6
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
call word__3c_3d
|
||||
call word_puts
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
call word__3e_3d
|
||||
call word_puts
|
||||
; push 4
|
||||
sub r12, 8
|
||||
mov qword [r12], 4
|
||||
; push 5
|
||||
sub r12, 8
|
||||
mov qword [r12], 5
|
||||
call word__3e_3d
|
||||
call word_puts
|
||||
ret
|
||||
word_test_2dc_2dfn:
|
||||
; push 3
|
||||
sub r12, 8
|
||||
mov qword [r12], 3
|
||||
; push 7
|
||||
sub r12, 8
|
||||
mov qword [r12], 7
|
||||
call word_fancy_add
|
||||
call word_puts
|
||||
ret
|
||||
word_main:
|
||||
call word_test_2dadd
|
||||
call word_test_2dsub
|
||||
call word_test_2dmul
|
||||
call word_test_2ddiv
|
||||
call word_test_2dmod
|
||||
call word_test_2ddrop
|
||||
call word_test_2ddup
|
||||
call word_test_2dswap
|
||||
call word_test_2dstore
|
||||
call word_test_2dmmap
|
||||
call word_test_2dmacro
|
||||
call word_test_2dif
|
||||
call word_test_2delse_2dif
|
||||
call word_test_2dfor
|
||||
call word_test_2dfor_2dzero
|
||||
call word_test_2dcmp
|
||||
call word_test_2dstruct
|
||||
call word_test_2dc_2dfn
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
ret
|
||||
section .data
|
||||
data_start:
|
||||
data_end:
|
||||
section .bss
|
||||
align 16
|
||||
dstack: resb DSTK_BYTES
|
||||
dstack_top:
|
||||
align 16
|
||||
rstack: resb RSTK_BYTES
|
||||
rstack_top:
|
||||
align 16
|
||||
print_buf: resb PRINT_BUF_BYTES
|
||||
print_buf_end:
|
||||
BIN
build/test.o
BIN
build/test.o
Binary file not shown.
@@ -1,592 +0,0 @@
|
||||
section .text
|
||||
%define DSTK_BYTES 65536
|
||||
%define RSTK_BYTES 65536
|
||||
%define PRINT_BUF_BYTES 128
|
||||
global _start
|
||||
_start:
|
||||
; initialize data/return stack pointers
|
||||
lea r12, [rel dstack_top]
|
||||
mov r15, r12
|
||||
lea r13, [rel rstack_top]
|
||||
call word_main
|
||||
mov rax, 0
|
||||
cmp r12, r15
|
||||
je .no_exit_value
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
.no_exit_value:
|
||||
mov rdi, rax
|
||||
mov rax, 60
|
||||
syscall
|
||||
word_c_40:
|
||||
mov rax, [r12]
|
||||
movzx rax, byte [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_c_21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rbx], al
|
||||
ret
|
||||
ret
|
||||
word_r_40:
|
||||
mov rax, [r13]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_strlen:
|
||||
mov rax, [r12] ; addr
|
||||
mov rcx, [r12 + 8] ; len
|
||||
add r12, 16 ; pop len and addr
|
||||
mov [r12], rcx ; push len
|
||||
ret
|
||||
ret
|
||||
word_puts:
|
||||
; detects string if top is len>=0 and next is a pointer in [data_start, data_end]
|
||||
mov rax, [r12] ; len or int value
|
||||
mov rbx, [r12 + 8] ; possible address
|
||||
cmp rax, 0
|
||||
jl puts_print_int
|
||||
lea r8, [rel data_start]
|
||||
lea r9, [rel data_end]
|
||||
cmp rbx, r8
|
||||
jl puts_print_int
|
||||
cmp rbx, r9
|
||||
jge puts_print_int
|
||||
; treat as string: (addr below len)
|
||||
mov rdx, rax ; len
|
||||
mov rsi, rbx ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
test rdx, rdx
|
||||
jz puts_str_newline_only
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
syscall
|
||||
puts_str_newline_only:
|
||||
mov byte [rel print_buf], 10
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
lea rsi, [rel print_buf]
|
||||
mov rdx, 1
|
||||
syscall
|
||||
ret
|
||||
|
||||
puts_print_int:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, rax
|
||||
mov r8, 0
|
||||
cmp rbx, 0
|
||||
jge puts_abs
|
||||
neg rbx
|
||||
mov r8, 1
|
||||
puts_abs:
|
||||
lea rsi, [rel print_buf_end]
|
||||
mov rcx, 0
|
||||
mov r10, 10
|
||||
cmp rbx, 0
|
||||
jne puts_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '0'
|
||||
inc rcx
|
||||
jmp puts_sign
|
||||
puts_digits:
|
||||
puts_loop:
|
||||
xor rdx, rdx
|
||||
mov rax, rbx
|
||||
div r10
|
||||
add dl, '0'
|
||||
dec rsi
|
||||
mov [rsi], dl
|
||||
inc rcx
|
||||
mov rbx, rax
|
||||
test rbx, rbx
|
||||
jne puts_loop
|
||||
puts_sign:
|
||||
cmp r8, 0
|
||||
je puts_finish_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '-'
|
||||
inc rcx
|
||||
puts_finish_digits:
|
||||
mov byte [rsi + rcx], 10
|
||||
inc rcx
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
mov rdx, rcx
|
||||
mov r9, rsi
|
||||
mov rsi, r9
|
||||
syscall
|
||||
ret
|
||||
word_dup:
|
||||
mov rax, [r12]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_write_buf:
|
||||
mov rdx, [r12] ; len
|
||||
mov rsi, [r12 + 8] ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, 1 ; fd = stdout
|
||||
syscall
|
||||
ret
|
||||
ret
|
||||
word_drop:
|
||||
add r12, 8
|
||||
ret
|
||||
word_over:
|
||||
mov rax, [r12 + 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_swap:
|
||||
mov rax, [r12]
|
||||
mov rbx, [r12 + 8]
|
||||
mov [r12], rbx
|
||||
mov [r12 + 8], rax
|
||||
ret
|
||||
word_rot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rcx ; top = x1
|
||||
mov [r12 + 8], rax ; next = x3
|
||||
mov [r12 + 16], rbx ; third = x2
|
||||
ret
|
||||
word__2drot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rbx ; top = x2
|
||||
mov [r12 + 8], rcx ; next = x1
|
||||
mov [r12 + 16], rax ; third = x3
|
||||
ret
|
||||
word_nip:
|
||||
mov rax, [r12]
|
||||
add r12, 8 ; drop lower element
|
||||
mov [r12], rax ; keep original top
|
||||
ret
|
||||
word_tuck:
|
||||
mov rax, [r12] ; x2
|
||||
mov rbx, [r12 + 8] ; x1
|
||||
sub r12, 8 ; make room
|
||||
mov [r12], rax ; x2
|
||||
mov [r12 + 8], rbx ; x1
|
||||
mov [r12 + 16], rax ; x2
|
||||
ret
|
||||
word_2dup:
|
||||
mov rax, [r12] ; b
|
||||
mov rbx, [r12 + 8] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word_2drop:
|
||||
add r12, 16
|
||||
ret
|
||||
word_2swap:
|
||||
mov rax, [r12] ; d
|
||||
mov rbx, [r12 + 8] ; c
|
||||
mov rcx, [r12 + 16] ; b
|
||||
mov rdx, [r12 + 24] ; a
|
||||
mov [r12], rcx ; top = b
|
||||
mov [r12 + 8], rdx ; next = a
|
||||
mov [r12 + 16], rax ; third = d
|
||||
mov [r12 + 24], rbx ; fourth = c
|
||||
ret
|
||||
word_2over:
|
||||
mov rax, [r12 + 16] ; b
|
||||
mov rbx, [r12 + 24] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word__2b:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
add qword [r12], rax
|
||||
ret
|
||||
word__2d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub qword [r12], rax
|
||||
ret
|
||||
word__2a:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
imul qword [r12]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__2f:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__25:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rdx
|
||||
ret
|
||||
word__3d_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
sete bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__21_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setne bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setl bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setg bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setle bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setge bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__40:
|
||||
mov rax, [r12]
|
||||
mov rax, [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rax], rbx
|
||||
add r12, 8
|
||||
ret
|
||||
word_mmap:
|
||||
; Save rsp and align to 16 bytes for syscall ABI
|
||||
mov rax, rsp
|
||||
and rsp, -16
|
||||
mov rdi, [r12+40] ; addr
|
||||
mov rsi, [r12+32] ; length
|
||||
mov rdx, [r12+24] ; prot
|
||||
mov r10, [r12+16] ; flags
|
||||
mov r8, [r12+8] ; fd
|
||||
mov r9, [r12] ; offset
|
||||
add r12, 48 ; pop 6 args
|
||||
mov rax, 9 ; syscall: mmap
|
||||
syscall
|
||||
mov rsp, rax ; restore rsp
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push result
|
||||
ret
|
||||
ret
|
||||
word_munmap:
|
||||
mov rsi, [r12]
|
||||
add r12, 8
|
||||
mov rdi, [r12]
|
||||
mov rax, 11
|
||||
syscall
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_exit:
|
||||
mov rdi, [r12]
|
||||
add r12, 8
|
||||
mov rax, 60
|
||||
syscall
|
||||
ret
|
||||
word_and:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
and rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_or:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
or rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_not:
|
||||
mov rax, [r12]
|
||||
test rax, rax
|
||||
setz al
|
||||
movzx rax, al
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__3er:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub r13, 8
|
||||
mov [r13], rax
|
||||
ret
|
||||
word_r_3e:
|
||||
mov rax, [r13]
|
||||
add r13, 8
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rdrop:
|
||||
add r13, 8
|
||||
ret
|
||||
word_pick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rpick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r13 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_read_file:
|
||||
; stack: path_ptr (top), path_len (next)
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
add r12, 16 ; pop args
|
||||
|
||||
; open(path_ptr, O_RDONLY=0, mode=0)
|
||||
mov rax, 2 ; syscall: open
|
||||
mov rdi, rsi ; filename
|
||||
xor rsi, rsi ; flags = O_RDONLY
|
||||
xor rdx, rdx ; mode = 0
|
||||
syscall
|
||||
mov r10, rax ; save open() result
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r8, rax ; fd
|
||||
|
||||
; use lseek to determine file size: lseek(fd, 0, SEEK_END)
|
||||
mov rax, 8 ; syscall: lseek
|
||||
mov rdi, r8 ; fd
|
||||
xor rsi, rsi ; offset = 0
|
||||
mov rdx, 2 ; SEEK_END
|
||||
syscall
|
||||
mov r11, rax ; save lseek() result
|
||||
cmp rax, 0
|
||||
jl .close_fail_lseek
|
||||
mov rsi, rax ; length = size
|
||||
|
||||
; mmap(NULL, size, PROT_READ=1, MAP_PRIVATE=2, fd, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
; rsi already holds length
|
||||
mov rdx, 1 ; PROT_READ
|
||||
mov r10, 2 ; MAP_PRIVATE
|
||||
mov r8, r8 ; fd
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
mov rbx, rax ; addr
|
||||
mov r12, r12 ; (no-op, for debug)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r8 ; fd
|
||||
syscall
|
||||
cmp rbx, -4095
|
||||
jae .fail_mmap
|
||||
sub r12, 16
|
||||
mov [r12], rsi ; len (rsi held length across syscall)
|
||||
mov [r12 + 8], rbx ; addr
|
||||
ret
|
||||
|
||||
.close_fail_lseek:
|
||||
mov rax, 3
|
||||
mov rdi, r8
|
||||
syscall
|
||||
mov rax, r11 ; return lseek() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -1
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
mov rax, r10 ; return open() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -2
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
mov rax, -1 ; return mmap() error
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -3
|
||||
ret
|
||||
ret
|
||||
word_main:
|
||||
; push str_0
|
||||
sub r12, 8
|
||||
mov qword [r12], str_0
|
||||
; push 13
|
||||
sub r12, 8
|
||||
mov qword [r12], 13
|
||||
call word_swap
|
||||
call word_read_file
|
||||
call word_dup
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
call word__3e
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
test rax, rax
|
||||
jz L_if_false_0
|
||||
call word_write_buf
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
call word_exit
|
||||
L_if_false_0:
|
||||
call word_dup
|
||||
; push -2
|
||||
sub r12, 8
|
||||
mov qword [r12], -2
|
||||
call word__3d_3d
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
test rax, rax
|
||||
jz L_if_false_1
|
||||
call word_drop
|
||||
; push str_1
|
||||
sub r12, 8
|
||||
mov qword [r12], str_1
|
||||
; push 21
|
||||
sub r12, 8
|
||||
mov qword [r12], 21
|
||||
call word_puts
|
||||
call word_swap
|
||||
call word_puts
|
||||
call word_exit
|
||||
L_if_false_1:
|
||||
call word_dup
|
||||
; push -1
|
||||
sub r12, 8
|
||||
mov qword [r12], -1
|
||||
call word__3d_3d
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
test rax, rax
|
||||
jz L_if_false_2
|
||||
call word_drop
|
||||
; push str_2
|
||||
sub r12, 8
|
||||
mov qword [r12], str_2
|
||||
; push 22
|
||||
sub r12, 8
|
||||
mov qword [r12], 22
|
||||
call word_puts
|
||||
call word_swap
|
||||
call word_puts
|
||||
call word_exit
|
||||
L_if_false_2:
|
||||
call word_dup
|
||||
; push -3
|
||||
sub r12, 8
|
||||
mov qword [r12], -3
|
||||
call word__3d_3d
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
test rax, rax
|
||||
jz L_if_false_3
|
||||
call word_drop
|
||||
; push str_3
|
||||
sub r12, 8
|
||||
mov qword [r12], str_3
|
||||
; push 13
|
||||
sub r12, 8
|
||||
mov qword [r12], 13
|
||||
call word_puts
|
||||
call word_exit
|
||||
L_if_false_3:
|
||||
; push str_4
|
||||
sub r12, 8
|
||||
mov qword [r12], str_4
|
||||
; push 25
|
||||
sub r12, 8
|
||||
mov qword [r12], 25
|
||||
call word_puts
|
||||
call word_dup
|
||||
call word_exit
|
||||
ret
|
||||
section .data
|
||||
data_start:
|
||||
str_0: db 47, 101, 116, 99, 47, 104, 111, 115, 116, 110, 97, 109, 101, 0
|
||||
str_0_len equ 13
|
||||
str_1: db 111, 112, 101, 110, 40, 41, 32, 102, 97, 105, 108, 101, 100, 58, 32, 101, 114, 114, 110, 111, 61, 0
|
||||
str_1_len equ 21
|
||||
str_2: db 102, 115, 116, 97, 116, 40, 41, 32, 102, 97, 105, 108, 101, 100, 58, 32, 101, 114, 114, 110, 111, 61, 0
|
||||
str_2_len equ 22
|
||||
str_3: db 109, 109, 97, 112, 40, 41, 32, 102, 97, 105, 108, 101, 100, 0
|
||||
str_3_len equ 13
|
||||
str_4: db 117, 110, 107, 110, 111, 119, 110, 32, 114, 101, 97, 100, 95, 102, 105, 108, 101, 32, 102, 97, 105, 108, 117, 114, 101, 0
|
||||
str_4_len equ 25
|
||||
data_end:
|
||||
section .bss
|
||||
align 16
|
||||
dstack: resb DSTK_BYTES
|
||||
dstack_top:
|
||||
align 16
|
||||
rstack: resb RSTK_BYTES
|
||||
rstack_top:
|
||||
align 16
|
||||
print_buf: resb PRINT_BUF_BYTES
|
||||
print_buf_end:
|
||||
Binary file not shown.
@@ -1,616 +0,0 @@
|
||||
section .text
|
||||
%define DSTK_BYTES 65536
|
||||
%define RSTK_BYTES 65536
|
||||
%define PRINT_BUF_BYTES 128
|
||||
global _start
|
||||
_start:
|
||||
; initialize data/return stack pointers
|
||||
lea r12, [rel dstack_top]
|
||||
mov r15, r12
|
||||
lea r13, [rel rstack_top]
|
||||
call word_main
|
||||
mov rax, 0
|
||||
cmp r12, r15
|
||||
je .no_exit_value
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
.no_exit_value:
|
||||
mov rdi, rax
|
||||
mov rax, 60
|
||||
syscall
|
||||
word_c_40:
|
||||
mov rax, [r12]
|
||||
movzx rax, byte [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_c_21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rbx], al
|
||||
ret
|
||||
ret
|
||||
word_r_40:
|
||||
mov rax, [r13]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_dup:
|
||||
mov rax, [r12]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_drop:
|
||||
add r12, 8
|
||||
ret
|
||||
word_over:
|
||||
mov rax, [r12 + 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_swap:
|
||||
mov rax, [r12]
|
||||
mov rbx, [r12 + 8]
|
||||
mov [r12], rbx
|
||||
mov [r12 + 8], rax
|
||||
ret
|
||||
word_rot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rcx ; top = x1
|
||||
mov [r12 + 8], rax ; next = x3
|
||||
mov [r12 + 16], rbx ; third = x2
|
||||
ret
|
||||
word__2drot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rbx ; top = x2
|
||||
mov [r12 + 8], rcx ; next = x1
|
||||
mov [r12 + 16], rax ; third = x3
|
||||
ret
|
||||
word_nip:
|
||||
mov rax, [r12]
|
||||
add r12, 8 ; drop lower element
|
||||
mov [r12], rax ; keep original top
|
||||
ret
|
||||
word_tuck:
|
||||
mov rax, [r12] ; x2
|
||||
mov rbx, [r12 + 8] ; x1
|
||||
sub r12, 8 ; make room
|
||||
mov [r12], rax ; x2
|
||||
mov [r12 + 8], rbx ; x1
|
||||
mov [r12 + 16], rax ; x2
|
||||
ret
|
||||
word_2dup:
|
||||
mov rax, [r12] ; b
|
||||
mov rbx, [r12 + 8] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word_2drop:
|
||||
add r12, 16
|
||||
ret
|
||||
word_2swap:
|
||||
mov rax, [r12] ; d
|
||||
mov rbx, [r12 + 8] ; c
|
||||
mov rcx, [r12 + 16] ; b
|
||||
mov rdx, [r12 + 24] ; a
|
||||
mov [r12], rcx ; top = b
|
||||
mov [r12 + 8], rdx ; next = a
|
||||
mov [r12 + 16], rax ; third = d
|
||||
mov [r12 + 24], rbx ; fourth = c
|
||||
ret
|
||||
word_2over:
|
||||
mov rax, [r12 + 16] ; b
|
||||
mov rbx, [r12 + 24] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word__2b:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
add qword [r12], rax
|
||||
ret
|
||||
word__2d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub qword [r12], rax
|
||||
ret
|
||||
word__2a:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
imul qword [r12]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__2f:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__25:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rdx
|
||||
ret
|
||||
word__3d_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
sete bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__21_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setne bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setl bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setg bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setle bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setge bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__40:
|
||||
mov rax, [r12]
|
||||
mov rax, [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rax], rbx
|
||||
add r12, 8
|
||||
ret
|
||||
word_mmap:
|
||||
; Save rsp and align to 16 bytes for syscall ABI
|
||||
mov rax, rsp
|
||||
and rsp, -16
|
||||
mov rdi, [r12+40] ; addr
|
||||
mov rsi, [r12+32] ; length
|
||||
mov rdx, [r12+24] ; prot
|
||||
mov r10, [r12+16] ; flags
|
||||
mov r8, [r12+8] ; fd
|
||||
mov r9, [r12] ; offset
|
||||
add r12, 48 ; pop 6 args
|
||||
mov rax, 9 ; syscall: mmap
|
||||
syscall
|
||||
mov rsp, rax ; restore rsp
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push result
|
||||
ret
|
||||
ret
|
||||
word_munmap:
|
||||
mov rsi, [r12]
|
||||
add r12, 8
|
||||
mov rdi, [r12]
|
||||
mov rax, 11
|
||||
syscall
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_exit:
|
||||
mov rdi, [r12]
|
||||
add r12, 8
|
||||
mov rax, 60
|
||||
syscall
|
||||
ret
|
||||
word_and:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
and rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_or:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
or rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_not:
|
||||
mov rax, [r12]
|
||||
test rax, rax
|
||||
setz al
|
||||
movzx rax, al
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__3er:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub r13, 8
|
||||
mov [r13], rax
|
||||
ret
|
||||
word_r_3e:
|
||||
mov rax, [r13]
|
||||
add r13, 8
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rdrop:
|
||||
add r13, 8
|
||||
ret
|
||||
word_pick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rpick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r13 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_read_file:
|
||||
; stack: path_ptr (top), path_len (next)
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
add r12, 16 ; pop args
|
||||
|
||||
; open(path_ptr, O_RDONLY=0, mode=0)
|
||||
mov rax, 2 ; syscall: open
|
||||
mov rdi, rsi ; filename
|
||||
xor rsi, rsi ; flags = O_RDONLY
|
||||
xor rdx, rdx ; mode = 0
|
||||
syscall
|
||||
mov r10, rax ; save open() result
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r8, rax ; fd
|
||||
|
||||
; use lseek to determine file size: lseek(fd, 0, SEEK_END)
|
||||
mov rax, 8 ; syscall: lseek
|
||||
mov rdi, r8 ; fd
|
||||
xor rsi, rsi ; offset = 0
|
||||
mov rdx, 2 ; SEEK_END
|
||||
syscall
|
||||
mov r11, rax ; save lseek() result
|
||||
cmp rax, 0
|
||||
jl .close_fail_lseek
|
||||
mov rsi, rax ; length = size
|
||||
|
||||
; mmap(NULL, size, PROT_READ=1, MAP_PRIVATE=2, fd, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
; rsi already holds length
|
||||
mov rdx, 1 ; PROT_READ
|
||||
mov r10, 2 ; MAP_PRIVATE
|
||||
mov r8, r8 ; fd
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
mov rbx, rax ; addr
|
||||
mov r12, r12 ; (no-op, for debug)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r8 ; fd
|
||||
syscall
|
||||
cmp rbx, -4095
|
||||
jae .fail_mmap
|
||||
sub r12, 16
|
||||
mov [r12], rsi ; len (rsi held length across syscall)
|
||||
mov [r12 + 8], rbx ; addr
|
||||
ret
|
||||
|
||||
.close_fail_lseek:
|
||||
mov rax, 3
|
||||
mov rdi, r8
|
||||
syscall
|
||||
mov rax, r11 ; return lseek() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -1
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
mov rax, r10 ; return open() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -2
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
mov rax, -1 ; return mmap() error
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -3
|
||||
ret
|
||||
ret
|
||||
word_write_file:
|
||||
; stack: path_ptr (top), path_len, buf_ptr, buf_len
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
mov r15, [r12 + 16] ; buf_ptr (save in callee-saved r15)
|
||||
mov r13, [r12 + 24] ; buf_len (save in callee-saved r13)
|
||||
add r12, 32 ; pop 4 args (we saved buf info)
|
||||
|
||||
; open(path_ptr, O_WRONLY|O_CREAT|O_TRUNC, 0666)
|
||||
mov rdi, rsi ; filename
|
||||
mov rsi, 577 ; flags = O_WRONLY|O_CREAT|O_TRUNC
|
||||
mov rdx, 438 ; mode = 0o666
|
||||
mov rax, 2 ; syscall: open
|
||||
syscall
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r9, rax ; save fd
|
||||
|
||||
; write(fd, buf_ptr, buf_len) -- use preserved r15/r13 which survive syscalls
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, r9 ; fd
|
||||
mov rsi, r15 ; buf_ptr
|
||||
mov rdx, r13 ; buf_len
|
||||
syscall
|
||||
mov r10, rax ; save write result
|
||||
cmp r10, 0
|
||||
jl .fail_write
|
||||
|
||||
; close(fd)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r9
|
||||
syscall
|
||||
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_write:
|
||||
mov rax, 3
|
||||
mov rdi, r9
|
||||
syscall
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_read_stdin:
|
||||
; stack: max_len
|
||||
mov r14, [r12] ; max_len
|
||||
add r12, 8 ; pop max_len
|
||||
|
||||
; mmap(NULL, max_len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
mov rsi, r14 ; length
|
||||
mov rdx, 3 ; PROT_READ|PROT_WRITE
|
||||
mov r10, 34 ; MAP_PRIVATE|MAP_ANONYMOUS
|
||||
mov r8, -1 ; fd = -1
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
cmp rax, -4095
|
||||
jae .fail_mmap
|
||||
mov rbx, rax ; buffer addr
|
||||
xor r9, r9 ; bytes_read = 0
|
||||
|
||||
.read_loop:
|
||||
mov rax, 0 ; syscall: read
|
||||
mov rdi, 0 ; fd = stdin
|
||||
lea rsi, [rbx + r9] ; buf + offset
|
||||
mov rdx, r14
|
||||
sub rdx, r9 ; remaining = max_len - bytes_read
|
||||
syscall
|
||||
cmp rax, 0
|
||||
je .done_read
|
||||
js .read_error
|
||||
add r9, rax
|
||||
jl .read_loop
|
||||
|
||||
.done_read:
|
||||
; push len (rcx) then addr (rbx)
|
||||
cmp r9, r14
|
||||
je .done_no_null
|
||||
mov byte [rbx + r9], 0
|
||||
.done_no_null:
|
||||
sub r12, 16
|
||||
mov [r12], r9
|
||||
mov [r12 + 8], rbx
|
||||
ret
|
||||
|
||||
.read_error:
|
||||
; return negative errno in rax, addr = 0
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], 0
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
sub r12, 16
|
||||
mov qword [r12], -1
|
||||
mov qword [r12 + 8], 0
|
||||
ret
|
||||
ret
|
||||
word_puts:
|
||||
; detects string if top is len>=0 and next is a pointer in [data_start, data_end]
|
||||
mov rax, [r12] ; len or int value
|
||||
mov rbx, [r12 + 8] ; possible address
|
||||
cmp rax, 0
|
||||
jl puts_print_int
|
||||
lea r8, [rel data_start]
|
||||
lea r9, [rel data_end]
|
||||
cmp rbx, r8
|
||||
jl puts_print_int
|
||||
cmp rbx, r9
|
||||
jge puts_print_int
|
||||
; treat as string: (addr below len)
|
||||
mov rdx, rax ; len
|
||||
mov rsi, rbx ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
test rdx, rdx
|
||||
jz puts_str_newline_only
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
syscall
|
||||
puts_str_newline_only:
|
||||
mov byte [rel print_buf], 10
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
lea rsi, [rel print_buf]
|
||||
mov rdx, 1
|
||||
syscall
|
||||
ret
|
||||
puts_print_int:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, rax
|
||||
mov r8, 0
|
||||
cmp rbx, 0
|
||||
jge puts_abs
|
||||
neg rbx
|
||||
mov r8, 1
|
||||
puts_abs:
|
||||
lea rsi, [rel print_buf_end]
|
||||
mov rcx, 0
|
||||
mov r10, 10
|
||||
cmp rbx, 0
|
||||
jne puts_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '0'
|
||||
inc rcx
|
||||
jmp puts_sign
|
||||
puts_digits:
|
||||
puts_loop:
|
||||
xor rdx, rdx
|
||||
mov rax, rbx
|
||||
div r10
|
||||
add dl, '0'
|
||||
dec rsi
|
||||
mov [rsi], dl
|
||||
inc rcx
|
||||
mov rbx, rax
|
||||
test rbx, rbx
|
||||
jne puts_loop
|
||||
puts_sign:
|
||||
cmp r8, 0
|
||||
je puts_finish_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '-'
|
||||
inc rcx
|
||||
puts_finish_digits:
|
||||
mov byte [rsi + rcx], 10
|
||||
inc rcx
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
mov rdx, rcx
|
||||
mov r9, rsi
|
||||
mov rsi, r9
|
||||
syscall
|
||||
ret
|
||||
word_write_buf:
|
||||
mov rdx, [r12] ; len
|
||||
mov rsi, [r12 + 8] ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, 1 ; fd = stdout
|
||||
syscall
|
||||
ret
|
||||
ret
|
||||
word_main:
|
||||
; push 1024
|
||||
sub r12, 8
|
||||
mov qword [r12], 1024
|
||||
call word_read_stdin
|
||||
call word_dup
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
call word__3e
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
test rax, rax
|
||||
jz L_if_false_0
|
||||
call word_write_buf
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
call word_exit
|
||||
L_if_false_0:
|
||||
; push str_0
|
||||
sub r12, 8
|
||||
mov qword [r12], str_0
|
||||
; push 17
|
||||
sub r12, 8
|
||||
mov qword [r12], 17
|
||||
call word_puts
|
||||
call word_exit
|
||||
ret
|
||||
section .data
|
||||
data_start:
|
||||
str_0: db 114, 101, 97, 100, 95, 115, 116, 100, 105, 110, 32, 102, 97, 105, 108, 101, 100, 0
|
||||
str_0_len equ 17
|
||||
data_end:
|
||||
section .bss
|
||||
align 16
|
||||
dstack: resb DSTK_BYTES
|
||||
dstack_top:
|
||||
align 16
|
||||
rstack: resb RSTK_BYTES
|
||||
rstack_top:
|
||||
align 16
|
||||
print_buf: resb PRINT_BUF_BYTES
|
||||
print_buf_end:
|
||||
Binary file not shown.
@@ -1,555 +0,0 @@
|
||||
section .text
|
||||
%define DSTK_BYTES 65536
|
||||
%define RSTK_BYTES 65536
|
||||
%define PRINT_BUF_BYTES 128
|
||||
global _start
|
||||
_start:
|
||||
; initialize data/return stack pointers
|
||||
lea r12, [rel dstack_top]
|
||||
mov r15, r12
|
||||
lea r13, [rel rstack_top]
|
||||
call word_main
|
||||
mov rax, 0
|
||||
cmp r12, r15
|
||||
je .no_exit_value
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
.no_exit_value:
|
||||
mov rdi, rax
|
||||
mov rax, 60
|
||||
syscall
|
||||
word_c_40:
|
||||
mov rax, [r12]
|
||||
movzx rax, byte [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_c_21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rbx], al
|
||||
ret
|
||||
ret
|
||||
word_r_40:
|
||||
mov rax, [r13]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_strlen:
|
||||
mov rax, [r12] ; addr
|
||||
mov rcx, [r12 + 8] ; len
|
||||
add r12, 16 ; pop len and addr
|
||||
mov [r12], rcx ; push len
|
||||
ret
|
||||
ret
|
||||
word_puts:
|
||||
; detects string if top is len>=0 and next is a pointer in [data_start, data_end]
|
||||
mov rax, [r12] ; len or int value
|
||||
mov rbx, [r12 + 8] ; possible address
|
||||
cmp rax, 0
|
||||
jl puts_print_int
|
||||
lea r8, [rel data_start]
|
||||
lea r9, [rel data_end]
|
||||
cmp rbx, r8
|
||||
jl puts_print_int
|
||||
cmp rbx, r9
|
||||
jge puts_print_int
|
||||
; treat as string: (addr below len)
|
||||
mov rdx, rax ; len
|
||||
mov rsi, rbx ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
test rdx, rdx
|
||||
jz puts_str_newline_only
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
syscall
|
||||
puts_str_newline_only:
|
||||
mov byte [rel print_buf], 10
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
lea rsi, [rel print_buf]
|
||||
mov rdx, 1
|
||||
syscall
|
||||
ret
|
||||
|
||||
puts_print_int:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, rax
|
||||
mov r8, 0
|
||||
cmp rbx, 0
|
||||
jge puts_abs
|
||||
neg rbx
|
||||
mov r8, 1
|
||||
puts_abs:
|
||||
lea rsi, [rel print_buf_end]
|
||||
mov rcx, 0
|
||||
mov r10, 10
|
||||
cmp rbx, 0
|
||||
jne puts_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '0'
|
||||
inc rcx
|
||||
jmp puts_sign
|
||||
puts_digits:
|
||||
puts_loop:
|
||||
xor rdx, rdx
|
||||
mov rax, rbx
|
||||
div r10
|
||||
add dl, '0'
|
||||
dec rsi
|
||||
mov [rsi], dl
|
||||
inc rcx
|
||||
mov rbx, rax
|
||||
test rbx, rbx
|
||||
jne puts_loop
|
||||
puts_sign:
|
||||
cmp r8, 0
|
||||
je puts_finish_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '-'
|
||||
inc rcx
|
||||
puts_finish_digits:
|
||||
mov byte [rsi + rcx], 10
|
||||
inc rcx
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
mov rdx, rcx
|
||||
mov r9, rsi
|
||||
mov rsi, r9
|
||||
syscall
|
||||
ret
|
||||
word_dup:
|
||||
mov rax, [r12]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_write_buf:
|
||||
mov rdx, [r12] ; len
|
||||
mov rsi, [r12 + 8] ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, 1 ; fd = stdout
|
||||
syscall
|
||||
ret
|
||||
ret
|
||||
word_drop:
|
||||
add r12, 8
|
||||
ret
|
||||
word_over:
|
||||
mov rax, [r12 + 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_swap:
|
||||
mov rax, [r12]
|
||||
mov rbx, [r12 + 8]
|
||||
mov [r12], rbx
|
||||
mov [r12 + 8], rax
|
||||
ret
|
||||
word_rot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rcx ; top = x1
|
||||
mov [r12 + 8], rax ; next = x3
|
||||
mov [r12 + 16], rbx ; third = x2
|
||||
ret
|
||||
word__2drot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rbx ; top = x2
|
||||
mov [r12 + 8], rcx ; next = x1
|
||||
mov [r12 + 16], rax ; third = x3
|
||||
ret
|
||||
word_nip:
|
||||
mov rax, [r12]
|
||||
add r12, 8 ; drop lower element
|
||||
mov [r12], rax ; keep original top
|
||||
ret
|
||||
word_tuck:
|
||||
mov rax, [r12] ; x2
|
||||
mov rbx, [r12 + 8] ; x1
|
||||
sub r12, 8 ; make room
|
||||
mov [r12], rax ; x2
|
||||
mov [r12 + 8], rbx ; x1
|
||||
mov [r12 + 16], rax ; x2
|
||||
ret
|
||||
word_2dup:
|
||||
mov rax, [r12] ; b
|
||||
mov rbx, [r12 + 8] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word_2drop:
|
||||
add r12, 16
|
||||
ret
|
||||
word_2swap:
|
||||
mov rax, [r12] ; d
|
||||
mov rbx, [r12 + 8] ; c
|
||||
mov rcx, [r12 + 16] ; b
|
||||
mov rdx, [r12 + 24] ; a
|
||||
mov [r12], rcx ; top = b
|
||||
mov [r12 + 8], rdx ; next = a
|
||||
mov [r12 + 16], rax ; third = d
|
||||
mov [r12 + 24], rbx ; fourth = c
|
||||
ret
|
||||
word_2over:
|
||||
mov rax, [r12 + 16] ; b
|
||||
mov rbx, [r12 + 24] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word__2b:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
add qword [r12], rax
|
||||
ret
|
||||
word__2d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub qword [r12], rax
|
||||
ret
|
||||
word__2a:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
imul qword [r12]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__2f:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__25:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rdx
|
||||
ret
|
||||
word__3d_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
sete bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__21_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setne bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setl bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setg bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setle bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setge bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__40:
|
||||
mov rax, [r12]
|
||||
mov rax, [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rax], rbx
|
||||
add r12, 8
|
||||
ret
|
||||
word_mmap:
|
||||
; Save rsp and align to 16 bytes for syscall ABI
|
||||
mov rax, rsp
|
||||
and rsp, -16
|
||||
mov rdi, [r12+40] ; addr
|
||||
mov rsi, [r12+32] ; length
|
||||
mov rdx, [r12+24] ; prot
|
||||
mov r10, [r12+16] ; flags
|
||||
mov r8, [r12+8] ; fd
|
||||
mov r9, [r12] ; offset
|
||||
add r12, 48 ; pop 6 args
|
||||
mov rax, 9 ; syscall: mmap
|
||||
syscall
|
||||
mov rsp, rax ; restore rsp
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push result
|
||||
ret
|
||||
ret
|
||||
word_munmap:
|
||||
mov rsi, [r12]
|
||||
add r12, 8
|
||||
mov rdi, [r12]
|
||||
mov rax, 11
|
||||
syscall
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_exit:
|
||||
mov rdi, [r12]
|
||||
add r12, 8
|
||||
mov rax, 60
|
||||
syscall
|
||||
ret
|
||||
word_and:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
and rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_or:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
or rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_not:
|
||||
mov rax, [r12]
|
||||
test rax, rax
|
||||
setz al
|
||||
movzx rax, al
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__3er:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub r13, 8
|
||||
mov [r13], rax
|
||||
ret
|
||||
word_r_3e:
|
||||
mov rax, [r13]
|
||||
add r13, 8
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rdrop:
|
||||
add r13, 8
|
||||
ret
|
||||
word_pick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rpick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r13 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_read_file:
|
||||
; stack: path_ptr (top), path_len (next)
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
add r12, 16 ; pop args
|
||||
|
||||
; open(path_ptr, O_RDONLY=0, mode=0)
|
||||
mov rax, 2 ; syscall: open
|
||||
mov rdi, rsi ; filename
|
||||
xor rsi, rsi ; flags = O_RDONLY
|
||||
xor rdx, rdx ; mode = 0
|
||||
syscall
|
||||
mov r10, rax ; save open() result
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r8, rax ; fd
|
||||
|
||||
; use lseek to determine file size: lseek(fd, 0, SEEK_END)
|
||||
mov rax, 8 ; syscall: lseek
|
||||
mov rdi, r8 ; fd
|
||||
xor rsi, rsi ; offset = 0
|
||||
mov rdx, 2 ; SEEK_END
|
||||
syscall
|
||||
mov r11, rax ; save lseek() result
|
||||
cmp rax, 0
|
||||
jl .close_fail_lseek
|
||||
mov rsi, rax ; length = size
|
||||
|
||||
; mmap(NULL, size, PROT_READ=1, MAP_PRIVATE=2, fd, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
; rsi already holds length
|
||||
mov rdx, 1 ; PROT_READ
|
||||
mov r10, 2 ; MAP_PRIVATE
|
||||
mov r8, r8 ; fd
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
mov rbx, rax ; addr
|
||||
mov r12, r12 ; (no-op, for debug)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r8 ; fd
|
||||
syscall
|
||||
cmp rbx, -4095
|
||||
jae .fail_mmap
|
||||
sub r12, 16
|
||||
mov [r12], rsi ; len (rsi held length across syscall)
|
||||
mov [r12 + 8], rbx ; addr
|
||||
ret
|
||||
|
||||
.close_fail_lseek:
|
||||
mov rax, 3
|
||||
mov rdi, r8
|
||||
syscall
|
||||
mov rax, r11 ; return lseek() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -1
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
mov rax, r10 ; return open() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -2
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
mov rax, -1 ; return mmap() error
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -3
|
||||
ret
|
||||
ret
|
||||
word_write_file:
|
||||
; stack: path_ptr (top), path_len, buf_ptr, buf_len
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
mov r14, [r12 + 16] ; buf_len
|
||||
mov rbx, [r12 + 24] ; buf_ptr
|
||||
add r12, 32 ; pop 4 args
|
||||
|
||||
; preserve buffer info in callee-saved regs (syscall clobbers rcx/r11)
|
||||
mov r15, r14 ; r15 = buf_ptr
|
||||
mov r13, rbx ; r13 = buf_len
|
||||
|
||||
; open(path_ptr, O_WRONLY|O_CREAT|O_TRUNC, 0666)
|
||||
mov rdi, rsi ; filename
|
||||
mov rsi, 577 ; flags = O_WRONLY(1)|O_CREAT(64)|O_TRUNC(512)
|
||||
mov rdx, 438 ; mode = 0o666
|
||||
mov rax, 2 ; syscall: open
|
||||
syscall
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r9, rax ; save fd
|
||||
|
||||
; write(fd, buf_ptr, buf_len) -- use r15/r13 which survive syscalls
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, r9 ; fd
|
||||
mov rsi, r15 ; buf_ptr
|
||||
mov rdx, r13 ; buf_len
|
||||
syscall
|
||||
mov r10, rax ; save write result
|
||||
cmp r10, 0
|
||||
jl .fail_write
|
||||
|
||||
; close(fd)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r9
|
||||
syscall
|
||||
|
||||
sub r12, 8
|
||||
mov [r12], r10 ; return bytes_written
|
||||
ret
|
||||
|
||||
.fail_write:
|
||||
mov rax, 3 ; close before returning error
|
||||
mov rdi, r9
|
||||
syscall
|
||||
sub r12, 8
|
||||
mov [r12], r10 ; return negative errno from write
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
sub r12, 8
|
||||
mov [r12], rax ; return negative errno from open
|
||||
ret
|
||||
ret
|
||||
word_main:
|
||||
; push str_0
|
||||
sub r12, 8
|
||||
mov qword [r12], str_0
|
||||
; push 26
|
||||
sub r12, 8
|
||||
mov qword [r12], 26
|
||||
call word_write_buf
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
ret
|
||||
section .data
|
||||
data_start:
|
||||
str_0: db 104, 101, 108, 108, 111, 32, 102, 114, 111, 109, 32, 119, 114, 105, 116, 101, 95, 98, 117, 102, 32, 116, 101, 115, 116, 10, 0
|
||||
str_0_len equ 26
|
||||
data_end:
|
||||
section .bss
|
||||
align 16
|
||||
dstack: resb DSTK_BYTES
|
||||
dstack_top:
|
||||
align 16
|
||||
rstack: resb RSTK_BYTES
|
||||
rstack_top:
|
||||
align 16
|
||||
print_buf: resb PRINT_BUF_BYTES
|
||||
print_buf_end:
|
||||
Binary file not shown.
@@ -1,593 +0,0 @@
|
||||
section .text
|
||||
%define DSTK_BYTES 65536
|
||||
%define RSTK_BYTES 65536
|
||||
%define PRINT_BUF_BYTES 128
|
||||
global _start
|
||||
_start:
|
||||
; initialize data/return stack pointers
|
||||
lea r12, [rel dstack_top]
|
||||
mov r15, r12
|
||||
lea r13, [rel rstack_top]
|
||||
call word_main
|
||||
mov rax, 0
|
||||
cmp r12, r15
|
||||
je .no_exit_value
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
.no_exit_value:
|
||||
mov rdi, rax
|
||||
mov rax, 60
|
||||
syscall
|
||||
word_c_40:
|
||||
mov rax, [r12]
|
||||
movzx rax, byte [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_c_21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rbx], al
|
||||
ret
|
||||
ret
|
||||
word_r_40:
|
||||
mov rax, [r13]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_strlen:
|
||||
mov rax, [r12] ; addr
|
||||
mov rcx, [r12 + 8] ; len
|
||||
add r12, 16 ; pop len and addr
|
||||
mov [r12], rcx ; push len
|
||||
ret
|
||||
ret
|
||||
word_puts:
|
||||
; detects string if top is len>=0 and next is a pointer in [data_start, data_end]
|
||||
mov rax, [r12] ; len or int value
|
||||
mov rbx, [r12 + 8] ; possible address
|
||||
cmp rax, 0
|
||||
jl puts_print_int
|
||||
lea r8, [rel data_start]
|
||||
lea r9, [rel data_end]
|
||||
cmp rbx, r8
|
||||
jl puts_print_int
|
||||
cmp rbx, r9
|
||||
jge puts_print_int
|
||||
; treat as string: (addr below len)
|
||||
mov rdx, rax ; len
|
||||
mov rsi, rbx ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
test rdx, rdx
|
||||
jz puts_str_newline_only
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
syscall
|
||||
puts_str_newline_only:
|
||||
mov byte [rel print_buf], 10
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
lea rsi, [rel print_buf]
|
||||
mov rdx, 1
|
||||
syscall
|
||||
ret
|
||||
|
||||
puts_print_int:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, rax
|
||||
mov r8, 0
|
||||
cmp rbx, 0
|
||||
jge puts_abs
|
||||
neg rbx
|
||||
mov r8, 1
|
||||
puts_abs:
|
||||
lea rsi, [rel print_buf_end]
|
||||
mov rcx, 0
|
||||
mov r10, 10
|
||||
cmp rbx, 0
|
||||
jne puts_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '0'
|
||||
inc rcx
|
||||
jmp puts_sign
|
||||
puts_digits:
|
||||
puts_loop:
|
||||
xor rdx, rdx
|
||||
mov rax, rbx
|
||||
div r10
|
||||
add dl, '0'
|
||||
dec rsi
|
||||
mov [rsi], dl
|
||||
inc rcx
|
||||
mov rbx, rax
|
||||
test rbx, rbx
|
||||
jne puts_loop
|
||||
puts_sign:
|
||||
cmp r8, 0
|
||||
je puts_finish_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '-'
|
||||
inc rcx
|
||||
puts_finish_digits:
|
||||
mov byte [rsi + rcx], 10
|
||||
inc rcx
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
mov rdx, rcx
|
||||
mov r9, rsi
|
||||
mov rsi, r9
|
||||
syscall
|
||||
ret
|
||||
word_dup:
|
||||
mov rax, [r12]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_write_buf:
|
||||
mov rdx, [r12] ; len
|
||||
mov rsi, [r12 + 8] ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, 1 ; fd = stdout
|
||||
syscall
|
||||
ret
|
||||
ret
|
||||
word_drop:
|
||||
add r12, 8
|
||||
ret
|
||||
word_over:
|
||||
mov rax, [r12 + 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_swap:
|
||||
mov rax, [r12]
|
||||
mov rbx, [r12 + 8]
|
||||
mov [r12], rbx
|
||||
mov [r12 + 8], rax
|
||||
ret
|
||||
word_rot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rcx ; top = x1
|
||||
mov [r12 + 8], rax ; next = x3
|
||||
mov [r12 + 16], rbx ; third = x2
|
||||
ret
|
||||
word__2drot:
|
||||
mov rax, [r12] ; x3
|
||||
mov rbx, [r12 + 8] ; x2
|
||||
mov rcx, [r12 + 16] ; x1
|
||||
mov [r12], rbx ; top = x2
|
||||
mov [r12 + 8], rcx ; next = x1
|
||||
mov [r12 + 16], rax ; third = x3
|
||||
ret
|
||||
word_nip:
|
||||
mov rax, [r12]
|
||||
add r12, 8 ; drop lower element
|
||||
mov [r12], rax ; keep original top
|
||||
ret
|
||||
word_tuck:
|
||||
mov rax, [r12] ; x2
|
||||
mov rbx, [r12 + 8] ; x1
|
||||
sub r12, 8 ; make room
|
||||
mov [r12], rax ; x2
|
||||
mov [r12 + 8], rbx ; x1
|
||||
mov [r12 + 16], rax ; x2
|
||||
ret
|
||||
word_2dup:
|
||||
mov rax, [r12] ; b
|
||||
mov rbx, [r12 + 8] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word_2drop:
|
||||
add r12, 16
|
||||
ret
|
||||
word_2swap:
|
||||
mov rax, [r12] ; d
|
||||
mov rbx, [r12 + 8] ; c
|
||||
mov rcx, [r12 + 16] ; b
|
||||
mov rdx, [r12 + 24] ; a
|
||||
mov [r12], rcx ; top = b
|
||||
mov [r12 + 8], rdx ; next = a
|
||||
mov [r12 + 16], rax ; third = d
|
||||
mov [r12 + 24], rbx ; fourth = c
|
||||
ret
|
||||
word_2over:
|
||||
mov rax, [r12 + 16] ; b
|
||||
mov rbx, [r12 + 24] ; a
|
||||
sub r12, 8
|
||||
mov [r12], rbx ; push a
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push b
|
||||
ret
|
||||
word__2b:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
add qword [r12], rax
|
||||
ret
|
||||
word__2d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub qword [r12], rax
|
||||
ret
|
||||
word__2a:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
imul qword [r12]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__2f:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__25:
|
||||
mov rbx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12]
|
||||
cqo
|
||||
idiv rbx
|
||||
mov [r12], rdx
|
||||
ret
|
||||
word__3d_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
sete bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__21_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setne bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setl bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setg bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3c_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setle bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__3e_3d:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
cmp rbx, rax
|
||||
mov rbx, 0
|
||||
setge bl
|
||||
mov [r12], rbx
|
||||
ret
|
||||
word__40:
|
||||
mov rax, [r12]
|
||||
mov rax, [rax]
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__21:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
mov [rax], rbx
|
||||
add r12, 8
|
||||
ret
|
||||
word_mmap:
|
||||
; Save rsp and align to 16 bytes for syscall ABI
|
||||
mov rax, rsp
|
||||
and rsp, -16
|
||||
mov rdi, [r12+40] ; addr
|
||||
mov rsi, [r12+32] ; length
|
||||
mov rdx, [r12+24] ; prot
|
||||
mov r10, [r12+16] ; flags
|
||||
mov r8, [r12+8] ; fd
|
||||
mov r9, [r12] ; offset
|
||||
add r12, 48 ; pop 6 args
|
||||
mov rax, 9 ; syscall: mmap
|
||||
syscall
|
||||
mov rsp, rax ; restore rsp
|
||||
sub r12, 8
|
||||
mov [r12], rax ; push result
|
||||
ret
|
||||
ret
|
||||
word_munmap:
|
||||
mov rsi, [r12]
|
||||
add r12, 8
|
||||
mov rdi, [r12]
|
||||
mov rax, 11
|
||||
syscall
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_exit:
|
||||
mov rdi, [r12]
|
||||
add r12, 8
|
||||
mov rax, 60
|
||||
syscall
|
||||
ret
|
||||
word_and:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
and rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_or:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, [r12]
|
||||
test rax, rax
|
||||
setz cl
|
||||
test rbx, rbx
|
||||
setz dl
|
||||
movzx rcx, cl
|
||||
movzx rdx, dl
|
||||
or rcx, rdx
|
||||
mov [r12], rcx
|
||||
ret
|
||||
word_not:
|
||||
mov rax, [r12]
|
||||
test rax, rax
|
||||
setz al
|
||||
movzx rax, al
|
||||
mov [r12], rax
|
||||
ret
|
||||
word__3er:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
sub r13, 8
|
||||
mov [r13], rax
|
||||
ret
|
||||
word_r_3e:
|
||||
mov rax, [r13]
|
||||
add r13, 8
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rdrop:
|
||||
add r13, 8
|
||||
ret
|
||||
word_pick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r12 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_rpick:
|
||||
mov rcx, [r12]
|
||||
add r12, 8
|
||||
mov rax, [r13 + rcx * 8]
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
word_read_file:
|
||||
; stack: path_ptr (top), path_len (next)
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
add r12, 16 ; pop args
|
||||
|
||||
; open(path_ptr, O_RDONLY=0, mode=0)
|
||||
mov rax, 2 ; syscall: open
|
||||
mov rdi, rsi ; filename
|
||||
xor rsi, rsi ; flags = O_RDONLY
|
||||
xor rdx, rdx ; mode = 0
|
||||
syscall
|
||||
mov r10, rax ; save open() result
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r8, rax ; fd
|
||||
|
||||
; use lseek to determine file size: lseek(fd, 0, SEEK_END)
|
||||
mov rax, 8 ; syscall: lseek
|
||||
mov rdi, r8 ; fd
|
||||
xor rsi, rsi ; offset = 0
|
||||
mov rdx, 2 ; SEEK_END
|
||||
syscall
|
||||
mov r11, rax ; save lseek() result
|
||||
cmp rax, 0
|
||||
jl .close_fail_lseek
|
||||
mov rsi, rax ; length = size
|
||||
|
||||
; mmap(NULL, size, PROT_READ=1, MAP_PRIVATE=2, fd, 0)
|
||||
mov rax, 9 ; syscall: mmap
|
||||
xor rdi, rdi ; addr = NULL
|
||||
; rsi already holds length
|
||||
mov rdx, 1 ; PROT_READ
|
||||
mov r10, 2 ; MAP_PRIVATE
|
||||
mov r8, r8 ; fd
|
||||
xor r9, r9 ; offset = 0
|
||||
syscall
|
||||
mov rbx, rax ; addr
|
||||
mov r12, r12 ; (no-op, for debug)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r8 ; fd
|
||||
syscall
|
||||
cmp rbx, -4095
|
||||
jae .fail_mmap
|
||||
sub r12, 16
|
||||
mov [r12], rsi ; len (rsi held length across syscall)
|
||||
mov [r12 + 8], rbx ; addr
|
||||
ret
|
||||
|
||||
.close_fail_lseek:
|
||||
mov rax, 3
|
||||
mov rdi, r8
|
||||
syscall
|
||||
mov rax, r11 ; return lseek() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -1
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
mov rax, r10 ; return open() error code
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -2
|
||||
ret
|
||||
|
||||
.fail_mmap:
|
||||
mov rax, -1 ; return mmap() error
|
||||
sub r12, 16
|
||||
mov [r12], rax
|
||||
mov qword [r12 + 8], -3
|
||||
ret
|
||||
ret
|
||||
word_write_file:
|
||||
; stack: path_ptr (top), path_len, buf_ptr, buf_len
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
mov r15, [r12 + 16] ; buf_ptr (save in callee-saved r15)
|
||||
mov r13, [r12 + 24] ; buf_len (save in callee-saved r13)
|
||||
add r12, 32 ; pop 4 args (we saved buf info)
|
||||
|
||||
; open(path_ptr, O_WRONLY|O_CREAT|O_TRUNC, 0666)
|
||||
mov rdi, rsi ; filename
|
||||
mov rsi, 577 ; flags = O_WRONLY|O_CREAT|O_TRUNC
|
||||
mov rdx, 438 ; mode = 0o666
|
||||
mov rax, 2 ; syscall: open
|
||||
syscall
|
||||
cmp rax, 0
|
||||
jl .fail_open
|
||||
mov r9, rax ; save fd
|
||||
|
||||
; write(fd, buf_ptr, buf_len) -- use preserved r15/r13 which survive syscalls
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, r9 ; fd
|
||||
mov rsi, r15 ; buf_ptr
|
||||
mov rdx, r13 ; buf_len
|
||||
syscall
|
||||
mov r10, rax ; save write result
|
||||
cmp r10, 0
|
||||
jl .fail_write
|
||||
|
||||
; close(fd)
|
||||
mov rax, 3 ; syscall: close
|
||||
mov rdi, r9
|
||||
syscall
|
||||
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_write:
|
||||
mov rax, 3
|
||||
mov rdi, r9
|
||||
syscall
|
||||
sub r12, 8
|
||||
mov [r12], r10
|
||||
ret
|
||||
|
||||
.fail_open:
|
||||
sub r12, 8
|
||||
mov [r12], rax
|
||||
ret
|
||||
ret
|
||||
word_main:
|
||||
; push str_0
|
||||
sub r12, 8
|
||||
mov qword [r12], str_0
|
||||
; push 27
|
||||
sub r12, 8
|
||||
mov qword [r12], 27
|
||||
call word_swap
|
||||
; push str_1
|
||||
sub r12, 8
|
||||
mov qword [r12], str_1
|
||||
; push 22
|
||||
sub r12, 8
|
||||
mov qword [r12], 22
|
||||
call word_swap
|
||||
call word_write_file
|
||||
call word_dup
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
call word__3e
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
test rax, rax
|
||||
jz L_if_false_0
|
||||
; push str_2
|
||||
sub r12, 8
|
||||
mov qword [r12], str_2
|
||||
; push 13
|
||||
sub r12, 8
|
||||
mov qword [r12], 13
|
||||
call word_puts
|
||||
call word_puts
|
||||
; push 0
|
||||
sub r12, 8
|
||||
mov qword [r12], 0
|
||||
call word_exit
|
||||
L_if_false_0:
|
||||
; push str_3
|
||||
sub r12, 8
|
||||
mov qword [r12], str_3
|
||||
; push 19
|
||||
sub r12, 8
|
||||
mov qword [r12], 19
|
||||
call word_puts
|
||||
call word_puts
|
||||
call word_exit
|
||||
ret
|
||||
section .data
|
||||
data_start:
|
||||
str_0: db 104, 101, 108, 108, 111, 32, 102, 114, 111, 109, 32, 119, 114, 105, 116, 101, 95, 102, 105, 108, 101, 32, 116, 101, 115, 116, 10, 0
|
||||
str_0_len equ 27
|
||||
str_1: db 47, 116, 109, 112, 47, 108, 50, 95, 116, 101, 115, 116, 95, 119, 114, 105, 116, 101, 46, 116, 120, 116, 0
|
||||
str_1_len equ 22
|
||||
str_2: db 119, 114, 111, 116, 101, 32, 98, 121, 116, 101, 115, 58, 32, 0
|
||||
str_2_len equ 13
|
||||
str_3: db 119, 114, 105, 116, 101, 32, 102, 97, 105, 108, 101, 100, 32, 101, 114, 114, 110, 111, 61, 0
|
||||
str_3_len equ 19
|
||||
data_end:
|
||||
section .bss
|
||||
align 16
|
||||
dstack: resb DSTK_BYTES
|
||||
dstack_top:
|
||||
align 16
|
||||
rstack: resb RSTK_BYTES
|
||||
rstack_top:
|
||||
align 16
|
||||
print_buf: resb PRINT_BUF_BYTES
|
||||
print_buf_end:
|
||||
Binary file not shown.
4
main.sl
4
main.sl
@@ -4,10 +4,10 @@ import fn.sl
|
||||
|
||||
: main
|
||||
2 40 +
|
||||
puts
|
||||
puti cr
|
||||
extend-syntax
|
||||
foo(1, 2)
|
||||
puts
|
||||
puti cr
|
||||
0
|
||||
;
|
||||
|
||||
|
||||
126
stdlib/io.sl
126
stdlib/io.sl
@@ -1,14 +1,13 @@
|
||||
|
||||
# L2 IO Primitives
|
||||
|
||||
# : read_file ( path_ptr path_len -- len addr | 0 0 )
|
||||
# : read_file ( path_addr path_len -- addr len | 0 0 )
|
||||
# Reads the file at the given path (pointer+length, not null-terminated),
|
||||
# returns (len addr) of mapped file, or (0 0) on error.
|
||||
# returns (addr len) of mapped file, or (0 0) on error.
|
||||
|
||||
:asm read_file {
|
||||
; stack: path_ptr (top), path_len (next)
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
; stack: path_addr (NOS), path_len (TOS)
|
||||
mov rdx, [r12] ; path_len
|
||||
mov rsi, [r12 + 8] ; path_addr
|
||||
add r12, 16 ; pop args
|
||||
|
||||
; open(path_ptr, O_RDONLY=0, mode=0)
|
||||
@@ -82,11 +81,11 @@
|
||||
|
||||
# : write_file ( path_ptr path_len buf_ptr buf_len -- bytes_written | neg_errno )
|
||||
:asm write_file {
|
||||
; stack: path_ptr (top), path_len, buf_ptr, buf_len
|
||||
mov rsi, [r12] ; path_ptr
|
||||
mov rdx, [r12 + 8] ; path_len
|
||||
mov r15, [r12 + 16] ; buf_ptr (save in callee-saved r15)
|
||||
mov r13, [r12 + 24] ; buf_len (save in callee-saved r13)
|
||||
; stack: path_addr, path_len, buf_addr, buf_len (TOS)
|
||||
mov r13, [r12] ; buf_len
|
||||
mov r15, [r12 + 8] ; buf_addr
|
||||
mov rdx, [r12 + 16] ; path_len
|
||||
mov rsi, [r12 + 24] ; path_addr
|
||||
add r12, 32 ; pop 4 args (we saved buf info)
|
||||
|
||||
; open(path_ptr, O_WRONLY|O_CREAT|O_TRUNC, 0666)
|
||||
@@ -133,7 +132,7 @@
|
||||
}
|
||||
;
|
||||
|
||||
# : read_stdin ( max_len -- len addr | neg_errno 0 )
|
||||
# : read_stdin ( max_len -- addr len | neg_errno 0 )
|
||||
:asm read_stdin {
|
||||
; stack: max_len
|
||||
mov r14, [r12] ; max_len
|
||||
@@ -192,28 +191,28 @@
|
||||
}
|
||||
;
|
||||
|
||||
:asm puts {
|
||||
:asm print {
|
||||
; detects string if top is len>=0 and next is a pointer in [data_start, data_end]
|
||||
mov rax, [r12] ; len or int value
|
||||
mov rbx, [r12 + 8] ; possible address
|
||||
cmp rax, 0
|
||||
jl puts_print_int
|
||||
jl .print_int
|
||||
lea r8, [rel data_start]
|
||||
lea r9, [rel data_end]
|
||||
cmp rbx, r8
|
||||
jl puts_print_int
|
||||
jl .print_int
|
||||
cmp rbx, r9
|
||||
jge puts_print_int
|
||||
jge .print_int
|
||||
; treat as string: (addr below len)
|
||||
mov rdx, rax ; len
|
||||
mov rsi, rbx ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
test rdx, rdx
|
||||
jz puts_str_newline_only
|
||||
jz .str_newline_only
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
syscall
|
||||
puts_str_newline_only:
|
||||
.str_newline_only:
|
||||
mov byte [rel print_buf], 10
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
@@ -221,27 +220,27 @@ puts_str_newline_only:
|
||||
mov rdx, 1
|
||||
syscall
|
||||
ret
|
||||
puts_print_int:
|
||||
.print_int:
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
mov rbx, rax
|
||||
mov r8, 0
|
||||
cmp rbx, 0
|
||||
jge puts_abs
|
||||
jge .abs
|
||||
neg rbx
|
||||
mov r8, 1
|
||||
puts_abs:
|
||||
.abs:
|
||||
lea rsi, [rel print_buf_end]
|
||||
mov rcx, 0
|
||||
mov r10, 10
|
||||
cmp rbx, 0
|
||||
jne puts_digits
|
||||
jne .digits
|
||||
dec rsi
|
||||
mov byte [rsi], '0'
|
||||
inc rcx
|
||||
jmp puts_sign
|
||||
puts_digits:
|
||||
puts_loop:
|
||||
jmp .sign
|
||||
.digits:
|
||||
.loop:
|
||||
xor rdx, rdx
|
||||
mov rax, rbx
|
||||
div r10
|
||||
@@ -251,14 +250,14 @@ puts_loop:
|
||||
inc rcx
|
||||
mov rbx, rax
|
||||
test rbx, rbx
|
||||
jne puts_loop
|
||||
puts_sign:
|
||||
jne .loop
|
||||
.sign:
|
||||
cmp r8, 0
|
||||
je puts_finish_digits
|
||||
je .finish_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '-'
|
||||
inc rcx
|
||||
puts_finish_digits:
|
||||
.finish_digits:
|
||||
mov byte [rsi + rcx], 10
|
||||
inc rcx
|
||||
mov rax, 1
|
||||
@@ -270,8 +269,9 @@ puts_finish_digits:
|
||||
}
|
||||
;
|
||||
|
||||
# : write_buf ( len addr -- )
|
||||
# : write_buf ( addr len -- )
|
||||
:asm write_buf {
|
||||
; data_start (trigger string_mode in compile-time VM)
|
||||
mov rdx, [r12] ; len
|
||||
mov rsi, [r12 + 8] ; addr
|
||||
add r12, 16 ; pop len + addr
|
||||
@@ -280,4 +280,68 @@ puts_finish_digits:
|
||||
syscall
|
||||
ret
|
||||
}
|
||||
;
|
||||
;
|
||||
|
||||
# : putc ( char -- )
|
||||
:asm putc {
|
||||
mov rax, [r12]
|
||||
add r12, 8
|
||||
lea rsi, [rel print_buf]
|
||||
mov [rsi], al
|
||||
mov rax, 1
|
||||
mov rdi, 1
|
||||
mov rdx, 1
|
||||
syscall
|
||||
ret
|
||||
}
|
||||
;
|
||||
|
||||
# : puti ( int -- )
|
||||
:asm puti {
|
||||
mov rax, [r12] ; get int
|
||||
add r12, 8 ; pop
|
||||
mov rbx, rax
|
||||
mov r8, 0 ; sign flag
|
||||
cmp rbx, 0
|
||||
jge .puti_pos
|
||||
neg rbx
|
||||
mov r8, 1
|
||||
.puti_pos:
|
||||
lea rsi, [rel print_buf_end]
|
||||
mov rcx, 0
|
||||
mov r10, 10
|
||||
cmp rbx, 0
|
||||
jne .puti_digits
|
||||
dec rsi
|
||||
mov byte [rsi], '0'
|
||||
inc rcx
|
||||
jmp .puti_sign
|
||||
.puti_digits:
|
||||
.puti_loop:
|
||||
xor rdx, rdx
|
||||
mov rax, rbx
|
||||
div r10
|
||||
add dl, '0'
|
||||
dec rsi
|
||||
mov [rsi], dl
|
||||
inc rcx
|
||||
mov rbx, rax
|
||||
test rbx, rbx
|
||||
jne .puti_loop
|
||||
.puti_sign:
|
||||
cmp r8, 0
|
||||
je .puti_done
|
||||
dec rsi
|
||||
mov byte [rsi], '-'
|
||||
inc rcx
|
||||
.puti_done:
|
||||
mov rax, 1 ; syscall: write
|
||||
mov rdi, 1 ; fd: stdout
|
||||
mov rdx, rcx ; length
|
||||
syscall
|
||||
ret
|
||||
}
|
||||
;
|
||||
|
||||
: cr 10 putc ;
|
||||
: puts write_buf cr ;
|
||||
|
||||
8
str.sl
8
str.sl
@@ -1,8 +0,0 @@
|
||||
import stdlib/stdlib.sl
|
||||
import stdlib/io.sl
|
||||
|
||||
: main
|
||||
"str.sl" swap read_file
|
||||
write_buf
|
||||
0
|
||||
;
|
||||
4
t.sl
4
t.sl
@@ -4,13 +4,13 @@ import fn.sl
|
||||
|
||||
fn foo(int a, int b){
|
||||
1
|
||||
puts
|
||||
puti cr
|
||||
return a b +;
|
||||
}
|
||||
|
||||
: main
|
||||
extend-syntax
|
||||
foo(3, 2)
|
||||
puts
|
||||
puti cr
|
||||
0
|
||||
;
|
||||
72
test.sl
72
test.sl
@@ -40,41 +40,41 @@ fn fancy_add(int a, int b){
|
||||
}
|
||||
|
||||
: test-add
|
||||
5 7 + puts
|
||||
5 7 + puti cr
|
||||
;
|
||||
|
||||
: test-sub
|
||||
10 3 - puts
|
||||
10 3 - puti cr
|
||||
;
|
||||
|
||||
: test-mul
|
||||
6 7 * puts
|
||||
6 7 * puti cr
|
||||
;
|
||||
|
||||
: test-div
|
||||
84 7 / puts
|
||||
84 7 / puti cr
|
||||
;
|
||||
|
||||
: test-mod
|
||||
85 7 % puts
|
||||
85 7 % puti cr
|
||||
;
|
||||
|
||||
: test-drop
|
||||
10 20 drop puts
|
||||
10 20 drop puti cr
|
||||
;
|
||||
|
||||
: test-dup
|
||||
11 dup + puts
|
||||
11 dup + puti cr
|
||||
;
|
||||
|
||||
: test-swap
|
||||
2 5 swap - puts
|
||||
2 5 swap - puti cr
|
||||
;
|
||||
|
||||
: test-store
|
||||
mem-slot dup
|
||||
123 swap !
|
||||
@ puts
|
||||
@ puti cr
|
||||
;
|
||||
|
||||
|
||||
@@ -89,33 +89,33 @@ fn fancy_add(int a, int b){
|
||||
dup
|
||||
1337 swap !
|
||||
dup
|
||||
@ puts
|
||||
@ puti cr
|
||||
4096 munmap drop
|
||||
;
|
||||
|
||||
: test-macro
|
||||
9 square puts
|
||||
MAGIC puts
|
||||
add13 puts
|
||||
9 square puti cr
|
||||
MAGIC puti cr
|
||||
add13 puti cr
|
||||
;
|
||||
|
||||
: test-if
|
||||
5 5 == if
|
||||
111 puts
|
||||
111 puti cr
|
||||
else
|
||||
222 puts
|
||||
222 puti cr
|
||||
then
|
||||
;
|
||||
|
||||
: test-else-if
|
||||
2
|
||||
dup 1 == if
|
||||
50 puts
|
||||
50 puti cr
|
||||
else
|
||||
dup 2 == if
|
||||
60 puts
|
||||
60 puti cr
|
||||
else
|
||||
70 puts
|
||||
70 puti cr
|
||||
then
|
||||
then
|
||||
drop
|
||||
@@ -126,7 +126,7 @@ fn fancy_add(int a, int b){
|
||||
5 for
|
||||
1 +
|
||||
next
|
||||
puts
|
||||
puti cr
|
||||
;
|
||||
|
||||
: test-for-zero
|
||||
@@ -134,38 +134,38 @@ fn fancy_add(int a, int b){
|
||||
0 for
|
||||
drop
|
||||
next
|
||||
puts
|
||||
puti cr
|
||||
;
|
||||
|
||||
: test-struct
|
||||
mem-slot
|
||||
dup 111 swap Point.x!
|
||||
dup 222 swap Point.y!
|
||||
dup Point.x@ puts
|
||||
Point.y@ puts
|
||||
Point.size puts
|
||||
dup Point.x@ puti cr
|
||||
Point.y@ puti cr
|
||||
Point.size puti cr
|
||||
;
|
||||
|
||||
: test-cmp
|
||||
5 5 == puts
|
||||
5 4 == puts
|
||||
5 4 != puts
|
||||
4 4 != puts
|
||||
3 5 < puts
|
||||
5 3 < puts
|
||||
5 3 > puts
|
||||
3 5 > puts
|
||||
5 5 <= puts
|
||||
6 5 <= puts
|
||||
5 5 >= puts
|
||||
4 5 >= puts
|
||||
5 5 == puti cr
|
||||
5 4 == puti cr
|
||||
5 4 != puti cr
|
||||
4 4 != puti cr
|
||||
3 5 < puti cr
|
||||
5 3 < puti cr
|
||||
5 3 > puti cr
|
||||
3 5 > puti cr
|
||||
5 5 <= puti cr
|
||||
6 5 <= puti cr
|
||||
5 5 >= puti cr
|
||||
4 5 >= puti cr
|
||||
;
|
||||
|
||||
: test-c-fn
|
||||
3
|
||||
7
|
||||
fancy_add()
|
||||
puts
|
||||
puti cr
|
||||
;
|
||||
|
||||
: main
|
||||
|
||||
@@ -2,9 +2,8 @@ import stdlib/stdlib.sl
|
||||
import stdlib/io.sl
|
||||
|
||||
: main
|
||||
"/etc/hostname" # (len addr)
|
||||
swap # (addr len)
|
||||
read_file # (file_len file_addr)
|
||||
"/etc/hostname" # (addr len)
|
||||
read_file # (file_addr file_len)
|
||||
dup 0 > if # if file_len > 0, success
|
||||
write_buf # print file contents (file_len file_addr)
|
||||
0
|
||||
@@ -13,13 +12,13 @@ import stdlib/io.sl
|
||||
dup -2 == if # open() failed
|
||||
drop
|
||||
"open() failed: errno=" puts
|
||||
swap puts
|
||||
swap puti cr
|
||||
exit
|
||||
then
|
||||
dup -1 == if # fstat() failed
|
||||
drop
|
||||
"fstat() failed: errno=" puts
|
||||
swap puts
|
||||
swap puti cr
|
||||
exit
|
||||
then
|
||||
dup -3 == if # mmap() failed
|
||||
|
||||
@@ -3,7 +3,7 @@ import stdlib/io.sl
|
||||
|
||||
: main
|
||||
1024
|
||||
read_stdin # returns (len addr)
|
||||
read_stdin # returns (addr len)
|
||||
dup 0 > if
|
||||
write_buf
|
||||
0 exit
|
||||
|
||||
@@ -2,18 +2,16 @@ import stdlib/stdlib.sl
|
||||
import stdlib/io.sl
|
||||
|
||||
: main
|
||||
"hello from write_file test\n" # push buf (len addr)
|
||||
swap # -> (addr len) = buf_ptr buf_len
|
||||
"/tmp/l2_test_write.txt" # push path (len addr)
|
||||
swap # -> (addr len) = path_ptr path_len
|
||||
"/tmp/l2_test_write.txt" # push path (addr len)
|
||||
"hello from write_file test\n" # push buf (addr len)
|
||||
write_file
|
||||
dup 0 > if
|
||||
"wrote bytes: " puts
|
||||
puts
|
||||
puti cr
|
||||
0
|
||||
exit
|
||||
then
|
||||
"write failed errno=" puts
|
||||
puts
|
||||
puti cr
|
||||
exit
|
||||
;
|
||||
;
|
||||
@@ -36,10 +36,10 @@ import {ROOT / 'fn.sl'}
|
||||
|
||||
: main
|
||||
2 40 +
|
||||
puts
|
||||
puti cr
|
||||
extend-syntax
|
||||
foo(1, 2)
|
||||
puts
|
||||
puti cr
|
||||
0
|
||||
;
|
||||
|
||||
@@ -60,9 +60,9 @@ import {ROOT / 'stdlib/io.sl'}
|
||||
5 for
|
||||
1 +
|
||||
next
|
||||
puts
|
||||
5 5 == puts
|
||||
5 4 == puts
|
||||
puti cr
|
||||
5 5 == puti cr
|
||||
5 4 == puti cr
|
||||
0
|
||||
;
|
||||
""",
|
||||
@@ -96,7 +96,7 @@ compile-only
|
||||
|
||||
: main
|
||||
emit-overridden
|
||||
puts
|
||||
puti cr
|
||||
0
|
||||
;
|
||||
""",
|
||||
|
||||
Reference in New Issue
Block a user