X-Git-Url: https://git.rrq.au/?a=blobdiff_plain;f=src%2Fmain.asm;h=3af5713ba81790adf989d42a777bf744c59f0409;hb=3ee67e335626610219a3c08ba38263547f5afff8;hp=d1d89fb159a71c3a928867094aa499ee9213c4dc;hpb=184d6bc9567f2e1efe1a9a39263f0be4ef1d5c96;p=rrq%2Fjonasforth.git diff --git a/src/main.asm b/src/main.asm index d1d89fb..3af5713 100644 --- a/src/main.asm +++ b/src/main.asm @@ -1,5 +1,6 @@ -;; The UEFI module defines the following functions. Each of these functions -;; preserve the value of RSI and RSP. They may use other registers as they like. +;; The UEFI module defines the following functions. Each of these +;; functions preserve the value of RSI and RSP. They may use other +;; registers as they like. ;; ;; os_initialize ;; Called at initialization. @@ -14,6 +15,7 @@ ;; ;; os_terminate ;; Shut down the system, returning the error code given in RAX. + include 'src/uefi.asm' ;; The code in this macro is placed at the end of each Forth word. When we are @@ -66,7 +68,8 @@ label: initial_latest_entry = label#_entry } -;; Define a Forth word that is implemented in assembly. See 'header' for details. +;; Define a Forth word that is implemented in assembly. See 'header' +;; for details. macro forth_asm label, name, immediate { header label, name, immediate dq .start @@ -79,7 +82,7 @@ include "impl.asm" ; Misc. subroutines include "bootstrap.asm" ; Forth words encoded in Assembly main: - cld ; Clear direction flag so LODSQ does the right thing. + cld ; Clear direction flag so LODSQ does the right thing. mov rbp, return_stack_top ; Initialize return stack call os_initialize @@ -89,12 +92,15 @@ main: program: dq MAIN -;; The codeword is the code that will be executed at the beginning of a forth -;; word. It needs to save the old RSI and update it to point to the next word to -;; execute. +;; The codeword is the code that will be executed at the beginning of +;; a forth word. It needs to save the old RSI and update it to point +;; to the next word to execute. header DOCOL, 'DOCOL' - pushr rsi ; Save old value of RSI on return stack; we will continue execution there after we are done executing this word - lea rsi, [rax + 8] ; RAX currently points to the address of the codeword, so we want to continue at RAX+8 + pushr rsi ; Save old value of RSI on return stack; we + ; will continue execution there after we are + ; done executing this word + lea rsi, [rax + 8] ; RAX currently points to the address of the + ; codeword, so we want to continue at RAX+8 next ; Execute word pointed to by RSI ;; This word is called at the end of a Forth definition. It just needs to @@ -103,16 +109,16 @@ forth_asm EXIT, 'EXIT' popr rsi next -;; LIT is a special word that reads the next "word pointer" and causes it to be -;; placed on the stack rather than executed. +;; LIT is a special word that reads the next "word pointer" and causes +;; it to be placed on the stack rather than executed. forth_asm LIT, 'LIT' lodsq push rax next -;; When LITSTRING is encountered while executing a word, it instead reads a -;; string from the definition of that word, and places that string on the stack -;; as (buffer, length). +;; When LITSTRING is encountered while executing a word, it instead +;; reads a string from the definition of that word, and places that +;; string on the stack as (buffer, length). forth_asm LITSTRING, 'LITSTRING' lodsb push rsi ; Buffer @@ -121,8 +127,9 @@ forth_asm LITSTRING, 'LITSTRING' add rsi, rax ; Skip over string before resuming execution next -;; Given a string (a pointer following by a size), return the location of the -;; dictionary entry for that word. If no such word exists, return 0. +;; Given a string (a pointer following by a size), return the location +;; of the dictionary entry for that word. If no such word exists, +;; return 0. forth_asm FIND, 'FIND' mov [.rsi], rsi @@ -139,8 +146,8 @@ forth_asm FIND, 'FIND' mov rsi, [.rsi] next -;; Given an entry in the dictionary, return a pointer to the codeword of that -;; entry. +;; Given an entry in the dictionary, return a pointer to the codeword +;; of that entry. forth_asm TCFA, '>CFA' pop rax add rax, 8 + 1 ; [rax] = length of name @@ -150,22 +157,25 @@ forth_asm TCFA, '>CFA' push rax next -;; BRANCH is the fundamental mechanism for branching. BRANCH reads the next word -;; as a signed integer literal and jumps by that offset. +;; BRANCH is the fundamental mechanism for branching. BRANCH reads the +;; next word as a signed integer literal and jumps by that offset. + forth_asm BRANCH, 'BRANCH' - add rsi, [rsi] ; [RSI], which is the next word, contains the offset; we add this to the instruction pointer. + add rsi, [rsi] ; [RSI], which is the next word, contains the offset + ; we add this to the instruction pointer. next ; Then, we can just continue execution as normal -;; 0BRANCH is like BRANCH, but it jumps only if the top of the stack is zero. +;; 0BRANCH is like BRANCH, but it jumps only if the top of the stack +;; is zero. forth_asm ZBRANCH, '0BRANCH' - ;; Compare top of stack to see if we should branch pop rax - cmp rax, 0 + cmp rax, 0 ; Compare top of stack to see if we should branch jnz .dont_branch .do_branch: jmp BRANCH.start .dont_branch: - add rsi, 8 ; We need to skip over the next word, which contains the offset. + add rsi, 8 ; We need to skip over the next word, which contains + ; the offset. next ;; Duplicate the top of the stack. @@ -192,10 +202,10 @@ forth_asm EMIT, 'EMIT' popr rsi next -;; Read a single character from the current input stream. Usually, this will wait -;; for the user to press a key, and then return the corresponding character. When -;; reading from a special buffer, it will instead return the next characater from -;; that buffer. +;; Read a single character from the current input stream. Usually, +;; this will wait for the user to press a key, and then return the +;; corresponding character. When reading from a special buffer, it +;; will instead return the next characater from that buffer. ;; ;; The ASCII character code is placed on the stack. forth_asm KEY, 'KEY' @@ -222,8 +232,8 @@ forth_asm KEY, 'KEY' dec [input_buffer_length] ret -;; Read a word and push it onto the stack as a pointer and a size. The pointer -;; is valid until the next call to READ_WORD. +;; Read a word and push it onto the stack as a pointer and a size. The +;; pointer is valid until the next call to READ_WORD. forth_asm READ_WORD, 'READ-WORD' push rsi .skip_whitespace: @@ -260,8 +270,8 @@ forth_asm READ_WORD, 'READ-WORD' next -;; Takes a string on the stack and replaces it with the decimal number that the -;; string represents. +;; Takes a string on the stack and replaces it with the decimal number +;; that the string represents. forth_asm PARSE_NUMBER, 'PARSE-NUMBER' pop rcx ; Length pop rdi ; String pointer @@ -419,8 +429,8 @@ forth_asm PLUS, '+' push rax next -;; Calculate difference between two integers on the stack. The second number is -;; subtracted from the first. +;; Calculate difference between two integers on the stack. The second +;; number is subtracted from the first. forth_asm MINUS, '-' pop rax pop rbx @@ -439,9 +449,10 @@ forth_asm TIMESMOD, '/MOD' push rdx ; a % b next -;; Read input until next " character is found. Push a string containing the -;; input on the stack as (buffer length). Note that the buffer is only valid -;; until the next call to S" and that no more than 255 characters can be read. +;; Read input until next " character is found. Push a string +;; containing the input on the stack as (buffer length). Note that the +;; buffer is only valid until the next call to S" and that no more +;; than 255 characters can be read. forth_asm READ_STRING, 'S"' ;; If the input buffer is set, we should read from there instead. cmp [input_buffer], 0 @@ -504,11 +515,12 @@ read_string_buffer: next -;; CREATE inserts a new header in the dictionary, and updates LATEST so that it -;; points to the header. To compile a word, the user can then call ',' to -;; continue to append data after the header. +;; CREATE inserts a new header in the dictionary, and updates LATEST +;; so that it points to the header. To compile a word, the user can +;; then call ',' to continue to append data after the header. ;; -;; It takes the name of the word as a string (address length) on the stack. +;; It takes the name of the word as a string (address length) on the +;; stack. forth_asm CREATE, 'CREATE' pop rcx ; Word string length pop rdx ; Word string pointer @@ -583,6 +595,16 @@ forth EFI_SYSTEM_TABLE_CONSTANT, 'SystemTable' dq LIT, system_table, GET dq EXIT +forth_asm EFICALL1, 'EFICALL1' + pop rax ; function pointer + pop rcx ; 1st argument + + sub rsp, 32 + call rax + add rsp, 32 + + next + forth_asm EFICALL2, 'EFICALL2' pop rax ; function pointer pop rdx ; 2nd argument @@ -669,18 +691,18 @@ forth INPUT_LENGTH, 'INPUT-LENGTH' 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 -;; used by FIND to look up words. +;; 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 used by FIND to look up words. latest_entry dq initial_latest_entry -;; The STATE variable is 0 when the interpreter is executing, and non-zero when -;; it is compiling. +;; The STATE variable is 0 when the interpreter is executing, and +;; non-zero when it is compiling. var_STATE dq 0 -;; The interpreter can read either from standard input or from a buffer. When -;; input-buffer is set (non-null), words like READ-WORD and S" will use this -;; buffer instead of reading user input. +;; The interpreter can read either from standard input or from a +;; buffer. When input-buffer is set (non-null), words like READ-WORD +;; and S" will use this buffer instead of reading user input. input_buffer dq 0 input_buffer_length dq 0 @@ -694,7 +716,7 @@ READ_STRING.buffer rb $FF READ_STRING.length dq ? DOTU.chars db '0123456789ABCDEF' -DOTU.buffer rq 16 ; 64-bit number has no more than 16 digits in hex +DOTU.buffer rq 16 ; 64-bit number has no more than 16 digits in hex DOTU.rbuffer rq 16 DOTU.length dq ? DOTU.printed_length dq ? @@ -712,9 +734,10 @@ here_top rq $4000 rq $2000 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. +;; 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 '../init/sys.f' file '../init/uefi.f'