251 lines
3.4 KiB
NASM
251 lines
3.4 KiB
NASM
; TODO Use memory area given in argument to preserve stack between calls
|
|
[bits 64]
|
|
|
|
; local variables macro
|
|
%define stack_size [rbp - 8]
|
|
%define stack_base [rbp - 16]
|
|
%define brkinit [rbp - 24]
|
|
%define args_ptr [rbp - 32]
|
|
|
|
%define stack_cur r11
|
|
|
|
; push & pop the RPN stack macros
|
|
; check if stack full, then push value
|
|
%macro rpn_push 1
|
|
inc stack_cur
|
|
cmp stack_cur, stack_size
|
|
jl %%end
|
|
xor stack_cur, stack_cur
|
|
%%end:
|
|
mov [r10 + stack_cur * 8], %1
|
|
%endmacro
|
|
|
|
; check if stack empty, then pop value
|
|
%macro rpn_pop 1
|
|
mov %1, [r10 + stack_cur * 8]
|
|
cmp stack_cur, 0
|
|
jg %%end
|
|
mov stack_cur, stack_size
|
|
%%end:
|
|
dec stack_cur
|
|
%endmacro
|
|
|
|
; define a label with code portion size
|
|
; and set global
|
|
%macro part_sz 1
|
|
%1_sz: dq $ - %1
|
|
global %1
|
|
global %1_sz
|
|
%endmacro
|
|
|
|
section .note.GNU-stack noalloc noexec nowrite progbits
|
|
|
|
section .data
|
|
|
|
rpn_exec:
|
|
; unsigned long int rpn_exec(unsigned long int stack_size, unsigned long args, unsigned long int *stack)
|
|
; rdi -> stack size (in values (64 bits))
|
|
; rsi -> args pointers
|
|
; rdx -> stack pointer or null
|
|
|
|
enter 32, 0
|
|
push rbx ; rbx MUST BE PRESERVED !!! (like r12 to r15 and rbp !)
|
|
|
|
mov stack_size, rdi
|
|
mov args_ptr, rsi
|
|
mov r10, rdx ; r10 is stack base
|
|
|
|
xor rdx, rdx
|
|
mov brkinit, rdx
|
|
|
|
cmp r10, 0
|
|
jne .nobrk
|
|
; if stack is NULL allocate using brk
|
|
|
|
mov rax, 0x0C
|
|
xor rdi, rdi ; get brk
|
|
syscall
|
|
|
|
mov brkinit, rax
|
|
mov rdi, stack_size
|
|
shl rdi, 3 ; mul 8
|
|
add rdi, rax
|
|
mov rax, 0x0C
|
|
syscall ; new brk
|
|
|
|
cmp rax, -1
|
|
jne .cont
|
|
leave
|
|
ret
|
|
.cont:
|
|
|
|
mov rcx, stack_size
|
|
mov rdi, brkinit
|
|
xor rax, rax
|
|
.bzero:
|
|
stosq
|
|
loop .bzero
|
|
mov r10, brkinit
|
|
|
|
.nobrk:
|
|
xor stack_cur, stack_cur ; r11 is stack item counter
|
|
|
|
|
|
part_sz rpn_exec
|
|
|
|
rpn_exec_ret:
|
|
rpn_pop rax
|
|
mov rdi, brkinit
|
|
cmp rdi, 0
|
|
jne .end
|
|
push rax
|
|
mov rax, 0x0C
|
|
mov rdi, brkinit
|
|
syscall
|
|
pop rax
|
|
.end:
|
|
pop rbx
|
|
leave
|
|
ret
|
|
part_sz rpn_exec_ret
|
|
|
|
rpn_value:
|
|
mov rax, strict qword 0x12345678
|
|
rpn_push rax
|
|
part_sz rpn_value
|
|
|
|
rpn_arg:
|
|
mov rax, strict qword 0x12345678
|
|
mov rsi, 8
|
|
mul rsi
|
|
mov rsi, args_ptr
|
|
add rsi, rax
|
|
mov rax, [rsi]
|
|
rpn_push rax
|
|
part_sz rpn_arg
|
|
|
|
rpn_add:
|
|
rpn_pop rax
|
|
rpn_pop rbx
|
|
add rax, rbx
|
|
rpn_push rax
|
|
part_sz rpn_add
|
|
|
|
rpn_sub:
|
|
rpn_pop rbx
|
|
rpn_pop rax
|
|
sub rax, rbx
|
|
rpn_push rax
|
|
part_sz rpn_sub
|
|
|
|
rpn_mul:
|
|
rpn_pop rbx
|
|
rpn_pop rax
|
|
mul rbx
|
|
rpn_push rax
|
|
part_sz rpn_mul
|
|
|
|
rpn_div:
|
|
rpn_pop rbx
|
|
rpn_pop rax
|
|
xor rdx, rdx
|
|
test rbx, rbx
|
|
jz .zerodiv
|
|
div rbx
|
|
jmp .end
|
|
.zerodiv: xor rax, rax
|
|
.end:
|
|
rpn_push rax
|
|
part_sz rpn_div
|
|
|
|
rpn_mod:
|
|
rpn_pop rbx
|
|
rpn_pop rax
|
|
xor rdx, rdx
|
|
test rbx, rbx
|
|
jz .zerodiv
|
|
div rbx
|
|
jmp .end
|
|
.zerodiv: xor rax, rax
|
|
.end:
|
|
rpn_push rdx
|
|
part_sz rpn_mod
|
|
|
|
rpn_neg:
|
|
rpn_pop rax
|
|
neg rax
|
|
rpn_push rax
|
|
part_sz rpn_neg
|
|
|
|
rpn_not:
|
|
rpn_pop rax
|
|
not rax
|
|
rpn_push rax
|
|
part_sz rpn_not
|
|
|
|
rpn_and:
|
|
rpn_pop rbx
|
|
rpn_pop rax
|
|
and rax, rbx
|
|
rpn_push rax
|
|
part_sz rpn_and
|
|
|
|
rpn_or:
|
|
rpn_pop rbx
|
|
rpn_pop rax
|
|
or rax, rbx
|
|
rpn_push rax
|
|
part_sz rpn_or
|
|
|
|
rpn_xor:
|
|
rpn_pop rbx
|
|
rpn_pop rax
|
|
xor rax, rbx
|
|
rpn_push rax
|
|
part_sz rpn_xor
|
|
|
|
rpn_shl:
|
|
rpn_pop rcx
|
|
rpn_pop rax
|
|
cmp rcx, 64
|
|
jge .zero
|
|
shl rax, cl
|
|
jmp .end
|
|
.zero:
|
|
xor rax, rax
|
|
.end:
|
|
rpn_push rax
|
|
part_sz rpn_shl
|
|
|
|
rpn_shr:
|
|
rpn_pop rcx
|
|
rpn_pop rax
|
|
cmp rcx, 64
|
|
jge .zero
|
|
shr rax, cl
|
|
jmp .end
|
|
.zero:
|
|
xor rax, rax
|
|
.end:
|
|
rpn_push rax
|
|
part_sz rpn_shr
|
|
|
|
rpn_xchg:
|
|
rpn_pop rbx
|
|
rpn_pop rax
|
|
rpn_push rbx
|
|
rpn_push rax
|
|
part_sz rpn_xchg
|
|
|
|
rpn_dup:
|
|
rpn_pop rax
|
|
rpn_push rax
|
|
rpn_push rax
|
|
part_sz rpn_dup
|
|
|
|
rpn_pop_op:
|
|
rpn_pop rax
|
|
part_sz rpn_pop_op
|
|
|
|
section .text
|
|
|