295 lines
11 KiB
ArmAsm
295 lines
11 KiB
ArmAsm
|
# 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
|