diff options
| author | hachem <im@hachem.wtf> | 2025-12-05 17:32:02 +0100 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2025-12-05 17:32:02 +0100 |
| commit | 339ae4a5de550dba1e54ae17340545970cae3082 (patch) | |
| tree | 13a356e5a0ebdadeb05ae4bd660a461e0fae46ed /src/Day1.asm | |
| parent | e92da05ceebffa2ef8c906c7f49e13ca5bc90a32 (diff) | |
[complete]: day 1
Diffstat (limited to 'src/Day1.asm')
| -rw-r--r-- | src/Day1.asm | 645 |
1 files changed, 363 insertions, 282 deletions
diff --git a/src/Day1.asm b/src/Day1.asm index ba5eb57..a749c6d 100644 --- a/src/Day1.asm +++ b/src/Day1.asm @@ -1,282 +1,363 @@ -; Advent of Code 2025 - Day 1.1 - -; #include <stddef.h> -; #include <stdio.h> -; #include <stdlib.h> -; #include <stdint.h> -; -; int main(void) -; { -; FILE* input = fopen("input/day1.txt", "r"); -; -; int32_t angle = 50; -; int32_t password = 0; -; -; char line[256]; -; while (fgets(line, sizeof(line), input)) -; { -; int32_t direction = (line[0] == 'L') ? -1 : 1; -; int32_t steps = atoi(line + 1); -; -; angle += direction * steps; -; angle = (angle % 100 + 100) % 100; -; -; if (angle == 0) -; password++; -; } -; -; fclose(input); -; printf("Password: %d\n", password); -; } - -global _start - -%define SYS_EXIT 1 -%define SYS_READ 3 -%define SYS_WRITE 4 -%define SYS_OPEN 5 -%define SYS_CLOSE 6 - -%define O_RDONLY 0 -%define STDOUT 1 - -section .data - inputPath db "input/day1.txt", 0 - newline db 10 ; '\n' - - angle dd 50 ; initial angle - password dd 0 ; result counter - -section .bss - buffer resb 4096 ; chunk read buffer - lineBuffer resb 256 ; one line max 255 chars + NUL - numberBuffer resb 16 ; for PrintInt - lineLen resd 1 ; current line length - -section .text - -_start: - ; open file - mov eax, SYS_OPEN - mov ebx, inputPath - mov ecx, O_RDONLY - int 0x80 - - mov esi, eax ; fd in ESI - mov dword [lineLen], 0 ; no chars in current line yet - -ReadLoop: - ; read up to 4096 bytes - mov eax, SYS_READ - mov ebx, esi - mov ecx, buffer - mov edx, 4096 - int 0x80 - - cmp eax, 0 - jle EOF ; 0 or negative = EOF or error - - mov edi, buffer ; scan pointer - mov ecx, eax ; bytes remaining in this chunk - -ScanChunk: - cmp ecx, 0 - je ReadLoop ; chunk done, read next - - mov al, [edi] - - ; windows can be a fucking bitch - ; handle CR (13) -> just skip - cmp al, 13 - je SkipCR - - ; handle LF (10) -> end of line - cmp al, 10 - je EndOfLine - - ; normal character: append to lineBuffer if space left - mov edx, [lineLen] - cmp edx, 255 ; leave 1 byte for NUL - jae SkipStore ; ignore extra chars if too long - mov [lineBuffer + edx], al - inc edx - mov [lineLen], edx - -SkipStore: - inc edi - dec ecx - jmp ScanChunk - -SkipCR: - inc edi - dec ecx - jmp ScanChunk - -EndOfLine: - ; terminate current line - mov edx, [lineLen] - mov byte [lineBuffer + edx], 0 - - ; if line isn't empty, process it - cmp edx, 0 - je LineDone - - push esi - mov esi, lineBuffer - call HandleLine - pop esi - -LineDone: - mov dword [lineLen], 0 ; reset line length - inc edi - dec ecx - jmp ScanChunk - -; process last line if not newline-terminated, then print result -EOF: - ; if there is a partial line at EOF, process it - mov edx, [lineLen] - cmp edx, 0 - jle FinishEOF - mov byte [lineBuffer + edx], 0 - - push esi - mov esi, lineBuffer - call HandleLine - pop esi - -FinishEOF: - mov eax, [password] - call PrintInt - - ; newline after result - mov eax, SYS_WRITE - mov ebx, STDOUT - mov ecx, newline - mov edx, 1 - int 0x80 - - ; close file and exit - mov eax, SYS_CLOSE - mov ebx, esi - int 0x80 - - mov eax, SYS_EXIT - xor ebx, ebx - int 0x80 - - -; Handle one line: ESI -> "L123" or "R45" -HandleLine: - mov al, [esi] - cmp al, 'L' - je .left - mov ebx, 1 ; direction = +1 for 'R' or anything else - jmp .after -.left: - mov ebx, -1 ; direction = -1 for 'L' -.after: - inc esi ; skip 'L' or 'R' - call ParseInt ; EAX = steps - - imul eax, ebx ; EAX = dir * steps - - mov edx, [angle] - add edx, eax ; update angle (can be out of range, signed) - - ; normalize edx into [0, 100[ using repeated +/-100 (no division) -NormLoop: - cmp edx, 0 - jl NormAdd - cmp edx, 100 - jl NormDone - sub edx, 100 - jmp NormLoop - -NormAdd: - add edx, 100 - jmp NormLoop - -NormDone: - mov [angle], edx - - cmp edx, 0 - jne .done - mov eax, [password] - inc eax - mov [password], eax -.done: - ret - -; ParseInt: - parse decimal number at [ESI] into EAX -; - stops at first non-digit -ParseInt: - xor eax, eax ; result = 0 - -.parseLoop: - mov dl, [esi] - cmp dl, '0' - jl .done - cmp dl, '9' - jg .done - - sub dl, '0' ; digit value 0..9 - movzx edx, dl - - imul eax, eax, 10 ; result *= 10 - add eax, edx ; result += digit - - inc esi - jmp .parseLoop - -.done: - ret - -; PrintInt: print unsigned integer in EAX to stdout -PrintInt: - mov edi, numberBuffer+15 ; write digits from the end - mov byte [edi], 0 ; terminator - dec edi - - cmp eax, 0 - jne .convert - mov byte [edi], '0' - jmp .finish - -.convert: - ; we will repeatedly compute: - ; q = eax / 10 - ; r = eax % 10 - ; using only subtraction -.nextDigit: - mov edx, eax ; tmp = current value - mov ecx, 0 ; q = 0 - - cmp edx, 10 - jb .lastDigit ; if < 10, quotient = 0, remainder = edx -.subLoop: - sub edx, 10 - inc ecx ; q++ - cmp edx, 10 - jae .subLoop ; while tmp >= 10 -.lastDigit: - ; now: - ; ecx = quotient - ; edx = remainder (0..9) - add dl, '0' - mov [edi], dl ; store digit - dec edi - - mov eax, ecx ; eax = quotient - test eax, eax - jnz .nextDigit ; more digits to extract? - - inc edi ; move to first digit -.finish: - mov eax, SYS_WRITE - mov ebx, STDOUT - mov ecx, edi - mov edx, numberBuffer+15 - sub edx, edi ; length - int 0x80 - ret +; Advent of Code 2025 - Day 1
+
+;
+; #include <stdio.h>
+; #include <stdlib.h>
+; #include <stddef.h>
+; #include <stdint.h>
+;
+; int main(void)
+; {
+; FILE* input = fopen("input/day1.txt", "r");
+;
+; int32_t angle1 = 50;
+; int32_t angle2 = 50;
+;
+; int32_t password1 = 0;
+; int32_t password2 = 0;
+;
+; char line[256];
+; while (fgets(line, sizeof(line), input))
+; {
+; int32_t direction = (line[0] == 'L') ? -1 : 1;
+; int32_t steps = atoi(line + 1);
+;
+; // part 1
+; angle1 += direction * steps;
+; angle1 %= 100;
+; if (angle1 < 0)
+; angle1 += 100;
+; if (angle1 == 0)
+; password1++;
+;
+; // part 2
+; for (int i = 0; i < steps; i++)
+; {
+; angle2 += direction;
+; if (angle2 == 100)
+; angle2 = 0;
+; else if (angle2 == -1)
+; angle2 = 99;
+; if (angle2 == 0)
+; password2++;
+; }
+; }
+;
+; fclose(input);
+;
+; printf("Password 1: %d\n", password1);
+; printf("Password 2: %d\n", password2);
+; }
+;
+
+global _start
+
+%define SYS_EXIT 1
+%define SYS_READ 3
+%define SYS_WRITE 4
+%define SYS_OPEN 5
+%define SYS_CLOSE 6
+
+%define O_RDONLY 0
+%define STDOUT 1
+
+section .data
+ inputPath db "input/day1.txt", 0
+ newline db 10
+
+ label1 db "Password 1: ", 0
+ label2 db "Password 2: ", 0
+
+ angle1 dd 50
+ angle2 dd 50
+
+ password1 dd 0
+ password2 dd 0
+
+section .bss
+ buffer resb 4096
+ lineBuffer resb 256
+ numberBuffer resb 16
+ lineLen resd 1
+
+section .text
+
+_start:
+ ; open file
+ mov eax, SYS_OPEN
+ mov ebx, inputPath
+ mov ecx, O_RDONLY
+ int 0x80
+
+ mov esi, eax ; fd in ESI
+ mov dword [lineLen], 0 ; no chars in current line yet
+ReadLoop:
+ ; read up to 4096 bytes
+ mov eax, SYS_READ
+ mov ebx, esi
+ mov ecx, buffer
+ mov edx, 4096
+ int 0x80
+
+ cmp eax, 0
+ jle EOF ; <=0 -> EOF or error
+
+ mov edi, buffer ; scan pointer
+ mov ebp, eax ; bytes remaining in this chunk
+
+ScanChunk:
+ cmp ebp, 0
+ je ReadLoop ; chunk done, read next
+
+ mov al, [edi]
+
+ ; windows can be a fucking bitch
+ ; handle CR (13) -> just skip
+ cmp al, 13
+ je SkipCR
+
+ ; handle LF (10) -> end of line
+ cmp al, 10
+ je EndOfLine
+
+ ; normal character -> append to lineBuffer if space left
+ mov edx, [lineLen]
+ cmp edx, 255 ; leave 1 byte for NULL
+ jae SkipStore ; ignore extra characters if too long
+ mov [lineBuffer+edx], al
+ inc edx
+ mov [lineLen], edx
+
+SkipStore:
+ inc edi
+ dec ebp
+ jmp ScanChunk
+
+SkipCR:
+ inc edi
+ dec ebp
+ jmp ScanChunk
+
+EndOfLine:
+ ; terminate current line
+ mov edx, [lineLen]
+ mov byte [lineBuffer+edx], 0
+
+ ; if line isn't empty, process it
+ cmp edx, 0
+ je LineDone
+
+ push esi
+ push edi
+ mov esi, lineBuffer
+ call HandleLine
+ pop edi
+ pop esi
+
+LineDone:
+ mov dword [lineLen], 0 ; reset line length
+ inc edi
+ dec ebp
+ jmp ScanChunk
+
+
+; process last line if not newline-terminated, then print result
+EOF:
+ ; if there is a partial line at EOF, process it
+ mov edx, [lineLen]
+ cmp edx, 0
+ jle PrintResults
+ mov byte [lineBuffer+edx], 0
+
+ push esi
+ mov esi, lineBuffer
+ call HandleLine
+ pop esi
+
+PrintResults:
+ mov ecx, label1
+ call PrintString
+ mov eax, [password1]
+ call PrintInt
+
+ ; newline
+ mov eax, SYS_WRITE
+ mov ebx, STDOUT
+ mov ecx, newline
+ mov edx, 1
+ int 0x80
+
+ mov ecx, label2
+ call PrintString
+ mov eax, [password2]
+ call PrintInt
+
+ ; newline
+ mov eax, SYS_WRITE
+ mov ebx, STDOUT
+ mov ecx, newline
+ mov edx, 1
+ int 0x80
+
+ mov eax, SYS_CLOSE
+ mov ebx, esi
+ int 0x80
+ mov eax, SYS_EXIT
+ xor ebx, ebx
+ int 0x80
+
+
+; Handle one line: ESI -> "L123" or "R45"
+HandleLine:
+ mov al, [esi]
+ cmp al, 'L'
+ je .left
+ mov ebx, 1 ; direction = +1 for 'R' or anything else
+ jmp .after
+.left:
+ mov ebx, -1 ; direction = -1 for 'L'
+.after:
+ inc esi ; skip 'L' or 'R'
+ call ParseInt ; EAX = steps
+ mov ecx, eax
+
+.part1
+ mov eax, ecx
+ imul eax, ebx ; EAX = dir*steps
+ mov edx, [angle1]
+ add edx, eax ; update angle (can be out of range signed)
+
+; normalize edx into [0; 100[ using repeated +- 100
+Norm1:
+ cmp edx, 0
+ jl N1Add
+ cmp edx, 100
+ jl N1Done
+ sub edx, 100
+ jmp Norm1
+N1Add:
+ add edx, 100
+ jmp Norm1
+N1Done:
+ mov [angle1], edx
+ cmp edx, 0
+ jne .startPart2
+ mov eax, [password1]
+ inc eax
+ mov [password1], eax
+
+; Part 2
+.startPart2:
+ mov edi, ebx
+
+part2Loop:
+ test ecx, ecx
+ jle .done
+ dec ecx
+
+ mov edx, [angle2]
+ add edx, edi
+ cmp edx, 100
+ jne .checkNegative
+ mov edx, 0
+ jmp .p2store
+.checkNegative:
+ cmp edx, -1
+ jne .p2store
+ mov edx, 99
+.p2store:
+ mov [angle2], edx
+ cmp edx, 0
+ jne part2Loop
+ mov eax, [password2]
+ inc eax
+ mov [password2], eax
+ jmp part2Loop
+.done:
+ ret
+
+
+; parse ASCII integer into EAX
+ParseInt:
+ xor eax, eax ; result = 0
+.parseLoop:
+ mov dl, [esi]
+ cmp dl, '0'
+ jl .done
+ cmp dl, '9'
+ jg .done
+
+ sub dl, '0' ; digit value 0..9
+ movzx edx, dl
+
+ imul eax, eax, 10 ; result *= 10
+ add eax, edx ; result += digit
+
+ inc esi
+ jmp .parseLoop
+.done:
+ ret
+
+PrintInt:
+ mov edi, numberBuffer+15 ; write digits from the end
+ mov byte [edi], 0 ; terminator
+ dec edi
+
+ cmp eax, 0
+ jne .convert
+ mov byte [edi], '0'
+ jmp .finish
+.convert:
+ ; we will repeatedly compute:
+ ; q = eax / 10
+ ; r = eax % 10
+ ; using only subtraction
+.nextDigit:
+ mov edx, eax ; tmp = current value
+ mov ecx, 0 ; q = 0
+
+ cmp edx, 10 ; if < 0, q=0, r=edx
+ jb .lastDigit
+.subLoop:
+ sub edx, 10
+ inc ecx ; q++
+ cmp edx, 10
+ jae .subLoop ; while tmp >= 10
+.lastDigit:
+ ; now:
+ ; ecx = quotient
+ ; edx = remainder (0..9)
+ add dl, '0'
+ mov [edi], dl ; store digit
+ dec edi
+ mov eax, ecx ; eax = quotient
+ test eax, eax
+ jnz .nextDigit ; more digits to extract?
+
+ inc edi ; move to first digit
+.finish:
+ mov eax, SYS_WRITE
+ mov ebx, STDOUT
+ mov ecx, edi
+ mov edx, numberBuffer+15
+ sub edx, edi ; length
+ int 0x80
+ ret
+
+PrintString:
+ push ecx
+ push edx
+ mov edx, 0
+.count:
+ cmp byte [ecx+edx], 0
+ je .doneCount
+ inc edx
+ jmp .count
+.doneCount:
+ mov eax, SYS_WRITE
+ mov ebx, STDOUT
+ int 0x80
+
+ pop edx
+ pop ecx
+ ret
|
