adventofcode2023/16/main_part1.s

430 lines
10 KiB
ArmAsm
Raw Normal View History

2023-12-16 18:41:45 -06:00
%include "utils.s"
global _start
[bits 32]
[section .text]
%define LINE_LEN 111 ; real
%define FILENAME "input"
;%define LINE_LEN 11 ; test
;%define FILENAME "input_test"
;%define ITER_PRINT
_start:
; bit 3 bit 2 bit 1 bit 0
; up down left right
; top left starts going right
mov byte [energized], 1
next_iteration:
%ifdef ITER_PRINT
; debug printing
dbg:
xor esi, esi ; top line
.for_lines:
xor ecx, ecx ; leftmost char
.for_chars:
movzx eax, byte [esi+ecx+energized]
movzx ebx, byte [esi+ecx+file]
pushad
test al, al
jz .prnt_char
p_string ansi_color_highbold_green
cmp bl, '.'
jne .prnt_char
popcnt ecx, eax
cmp ecx, 1
jg .prnt_num
cmp al, 1
je .prnt_right
cmp al, 2
je .prnt_left
cmp al, 4
je .prnt_down
.prnt_up: mov al, '^'
call print_char
jmp .prnt_done
.prnt_down: mov al, 'v'
call print_char
jmp .prnt_done
.prnt_left: mov al, '<'
call print_char
jmp .prnt_done
.prnt_right: mov al, '>'
call print_char
jmp .prnt_done
.prnt_num:
mov eax, ecx
call print_dec
jmp .prnt_done
.prnt_char:
mov al, [esi+ecx+file]
call print_char
.prnt_done:
p_string ansi_color_reset
popad
.for_chars_cont:
inc ecx
cmp ecx, LINE_LEN-2
jbe .for_chars
.for_chars_done:
.for_lines_cont:
call newline
add esi, LINE_LEN
cmp esi, len(file)
jb .for_lines
call newline
; debug printing end
%endif
xor esi, esi ; top line
for_lines:
xor ecx, ecx ; leftmost char
for_chars:
movzx eax, byte [esi+ecx+energized]
movzx ebx, byte [esi+ecx+file]
; skip if not energized
test eax, eax
jz for_chars_cont
; select thing
cmp bl, '.'
je empty
cmp bl, '/'
je mirror_one
cmp bl, '\'
je mirror_two
cmp bl, '-'
je horz_split
cmp bl, '|'
je vert_split
p_string what_the_fuck
jmp exit
empty: ; .
; propagate
; test right
bt eax, 0
jnc .t_left
or byte [esi+ecx+energized+1], 1<<0
.t_left:
bt eax, 1
jnc .t_down
or byte [esi+ecx+energized-1], 1<<1
.t_down:
bt eax, 2
jnc .t_up
or byte [esi+ecx+energized+LINE_LEN], 1<<2
.t_up:
bt eax, 3
jnc .done
or byte [esi+ecx+energized-LINE_LEN], 1<<3
.done:
jmp for_chars_cont
mirror_one: ; /
; our energized is what hits us
; test right >/
bt eax, 0
jnc .t_left
or byte [esi+ecx+energized-LINE_LEN], 1<<3 ; up char going up
.t_left: ; /<
bt eax, 1
jnc .t_down
or byte [esi+ecx+energized+LINE_LEN], 1<<2 ; down going down
.t_down:
bt eax, 2 ; v
jnc .t_up ; /
or byte [esi+ecx+energized-1], 1<<1 ; left going left
.t_up:
bt eax, 3 ; /
jnc .done ; ^
or byte [esi+ecx+energized+1], 1<<0 ; right going right
.done:
jmp for_chars_cont
mirror_two: ; \
; our energized is what hits us
; test right >\
bt eax, 0
jnc .t_left
or byte [esi+ecx+energized+LINE_LEN], 1<<2 ; down char going down
.t_left: ; \<
bt eax, 1
jnc .t_down
or byte [esi+ecx+energized-LINE_LEN], 1<<3 ; up going up
.t_down:
bt eax, 2 ; v
jnc .t_up ; \
or byte [esi+ecx+energized+1], 1<<0 ; right going right
.t_up:
bt eax, 3 ; \
jnc .done ; ^
or byte [esi+ecx+energized-1], 1<<1 ; left going left
.done:
jmp for_chars_cont
horz_split: ; -
; our energized is what hits us
; right and left propagate
; test right
bt eax, 0
jnc .t_left
or byte [esi+ecx+energized+1], 1<<0
.t_left:
bt eax, 1
jnc .t_vert
or byte [esi+ecx+energized-1], 1<<1
; down and up go both left and right
.t_vert:
and eax, 1<<2 | 1<<3
jz .done
or byte [esi+ecx+energized+1], 1<<0 ; right going right
or byte [esi+ecx+energized-1], 1<<1 ; left going left
.done:
jmp for_chars_cont
vert_split: ; |
; our energized is what hits us
; down and up propagate
; test down
bt eax, 2
jnc .t_up
or byte [esi+ecx+energized+LINE_LEN], 1<<2
.t_up:
bt eax, 3
jnc .t_vert
or byte [esi+ecx+energized-LINE_LEN], 1<<3
; left and right go both down and up
.t_vert:
and eax, 1<<0 | 1<<1
jz .done
or byte [esi+ecx+energized+LINE_LEN], 1<<2 ; down going down
or byte [esi+ecx+energized-LINE_LEN], 1<<3 ; up going up
.done:
for_chars_cont:
inc ecx
cmp ecx, LINE_LEN-2
jbe for_chars
for_chars_done:
for_lines_cont:
add esi, LINE_LEN
cmp esi, len(file)
jb for_lines
xor ebp, ebp ; energized count
sub esi, LINE_LEN ; last line
; now go through backward
bkwd_for_lines:
mov ecx, LINE_LEN-2 ; rightmost char
bkwd_for_chars:
movzx eax, byte [esi+ecx+energized]
movzx ebx, byte [esi+ecx+file]
; skip if not energized
test eax, eax
jz bkwd_for_chars_cont
inc ebp ; energized count
; select thing
cmp bl, '.'
je bkwd_empty
cmp bl, '/'
je bkwd_mirror_one
cmp bl, '\'
je bkwd_mirror_two
cmp bl, '-'
je bkwd_horz_split
cmp bl, '|'
je bkwd_vert_split
p_string what_the_fuck
jmp exit
bkwd_empty: ; .
; propagate
; test right
bt eax, 0
jnc .t_left
or byte [esi+ecx+energized+1], 1<<0
.t_left:
bt eax, 1
jnc .t_down
or byte [esi+ecx+energized-1], 1<<1
.t_down:
bt eax, 2
jnc .t_up
or byte [esi+ecx+energized+LINE_LEN], 1<<2
.t_up:
bt eax, 3
jnc .done
or byte [esi+ecx+energized-LINE_LEN], 1<<3
.done:
jmp bkwd_for_chars_cont
bkwd_mirror_one: ; /
; our energized is what hits us
; test right >/
bt eax, 0
jnc .t_left
or byte [esi+ecx+energized-LINE_LEN], 1<<3 ; up char going up
.t_left: ; /<
bt eax, 1
jnc .t_down
or byte [esi+ecx+energized+LINE_LEN], 1<<2 ; down going down
.t_down:
bt eax, 2 ; v
jnc .t_up ; /
or byte [esi+ecx+energized-1], 1<<1 ; left going left
.t_up:
bt eax, 3 ; /
jnc .done ; ^
or byte [esi+ecx+energized+1], 1<<0 ; right going right
.done:
jmp bkwd_for_chars_cont
bkwd_mirror_two: ; \
; our energized is what hits us
; test right >\
bt eax, 0
jnc .t_left
or byte [esi+ecx+energized+LINE_LEN], 1<<2 ; down char going down
.t_left: ; \<
bt eax, 1
jnc .t_down
or byte [esi+ecx+energized-LINE_LEN], 1<<3 ; up going up
.t_down:
bt eax, 2 ; v
jnc .t_up ; \
or byte [esi+ecx+energized+1], 1<<0 ; right going right
.t_up:
bt eax, 3 ; \
jnc .done ; ^
or byte [esi+ecx+energized-1], 1<<1 ; left going left
.done:
jmp bkwd_for_chars_cont
bkwd_horz_split: ; -
; our energized is what hits us
; right and left propagate
; test right
bt eax, 0
jnc .t_left
or byte [esi+ecx+energized+1], 1<<0
.t_left:
bt eax, 1
jnc .t_vert
or byte [esi+ecx+energized-1], 1<<1
; down and up go both left and right
.t_vert:
and eax, 1<<2 | 1<<3
jz .done
or byte [esi+ecx+energized+1], 1<<0 ; right going right
or byte [esi+ecx+energized-1], 1<<1 ; left going left
.done:
jmp bkwd_for_chars_cont
bkwd_vert_split: ; |
; our energized is what hits us
; down and up propagate
; test down
bt eax, 2
jnc .t_up
or byte [esi+ecx+energized+LINE_LEN], 1<<2
.t_up:
bt eax, 3
jnc .t_vert
or byte [esi+ecx+energized-LINE_LEN], 1<<3
; left and right go both down and up
.t_vert:
and eax, 1<<0 | 1<<1
jz .done
or byte [esi+ecx+energized+LINE_LEN], 1<<2 ; down going down
or byte [esi+ecx+energized-LINE_LEN], 1<<3 ; up going up
.done:
bkwd_for_chars_cont:
dec ecx
jnz bkwd_for_chars
bkwd_for_chars_done:
bkwd_for_lines_cont:
sub esi, LINE_LEN
jns bkwd_for_lines
cmp ebp, [last_energized]
mov [last_energized], ebp
jne next_iteration
; print final
xor ebp, ebp
print_final:
xor esi, esi ; top line
.for_lines:
xor ecx, ecx ; leftmost char
.for_chars:
movzx eax, byte [esi+ecx+energized]
movzx ebx, byte [esi+ecx+file]
test al, al
jz .prnt_char
inc ebp
p_string ansi_color_highbold_green
cmp bl, '.'
jne .prnt_char
popcnt edx, eax
cmp edx, 1
jg .prnt_num
cmp al, 1
je .prnt_right
cmp al, 2
je .prnt_left
cmp al, 4
je .prnt_down
.prnt_up: mov al, '^'
call print_char
jmp .prnt_done
.prnt_down: mov al, 'v'
call print_char
jmp .prnt_done
.prnt_left: mov al, '<'
call print_char
jmp .prnt_done
.prnt_right: mov al, '>'
call print_char
jmp .prnt_done
.prnt_num:
mov eax, edx
call print_dec
jmp .prnt_done
.prnt_char:
mov al, [esi+ecx+file]
call print_char
.prnt_done:
p_string ansi_color_reset
.for_chars_cont:
inc ecx
cmp ecx, LINE_LEN-2
jbe .for_chars
.for_chars_done:
.for_lines_cont:
call newline
add esi, LINE_LEN
cmp esi, len(file)
jb .for_lines
call newline
game_over:
mov eax, ebp
call print_dec
call newline
jmp exit
[section .data]
final_value: dd 0
last_energized: dd 0
file: incbin FILENAME
.over:
[section .bss]
padding: resb 128
energized: resb 128*128
[section .rodata]
what_the_fuck: db "Something is terribly wrong in this world."
.over:
ansi_color_reset: db `\e[0m`
.over:
ansi_color_green: db `\e[0;32m`
.over:
ansi_color_highbold_green: db `\e[1;92m`
.over: