GAS (AT&T) ASM - Value at one address change after changing value at another address, why?

33 Views Asked by At

This function take an array of (x,y) coordinates, each number is a byte unsigned int, but only between the size 0-32767. The function converts thees numbers to ascii and stores it in another buffer. The format is "x \t y \n". The function starts for the end of the coordinate array and works backwards to the start. **The function works until the last number. **

Test input (in base 10) 2084, 3146, 30093, 9127

When loading the 4, 8 byte unsigned int, where first number is stored at %rdi, the value at (%rdi) is 2084 (translated from base 16) this is confirmed by using GDB at the line : movq (%rdi), %r12 # test to see what is stored at (%rdi) But after movb $10, (%rcx) # insert newline the value at (%rdi) is changed, and I don't get why.

The function:

.section .text
.globl ints_to_ascii # void ints_to_ascii()
#   %rdi = Array start address 
#   %rsi = Data length
#   %rdx = print buffer address
#   %rcx = print buffer length

ints_to_ascii:

    push %rbp
    movq %rsp, %rbp

    addq %rdi, %rsi     # make rsi point at end of coordinate array, used to get 8 byte numbers

    addq %rdx, %rcx     # make rcx point at end of buffer
    movq $10, %r10      # Divisor (10 for decimal)

    
.LparseData_coordinateLoop:
    
    cmpq %rdi, %rsi 
    jle .LparseData_coordinateLoop_end
    
    dec %rcx           # Move the pointer one position to the left
    movq (%rdi), %r12   # test to see what is stored at (%rdi)
    movb $10, (%rcx)    # insert newline

    movq (%rdi), %r12   # test to see what is stored at (%rdi)
    subq $8, %rsi      # point to the next place for a number
    movq (%rsi), %rax
    
convert_y_loop:

    xorq %rdx, %rdx        # Clear the remainder
    divq %r10              # Divide RAX by 10, result in RAX, remainder in RDX
    
    dec %rcx           # Move the pointer one position to the left
    mov %dl, (%rcx)  # Store the ASCII digit in the buffer
    addq $48, (%rcx)    #add 48 to convert to ascii

    cmpq $0, %rax       # Check if quotient is zero
    jne convert_y_loop       # If not zero, continue the loop

convert_y_loop_end:

    dec %rcx           # Move the pointer one position to the left
    movb $9, (%rcx)     # insert tab

    subq $8, %rsi      # point to the next place for a number
    movq (%rsi), %rax

convert_x_loop:
    xorq %rdx, %rdx        # Clear the remainder
    divq %r10              # Divide RAX by 10, result in RAX, remainder in RDX

    dec %rcx           # Move the pointer one position to the left
    mov %dl, (%rcx)       # Store the ASCII character
    addq $48, (%rcx)    #add 48 to convert to ascii

    cmpq $0, %rax       # Check if quotient is zero
    jne convert_x_loop       # If not zero, continue the loop

convert_x_loop_end:

    jmp .LparseData_coordinateLoop
.LparseData_coordinateLoop_end:

    movq %rbp, %rsp
    pop %rbp
    ret

I have tried using GDB and have inserted movq (%rdi), %r12 # test to see what is stored at (%rdi) multiple time to see exactly where (%rdi)changed.

1

There are 1 best solutions below

2
Gusbc On

Thank you to @Jester. There was a bug in the "main" file, that made the buffers overlap by one byte. The buffers were right after each ofter in memory, and another function changed the value describing the length of the first buffer by adding one to it. This caused an overlap of the to buffers by one byte.