clean up some stuff
This commit is contained in:
@@ -160,7 +160,7 @@ the `type` hex digit is defined as the following:
|
|||||||
|
|
||||||
| hex | meaning | examples |
|
| hex | meaning | examples |
|
||||||
|-----|----------|-|
|
|-----|----------|-|
|
||||||
| 0x0 | ignored | `; this entire comment is 1 token` |
|
| 0x0 | ignored | |
|
||||||
| 0x1 | operator | `mov`, `hlt` |
|
| 0x1 | operator | `mov`, `hlt` |
|
||||||
| 0x2 | register | `rsp`, `al` |
|
| 0x2 | register | `rsp`, `al` |
|
||||||
| 0xF | unknown | any token ID not represented in the lookup table |
|
| 0xF | unknown | any token ID not represented in the lookup table |
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ TEST_ARENA_SIZE equ 0x1000 ; maximum size tests can use
|
|||||||
|
|
||||||
TOKEN_TABLE_ADDR equ 0x00060000 ; address the token table is loaded at
|
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 0x1000 ; max length of table
|
||||||
TOKEN_TABLE_ENTRY_SIZE equ 2 ; size of token table entry; things may break
|
|
||||||
; if this ever changes
|
|
||||||
|
|
||||||
OUTPUT_ADDR equ 0x00070000 ; address of outputed binary
|
OUTPUT_ADDR equ 0x00070000 ; address of outputed binary
|
||||||
OUTPUT_SIZE equ 0x1000 ; max length of outputed binary
|
OUTPUT_SIZE equ 0x1000 ; max length of outputed binary
|
||||||
@@ -49,11 +47,14 @@ start:
|
|||||||
mov rdi, program ; -> program
|
mov rdi, program ; -> program
|
||||||
mov rsi, [program.size] ; = size of program
|
mov rsi, [program.size] ; = size of program
|
||||||
call tokenise
|
call tokenise
|
||||||
; rax = number of tokens processed
|
; rax = number of tokens in token table
|
||||||
mov rdi, rax
|
mov rdi, rax
|
||||||
|
|
||||||
push rdi
|
push rdi
|
||||||
|
|
||||||
call clear_output_arena
|
call clear_output_arena
|
||||||
pop rdi
|
|
||||||
|
pop rdi ; rdi = number of tokens in token table
|
||||||
call assemble
|
call assemble
|
||||||
|
|
||||||
jmp halt
|
jmp halt
|
||||||
@@ -64,8 +65,6 @@ start:
|
|||||||
|
|
||||||
; ------------------------------------------------------------------------------
|
; ------------------------------------------------------------------------------
|
||||||
; assemble
|
; assemble
|
||||||
; TODO write tests
|
|
||||||
; TODO make it work :/ putting the cart before the horse
|
|
||||||
;
|
;
|
||||||
; description:
|
; description:
|
||||||
; assembles the program from tokens located at TOKEN_TABLE_ADDR into a flat
|
; assembles the program from tokens located at TOKEN_TABLE_ADDR into a flat
|
||||||
@@ -85,25 +84,33 @@ start:
|
|||||||
; ------------------------------------------------------------------------------
|
; ------------------------------------------------------------------------------
|
||||||
|
|
||||||
assemble:
|
assemble:
|
||||||
xor eax, eax ; rax = number of tokens processed
|
; TODO deal with src=imm and src=imm8
|
||||||
mov [.tokens_total], edi ; rdi = number of tokens in table
|
xor eax, eax
|
||||||
|
mov [.tokens_processed], eax ; eax = number of tokens processed
|
||||||
|
mov [.tokens_total], edi ; edi = total number of tokens in table
|
||||||
|
|
||||||
.loop:
|
.loop:
|
||||||
xor edi, edi
|
call .get_next_tte
|
||||||
mov di, [rax * TOKEN_TABLE_ENTRY_SIZE + TOKEN_TABLE_ADDR] ; next tte
|
; di = tte
|
||||||
|
call get_tte_type
|
||||||
|
; al = type
|
||||||
|
|
||||||
|
cmp al, 0x1 ; check if next tte is an operator
|
||||||
|
je .operator ; if so, handle
|
||||||
|
jmp .unexpected_token ; otherwise, fail
|
||||||
|
|
||||||
; di = tte of operator
|
|
||||||
.operator: ; if next tte's type is an operator:
|
.operator: ; if next tte's type is an operator:
|
||||||
push rdi
|
|
||||||
; di = tte of operator
|
; di = tte of operator
|
||||||
call get_tte_typed_metadata
|
call get_tte_typed_metadata
|
||||||
; al = tte typed metadata
|
; al = tte typed metadata
|
||||||
pop rdi
|
|
||||||
|
cmp al, UNRECOGNISED_ID_METADATA ; make sure token has metadata on record
|
||||||
|
je .unexpected_token ; if not, fail
|
||||||
|
|
||||||
and al, 11b ; mask for # operands
|
and al, 11b ; mask for # operands
|
||||||
|
|
||||||
cmp al, 0 ; check if operator has no operands
|
cmp al, 0 ; check if operator has no operands
|
||||||
je .operator_0 ; if so, handle case of no operands
|
je .operator_0 ; if so, handle case of no operands
|
||||||
|
|
||||||
cmp al, 1 ; check if operator has one operand
|
cmp al, 1 ; check if operator has one operand
|
||||||
je .operator_1 ; if so, handle case of one operand
|
je .operator_1 ; if so, handle case of one operand
|
||||||
@@ -111,39 +118,25 @@ assemble:
|
|||||||
cmp al, 2 ; check if operator has two operands
|
cmp al, 2 ; check if operator has two operands
|
||||||
je .operator_2 ; if so, handle case of two operands
|
je .operator_2 ; if so, handle case of two operands
|
||||||
|
|
||||||
jmp .unexpected_token ; TODO actually check operator type or not first
|
jmp .unexpected_token
|
||||||
; if get_tte_typed_metadata happens to return 0, 1,
|
|
||||||
; or 2 on a non-operator, it doesn't get caught
|
|
||||||
|
|
||||||
; di = tte of operator
|
|
||||||
.operator_0:
|
.operator_0:
|
||||||
push rsi
|
|
||||||
mov rsi, .msg_operator_0
|
mov rsi, .msg_operator_0
|
||||||
call print.debug
|
call print.debug
|
||||||
pop rsi
|
|
||||||
|
|
||||||
push rdi
|
|
||||||
push rsi
|
|
||||||
; di = tte of operator
|
; di = tte of operator
|
||||||
mov sil, 0b ; standard opcode
|
mov sil, 0b ; opcode
|
||||||
call get_opcode
|
call get_opcode
|
||||||
; al = opcode
|
; al = opcode
|
||||||
; dl = op flag (none)
|
; dl = 0x00
|
||||||
call .output_byte
|
call .output_byte
|
||||||
pop rsi
|
|
||||||
pop rdi
|
|
||||||
|
|
||||||
jmp .loop_next_token
|
jmp .loop_next_token
|
||||||
|
|
||||||
; di = tte of operator
|
|
||||||
.operator_1:
|
.operator_1:
|
||||||
push rsi
|
|
||||||
mov rsi, .msg_operator_1
|
mov rsi, .msg_operator_1
|
||||||
call print.debug
|
call print.debug
|
||||||
pop rsi
|
|
||||||
|
|
||||||
push rdi
|
|
||||||
push rsi
|
|
||||||
; di = tte of operator
|
; di = tte of operator
|
||||||
mov sil, 0b ; dst=r/m
|
mov sil, 0b ; dst=r/m
|
||||||
call get_opcode
|
call get_opcode
|
||||||
@@ -152,13 +145,10 @@ assemble:
|
|||||||
push rdx
|
push rdx
|
||||||
call .output_byte
|
call .output_byte
|
||||||
pop rdx ; dl = op flag
|
pop rdx ; dl = op flag
|
||||||
pop rsi
|
|
||||||
pop rdi ; di = tte of operator
|
|
||||||
|
|
||||||
call .next_token
|
call .next_token
|
||||||
jge .break
|
jge .break
|
||||||
xor edi, edi
|
call .get_next_tte
|
||||||
mov di, [rax * TOKEN_TABLE_ENTRY_SIZE + TOKEN_TABLE_ADDR] ; di = next tte
|
|
||||||
|
|
||||||
push rdi
|
push rdi
|
||||||
and di, 0xFF00
|
and di, 0xFF00
|
||||||
@@ -178,23 +168,19 @@ assemble:
|
|||||||
jmp .loop_next_token
|
jmp .loop_next_token
|
||||||
|
|
||||||
.operator_1_memory:
|
.operator_1_memory:
|
||||||
push rsi
|
|
||||||
mov rsi, .msg_operator_1_memory
|
mov rsi, .msg_operator_1_memory
|
||||||
call print.debug
|
call print.debug
|
||||||
pop rsi
|
|
||||||
jmp .unsupported_memory_access
|
jmp .unsupported_memory_access
|
||||||
|
|
||||||
.operator_1_register:
|
.operator_1_register:
|
||||||
push rsi
|
|
||||||
mov rsi, .msg_operator_1_register
|
mov rsi, .msg_operator_1_register
|
||||||
call print.debug
|
call print.debug
|
||||||
pop rsi
|
|
||||||
|
|
||||||
mov si, di ; si = `R/M` tte
|
mov si, di ; si = `R/M` tte
|
||||||
and edx, 0xFF
|
and edx, 0xFF
|
||||||
or dx, 0xFE00 ; pass di as direct value
|
or edx, 0xFE00 ; pass di as direct value
|
||||||
mov di, dx ; di = op flag
|
mov edi, edx ; di = op flag
|
||||||
mov dl, 11b ; dl = mod bits
|
mov edx, 11b ; dl = mod bits
|
||||||
call get_ModRM
|
call get_ModRM
|
||||||
; al = Mod R/M byte
|
; al = Mod R/M byte
|
||||||
call .output_byte
|
call .output_byte
|
||||||
@@ -202,17 +188,14 @@ assemble:
|
|||||||
jmp .loop_next_token
|
jmp .loop_next_token
|
||||||
|
|
||||||
.operator_2:
|
.operator_2:
|
||||||
push rsi
|
|
||||||
mov rsi, .msg_operator_2
|
mov rsi, .msg_operator_2
|
||||||
call print.debug
|
call print.debug
|
||||||
pop rsi
|
|
||||||
|
|
||||||
mov cx, di ; cx = tte of operator
|
mov cx, di ; cx = tte of operator
|
||||||
|
|
||||||
call .next_token
|
call .next_token
|
||||||
jge .break
|
jge .break
|
||||||
xor edi, edi
|
call .get_next_tte
|
||||||
mov di, [rax * TOKEN_TABLE_ENTRY_SIZE + TOKEN_TABLE_ADDR] ; di = next tte
|
|
||||||
|
|
||||||
push rdi
|
push rdi
|
||||||
and di, 0xFF00
|
and di, 0xFF00
|
||||||
@@ -232,57 +215,49 @@ assemble:
|
|||||||
jmp .loop_next_token
|
jmp .loop_next_token
|
||||||
|
|
||||||
.operator_2_memory:
|
.operator_2_memory:
|
||||||
push rsi
|
|
||||||
mov rsi, .msg_operator_2_memory
|
mov rsi, .msg_operator_2_memory
|
||||||
call print.debug
|
call print.debug
|
||||||
pop rsi
|
|
||||||
|
|
||||||
cmp di, 0x1000 ; check if token is addressing a register
|
cmp di, 0x1000 ; check if token is addressing a register
|
||||||
jne .unsupported_memory_access ; if not, unsupported :/
|
jne .unsupported_memory_access ; if not, unsupported
|
||||||
|
|
||||||
|
mov edi, ecx ; di = tte of operator
|
||||||
push rdi
|
xor esi, esi ; dst=r/m; src=r
|
||||||
mov di, cx ; di = tte of operator
|
|
||||||
mov sil, 0 ; dst = r/m
|
|
||||||
call get_opcode
|
call get_opcode
|
||||||
; al = opcode
|
; al = opcode
|
||||||
; dl = op flag
|
; dl = op flag
|
||||||
; TODO act accordingly if the op flag is present
|
|
||||||
call .output_byte
|
call .output_byte
|
||||||
pop rdi
|
|
||||||
|
|
||||||
call .next_token
|
call .next_token
|
||||||
jge .break
|
jge .break
|
||||||
xor edi, edi
|
call .get_next_tte
|
||||||
mov di, [rax * TOKEN_TABLE_ENTRY_SIZE + TOKEN_TABLE_ADDR] ; di = next tte
|
|
||||||
|
|
||||||
mov si, di ; si = dst tte
|
mov si, di ; si = dst register tte
|
||||||
|
|
||||||
call .next_token
|
call .next_token
|
||||||
jge .break
|
jge .break
|
||||||
xor edi, edi
|
call .get_next_tte
|
||||||
mov di, [rax * TOKEN_TABLE_ENTRY_SIZE + TOKEN_TABLE_ADDR] ; di = next tte
|
|
||||||
|
|
||||||
push rdi
|
push rdi
|
||||||
and di, 0xFF00
|
and di, 0xFF00
|
||||||
cmp di, 0x1000 ; check if token is a memory address
|
cmp di, 0x1000 ; check if token is a memory address
|
||||||
pop rdi ; di = next tte
|
pop rdi ; di = next tte
|
||||||
je .unsupported_memory_access ; no case of *],[* in asm
|
je .unsupported_memory_access ; if so, fail; no case of *],[* in asm
|
||||||
|
|
||||||
; di = next tte
|
; di = next tte
|
||||||
call get_tte_type
|
call get_tte_type
|
||||||
; al = type of token
|
; al = type of token
|
||||||
|
|
||||||
cmp al, 0x02
|
cmp al, 0x02 ; check if token is a register
|
||||||
je .operator_2_memory_register
|
je .operator_2_memory_register ; if so, handle
|
||||||
|
|
||||||
jmp .loop_next_token
|
jmp .unexpected_token
|
||||||
|
|
||||||
.operator_2_memory_register:
|
.operator_2_memory_register:
|
||||||
push rsi
|
push rsi
|
||||||
mov rsi, .msg_operator_2_memory_register
|
mov rsi, .msg_operator_2_memory_register
|
||||||
call print.debug
|
call print.debug
|
||||||
pop rsi
|
pop rsi ; si = r/m
|
||||||
|
|
||||||
; si = r/m; dst tte
|
; si = r/m; dst tte
|
||||||
; di = reg; src tte
|
; di = reg; src tte
|
||||||
@@ -294,10 +269,8 @@ assemble:
|
|||||||
jmp .loop_next_token
|
jmp .loop_next_token
|
||||||
|
|
||||||
.operator_2_register:
|
.operator_2_register:
|
||||||
push rsi
|
|
||||||
mov rsi, .msg_operator_2_register
|
mov rsi, .msg_operator_2_register
|
||||||
call print.debug
|
call print.debug
|
||||||
pop rsi
|
|
||||||
|
|
||||||
push rdi
|
push rdi
|
||||||
mov di, cx ; di = tte of operator
|
mov di, cx ; di = tte of operator
|
||||||
@@ -307,14 +280,13 @@ assemble:
|
|||||||
; dl = op flag
|
; dl = op flag
|
||||||
; TODO do something if the op flag is present
|
; TODO do something if the op flag is present
|
||||||
call .output_byte
|
call .output_byte
|
||||||
pop rdi
|
pop rdi ; di = dst tte
|
||||||
|
|
||||||
mov si, di ; si = dst tte
|
mov si, di ; si = dst tte
|
||||||
|
|
||||||
call .next_token
|
call .next_token
|
||||||
jge .break
|
jge .break
|
||||||
xor edi, edi
|
call .get_next_tte
|
||||||
mov di, [rax * TOKEN_TABLE_ENTRY_SIZE + TOKEN_TABLE_ADDR] ; di = next tte
|
|
||||||
|
|
||||||
push rdi
|
push rdi
|
||||||
and di, 0xFF00
|
and di, 0xFF00
|
||||||
@@ -326,31 +298,30 @@ assemble:
|
|||||||
call get_tte_type
|
call get_tte_type
|
||||||
; al = type of token
|
; al = type of token
|
||||||
|
|
||||||
cmp al, 0x02
|
cmp al, 0x02 ; check if token is a register
|
||||||
je .operator_2_register_register
|
je .operator_2_register_register ; if so, handle
|
||||||
|
|
||||||
jmp .loop_next_token
|
jmp .unexpected_token
|
||||||
|
|
||||||
.operator_2_register_memory:
|
.operator_2_register_memory:
|
||||||
push rsi
|
push rsi
|
||||||
mov rsi, .msg_operator_2_register_memory
|
mov rsi, .msg_operator_2_register_memory
|
||||||
call print.debug
|
call print.debug
|
||||||
pop rsi
|
pop rsi ; si = dst tte
|
||||||
|
|
||||||
cmp di, 0x1000 ; check if token is addressing to a register
|
cmp di, 0x1000 ; check if token is addressing to a register
|
||||||
jne .unsupported_memory_access ; if not, unsupported :/
|
jne .unsupported_memory_access ; if not, unsupported
|
||||||
|
|
||||||
call .next_token
|
call .next_token
|
||||||
jge .break
|
jge .break
|
||||||
xor edi, edi
|
call .get_next_tte
|
||||||
mov di, [rax * TOKEN_TABLE_ENTRY_SIZE + TOKEN_TABLE_ADDR] ; di = next tte
|
|
||||||
|
|
||||||
; si = `R/M` tte
|
; si = r/m; dst tte
|
||||||
; di = `reg` tte
|
; di = reg; src tte
|
||||||
push rsi
|
push rsi
|
||||||
mov si, di
|
mov esi, edi ; si = reg; src tte
|
||||||
pop rdi
|
pop rdi ; di = r/m; dst tte
|
||||||
mov dl, 00b ; dl = mod bits
|
mov edx, 00b ; dl = mod bits
|
||||||
call get_ModRM
|
call get_ModRM
|
||||||
; al = Mod R/M byte
|
; al = Mod R/M byte
|
||||||
call .output_byte
|
call .output_byte
|
||||||
@@ -358,15 +329,13 @@ assemble:
|
|||||||
jmp .loop_next_token
|
jmp .loop_next_token
|
||||||
|
|
||||||
.operator_2_register_register:
|
.operator_2_register_register:
|
||||||
push rsi
|
|
||||||
mov rsi, .msg_operator_2_register_register
|
mov rsi, .msg_operator_2_register_register
|
||||||
call print.debug
|
call print.debug
|
||||||
pop rsi
|
|
||||||
|
|
||||||
push rsi
|
push rsi
|
||||||
mov si, di ; si = reg; src tte
|
mov esi, edi ; si = reg; src tte
|
||||||
pop rdi ; di = r/m; dst tte
|
pop rdi ; di = r/m; dst tte
|
||||||
mov dl, 11b ; dl = mod bits
|
mov edx, 11b ; dl = mod bits
|
||||||
call get_ModRM
|
call get_ModRM
|
||||||
; al = Mod R/M byte
|
; al = Mod R/M byte
|
||||||
call .output_byte
|
call .output_byte
|
||||||
@@ -402,6 +371,13 @@ assemble:
|
|||||||
cmp eax, edi
|
cmp eax, edi
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
; eax = current entry index in token table
|
||||||
|
; returns di = next tte
|
||||||
|
.get_next_tte:
|
||||||
|
xor edi, edi
|
||||||
|
mov di, [eax * 2 + TOKEN_TABLE_ADDR]
|
||||||
|
ret
|
||||||
|
|
||||||
.tokens_processed dd 0
|
.tokens_processed dd 0
|
||||||
.tokens_total dd 0
|
.tokens_total dd 0
|
||||||
|
|
||||||
@@ -444,27 +420,27 @@ assemble:
|
|||||||
; ------------------------------------------------------------------------------
|
; ------------------------------------------------------------------------------
|
||||||
|
|
||||||
get_tte_type:
|
get_tte_type:
|
||||||
and rdi, 0xFFFF ; mask input so it behaves as expected
|
and edi, 0xFFFF ; di = token table entry
|
||||||
xor eax, eax
|
xor eax, eax ; eax = tokens.by_id index
|
||||||
|
|
||||||
.loop:
|
.loop:
|
||||||
cmp rax, (tokens.by_id_end - tokens.by_id) / 4 ; make sure it's still in range
|
cmp eax, (tokens.by_id_end - tokens.by_id) / 4 ; index range check
|
||||||
jg .not_found
|
jg .not_found
|
||||||
|
|
||||||
mov cx, [tokens.by_id + rax * 4] ; next entry in tokens.by_id
|
mov cx, [tokens.by_id + eax * 4] ; next entry in tokens.by_id
|
||||||
|
|
||||||
cmp cx, di
|
cmp cx, di
|
||||||
je .found
|
je .found
|
||||||
|
|
||||||
inc rax
|
inc eax
|
||||||
jmp .loop
|
jmp .loop
|
||||||
.not_found:
|
.not_found:
|
||||||
mov al, UNRECOGNISED_ID_TYPE
|
mov eax, UNRECOGNISED_ID_TYPE
|
||||||
and ax, 0xF ; mask as expected
|
and eax, 0xF
|
||||||
ret
|
ret
|
||||||
.found:
|
.found:
|
||||||
mov al, [2 + tokens.by_id + rax * 4]
|
mov al, [2 + tokens.by_id + eax * 4]
|
||||||
and ax, 0xF ; mask as expected
|
and eax, 0xF ; mask as expected
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; ------------------------------------------------------------------------------
|
; ------------------------------------------------------------------------------
|
||||||
@@ -483,27 +459,26 @@ get_tte_type:
|
|||||||
; ------------------------------------------------------------------------------
|
; ------------------------------------------------------------------------------
|
||||||
|
|
||||||
get_tte_typed_metadata:
|
get_tte_typed_metadata:
|
||||||
and rdi, 0xFFFF ; mask input so it behaves as expected
|
and edi, 0xFFFF ; di = token table entry
|
||||||
xor eax, eax
|
xor eax, eax ; eax = tokens.by_id index
|
||||||
|
|
||||||
.loop:
|
.loop:
|
||||||
cmp rax, (tokens.by_id_end - tokens.by_id) / 4 ; make sure it's still in range
|
cmp eax, (tokens.by_id_end - tokens.by_id) / 4 ; index range check
|
||||||
jg .not_found
|
jg .not_found
|
||||||
|
|
||||||
mov cx, [tokens.by_id + rax * 4] ; next entry in tokens.by_id
|
mov cx, [tokens.by_id + eax * 4] ; next entry in tokens.by_id
|
||||||
|
|
||||||
cmp cx, di
|
cmp cx, di
|
||||||
je .found
|
je .found
|
||||||
|
|
||||||
inc rax
|
inc eax
|
||||||
jmp .loop
|
jmp .loop
|
||||||
.not_found:
|
.not_found:
|
||||||
xor eax, eax
|
mov eax, UNRECOGNISED_ID_METADATA
|
||||||
mov al, UNRECOGNISED_ID_METADATA
|
|
||||||
ret
|
ret
|
||||||
.found:
|
.found:
|
||||||
mov al, [3 + tokens.by_id + rax * 4]
|
mov al, [3 + tokens.by_id + eax * 4]
|
||||||
and rax, 0xFF
|
and eax, 0xFF
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; ------------------------------------------------------------------------------
|
; ------------------------------------------------------------------------------
|
||||||
@@ -524,11 +499,14 @@ get_tte_typed_metadata:
|
|||||||
get_ModRM:
|
get_ModRM:
|
||||||
push rbx
|
push rbx
|
||||||
|
|
||||||
and dl, 11b ; mask for mod bits
|
and edi, 0xFFFF ; di = token table entry `reg`
|
||||||
shl dl, 6
|
and esi, 0xFFFF ; si = token table entry `R/M`
|
||||||
|
|
||||||
|
and edx, 11b ; dl = mod bits
|
||||||
|
shl edx, 6 ; and position
|
||||||
|
|
||||||
push rdi
|
push rdi
|
||||||
shr di, 8
|
shr edi, 8
|
||||||
cmp dil, 0xFE
|
cmp dil, 0xFE
|
||||||
pop rdi
|
pop rdi
|
||||||
je .pass_di_as_op_flag
|
je .pass_di_as_op_flag
|
||||||
@@ -541,25 +519,25 @@ get_ModRM:
|
|||||||
jmp .continue
|
jmp .continue
|
||||||
|
|
||||||
.pass_di_as_op_flag:
|
.pass_di_as_op_flag:
|
||||||
mov bl, dil ; bl = op flag
|
mov ebx, edi ; bl = op flag
|
||||||
and bl, 111b ; mask
|
and ebx, 111b
|
||||||
|
|
||||||
.continue:
|
.continue:
|
||||||
shl bl, 3
|
shl ebx, 3
|
||||||
|
|
||||||
mov rdi, rsi ; do the other one
|
mov edi, esi ; do the other one
|
||||||
|
|
||||||
; di = tte
|
; di = tte
|
||||||
call get_reg_bits
|
call get_reg_bits
|
||||||
; al = reg bits
|
; al = reg bits
|
||||||
|
|
||||||
mov cl, al
|
mov ecx, eax
|
||||||
|
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
or al, dl ; mod bits
|
or eax, edx ; mod bits
|
||||||
or al, bl ; reg bits
|
or eax, ebx ; reg bits
|
||||||
or al, cl ; R/M bits
|
or eax, ecx ; R/M bits
|
||||||
and rax, 0xFF ; mask for byte
|
and eax, 0xFF ; mask for byte
|
||||||
pop rbx
|
pop rbx
|
||||||
ret
|
ret
|
||||||
|
|
||||||
@@ -581,49 +559,45 @@ get_ModRM:
|
|||||||
; ------------------------------------------------------------------------------
|
; ------------------------------------------------------------------------------
|
||||||
|
|
||||||
get_opcode:
|
get_opcode:
|
||||||
and rdi, 0xFFFF
|
and edi, 0xFFFF ; di = token table entry
|
||||||
|
|
||||||
add rsi, 2
|
add esi, 2
|
||||||
and rsi, 111b
|
and esi, 111b ; offset within opcode entry
|
||||||
sub rsi, 2
|
sub esi, 2 ; between 0 and 5
|
||||||
|
|
||||||
xor eax, eax
|
xor eax, eax ; eax = opcodes.by_id index
|
||||||
|
|
||||||
.loop:
|
.loop:
|
||||||
cmp rax, (opcodes.by_id_end - opcodes.by_id) / 16 ; make sure it's still in range
|
cmp eax, (opcodes.by_id_end - opcodes.by_id) / 16 ; make sure it's still in range
|
||||||
jg .not_found
|
jg .not_found
|
||||||
|
|
||||||
shl rax, 4
|
shl eax, 4
|
||||||
mov cx, [opcodes.by_id + rax] ; next entry in opcodes.by_id
|
mov cx, [opcodes.by_id + eax] ; next entry in opcodes.by_id
|
||||||
shr rax, 4
|
shr eax, 4
|
||||||
|
|
||||||
cmp cx, di
|
cmp cx, di
|
||||||
je .found
|
je .found
|
||||||
|
|
||||||
inc rax
|
inc eax
|
||||||
jmp .loop
|
jmp .loop
|
||||||
.not_found:
|
.not_found:
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
mov al, UNRECOGNISED_ID_OPCODE
|
mov eax, UNRECOGNISED_ID_OPCODE
|
||||||
ret
|
ret
|
||||||
.found:
|
.found:
|
||||||
shl rax, 4
|
shl eax, 4
|
||||||
push rsi
|
push rsi
|
||||||
shr rsi, 1
|
shr esi, 1
|
||||||
mov dl, [rsi + 8 + opcodes.by_id + rax]
|
mov dl, [esi + 8 + opcodes.by_id + eax]
|
||||||
pop rsi
|
pop rsi
|
||||||
|
|
||||||
push rsi
|
test esi, 1 ; check if offset is odd
|
||||||
and rsi, 1
|
jz .found_continue
|
||||||
cmp esi, 1 ; check if offset is odd
|
shr edx, 4 ; if so, upper part of dl byte
|
||||||
pop rsi
|
|
||||||
jne .found_continue
|
|
||||||
|
|
||||||
shr dl, 4 ; if so, actually 1 further on dl byte
|
|
||||||
.found_continue:
|
.found_continue:
|
||||||
mov al, [rsi + 2 + opcodes.by_id + rax]
|
mov al, [esi + 2 + opcodes.by_id + eax]
|
||||||
and rax, 0xFF ; mask
|
and eax, 0xFF
|
||||||
and rdx, 0x0F ; mask
|
and edx, 0x0F
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; ------------------------------------------------------------------------------
|
; ------------------------------------------------------------------------------
|
||||||
@@ -644,8 +618,8 @@ get_reg_bits:
|
|||||||
; di = tte
|
; di = tte
|
||||||
call get_tte_typed_metadata
|
call get_tte_typed_metadata
|
||||||
; al = typed metadata
|
; al = typed metadata
|
||||||
shr al, 2 ; discard type data
|
shr eax, 2 ; discard type data
|
||||||
and al, 111b ; mask
|
and eax, 111b ; mask
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; ------------------------------------------------------------------------------
|
; ------------------------------------------------------------------------------
|
||||||
@@ -823,7 +797,7 @@ tokenise:
|
|||||||
pop rdi ; rdi = byte counter
|
pop rdi ; rdi = byte counter
|
||||||
pop rax ; rax = tokens processed
|
pop rax ; rax = tokens processed
|
||||||
|
|
||||||
mov [TOKEN_TABLE_ADDR + rax * TOKEN_TABLE_ENTRY_SIZE], cx
|
mov [TOKEN_TABLE_ADDR + rax * 2], cx
|
||||||
inc rax ; plus 1 token processed
|
inc rax ; plus 1 token processed
|
||||||
|
|
||||||
mov byte [.expecting], E_COMMENT | E_NEWLINE | E_WHITESPACE | E_OPERAND
|
mov byte [.expecting], E_COMMENT | E_NEWLINE | E_WHITESPACE | E_OPERAND
|
||||||
@@ -891,15 +865,15 @@ tokenise:
|
|||||||
|
|
||||||
; cx = token ID
|
; cx = token ID
|
||||||
.operand_register:
|
.operand_register:
|
||||||
mov [TOKEN_TABLE_ADDR + rax * TOKEN_TABLE_ENTRY_SIZE], cx
|
mov [TOKEN_TABLE_ADDR + rax * 2], cx
|
||||||
inc rax ; another token processed
|
inc rax ; another token processed
|
||||||
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 * 2], 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 * 2], cx
|
||||||
inc rax ; the register as returned by evaluate_operand
|
inc rax ; the register as returned by evaluate_operand
|
||||||
jmp .operand_break_continue
|
jmp .operand_break_continue
|
||||||
|
|
||||||
@@ -983,11 +957,8 @@ tokenise:
|
|||||||
; ------------------------------------------------------------------------------
|
; ------------------------------------------------------------------------------
|
||||||
|
|
||||||
evaluate_operand:
|
evaluate_operand:
|
||||||
push rdi
|
push rdi ; rdi -> start of operand
|
||||||
|
; rsi = size of operand
|
||||||
push rsi
|
|
||||||
mov rsi, rdi ; rsi -> start of operand
|
|
||||||
pop rdi ; rdi = size of operand
|
|
||||||
call trim_trailing_whitespace
|
call trim_trailing_whitespace
|
||||||
|
|
||||||
pop rdi ; rdi -> first byte of operand
|
pop rdi ; rdi -> first byte of operand
|
||||||
@@ -1467,38 +1438,38 @@ djb2:
|
|||||||
; trims whitespace from the start and end of the given byte array.
|
; trims whitespace from the start and end of the given byte array.
|
||||||
;
|
;
|
||||||
; parameters:
|
; parameters:
|
||||||
; rdi = size of list
|
; rdi -> start of list
|
||||||
; rsi -> start of list
|
; rsi = size of list
|
||||||
;
|
;
|
||||||
; returned:
|
; returned:
|
||||||
; rax = new size of list
|
; rax = new size of list
|
||||||
; ------------------------------------------------------------------------------
|
; ------------------------------------------------------------------------------
|
||||||
|
|
||||||
trim_trailing_whitespace:
|
trim_trailing_whitespace:
|
||||||
cmp rdi, 0 ; list of length zero
|
test rsi, rsi ; list of length zero
|
||||||
je .done ; already trimmed
|
jz .done ; already trimmed
|
||||||
|
|
||||||
push rdi
|
|
||||||
push rsi
|
push rsi
|
||||||
|
push rdi
|
||||||
|
|
||||||
mov dl, [rsi + rdi - 1] ; last element of given list
|
mov dl, [rdi + rsi - 1] ; last element of given list
|
||||||
mov rsi, whitespace_2 ; pointer of whitespace list
|
mov rsi, whitespace_2 ; pointer of whitespace list
|
||||||
mov rdi, 2 ; length of whitespace list
|
mov edi, 2 ; length of whitespace list
|
||||||
call elemb
|
call elemb
|
||||||
|
|
||||||
pop rsi ; rsi -> start of list
|
pop rdi ; rdi -> start of list
|
||||||
pop rdi ; rdi = size of list
|
pop rsi ; rsi = size of list
|
||||||
|
|
||||||
cmp al, 0 ; if last element whitespace
|
test eax, eax ; if last element whitespace
|
||||||
je .done ; then break
|
jz .done ; then break
|
||||||
|
|
||||||
.trim: ; otherwise one shorter
|
.trim: ; otherwise one shorter
|
||||||
dec rdi
|
dec rsi
|
||||||
call trim_trailing_whitespace
|
call trim_trailing_whitespace
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.done:
|
.done:
|
||||||
mov rax, rdi
|
mov rax, rsi
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; ------------------------------------------------------------------------------
|
; ------------------------------------------------------------------------------
|
||||||
@@ -1510,8 +1481,8 @@ trim_trailing_whitespace:
|
|||||||
|
|
||||||
clear_token_table:
|
clear_token_table:
|
||||||
xor eax, eax ; value to write
|
xor eax, eax ; value to write
|
||||||
mov rcx, TOKEN_TABLE_SIZE / 4 ; number of double words
|
mov ecx, TOKEN_TABLE_SIZE / 4 ; number of double words
|
||||||
mov rdi, TOKEN_TABLE_ADDR ; address to start
|
mov edi, TOKEN_TABLE_ADDR ; address to start
|
||||||
rep stosd
|
rep stosd
|
||||||
ret
|
ret
|
||||||
|
|
||||||
@@ -1524,8 +1495,8 @@ clear_token_table:
|
|||||||
|
|
||||||
clear_test_arena:
|
clear_test_arena:
|
||||||
xor eax, eax ; value to write
|
xor eax, eax ; value to write
|
||||||
mov rcx, TOKEN_TABLE_SIZE / 4 ; number of double words
|
mov ecx, TOKEN_TABLE_SIZE / 4 ; number of double words
|
||||||
mov rdi, TOKEN_TABLE_ADDR ; address to start
|
mov edi, TOKEN_TABLE_ADDR ; address to start
|
||||||
rep stosd
|
rep stosd
|
||||||
ret
|
ret
|
||||||
|
|
||||||
@@ -1538,8 +1509,8 @@ clear_test_arena:
|
|||||||
|
|
||||||
clear_output_arena:
|
clear_output_arena:
|
||||||
xor eax, eax ; value to write
|
xor eax, eax ; value to write
|
||||||
mov rcx, OUTPUT_SIZE / 4 ; number of double words
|
mov ecx, OUTPUT_SIZE / 4 ; number of double words
|
||||||
mov rdi, OUTPUT_ADDR ; address to start
|
mov edi, OUTPUT_ADDR ; address to start
|
||||||
rep stosd
|
rep stosd
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|||||||
@@ -654,7 +654,7 @@ test_evaluate_operand:
|
|||||||
|
|
||||||
msg_pass:
|
msg_pass:
|
||||||
db 0x0A
|
db 0x0A
|
||||||
times (TEST_LINE_LENGTH + .start + 5 - .end) db " ", ; right align
|
times (TEST_LINE_LENGTH + .start - .end) db " ", ; right align
|
||||||
db 0x1B, "[32m"
|
db 0x1B, "[32m"
|
||||||
.start db "passed."
|
.start db "passed."
|
||||||
.end db 0x1B, "[0m", 0x0A, 0x00
|
.end db 0x1B, "[0m", 0x0A, 0x00
|
||||||
|
|||||||
Reference in New Issue
Block a user