diff --git a/twasm/asm/main.asm b/twasm/asm/main.asm index a48c652..c068c5e 100644 --- a/twasm/asm/main.asm +++ b/twasm/asm/main.asm @@ -75,6 +75,7 @@ start: ; 0x1000 ; memory address, following byte should be a register ; 0x1000 ; not a register ; - operator tokens followed by the wrong number of arguments +; TODO enforce this in `tokenise` ; 0x004F ; hlt, expects 0 arguments ; 0x0000 ; rax, an argument ; - an undefined token is included, like 0x0051 @@ -92,17 +93,6 @@ assemble: mov di, [rax * TOKEN_TABLE_ENTRY_SIZE + TOKEN_TABLE_ADDR] ; next tte push rax - ; di = next tte - call get_tte_type - ; al = type of token - - ; on stack: - ; rax = number of tokens processed - ; rdi = number of tokens in table - cmp al, 0x01 ; check if next tte's type is an operator - je .operator ; if so, handle case of operator - jne .continue_operator ; if not, jump past the case - ; di = tte of operator .operator: ; if next tte's type is an operator: push rdi @@ -122,7 +112,9 @@ assemble: cmp al, 2 ; check if operator has two operands je .operator_2 ; if so, handle case of two operands - jmp .operator_with_args ; of not, handle case of some operands + jmp .unexpected_token ; TODO actually check operator type or not first + ; 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: @@ -138,7 +130,11 @@ assemble: call .output_byte pop rdi - jmp .continue + pop rax ; rax = number of tokens processed + pop rdi ; rdi = total number of tokens + inc rax + cmp rax, rdi + jmp .loop ; di = tte of operator .operator_1: @@ -327,99 +323,13 @@ assemble: jge .break jmp .loop - ; di = tte of operator - .operator_with_args: - mov [.pending_operator_num_args], al ; save # args fttb - - push rdi - ; di = next tte - call get_opcode - ; al = opcode - mov [.pending_operator_opcode], al ; save opcode fttb - pop rdi - - jmp .continue - - .continue_operator: - cmp al, 0x02 ; check if next tte's type is a register - je .register ; if so, handle case of register - jne .continue_register ; if not, jump past the case - - ; di MUST be a valid register tte - .register: ; if next tte's type is a register: - call .dec_num_args ; because we've found an argument, we need 1 fewer noch - - cmp byte [.pending_operator_num_args], 1 ; check if this is 1st of 2 args - je .register_one_of_two ; if so, jump to handler - - cmp byte [.pending_operator_num_args], 0 ; check if this is the last arg - je .register_last ; if so, jump to handler - ; note: not necessarily the last - ; of 2 args, it could also be the - ; last of 1 - - ; otherwise, discard the token, reset things, and keep going :/ - push rsi - mov rsi, .warn_unexpected_register - call print.warn - pop rsi - call .reset_state - jmp .continue_register - - .register_one_of_two: ; if it's the first of 2 arguments: - mov [.first_argument], di ; ax = tte - jmp .continue_register - - .register_last: ; if it's the last argument: - ; swap so the first argument sits in .first_argument - push rax - mov ax, di - mov di, [.first_argument] - mov [.first_argument], ax - pop rax - - cmp di, UNRECOGNISED_TOKEN_ID ; check if the second argument is defined - jne .operator_finalise_2 ; if so, there are 2 arguments - ; if not, there is just 1 - - .operator_finalise_1: - mov di, 0x0000 ; id of rax. reg bits 000b - - .operator_finalise_2: - ; TODO avoid swapping earlier and now :/ - mov cx, di - mov di, [.first_argument] - mov si, cx - mov dl, 11b - call get_ModRM - ; al = ModR/M byte - push rax - mov al, [.pending_operator_opcode] - call .output_byte ; output operator's opcode - pop rax - - call .output_byte ; output ModR/M byte - - call .reset_state ; reset all the state parts of this function - jmp .continue_register - - .continue_register: - - .continue: - pop rax ; rax = number of tokens processed - pop rdi ; rdi = total number of tokens - - inc rax - cmp rax, rdi - jge .break ; at end of table, break - jmp .loop - .break: ret - ; constants - - .warn_unexpected_register db "ignoring unexpected register", 0x0A, 0x00 + .unexpected_token: + mov rsi, .msg_unexpected_token + call print.error + jmp halt ; procedures @@ -430,35 +340,10 @@ assemble: inc edx ; increment address mov [.next_output_byte], edx ; put output byte's address ret + .next_output_byte dd OUTPUT_ADDR ; next empty byte in output + ; TODO get rid of this sketchy bit of state - ; runs dec on .pending_operator_num_args - .dec_num_args: - push rax - mov al, [.pending_operator_num_args] - dec al - mov [.pending_operator_num_args], al - pop rax - ret - - ; resets sketchy memory-based state - ; TODO put this state in an accumulator or something - .reset_state: - ; I don't actually know if these `word` directives are needed - ; TODO check that. I think they are, becasue Nasm doesn't record the size - ; of labels? - mov word [.pending_operator_opcode], UNRECOGNISED_TOKEN_ID - mov [.pending_operator_num_args], 0x00 - mov word [.first_argument], UNRECOGNISED_TOKEN_ID - ret - - ; state variables - - .pending_operator_opcode db 0x00 ; the operator seeking args - .pending_operator_num_args db 0x00 ; # of args it takes - - .first_argument dw UNRECOGNISED_TOKEN_ID ; first argument if there are two - - .next_output_byte dd OUTPUT_ADDR ; next empty byte in output + .msg_unexpected_token db "unexpected token while assembling, aborting", 0x0A, 0x00 .msg_operator_0 db "operator_0", 0x0A, 0x00 .msg_operator_1 db "operator_1", 0x0A, 0x00 .msg_operator_1_memory_access db "operator_1_memory_access", 0x0A, 0x00