0

I decided to make an assembly program to convert a quadword to a base-10 string. I use the standard division by 10 and reversing method. Here's my code for that:

section .text
global  qword_to_string
qword_to_string:
  ; Converts a qword to a null terminated ASCII string.
  ; Input:
  ;   - rdi <== The qword to convert to a string. The function destroys this number.
  ;   - rsi <== A pointer to a buffer to store the string.

  ; This currently only supports non-negative integers.

  test  rdi, rdi ; check if num is 0
  jz    .zero    ; if the number is 0, jump to .zero
  xor   ecx, ecx ; rcx = 0, the 'i' for rdi
  mov   rax, rdi ; dividend
  mov   r8d, 10  ; divisor
.divide:
  div   r8       ; edx = num % 10
  add   edx, 48  ; edx += '0'
  mov   byte [rsi+rcx], dl ; append to string
  inc   rcx      ; i++
  test  rax, rax
  jnz   .divide  ; loop till num != 0
  ; Now reverse the string.
  xor   r8d, r8d ; start = 0
  mov   byte [rsi+rcx+1], 0
  ; Skip this if rcx is 1
  cmp   rcx, 1
  je    .ret
  lea   rdi, [rcx+1]
  shr   rdi, 1   ; rdi = strlen(str) / 2
  dec   rcx
.reverse:
  mov   al, byte [rsi+r8]    ; al = str[start]
  mov   dl, byte [rsi+rcx]   ; dl = str[end]
  ; Swap the values
  mov   byte [rsi+r8], dl
  mov   byte [rsi+rcx], al
  inc   r8
  dec   rcx
  dec   rdi
  jnz   .reverse
.ret:
  ret
.zero:
  mov   byte [rsi], '0'
  mov   byte [rsi+1], 0
  ret

This program does not work, but I can't figure out why. I know that SIGFPE usually means division by 0, so I used a debugger to trace the problem to the first code line in the '.divide' loop (on the second run). On inspecting the registers rax and r8, for a number such as 42, none of them are 0 (4, and 10 respectively)

I tried adding this line

mov   r8d, 10  ; divisor

inside the loop, assuming that it had somehow been overwritten to 0, but that didn't get rid of the error. What's going on here?

avighnac
  • 376
  • 4
  • 12
  • 1
    Recall that `div r8` divides `rdx:rax` by `r8`, not just `rax` by `r8`. Clear `rdx` to make it work. – fuz Nov 09 '22 at 09:55
  • Related: [How do I print an integer in Assembly Level Programming without printf from the c library?](https://stackoverflow.com/a/46301894) - you can sometimes avoid a 2nd loop at all, or at worst the problem is just memmove instead of reverse if you store in descending order from the end of a buffer. – Peter Cordes Nov 09 '22 at 11:57

0 Answers0