; 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 .data rpn_exec: ; unsigned long int rpn_exec(unsigned long int stack_size, unsigned long args) ; rdi -> stack size (in values (64 bits)) ; rsi -> args pointers enter 32, 0 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: 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