1
0
Fork 0

Compare commits

...

2 Commits

Author SHA1 Message Date
chylex da72d87c94
Update README 2022-02-10 13:39:16 +01:00
chylex da6c7d7d5b
Refactor 2015 - Day 1 (move all but input file reading to ASM) 2022-02-10 13:25:24 +01:00
6 changed files with 109 additions and 66 deletions

View File

@ -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)

View File

@ -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

View File

@ -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;
}

68
2015/utils/file.h Normal file
View File

@ -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

15
2015/utils/main.c Normal file
View File

@ -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;
}
}

View File

@ -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: