;; vim: syntax=fasm
-format ELF64 executable
+include "uefi.asm"
;; "Syscalls" {{{
;;
;; Clobbers: RAX, RCX, R11, RDI, RSI
macro sys_print_string {
- mov rax, 1
- mov rdi, 1
- mov rsi, rcx
- syscall
+ push r8
+ push r9
+ push r10
+
+ call uefi_print_string
+
+ pop r10
+ pop r9
+ pop r8
+}
+
+;; Read a character from the user into the given buffer.
+;;
+;; Input:
+;; - RSI = Character buffer
+;;
+;; Output:
+;; - BYTE [RSI] = Character
+;;
+;; Clobbers: RAX, RCX, R11, RDI, RSI, RDX
+macro sys_read_char {
+ push rbx
+ push r8
+ push r9
+ push r10
+ push r15
+
+ mov rcx, rsi
+ call uefi_read_char
+
+ pop r15
+ pop r10
+ pop r9
+ pop r8
+ pop rbx
+}
+
+macro sys_terminate code {
+ mov rax, code
+ call uefi_terminate
}
;; }}}
.start:
}
-segment readable executable
-
-entry main
+section '.text' code readable executable
include "impl.asm" ; Misc. subroutines
include "bootstrap.asm" ; Forth words encoded in Assembly
cld ; Clear direction flag so LODSQ does the right thing.
mov rbp, return_stack_top ; Initialize return stack
+ call uefi_initialize
+
mov rax, MAIN
jmp qword [rax]
;; Exit the program cleanly.
forth_asm TERMINATE, 'TERMINATE'
- mov rax, $3C
- mov rdi, 0
- syscall
+ sys_terminate 0
;; Duplicate a pair of elements.
forth_asm PAIRDUP, '2DUP'
mov [.length], 0
.read_char:
- mov rax, 0
- mov rdi, 0
mov rsi, .char_buffer
- mov rdx, 1
- syscall
+ sys_read_char
mov al, [.char_buffer]
cmp al, '"'
;; We borrow READ_STRING's buffer. They won't mind.
mov [READ_STRING.length], 0
- ;; Skip space ([TODO]: Shouldn't we do this while parsing instead?)
- inc [input_buffer]
- dec [input_buffer_length]
-
.read_char:
mov rbx, [input_buffer]
mov al, [rbx]
dq LIT, input_buffer_length
dq EXIT
-segment readable writable
+section '.data' readable writable
;; The LATEST variable holds a pointer to the word that was last added to the
;; dictionary. This pointer is updated as new words are added, and its value is
rq $2000
return_stack_top:
-segment readable
-
;; We store some Forth code in sys.f that defined common words that the user
;; would expect to have available at startup. To execute these words, we just
;; include the file directly in the binary, and then interpret it at startup.