Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
forth_tutorial/forth14/forth.asm
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
233 lines (219 sloc)
3.57 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
global _start | |
%define True 1 | |
%define False 0 | |
%define r1 rax | |
%define r2 rcx | |
%define r3 rdx | |
%define r5 rbp | |
%define stdin 0 | |
%define stdout 1 | |
%macro pushdata 1 | |
push r1 | |
push r5 | |
mov r5, [data_stack_length] | |
;; In case we want to do this with a constant or address | |
mov r1, %1 | |
mov [data_stack + 8*r5], r1 | |
inc qword [data_stack_length] | |
pop r5 | |
pop r1 | |
%endmacro | |
%macro popdata 1 | |
push r5 | |
dec qword [data_stack_length] | |
mov r5, [data_stack_length] | |
mov %1, [data_stack + 8*r5] | |
pop r5 | |
%endmacro | |
%macro prints 1+ | |
jmp %%endstr | |
%%str: db %1 | |
%%endstr: | |
mov eax, 1 | |
mov rdi, stdout | |
lea rsi, [%%str] | |
mov rdx, %%endstr-%%str | |
syscall | |
%endmacro | |
section .data | |
eol: db 10 | |
space: db 32 | |
print_chars: db "0123456789abcdef" | |
primitive_function: dq push1, print, return | |
memory: dq 0, 1, 0, 1, 2 | |
section .bss | |
call_stack_length: resq 1 | |
call_stack: resq 10000 | |
data_stack_length: resq 1 | |
data_stack: resq 10000 | |
section .text | |
_start: | |
;; Start at memory[0] | |
pushdata 0 | |
call call_stack.push | |
prints "Running main loop" | |
call printeol | |
call main_loop | |
exit: | |
mov eax, 60 | |
mov rdi, 0 | |
syscall | |
call_stack.len: | |
pushdata [call_stack_length] | |
ret | |
call_stack.push: | |
popdata r1 | |
mov r2, [call_stack_length] | |
mov [call_stack + 8*r2], r1 | |
inc qword [call_stack_length] | |
ret | |
call_stack.pop: | |
dec qword [call_stack_length] | |
mov r1, [call_stack_length] | |
mov r1, [call_stack + 8*r1] | |
pushdata r1 | |
ret | |
memory.get: | |
popdata r1 | |
mov r1, [memory + 8*r1] | |
pushdata r1 | |
ret | |
if_else: | |
popdata r3 | |
popdata r1 | |
popdata r2 | |
cmp r2, 0 | |
je .false | |
call r1 | |
ret | |
.false: | |
call r3 | |
ret | |
equal: | |
popdata r1 | |
popdata r2 | |
cmp r1, r2 | |
je .true | |
.false: | |
pushdata False | |
ret | |
.true: | |
pushdata True | |
ret | |
add: | |
popdata r1 | |
popdata r2 | |
add r2, r1 | |
pushdata r2 | |
ret | |
call_primitive: | |
popdata r1 | |
call [primitive_function + 8*r1] | |
ret | |
is_primitive: | |
pushdata True | |
ret | |
push1: | |
pushdata 1 | |
ret | |
print: | |
;; Print value at the top of the stack as an integer in hex. | |
;; Callable without losing register values | |
push qword rax | |
push qword rcx | |
push qword rdx | |
push qword rbx | |
push qword rbp | |
push qword rsi | |
push qword rdi | |
;; x = data_stack.pop() | |
popdata r3 | |
mov r1, 8 | |
dec r1 | |
.loop8times: | |
;; sys.print(stdout, print_chars[x & 1111b], 1) | |
mov r2, r3 | |
and r2, 1111b | |
push qword r1 | |
push qword r3 | |
mov eax, 1 | |
mov rdi, stdout | |
lea rsi, [print_chars + 1*r2] | |
mov rdx, 1 | |
syscall | |
pop r3 | |
pop r1 | |
;; x >>= 4 | |
shr r3, 4 | |
dec r1 | |
jns .loop8times | |
mov eax, 1 | |
mov rdi, stdout | |
lea rsi, [space] | |
mov rdx, 1 | |
syscall | |
pop rdi | |
pop rsi | |
pop rbp | |
pop rbx | |
pop rdx | |
pop rcx | |
pop rax | |
ret | |
printeol: | |
mov eax, 1 | |
mov rdi, stdout | |
lea rsi, [eol] | |
mov rdx, 1 | |
syscall | |
ret | |
printspace: | |
mov eax, 1 | |
mov rdi, stdout | |
lea rsi, [space] | |
mov rdx, 1 | |
syscall | |
ret | |
main_loop: | |
.loop: | |
call call_stack.len | |
pushdata 0 | |
call equal | |
popdata r1 | |
test r1, r1 | |
jnz .end | |
call call_stack.pop | |
call s11 | |
call memory.get | |
call s21 | |
pushdata 1 | |
call add | |
call call_stack.push | |
call s11 | |
call is_primitive | |
pushdata call_primitive | |
pushdata call_stack.push | |
call if_else | |
jmp .loop | |
.end: | |
ret | |
return: | |
call call_stack.pop | |
call s2 | |
ret | |
s11: | |
popdata r1 | |
pushdata r1 | |
pushdata r1 | |
ret | |
s21: | |
popdata r1 | |
popdata r2 | |
pushdata r1 | |
pushdata r2 | |
ret | |
s2: | |
popdata r1 | |
popdata r2 | |
pushdata r2 | |
ret | |