hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/aoc-2025/day6.asm
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-05 19:32:30 +0200
committerhachem <im@hachem.wtf>2026-09-05 19:32:30 +0200
commit3c276e5263f7994b546b65716f0911d9c828c198 (patch)
treec1cccc2c58cb8b42b96c6c8c17ba1df7f24180cb /aoc-2025/day6.asm
parent9c9e26a5cab8f12f949be3ab6fea824f3d64a6ee (diff)
refactor: add day-4-8
Diffstat (limited to 'aoc-2025/day6.asm')
-rw-r--r--aoc-2025/day6.asm419
1 files changed, 419 insertions, 0 deletions
diff --git a/aoc-2025/day6.asm b/aoc-2025/day6.asm
new file mode 100644
index 0000000..774ca4c
--- /dev/null
+++ b/aoc-2025/day6.asm
@@ -0,0 +1,419 @@
+; Advent of Code 2025 - Day 6
+
+bits 64
+default rel
+
+global _start
+
+%define SYS_EXIT 60
+%define SYS_READ 0
+%define SYS_WRITE 1
+%define SYS_OPEN 2
+%define SYS_CLOSE 3
+
+%define O_RDONLY 0
+%define STDOUT 1
+
+%define RAW_SIZE 1048576
+%define MAX_W 8192
+%define MAX_H 64
+%define GRID_SIZE (MAX_W * MAX_H)
+
+section .data
+ input_path db "input/day6.txt", 0
+
+ newline db 10
+
+ label1 db "Part 1: ", 0
+ label2 db "Part 2: ", 0
+
+section .bss
+ raw resb RAW_SIZE
+ grid resb GRID_SIZE ; height x width, space-filled
+
+ raw_len resq 1
+ width resq 1
+ height resq 1
+
+ blk_c0 resq 1 ; current block: columns [blk_c0, blk_c1)
+ blk_c1 resq 1
+ op resq 1 ; 0 = add, 1 = mul, -1 = none
+
+ part1 resq 1
+ part2 resq 1
+
+ number_buffer resb 32
+
+section .text
+
+_start:
+ mov rax, SYS_OPEN
+ mov rdi, input_path
+ mov rsi, O_RDONLY
+ xor rdx, rdx
+ syscall
+ mov r12, rax
+
+ xor r13, r13
+read_loop:
+ mov rax, SYS_READ
+ mov rdi, r12
+ lea rsi, [raw + r13]
+ mov rdx, RAW_SIZE
+ sub rdx, r13
+ syscall
+ cmp rax, 0
+ jle read_done
+ add r13, rax
+ jmp read_loop
+read_done:
+ mov [raw_len], r13
+
+ mov rax, SYS_CLOSE
+ mov rdi, r12
+ syscall
+
+ ; width = length of the first line
+ xor rcx, rcx
+width_scan:
+ cmp rcx, [raw_len]
+ jge width_done
+ mov al, [raw + rcx]
+ cmp al, 10
+ je width_done
+ cmp al, 13
+ je width_done
+ inc rcx
+ jmp width_scan
+width_done:
+ mov [width], rcx
+
+ ; height = number of lines (newlines, plus one if the last line has no newline)
+ xor rcx, rcx
+ xor r8, r8
+height_scan:
+ cmp rcx, [raw_len]
+ jge height_tail
+ mov al, [raw + rcx]
+ cmp al, 10
+ jne height_next
+ inc r8
+height_next:
+ inc rcx
+ jmp height_scan
+height_tail:
+ mov rax, [raw_len]
+ test rax, rax
+ jz height_store
+ mov dl, [raw + rax - 1]
+ cmp dl, 10
+ je height_store
+ inc r8
+height_store:
+ mov [height], r8
+
+ ; space-fill the grid, then copy the raw bytes into it
+ mov rax, [height]
+ imul rax, [width]
+ mov rcx, rax
+ lea rdi, [grid]
+ mov al, ' '
+ rep stosb
+
+ xor r8, r8 ; raw index
+ xor r9, r9 ; row
+ xor r10, r10 ; col
+fill_loop:
+ cmp r8, [raw_len]
+ jge fill_done
+ mov al, [raw + r8]
+ inc r8
+ cmp al, 10
+ je fill_newline
+ cmp al, 13
+ je fill_loop
+ cmp r10, [width]
+ jge fill_loop
+ mov rdx, r9
+ imul rdx, [width]
+ add rdx, r10
+ mov [grid + rdx], al
+ inc r10
+ jmp fill_loop
+fill_newline:
+ inc r9
+ xor r10, r10
+ jmp fill_loop
+fill_done:
+
+ ; walk the columns, carving out blocks between all-space separators
+ xor r15, r15 ; column cursor
+block_scan:
+ cmp r15, [width]
+ jge blocks_done
+ mov rdi, r15
+ call col_is_sep
+ test rax, rax
+ jnz block_sep
+ mov [blk_c0], r15
+block_extend:
+ cmp r15, [width]
+ jge block_end
+ mov rdi, r15
+ call col_is_sep
+ test rax, rax
+ jnz block_end
+ inc r15
+ jmp block_extend
+block_end:
+ mov [blk_c1], r15
+ call process_block
+ jmp block_scan
+block_sep:
+ inc r15
+ jmp block_scan
+blocks_done:
+
+print_results:
+ mov rcx, label1
+ call print_string
+ mov rax, [part1]
+ call print_int64
+ call print_newline
+
+ mov rcx, label2
+ call print_string
+ mov rax, [part2]
+ call print_int64
+ call print_newline
+
+ mov rax, SYS_EXIT
+ xor rdi, rdi
+ syscall
+
+; col_is_sep: is every row of column RDI a space?
+; Output: RAX = 1 if the column is a separator, else 0
+; Clobbers: RAX, RDX, R8
+col_is_sep:
+ xor r8, r8
+.loop:
+ cmp r8, [height]
+ jge .sep
+ mov rax, r8
+ imul rax, [width]
+ add rax, rdi
+ movzx edx, byte [grid + rax]
+ cmp dl, ' '
+ jne .not
+ inc r8
+ jmp .loop
+.sep:
+ mov rax, 1
+ ret
+.not:
+ xor rax, rax
+ ret
+
+; process_block: fold the block [blk_c0, blk_c1) for both parts.
+; Part 1 reads each row as a number; part 2 reads each column as a number.
+; The bottom row supplies the operator. Clobbers RAX, RCX, RDX, R8-R14.
+process_block:
+ ; find the operator on the bottom row within the block
+ mov rax, [height]
+ dec rax
+ imul rax, [width]
+ mov r11, rax ; offset of the operator row
+ mov qword [op], -1
+ mov rcx, [blk_c0]
+.find_op:
+ cmp rcx, [blk_c1]
+ jge .op_done
+ mov rdx, r11
+ add rdx, rcx
+ mov al, [grid + rdx]
+ cmp al, '+'
+ je .set_add
+ cmp al, '*'
+ je .set_mul
+ inc rcx
+ jmp .find_op
+.set_add:
+ mov qword [op], 0
+ jmp .op_done
+.set_mul:
+ mov qword [op], 1
+.op_done:
+ cmp qword [op], 0
+ jl .ret ; no operator -> not a real problem
+
+ ; part 1: one number per row
+ mov r12, [op]
+ xor r13, r13 ; accumulator
+ test r12, r12
+ jz .p1_acc
+ mov r13, 1
+.p1_acc:
+ xor r14, r14 ; count of numbers folded
+ xor r10, r10 ; row
+.p1_rows:
+ mov rax, [height]
+ dec rax
+ cmp r10, rax
+ jge .p1_done
+ mov rax, r10
+ imul rax, [width]
+ mov r11, rax ; row offset
+ xor r8, r8 ; number
+ xor r9, r9 ; saw a digit?
+ mov rcx, [blk_c0]
+.p1_cols:
+ cmp rcx, [blk_c1]
+ jge .p1_fold
+ mov rdx, r11
+ add rdx, rcx
+ movzx eax, byte [grid + rdx]
+ cmp al, '0'
+ jl .p1_col_next
+ cmp al, '9'
+ jg .p1_col_next
+ sub al, '0'
+ movzx rax, al
+ imul r8, r8, 10
+ add r8, rax
+ mov r9, 1
+.p1_col_next:
+ inc rcx
+ jmp .p1_cols
+.p1_fold:
+ test r9, r9
+ jz .p1_row_next
+ test r12, r12
+ jnz .p1_mul
+ add r13, r8
+ jmp .p1_counted
+.p1_mul:
+ imul r13, r8
+.p1_counted:
+ inc r14
+.p1_row_next:
+ inc r10
+ jmp .p1_rows
+.p1_done:
+ test r14, r14
+ jz .p2
+ add [part1], r13
+
+ ; part 2: one number per column
+.p2:
+ mov r12, [op]
+ xor r13, r13
+ test r12, r12
+ jz .p2_acc
+ mov r13, 1
+.p2_acc:
+ xor r14, r14
+ mov rcx, [blk_c0] ; column
+.p2_cols:
+ cmp rcx, [blk_c1]
+ jge .p2_done
+ xor r8, r8 ; number
+ xor r9, r9 ; saw a digit?
+ xor r10, r10 ; row
+.p2_rows:
+ mov rax, [height]
+ dec rax
+ cmp r10, rax
+ jge .p2_fold
+ mov rax, r10
+ imul rax, [width]
+ add rax, rcx
+ movzx edx, byte [grid + rax]
+ cmp dl, '0'
+ jl .p2_row_next
+ cmp dl, '9'
+ jg .p2_row_next
+ sub dl, '0'
+ movzx rdx, dl
+ imul r8, r8, 10
+ add r8, rdx
+ mov r9, 1
+.p2_row_next:
+ inc r10
+ jmp .p2_rows
+.p2_fold:
+ test r9, r9
+ jz .p2_col_next
+ test r12, r12
+ jnz .p2_mul
+ add r13, r8
+ jmp .p2_counted
+.p2_mul:
+ imul r13, r8
+.p2_counted:
+ inc r14
+.p2_col_next:
+ inc rcx
+ jmp .p2_cols
+.p2_done:
+ test r14, r14
+ jz .ret
+ add [part2], r13
+.ret:
+ ret
+
+print_newline:
+ mov rax, SYS_WRITE
+ mov rdi, STDOUT
+ mov rsi, newline
+ mov rdx, 1
+ syscall
+ ret
+
+print_int64:
+ mov rdi, number_buffer+31
+ mov byte [rdi], 0
+ dec rdi
+
+ cmp rax, 0
+ jne .conv
+
+ mov byte [rdi], '0'
+ jmp .done
+.conv:
+ mov rbx, 10
+.next:
+ xor rdx, rdx
+ div rbx
+ add dl, '0'
+ mov [rdi], dl
+ dec rdi
+ test rax, rax
+ jnz .next
+
+ inc rdi
+.done:
+ mov rax, SYS_WRITE
+ mov rsi, rdi
+ mov rdi, STDOUT
+ mov rdx, number_buffer+31
+ sub rdx, rsi
+ syscall
+ ret
+
+print_string:
+ push rcx
+ push rdx
+ mov rdx, 0
+.length:
+ cmp byte [rcx+rdx], 0
+ je .submit
+ inc rdx
+ jmp .length
+.submit:
+ mov rax, SYS_WRITE
+ mov rdi, STDOUT
+ mov rsi, rcx
+ syscall
+ pop rdx
+ pop rcx
+ ret