aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormithe24 <mithe24@student.sdu.dk>2025-10-26 15:38:43 +0100
committermithe24 <mithe24@student.sdu.dk>2025-10-29 13:49:57 +0100
commit2e39f481369d708cf2c723136c3bf4c765d6c994 (patch)
tree0e5d7b8588ad8d31875725cfabbc17d876037038
parent88d4c92a5a757ed4ee88373e9ae53bfe27041e7f (diff)
downloadsorter-2e39f481369d708cf2c723136c3bf4c765d6c994.tar.gz
sorter-2e39f481369d708cf2c723136c3bf4c765d6c994.zip
fix(printing & int2str): Better printing and int to string func
Diffstat (limited to '')
-rw-r--r--src/array_maker.s2
-rw-r--r--src/lib/int2str.s83
-rw-r--r--src/lib/tub2tsv.s86
-rw-r--r--src/main.s11
-rw-r--r--src/outputGenerator.s153
5 files changed, 179 insertions, 156 deletions
diff --git a/src/array_maker.s b/src/array_maker.s
index 7586d84..b0809ca 100644
--- a/src/array_maker.s
+++ b/src/array_maker.s
@@ -127,7 +127,7 @@ end:
# --------------------------------------------
.globl create_file_buffer
.type create_file_buffer, @function
- create_file_buffer:
+create_file_buffer:
# save
push %r15
push %r14
diff --git a/src/lib/int2str.s b/src/lib/int2str.s
new file mode 100644
index 0000000..82a2aaa
--- /dev/null
+++ b/src/lib/int2str.s
@@ -0,0 +1,83 @@
+# --------------------------------------------
+# FUNCTION: int2str
+# PURPOSE : Convert a 64 bit integer into ascii
+# into ASCII encoding
+# INPUTS : rdi = 64 bit integer
+# rsi = address of buffer
+# OUTPUTS : rax = address of string (points into the provided buffer)
+# rdx = length of string
+# CLOBBERS:
+# --------------------------------------------
+.section .text
+.globl int2str
+.type int2str, @function
+int2str:
+ pushq %rbx # save callee-saved register
+
+ movq %rdi, %rax # integer to convert
+ movq %rsi, %rbx # buffer base
+ movq %rsi, %r9 # save original buffer
+ leaq 19(%rbx), %r8 # pointer to last char position
+ movq $10, %rcx # divisor
+ xorq %r10, %r10 # sign flag (0 = positive)
+
+ # handle sign
+ testq %rax, %rax
+ jns .convert
+ negq %rax # if the number negative we negate it and
+ movq $1, %r10 # set sign flag
+
+.convert:
+ testq %rax, %rax
+ jnz .loop # check if the number is 0
+
+ # if the number is 0, we just set the char to '0', and length to 0.
+ movb $'0', (%r8)
+ movq %r8, %rax
+ movq $1, %rdx
+ jmp .shift_left # shift the result leftmust
+
+.loop:
+ xorq %rdx, %rdx # clear rdx before division
+ divq %rcx # divide rdx:rax by 10
+ addb $'0', %dl # add ASCII base
+ movb %dl, (%r8) # move digit into buffer
+ decq %r8 # decrement pointer
+ testq %rax, %rax # while quotient is not 0, loop
+ jnz .loop
+
+ incq %r8 # move back to first digit
+
+ # add '-' if negative
+ testq %r10, %r10
+ jns .calc_len
+ decq %r8
+ movb $'-', (%r8)
+
+.calc_len: # count length of the string
+ movq %r8, %rax # string start
+ leaq 20(%r9), %rdx # end of buffer
+ subq %rax, %rdx # string length
+
+.shift_left:
+ # shift string to leftmost in buffer if not already there
+ cmpq %rax, %r9
+ je .done # already leftmost
+ movq %rdx, %rcx # rcx = length of string
+ movq %rax, %rsi # rsi = source :: start of string
+ movq %r9, %rdi # rdi = destination :: original buff start
+ rep movsb # copy string left
+ # Found this online. It's a way to copy down values in memoery.
+ # movbs = Move String Byte..
+ # It copies 1 byte from memoery to memoery and
+ # incrementing destination and incrementing source.
+ # Source :: %rsi
+ # Dest :: %rdi
+ # rep = repeat wow.
+ # It's a prefix that repeats an isntructution rcx times
+ # https://stackoverflow.com/questions/27804852/assembly-rep-movs-mechanism
+ movq %r9, %rax # return pointer to start
+
+.done:
+ popq %rbx
+ ret
diff --git a/src/lib/tub2tsv.s b/src/lib/tub2tsv.s
new file mode 100644
index 0000000..558c51e
--- /dev/null
+++ b/src/lib/tub2tsv.s
@@ -0,0 +1,86 @@
+# --------------------------------------------
+# FUNCTION: tub2tsv
+# PURPOSE : take a buffer of coordinates
+# and print each coordinate on a line
+# INPUTS : rdi = pointer to buffer,
+# rsi = number of coordinates
+# OUTPUTS : rax = address to string of tab seperated values
+# rdx = number of bytes
+# CLOBBERS:
+# --------------------------------------------
+.section .text
+.globl tub2tsv
+.type tub2tsv, @function
+tub2tsv:
+ # save callee-saved registers
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+ pushq %rbx
+
+ movq %rdi, %r12 # r12 = address to array of coordinates
+ movq %rsi, %r13 # r13 = count of coordinates
+
+ # allocate memory based on number of coordinates and max integer size
+ # maybe allocate in chunks might be better, as to waste less memory
+ movq %rsi, %rdi
+ imulq $42, %rdi # 20 bytes for each coordindate + tab
+ incq %rdi # +1 byte for null terminator
+ call allocate
+ movq %rax, %r14 # r14 = output buffer start
+ movq %rax, %r15 # r15 = current write pos
+
+ xorq %rbx, %rbx # loop counter
+
+.tub2tsv_loop:
+ cmpq %r13, %rbx # if loop counter >= count of coordinates
+ jge .tub2tsv_exit # done
+
+ # get addrss to current tuple
+ movq (%r12, %rbx, 8), %rdi # rdi = array[loop counter]
+ pushq %rdi # save pointer to current tuple
+
+ # convert first integer to ASCII
+ movq (%rdi), %rdi # rdi = first int
+ movq %r15, %rsi # rsi = current write pos
+ call int2str # rax = string start, rdx = length
+ addq %rdx, %r15 # advance write pos with num bytes written
+
+ # write tab
+ movb $'\t', (%r15)
+ incq %r15
+
+ # convert second integer to ASCII
+ popq %rdi # restore pointer to tuple
+ movq 8(%rdi), %rdi # rdi = second int
+ movq %r15, %rsi # rsi = current write pos
+ call int2str # rax = string start, rdx = length
+ addq %rdx, %r15 # advance write pos with num bytes written
+
+ # write newline
+ movb $'\n', (%r15)
+ incq %r15
+
+ incq %rbx
+ jmp .tub2tsv_loop
+
+.tub2tsv_exit:
+ # add null terminator
+ movb $0, (%r15)
+
+ # move address to output register
+ movq %r14, %rax
+
+ # return length in rdx
+ movq %r15, %rdx
+ subq %r14, %rdx
+
+ # restore callee-saved registers
+ popq %rbx
+ popq %r15
+ popq %r14
+ popq %r13
+ popq %r12
+
+ ret
diff --git a/src/main.s b/src/main.s
index 318bb02..196515f 100644
--- a/src/main.s
+++ b/src/main.s
@@ -19,10 +19,17 @@ _start:
movq $1, %rdx # Sort by key 1
call qsort # Sort the array
- # Print array
+ # Convert array to string
+ # in tsv format
movq %rax, %rdi # Select the pointer to the array
movq %r15, %rsi # Select length of array
- call print_buffer # Print array
+ call tub2tsv # Print array
+
+ # print string to stdout
+ movq %rax, %rsi
+ movq $1, %rax
+ movq $1, %rdi
+ syscall
# Exit
movq $60, %rax
diff --git a/src/outputGenerator.s b/src/outputGenerator.s
deleted file mode 100644
index 1e9224b..0000000
--- a/src/outputGenerator.s
+++ /dev/null
@@ -1,153 +0,0 @@
-.section .data
-# This buffer holds the ASCII code for tab and newline
-newline:
- .byte 10 # '\n'
-
-tab:
- .byte 9 # '\tab'
-
-.section .text
-# --------------------------------------------
-# FUNCTION: print_tab
-# PURPOSE : print a tab character ('\t')
-# INPUTS :
-# OUTPUTS :
-# CLOBBERS: rax, rdi, rsi, rdx
-# --------------------------------------------
-.globl print_tab
-.type print_tab, @function
-print_tab:
- movq $1, %rax # write
- movq $1, %rdi # stdout
- movq $tab, %rsi # load tab character
- movq $1, %rdx # 1 byte
- syscall
- ret
-
-
-# --------------------------------------------
-# FUNCTION: print_newline
-# PURPOSE : print a newline character ('\n')
-# INPUTS :
-# OUTPUTS :
-# CLOBBERS: rax, rdi, rsi, rdx
-# --------------------------------------------
-.globl print_newline
-.type print_newline, @function
-print_newline:
- movq $1, %rax # write
- movq $1, %rdi # stdout
- movq $newline, %rsi # load newline character
- movq $1, %rdx # 1 byte
- syscall
- ret
-
-
-# --------------------------------------------
-# FUNCTION: print_buffer
-# PURPOSE : take a buffer of coordinates and print each coordinate on a line
-# INPUTS : rdi = pointer to buffer, rsi = number of coordinates
-# OUTPUTS :
-# CLOBBERS: rax, rdi,
-# --------------------------------------------
-.globl print_buffer
-.type print_buffer, @function
-print_buffer:
- cmpq $0, %rsi
- jle done # if n > 0 print_coordinate
-
- movq %rdi, %rdx # save pointer, rdi is used for print_num
-
-loop:
- movq (%rdx), %r15 # Pointer element
-
- # print x and tab
- movq (%r15), %rdi # Get 1st number from element
- call print_num # Print it
- push %rdx # save pointer
- push %rsi # save n
- call print_tab
- pop %rsi # retrieve n
- pop %rdx # retrieve pointer
-
- # print y and newline
- movq 8(%r15), %rdi # Get the 2nd number
- call print_num # Print it
- push %rdx # save pointer
- push %rsi # save n
- call print_newline
- pop %rsi # retrieve n
- pop %rdx # retrieve pointer
-
-
- # move to next coordinate and decq n
- addq $8, %rdx
- decq %rsi
-
- cmpq $0, %rsi
- jg loop
-
-done:
- ret
-
-
-# --------------------------------------------
-# FUNCTION: print_num
-# PURPOSE : print rdi as an unsigned integer
-# INPUTS : rdi
-# OUTPUTS :
-# CLOBBERS:
-# Note: the function does not follow the ordinary calling convention,
-# but restores all registers.
-# --------------------------------------------
-
-.type print_num, @function
-.globl print_num
-print_num:
- push %rbp
- movq %rsp, %rbp
-
- # save
- push %rax
- push %rdi
- push %rsi
- push %rdx
- push %rcx
- push %r8
- push %r9
-
- movq %rdi, %rax # arg
- movq $0, %r9 # digit count
-.Lprint_num_convertLoop:
- movq $0, %rdx
- movq $10, %rcx
- idivq %rcx
- addq $48, %rdx # '0' is 48
- push %rdx
- addq $1, %r9
- cmpq $0, %rax
- jne .Lprint_num_convertLoop
-.Lprint_num_printLoop:
- movq $1, %rax # sys_write
- movq $1, %rdi # stdout
- movq %rsp, %rsi # buf
- movq $1, %rdx # len
- syscall
- addq $8, %rsp
- addq $-1, %r9
- jne .Lprint_num_printLoop
-
- # restore
- pop %r9
- pop %r8
- pop %rcx
- pop %rdx
- pop %rsi
- pop %rdi
- pop %rax
-
- movq %rbp, %rsp
- pop %rbp
- ret
-
-