summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandromeda <andromeda@lenovo>2026-03-30 16:09:25 +0200
committerandromeda <andromeda@lenovo>2026-03-30 16:09:25 +0200
commitf789d49e8a570db87d49886bb91ed2d8a62a492f (patch)
tree370a8d731713d4db52564ef9fbc3bb427df4f254
parentb1e7d2e3d53e2560d5cdb3f6c27478be4c7f0081 (diff)
tokenise labels and constants! Now assembly highkey fails but ok
-rw-r--r--bootler/asm/boot.asm2
-rw-r--r--twasm/README.md109
-rw-r--r--twasm/asm/main.asm343
3 files changed, 342 insertions, 112 deletions
diff --git a/bootler/asm/boot.asm b/bootler/asm/boot.asm
index 85b9a63..8e3e534 100644
--- a/bootler/asm/boot.asm
+++ b/bootler/asm/boot.asm
@@ -6,7 +6,7 @@
LOAD_ADDR equ 0x7C00
KERNEL_START equ 2 ; first sector on disk to load kernel from; 1 indexed
-KERNEL_SIZE equ 16 ; length of kernel in sectors
+KERNEL_SIZE equ 32 ; length of kernel in sectors
KERNEL_LOAD_ADDR_ES equ 0x1000 ; kernel to be loaded at es * 0x10 + 0x0000
PAGE_TABLE_LOAD_ADDR equ 0x1000 ; start of page table; 4 * pt size
diff --git a/twasm/README.md b/twasm/README.md
index 77905a6..774f568 100644
--- a/twasm/README.md
+++ b/twasm/README.md
@@ -22,11 +22,14 @@ tokeniser
------------------------
byte(s) -> next byte(s)
------------------------
-Newline -> Newline
+Newline -> Label
+ -> Newline
-> Komment
-> Operator
-> Directive
+Label -> Newline
+
Komment -> Newline
Operator -> Newline
@@ -45,37 +48,6 @@ Directive -> Newline
------------------------
```
-not yet implemented:
-
-```
-------------------------
-operand parser
-------------------------
-byte(s) -> next byte(s)
-------------------------
-START -> '['
- -> Register
- -> Constant
-
-'[' -> Register
- -> Constant
-
-']' -> END
-
-Register -> IF #[, ']'
- -> Operator
-
-Constant -> IF #[, ']'
- -> Operator
-
-Operator -> IF NOT #R, Register
- -> Constant
-------------------------
-:R: = whether a register has been found
-:[: = whether a '[' has been found
-------------------------
-```
-
### memory map
```
@@ -88,6 +60,10 @@ Operator -> IF NOT #R, Register
+------ 0x00060000 ------+
| test arena |
+------ 0x00050000 ------+
+| label table |
++------ 0x00040000 ------+
+| awaiting label table |
++------ 0x00030000 ------+
| stack (rsp) |
+------------------------+
| input |
@@ -105,6 +81,7 @@ each word represents a token on the token table.
each token gets loaded into the token table with the following form:
```
+2 bytes
+----------+
| 15 0 |
+----------+
@@ -112,6 +89,40 @@ each token gets loaded into the token table with the following form:
+----------+
```
+#### label table (LT)
+
+label definitions are stored and recalled from this table. The memory addresses are relative to the start of the program
+
+```
+16 bytes
++---------+
+| 127 64 |
++---------+
+| address |
++---------+
+| 63 0 |
++---------+
+| hash |
++---------+
+```
+
+#### awaiting label table (ALT)
+
+forward references are stored in this table to be filled in after assembly is otherwise complete. The memory addresses are relative to the start of the program
+
+```
+16 bytes
++----------+----------+------------------+---------+
+| 127 105 | 104 104 | 103 96 | 95 64 |
++----------+----------+------------------+---------+
+| reserved | abs flag | # bytes reserved | address |
++----------+----------+------------------+---------+
+| 63 0 |
++--------------------------------------------------+
+| hash |
++--------------------------------------------------+
+```
+
### internal data structures
#### `tokens.[operators|registers]`
@@ -121,6 +132,7 @@ contains tokens by their type. Intended to be searched by token name to get the
each entry is in the following form:
```
+6 bytes
+----------+--------------------------------+
| 47 32 | 31 0 |
+----------+--------------------------------+
@@ -129,26 +141,16 @@ each entry is in the following form:
```
-example implementation:
-
-```nasm
-tokens
- .registers:
- dd "r8"
- dw 0x0008
- .by_name3: ; this is required for futureproofness; the caller can use this to
- ; find the size of registers.by_name2
-```
-
note that tokens longer than 4 bytes are problematic :/
#### `tokens.by_id`
-contains some tokens with their metadata. Some tokens have embedded information (`0x10XX` for instance). Those will not have entries in this table, being handled instead inside the assemble function itself.
+contains some tokens with their metadata. Some tokens have embedded information (`0x10XX` for instance). Those do not have entries in this table, being handled instead inside the assemble function itself.
metadata about some tokens in the following form:
```
+4 bytes
+----------------+----------+-------+----------+
| 31 24 | 23 20 | 19 16 | 15 0 |
+----------------+----------+-------+----------+
@@ -168,6 +170,7 @@ the `type` hex digit is defined as the following:
type metadata for the different types is as follows:
```
+1 byte
+----------+
| type 0x0 |
+----------+
@@ -178,6 +181,7 @@ type metadata for the different types is as follows:
```
```
+1 byte
+-------------------------------+
| type 0x1 |
+----------+--------------------+
@@ -188,6 +192,7 @@ type metadata for the different types is as follows:
```
```
+1 byte
+------------------------------+
| type 0x2 |
+----------+-----------+-------+
@@ -210,6 +215,7 @@ type metadata for the different types is as follows:
entries are as follows:
```
+16 bytes
+------------------------------+
| 0 operand operators |
+------------------------------+
@@ -230,6 +236,7 @@ entries are as follows:
| reserved | opcode | token ID |
+----------+--------+----------+
+16 bytes
+-------------------------------------------------------------+
| 1 operand operators |
+-------------------------------------------------------------+
@@ -252,6 +259,7 @@ entries are as follows:
| | dst=r/m | |
+----------+---------------+----------------------------------+
+16 bytes
+----------------------------------------------+
| 2 operand operators |
+----------------------------------------------+
@@ -389,14 +397,23 @@ supported tokens are listed below
| ret | 0x005A | |
| cmp | 0x005B | |
| | 0x10XX | some memory address; `XX` is as specified below |
-| | 0xFEXX | used to pass some raw value `XX` in place of a token id |
+| | 0x20XX | some constant; `XX` is as specified below |
+| | 0x3XXX | some label definition; `XXX` is its entry index in the label table |
+| | 0x4XXX | some label reference; `XXX` is its entry index in the label table
+| | 0xFEXX | used to pass some raw value `XX` in place of a token id to a couple of functions that mention this as a feature. If the function doesn't mention it, it will lead to undefined behaviour |
| | 0xFFFF | unrecognised token |
values of `XX` in `0x10XX`:
| XX | description |
|------|-------------|
-| 0x00 | following byte is the token ID of some register |
+| 0x00 | following word is the token ID of some register |
+
+values of `XX` in `0x20XX`:
+
+| XX | description |
+|------|-------------|
+| 0x00 | following 8 bytes are the constant's value |
### example program
diff --git a/twasm/asm/main.asm b/twasm/asm/main.asm
index 0383da2..156bf02 100644
--- a/twasm/asm/main.asm
+++ b/twasm/asm/main.asm
@@ -2,16 +2,21 @@
LOAD_ADDR equ 0x00010000 ; address this program is loaded at
+STACK_ADDR equ 0x00030000 ; address to put the 64-bit stack at
+
+AWAITING_LABEL_TABLE_ADDR equ 0x00030000 ; address to store pending labels at
+AWAITING_LABEL_TABLE_SIZE equ 0x00010000
+LABEL_TABLE_ADDR equ 0x00040000 ; address to store labels at
+LABEL_TABLE_SIZE equ 0x00010000
+
TEST_ARENA_ADDR equ 0x00050000 ; address to run tests at
-TEST_ARENA_SIZE equ 0x1000 ; maximum size tests can use
+TEST_ARENA_SIZE equ 0x00010000 ; maximum size tests can use
TOKEN_TABLE_ADDR equ 0x00060000 ; address the token table is loaded at
-TOKEN_TABLE_SIZE equ 0x1000 ; max length of table
+TOKEN_TABLE_SIZE equ 0x00010000 ; max length of table
OUTPUT_ADDR equ 0x00070000 ; address of outputed binary
-OUTPUT_SIZE equ 0x1000 ; max length of outputed binary
-
-STACK_ADDR equ 0x00060000 ; address to put the 64-bit stack at
+OUTPUT_SIZE equ 0x00010000 ; max length of outputed binary
UNRECOGNISED_TOKEN_ID equ 0xFFFF ; id of an unrecognised token
UNRECOGNISED_ID_TYPE equ 0x0F ; type of an unrecognised id
@@ -27,6 +32,7 @@ E_WHITESPACE equ 1 << 2
E_COMMA equ 1 << 3
E_OPERATOR equ 1 << 4
E_OPERAND equ 1 << 5
+E_LABEL equ 1 << 6
[bits 64]
[org LOAD_ADDR]
@@ -43,6 +49,7 @@ start:
call run_tests
call clear_token_table
+ call clear_label_tables
mov rdi, program ; -> program
mov rsi, [program.size] ; = size of program
@@ -98,6 +105,7 @@ assemble:
cmp al, 0x1 ; check if next tte is an operator
je .operator ; if so, handle
+
jmp .unexpected_token ; otherwise, fail
.operator: ; if next tte's type is an operator:
@@ -120,7 +128,6 @@ assemble:
je .operator_2 ; if so, handle case of two operands
jmp .unexpected_token
-
.operator_0:
mov rsi, .msg_operator_0
call print.debug
@@ -133,7 +140,6 @@ assemble:
call .write_byte
jmp .loop_next_token
-
.operator_1:
mov rsi, .msg_operator_1
call print.debug
@@ -167,12 +173,10 @@ assemble:
je .operator_1_register
jmp .unexpected_token
-
.operator_1_memory:
mov rsi, .msg_operator_1_memory
call print.debug
jmp .unsupported_memory_access
-
.operator_1_register:
mov rsi, .msg_operator_1_register
call print.debug
@@ -213,7 +217,6 @@ assemble:
call .write_byte
jmp .loop_next_token
-
.operator_2:
mov rsi, .msg_operator_2
call print.debug
@@ -240,7 +243,6 @@ assemble:
je .operator_2_register
jmp .unexpected_token
-
.operator_2_memory:
mov rsi, .msg_operator_2_memory
call print.debug
@@ -319,7 +321,6 @@ assemble:
cmp al, 11b ; 64 bit
je .operator_2_memory_register_64
-
.operator_2_memory_register_16:
mov al, 0x66
call .push_byte
@@ -337,7 +338,6 @@ assemble:
call .write_byte
jmp .loop_next_token
-
.operator_2_register:
mov rsi, .msg_operator_2_register
call print.debug
@@ -398,7 +398,6 @@ assemble:
je .operator_2_register_register ; if so, handle
jmp .unexpected_token
-
.operator_2_register_memory:
push rsi
mov rsi, .msg_operator_2_register_memory
@@ -441,7 +440,6 @@ assemble:
call .write_byte
jmp .loop_next_token
-
.operator_2_register_register:
push rsi
mov rsi, .msg_operator_2_register_register
@@ -543,7 +541,6 @@ assemble:
jmp .operator_2_register_register_continue
.operator_2_register_register_continue:
-
push rsi
mov esi, edi ; si = reg; src tte
pop rdi ; di = r/m; dst tte
@@ -658,7 +655,7 @@ assemble:
call .output_byte
mov byte [ecx], 0x00
jmp .flush_write_buffer_loop
- .flush_write_buffer_break
+ .flush_write_buffer_break:
mov dword [.buffer_pointer], .buffer
pop rax
pop rcx
@@ -680,6 +677,7 @@ assemble:
.msg_operator_2_register db "operator_2_register", 0x0A, 0x00
.msg_operator_2_register_memory db "operator_2_register_memory", 0x0A, 0x00
.msg_operator_2_register_register db "operator_2_register_register", 0x0A, 0x00
+ .msg_potential_label db "potential_label", 0x0A, 0x00
; ------------------------------------------------------------------------------
; get_tte_type
@@ -956,9 +954,11 @@ tokenise:
pop rsi ; rsi -> last byte of program
jnz .skip_byte_whitespace
- test byte [.expecting], E_OPERATOR ; check if an operator is expected
+ test byte [.expecting], E_LABEL ; check if a label is expected
+ jnz .label ; if so, handle it
+ test byte [.expecting], E_OPERATOR ; else, check if an operator is expected
jnz .operator ; if so, handle it
- jmp .operand ; otherwise, handle as an operand
+ jmp .operand ; else, handle as an operand
.comment:
push rsi
@@ -1021,11 +1021,72 @@ tokenise:
test byte [.expecting], E_NEWLINE ; make sure a newline was expected
jz .unexpected_newline ; if not, error
- mov byte [.expecting], E_COMMENT | E_NEWLINE | E_WHITESPACE | E_OPERATOR
+ mov byte [.expecting], E_COMMENT | E_NEWLINE | E_WHITESPACE | E_OPERATOR | E_LABEL
inc rdi
jmp .loop
+ .label:
+ push rax
+ xor eax, eax ; rax = number of bytes in label
+ .label_loop:
+ mov dl, [rdi + rax] ; next byte
+ cmp dl, ":"
+ je .label_break
+ cmp dl, " "
+ je .label_not_found
+ cmp dl, 0x0A
+ je .label_not_found
+ cmp dl, 0x00
+ je .label_not_found
+ cmp dl, ";"
+ je .label_not_found
+ inc eax ; inc byte counter
+ cmp rdi, rsi
+ jge .break
+ jmp .label_loop
+ .label_break:
+ push rsi
+ mov rsi, .found
+ call print.debug
+ mov rsi, .msg_label
+ call print
+ pop rsi ; rsi -> last byte of program
+
+ push rax
+ push rdi
+ push rsi
+
+ mov rsi, rdi ; rsi -> start of string
+ mov rdi, rax ; rdi = size of string
+ call djb2
+ ; rax = hash
+ mov rdi, rax ; rdi = hash
+ call add_label_hash
+ ; rax = index on label table
+ mov cx, ax
+ and cx, 0x0FFF
+ or cx, 0x3000
+
+ pop rsi ; rsi -> last byte of program
+ pop rdi ; rdi -> current byte of program
+ pop rax ; rax = number of bytes in label
+
+ add rdi, rax ; move on to next byte
+ inc rdi ; move past the colon
+
+ pop rax ; rax = number of tokens processed
+
+ mov [TOKEN_TABLE_ADDR + rax * 2], cx
+ inc rax ; the next token
+
+ mov byte [.expecting], E_COMMENT | E_NEWLINE | E_WHITESPACE
+ jmp .loop
+ .label_not_found:
+ pop rax ; rax = number of tokens processed
+ mov byte [.expecting], E_COMMENT | E_NEWLINE | E_WHITESPACE | E_OPERATOR
+ jmp .loop
+
.operator:
; debug message
push rsi
@@ -1038,7 +1099,6 @@ tokenise:
mov rcx, rax ; rcx = number of tokens processed
xor eax, eax ; eax = number of bytes in operator
mov [.pending_operator], eax ; zero pending operator
-
.operator_loop:
; TODO give this its own error
@@ -1063,7 +1123,6 @@ tokenise:
cmp rdi, rsi
jge .break
jmp .operator_loop ; and loop
-
.operator_break:
; rax already pushed from .operator
push rdi
@@ -1097,7 +1156,6 @@ tokenise:
push rax
push rdi
xor eax, eax ; rax = length of operand
-
.operand_loop:
mov dl, [rdi]
@@ -1113,7 +1171,6 @@ tokenise:
inc rax ; inc length counter
inc rdi ; inc byte pointer
jmp .operand_loop
-
.operand_break:
pop rdi ; rdi -> first byte of operand
push rdi
@@ -1121,9 +1178,11 @@ tokenise:
mov rsi, rax ; rsi = length of operand in bytes
mov cx, ax ; cx = length counter for safe keeping
+ push rcx
call evaluate_operand
; dl = return code
; rax = binary data
+ pop rcx
pop rsi
pop rdi ; rdi = first byte of operand
add di, cx ; rdi = last byte of operand
@@ -1131,31 +1190,48 @@ tokenise:
pop rax ; rax = number of tokens processed
; operand is some reg
- ; cx = token ID
cmp dl, 0x00
+ ; cx = token ID
je .operand_register
; operand is some [reg]
- ; cx = token ID
cmp dl, 0x10
+ ; cx = token ID
je .operand_addr_register
- jmp .unexpected_operand
+ ; operand is some constant
+ cmp dl, 0x20
+ ; rcx = constant value
+ je .operand_constant
+
+ ; operand is some label
+ cmp dl, 0x30
+ ; rcx = index of label in LT
+ je .operand_label
- ; cx = token ID
+ jmp .unexpected_operand
.operand_register:
mov [TOKEN_TABLE_ADDR + rax * 2], cx
inc rax ; another token processed
jmp .operand_break_continue
-
- ; cx = token ID
.operand_addr_register:
mov word [TOKEN_TABLE_ADDR + rax * 2], 0x1000
inc rax ; 0x1000: addr reg token, next token is the register
mov [TOKEN_TABLE_ADDR + rax * 2], cx
inc rax ; the register as returned by evaluate_operand
jmp .operand_break_continue
-
+ .operand_constant:
+ mov word [TOKEN_TABLE_ADDR + rax * 2], 0x2000
+ inc rax ; another token processed
+ mov [TOKEN_TABLE_ADDR + rax * 2], rcx
+ add rax, 4
+ jmp .operand_break_continue
+ .operand_label:
+ and cx, 0x0FFF
+ or cx, 0x3000
+ mov [TOKEN_TABLE_ADDR + rax * 2], cx
+ inc rax
+ jmp .operand_break_continue
.operand_break_continue:
mov byte [.expecting], E_COMMENT | E_NEWLINE | E_WHITESPACE | E_COMMA
jmp .loop
@@ -1164,8 +1240,7 @@ tokenise:
ret
; state
-
- .expecting db E_COMMENT | E_NEWLINE | E_WHITESPACE | E_OPERATOR
+ .expecting db E_COMMENT | E_NEWLINE | E_WHITESPACE | E_OPERATOR | E_LABEL
.unexpected_whitespace:
mov rsi, .err_unexpected
@@ -1209,6 +1284,7 @@ tokenise:
.msg_comment db "comment.", 0x0A, 0x00
.msg_newline db "newline.", 0x0A, 0x00
.msg_comma db "comma.", 0x0A, 0x00
+ .msg_label db "label.", 0x0A, 0x00
.msg_operator db "operator.", 0x0A, 0x00
.msg_operand db "operand.", 0x0A, 0x00
.pending_operator dd 0 ; the operator token that is pending processing
@@ -1220,10 +1296,12 @@ tokenise:
; takes the location and length of an operand and evaluates it into binary data
; and a return code to interpret the binary data.
;
-; | code | rsi contents | notes |
+; | code | rax contents | notes |
; |------|----------------------|-------|
; | 0x00 | token ID of register | reg |
; | 0x10 | token ID of register | [reg] |
+; | 0x20 | constant value | const |
+; | 0x30 | index of label in LT | label |
; | 0xFF | - | error |
;
; parameters:
@@ -1239,6 +1317,7 @@ evaluate_operand:
push rdi ; rdi -> start of operand
; rsi = size of operand
call trim_trailing_whitespace
+ ; rax = new size of operand
pop rdi ; rdi -> first byte of operand
mov rsi, rax ; rsi = size of operand w/o trailing whitespace
@@ -1249,7 +1328,7 @@ evaluate_operand:
cmp byte [rdi], '[' ; case: memory addressing
je .address
- jmp .register ; otherwise: register
+ jmp .register ; otherwise: register (or constant, or label)
.address:
cmp byte [rdi + rsi - 1], ']' ; check if address is closed correctly
@@ -1262,12 +1341,13 @@ evaluate_operand:
cmp dl, 0x10 ; make sure return code isn't another memory reference
je .unrecognised ; if it is, fail
- or dl, 0x10 ; flip bit for address return
+ shr edx, 4
+ or dl, 0x10 ; address return
ret
.register:
cmp rsi, 4
- jg .unrecognised
+ jg .constant ; not a register: too long. Maybe constant?
push rdi
mov edi, [rdi] ; edi = register to be searched
@@ -1288,18 +1368,47 @@ evaluate_operand:
.register3:
and edi, 0xFFFFFF
.register4:
-
call identify_register
; ax = register's token ID or UNRECOGNISED_TOKEN_ID
- pop rdi
+ pop rdi ; rdi -> first byte of operand
- cmp ax, UNRECOGNISED_TOKEN_ID
- je .unrecognised
+ cmp ax, UNRECOGNISED_TOKEN_ID ; if not a register, constant?
+ je .constant
mov dl, 0x00
ret
+ .constant:
+ push rdi
+ push rsi
+ ; rdi -> first byte of constant
+ ; rsi = size of constant in bytes
+ call evaluate_constant
+ ; dl = type of constant
+ ; rax = hex value of constant
+ pop rdi ; rdi = size of label in bytes
+ pop rsi ; rsi -> first byte of label
+
+ cmp dl, 0xFF
+ je .label
+
+ ; rax = hex value of constant
+ mov dl, 0x20
+ ret
+
+ .label:
+ ; rdi = size of label in bytes
+ ; rsi -> first byte of label
+ call djb2
+ ; rax = hash
+ mov rdi, rax ; rdi = hash
+ call add_label_hash
+ ; rax = index in LT of label
+ mov dl, 0x30
+ ret
+
.unrecognised:
+ xor eax, eax
mov dl, 0xFF
ret
@@ -1353,6 +1462,7 @@ evaluate_constant:
je .chr
pop rcx
+ push rcx ; waste value; .unrecognise expects something on the stack
jmp .unrecognised
.numeric:
@@ -1396,12 +1506,10 @@ evaluate_constant:
cmp dl, 9 ; if !digit:
jg .hex_alpha ; letter
jmp .hex_continue ; else loop
-
.hex_alpha:
sub dl, 7 ; map [('A'-'0')..('F'-'0')] to [0xA..0xF]
cmp dl, 0xF ; if not in the range [0xA..0xF]
jg .unrecognised ; then unrecognised
-
.hex_continue:
and dl, 0x0F ; mask
or al, dl ; and add newest nibble
@@ -1471,14 +1579,12 @@ evaluate_constant:
inc rdi
jmp .chr
-
.chr_break:
cmp rcx, 1 ; for each [1..rcx]
jle .chr_break_for_good
rol rax, 8 ; roll left to make up for the roll right earlier
dec rcx
jmp .chr_break
-
.chr_break_for_good:
mov dl, [rdi] ; make sure the chr is closed
cmp dl, '"'
@@ -1492,8 +1598,9 @@ evaluate_constant:
.unrecognised:
pop rdx
- mov rdx, 0xFF ; unrecognised type
+ mov edx, 0xFF ; unrecognised type
ret
+ .msg db "evaluate_constant", 0x0A, 0x00
; ------------------------------------------------------------------------------
; identify_register
@@ -1751,6 +1858,38 @@ trim_trailing_whitespace:
ret
; ------------------------------------------------------------------------------
+; add_label_hash
+;
+; description:
+; adds a label hash to the label table, or just finds it if already present
+;
+; parameters
+; rdi = 64-bit hash to be added
+;
+; returned
+; rax = index in label table
+; ------------------------------------------------------------------------------
+
+add_label_hash:
+ xor eax, eax
+ .loop:
+ cmp rax, LABEL_TABLE_SIZE
+ jge .break
+ mov rcx, [LABEL_TABLE_ADDR + rax]
+ ; TODO bug if there's an empty slot before the entry, it won't be found
+ cmp rcx, 0 ; empty slot
+ je .break
+ cmp rcx, rdi ; already present
+ je .break
+ add rax, 16
+ jmp .loop
+ .break:
+ mov [LABEL_TABLE_ADDR + rax], rdi
+ shr rax, 4 ; rax / 16
+ ; rax = index
+ ret
+
+; ------------------------------------------------------------------------------
; clear_token_table
;
; description:
@@ -1765,6 +1904,26 @@ clear_token_table:
ret
; ------------------------------------------------------------------------------
+; clear_label_tables
+;
+; description:
+; clears the label table as specified by LABEL_TABLE_SIZE and LABEL_TABLE_ADDR
+; and the awaiting label table as specified by AWAITING_LABEL_TABLE_SIZE and
+; AWAITING_LABEL_TABLE_ADDR
+; ------------------------------------------------------------------------------
+
+clear_label_tables:
+ xor eax, eax ; value to write
+ mov ecx, LABEL_TABLE_SIZE / 4 ; number of double words
+ mov edi, LABEL_TABLE_ADDR ; address to start
+ rep stosd
+ xor eax, eax ; value to write
+ mov ecx, AWAITING_LABEL_TABLE_SIZE / 4 ; number of double words
+ mov edi, AWAITING_LABEL_TABLE_ADDR ; address to start
+ rep stosd
+ ret
+
+; ------------------------------------------------------------------------------
; clear_test_arena
;
; description:
@@ -1772,9 +1931,9 @@ clear_token_table:
; ------------------------------------------------------------------------------
clear_test_arena:
- xor eax, eax ; value to write
- mov ecx, TOKEN_TABLE_SIZE / 4 ; number of double words
- mov edi, TOKEN_TABLE_ADDR ; address to start
+ xor eax, eax ; value to write
+ mov ecx, TEST_ARENA_SIZE / 4 ; number of double words
+ mov edi, TEST_ARENA_ADDR ; address to start
rep stosd
ret
@@ -2341,22 +2500,76 @@ whitespace_2 db " ", 0x0D
; test program
program:
- db "xor eax, eax", 0x0A
- db "mov rax, rax", 0x0A
- db "mov rax, rbx", 0x0A
- db "mov eax, ebx", 0x0A
- db "mov ax, bx", 0x0A
- db "inc rax ; inline comment", 0x0A
- db "dec rax", 0x0A
- db "; one line comment", 0x0A
- db "mov rdx, [rax]", 0x0A
- db "mov [rax], rdx", 0x0A
- db "mov [rcx], rbx", 0x0A
- db "mov rcx, [rbx]", 0x0A
- db "mov rcx, [ebx]", 0x0A
- db "mov ecx, [ebx]", 0x0A
- db "mov cx, [ebx]", 0x0A
- db "hlt", 0x0A
+ db "print:", 0x0A
+ db " push rdx", 0x0A
+ db " push rax", 0x0A
+ db " push rsi", 0x0A
+ db "", 0x0A
+ db " mov edx, 0x3F8", 0x0A
+ db " .loop:", 0x0A
+ db " mov al, [rsi]", 0x0A
+ db " cmp al, 0x00", 0x0A
+ db " je .done", 0x0A
+ db " out dx, al", 0x0A
+ db " inc rsi", 0x0A
+ db " jmp .loop", 0x0A
+ db " .done:", 0x0A
+ db " pop rsi", 0x0A
+ db " pop rax", 0x0A
+ db " pop rdx", 0x0A
+ db " ret", 0x0A
+ db " .debug:", 0x0A
+ db " push rsi", 0x0A
+ db " mov rsi, .debug_msg", 0x0A
+ db " call print", 0x0A
+ db " pop rsi", 0x0A
+ db " jmp print ; tail call", 0x0A
+ db " .error:", 0x0A
+ db " push rsi", 0x0A
+ db " mov rsi, .error_msg", 0x0A
+ db " call print", 0x0A
+ db " pop rsi", 0x0A
+ db " jmp print ; tail call", 0x0A
+ db " .test:", 0x0A
+ db " push rsi", 0x0A
+ db " mov rsi, .test_msg", 0x0A
+ db " call print", 0x0A
+ db " pop rsi", 0x0A
+ db " jmp print ; tail call", 0x0A
+ db " .warn:", 0x0A
+ db " push rsi", 0x0A
+ db " mov rsi, .warn_msg", 0x0A
+ db " call print", 0x0A
+ db " pop rsi", 0x0A
+ db " jmp print ; tail call", 0x0A
+ db " .debug_msg:", 0x0A
+ db " db 0x1B", 0x0A
+ db ' db "[36m"', 0x0A
+ db ' db "[DEBUG]: "', 0x0A
+ db " db 0x1B", 0x0A
+ db ' db "[0m"', 0x0A
+ db " db 0x00", 0x0A
+ db " .error_msg:", 0x0A
+ db " db 0x1B", 0x0A
+ db ' db "[1;31m"', 0x0A
+ db ' db "[ERROR]: "', 0x0A
+ db " db 0x1B", 0x0A
+ db ' db "[0m"', 0x0A
+ db " db 0x00", 0x0A
+ db " .test_msg:", 0x0A
+ db " db 0x1B", 0x0A
+ db ' db "[1;33m"', 0x0A
+ db ' db "[TEST]: "', 0x0A
+ db " db 0x1B", 0x0A
+ db ' db "[0m"', 0x0A
+ db " db 0x00", 0x0A
+ db " .warn_msg:", 0x0A
+ db " db 0x1B", 0x0A
+ db ' db "[1;35m"', 0x0A
+ db ' db "[WARN]: "', 0x0A
+ db " db 0x1B", 0x0A
+ db ' db "[0m"', 0x0A
+ db " db 0x00", 0x0A
.size dq $ - program
msg_end db "end of the binary ->|", 0x0A, 0x00