diff --git a/stages/hex0/hex1.asm b/stages/hex0/hex1.asm index d5e8bee..7e1acfe 100644 --- a/stages/hex0/hex1.asm +++ b/stages/hex0/hex1.asm @@ -12,6 +12,10 @@ ;; +0x6000 num_labels: u32 ;; +0x6004 scratch space +section .data + _start_lbl db "_start", 0 + +section .text ;; exits the program panic: mov rax, 60 ; syscall: exit @@ -25,20 +29,21 @@ die: syscall ;; calculates a quick hash of a byte sequence given by rdi (pointer) and rsi (length) - .fashhash_exit: - ret fasthash: mov eax, 0x811c9dc5 ; FNV offset basis .fashhash_loop: test rsi, rsi - jz .fashhash_done - movzx ecx, byte ptr [rdi] ; get next byte + jz .fashhash_exit + movzx ecx, byte [rdi] ; get next byte xor eax, ecx imul eax, 0x1000193 ; FNV prime inc rdi dec rsi jmp .fashhash_loop + .fashhash_exit: + ret + ;; push the label pointed at by rdi with length rsi, and the current file offset onto the labels array. push_lbl: mov eax, dword [r15 + 0x6000] @@ -53,19 +58,14 @@ push_lbl: mov qword [rdi + rdx], rax ; store hash in labels array mov eax, dword [r15 + 0x500c] ; get current file offset mov dword [rdi + rdx + 8], eax ; store file offset in labels array - inc dword ptr [r15 + 0x6000] + inc dword [r15 + 0x6000] ret ;; searches for the offset of the label with the name pointed at by rdi with length rsi, and returns it in rax. If the label is not found, dies. - .find_lbl_not_found: - call panic - .find_lbl_found: - mov eax, dword ptr [rdx + 8] ; get file offset of label - ret find_lbl: call fasthash lea rdx, [r15 + 0x5010] ; rdx = pointer to start of labels array - mov ebx, dword ptr [r15 + 0x6000] + mov ebx, dword [r15 + 0x6000] .find_lbl_loop: test rbx, rbx jz .find_lbl_not_found @@ -75,18 +75,25 @@ find_lbl: add rdx, 12 ; move to next label entry jmp .find_lbl_loop + .find_lbl_not_found: + call panic + .find_lbl_found: + mov eax, dword [rdx + 8] ; get file offset of label + ret + die_jmp_start: ;; @_start_lbl: 5F 73 74 61 72 74 00 00 - lea rdi, [@_start_lbl] + ;; lea rdi, [@_start_lbl] + mov rdi, _start_lbl mov rsi, 6 call find_lbl add dword [r15 + 0x500c], 5 ; advance the file offset by 5 sub eax, dword [r15 + 0x500c] ; add current file offset mov edi, dword [r15 + 0x5004] ; get current write cursor - lea rdi, [r15 + edi + 0x1000] ; rdi = pointer to write location in write_buf - mov byte ptr [rdi], 0xe9 ; write the opcode for jmp rel32 - mov dword ptr [rdi + 1], eax ; write the offset of the label reference - add dword ptr [r15 + 0x5004], 5 ; advance the write cursor by 5 + lea rdi, [r15 + rdi + 0x1000] ; rdi = pointer to write location in write_buf + mov byte [rdi], 0xe9 ; write the opcode for jmp rel32 + mov dword [rdi + 1], eax ; write the offset of the label reference + add dword [r15 + 0x5004], 5 ; advance the write cursor by 5 call die ;; reads up to 0x1000 bytes from stdin into buf, and sets read_end to the number of bytes read, and resets read_cursor to 0 @@ -108,27 +115,28 @@ wrt_stdout: mov rax, 1 ; syscall: write mov rdi, 1 ; fd: stdout lea rsi, [r15 + 0x1000] ; buf: pointer to write_buf - mov rdx, dword [r15 + 0x5004] ; count: write_cursor + mov edx, dword [r15 + 0x5004] ; count: write_cursor syscall - mov dword ptr [r15 + 0x5004], 0 + mov dword [r15 + 0x5004], 0 ret ;; return the next byte from the input ;; automatically writes to stdout and reads from stdin if we are at the end of the buffer - .rd_buf_end: - mov eax, dword ptr [r15 + 0x5000] ; get read_cursor - xor rax, rax - mov al, byte ptr [r15 + rax] ; get next byte from buf - inc dword ptr [r15 + 0x5000] ; advance read_cursor - ret rd_buf: - mov eax, dword ptr [r15 + 0x5000] ; get read_cursor - cmp eax, dword ptr [r15 + 0x5008] ; compare to read_end + mov eax, dword [r15 + 0x5000] ; get read_cursor + cmp eax, dword [r15 + 0x5008] ; compare to read_end jl .rd_buf_end call wrt_stdout call rd_stdin jmp .rd_buf_end + .rd_buf_end: + mov edx, dword [r15 + 0x5000] ; get read_cursor + xor rax, rax + mov al, byte [r15 + rdx] ; get next byte from buf + inc dword [r15 + 0x5000] ; advance read_cursor + ret + ;; The grammar is slightly updated from hex0, as follows: ;; program = (label-def / instruction-seq / comment)* ;; comment = ";" [^\n]* "\n" @@ -144,98 +152,106 @@ rd_buf: ;; whitespace = [ \t\n]+ - .skip_line_read: - call rd_buf skip_line: - cmp al, '\n' + cmp al, `\n` jne .skip_line_read call rd_buf ret - .skip_whitespace_read: + .skip_line_read: call rd_buf + jmp skip_line + skip_whitespaces: cmp al, ' ' je .skip_whitespace_read - cmp al, '\t' + cmp al, `\t` je .skip_whitespace_read - cmp al, '\n' + cmp al, `\n` je .skip_whitespace_read ret - .skip_comment_ret: - ret - .skip_comment_read: + .skip_whitespace_read: call rd_buf + jmp skip_whitespaces + skip_comment: - cmp al, '\;' + cmp al, ";" jne .skip_comment_ret call skip_line ret + .skip_comment_ret: + ret + +get_next_token: + cmp al, ";" + je .get_next_token_skip + cmp al, ' ' + je .get_next_token_skip + cmp al, `\t` + je .get_next_token_skip + cmp al, `\n` + je .get_next_token_skip + ret .get_next_token_skip: call skip_whitespaces call skip_comment -get_next_token: - cmp al, '\;' - je .get_next_token_skip - cmp al, ' ' - je .get_next_token_skip - cmp al, '\t' - je .get_next_token_skip - cmp al, '\n' - je .get_next_token_skip - ret + jmp get_next_token ;; read the label into scratch, call push_lbl - .label_ret - lea rdi, [r15 + 0x6004] ; rdi = pointer to scratch - call push_lbl - ret label: - lea rdi, [r15 + 0x6004] ; rdi = pointer to scratch + cmp al, '@' + jne .not_label xor rsi, rsi ; rsi = length of label + .label_loop: + push rsi + call rd_buf + pop rsi + lea rdi, [r15 + 0x6004] ; rdi = pointer to scratch cmp al, ':' je .label_ret - mov byte ptr [rdi + rsi], al + mov byte [rdi + rsi], al inc rsi + jmp .label_loop + + .label_ret: + lea rdi, [r15 + 0x6004] ; rdi = pointer to scratch + call push_lbl + .not_label: + ret + +label_ref: + cmp al, "'" + jne .not_label_ref call rd_buf - jmp label + xor rsi, rsi ; rsi = length of label + .label_ref_loop: + push rsi + call rd_buf + pop rsi + lea rdi, [r15 + 0x6004] ; rdi = pointer to scratch + cmp al, ' ' + je .label_ref_ret + cmp al, `\t` + je .label_ref_ret + cmp al, `\n` + je .label_ref_ret + mov byte [rdi + rsi], al + inc rsi + jmp .label_ref_loop .label_ref_ret: lea rdi, [r15 + 0x6004] call find_lbl - add dword ptr [r15 + 0x500c], 4 ; advance the file offset by 4 - sub eax, dword ptr [r15 + 0x500c] ; add current file offset - mov edi, dword ptr [r15 + 0x5004] ; get current write cursor - mov dword ptr [r15 + 0x1000 + rdi], eax ; write the opcode for jmp rel32 - add dword ptr [r15 + 0x5004], 4 ; advance the write cursor by 4 + add dword [r15 + 0x500c], 4 ; advance the file offset by 4 + sub eax, dword [r15 + 0x500c] ; add current file offset + mov edi, dword [r15 + 0x5004] ; get current write cursor + mov dword [r15 + 0x1000 + rdi], eax ; write the opcode for jmp rel32 + add dword [r15 + 0x5004], 4 ; advance the write cursor by 4 + .not_label_ref: ret -label_ref: - lea rdi, [r15 + 0x6004] ; rdi = pointer to scratch - xor rsi, rsi - call rd_buf - cmp al, ' ' - je .label_ref_ret - cmp al, '\t' - je .label_ref_ret - cmp al, '\n' - je .label_ref_ret - mov byte ptr [rdi + rsi], al - inc rsi - jmp label_ref - .invalid_hex: - call panic - .is_digit: - sub al, '0' - ret - .is_lower_hex: - sub al, 'a' - 10 - ret - .is_upper_hex: - sub al, 'A' - 10 - ret char_to_u4: cmp al, '0' jb .invalid_hex @@ -251,35 +267,52 @@ char_to_u4: jbe .is_upper_hex jmp .invalid_hex + .invalid_hex: + call panic + .is_digit: + sub al, '0' + ret + .is_lower_hex: + sub al, 'a' - 10 + ret + .is_upper_hex: + sub al, 'A' - 10 + ret + octet: sub rsp, 8 call char_to_u4 - shl rax, 4 - mov byte ptr [rsp], al + mov byte [rsp], al call rd_buf call char_to_u4 - or byte ptr [rsp], al - mov al, byte ptr [rsp] + mov bl, byte [rsp] + shl bl, 4 + or al, bl + mov edi, dword [r15 + 0x5004] ; get current write cursor + lea rdx, [r15 + 0x1000] + mov byte [rdi + rdx], al ; write the byte to the write_buf + inc dword [r15 + 0x5004] ; advance the write cursor by 1 + inc dword [r15 + 0x500c] ; advance file offset by 1 add rsp, 8 - inc file_offset ret + global _start _start: push rbp mov rbp, rsp sub rsp, 0x8000 ; allocate space for our variables + some scratch space mov r15, rsp ; r15 will point to the start of our variables + mov dword [r15 + 0x6000], 0 ; num_labels = 0 + mov dword [r15 + 0x500c], 0 ; file_offset = 0 + mov dword [r15 + 0x5008], 0 ; read_end = 0 + mov dword [r15 + 0x5004], 0 ; write_cursor = 0 + mov dword [r15 + 0x5000], 0 ; read_cursor = 0 - call rd_buf .loop: + call rd_buf call get_next_token - cmp al, '@' - ;; label call label - cmp al, '\'' - ;; label-ref call label_ref - ;; else opcode call octet jmp .loop