Last active
December 5, 2020 22:45
-
-
Save Yepoleb/09ab9339dbe1acb2ee11e6c7b6ea7890 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Compile: gcc aoc_day1.s -nostdlib -fPIC -o aoc_day1 | |
.intel_syntax noprefix | |
.data | |
.section .rodata | |
filename: | |
.string "input_1.txt" | |
errormsg_open: | |
.string "Failed to open file\n" | |
.set errormsg_open_len, . - errormsg_open - 1 | |
successmsg_open: | |
.string "Successfully opened file!\n" | |
.set successmsg_open_len, . - successmsg_open - 1 | |
errormsg_read: | |
.string "Read failed\n" | |
.set errormsg_read_len, . - errormsg_read - 1 | |
newline: | |
.string "\n" | |
.bss | |
ibuffer_fd: | |
.skip 8 | |
ibuffer_size: | |
.skip 8 | |
ibuffer_pos: | |
.skip 8 | |
.set ibuffer_maxsize, 1024 | |
ibuffer: | |
.skip ibuffer_maxsize | |
values: | |
.skip 200 * 8 | |
.set values_maxsize, 200 * 8 | |
.text | |
# Parameters: msg:rdi, msg_len:rsi | |
write_stdout: | |
mov rdx, rsi # count = msg_len | |
mov rsi, rdi # buf = msg | |
mov rax, 1 # write | |
mov rdi, 1 # stdout | |
syscall | |
ret | |
# Like write_stdout but adds a newline | |
# Parameters: msg:rdi, msg_len:rsi | |
print_stdout: | |
call write_stdout | |
lea rdi, [rip + newline] | |
mov rsi, 1 | |
call write_stdout | |
# Parameters: msg:rdi, msg_len:rsi | |
quit_with_error: | |
mov rdx, rsi # count = msg_len | |
mov rsi, rdi # buf = msg | |
mov rax, 1 # write | |
mov rdi, 2 # stderr | |
syscall | |
mov rax, 60 # exit | |
mov rdi, 1 # returncode | |
syscall | |
# Parameters: line_ptr:rdi | |
# Returns: line_end:rax, eof:rdx | |
get_line: | |
push r12 | |
mov r12, rdi # line_pos_ptr | |
get_line_loop: | |
call get_byte # char:rax, eof:rdx | |
test rdx, rdx # if eof: return | |
jnz get_line_return | |
cmp rax, 0x0A # if \n: return | |
je get_line_return | |
mov byte ptr [r12], al # set char | |
inc r12 | |
jmp get_line_loop | |
get_line_return: | |
mov rax, r12 | |
pop r12 | |
ret | |
# Returns: byte:rax, eof:rdx | |
get_byte: | |
mov r8, [rip + ibuffer_pos] | |
mov r9, [rip + ibuffer_size] | |
lea r10, [rip + ibuffer] | |
cmp r8, r9 | |
jb get_byte_buffer_healthy # pos < size | |
# refresh buffer | |
mov rax, 0 # read | |
mov rdi, [rip + ibuffer_fd] # fd | |
mov rsi, r10 # buf = ibuffer | |
mov rdx, ibuffer_maxsize # count | |
syscall # bytes_read/errno:rax | |
cmp rax, 0 | |
jl get_byte_read_failed | |
je get_byte_return_eof | |
mov r9, rax # ibuffer_size = return value | |
mov [rip + ibuffer_size], r9 # write back to memory | |
mov r8, 0 # ibuffer_pos = 0 | |
get_byte_buffer_healthy: | |
movzx rax, byte ptr [r10 + r8] # ibuffer + ibuffer_pos | |
inc r8 # ibuffer_pos++ | |
mov [rip + ibuffer_pos], r8 # write back to memory | |
mov rdx, 0 | |
ret | |
get_byte_return_eof: | |
mov rax, 0 | |
mov rdx, 1 | |
ret | |
get_byte_read_failed: | |
lea rdi, [rip + errormsg_read] | |
mov rsi, errormsg_read_len | |
jmp quit_with_error | |
# Parameters: string_begin:rdi, string_end:rsi | |
# Returns: value:rax | |
parse_int: | |
mov rax, 0 | |
parse_int_loop: | |
cmp rdi, rsi | |
jge parse_int_return | |
imul rax, rax, 10 # Multiply rax by 10 | |
movzx rdx, byte ptr [rdi] | |
add rdx, -'0' # Subtract char value of '0' | |
add rax, rdx # Add digit value | |
inc rdi | |
jmp parse_int_loop | |
parse_int_return: | |
ret | |
# Parameters: intval:rdi, buffer_start:rsi | |
# Returns: buffer_end:rax | |
format_int: | |
mov r8, rsi # buffer_end = buffer_start | |
mov rax, rdi # remval = intval | |
format_int_digits_loop: | |
test rax, rax | |
jz format_int_digits_end | |
mov rdx, 0 # clear rdx for division | |
mov rcx, 10 | |
div rcx # rax = remval / 10, rdx = remval % 10 | |
add rdx, '0' # Add char value of '0' | |
mov byte ptr [r8], dl # Write character to buffer | |
inc r8 | |
jmp format_int_digits_loop | |
format_int_digits_end: | |
# Reverse digits | |
mov r9, rsi # pos_low = buffer_start | |
mov rax, r8 # Move buffer_end to return variable so r8 can become pos_high | |
add r8, -1 # subtract 1 from end to point at last character | |
format_int_reverse_loop: | |
cmp r9, r8 | |
jge format_int_reverse_end # if pow_low >= pos_high: break | |
mov cl, byte ptr [r8] # exchange values | |
mov dl, byte ptr [r9] | |
mov byte ptr [r9], cl | |
mov byte ptr [r8], dl | |
inc r9 # increase/decrease pointers | |
dec r8 | |
jmp format_int_reverse_loop | |
format_int_reverse_end: | |
ret | |
.global _start | |
_start: | |
# Open input file | |
mov rax, 2 # open | |
lea rdi, [rip + filename] | |
mov rsi, 0 # flags | |
mov rdx, 0 # mode read | |
syscall | |
mov [rip + ibuffer_fd], rax | |
cmp rax, 0 | |
jle open_failed | |
# Print success message | |
lea rdi, [rip + successmsg_open] | |
mov rsi, successmsg_open_len | |
call write_stdout | |
# Read input values | |
lea r12, [rip + values] # values_pos:r12 = &values | |
sub rsp, 32 # rsp = line_begin | |
input_loop: | |
mov rdi, rsp | |
call get_line # line_end:rax, eof:rdx | |
test rdx, rdx # if eof | |
jnz input_loop_end | |
# Output line | |
#mov rdi, rsp | |
#mov rsi, rax | |
#sub rsi, rsp # calculate length | |
#call print_stdout | |
mov rdi, rsp | |
mov rsi, rax | |
call parse_int # parse_int(line_begin, line_end) -> rax | |
mov qword ptr [r12], rax | |
add r12, 8 | |
jmp input_loop | |
input_loop_end: | |
lea r10, [rip + values] # i_pos | |
outer_loop: | |
cmp r10, r12 # while i_pos < values_end | |
jge outer_loop_end | |
mov r11, r10 | |
inner_loop: | |
cmp r11, r12 # while j_pos < values_end | |
jge inner_loop_end | |
mov r13, qword ptr [r10] # ival | |
mov r14, qword ptr [r11] # jval | |
mov rcx, r13 | |
add rcx, r14 | |
cmp rcx, 2020 | |
je outer_loop_end | |
add r11, 8 | |
jmp inner_loop | |
inner_loop_end: | |
add r10, 8 | |
jmp outer_loop | |
outer_loop_end: | |
# ival:r13, jval:r14 | |
# repurposing input line buffer for output | |
mov r15, r13 | |
imul r15, r14 # ival*jval:r15 | |
mov rsi, rsp # line_pos | |
mov rdi, r13 | |
call format_int # format_int(ival, line_pos) -> line_pos:rax | |
mov byte ptr [rax], ' ' | |
lea rsi, [rax + 1] | |
mov rdi, r14 | |
call format_int | |
mov byte ptr [rax], ' ' | |
lea rsi, [rax + 1] | |
mov rdi, r15 | |
call format_int | |
mov byte ptr [rax], '\n' | |
mov rdi, rsp | |
lea rsi, [rax + 1] | |
sub rsi, rdi # calculate string length | |
call write_stdout | |
add rsp, 32 # delete line buffer | |
mov rax, 60 # exit | |
mov rdi, 0 | |
syscall | |
open_failed: | |
lea rdi, [rip + errormsg_open] | |
mov rsi, errormsg_open_len | |
jmp quit_with_error |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Does not fully match the final code, but the general concepts are the same | |
MAX_BUFFERSIZE = 5 | |
class FileStream: | |
def __init__(self, fd): | |
self.fd = fd | |
self.buffer = b"" | |
self.buffer_size = 0 | |
self.index = 0 | |
def refreshBuffer(self): | |
self.buffer = self.fd.read(MAX_BUFFERSIZE) | |
self.buffer_size = len(self.buffer) | |
if not self.buffer_size: | |
return True | |
self.index = 0 | |
return False | |
def getByte(self): | |
if self.index >= self.buffer_size: | |
eof = self.refreshBuffer() | |
if eof: | |
return ("\0", True) | |
b = self.buffer[self.index] | |
self.index += 1 | |
return (b, False) | |
def readLine(stream): | |
line = "" | |
while True: | |
char, eof = stream.getByte() | |
if eof: | |
return (line, True) | |
if char == "\n": | |
return (line, False) | |
line += char | |
def parseInt(int_str): | |
val = 0 | |
for i in range(len(int_str)): | |
val = val * 10 + ord(int_str[i]) - ord("0") | |
return val | |
def reverse(l): | |
pos_low = 0 | |
pos_high = len(l) - 1 | |
while pos_low < pos_high: | |
t1 = l[pos_low] | |
t2 = l[pos_high] | |
l[pos_low] = t2 | |
l[pos_high] = t1 | |
pos_low += 1 | |
pos_high -= 1 | |
def formatInt(intval): | |
remval = intval | |
digits_reversed = [] | |
while remval: | |
digit_val = remval % 10 | |
remval = remval // 10 | |
digits_reversed.append(chr(ord("0") + digit_val)) | |
reverse2(digits_reversed) | |
return "".join(digits_reversed) | |
class DynamicIntArray: | |
def __init__(self, mem, memsize): | |
self.mem = mem | |
self.memsize = memsize | |
self.size = 0 | |
def append(self, value): | |
assert self.size < self.memsize | |
self.mem[self.size] = value | |
self.size += 1 | |
def __getitem__(self, index): | |
return self.mem[index] | |
values = DynamicIntArray([0] * 200, 200) | |
f = open("input_1.txt") | |
stream = FileStream(f) | |
while True: | |
line, eof = stream.readLine() | |
if eof: | |
break | |
value = parseInt(line) | |
values.append(value) | |
for i in range(values.size): | |
for j in range(i, values.size): | |
ival = values[i] | |
jval = values[j] | |
if ival + jval == 2020: | |
print(formatInt(ival), formatInt(jval), formatInt(ival * jval)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment