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?