Compare commits
3 Commits
9233ca421b
...
b607bd13f3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b607bd13f3 | ||
|
|
40be72a5c3 | ||
|
|
f4f0f50d80 |
@@ -210,11 +210,11 @@ type metadata for the different types is as follows:
|
|||||||
entries are as follows:
|
entries are as follows:
|
||||||
|
|
||||||
```
|
```
|
||||||
+----------+--------+----------+
|
+-----------------+-----------------+----------+
|
||||||
| 31 24 | 23 16 | 15 0 |
|
| 31 24 | 23 16 | 15 0 |
|
||||||
+----------+--------+----------+
|
+-----------------+-----------------+----------+
|
||||||
| reserved | opcode | token ID |
|
| dest=reg opcode | dest=r/m opcode | token ID |
|
||||||
+----------+--------+----------+
|
+-----------------+-----------------+----------+
|
||||||
```
|
```
|
||||||
|
|
||||||
note the lack of support for multiple-byte opcodes or multiple opcodes for one token ID; these features will likely be added at some point after the parser accumulates too much jank.
|
note the lack of support for multiple-byte opcodes or multiple opcodes for one token ID; these features will likely be added at some point after the parser accumulates too much jank.
|
||||||
|
|||||||
@@ -124,16 +124,20 @@ assemble:
|
|||||||
pop rsi
|
pop rsi
|
||||||
|
|
||||||
push rdi
|
push rdi
|
||||||
|
push rsi
|
||||||
; di = tte of operator
|
; di = tte of operator
|
||||||
|
mov sil, 0b ; standard opcode
|
||||||
call get_opcode
|
call get_opcode
|
||||||
; al = opcode
|
; al = opcode
|
||||||
call .output_byte
|
call .output_byte
|
||||||
|
pop rsi
|
||||||
pop rdi
|
pop rdi
|
||||||
|
|
||||||
pop rax ; rax = number of tokens processed
|
pop rax ; rax = number of tokens processed
|
||||||
pop rdi ; rdi = total number of tokens
|
pop rdi ; rdi = total number of tokens
|
||||||
inc rax
|
inc rax
|
||||||
cmp rax, rdi
|
cmp rax, rdi
|
||||||
|
jge .break
|
||||||
jmp .loop
|
jmp .loop
|
||||||
|
|
||||||
; di = tte of operator
|
; di = tte of operator
|
||||||
@@ -144,10 +148,13 @@ assemble:
|
|||||||
pop rsi
|
pop rsi
|
||||||
|
|
||||||
push rdi
|
push rdi
|
||||||
|
push rsi
|
||||||
; di = tte of operator
|
; di = tte of operator
|
||||||
|
mov sil, 0b ; dst=r/m
|
||||||
call get_opcode
|
call get_opcode
|
||||||
; al = opcode
|
; al = opcode
|
||||||
call .output_byte
|
call .output_byte
|
||||||
|
pop rsi
|
||||||
pop rdi ; di = tte of operator
|
pop rdi ; di = tte of operator
|
||||||
|
|
||||||
pop rax ; rax = number of tokens processed
|
pop rax ; rax = number of tokens processed
|
||||||
@@ -214,12 +221,7 @@ assemble:
|
|||||||
call print.debug
|
call print.debug
|
||||||
pop rsi
|
pop rsi
|
||||||
|
|
||||||
push rdi
|
mov cx, di ; cx = tte of operator
|
||||||
; di = tte of operator
|
|
||||||
call get_opcode
|
|
||||||
; al = opcode
|
|
||||||
call .output_byte
|
|
||||||
pop rdi ; di = tte of operator
|
|
||||||
|
|
||||||
pop rax
|
pop rax
|
||||||
pop rdi
|
pop rdi
|
||||||
@@ -237,9 +239,11 @@ assemble:
|
|||||||
pop rdi ; di = next tte
|
pop rdi ; di = next tte
|
||||||
je .operator_2_memory_access
|
je .operator_2_memory_access
|
||||||
|
|
||||||
|
push rcx
|
||||||
; di = next tte
|
; di = next tte
|
||||||
call get_tte_type
|
call get_tte_type
|
||||||
; al = type of token
|
; al = type of token
|
||||||
|
pop rcx ; cx = tte of operator
|
||||||
|
|
||||||
cmp al, 0x02 ; type: register
|
cmp al, 0x02 ; type: register
|
||||||
je .operator_2_register
|
je .operator_2_register
|
||||||
@@ -256,7 +260,80 @@ assemble:
|
|||||||
mov rsi, .msg_operator_2_memory_access
|
mov rsi, .msg_operator_2_memory_access
|
||||||
call print.debug
|
call print.debug
|
||||||
pop rsi
|
pop rsi
|
||||||
jmp .unsupported_memory_access
|
|
||||||
|
cmp di, 0x1000 ; check if token is addressing a register
|
||||||
|
jne .unsupported_memory_access ; if not, unsupported :/
|
||||||
|
|
||||||
|
|
||||||
|
push rdi
|
||||||
|
mov di, cx ; di = tte of operator
|
||||||
|
mov sil, 0 ; dst = r/m
|
||||||
|
call get_opcode
|
||||||
|
; al = opcode
|
||||||
|
call .output_byte
|
||||||
|
pop rdi
|
||||||
|
|
||||||
|
pop rax
|
||||||
|
pop rdi
|
||||||
|
inc rax
|
||||||
|
cmp rax, rdi
|
||||||
|
jge .break
|
||||||
|
push rdi
|
||||||
|
push rax
|
||||||
|
xor edi, edi
|
||||||
|
mov di, [rax * TOKEN_TABLE_ENTRY_SIZE + TOKEN_TABLE_ADDR] ; di = next tte
|
||||||
|
|
||||||
|
mov si, di ; si = dst tte
|
||||||
|
|
||||||
|
pop rax
|
||||||
|
pop rdi
|
||||||
|
inc rax
|
||||||
|
cmp rax, rdi
|
||||||
|
jge .break
|
||||||
|
push rdi
|
||||||
|
push rax
|
||||||
|
xor edi, edi
|
||||||
|
mov di, [rax * TOKEN_TABLE_ENTRY_SIZE + TOKEN_TABLE_ADDR] ; di = next tte
|
||||||
|
|
||||||
|
push rdi
|
||||||
|
and di, 0xFF00
|
||||||
|
cmp di, 0x1000 ; check if token is a memory address
|
||||||
|
pop rdi ; di = next tte
|
||||||
|
je .unsupported_memory_access ; no case of *],[* in asm
|
||||||
|
|
||||||
|
; di = next tte
|
||||||
|
call get_tte_type
|
||||||
|
; al = type of token
|
||||||
|
|
||||||
|
cmp al, 0x02
|
||||||
|
je .operator_2_memory_access_register
|
||||||
|
|
||||||
|
pop rax ; rax = number of tokens processed
|
||||||
|
pop rdi ; rdi = total number of tokens
|
||||||
|
inc rax
|
||||||
|
cmp rax, rdi
|
||||||
|
jge .break
|
||||||
|
jmp .loop
|
||||||
|
|
||||||
|
.operator_2_memory_access_register:
|
||||||
|
push rsi
|
||||||
|
mov rsi, .msg_operator_2_memory_access_register
|
||||||
|
call print.debug
|
||||||
|
pop rsi
|
||||||
|
|
||||||
|
; si = r/m; dst tte
|
||||||
|
; di = reg; src tte
|
||||||
|
mov dl, 00b ; dl = mod bits
|
||||||
|
call get_ModRM
|
||||||
|
; al = Mod R/M byte
|
||||||
|
call .output_byte
|
||||||
|
|
||||||
|
pop rax ; rax = number of tokens processed
|
||||||
|
pop rdi ; rdi = total number of tokens
|
||||||
|
inc rax
|
||||||
|
cmp rax, rdi
|
||||||
|
jge .break
|
||||||
|
jmp .loop
|
||||||
|
|
||||||
.operator_2_register:
|
.operator_2_register:
|
||||||
push rsi
|
push rsi
|
||||||
@@ -264,7 +341,15 @@ assemble:
|
|||||||
call print.debug
|
call print.debug
|
||||||
pop rsi
|
pop rsi
|
||||||
|
|
||||||
mov si, di ; si = `R/M` tte
|
push rdi
|
||||||
|
mov di, cx ; di = tte of operator
|
||||||
|
mov sil, 1 ; dst = reg
|
||||||
|
call get_opcode
|
||||||
|
; al = opcode
|
||||||
|
call .output_byte
|
||||||
|
pop rdi
|
||||||
|
|
||||||
|
mov si, di ; si = dst tte
|
||||||
|
|
||||||
pop rax
|
pop rax
|
||||||
pop rdi
|
pop rdi
|
||||||
@@ -290,7 +375,7 @@ assemble:
|
|||||||
je .operator_2_register_register
|
je .operator_2_register_register
|
||||||
|
|
||||||
pop rax ; rax = number of tokens processed
|
pop rax ; rax = number of tokens processed
|
||||||
pop rdi ; rdi = total nnumber of tokens
|
pop rdi ; rdi = total number of tokens
|
||||||
inc rax
|
inc rax
|
||||||
cmp rax, rdi
|
cmp rax, rdi
|
||||||
jge .break
|
jge .break
|
||||||
@@ -338,11 +423,9 @@ assemble:
|
|||||||
call print.debug
|
call print.debug
|
||||||
pop rsi
|
pop rsi
|
||||||
|
|
||||||
; si = `R/M` tte
|
|
||||||
; di = `reg` tte
|
|
||||||
push rsi
|
push rsi
|
||||||
mov si, di
|
mov si, di ; si = reg; src tte
|
||||||
pop rdi
|
pop rdi ; di = r/m; dst tte
|
||||||
mov dl, 11b ; dl = mod bits
|
mov dl, 11b ; dl = mod bits
|
||||||
call get_ModRM
|
call get_ModRM
|
||||||
; al = Mod R/M byte
|
; al = Mod R/M byte
|
||||||
@@ -388,6 +471,7 @@ assemble:
|
|||||||
.msg_operator_1_register db "operator_1_register", 0x0A, 0x00
|
.msg_operator_1_register db "operator_1_register", 0x0A, 0x00
|
||||||
.msg_operator_2 db "operator_2", 0x0A, 0x00
|
.msg_operator_2 db "operator_2", 0x0A, 0x00
|
||||||
.msg_operator_2_memory_access db "operator_2_memory_access", 0x0A, 0x00
|
.msg_operator_2_memory_access db "operator_2_memory_access", 0x0A, 0x00
|
||||||
|
.msg_operator_2_memory_access_register db "operator_2_memory_access_register", 0x0A, 0x00
|
||||||
.msg_operator_2_register db "operator_2_register", 0x0A, 0x00
|
.msg_operator_2_register db "operator_2_register", 0x0A, 0x00
|
||||||
.msg_operator_2_register_memory_access db "operator_2_register_memory_access", 0x0A, 0x00
|
.msg_operator_2_register_memory_access db "operator_2_register_memory_access", 0x0A, 0x00
|
||||||
.msg_operator_2_register_register db "operator_2_register_register", 0x0A, 0x00
|
.msg_operator_2_register_register db "operator_2_register_register", 0x0A, 0x00
|
||||||
@@ -514,10 +598,13 @@ get_ModRM:
|
|||||||
; get_opcode
|
; get_opcode
|
||||||
;
|
;
|
||||||
; description:
|
; description:
|
||||||
; given an operator token, returns its opcode
|
; given an operator token, returns its opcode. For operators with multiple
|
||||||
|
; opcodes, the variant can be specified.
|
||||||
;
|
;
|
||||||
; parameters:
|
; parameters:
|
||||||
; di = token table entry
|
; di = token table entry
|
||||||
|
; sil = lower bit: 0: dst=r/m or only opcode
|
||||||
|
; 1: dst=reg or 0x00
|
||||||
;
|
;
|
||||||
; returned:
|
; returned:
|
||||||
; al = opcode; the rest of rax is zeroed
|
; al = opcode; the rest of rax is zeroed
|
||||||
@@ -525,6 +612,7 @@ get_ModRM:
|
|||||||
|
|
||||||
get_opcode:
|
get_opcode:
|
||||||
and rdi, 0xFFFF
|
and rdi, 0xFFFF
|
||||||
|
and rsi, 1
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
|
|
||||||
.loop:
|
.loop:
|
||||||
@@ -543,7 +631,7 @@ get_opcode:
|
|||||||
mov al, UNRECOGNISED_ID_OPCODE
|
mov al, UNRECOGNISED_ID_OPCODE
|
||||||
ret
|
ret
|
||||||
.found:
|
.found:
|
||||||
mov al, [2 + opcodes.by_id + rax * 4]
|
mov al, [rsi + 2 + opcodes.by_id + rax * 4]
|
||||||
and rax, 0xFF ; mask
|
and rax, 0xFF ; mask
|
||||||
ret
|
ret
|
||||||
|
|
||||||
@@ -817,7 +905,7 @@ tokenise:
|
|||||||
jmp .operand_break_continue
|
jmp .operand_break_continue
|
||||||
|
|
||||||
; cx = token ID
|
; cx = token ID
|
||||||
.operand_addr_register
|
.operand_addr_register:
|
||||||
mov word [TOKEN_TABLE_ADDR + rax * TOKEN_TABLE_ENTRY_SIZE], 0x1000
|
mov word [TOKEN_TABLE_ADDR + rax * TOKEN_TABLE_ENTRY_SIZE], 0x1000
|
||||||
inc rax ; 0x1000: addr reg token, next token is the register
|
inc rax ; 0x1000: addr reg token, next token is the register
|
||||||
mov [TOKEN_TABLE_ADDR + rax * TOKEN_TABLE_ENTRY_SIZE], cx
|
mov [TOKEN_TABLE_ADDR + rax * TOKEN_TABLE_ENTRY_SIZE], cx
|
||||||
@@ -1417,12 +1505,12 @@ trim_trailing_whitespace:
|
|||||||
cmp al, 0 ; if last element whitespace
|
cmp al, 0 ; if last element whitespace
|
||||||
je .done ; then break
|
je .done ; then break
|
||||||
|
|
||||||
.trim ; otherwise one shorter
|
.trim: ; otherwise one shorter
|
||||||
dec rdi
|
dec rdi
|
||||||
call trim_trailing_whitespace
|
call trim_trailing_whitespace
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.done
|
.done:
|
||||||
mov rax, rdi
|
mov rax, rdi
|
||||||
ret
|
ret
|
||||||
|
|
||||||
@@ -1707,20 +1795,20 @@ tokens:
|
|||||||
opcodes:
|
opcodes:
|
||||||
.by_id:
|
.by_id:
|
||||||
dw 0x0053 ; xor
|
dw 0x0053 ; xor
|
||||||
db 0x31
|
db 0x31 ; r/m <- reg
|
||||||
db 0x00 ; reserved
|
db 0x33 ; reg <- r/m
|
||||||
|
|
||||||
dw 0x0054 ; inc
|
dw 0x0054 ; inc
|
||||||
db 0xFF
|
db 0xFF ; r/m
|
||||||
db 0x00 ; reserved
|
db 0x00 ;
|
||||||
|
|
||||||
dw 0x0056 ; mov
|
dw 0x0056 ; mov
|
||||||
db 0x8B
|
db 0x89 ; r/m <- reg
|
||||||
db 0x00 ; reserved
|
db 0x8B ; reg <- r/m
|
||||||
|
|
||||||
dw 0x004F ; hlt
|
dw 0x004F ; hlt
|
||||||
db 0xF4
|
db 0xF4 ; .
|
||||||
db 0x00 ; reserved
|
db 0x00 ;
|
||||||
.by_id_end:
|
.by_id_end:
|
||||||
|
|
||||||
msg_welcome db "Welcome to Twasm", 0x0A, 0x00
|
msg_welcome db "Welcome to Twasm", 0x0A, 0x00
|
||||||
@@ -1735,7 +1823,7 @@ program:
|
|||||||
db "; one line comment", 0x0A
|
db "; one line comment", 0x0A
|
||||||
db "mov rdx, [rax]", 0x0A
|
db "mov rdx, [rax]", 0x0A
|
||||||
db "mov [rax], rdx", 0x0A
|
db "mov [rax], rdx", 0x0A
|
||||||
db "hlt", 0x0A ; TODO make it so it doesn't need to end with a newline; this
|
db "hlt", 0x0A
|
||||||
; would mean range checking members in operator/operand/com-
|
.size dq $ - program
|
||||||
; ment loops at the end of the program
|
|
||||||
.size db $ - program
|
msg_end db "end of the binary ->|", 0x0A, 0x00
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ run_tests:
|
|||||||
mov rsi, .msg
|
mov rsi, .msg
|
||||||
call print.test
|
call print.test
|
||||||
|
|
||||||
|
call test_completeness
|
||||||
|
|
||||||
call clear_test_arena
|
call clear_test_arena
|
||||||
call test_djb2
|
call test_djb2
|
||||||
|
|
||||||
@@ -46,6 +48,27 @@ run_tests:
|
|||||||
ret
|
ret
|
||||||
.msg db "running test suite...", 0x0A, 0x00
|
.msg db "running test suite...", 0x0A, 0x00
|
||||||
|
|
||||||
|
; ------------------------------------------------------------------------------
|
||||||
|
; test_completeness
|
||||||
|
;
|
||||||
|
; description:
|
||||||
|
; visual confirmation of binary integrity
|
||||||
|
; ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
test_completeness:
|
||||||
|
mov rsi, .msg
|
||||||
|
call print.test
|
||||||
|
mov rsi, .msg_content
|
||||||
|
call print
|
||||||
|
mov rsi, msg_end
|
||||||
|
call print
|
||||||
|
mov rsi, .msg_confirm
|
||||||
|
call print
|
||||||
|
ret
|
||||||
|
.msg db "test_completeness...", 0x0A, 0x00
|
||||||
|
.msg_content db " here is the ", 0x00
|
||||||
|
.msg_confirm db " here is the end of the binary ->|", 0x0A, " assert: the previous 2 lines are identical", 0x0A, 0x00
|
||||||
|
|
||||||
; ------------------------------------------------------------------------------
|
; ------------------------------------------------------------------------------
|
||||||
; test_elemb
|
; test_elemb
|
||||||
;
|
;
|
||||||
@@ -228,6 +251,11 @@ test_get_tte_typed_metadata:
|
|||||||
cmp al, 0x02 ; # operands
|
cmp al, 0x02 ; # operands
|
||||||
jne .fail
|
jne .fail
|
||||||
|
|
||||||
|
mov di, 0x004F ; hlt
|
||||||
|
call get_tte_typed_metadata
|
||||||
|
cmp al, 0x00 ; # operands
|
||||||
|
jne .fail
|
||||||
|
|
||||||
mov di, 0x0003 ; rdx
|
mov di, 0x0003 ; rdx
|
||||||
call get_tte_typed_metadata
|
call get_tte_typed_metadata
|
||||||
cmp al, 00001011b ; reg: 010b
|
cmp al, 00001011b ; reg: 010b
|
||||||
@@ -266,21 +294,32 @@ test_get_opcode:
|
|||||||
call print.test
|
call print.test
|
||||||
|
|
||||||
mov di, 0x0053 ; xor
|
mov di, 0x0053 ; xor
|
||||||
|
mov sil, 0b
|
||||||
call get_opcode
|
call get_opcode
|
||||||
cmp al, 0x31
|
cmp al, 0x31
|
||||||
jne .fail
|
jne .fail
|
||||||
|
|
||||||
|
mov di, 0x0053 ; xor
|
||||||
|
mov sil, 1b
|
||||||
|
call get_opcode
|
||||||
|
cmp al, 0x33
|
||||||
|
jne .fail
|
||||||
|
|
||||||
|
|
||||||
mov di, 0x0054 ; inc
|
mov di, 0x0054 ; inc
|
||||||
|
mov sil, 0b
|
||||||
call get_opcode
|
call get_opcode
|
||||||
cmp al, 0xFF
|
cmp al, 0xFF
|
||||||
jne .fail
|
jne .fail
|
||||||
|
|
||||||
mov di, 0x004F ; hlt
|
mov di, 0x004F ; hlt
|
||||||
|
mov sil, 0b
|
||||||
call get_opcode
|
call get_opcode
|
||||||
cmp al, 0xF4
|
cmp al, 0xF4
|
||||||
jne .fail
|
jne .fail
|
||||||
|
|
||||||
mov di, 0x0003 ; rdx (not an operator)
|
mov di, 0x0003 ; rdx (not an operator)
|
||||||
|
mov sil, 0b
|
||||||
call get_opcode
|
call get_opcode
|
||||||
cmp al, UNRECOGNISED_ID_OPCODE
|
cmp al, UNRECOGNISED_ID_OPCODE
|
||||||
jne .fail
|
jne .fail
|
||||||
|
|||||||
Reference in New Issue
Block a user