fix so nasm can compile for testing
This commit is contained in:
parent
44d5e95970
commit
7472eb1279
|
|
@ -12,6 +12,10 @@
|
||||||
;; +0x6000 num_labels: u32
|
;; +0x6000 num_labels: u32
|
||||||
;; +0x6004 scratch space
|
;; +0x6004 scratch space
|
||||||
|
|
||||||
|
section .data
|
||||||
|
_start_lbl db "_start", 0
|
||||||
|
|
||||||
|
section .text
|
||||||
;; exits the program
|
;; exits the program
|
||||||
panic:
|
panic:
|
||||||
mov rax, 60 ; syscall: exit
|
mov rax, 60 ; syscall: exit
|
||||||
|
|
@ -25,20 +29,21 @@ die:
|
||||||
syscall
|
syscall
|
||||||
|
|
||||||
;; calculates a quick hash of a byte sequence given by rdi (pointer) and rsi (length)
|
;; calculates a quick hash of a byte sequence given by rdi (pointer) and rsi (length)
|
||||||
.fashhash_exit:
|
|
||||||
ret
|
|
||||||
fasthash:
|
fasthash:
|
||||||
mov eax, 0x811c9dc5 ; FNV offset basis
|
mov eax, 0x811c9dc5 ; FNV offset basis
|
||||||
.fashhash_loop:
|
.fashhash_loop:
|
||||||
test rsi, rsi
|
test rsi, rsi
|
||||||
jz .fashhash_done
|
jz .fashhash_exit
|
||||||
movzx ecx, byte ptr [rdi] ; get next byte
|
movzx ecx, byte [rdi] ; get next byte
|
||||||
xor eax, ecx
|
xor eax, ecx
|
||||||
imul eax, 0x1000193 ; FNV prime
|
imul eax, 0x1000193 ; FNV prime
|
||||||
inc rdi
|
inc rdi
|
||||||
dec rsi
|
dec rsi
|
||||||
jmp .fashhash_loop
|
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 the label pointed at by rdi with length rsi, and the current file offset onto the labels array.
|
||||||
push_lbl:
|
push_lbl:
|
||||||
mov eax, dword [r15 + 0x6000]
|
mov eax, dword [r15 + 0x6000]
|
||||||
|
|
@ -53,19 +58,14 @@ push_lbl:
|
||||||
mov qword [rdi + rdx], rax ; store hash in labels array
|
mov qword [rdi + rdx], rax ; store hash in labels array
|
||||||
mov eax, dword [r15 + 0x500c] ; get current file offset
|
mov eax, dword [r15 + 0x500c] ; get current file offset
|
||||||
mov dword [rdi + rdx + 8], eax ; store file offset in labels array
|
mov dword [rdi + rdx + 8], eax ; store file offset in labels array
|
||||||
inc dword ptr [r15 + 0x6000]
|
inc dword [r15 + 0x6000]
|
||||||
ret
|
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.
|
;; 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:
|
find_lbl:
|
||||||
call fasthash
|
call fasthash
|
||||||
lea rdx, [r15 + 0x5010] ; rdx = pointer to start of labels array
|
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:
|
.find_lbl_loop:
|
||||||
test rbx, rbx
|
test rbx, rbx
|
||||||
jz .find_lbl_not_found
|
jz .find_lbl_not_found
|
||||||
|
|
@ -75,18 +75,25 @@ find_lbl:
|
||||||
add rdx, 12 ; move to next label entry
|
add rdx, 12 ; move to next label entry
|
||||||
jmp .find_lbl_loop
|
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:
|
die_jmp_start:
|
||||||
;; @_start_lbl: 5F 73 74 61 72 74 00 00
|
;; @_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
|
mov rsi, 6
|
||||||
call find_lbl
|
call find_lbl
|
||||||
add dword [r15 + 0x500c], 5 ; advance the file offset by 5
|
add dword [r15 + 0x500c], 5 ; advance the file offset by 5
|
||||||
sub eax, dword [r15 + 0x500c] ; add current file offset
|
sub eax, dword [r15 + 0x500c] ; add current file offset
|
||||||
mov edi, dword [r15 + 0x5004] ; get current write cursor
|
mov edi, dword [r15 + 0x5004] ; get current write cursor
|
||||||
lea rdi, [r15 + edi + 0x1000] ; rdi = pointer to write location in write_buf
|
lea rdi, [r15 + rdi + 0x1000] ; rdi = pointer to write location in write_buf
|
||||||
mov byte ptr [rdi], 0xe9 ; write the opcode for jmp rel32
|
mov byte [rdi], 0xe9 ; write the opcode for jmp rel32
|
||||||
mov dword ptr [rdi + 1], eax ; write the offset of the label reference
|
mov dword [rdi + 1], eax ; write the offset of the label reference
|
||||||
add dword ptr [r15 + 0x5004], 5 ; advance the write cursor by 5
|
add dword [r15 + 0x5004], 5 ; advance the write cursor by 5
|
||||||
call die
|
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
|
;; 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 rax, 1 ; syscall: write
|
||||||
mov rdi, 1 ; fd: stdout
|
mov rdi, 1 ; fd: stdout
|
||||||
lea rsi, [r15 + 0x1000] ; buf: pointer to write_buf
|
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
|
syscall
|
||||||
mov dword ptr [r15 + 0x5004], 0
|
mov dword [r15 + 0x5004], 0
|
||||||
ret
|
ret
|
||||||
|
|
||||||
;; return the next byte from the input
|
;; return the next byte from the input
|
||||||
;; automatically writes to stdout and reads from stdin if we are at the end of the buffer
|
;; 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:
|
rd_buf:
|
||||||
mov eax, dword ptr [r15 + 0x5000] ; get read_cursor
|
mov eax, dword [r15 + 0x5000] ; get read_cursor
|
||||||
cmp eax, dword ptr [r15 + 0x5008] ; compare to read_end
|
cmp eax, dword [r15 + 0x5008] ; compare to read_end
|
||||||
jl .rd_buf_end
|
jl .rd_buf_end
|
||||||
call wrt_stdout
|
call wrt_stdout
|
||||||
call rd_stdin
|
call rd_stdin
|
||||||
jmp .rd_buf_end
|
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:
|
;; The grammar is slightly updated from hex0, as follows:
|
||||||
;; program = (label-def / instruction-seq / comment)*
|
;; program = (label-def / instruction-seq / comment)*
|
||||||
;; comment = ";" [^\n]* "\n"
|
;; comment = ";" [^\n]* "\n"
|
||||||
|
|
@ -144,98 +152,106 @@ rd_buf:
|
||||||
;; whitespace = [ \t\n]+
|
;; whitespace = [ \t\n]+
|
||||||
|
|
||||||
|
|
||||||
.skip_line_read:
|
|
||||||
call rd_buf
|
|
||||||
skip_line:
|
skip_line:
|
||||||
cmp al, '\n'
|
cmp al, `\n`
|
||||||
jne .skip_line_read
|
jne .skip_line_read
|
||||||
call rd_buf
|
call rd_buf
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.skip_whitespace_read:
|
.skip_line_read:
|
||||||
call rd_buf
|
call rd_buf
|
||||||
|
jmp skip_line
|
||||||
|
|
||||||
skip_whitespaces:
|
skip_whitespaces:
|
||||||
cmp al, ' '
|
cmp al, ' '
|
||||||
je .skip_whitespace_read
|
je .skip_whitespace_read
|
||||||
cmp al, '\t'
|
cmp al, `\t`
|
||||||
je .skip_whitespace_read
|
je .skip_whitespace_read
|
||||||
cmp al, '\n'
|
cmp al, `\n`
|
||||||
je .skip_whitespace_read
|
je .skip_whitespace_read
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.skip_comment_ret:
|
.skip_whitespace_read:
|
||||||
ret
|
|
||||||
.skip_comment_read:
|
|
||||||
call rd_buf
|
call rd_buf
|
||||||
|
jmp skip_whitespaces
|
||||||
|
|
||||||
skip_comment:
|
skip_comment:
|
||||||
cmp al, '\;'
|
cmp al, ";"
|
||||||
jne .skip_comment_ret
|
jne .skip_comment_ret
|
||||||
call skip_line
|
call skip_line
|
||||||
ret
|
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:
|
.get_next_token_skip:
|
||||||
call skip_whitespaces
|
call skip_whitespaces
|
||||||
call skip_comment
|
call skip_comment
|
||||||
get_next_token:
|
jmp 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
|
|
||||||
|
|
||||||
;; read the label into scratch, call push_lbl
|
;; read the label into scratch, call push_lbl
|
||||||
.label_ret
|
|
||||||
lea rdi, [r15 + 0x6004] ; rdi = pointer to scratch
|
|
||||||
call push_lbl
|
|
||||||
ret
|
|
||||||
label:
|
label:
|
||||||
lea rdi, [r15 + 0x6004] ; rdi = pointer to scratch
|
cmp al, '@'
|
||||||
|
jne .not_label
|
||||||
xor rsi, rsi ; rsi = length of 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, ':'
|
cmp al, ':'
|
||||||
je .label_ret
|
je .label_ret
|
||||||
mov byte ptr [rdi + rsi], al
|
mov byte [rdi + rsi], al
|
||||||
inc rsi
|
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
|
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:
|
.label_ref_ret:
|
||||||
lea rdi, [r15 + 0x6004]
|
lea rdi, [r15 + 0x6004]
|
||||||
call find_lbl
|
call find_lbl
|
||||||
add dword ptr [r15 + 0x500c], 4 ; advance the file offset by 4
|
add dword [r15 + 0x500c], 4 ; advance the file offset by 4
|
||||||
sub eax, dword ptr [r15 + 0x500c] ; add current file offset
|
sub eax, dword [r15 + 0x500c] ; add current file offset
|
||||||
mov edi, dword ptr [r15 + 0x5004] ; get current write cursor
|
mov edi, dword [r15 + 0x5004] ; get current write cursor
|
||||||
mov dword ptr [r15 + 0x1000 + rdi], eax ; write the opcode for jmp rel32
|
mov dword [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 + 0x5004], 4 ; advance the write cursor by 4
|
||||||
|
.not_label_ref:
|
||||||
ret
|
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:
|
char_to_u4:
|
||||||
cmp al, '0'
|
cmp al, '0'
|
||||||
jb .invalid_hex
|
jb .invalid_hex
|
||||||
|
|
@ -251,35 +267,52 @@ char_to_u4:
|
||||||
jbe .is_upper_hex
|
jbe .is_upper_hex
|
||||||
jmp .invalid_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:
|
octet:
|
||||||
sub rsp, 8
|
sub rsp, 8
|
||||||
call char_to_u4
|
call char_to_u4
|
||||||
shl rax, 4
|
mov byte [rsp], al
|
||||||
mov byte ptr [rsp], al
|
|
||||||
call rd_buf
|
call rd_buf
|
||||||
call char_to_u4
|
call char_to_u4
|
||||||
or byte ptr [rsp], al
|
mov bl, byte [rsp]
|
||||||
mov al, byte ptr [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
|
add rsp, 8
|
||||||
inc file_offset
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
global _start
|
||||||
_start:
|
_start:
|
||||||
push rbp
|
push rbp
|
||||||
mov rbp, rsp
|
mov rbp, rsp
|
||||||
sub rsp, 0x8000 ; allocate space for our variables + some scratch space
|
sub rsp, 0x8000 ; allocate space for our variables + some scratch space
|
||||||
mov r15, rsp ; r15 will point to the start of our variables
|
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:
|
.loop:
|
||||||
|
call rd_buf
|
||||||
call get_next_token
|
call get_next_token
|
||||||
cmp al, '@'
|
|
||||||
;; label
|
|
||||||
call label
|
call label
|
||||||
cmp al, '\''
|
|
||||||
;; label-ref
|
|
||||||
call label_ref
|
call label_ref
|
||||||
;; else opcode
|
|
||||||
call octet
|
call octet
|
||||||
jmp .loop
|
jmp .loop
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue