X-Git-Url: https://git.rrq.au/?a=blobdiff_plain;ds=sidebyside;f=main.asm;h=e510410a5069b239621a1c14edb58893bce05dac;hb=61b721d365efaaae4d5ebb8d13972faa697be54b;hp=5985b997af8095926394802fd7e6c59b636a5510;hpb=bcba0c88f4eaddac8e0d8c0fa68264b2e81ee272;p=rrq%2Fjonasforth.git diff --git a/main.asm b/main.asm index 5985b99..e510410 100644 --- a/main.asm +++ b/main.asm @@ -1,10 +1,16 @@ ;; vim: syntax=fasm ;; At compile-time we load the module given by the environment variable -;; OS_INCLUDE. This module should define the following macros: +;; OS_INCLUDE. All of the following these procedures should preserve the value +;; of RSI and RSP. They may use other registers as they like. ;; -;; Each of these functions should preserve the value of RSI and RSP. They may -;; use other registers as they like. +;; The module should provide the following: +;; +;; os_code_section +;; Macro to start the text segment. +;; +;; os_data_section +;; Macro to start the data segment. ;; ;; os_initialize ;; Called at initialization. @@ -15,62 +21,12 @@ ;; ;; os_read_char ;; Wait for the user to type a key, and then put the corresponding ASCII byte -;; into the buffer pointed to by RCX. +;; into RAX. ;; ;; os_terminate -;; Shut down the system. +;; Shut down the system, returning the error code given in RAX. include '%OS_INCLUDE%' -;; Print a string of a given length. -;; -;; Input: -;; - RCX = Pointer to buffer -;; - RDX = Buffer length -;; -;; Clobbers: RAX, RCX, R11, RDI, RSI -macro sys_print_string { - push r8 - push r9 - push r10 - - call os_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 os_read_char - - pop r15 - pop r10 - pop r9 - pop r8 - pop rbx -} - -macro sys_terminate code { - mov rax, code - call os_terminate -} - ;; The code in this macro is placed at the end of each Forth word. When we are ;; executing a definition, this code is what causes execution to resume at the ;; next word in that definition. @@ -128,11 +84,11 @@ macro forth_asm label, name, immediate { .start: } -section '.text' code readable executable - include "impl.asm" ; Misc. subroutines include "bootstrap.asm" ; Forth words encoded in Assembly +os_code_section + main: cld ; Clear direction flag so LODSQ does the right thing. mov rbp, return_stack_top ; Initialize return stack @@ -240,7 +196,7 @@ forth_asm EMIT, 'EMIT' lea rcx, [rsp] mov rdx, 1 - sys_print_string + call os_print_string add rsp, 8 popr rax @@ -265,12 +221,7 @@ forth_asm KEY, 'KEY' jne .from_buffer ;; Reading user input - push rsi - mov rsi, .buffer - sys_read_char - pop rsi - - movzx rax, byte [.buffer] + call os_read_char ret .from_buffer: @@ -341,7 +292,7 @@ forth_asm TELL, 'TELL' pop rdx ; Length pop rcx ; Buffer - sys_print_string + call os_print_string popr rsi popr rax @@ -349,7 +300,8 @@ forth_asm TELL, 'TELL' ;; Exit the program cleanly. forth_asm TERMINATE, 'TERMINATE' - sys_terminate 0 + mov rax, 0 + call os_terminate ;; Duplicate a pair of elements. forth_asm PAIRDUP, '2DUP' @@ -438,7 +390,7 @@ forth_asm DOTU, '.U' ;; Print the buffer mov rcx, .buffer mov rdx, [.printed_length] - sys_print_string + call os_print_string ;; Restore RSI and continue execution pop rsi @@ -511,10 +463,7 @@ forth_asm READ_STRING, 'S"' mov [.length], 0 .read_char: - mov rsi, .char_buffer - sys_read_char - - mov al, [.char_buffer] + call os_read_char cmp al, '"' je .done @@ -639,6 +588,69 @@ forth MAIN, 'MAIN' dq BRANCH, -8 * 2 dq TERMINATE +;; EFI: + +forth EFI_SYSTEM_TABLE_CONSTANT, 'SystemTable' + dq LIT, system_table, GET + dq EXIT + +forth_asm EFICALL2, 'EFICALL2' + pop rax ; function pointer + pop rdx ; 2nd argument + pop rcx ; 1st argument + + sub rsp, 32 + call rax + add rsp, 32 + + next + +forth_asm EFICALL3, 'EFICALL3' + pop rax ; function pointer + pop r8 ; 3rd argument + pop rdx ; 2nd argument + pop rcx ; 1st argument + + sub rsp, 32 + call rax + add rsp, 32 + + push rax + + next + +forth_asm EFICALL10, 'EFICALL10' + pop rax ; function pointer + + mov rcx, [rsp + 8 * 9] + mov rdx, [rsp + 8 * 8] + mov r8, [rsp + 8 * 7] + mov r9, [rsp + 8 * 6] + + ;; Reverse order of stack arguments + mov r10, [rsp + 8 * 5] + mov r11, [rsp + 8 * 0] + mov [rsp + 8 * 5], r11 + mov [rsp + 8 * 0], r10 + + mov r10, [rsp + 8 * 4] + mov r11, [rsp + 8 * 1] + mov [rsp + 8 * 4], r11 + mov [rsp + 8 * 1], r10 + + mov r10, [rsp + 8 * 3] + mov r11, [rsp + 8 * 2] + mov [rsp + 8 * 3], r11 + mov [rsp + 8 * 2], r10 + + sub rsp, 32 + call rax + add rsp, 32 + 8 * 10 + + push rax + + next + ;; Built-in variables: forth STATE, 'STATE' @@ -666,7 +678,7 @@ forth INPUT_LENGTH, 'INPUT-LENGTH' dq LIT, input_buffer_length dq EXIT -section '.data' readable writable +os_data_section ;; 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 @@ -714,6 +726,8 @@ return_stack_top: ;; 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. -sysf file 'sys.f' +sysf: +file 'sys.f' +file 'uefi.f' sysf.len = $ - sysf