From 2e39f481369d708cf2c723136c3bf4c765d6c994 Mon Sep 17 00:00:00 2001 From: mithe24 Date: Sun, 26 Oct 2025 15:38:43 +0100 Subject: fix(printing & int2str): Better printing and int to string func --- src/array_maker.s | 2 +- src/lib/int2str.s | 83 +++++++++++++++++++++++++++ src/lib/tub2tsv.s | 86 ++++++++++++++++++++++++++++ src/main.s | 11 +++- src/outputGenerator.s | 153 -------------------------------------------------- 5 files changed, 179 insertions(+), 156 deletions(-) create mode 100644 src/lib/int2str.s create mode 100644 src/lib/tub2tsv.s delete mode 100644 src/outputGenerator.s 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 - - -- cgit v1.2.3-70-g09d2