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 + ; 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 + + ; all numeric prefixes further handled in .numeric cmp dl, '0' - jne .unrecognised + je .numeric - mov dl, [rdi] - dec rsi ; one fewer byte left - inc rdi ; point to next byte - - ; hex case - mov rcx, 0x00 + ; char case + mov rcx, 0x03 push rcx - cmp dl, 'x' - je .hex_loop + cmp dl, "'" + je .chr pop rcx - ; octal case - mov rcx, 0x01 + ; str case + mov rcx, 0x04 push rcx - cmp dl, 'q' - je .oct_loop - pop rcx - - ; binary case - mov rcx, 0x02 - 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