write_file
This commit is contained in:
2
a.sl
2
a.sl
@@ -1,4 +1,4 @@
|
|||||||
import stdlib.sl
|
import stdlib/stdlib.sl
|
||||||
|
|
||||||
: main
|
: main
|
||||||
"hello world" puts
|
"hello world" puts
|
||||||
|
|||||||
13
build/a.asm
13
build/a.asm
@@ -18,6 +18,19 @@ _start:
|
|||||||
mov rdi, rax
|
mov rdi, rax
|
||||||
mov rax, 60
|
mov rax, 60
|
||||||
syscall
|
syscall
|
||||||
|
word_strlen:
|
||||||
|
mov rsi, [r12] ; addr
|
||||||
|
mov rcx, 0
|
||||||
|
strlen_loop:
|
||||||
|
mov al, [rsi + rcx]
|
||||||
|
cmp al, 0
|
||||||
|
je strlen_done
|
||||||
|
inc rcx
|
||||||
|
jmp strlen_loop
|
||||||
|
strlen_done:
|
||||||
|
mov [r12], rcx ; len
|
||||||
|
ret
|
||||||
|
ret
|
||||||
word_puts:
|
word_puts:
|
||||||
; 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
|
||||||
|
|||||||
521
build/debug_addresses.asm
Normal file
521
build/debug_addresses.asm
Normal file
@@ -0,0 +1,521 @@
|
|||||||
|
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:
|
||||||
BIN
build/debug_addresses.o
Normal file
BIN
build/debug_addresses.o
Normal file
Binary file not shown.
503
build/str.asm
Normal file
503
build/str.asm
Normal file
@@ -0,0 +1,503 @@
|
|||||||
|
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 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
|
||||||
|
section .data
|
||||||
|
data_start:
|
||||||
|
str_0: db 115, 116, 114, 46, 115, 108, 0
|
||||||
|
str_0_len equ 6
|
||||||
|
data_end:
|
||||||
|
section .bss
|
||||||
|
align 16
|
||||||
|
dstack: resb DSTK_BYTES
|
||||||
|
dstack_top:
|
||||||
|
align 16
|
||||||
|
rstack: resb RSTK_BYTES
|
||||||
|
rstack_top:
|
||||||
|
align 16
|
||||||
|
print_buf: resb PRINT_BUF_BYTES
|
||||||
|
print_buf_end:
|
||||||
BIN
build/str.o
Normal file
BIN
build/str.o
Normal file
Binary file not shown.
592
build/test_read_file.asm
Normal file
592
build/test_read_file.asm
Normal file
@@ -0,0 +1,592 @@
|
|||||||
|
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:
|
||||||
BIN
build/test_read_file.o
Normal file
BIN
build/test_read_file.o
Normal file
Binary file not shown.
555
build/test_write_buf.asm
Normal file
555
build/test_write_buf.asm
Normal file
@@ -0,0 +1,555 @@
|
|||||||
|
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:
|
||||||
BIN
build/test_write_buf.o
Normal file
BIN
build/test_write_buf.o
Normal file
Binary file not shown.
594
build/test_write_file.asm
Normal file
594
build/test_write_file.asm
Normal file
@@ -0,0 +1,594 @@
|
|||||||
|
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 22
|
||||||
|
sub r12, 8
|
||||||
|
mov qword [r12], 22
|
||||||
|
call word_swap
|
||||||
|
; push str_1
|
||||||
|
sub r12, 8
|
||||||
|
mov qword [r12], str_1
|
||||||
|
; push 27
|
||||||
|
sub r12, 8
|
||||||
|
mov qword [r12], 27
|
||||||
|
call word_swap
|
||||||
|
call word_2swap
|
||||||
|
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 47, 116, 109, 112, 47, 108, 50, 95, 116, 101, 115, 116, 95, 119, 114, 105, 116, 101, 46, 116, 120, 116, 0
|
||||||
|
str_0_len equ 22
|
||||||
|
str_1: 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_1_len equ 27
|
||||||
|
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:
|
||||||
BIN
build/test_write_file.o
Normal file
BIN
build/test_write_file.o
Normal file
Binary file not shown.
2
hello.sl
2
hello.sl
@@ -1,4 +1,4 @@
|
|||||||
import stdlib.sl
|
import stdlib/stdlib.sl
|
||||||
|
|
||||||
: main
|
: main
|
||||||
"hello world" puts
|
"hello world" puts
|
||||||
|
|||||||
1
main.py
1
main.py
@@ -2138,7 +2138,6 @@ def _register_compile_time_primitives(dictionary: Dictionary) -> None:
|
|||||||
register("list-new", _ct_list_new, compile_only=True)
|
register("list-new", _ct_list_new, compile_only=True)
|
||||||
register("list-clone", _ct_list_clone, compile_only=True)
|
register("list-clone", _ct_list_clone, compile_only=True)
|
||||||
register("list-append", _ct_list_append, compile_only=True)
|
register("list-append", _ct_list_append, compile_only=True)
|
||||||
register("drop", _ct_drop)
|
|
||||||
register("list-pop", _ct_list_pop, compile_only=True)
|
register("list-pop", _ct_list_pop, compile_only=True)
|
||||||
register("list-pop-front", _ct_list_pop_front, compile_only=True)
|
register("list-pop-front", _ct_list_pop_front, compile_only=True)
|
||||||
register("list-peek-front", _ct_list_peek_front, compile_only=True)
|
register("list-peek-front", _ct_list_peek_front, compile_only=True)
|
||||||
|
|||||||
2
main.sl
2
main.sl
@@ -1,4 +1,4 @@
|
|||||||
import stdlib.sl
|
import stdlib/stdlib.sl
|
||||||
import fn.sl
|
import fn.sl
|
||||||
|
|
||||||
: main
|
: main
|
||||||
|
|||||||
BIN
stat_offset
Executable file
BIN
stat_offset
Executable file
Binary file not shown.
8
stat_offset.c
Normal file
8
stat_offset.c
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
printf("st_size offset: %zu\n", offsetof(struct stat, st_size));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
134
stdlib/io.sl
Normal file
134
stdlib/io.sl
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
|
||||||
|
# L2 IO Primitives
|
||||||
|
|
||||||
|
# : read_file ( path_ptr path_len -- len addr | 0 0 )
|
||||||
|
# Reads the file at the given path (pointer+length, not null-terminated),
|
||||||
|
# returns (len addr) of mapped file, or (0 0) on error.
|
||||||
|
|
||||||
|
:asm 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
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
# : write_file ( path_ptr path_len buf_ptr buf_len -- bytes_written | neg_errno )
|
||||||
|
:asm write_file {
|
||||||
|
; stack: path_ptr (top), path_len, buf_ptr, buf_len
|
||||||
|
mov rsi, [r12] ; path_ptr
|
||||||
|
mov rdx, [r12 + 8] ; path_len
|
||||||
|
mov r15, [r12 + 16] ; buf_ptr (save in callee-saved r15)
|
||||||
|
mov r13, [r12 + 24] ; buf_len (save in callee-saved r13)
|
||||||
|
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
|
||||||
|
}
|
||||||
|
;
|
||||||
@@ -1,3 +1,41 @@
|
|||||||
|
# : c@ ( addr -- byte )
|
||||||
|
:asm c@ {
|
||||||
|
mov rax, [r12]
|
||||||
|
movzx rax, byte [rax]
|
||||||
|
mov [r12], rax
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
# : c! ( byte addr -- )
|
||||||
|
:asm c! {
|
||||||
|
mov rax, [r12]
|
||||||
|
add r12, 8
|
||||||
|
mov rbx, [r12]
|
||||||
|
mov [rbx], al
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
# : r@ ( -- x )
|
||||||
|
:asm r@ {
|
||||||
|
mov rax, [r13]
|
||||||
|
sub r12, 8
|
||||||
|
mov [r12], rax
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
# : strlen ( addr len -- len )
|
||||||
|
:asm strlen {
|
||||||
|
mov rax, [r12] ; addr
|
||||||
|
mov rcx, [r12 + 8] ; len
|
||||||
|
add r12, 16 ; pop len and addr
|
||||||
|
mov [r12], rcx ; push len
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
:asm puts {
|
:asm puts {
|
||||||
; 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
|
||||||
@@ -84,6 +122,18 @@ puts_finish_digits:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
# : write_buf ( len addr -- )
|
||||||
|
:asm 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
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
:asm drop {
|
:asm drop {
|
||||||
add r12, 8
|
add r12, 8
|
||||||
}
|
}
|
||||||
@@ -303,20 +353,22 @@ puts_finish_digits:
|
|||||||
;
|
;
|
||||||
|
|
||||||
:asm mmap {
|
:asm mmap {
|
||||||
mov r9, [r12]
|
; Save rsp and align to 16 bytes for syscall ABI
|
||||||
add r12, 8
|
mov rax, rsp
|
||||||
mov r8, [r12]
|
and rsp, -16
|
||||||
add r12, 8
|
mov rdi, [r12+40] ; addr
|
||||||
mov r10, [r12]
|
mov rsi, [r12+32] ; length
|
||||||
add r12, 8
|
mov rdx, [r12+24] ; prot
|
||||||
mov rdx, [r12]
|
mov r10, [r12+16] ; flags
|
||||||
add r12, 8
|
mov r8, [r12+8] ; fd
|
||||||
mov rsi, [r12]
|
mov r9, [r12] ; offset
|
||||||
add r12, 8
|
add r12, 48 ; pop 6 args
|
||||||
mov rdi, [r12]
|
mov rax, 9 ; syscall: mmap
|
||||||
mov rax, 9
|
|
||||||
syscall
|
syscall
|
||||||
mov [r12], rax
|
mov rsp, rax ; restore rsp
|
||||||
|
sub r12, 8
|
||||||
|
mov [r12], rax ; push result
|
||||||
|
ret
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
8
str.sl
Normal file
8
str.sl
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import stdlib/stdlib.sl
|
||||||
|
import stdlib/io.sl
|
||||||
|
|
||||||
|
: main
|
||||||
|
"str.sl" swap read_file
|
||||||
|
write_buf
|
||||||
|
0
|
||||||
|
;
|
||||||
2
t.sl
2
t.sl
@@ -1,4 +1,4 @@
|
|||||||
import stdlib.sl
|
import stdlib/stdlib.sl
|
||||||
import fn.sl
|
import fn.sl
|
||||||
|
|
||||||
fn foo(int a, int b){
|
fn foo(int a, int b){
|
||||||
|
|||||||
2
test.sl
2
test.sl
@@ -1,4 +1,4 @@
|
|||||||
import stdlib.sl
|
import stdlib/stdlib.sl
|
||||||
import fn.sl
|
import fn.sl
|
||||||
|
|
||||||
:asm mem-slot {
|
:asm mem-slot {
|
||||||
|
|||||||
BIN
test_read_file.out
Executable file
BIN
test_read_file.out
Executable file
Binary file not shown.
33
test_read_file.sl
Normal file
33
test_read_file.sl
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import stdlib/stdlib.sl
|
||||||
|
import stdlib/io.sl
|
||||||
|
|
||||||
|
: main
|
||||||
|
"/etc/hostname" # (len addr)
|
||||||
|
swap # (addr len)
|
||||||
|
read_file # (file_len file_addr)
|
||||||
|
dup 0 > if # if file_len > 0, success
|
||||||
|
write_buf # print file contents (file_len file_addr)
|
||||||
|
0
|
||||||
|
exit
|
||||||
|
then
|
||||||
|
dup -2 == if # open() failed
|
||||||
|
drop
|
||||||
|
"open() failed: errno=" puts
|
||||||
|
swap puts
|
||||||
|
exit
|
||||||
|
then
|
||||||
|
dup -1 == if # fstat() failed
|
||||||
|
drop
|
||||||
|
"fstat() failed: errno=" puts
|
||||||
|
swap puts
|
||||||
|
exit
|
||||||
|
then
|
||||||
|
dup -3 == if # mmap() failed
|
||||||
|
drop
|
||||||
|
"mmap() failed" puts
|
||||||
|
exit
|
||||||
|
then
|
||||||
|
"unknown read_file failure" puts
|
||||||
|
dup # file_len file_len file_addr
|
||||||
|
exit # Exit with returned file_len as the program exit code (debug)
|
||||||
|
;
|
||||||
8
test_write_buf.sl
Normal file
8
test_write_buf.sl
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import stdlib/stdlib.sl
|
||||||
|
import stdlib/io.sl
|
||||||
|
|
||||||
|
: main
|
||||||
|
"hello from write_buf test\n"
|
||||||
|
write_buf
|
||||||
|
0
|
||||||
|
;
|
||||||
20
test_write_file.sl
Normal file
20
test_write_file.sl
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import stdlib/stdlib.sl
|
||||||
|
import stdlib/io.sl
|
||||||
|
|
||||||
|
: main
|
||||||
|
"/tmp/l2_test_write.txt" # push path (len addr)
|
||||||
|
swap # -> (addr len) = path_ptr path_len
|
||||||
|
"hello from write_file test\n" # push buf (len addr)
|
||||||
|
swap # -> (addr len) = buf_ptr buf_len
|
||||||
|
2swap # reorder pairs -> path_ptr path_len buf_ptr buf_len
|
||||||
|
write_file
|
||||||
|
dup 0 > if
|
||||||
|
"wrote bytes: " puts
|
||||||
|
puts
|
||||||
|
0
|
||||||
|
exit
|
||||||
|
then
|
||||||
|
"write failed errno=" puts
|
||||||
|
puts
|
||||||
|
exit
|
||||||
|
;
|
||||||
@@ -30,7 +30,7 @@ CASES: List[TestCase] = [
|
|||||||
TestCase(
|
TestCase(
|
||||||
name="call_syntax_parens",
|
name="call_syntax_parens",
|
||||||
source=f"""
|
source=f"""
|
||||||
import {ROOT / 'stdlib.sl'}
|
import {ROOT / 'stdlib/stdlib.sl'}
|
||||||
import {ROOT / 'fn.sl'}
|
import {ROOT / 'fn.sl'}
|
||||||
|
|
||||||
: main
|
: main
|
||||||
@@ -51,7 +51,7 @@ fn foo(int a, int b){{
|
|||||||
TestCase(
|
TestCase(
|
||||||
name="loops_and_cmp",
|
name="loops_and_cmp",
|
||||||
source=f"""
|
source=f"""
|
||||||
import {ROOT / 'stdlib.sl'}
|
import {ROOT / 'stdlib/stdlib.sl'}
|
||||||
|
|
||||||
: main
|
: main
|
||||||
0
|
0
|
||||||
@@ -69,7 +69,7 @@ import {ROOT / 'stdlib.sl'}
|
|||||||
TestCase(
|
TestCase(
|
||||||
name="override_dup_compile_time",
|
name="override_dup_compile_time",
|
||||||
source=f"""
|
source=f"""
|
||||||
import {ROOT / 'stdlib.sl'}
|
import {ROOT / 'stdlib/stdlib.sl'}
|
||||||
|
|
||||||
: dup
|
: dup
|
||||||
6
|
6
|
||||||
@@ -102,7 +102,7 @@ compile-only
|
|||||||
TestCase(
|
TestCase(
|
||||||
name="string_puts",
|
name="string_puts",
|
||||||
source=f"""
|
source=f"""
|
||||||
import {ROOT / 'stdlib.sl'}
|
import {ROOT / 'stdlib/stdlib.sl'}
|
||||||
|
|
||||||
: main
|
: main
|
||||||
\"hello world\" puts
|
\"hello world\" puts
|
||||||
|
|||||||
BIN
write_buf_test
Executable file
BIN
write_buf_test
Executable file
Binary file not shown.
Reference in New Issue
Block a user