day 20 part 1
This commit is contained in:
parent
2598b444f8
commit
9f5df0a65c
3
20/Makefile
Normal file
3
20/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
all:
|
||||
nasm -g -felf32 main.s && ld -melf_i386 -g main.o
|
||||
|
58
20/input
Normal file
58
20/input
Normal file
@ -0,0 +1,58 @@
|
||||
%cd -> jx, gh
|
||||
%bk -> jp, cn
|
||||
%px -> xc, hg
|
||||
%tv -> gh, xl
|
||||
&xc -> bm, zq, jf, hg, bd, hn
|
||||
%bd -> px
|
||||
&bh -> mf
|
||||
%dx -> cn, rb
|
||||
%vv -> pp, gh
|
||||
broadcaster -> cx, zq, tv, rh
|
||||
%rb -> cn, qr
|
||||
&jf -> mf
|
||||
%jd -> mm
|
||||
%cx -> xd, cn
|
||||
%zs -> cz
|
||||
%hn -> bm
|
||||
%xr -> bd, xc
|
||||
&mf -> rx
|
||||
%zq -> kg, xc
|
||||
&cn -> sh, jd, cx, tc, xd
|
||||
%cs -> xj
|
||||
%fb -> tc, cn
|
||||
%mm -> cn, bk
|
||||
%sq -> th, hz
|
||||
%sz -> vx
|
||||
%xl -> gh, sz
|
||||
%vm -> gh, vv
|
||||
%jp -> cn
|
||||
%qr -> cn, jd
|
||||
%bq -> xc, zv
|
||||
&sh -> mf
|
||||
%gz -> gs, hz
|
||||
%qc -> qg, xc
|
||||
%hg -> bq
|
||||
%dt -> sq, hz
|
||||
%xj -> fz
|
||||
%qs -> gh
|
||||
%fz -> hz, zs
|
||||
%qg -> xc
|
||||
%pp -> qs, gh
|
||||
%zv -> xc, qc
|
||||
%rh -> hz, mr
|
||||
&gh -> tv, lk, sz, bh, vx
|
||||
%th -> hz
|
||||
&mz -> mf
|
||||
%bm -> xr
|
||||
%lk -> pg
|
||||
%jx -> lk, gh
|
||||
&hz -> xj, cs, zs, rh, mz
|
||||
%tc -> dx
|
||||
%mr -> hz, gz
|
||||
%xd -> jk
|
||||
%pg -> vm, gh
|
||||
%kg -> hn, xc
|
||||
%gs -> cs, hz
|
||||
%vx -> cd
|
||||
%cz -> hz, dt
|
||||
%jk -> cn, fb
|
5
20/input_test
Normal file
5
20/input_test
Normal file
@ -0,0 +1,5 @@
|
||||
broadcaster -> aa, bb, cc
|
||||
%aa -> bb
|
||||
%bb -> cc
|
||||
%cc -> iv
|
||||
&iv -> aa
|
5
20/input_test2
Normal file
5
20/input_test2
Normal file
@ -0,0 +1,5 @@
|
||||
broadcaster -> aa
|
||||
%aa -> iv, cn
|
||||
&iv -> bb
|
||||
%bb -> cn
|
||||
&cn -> ou
|
296
20/main_part1.s
Normal file
296
20/main_part1.s
Normal file
@ -0,0 +1,296 @@
|
||||
%include "utils.s"
|
||||
|
||||
global _start
|
||||
[bits 32]
|
||||
[section .text]
|
||||
|
||||
%define FILENAME "input"
|
||||
;%define FILENAME "input_test"
|
||||
;%define FILENAME "input_test2"
|
||||
|
||||
;%define DBG
|
||||
;%define DBG_ITERS 1000
|
||||
|
||||
_start:
|
||||
|
||||
; read in modules
|
||||
; module data (16 bytes):
|
||||
; 0
|
||||
; bit 1: type (0: flipflop, 1: conj) bit 0: state (0: low, 1: high)
|
||||
; 1 2 3 4 5 6
|
||||
; destination IDX list
|
||||
; 7 8 9 A B C D E F
|
||||
; input states (for conj modules)
|
||||
; bit 0 is remembered state, higher is index
|
||||
|
||||
mov esi, file
|
||||
read_modules:
|
||||
lodsb
|
||||
cmp al, '%'
|
||||
je .flipflop
|
||||
cmp al, '&'
|
||||
je .conjunc
|
||||
; broadcaster
|
||||
%ifdef DBG
|
||||
mov al, 'B'
|
||||
call print_char
|
||||
mov al, 'R'
|
||||
call print_char
|
||||
call space
|
||||
%endif
|
||||
mov ch, 1<<1
|
||||
mov al, 1
|
||||
%ifdef DBG
|
||||
call print_hex_byte
|
||||
call space
|
||||
%endif
|
||||
mov cl, -1 ; broadcaster is special
|
||||
add esi, 14
|
||||
mov edi, modules+16 ; module 1 is broadcast
|
||||
jmp .get_dests
|
||||
.flipflop:
|
||||
mov cl, 0b00 ; low, flipflop
|
||||
jmp .get_idx
|
||||
.conjunc:
|
||||
mov cl, 0b10 ; low, conj
|
||||
jmp .get_idx
|
||||
.get_idx:
|
||||
; get ID
|
||||
lodsb
|
||||
%ifdef DBG
|
||||
call print_char
|
||||
%endif
|
||||
mov bh, al
|
||||
lodsb
|
||||
%ifdef DBG
|
||||
call print_char
|
||||
call space
|
||||
%endif
|
||||
mov bl, al
|
||||
call id_to_idx ; idx in edx
|
||||
mov ch, dl
|
||||
%ifdef DBG
|
||||
mov al, dl
|
||||
call print_hex_byte
|
||||
call space
|
||||
%endif
|
||||
shl ch, 1
|
||||
shl edx, 4 ; * 16
|
||||
lea edi, [modules+edx]
|
||||
add esi, 4
|
||||
.get_dests:
|
||||
; type/state in CL
|
||||
mov [edi], cl
|
||||
inc edi
|
||||
.next_dest:
|
||||
; get dest ID
|
||||
lodsb
|
||||
%ifdef DBG
|
||||
call print_char
|
||||
%endif
|
||||
mov bh, al
|
||||
lodsb
|
||||
%ifdef DBG
|
||||
call print_char
|
||||
call space
|
||||
%endif
|
||||
mov bl, al
|
||||
call id_to_idx
|
||||
mov al, dl
|
||||
%ifdef DBG
|
||||
call print_hex_byte
|
||||
call space
|
||||
%endif
|
||||
stosb
|
||||
; store our idx<<1 in dest inputs
|
||||
shl edx, 4 ; * 16
|
||||
lea edx, [modules+edx+7]
|
||||
.store_input:
|
||||
cmp byte [edx], 0
|
||||
jnz .check_next_input
|
||||
mov byte [edx], ch
|
||||
jmp .input_stored
|
||||
.check_next_input:
|
||||
inc edx
|
||||
jmp .store_input
|
||||
.input_stored:
|
||||
; check if more
|
||||
lodsb
|
||||
cmp al, ','
|
||||
jne .cont ; no more
|
||||
inc esi ; space
|
||||
jmp .next_dest
|
||||
.cont:
|
||||
%ifdef DBG
|
||||
call newline
|
||||
%endif
|
||||
cmp esi, file.over
|
||||
jb read_modules
|
||||
|
||||
main:
|
||||
mov ecx, 1000
|
||||
%ifdef DBG
|
||||
mov ecx, DBG_ITERS
|
||||
%endif
|
||||
.loop:
|
||||
push ecx
|
||||
; start an iteration, broadcaster (1) sends low to everything
|
||||
mov dword [queue_head], 0
|
||||
mov dword [queue_tail], 2
|
||||
mov word [queue], 0b10 ; low to index 1
|
||||
call do_iters
|
||||
pop ecx
|
||||
loop .loop
|
||||
jmp game_over
|
||||
|
||||
do_iters:
|
||||
; get head of queue
|
||||
mov eax, [queue_head]
|
||||
mov ax, [eax+queue]
|
||||
%ifdef DBG
|
||||
call print_hex_word
|
||||
call newline
|
||||
%endif
|
||||
mov cl, ah ; sender
|
||||
movzx eax, al
|
||||
shr eax, 1 ; get pulse
|
||||
setc bl
|
||||
jc .got_high
|
||||
inc dword [low_count]
|
||||
jmp .add_done
|
||||
.got_high:
|
||||
inc dword [high_count]
|
||||
.add_done:
|
||||
; get module
|
||||
mov bh, al ; idx
|
||||
shl eax, 4 ; * 16
|
||||
lea edi, [modules+eax]
|
||||
mov al, [edi]
|
||||
cmp al, -1
|
||||
je .broadcast
|
||||
bt ax, 1
|
||||
jc .conj
|
||||
.flipflop:
|
||||
; if high, do nothing
|
||||
test bl, bl
|
||||
jnz .cont
|
||||
; if low, flip and send result
|
||||
xor al, 1
|
||||
bt ax, 0
|
||||
setc bl
|
||||
mov [edi], al
|
||||
jmp add_cmds
|
||||
.conj:
|
||||
mov dl, 1
|
||||
mov esi, 7
|
||||
.check_mem:
|
||||
mov al, [edi+esi]
|
||||
test al, al
|
||||
jz .mem_done
|
||||
shr al, 1
|
||||
setc dh
|
||||
cmp al, cl
|
||||
jne .mem_cont
|
||||
shr bl, 1
|
||||
setc dh
|
||||
rcl al, 1
|
||||
mov [edi+esi], al
|
||||
.mem_cont:
|
||||
and dl, dh
|
||||
inc esi
|
||||
cmp esi, 0xF
|
||||
jbe .check_mem
|
||||
.mem_done:
|
||||
; send high if not all were high
|
||||
xor dl, 1
|
||||
mov bl, dl
|
||||
jmp add_cmds
|
||||
.broadcast:
|
||||
jmp add_cmds ; just add commands with same pulse
|
||||
.cont:
|
||||
mov eax, [queue_head]
|
||||
add eax, 2
|
||||
and eax, 511
|
||||
mov [queue_head], eax
|
||||
cmp eax, [queue_tail]
|
||||
jne do_iters
|
||||
ret
|
||||
; BH: module IDX, BL: pulse, EDI: *module
|
||||
add_cmds:
|
||||
mov dx, bx ; save
|
||||
mov ecx, 1
|
||||
.loop:
|
||||
mov al, [edi+ecx]
|
||||
test al, al
|
||||
jz .done
|
||||
mov bx, dx
|
||||
shl al, 1
|
||||
or bl, al
|
||||
%ifdef DBG
|
||||
call space
|
||||
mov ax, bx
|
||||
call print_hex_word
|
||||
call newline
|
||||
%endif
|
||||
; add to queue
|
||||
mov eax, [queue_tail]
|
||||
mov [eax+queue], bx
|
||||
add eax, 2
|
||||
and eax, 511
|
||||
mov [queue_tail], eax
|
||||
inc ecx
|
||||
cmp ecx, 6
|
||||
jbe .loop
|
||||
.done:
|
||||
jmp do_iters.cont
|
||||
|
||||
game_over:
|
||||
mov eax, [low_count]
|
||||
call print_dec
|
||||
call space
|
||||
mov eax, [high_count]
|
||||
call print_dec
|
||||
call newline
|
||||
p_string info
|
||||
mul dword [low_count]
|
||||
call print_dec
|
||||
mov al, ':'
|
||||
call print_char
|
||||
mov eax, edx
|
||||
call print_dec
|
||||
call newline
|
||||
jmp exit
|
||||
|
||||
; ID in BX, IDX return in EDX
|
||||
id_to_idx:
|
||||
xor edx, edx
|
||||
.test:
|
||||
cmp [module_idx_to_id+edx*2], bx
|
||||
je .found
|
||||
inc dx
|
||||
cmp dx, [next_module_idx]
|
||||
jb .test
|
||||
; new ID
|
||||
mov [module_idx_to_id+edx*2], bx
|
||||
inc word [next_module_idx]
|
||||
.found:
|
||||
ret
|
||||
|
||||
[section .data]
|
||||
low_count: dd 0
|
||||
high_count: dd 0
|
||||
next_module_idx: dw 2 ; 1 reserved for broadcaster
|
||||
in_idx: dw 0
|
||||
queue_head: dd queue
|
||||
queue_tail: dd queue
|
||||
file: incbin FILENAME
|
||||
.over: db 0 ; EOF
|
||||
|
||||
[section .bss]
|
||||
modules: resb 64*16
|
||||
module_idx_to_id: resw 64
|
||||
queue: resw 64*8
|
||||
|
||||
[section .rodata]
|
||||
info: db `LOW:HIGH\n`
|
||||
.over:
|
336
20/utils.s
Normal file
336
20/utils.s
Normal file
@ -0,0 +1,336 @@
|
||||
[bits 32]
|
||||
[section .text]
|
||||
; call # val val2
|
||||
; int $0x80 eax eax edx -
|
||||
;
|
||||
; arg1 arg2 arg3 arg4 arg5 arg6 arg7
|
||||
; ebx ecx edx esi edi ebp -
|
||||
|
||||
exit:
|
||||
mov eax, 1 ; exit
|
||||
int 0x80
|
||||
|
||||
; filename in EBX
|
||||
; return handle in EBX
|
||||
; read only
|
||||
open_file:
|
||||
push eax
|
||||
push ecx
|
||||
mov eax, 5 ; open
|
||||
xor ecx, ecx ; read only
|
||||
int 0x80
|
||||
mov ebx, eax
|
||||
pop ecx
|
||||
pop eax
|
||||
ret
|
||||
|
||||
; file handle in EBX
|
||||
; buffer in ECX
|
||||
; count of bytes to read in EDX
|
||||
; return bytes actually read in EAX
|
||||
; exits on error
|
||||
read_file:
|
||||
mov eax, 3 ; read
|
||||
int 0x80
|
||||
test eax, eax
|
||||
js .err
|
||||
ret
|
||||
.err:
|
||||
mov eax, 4 ; write
|
||||
mov ebx, 1 ; stdout
|
||||
mov ecx, .err_str
|
||||
mov edx, 21
|
||||
int 0x80
|
||||
jmp exit
|
||||
.err_str: db `Could not read file.\n`
|
||||
|
||||
; string input in ESI
|
||||
; value in EAX
|
||||
; CF set if none, clear if some
|
||||
; ESI set past checked area
|
||||
dec_parse:
|
||||
push ebx
|
||||
push edx
|
||||
push edi
|
||||
xor eax, eax
|
||||
xor edi, edi
|
||||
mov ebx, 10 ; base
|
||||
lodsb
|
||||
sub al, '0'
|
||||
js .no_input
|
||||
cmp al, 9
|
||||
jle .got_char
|
||||
.no_input:
|
||||
stc ; set CF
|
||||
jmp .done
|
||||
.loop:
|
||||
xor eax,eax
|
||||
lodsb
|
||||
sub al, '0'
|
||||
js .dec_done
|
||||
cmp al, 9
|
||||
jg .dec_done
|
||||
.got_char:
|
||||
xchg edi,eax
|
||||
mul ebx
|
||||
add edi,eax
|
||||
jmp .loop
|
||||
.dec_done:
|
||||
clc ; clear CF
|
||||
.done:
|
||||
mov eax,edi
|
||||
pop edi
|
||||
pop edx
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
; string input in ESI
|
||||
; value in EAX
|
||||
; CF set if none, clear if some
|
||||
; ESI set past checked area
|
||||
sign_dec_parse:
|
||||
push ebx
|
||||
push ecx
|
||||
push edx
|
||||
push edi
|
||||
xor eax, eax
|
||||
xor edi, edi
|
||||
xor ecx, ecx ; neg flag
|
||||
mov ebx, 10 ; base
|
||||
cmp byte [esi], '-'
|
||||
jne .no_minus
|
||||
inc esi
|
||||
mov cl, 1
|
||||
.no_minus:
|
||||
lodsb
|
||||
sub al, '0'
|
||||
js .no_input
|
||||
cmp al, 9
|
||||
jle .got_char
|
||||
.no_input:
|
||||
stc ; set CF
|
||||
jmp .done
|
||||
.loop:
|
||||
xor eax,eax
|
||||
lodsb
|
||||
sub al, '0'
|
||||
js .dec_done
|
||||
cmp al, 9
|
||||
jg .dec_done
|
||||
.got_char:
|
||||
xchg edi,eax
|
||||
mul ebx
|
||||
add edi,eax
|
||||
jmp .loop
|
||||
.dec_done:
|
||||
test ecx, ecx
|
||||
jz .not_neg
|
||||
neg edi
|
||||
.not_neg:
|
||||
clc ; clear CF
|
||||
.done:
|
||||
mov eax,edi
|
||||
pop edi
|
||||
pop edx
|
||||
pop ecx
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
; modifies no regs
|
||||
newline:
|
||||
pushad
|
||||
push 10
|
||||
mov eax, 4 ; write
|
||||
mov ebx, 1 ; stdout
|
||||
mov ecx, esp ; string
|
||||
mov edx, 1 ; length
|
||||
int 0x80
|
||||
add esp, 4
|
||||
popad
|
||||
ret
|
||||
; modifies no regs
|
||||
space:
|
||||
pushad
|
||||
push 9
|
||||
mov eax, 4 ; write
|
||||
mov ebx, 1 ; stdout
|
||||
mov ecx, esp ; string
|
||||
mov edx, 1 ; length
|
||||
int 0x80
|
||||
add esp, 4
|
||||
popad
|
||||
ret
|
||||
|
||||
; input in EAX, all regs unmodified
|
||||
print_dec:
|
||||
pushad ; save regs
|
||||
; max 4294967296 is 10 chars
|
||||
; round to nearest 32-bit boundary
|
||||
sub esp, 12
|
||||
; string in ECX, length in EDX
|
||||
lea ecx, [esp+11] ; last possible byte
|
||||
; check for 0
|
||||
test eax, eax
|
||||
jz .zero
|
||||
mov ebx, 10 ; base 10
|
||||
xor esi, esi ; counter
|
||||
.div_shit:
|
||||
xor edx, edx
|
||||
; divide
|
||||
div ebx
|
||||
dec ecx ; next char
|
||||
inc esi
|
||||
; store
|
||||
add dl, '0'
|
||||
mov byte [ecx], dl
|
||||
; check if done
|
||||
test eax, eax
|
||||
jnz .div_shit ; continue
|
||||
mov edx, esi ; counter in edx
|
||||
jmp .write
|
||||
.zero:
|
||||
mov byte [ecx], '0'
|
||||
mov edx, 1 ; length
|
||||
.write:
|
||||
mov eax, 4 ; write
|
||||
mov ebx, 1 ; stdout
|
||||
int 0x80
|
||||
add esp, 12 ; restore stack
|
||||
popad ; restore regs
|
||||
ret
|
||||
|
||||
; input in EAX, all regs unmodified
|
||||
print_sign_dec:
|
||||
pushad ; save regs
|
||||
; range -2147483648 to 2147483647 is 11 chars
|
||||
; round to nearest 32-bit boundary
|
||||
sub esp, 12
|
||||
; string in ECX, length in EDX
|
||||
lea ecx, [esp+11] ; last possible byte
|
||||
; check for 0, negative
|
||||
xor ebp, ebp
|
||||
test eax, eax
|
||||
jz .zero
|
||||
jns .positive
|
||||
neg eax
|
||||
mov ebp, 1
|
||||
.positive:
|
||||
mov ebx, 10 ; base 10
|
||||
xor esi, esi ; counter
|
||||
.div_shit:
|
||||
xor edx, edx
|
||||
; divide
|
||||
div ebx
|
||||
dec ecx ; next char
|
||||
inc esi
|
||||
; store
|
||||
add dl, '0'
|
||||
mov byte [ecx], dl
|
||||
; check if done
|
||||
test eax, eax
|
||||
jnz .div_shit ; continue
|
||||
mov edx, esi ; counter in edx
|
||||
jmp .write
|
||||
.zero:
|
||||
mov byte [ecx], '0'
|
||||
mov edx, 1 ; length
|
||||
.write:
|
||||
test ebp, ebp
|
||||
jz .no_minus
|
||||
dec ecx
|
||||
inc edx
|
||||
mov byte [ecx], '-'
|
||||
.no_minus:
|
||||
mov eax, 4 ; write
|
||||
mov ebx, 1 ; stdout
|
||||
int 0x80
|
||||
add esp, 12 ; restore stack
|
||||
popad ; restore regs
|
||||
ret
|
||||
|
||||
; input in EAX, all regs unmodified
|
||||
print_hex:
|
||||
pushad
|
||||
mov ebx, eax
|
||||
shr eax, 16
|
||||
call print_hex_word
|
||||
mov eax, ebx
|
||||
call print_hex_word
|
||||
popad
|
||||
ret
|
||||
|
||||
; input in AX, all regs unmodified
|
||||
print_hex_word:
|
||||
pushad
|
||||
mov bx, ax
|
||||
mov al, ah
|
||||
call print_hex_byte
|
||||
mov ax, bx
|
||||
call print_hex_byte
|
||||
popad
|
||||
ret
|
||||
|
||||
; input in AL, all regs unmodified
|
||||
print_hex_byte:
|
||||
pushad
|
||||
push '0000'
|
||||
mov bl, al
|
||||
shr bl, 4
|
||||
mov dx, '0'
|
||||
mov cx, 'A' - 10
|
||||
cmp bl, 9
|
||||
cmovg dx, cx
|
||||
add bl, dl
|
||||
mov [esp], bl
|
||||
mov bl, al
|
||||
and bl, 0xF
|
||||
mov dx, '0'
|
||||
mov cx, 'A' - 10
|
||||
cmp bl, 9
|
||||
cmovg dx, cx
|
||||
add bl, dl
|
||||
mov [esp+1], bl
|
||||
mov eax, 4 ; write
|
||||
mov ebx, 1 ; stdout
|
||||
mov edx, 2 ; length
|
||||
mov ecx, esp ; string
|
||||
int 0x80
|
||||
add esp, 4
|
||||
popad
|
||||
ret
|
||||
|
||||
; input in ESI, len in ECX, all regs unmodified
|
||||
print_string:
|
||||
pushad ; save regs
|
||||
mov eax, 4 ; write
|
||||
mov ebx, 1 ; stdout
|
||||
mov edx, ecx ; length
|
||||
mov ecx, esi ; string
|
||||
int 0x80
|
||||
popad ; restore regs
|
||||
ret
|
||||
|
||||
; input in AL, all regs unmodified
|
||||
print_char:
|
||||
pushad ; save regs
|
||||
push eax
|
||||
mov eax, 4 ; write
|
||||
mov ebx, 1 ; stdout
|
||||
mov edx, 1 ; length
|
||||
mov ecx, esp ; string
|
||||
int 0x80
|
||||
add esp, 4
|
||||
popad ; restore regs
|
||||
ret
|
||||
|
||||
; --- MACROS ---
|
||||
%define len(x) x %+ .over - x
|
||||
%macro p_string 1
|
||||
push esi
|
||||
push ecx
|
||||
mov esi, %1
|
||||
mov ecx, len(%1)
|
||||
call print_string
|
||||
pop ecx
|
||||
pop esi
|
||||
%endmacro
|
Loading…
Reference in New Issue
Block a user