Add extension to notes file
[rrq/jonasforth.git] / main.asm
1 format ELF64 executable
2
3 ;; The code in this macro is placed at the end of each Forth word. When we are
4 ;; executing a definition, this code is what causes execution to resume at the
5 ;; next word in that definition.
6 macro next {
7     ;; RSI points to the address of the definition of the next word to execute.
8     lodsq                   ; Load value at RSI into RAX and increment RSI
9     ;; Now RAX contains the location of the next word to execute. The first 8
10     ;; bytes of this word is the address of the codeword, which is what we want
11     ;; to execute.
12     jmp qword [rax]         ; Jump to the codeword of the current word
13 }
14
15 ;; pushr and popr work on the return stack, whose location is stored in the
16 ;; register RBP.
17 macro pushr x {
18     sub rbp, 8
19     mov qword [rbp], x
20 }
21 macro popr x {
22     mov x, [rbp]
23     add rbp, 8
24 }
25
26 segment readable executable
27
28 main:
29     cld                        ; Clear direction flag so LODSQ does the right thing.
30     mov rbp, return_stack_top  ; Initialize return stack
31
32     mov rsi, program
33     next
34
35 program:
36     dq HELLO
37
38 ;; The codeword is the code that will be executed at the beginning of a forth
39 ;; word. It needs to save the old RSI and update it to point to the next word to
40 ;; execute.
41 docol:
42     pushr rsi            ; Save old value of RSI on return stack; we will continue execution there after we are done executing this word
43     lea rsi, [rax + 8]   ; RAX currently points to the address of the codeword, so we want to continue at RAX+8
44     next                 ; Execute word pointed to by RSI
45
46 ;; This codeword is called at the end of a Forth definition. It just needs to
47 ;; restore the old value of RSI (saved by 'docol') and resume execution.
48 exit:
49     popr rsi
50     next
51
52 EMIT:
53     dq .start
54 .start:
55     pushr rsi
56     pushr rax
57     mov rax, 1
58     mov rdi, 1
59     lea rsi, [rsp]
60     mov rdx, 1
61     syscall
62     add rsp, 8
63     popr rax
64     popr rsi
65     next
66
67 PUSH_HELLO_CHARS:
68     dq .start
69 .start:
70     push $A
71     push 'o'
72     push 'l'
73     push 'l'
74     push 'e'
75     push 'H'
76     next
77
78 HELLO:
79     dq docol
80     dq PUSH_HELLO_CHARS
81     dq EMIT
82     dq EMIT
83     dq EMIT
84     dq EMIT
85     dq EMIT
86     dq EMIT
87     dq exit
88
89 PROGRAM:
90     dq docol
91     dq HELLO
92     dq HELLO
93     dq HELLO
94     dq exit
95
96 segment readable writable
97
98 ;; Return stack
99 rq $2000
100 return_stack_top: