day 4
This commit is contained in:
parent
412ce5a7b0
commit
c079e80137
@ -3,9 +3,16 @@
|
|||||||
|
|
||||||
Today's language: **C**
|
Today's language: **C**
|
||||||
|
|
||||||
|
Extra: Task 1 in **vimscript**, generated by OpenAI with just a few fixes by myself
|
||||||
|
|
||||||
All the characters (the Elf's items) occuring in (half) a line (backpack) are stored as bits in an unsigned long, duplicate characters can then be determined by bitwise and-ing these numbers.
|
All the characters (the Elf's items) occuring in (half) a line (backpack) are stored as bits in an unsigned long, duplicate characters can then be determined by bitwise and-ing these numbers.
|
||||||
```shell
|
```shell
|
||||||
# Find the item type that appears in both compartments of each rucksack. What is the sum of the priorities of those item types?
|
# Find the item type that appears in both compartments of each rucksack. What is the sum of the priorities of those item types?
|
||||||
gcc main.c -o day3
|
gcc main.c -o day3
|
||||||
./day3
|
./day3
|
||||||
|
|
||||||
|
# OpenAI vim script
|
||||||
|
vim rucksack_items.txt
|
||||||
|
# in vim:
|
||||||
|
# :source day3-1.vim
|
||||||
```
|
```
|
||||||
|
47
3/day3-1.vim
Normal file
47
3/day3-1.vim
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
" Define the function that will be run when the script is executed
|
||||||
|
function! FindAndSumCharacters()
|
||||||
|
" Initialize the sum to 0
|
||||||
|
let sum = 0
|
||||||
|
|
||||||
|
" Iterate over every line in the file
|
||||||
|
" Note: The cursor position is not relevant here, since the script
|
||||||
|
" will process the entire file
|
||||||
|
for line in getline(1, '$')
|
||||||
|
" Get the first and second half of the line
|
||||||
|
let first_half = line[:len(line)/2]
|
||||||
|
let second_half = line[len(line)/2:]
|
||||||
|
|
||||||
|
" Find the character that occurs in both the first and second half
|
||||||
|
" of the line.
|
||||||
|
" Note: There will be only one such character, since the prompt
|
||||||
|
" specified that each line contains only a-zA-Z
|
||||||
|
let common_char = ''
|
||||||
|
for char in first_half
|
||||||
|
if match(second_half, '\C' . char) >= 0
|
||||||
|
let common_char = char
|
||||||
|
" echo first_half . " - " . second_half . " - char" . common_char
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
" Convert the character to a number
|
||||||
|
let common_char_num = char2nr(common_char)
|
||||||
|
let char_num = 0
|
||||||
|
if common_char_num >= char2nr('a') && common_char_num <= char2nr('z')
|
||||||
|
let char_num = common_char_num - char2nr('a') + 1
|
||||||
|
elseif common_char_num >= char2nr('A') && common_char_num <= char2nr('Z')
|
||||||
|
let char_num = common_char_num + 27 - char2nr('A')
|
||||||
|
endif
|
||||||
|
" echo "char_num " . char_num . "for char " . common_char . " char2nr " . char2nr(common_char)
|
||||||
|
|
||||||
|
" Add the number to the sum
|
||||||
|
let sum += char_num
|
||||||
|
endfor
|
||||||
|
|
||||||
|
" Output the final sum
|
||||||
|
echo sum
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Run the script when it is loaded
|
||||||
|
call FindAndSumCharacters()
|
||||||
|
|
3
4/.gitignore
vendored
Normal file
3
4/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
*.o
|
||||||
|
.old
|
||||||
|
day4
|
22
4/.vimspector.json
Normal file
22
4/.vimspector.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"configurations": {
|
||||||
|
"vulkan_test": {
|
||||||
|
"adapter": "vscode-cpptools",
|
||||||
|
"configuration": {
|
||||||
|
"name": "day4",
|
||||||
|
"type": "asmdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"externalConsole": true,
|
||||||
|
"logging": {
|
||||||
|
"engineLogging": true
|
||||||
|
},
|
||||||
|
"stopOnEntry": true,
|
||||||
|
"stopAtEntry": true,
|
||||||
|
"debugOptions": [],
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"cwd": "~/Sonstiges/AdventOfCode/4",
|
||||||
|
"program": "~/Sonstiges/AdventOfCode/4/day4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
4/Makefile
Normal file
14
4/Makefile
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
ASM_SRC = day4.s
|
||||||
|
C_SRC = day4-from-ai.c
|
||||||
|
# DEBUG = -g
|
||||||
|
DEBUG =
|
||||||
|
|
||||||
|
asm:
|
||||||
|
as -o day4.o $(ASM_SRC) $(DEBUG)
|
||||||
|
ld $(DEBUG) -o day4 day4.o -lc
|
||||||
|
@# for some reason an invalid interpreter is in the binary, which leads to 'file not found error' when running
|
||||||
|
patchelf --set-interpreter "/usr/lib/ld-linux-x86-64.so.2" day4
|
||||||
|
|
||||||
|
c:
|
||||||
|
gcc $(C_SRC) -o day4 "section-pairs.txt"
|
||||||
|
|
28
4/README.md
Normal file
28
4/README.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# [Day 4](https://adventofcode.com/2022/day/4)
|
||||||
|
:gift::gift::gift::gift:
|
||||||
|
Today's language: **gnu x86-64** (and alternatively **c**)
|
||||||
|
|
||||||
|
Today I wanted to use OpenAI to solve the tasks using gnu x86-64, which I have never used before
|
||||||
|
(I did some small things in [6502-asssembly](https://github.com/MatthiasQuintern/6502), so it wasn't all new).
|
||||||
|
The prompt can be seen in prompt.txt.
|
||||||
|
It did a lot of things right, however:
|
||||||
|
- It did generate x86 (32-bit) code because I did not specify x86-64. So I changed the `int $0x80` system calls to use `syscall` (which also meant I had to change all the registers and [syscall numbers](https://filippo.io/linux-syscall-table/))
|
||||||
|
- It did get the argument order for `sscanf` wrong, even when I specifically asked it told me that the line to read comes last
|
||||||
|
- It did not correctly implement the logic to test the condition
|
||||||
|
- It sometimes me wrong syscall numbers (they were just wrong, not even x86)
|
||||||
|
- It told me the `read` syscall can read until a `newline` by passing `newline` as last arg
|
||||||
|
|
||||||
|
So I had to fix all that. I tried to exclusively use the AI to get answers to my questions, however I did sometimes revert to the internet.
|
||||||
|
It was still a good starting point and provided lots of help.
|
||||||
|
At the end of the ~~evening~~ next morning I had coded the task in x86-64 assembly.
|
||||||
|
|
||||||
|
To test scanf, I gave it the exact same prompt but said I wanted it in *c*.
|
||||||
|
It instantly produced compilable c code that gave the right answer...
|
||||||
|
```shell
|
||||||
|
# for the assembly program
|
||||||
|
make asm
|
||||||
|
./day4
|
||||||
|
# for the c promgram
|
||||||
|
make c
|
||||||
|
./day4
|
||||||
|
```
|
71
4/day4-from-ai.c
Normal file
71
4/day4-from-ai.c
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file was generated by OpenAI and was not modified apart from this comment. The prompt was:
|
||||||
|
* consider a text file like this:
|
||||||
|
* 22-65,22-66
|
||||||
|
* 91-94,63-91
|
||||||
|
* 6-88,5-31
|
||||||
|
* 85-86,64-86
|
||||||
|
* 40-65,40-65
|
||||||
|
* 25-82,24-94
|
||||||
|
*
|
||||||
|
* write c program that:
|
||||||
|
* - reads a text file like this line by line and count how often one of the two ranges contains the other.
|
||||||
|
* - accepts the filename via command line arg
|
||||||
|
* - outputs the result using printf with a suitable string
|
||||||
|
* A range r1 contains the other r2 when the r1.lower <= r2.lower and r1.upper >= r2.upper
|
||||||
|
* the program needs to output how often that is the case in the entire file
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Structure to represent a range in the file
|
||||||
|
struct range {
|
||||||
|
int lower;
|
||||||
|
int upper;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to parse a line from the file and return the two ranges in the line
|
||||||
|
void parse_line(const char *line, struct range *range1, struct range *range2) {
|
||||||
|
// Parse the two ranges in the line
|
||||||
|
sscanf(line, "%d-%d,%d-%d", &range1->lower, &range1->upper, &range2->lower, &range2->upper);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
// Check if a filename was provided
|
||||||
|
if (argc < 2) {
|
||||||
|
fprintf(stderr, "Error: No filename provided\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the file for reading
|
||||||
|
FILE *fp = fopen(argv[1], "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
fprintf(stderr, "Error: Unable to open file for reading\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the file line by line
|
||||||
|
char line[256];
|
||||||
|
int count = 0;
|
||||||
|
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||||
|
// Parse the two ranges in the line
|
||||||
|
struct range range1, range2;
|
||||||
|
parse_line(line, &range1, &range2);
|
||||||
|
|
||||||
|
// Check if one range contains the other
|
||||||
|
if ((range1.lower <= range2.lower && range1.upper >= range2.upper) ||
|
||||||
|
(range2.lower <= range1.lower && range2.upper >= range1.upper)) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the file
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
// Print the result
|
||||||
|
printf("The file contains %d lines where one of the two ranges contains the other\n", count);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
66
4/day4-from-ai.s
Normal file
66
4/day4-from-ai.s
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
.data
|
||||||
|
filename: .asciz "input.txt"
|
||||||
|
format: .asciz "%d-%d,%d-%d"
|
||||||
|
result: .asciz "Result: %d\n"
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl main
|
||||||
|
|
||||||
|
main:
|
||||||
|
pushl %ebp
|
||||||
|
movl %esp, %ebp
|
||||||
|
|
||||||
|
xorl %eax, %eax # initialize count to 0
|
||||||
|
movl $1, %ebx # initialize loop variable to 1
|
||||||
|
|
||||||
|
# open the file and store the file descriptor in %ecx
|
||||||
|
movl $5, %eax # set the number of the "open" syscall to 5
|
||||||
|
movl $filename, %ebx # move the address of the filename to %ebx
|
||||||
|
xorl %edx, %edx # set the flags to 0
|
||||||
|
int $0x80
|
||||||
|
|
||||||
|
# read the file line by line
|
||||||
|
.loop:
|
||||||
|
movl $3, %eax # set the number of the "read" syscall to 3
|
||||||
|
movl %ecx, %ebx # move the file descriptor to %ebx
|
||||||
|
movl $buffer, %ecx # move the address of the buffer to %ecx
|
||||||
|
movl $BUFSIZ, %edx # move the size of the buffer to %edx
|
||||||
|
int $0x80
|
||||||
|
|
||||||
|
# check if end of file has been reached
|
||||||
|
cmpl $0, %eax
|
||||||
|
jz .done # if so, jump to .done
|
||||||
|
|
||||||
|
# parse the line and check if it satisfies the condition
|
||||||
|
call sscanf
|
||||||
|
movl %eax, %edi
|
||||||
|
movl %ebx, %esi
|
||||||
|
movl %ecx, %ebp
|
||||||
|
movl %edx, %ebx
|
||||||
|
cmpl %edi, %ebp
|
||||||
|
jl .not_contained
|
||||||
|
cmpl %esi, %ebx
|
||||||
|
jg .not_contained
|
||||||
|
incl %eax # increment count
|
||||||
|
|
||||||
|
.not_contained:
|
||||||
|
incl %ebx # increment loop variable
|
||||||
|
|
||||||
|
jmp .loop # repeat the loop
|
||||||
|
|
||||||
|
.done:
|
||||||
|
# print the result
|
||||||
|
movl $1, %eax # set the number of the "write" syscall to 1
|
||||||
|
movl $1, %ebx # set the file descriptor to stdout (1)
|
||||||
|
movl $result, %ecx # move the address of the result string to %ecx
|
||||||
|
movl %eax, %edx # move the count to %edx
|
||||||
|
int $0x80
|
||||||
|
|
||||||
|
# close the file
|
||||||
|
movl $6, %eax # set the number of the "close" syscall to 6
|
||||||
|
movl %ecx, %ebx # move the file descriptor to %ebx
|
||||||
|
int $0x80
|
||||||
|
|
||||||
|
leave
|
||||||
|
ret
|
||||||
|
|
294
4/day4.s
Normal file
294
4/day4.s
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
# Parts of this code were generated by OpenAI
|
||||||
|
# I did however have to modifiy nearly all of it
|
||||||
|
|
||||||
|
.data
|
||||||
|
count_contained:.long 0
|
||||||
|
count_overlap: .long 0
|
||||||
|
file: .quad 0 # file descriptor
|
||||||
|
line_length: .quad 0 # store the length of the current line in line_buffer
|
||||||
|
line_nr: .long 0 # store the line number
|
||||||
|
r1_upper: .long 0 # range 1 upper value
|
||||||
|
r2_upper: .long 0 # range 2 upper value
|
||||||
|
r1_lower: .long 0 # range 1 lower value
|
||||||
|
r2_lower: .long 0 # range 2 lower value
|
||||||
|
current_char: .long 0
|
||||||
|
|
||||||
|
filename: .asciz "section-pairs.txt"
|
||||||
|
format: .asciz "%d-%d,%d-%d"
|
||||||
|
f_contained: .asciz "Current line has containment. count_contained: [%d]\n"
|
||||||
|
f_res_cont: .asciz "The file contains %d lines where one of the two ranges contains the other\n"
|
||||||
|
f_res_over: .asciz "The file contains %d lines where one of the two ranges overlaps the other\n"
|
||||||
|
f_line_nr: .asciz "Line Nr: [%d] -\t"
|
||||||
|
f_line_length: .asciz "Line Length: [%d] -\tContent: '"
|
||||||
|
f_q_newline: .asciz "'\n"
|
||||||
|
f_error_open: .asciz "Error %d while opening file\n"
|
||||||
|
f_error_read: .asciz "Error %d while reading file.\n"
|
||||||
|
f_error_match: .asciz "Error %d while matching line.\n"
|
||||||
|
|
||||||
|
LINE_BUFSIZ = 32
|
||||||
|
PRINT_BUFSIZ = 100
|
||||||
|
SYS_READ = 0
|
||||||
|
SYS_WRITE = 1
|
||||||
|
SYS_OPEN = 2
|
||||||
|
SYS_CLOSE = 3
|
||||||
|
SYS_EXIT = 60
|
||||||
|
STDOUT = 1
|
||||||
|
|
||||||
|
.bss
|
||||||
|
line_buffer: .skip LINE_BUFSIZ
|
||||||
|
print_buffer: .skip PRINT_BUFSIZ
|
||||||
|
|
||||||
|
.text
|
||||||
|
.globl _start
|
||||||
|
.globl sscanfl
|
||||||
|
|
||||||
|
|
||||||
|
# syscall arg order
|
||||||
|
# (call #: rax) - rdi rsi rdx r10 r8 r9
|
||||||
|
_start:
|
||||||
|
push %rbp
|
||||||
|
mov %rsp, %rbp
|
||||||
|
|
||||||
|
# xorl %eax, %eax # initialize count_contained to 0
|
||||||
|
# movl $1, %ebx # initialize loop variable to 1
|
||||||
|
|
||||||
|
# open the file and store the file descriptor in %ecx
|
||||||
|
movq $SYS_OPEN, %rax # set the number of the "open" syscall
|
||||||
|
movq $filename, %rdi # move the address of the filename to %ebx
|
||||||
|
xorq %rsi, %rsi # set the flags to 0
|
||||||
|
xorq %rdx, %rdx # set the mode to 0 = read
|
||||||
|
# movq $777, %rsi
|
||||||
|
syscall
|
||||||
|
|
||||||
|
# if read fails, jump to error
|
||||||
|
jl .error_open
|
||||||
|
jg .error_open
|
||||||
|
# negative return value is error
|
||||||
|
cmpq $0, %rax
|
||||||
|
jl .error_open
|
||||||
|
|
||||||
|
movq %rax, file # store file descriptor in file
|
||||||
|
|
||||||
|
# read the file line by line
|
||||||
|
.loop:
|
||||||
|
call read_next_line
|
||||||
|
|
||||||
|
cmpq $0, %rax # rax is number of chars read, if 0 we are done
|
||||||
|
je .done
|
||||||
|
|
||||||
|
# get and print line lenght
|
||||||
|
movq %rax, line_length
|
||||||
|
|
||||||
|
# increment line nr
|
||||||
|
incl line_nr # increment line_nr
|
||||||
|
|
||||||
|
# print line nr
|
||||||
|
movl line_nr, %edx # load to print
|
||||||
|
leaq f_line_nr, %rsi # set print format
|
||||||
|
push %rdx
|
||||||
|
call print_rsi_rdx
|
||||||
|
pop %rdx
|
||||||
|
|
||||||
|
# print line lenght
|
||||||
|
movq line_length, %rdx
|
||||||
|
leaq f_line_length, %rsi
|
||||||
|
push %rdx
|
||||||
|
call print_rsi_rdx
|
||||||
|
pop %rdx
|
||||||
|
|
||||||
|
# print the line
|
||||||
|
movq $SYS_WRITE, %rax # set the number of the "write" syscall to 4
|
||||||
|
movq $STDOUT, %rdi # move the file descriptor (1 for stdout) to %ebx
|
||||||
|
movq $LINE_BUFSIZ, %rdx # number of bytes
|
||||||
|
leaq line_buffer, %rsi # buffer
|
||||||
|
syscall
|
||||||
|
|
||||||
|
# print newline
|
||||||
|
movq $SYS_WRITE, %rax # set the number of the "write" syscall to 4
|
||||||
|
movq $STDOUT, %rdi # move the file descriptor (1 for stdout) to %ebx
|
||||||
|
movq $2, %rdx # number of bytes
|
||||||
|
leaq f_q_newline, %rsi # buffer
|
||||||
|
syscall
|
||||||
|
|
||||||
|
# from first arg to last
|
||||||
|
leaq line_buffer, %rdi # Load the address of the line_buffer into %rdi
|
||||||
|
leaq format, %rsi # Move the address of the format string into %rs
|
||||||
|
leaq r1_lower, %rdx # Move the address of the first output register into %esi
|
||||||
|
leaq r1_upper, %rcx # Move the address of the second output register into %edx
|
||||||
|
leaq r2_lower, %r8 # Move the address of the third output register into %ecx
|
||||||
|
leaq r2_upper, %r9 # Move the address of the fourth output register into %r8d
|
||||||
|
|
||||||
|
push %rbx # to align the stack
|
||||||
|
call sscanf # Call the scanf function
|
||||||
|
pop %rbx # restore stack ptr
|
||||||
|
cmp $0, %rax
|
||||||
|
je .error_match # 0 is not succesful
|
||||||
|
|
||||||
|
# load the results into registers
|
||||||
|
movl r1_lower, %eax
|
||||||
|
movl r2_lower, %ebx
|
||||||
|
movl r1_upper, %ecx
|
||||||
|
movl r2_upper, %edx
|
||||||
|
|
||||||
|
cmp %ebx, %eax # compare r1l to r2l
|
||||||
|
jg .cont_r1l_greater_r2l
|
||||||
|
je .is_contained # if lower bounds are equal, one must be contained in the other
|
||||||
|
jl .cont_r1l_less_r2l
|
||||||
|
|
||||||
|
# 1) check containment
|
||||||
|
.cont_r1l_greater_r2l: # r1l > r2l
|
||||||
|
# to be contained: r1u <= r2u
|
||||||
|
cmp %edx, %ecx
|
||||||
|
jl .is_contained
|
||||||
|
je .is_contained
|
||||||
|
jmp .not_contained
|
||||||
|
|
||||||
|
|
||||||
|
.cont_r1l_less_r2l:
|
||||||
|
# to be contained: r1u >= r1u
|
||||||
|
cmp %edx, %ecx
|
||||||
|
jg .is_contained
|
||||||
|
je .is_contained
|
||||||
|
jmp .not_contained
|
||||||
|
|
||||||
|
movq $42, %rax
|
||||||
|
jmp .error_open # it should not come to this
|
||||||
|
|
||||||
|
.is_contained:
|
||||||
|
incl count_contained
|
||||||
|
jmp .overlaps # containment € overlap
|
||||||
|
.not_contained:
|
||||||
|
|
||||||
|
# 2) overlap
|
||||||
|
# two ranges overlap if
|
||||||
|
# r1l > r2l:
|
||||||
|
# r1l <= r2u
|
||||||
|
# r1l < r2l:
|
||||||
|
# r1u >= r2l
|
||||||
|
# r1l == r2l
|
||||||
|
cmpl %ebx, %eax # compare r1l to r2l
|
||||||
|
jg .over_r1l_greater_r2l
|
||||||
|
je .overlaps
|
||||||
|
jl .over_r1l_less_r2l
|
||||||
|
|
||||||
|
movq $43, %rax
|
||||||
|
jmp .error_open # should not happen
|
||||||
|
|
||||||
|
.over_r1l_greater_r2l: # r1l > r2l
|
||||||
|
cmpl %edx, %eax # overlap if r1l <= r2u
|
||||||
|
je .overlaps
|
||||||
|
jl .overlaps
|
||||||
|
jmp .no_overlap
|
||||||
|
|
||||||
|
.over_r1l_less_r2l: # r1l < r2l
|
||||||
|
cmpl %ebx, %ecx # overlap if r1u >= r2l
|
||||||
|
jg .overlaps
|
||||||
|
je .overlaps
|
||||||
|
jmp .no_overlap
|
||||||
|
|
||||||
|
.overlaps:
|
||||||
|
incl count_overlap
|
||||||
|
|
||||||
|
.no_overlap:
|
||||||
|
|
||||||
|
jmp .loop # repeat the loop
|
||||||
|
|
||||||
|
.done:
|
||||||
|
|
||||||
|
movl count_contained, %edx
|
||||||
|
leaq f_res_cont, %rsi # set print format
|
||||||
|
push %rsi
|
||||||
|
call print_rsi_rdx
|
||||||
|
pop %rsi
|
||||||
|
|
||||||
|
movl count_overlap, %edx
|
||||||
|
leaq f_res_over, %rsi # set print format
|
||||||
|
push %rsi
|
||||||
|
call print_rsi_rdx
|
||||||
|
pop %rsi
|
||||||
|
|
||||||
|
movq $0, %r10 # set exit status
|
||||||
|
jmp .close_file
|
||||||
|
|
||||||
|
.error_open:
|
||||||
|
leaq f_error_open, %rsi # set print format
|
||||||
|
jmp .error
|
||||||
|
.error_read:
|
||||||
|
leaq f_error_read, %rsi # set print format
|
||||||
|
jmp .error
|
||||||
|
.error_match:
|
||||||
|
leaq f_error_match, %rsi # set print format
|
||||||
|
.error:
|
||||||
|
movq %rax, %rdx # print rax
|
||||||
|
# leaq f_error, %rsi # set print format
|
||||||
|
push %rax
|
||||||
|
call print_rsi_rdx
|
||||||
|
pop %rax
|
||||||
|
movq %rax, %r10 # set exit status
|
||||||
|
|
||||||
|
.close_file:
|
||||||
|
# close the file, expect exit status in %r10
|
||||||
|
movq $SYS_CLOSE, %rax # set the number of the "close" syscall to 3
|
||||||
|
movq file, %rdi # move the file descriptor to %rdi
|
||||||
|
syscall
|
||||||
|
|
||||||
|
leave
|
||||||
|
|
||||||
|
movq $SYS_EXIT, %rax
|
||||||
|
movq %r10, %rdi
|
||||||
|
syscall
|
||||||
|
|
||||||
|
|
||||||
|
read_next_line:
|
||||||
|
# read char by char, until newline or eof, return number of chars in rax
|
||||||
|
xorq %r10, %r10 # charcount_contained
|
||||||
|
xorq %rsi, %rsi # make sure rsi is 0
|
||||||
|
xorq %r11, %r11 # make sure r11 is 0
|
||||||
|
.load_char:
|
||||||
|
movq $SYS_READ, %rax # set the number of the "read" syscall
|
||||||
|
movq file, %rdi # move the file descriptor to %rdi
|
||||||
|
leaq current_char, %rsi # move the address of the charbuffer to %rsi
|
||||||
|
movq $1, %rdx # read only 1 char
|
||||||
|
syscall
|
||||||
|
|
||||||
|
jl .error_read
|
||||||
|
|
||||||
|
cmpq $0, %rax # if no char is loaded - eof
|
||||||
|
je .line_complete
|
||||||
|
|
||||||
|
movb current_char, %r11b
|
||||||
|
|
||||||
|
cmpb $'\n', %r11b # if newline
|
||||||
|
je .line_complete
|
||||||
|
|
||||||
|
movb %r11b, line_buffer(,%r10,1) # copy current char into the place at charcount_contained
|
||||||
|
incq %r10 # increment charcount_contained
|
||||||
|
jmp .load_char
|
||||||
|
.line_complete:
|
||||||
|
# null terminate the line
|
||||||
|
leaq line_buffer, %rax
|
||||||
|
movq $0, (%rax,%r10,1)
|
||||||
|
|
||||||
|
movq %r10, %rax # return number of chars loaded in rax
|
||||||
|
ret
|
||||||
|
|
||||||
|
print_rsi_rdx:
|
||||||
|
# print an int with $format, first get the formatted string from sprintf and the do a write syscall to stdout
|
||||||
|
# print the format string in %rsi which contains one int in %rdx
|
||||||
|
push %rdx # save the value
|
||||||
|
|
||||||
|
# Set up the format string and the integer value
|
||||||
|
leaq print_buffer, %rdi # Load the address of the buffer into %rdi
|
||||||
|
# Use sprintf to format the string and the integer value
|
||||||
|
call sprintf # Call the sprintf function
|
||||||
|
# Determine the number of bytes written to the buffer
|
||||||
|
movq %rax, %rdx # Move the number of bytes written to %rdx
|
||||||
|
|
||||||
|
# Set up the write syscall
|
||||||
|
movq $SYS_WRITE, %rax # set the number of the "write" syscall to 4
|
||||||
|
movq $STDOUT, %rdi # move the file descriptor (1 for stdout) to %ebx
|
||||||
|
leaq print_buffer, %rsi
|
||||||
|
syscall
|
||||||
|
|
||||||
|
pop %rdx
|
||||||
|
ret
|
26
4/prompt.md
Normal file
26
4/prompt.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# original prompt
|
||||||
|
consider a text file like this:
|
||||||
|
22-65,22-66
|
||||||
|
91-94,63-91
|
||||||
|
6-88,5-31
|
||||||
|
85-86,64-86
|
||||||
|
40-65,40-65
|
||||||
|
25-82,24-94
|
||||||
|
|
||||||
|
write an gnu-x86 assembly program that:
|
||||||
|
- reads a text file like this line by line and count how often one of the two ranges contains the other.
|
||||||
|
- accepts the filename via command line arg
|
||||||
|
- outputs the result using printf with a suitable string
|
||||||
|
A range r1 contains the other r2 when the r1.lower <= r2.lower and r1.upper >= r2.upper
|
||||||
|
the program needs to output how often that is the case in the entire file
|
||||||
|
|
||||||
|
# add task 2 to c code:
|
||||||
|
can you add another check to the c code:
|
||||||
|
it should now also check if one of the ranges overlaps the other.
|
||||||
|
A range r1 overlaps the other r2 if:
|
||||||
|
- r1.lower == r2.lower
|
||||||
|
- r1.upper == r2.upper
|
||||||
|
- r1.lower > r2.lower and r1.lower <= r2.upper
|
||||||
|
- r1.upper < r1.upper r1.upper >= r2.lower
|
||||||
|
...
|
||||||
|
sorry i failed to mention that the overlaps and containment should be counted separately
|
1000
4/section-pairs.txt
Normal file
1000
4/section-pairs.txt
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user