summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandromeda <andromeda@lenovo>2026-03-17 21:16:17 +0100
committerandromeda <andromeda@lenovo>2026-03-17 21:16:17 +0100
commite79a30ba713054053e8995639a14b00e8ea1c16f (patch)
treea6ec490c5124362892b7fc78068f41c9a256c842
parent0160d2e127f506bb36625861e2dd91e009583e24 (diff)
add rough char/str parsing
-rw-r--r--twasm/asm/main.asm120
-rw-r--r--twasm/asm/tests.asm21
2 files changed, 120 insertions, 21 deletions
diff --git a/twasm/asm/main.asm b/twasm/asm/main.asm
index c792eb9..2c28dbf 100644
--- a/twasm/asm/main.asm
+++ b/twasm/asm/main.asm
@@ -732,9 +732,11 @@ tokenise:
; | 0x00 | 0x | hexidecimal |
; | 0x01 | 0q | octal |
; | 0x02 | 0b | binary |
+; | 0x03 | '' | ascii char |
+; | 0x04 | "" | ascii string |
; | 0xFF | | unrecognised |
;
-; where `p.` is the prefix
+; where `p.` is the prefix or otherwise indicator
;
; parameters:
; rdi -> first byte of constant
@@ -750,40 +752,62 @@ evaluate_constant:
; rdi -> current byte of constant
xor eax, eax ; rax = value of constant
- ; TODO fix this cheap trick xD
- mov dl, [rdi]
- dec rsi ; one fewer byte left
- inc rdi ; point to next byte
- cmp dl, '0'
- jne .unrecognised
+ ; each case pushes the return value of dl into `rcx`, which is popped into dl
+ ; to return
mov dl, [rdi]
dec rsi ; one fewer byte left
inc rdi ; point to next byte
- ; hex case
- mov rcx, 0x00
- push rcx
- cmp dl, 'x'
- je .hex_loop
- pop rcx
+ ; all numeric prefixes further handled in .numeric
+ cmp dl, '0'
+ je .numeric
- ; octal case
- mov rcx, 0x01
+ ; char case
+ mov rcx, 0x03
push rcx
- cmp dl, 'q'
- je .oct_loop
+ cmp dl, "'"
+ je .chr
pop rcx
- ; binary case
- mov rcx, 0x02
+ ; str case
+ mov rcx, 0x04
push rcx
- cmp dl, 'b'
- je .bin_loop
+ xor ecx, ecx ; rcx = number of times right-rolled
+ cmp dl, '"'
+ je .str
pop rcx
jmp .unrecognised
+ .numeric:
+ mov dl, [rdi]
+ dec rsi ; one fewer byte left
+ inc rdi ; point to next byte
+
+ ; hex case
+ mov rcx, 0x00
+ push rcx
+ cmp dl, 'x'
+ je .hex_loop
+ pop rcx
+
+ ; octal case
+ mov rcx, 0x01
+ push rcx
+ cmp dl, 'q'
+ je .oct_loop
+ pop rcx
+
+ ; binary case
+ mov rcx, 0x02
+ push rcx
+ cmp dl, 'b'
+ je .bin_loop
+ pop rcx
+
+ jmp .unrecognised
+
.hex_loop:
cmp rsi, 0 ; make sure we're in range
je .break ; if not, break
@@ -849,6 +873,60 @@ evaluate_constant:
inc rdi
jmp .bin_loop
+ .chr:
+ mov al, [rdi]
+
+ ; bound check byte as printable char
+ cmp al, 0x20
+ jl .unrecognised
+ cmp al, 0x7E
+ jg .unrecognised
+
+ dec rsi
+ inc rdi
+ mov dl, [rdi]
+ cmp dl, "'"
+ jne .unrecognised
+
+ jmp .break
+
+ .str:
+ ; TODO range check rcx / return string longer as a register
+ cmp rsi, 1 ; range check
+ je .str_break
+
+ ror rax, 8
+ inc rcx
+
+ mov dl, [rdi]
+
+ ; bound check byte as printable char
+ cmp dl, 0x20
+ jl .unrecognised
+ cmp dl, 0x7E
+ jg .unrecognised
+
+ or al, dl
+
+ dec rsi
+ inc rdi
+
+ jmp .str
+
+ .str_break:
+ cmp rcx, 1 ; for each [1..rcx]
+ jle .str_break_for_good
+ rol rax, 8 ; roll left to make up for the roll right earlier
+ dec rcx
+ jmp .str_break
+
+ .str_break_for_good:
+ mov dl, [rdi]
+ cmp dl, '"'
+ jne .unrecognised
+
+ jmp .break
+
.break:
pop rdx
ret
diff --git a/twasm/asm/tests.asm b/twasm/asm/tests.asm
index bc2ad84..4d0ddc8 100644
--- a/twasm/asm/tests.asm
+++ b/twasm/asm/tests.asm
@@ -368,6 +368,23 @@ test_evaluate_constant:
cmp rdx, 0x02
jne .fail
+ ; char
+ mov rdi, .case0c
+ mov rsi, 3
+ call evaluate_constant
+ cmp rax, [.case0c_solution]
+ jne .fail
+ cmp rdx, 0x03
+ jne .fail
+
+ ; str
+ mov rdi, .case0s
+ mov rsi, 5
+ call evaluate_constant
+ cmp rax, [.case0s_solution]
+ jne .fail
+ cmp rdx, 0x04
+
.pass:
mov rsi, msg_pass
call print
@@ -385,6 +402,10 @@ test_evaluate_constant:
.case2h_solution dq 0x1234567890
.case3h db "0x243F6A8885A308D3"
.case3h_solution dq 0x243F6A8885A308D3
+ .case0c db "' '"
+ .case0c_solution dq ' '
+ .case0s db '"str"'
+ .case0s_solution dq "str"
.case0q db "0q31103755242102"
.case0q_solution dq 0q31103755242102