Assembly code is really fun

This commit is contained in:
Bill Rossi 2023-12-21 09:40:11 -05:00
parent 7cef5d2316
commit 47c1398c6d
4 changed files with 118 additions and 42 deletions

View File

@ -1,6 +1,7 @@
format ELF64 executable 3
include "lib/linux_syscall.inc"
include "lib/itoa.inc"
include "lib/print.inc"
segment readable executable
entry main
@ -20,6 +21,17 @@ main:
;; Close the input file
close [input_fd]
call part_1
call part_2
;; Unmap the mapped file
munmap [input], [file_stat.st_size]
;; Done!
exit 0
part_1:
;; Setup the loop variables for counting
;; rbx starts at the first byte of input, and is incremented to read it all
mov rbx, [input]
@ -28,42 +40,47 @@ main:
;; rdx counts down from the file's size to 0
mov rdx, [file_stat.st_size]
lp:
.lp:
;; Is the current character the "go up" character?
cmp byte [rbx], '('
;; If so, jump to "up"
je up
je .up
;; Is the current character the "go down" character?
cmp byte [rbx], ')'
;; If so, it's the "go down" character, so decrement the current floor
je down
je .down
;; Otherwise it's the EOF probably, skip it
jmp other
up:
jmp .other
.up:
;; We should "go up", so increment the current floor
inc rcx
jmp other
down:
jmp .other
.down:
;; We should "go down", so decrement the current floor
dec rcx
other:
.other:
;; Check the next character in the file
inc rbx
;; Count down the file's length
dec rdx
;; If we haven't reached the end of the file, loop
jnz lp
jnz .lp
;; Put part 1's answer in rax
mov rax, rcx
mov rbx, part_1
;; Convert rax to a c string in rbx
mov rbx, part_1_answer
call itoa
;; Write part 1's verbiage to STDOUT
write STDOUT, part_1_verbiage, 8
write STDOUT, part_1, 6
write STDOUT, newline, 1
;; Print part 1's verbiage
mov rdi, part_1_verbiage
call print_c_string
call print_newline
ret
part_2:
;; Setup the loop variables for counting
;; rbx starts at the first byte of input, and is incremented to read it all
mov rbx, [input]
@ -71,44 +88,40 @@ other:
mov rcx, 0
;; rdx tracks how many steps we've made so far
mov rdx, 0
lp2:
.lp:
cmp byte [rbx], '('
je up2
je .up
dec rcx
jmp moved2
up2:
jmp .moved
.up:
inc rcx
moved2:
.moved:
inc rdx
cmp rcx, 0
jl done
jl .done
inc rbx
jnz lp2
done:
jnz .lp
.done:
;; Put part 2's answer in rax
mov rax, rdx
mov rbx, part_2
;; Convert rax to a c string in rbx
mov rbx, part_2_answer
call itoa
;; Write part 2's verbiage to STDOUT
write STDOUT, part_2_verbiage, 8
write STDOUT, part_2, 6
write STDOUT, newline, 1
;; Unmap the mapped file
munmap [input], [file_stat.st_size]
;; Done!
exit 0
;; Print part 2's verbiage
mov rdi, part_2_verbiage
call print_c_string
call print_newline
ret
segment readable writable
input_filename db '../data/2015/1/input.txt', 0
input_fd dq -1
input dq -1
part_1_verbiage db 'Part 1: ', 0
part_1 db ' ', 0
part_2_verbiage db 'Part 2: ', 0
part_2 db ' ', 0
newline db 10
part_1_verbiage db 'Part 1: '
part_1_answer db ' ', 0
part_2_verbiage db 'Part 2: '
part_2_answer db ' ', 0
file_stat s_stat

View File

@ -1,22 +1,28 @@
format ELF64 executable 3
include "lib/linux_syscall.inc"
include "lib/print.inc"
include "lib/itoa.inc"
segment readable executable
entry main
main:
mov rdi, input_filename
mov rax, 42069
mov rbx, part_1
call itoa
mov rdi, part_1_verbiage
call print_c_string
exit 0
segment readable writable
input_filename db '../data/2015/1/input.txt', 0, 'more text', 0
input_fd dq -1
input dq -1
part_1_verbiage db 'Part 1: ', 0
part_1 db ' ', 0
part_1_verbiage db 'Part 1: '
part_1 db ' ', 0
part_2_verbiage db 'Part 2: ', 0
part_2 db ' ', 0
part_2 db ' ', 0
newline db 10
file_stat s_stat

View File

@ -1,12 +1,21 @@
;; rax contains the integer
;; rbx contains a pointer to the string buffer
itoa:
;; Fill 6 digits with zeroes
mov byte [rbx], '0'
mov byte [rbx + 1], '0'
mov byte [rbx + 2], '0'
mov byte [rbx + 3], '0'
mov byte [rbx + 4], '0'
mov byte [rbx + 5], '0'
;; Special case for the number '0'
cmp rax, 0
jne .not_zero
mov byte [rbx + 1], 0
ret
.not_zero:
sub rax, 100000
inc byte [rbx]
cmp rax, 0
@ -42,4 +51,47 @@ itoa:
add rax, 10
dec byte [rbx + 4]
add [rbx + 5], rax
;; Time to shift everything left
;; End the current string with a null byte
mov byte [rbx + 6], 0
.shift_left_loop:
cmp byte [rbx], '0'
jne .done
mov rcx, rbx
inc rcx
mov rdx, [rcx]
and rdx, 255
mov [rbx], dx
inc rcx
mov rdx, [rcx]
and rdx, 255
mov [rbx + 1], dx
inc rcx
mov rdx, [rcx]
and rdx, 255
mov [rbx + 2], dx
inc rcx
mov rdx, [rcx]
and rdx, 255
mov [rbx + 3], dx
inc rcx
mov rdx, [rcx]
and rdx, 255
mov [rbx + 4], dx
inc rcx
mov rdx, [rcx]
and rdx, 255
mov [rbx + 5], dx
jmp .shift_left_loop
.done:
ret

View File

@ -31,3 +31,8 @@ print_c_string:
write STDOUT, r11, r12
ret
newline db 10, 0
print_newline:
write STDOUT, newline, 1
ret