updates to io.sl

This commit is contained in:
IgorCielniak
2025-12-19 20:23:26 +01:00
parent 8b5ccf4edc
commit 002b36f89c
40 changed files with 152 additions and 9091 deletions

2
a.sl
View File

@@ -4,4 +4,4 @@ import stdlib/io.sl
: main : main
"hello world" puts "hello world" puts
; ;
compile-time main compile-time main

View File

@@ -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/a.o

Binary file not shown.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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:

Binary file not shown.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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:

Binary file not shown.

View File

@@ -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.

View File

@@ -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:

BIN
build/t.o

Binary file not shown.

View File

@@ -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:

Binary file not shown.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -4,10 +4,10 @@ import fn.sl
: main : main
2 40 + 2 40 +
puts puti cr
extend-syntax extend-syntax
foo(1, 2) foo(1, 2)
puts puti cr
0 0
; ;

View File

@@ -1,14 +1,13 @@
# L2 IO Primitives # 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), # 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 { :asm read_file {
; stack: path_ptr (top), path_len (next) ; stack: path_addr (NOS), path_len (TOS)
mov rsi, [r12] ; path_ptr mov rdx, [r12] ; path_len
mov rdx, [r12 + 8] ; path_len mov rsi, [r12 + 8] ; path_addr
add r12, 16 ; pop args add r12, 16 ; pop args
; open(path_ptr, O_RDONLY=0, mode=0) ; 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 ) # : write_file ( path_ptr path_len buf_ptr buf_len -- bytes_written | neg_errno )
:asm write_file { :asm write_file {
; stack: path_ptr (top), path_len, buf_ptr, buf_len ; stack: path_addr, path_len, buf_addr, buf_len (TOS)
mov rsi, [r12] ; path_ptr mov r13, [r12] ; buf_len
mov rdx, [r12 + 8] ; path_len mov r15, [r12 + 8] ; buf_addr
mov r15, [r12 + 16] ; buf_ptr (save in callee-saved r15) mov rdx, [r12 + 16] ; path_len
mov r13, [r12 + 24] ; buf_len (save in callee-saved r13) mov rsi, [r12 + 24] ; path_addr
add r12, 32 ; pop 4 args (we saved buf info) add r12, 32 ; pop 4 args (we saved buf info)
; open(path_ptr, O_WRONLY|O_CREAT|O_TRUNC, 0666) ; 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 { :asm read_stdin {
; stack: max_len ; stack: max_len
mov r14, [r12] ; 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] ; 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 rax, [r12] ; len or int value
mov rbx, [r12 + 8] ; possible address mov rbx, [r12 + 8] ; possible address
cmp rax, 0 cmp rax, 0
jl puts_print_int jl .print_int
lea r8, [rel data_start] lea r8, [rel data_start]
lea r9, [rel data_end] lea r9, [rel data_end]
cmp rbx, r8 cmp rbx, r8
jl puts_print_int jl .print_int
cmp rbx, r9 cmp rbx, r9
jge puts_print_int jge .print_int
; treat as string: (addr below len) ; treat as string: (addr below len)
mov rdx, rax ; len mov rdx, rax ; len
mov rsi, rbx ; addr mov rsi, rbx ; addr
add r12, 16 ; pop len + addr add r12, 16 ; pop len + addr
test rdx, rdx test rdx, rdx
jz puts_str_newline_only jz .str_newline_only
mov rax, 1 mov rax, 1
mov rdi, 1 mov rdi, 1
syscall syscall
puts_str_newline_only: .str_newline_only:
mov byte [rel print_buf], 10 mov byte [rel print_buf], 10
mov rax, 1 mov rax, 1
mov rdi, 1 mov rdi, 1
@@ -221,27 +220,27 @@ puts_str_newline_only:
mov rdx, 1 mov rdx, 1
syscall syscall
ret ret
puts_print_int: .print_int:
mov rax, [r12] mov rax, [r12]
add r12, 8 add r12, 8
mov rbx, rax mov rbx, rax
mov r8, 0 mov r8, 0
cmp rbx, 0 cmp rbx, 0
jge puts_abs jge .abs
neg rbx neg rbx
mov r8, 1 mov r8, 1
puts_abs: .abs:
lea rsi, [rel print_buf_end] lea rsi, [rel print_buf_end]
mov rcx, 0 mov rcx, 0
mov r10, 10 mov r10, 10
cmp rbx, 0 cmp rbx, 0
jne puts_digits jne .digits
dec rsi dec rsi
mov byte [rsi], '0' mov byte [rsi], '0'
inc rcx inc rcx
jmp puts_sign jmp .sign
puts_digits: .digits:
puts_loop: .loop:
xor rdx, rdx xor rdx, rdx
mov rax, rbx mov rax, rbx
div r10 div r10
@@ -251,14 +250,14 @@ puts_loop:
inc rcx inc rcx
mov rbx, rax mov rbx, rax
test rbx, rbx test rbx, rbx
jne puts_loop jne .loop
puts_sign: .sign:
cmp r8, 0 cmp r8, 0
je puts_finish_digits je .finish_digits
dec rsi dec rsi
mov byte [rsi], '-' mov byte [rsi], '-'
inc rcx inc rcx
puts_finish_digits: .finish_digits:
mov byte [rsi + rcx], 10 mov byte [rsi + rcx], 10
inc rcx inc rcx
mov rax, 1 mov rax, 1
@@ -270,8 +269,9 @@ puts_finish_digits:
} }
; ;
# : write_buf ( len addr -- ) # : write_buf ( addr len -- )
:asm write_buf { :asm write_buf {
; data_start (trigger string_mode in compile-time VM)
mov rdx, [r12] ; len mov rdx, [r12] ; len
mov rsi, [r12 + 8] ; addr mov rsi, [r12 + 8] ; addr
add r12, 16 ; pop len + addr add r12, 16 ; pop len + addr
@@ -280,4 +280,68 @@ puts_finish_digits:
syscall syscall
ret 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
View File

@@ -1,8 +0,0 @@
import stdlib/stdlib.sl
import stdlib/io.sl
: main
"str.sl" swap read_file
write_buf
0
;

4
t.sl
View File

@@ -4,13 +4,13 @@ import fn.sl
fn foo(int a, int b){ fn foo(int a, int b){
1 1
puts puti cr
return a b +; return a b +;
} }
: main : main
extend-syntax extend-syntax
foo(3, 2) foo(3, 2)
puts puti cr
0 0
; ;

72
test.sl
View File

@@ -40,41 +40,41 @@ fn fancy_add(int a, int b){
} }
: test-add : test-add
5 7 + puts 5 7 + puti cr
; ;
: test-sub : test-sub
10 3 - puts 10 3 - puti cr
; ;
: test-mul : test-mul
6 7 * puts 6 7 * puti cr
; ;
: test-div : test-div
84 7 / puts 84 7 / puti cr
; ;
: test-mod : test-mod
85 7 % puts 85 7 % puti cr
; ;
: test-drop : test-drop
10 20 drop puts 10 20 drop puti cr
; ;
: test-dup : test-dup
11 dup + puts 11 dup + puti cr
; ;
: test-swap : test-swap
2 5 swap - puts 2 5 swap - puti cr
; ;
: test-store : test-store
mem-slot dup mem-slot dup
123 swap ! 123 swap !
@ puts @ puti cr
; ;
@@ -89,33 +89,33 @@ fn fancy_add(int a, int b){
dup dup
1337 swap ! 1337 swap !
dup dup
@ puts @ puti cr
4096 munmap drop 4096 munmap drop
; ;
: test-macro : test-macro
9 square puts 9 square puti cr
MAGIC puts MAGIC puti cr
add13 puts add13 puti cr
; ;
: test-if : test-if
5 5 == if 5 5 == if
111 puts 111 puti cr
else else
222 puts 222 puti cr
then then
; ;
: test-else-if : test-else-if
2 2
dup 1 == if dup 1 == if
50 puts 50 puti cr
else else
dup 2 == if dup 2 == if
60 puts 60 puti cr
else else
70 puts 70 puti cr
then then
then then
drop drop
@@ -126,7 +126,7 @@ fn fancy_add(int a, int b){
5 for 5 for
1 + 1 +
next next
puts puti cr
; ;
: test-for-zero : test-for-zero
@@ -134,38 +134,38 @@ fn fancy_add(int a, int b){
0 for 0 for
drop drop
next next
puts puti cr
; ;
: test-struct : test-struct
mem-slot mem-slot
dup 111 swap Point.x! dup 111 swap Point.x!
dup 222 swap Point.y! dup 222 swap Point.y!
dup Point.x@ puts dup Point.x@ puti cr
Point.y@ puts Point.y@ puti cr
Point.size puts Point.size puti cr
; ;
: test-cmp : test-cmp
5 5 == puts 5 5 == puti cr
5 4 == puts 5 4 == puti cr
5 4 != puts 5 4 != puti cr
4 4 != puts 4 4 != puti cr
3 5 < puts 3 5 < puti cr
5 3 < puts 5 3 < puti cr
5 3 > puts 5 3 > puti cr
3 5 > puts 3 5 > puti cr
5 5 <= puts 5 5 <= puti cr
6 5 <= puts 6 5 <= puti cr
5 5 >= puts 5 5 >= puti cr
4 5 >= puts 4 5 >= puti cr
; ;
: test-c-fn : test-c-fn
3 3
7 7
fancy_add() fancy_add()
puts puti cr
; ;
: main : main

View File

@@ -2,9 +2,8 @@ import stdlib/stdlib.sl
import stdlib/io.sl import stdlib/io.sl
: main : main
"/etc/hostname" # (len addr) "/etc/hostname" # (addr len)
swap # (addr len) read_file # (file_addr file_len)
read_file # (file_len file_addr)
dup 0 > if # if file_len > 0, success dup 0 > if # if file_len > 0, success
write_buf # print file contents (file_len file_addr) write_buf # print file contents (file_len file_addr)
0 0
@@ -13,13 +12,13 @@ import stdlib/io.sl
dup -2 == if # open() failed dup -2 == if # open() failed
drop drop
"open() failed: errno=" puts "open() failed: errno=" puts
swap puts swap puti cr
exit exit
then then
dup -1 == if # fstat() failed dup -1 == if # fstat() failed
drop drop
"fstat() failed: errno=" puts "fstat() failed: errno=" puts
swap puts swap puti cr
exit exit
then then
dup -3 == if # mmap() failed dup -3 == if # mmap() failed

View File

@@ -3,7 +3,7 @@ import stdlib/io.sl
: main : main
1024 1024
read_stdin # returns (len addr) read_stdin # returns (addr len)
dup 0 > if dup 0 > if
write_buf write_buf
0 exit 0 exit

View File

@@ -2,18 +2,16 @@ import stdlib/stdlib.sl
import stdlib/io.sl import stdlib/io.sl
: main : main
"hello from write_file test\n" # push buf (len addr) "/tmp/l2_test_write.txt" # push path (addr len)
swap # -> (addr len) = buf_ptr buf_len "hello from write_file test\n" # push buf (addr len)
"/tmp/l2_test_write.txt" # push path (len addr)
swap # -> (addr len) = path_ptr path_len
write_file write_file
dup 0 > if dup 0 > if
"wrote bytes: " puts "wrote bytes: " puts
puts puti cr
0 0
exit exit
then then
"write failed errno=" puts "write failed errno=" puts
puts puti cr
exit exit
; ;

View File

@@ -36,10 +36,10 @@ import {ROOT / 'fn.sl'}
: main : main
2 40 + 2 40 +
puts puti cr
extend-syntax extend-syntax
foo(1, 2) foo(1, 2)
puts puti cr
0 0
; ;
@@ -60,9 +60,9 @@ import {ROOT / 'stdlib/io.sl'}
5 for 5 for
1 + 1 +
next next
puts puti cr
5 5 == puts 5 5 == puti cr
5 4 == puts 5 4 == puti cr
0 0
; ;
""", """,
@@ -96,7 +96,7 @@ compile-only
: main : main
emit-overridden emit-overridden
puts puti cr
0 0
; ;
""", """,