Compare commits
2 Commits
aa62e04926
...
da72d87c94
Author | SHA1 | Date |
---|---|---|
chylex | da72d87c94 | |
chylex | da6c7d7d5b |
|
@ -6,4 +6,4 @@ enable_language(ASM_NASM)
|
|||
set(CMAKE_NASM_LINK_EXECUTABLE "ld <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
|
||||
set(CAN_USE_ASSEMBLER TRUE)
|
||||
|
||||
add_executable(${PROJECT_NAME} main.asm main.c)
|
||||
add_executable(${PROJECT_NAME} main.asm ../utils/main.c ../utils/file.h)
|
||||
|
|
|
@ -1,32 +1,30 @@
|
|||
bits 32
|
||||
extern _printf
|
||||
|
||||
section .data
|
||||
|
||||
print_final_floor: db `Final floor: %d\n`, 0
|
||||
print_first_entered_basement: db `First entered basement: %d\n`, 0
|
||||
|
||||
section .text
|
||||
|
||||
global _walkFloors
|
||||
global _entryPoint
|
||||
|
||||
_walkFloors:
|
||||
_entryPoint:
|
||||
enter 0,0
|
||||
push ebx
|
||||
push edi
|
||||
|
||||
; [ ebp + 8 ] = int currentFloor
|
||||
; [ ebp + 12 ] = int* totalInstructionCounter
|
||||
; [ ebp + 16 ] = int* firstEnteredBasement
|
||||
; [ ebp + 20 ] = char* instructions
|
||||
; [ ebp + 24 ] = size_t instructionCount
|
||||
|
||||
mov eax, [ ebp + 8 ] ; eax = currentFloor
|
||||
mov edx, [ ebp + 20 ] ; edx = instructions
|
||||
xor ecx, ecx ; ecx = 0
|
||||
xor eax, eax ; current floor
|
||||
xor ebx, ebx ; current instruction
|
||||
xor ecx, ecx ; instruction counter
|
||||
mov edx, [ ebp + 8 ] ; instruction pointer
|
||||
mov edi, -1 ; first entered basement (-1 = unset)
|
||||
|
||||
.instructionLoop:
|
||||
cmp ecx, [ ebp + 24 ] ; check if we went past instructionCount
|
||||
jge .end ; if so, we are done here
|
||||
inc ecx ; otherwise, increment instruction counter and continue
|
||||
|
||||
inc ecx ; increment instruction counter
|
||||
mov bl, [ edx ] ; bl = instructions[edx]
|
||||
inc edx ; edx++
|
||||
inc edx ; increment instruction pointer
|
||||
|
||||
cmp bl, '(' ; left parenthesis...
|
||||
je .moveUpFloor ; moves up a floor
|
||||
|
@ -45,21 +43,19 @@ _walkFloors:
|
|||
jmp .instructionLoop
|
||||
|
||||
.onEnteredBasement:
|
||||
mov ebx, [ ebp + 16 ] ; ebx = &firstEnteredBasement
|
||||
cmp dword [ ebx ], -1 ; check if firstEnteredBasement has not been set yet
|
||||
jne .instructionLoop ; if it was already set, go to next instruction
|
||||
|
||||
mov edi, [ ebp + 12 ] ; edi = &totalInstructionCounter
|
||||
mov edi, [ edi ] ; edi = totalInstructionCounter
|
||||
add edi, ecx ; add current instruction counter to the total
|
||||
mov dword [ ebx ], edi ; set firstEnteredBasement to the total
|
||||
cmp edi, -1 ; check if firstEnteredBasement has not been set yet
|
||||
jne .instructionLoop ; if it was already set, go to next instruction
|
||||
mov edi, ecx ; set first entered basement to instruction counter
|
||||
jmp .instructionLoop
|
||||
|
||||
.end:
|
||||
mov edi, [ ebp + 12 ] ; edi = &totalInstructionCounter
|
||||
mov ebx, [ edi ] ; ebx = totalInstructionCounter
|
||||
add ebx, ecx ; add current instruction counter to the total
|
||||
mov dword [ edi ], ebx ; set totalInstructionCounter to the new total
|
||||
push eax
|
||||
push dword print_final_floor
|
||||
call _printf
|
||||
|
||||
push edi
|
||||
push dword print_first_entered_basement
|
||||
call _printf
|
||||
|
||||
pop edi
|
||||
pop ebx
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
#include "stdio.h"
|
||||
|
||||
#define BUFFER_SIZE 256
|
||||
|
||||
int walkFloors(int currentFloor, int* totalInstructionCounter, int* firstEnteredBasement, char* instructions, size_t instructionCount);
|
||||
|
||||
int main() {
|
||||
FILE* file;
|
||||
errno_t openErr = fopen_s(&file, "input/1.txt", "rb");
|
||||
if (openErr != 0 || !file) {
|
||||
printf("Error opening input file, code %d\n", openErr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int floor = 0;
|
||||
int totalInstructionCounter = 0;
|
||||
int firstEnteredBasement = -1;
|
||||
|
||||
char buffer[BUFFER_SIZE];
|
||||
while (!feof(file)) {
|
||||
size_t readBytes = fread_s(&buffer, BUFFER_SIZE, 1, BUFFER_SIZE, file);
|
||||
|
||||
int readErr = ferror(file);
|
||||
if (readErr) {
|
||||
printf("Error reading input file, code %d\n", readErr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
floor = walkFloors(floor, &totalInstructionCounter, &firstEnteredBasement, buffer, readBytes);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
printf("Final floor: %d\n", floor);
|
||||
printf("First entered basement: %d\n", firstEnteredBasement);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
#ifndef ADVENTOFCODE_FILE_H
|
||||
#define ADVENTOFCODE_FILE_H
|
||||
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
#define MAX_READ_SIZE 4096
|
||||
|
||||
char* readFile(const char* filename) {
|
||||
FILE* file;
|
||||
errno_t openErr = fopen_s(&file, filename, "rb");
|
||||
if (openErr != 0 || !file) {
|
||||
printf("Error opening input file, code %d\n", openErr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fseek(file, 0L, SEEK_END);
|
||||
int fileSize = ftell(file);
|
||||
rewind(file);
|
||||
|
||||
if (fileSize == 0) {
|
||||
printf("Input file is empty\n");
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* contents = malloc(fileSize + 1);
|
||||
if (!contents) {
|
||||
printf("Error allocating %d bytes for storing input file\n", fileSize + 1);
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t position = 0;
|
||||
while (position < fileSize) {
|
||||
size_t remainingSpace = fileSize - position;
|
||||
size_t readBytes = fread_s(contents + position, remainingSpace, 1, min(remainingSpace, MAX_READ_SIZE), file);
|
||||
position += readBytes;
|
||||
|
||||
int readErr = ferror(file);
|
||||
if (readErr) {
|
||||
perror("Error reading input file");
|
||||
fclose(file);
|
||||
free(contents);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (readBytes == 0) {
|
||||
printf("Error reading input file, read 0 bytes\n");
|
||||
fclose(file);
|
||||
free(contents);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
|
||||
if (position != fileSize) {
|
||||
printf("Error reading whole file, read only %d bytes out of %d\n", position, fileSize);
|
||||
free(contents);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
contents[fileSize] = 0;
|
||||
return contents;
|
||||
}
|
||||
|
||||
#endif //ADVENTOFCODE_FILE_H
|
|
@ -0,0 +1,15 @@
|
|||
#include "file.h"
|
||||
|
||||
void entryPoint(char* input);
|
||||
|
||||
int main() {
|
||||
char* input = readFile("input/1.txt");
|
||||
|
||||
if (input == NULL) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
entryPoint(input);
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@ The source code is in `main.kt`. The run configuration executes the `main()` met
|
|||
|
||||
The repository contains a CMake project (`CMakeLists.txt`) that sets up every day as a CMake subproject. You should be able to load the CMake project into [CLion](https://www.jetbrains.com/clion/).
|
||||
|
||||
The source code is in `main.c` with some boilerplate that reads the input file, and calls functions in `main.asm` which implement the logic of each puzzle.
|
||||
The source code is in `main.c`, which is either in the puzzle's own folder, or in `utils` if no adjustments are needed. By default, `main.c` reads the whole input file into a buffer, and passes it as a parameter to the `entryPoint` function defined in `main.asm` which implements the logic and output of each puzzle.
|
||||
|
||||
Note that everything is targeted for Windows x86 or WoW64, and assembly is not portable, so running on a different OS will most likely require some changes. You will need to:
|
||||
|
||||
|
|
Loading…
Reference in New Issue