;;; This file define/describes the "machine" ;;; ;;; Abstract Machine: ;;; https://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture ;;; ;;; General Purpose Registers ( * marks those used in syscalls ) ;;; *rax = ( -, eax = ( -, ax = ( ah, al) )) "accumulator" ;;; rbx = ( -, ebx = ( -, bx = ( bh, bl) )) "base" ;;; *rcx = ( -, ecx = ( -, cx = ( ch, cl) )) "counter" ;;; *rdx = ( -, edx = ( -, dx = ( dh, dl) )) "data" ;;; rsp = ( -, esp = ( -, sp = ( -, spl) )) "stack pointer" ;;; rbp = ( -, ebp = ( -, bp = ( -, bpl) )) "stack base pointer" ;;; *rsi = ( -, esi = ( -, si = ( -, sil) )) "source" ;;; *rdi = ( -, edi = ( -, di = ( -, dil) )) "destination" ;;; *r8 ;;; *r9 ;;; r10 ;;; *r11 ;;; r12 ;;; r13 ;;; r14 ;;; r15 ;;; clobbers rdi rsi rdx rcx r8 r9 r11 ;;; rax = syscall id ;;; ;;; Segment Registers ;;; SS "Stack Segment" ;;; CS "Code Segment" ;;; DS "Data Segment" ;;; ES "Extra Segment" ;;; FS "more Extra Segment" ;;; GS "more more Extra Segment" ;;; ;;; EFLAGS Register ;;; 0,0,0,0,0,0,0,0,0,0,ID,VIP,VIF,AC,VM,RF, ;;; 0,NT,[IOPL,IOPL],OF,DF,IF,TF,SF,ZF,0,AF,0,PF,1,CF ;;; ;;; Instruction pointer ;;; EIP ;;; ;;; Syscall allocations ;;; clobbers rdi rsi rdx rcx r8 r9 r11 ;;; rax = syscall id ;;; ;;; ###################################################################### ;;; ============================================================ ;;; FORTH machine model ;;; rsp = data stack pointer ;;; rbp = return stack pointer ;;; rsi = instruction pointer ;;; ======================================== ;;; The pushr macro pushes x onto the return stack ;;; The popr macro pops x from the return stack macro pushr x { sub rbp, 8 mov [rbp], x } macro popr x { mov x, [rbp] add rbp, 8 } ;;; ======================================== ;;; The next macro "moves" execution to the next FORTH instruction, ;;; using rsi as instruction pointer. It points to the doer field of a ;;; word, which points to the assembly code that implements the ;;; execution effect of the word. That doer code is entered with rsi ;;; referring to the subsequent address in the colling word, and rax ;;; referring to the doer field of the called word. macro next { lodsq ; mov rax, [rsi] + add rsi,8 jmp qword [rax] ; goto code of that FORTH word (64 bit jump) } ;;; ======================================== ;;; The FORTH macro transitions to inline FORTH execution. macro FORTH { local forthcode mov rsi,forthcode next ;; align 8 forthcode: } ;;; ======================================== ;;; The ENDFORTH macro transitions back to inline assembler after FORTH macro ENDFORTH { dq inline_code } ;;; ======================================== ;;; The DOFORTH lays out a single FORTH call macro DOFORTH label { FORTH dq label ENDFORTH } ;;; ======================================== ;;; Macro WORD starts a FORTH word definition in this code ;;; previous_word = 0 ; Used for chaining the words IMMEDIATE = 1 ; optional flag (symbol) macro WORD label, name, doer, flags { ;; align 8 label#_TFA: ;; TFA dq previous_word previous_word = label#_TFA ;; PFA label#_PFA: db flags + 0 db label - $ - 2 db name db 0 ;; align 8 label#_OFF: dq 0 ; The DOES offset. Defaults to 0. ;; also CFA = pointer to "doer" label: if doer eq dq doforth else if doer in dq label#_DFA else dq doer end if end if ;; DFA label#_DFA: } ;;; ======================================== ;;; The block macro lays out the length for a subsequent block to the ;;; given label. macro BLOCK endlabel { local datastart dq endlabel - datastart datastart: }