2023-12-19 04:20:18 -05:00
|
|
|
format ELF64 executable 3
|
2023-12-20 07:16:28 -05:00
|
|
|
include "lib/linux_syscall.inc"
|
|
|
|
include "lib/itoa.inc"
|
2023-12-19 04:20:18 -05:00
|
|
|
|
|
|
|
segment readable executable
|
|
|
|
entry main
|
|
|
|
|
|
|
|
main:
|
|
|
|
;; Determine the file size of the input file
|
|
|
|
stat input_filename, file_stat
|
|
|
|
|
|
|
|
;; Open a file descriptor for the input file
|
|
|
|
open input_filename, 0
|
|
|
|
mov [input_fd], rax
|
|
|
|
|
|
|
|
;; Map the input file into memory
|
|
|
|
mmap 0, [file_stat.st_size], PROT_READ, MAP_PRIVATE, [input_fd], 0
|
|
|
|
mov [input], rax
|
|
|
|
|
|
|
|
;; Close the input file
|
|
|
|
close [input_fd]
|
|
|
|
|
|
|
|
;; Setup the loop variables for counting
|
|
|
|
;; rbx starts at the first byte of input, and is incremented to read it all
|
|
|
|
mov rbx, [input]
|
|
|
|
;; rcx tracks the current floor
|
|
|
|
mov rcx, 0
|
|
|
|
;; rdx counts down from the file's size to 0
|
|
|
|
mov rdx, [file_stat.st_size]
|
|
|
|
|
|
|
|
lp:
|
|
|
|
;; Is the current character the "go up" character?
|
|
|
|
cmp byte [rbx], '('
|
|
|
|
;; If so, jump to "up"
|
|
|
|
je up
|
2023-12-20 07:16:28 -05:00
|
|
|
;; 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
|
|
|
|
;; Otherwise it's the EOF probably, skip it
|
|
|
|
jmp other
|
2023-12-19 04:20:18 -05:00
|
|
|
up:
|
|
|
|
;; We should "go up", so increment the current floor
|
|
|
|
inc rcx
|
2023-12-20 07:16:28 -05:00
|
|
|
jmp other
|
|
|
|
down:
|
|
|
|
;; We should "go down", so decrement the current floor
|
|
|
|
dec rcx
|
|
|
|
other:
|
2023-12-19 04:20:18 -05:00
|
|
|
;; 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
|
|
|
|
|
|
|
|
;; Put part 1's answer in rax
|
|
|
|
mov rax, rcx
|
|
|
|
mov rbx, part_1
|
|
|
|
call itoa
|
|
|
|
|
|
|
|
;; Write part 1's verbiage to STDOUT
|
|
|
|
write STDOUT, part_1_verbiage, 8
|
|
|
|
write STDOUT, part_1, 6
|
|
|
|
write STDOUT, newline, 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]
|
|
|
|
;; rcx tracks the current floor
|
|
|
|
mov rcx, 0
|
|
|
|
;; rdx tracks how many steps we've made so far
|
|
|
|
mov rdx, 0
|
|
|
|
lp2:
|
|
|
|
cmp byte [rbx], '('
|
|
|
|
je up2
|
|
|
|
dec rcx
|
|
|
|
jmp moved2
|
|
|
|
up2:
|
|
|
|
inc rcx
|
|
|
|
moved2:
|
|
|
|
inc rdx
|
|
|
|
cmp rcx, 0
|
|
|
|
jl done
|
|
|
|
inc rbx
|
|
|
|
jnz lp2
|
|
|
|
done:
|
|
|
|
|
|
|
|
;; Put part 2's answer in rax
|
|
|
|
mov rax, rdx
|
|
|
|
mov rbx, part_2
|
|
|
|
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
|
|
|
|
|
|
|
|
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
|
|
|
|
file_stat s_stat
|