I am writing a simple sprintf() function in assembly. I seem to be unable to find out why my code gets an arithmetic exeption when I try dividing by $0xA. It does not happen if I change everything to their extended versions like %EAX.
.data
divisor: .byte 0xA
.text
.globl sprinter
sprinter:
.
.
.
add_unsigned_decimal_number:
pushl (%ebx)
call uint_inner
jmp next_char
uint_inner:
xor %eax, %eax
xor %edx, %edx
movw 4(%esp), %dx #Move first half of the parameter into %dx
movw 6(%esp), %ax #Move second half into %ax
#################Here it crashes###################
divw divisor #Divide by 10 (0xA)
###################################################
cmpw $0x0, %ax
je return #return if equal
pushw %dx #Save the result
pushw %ax #add a parameter for the next call
call uint_inner
pop %eax #to remove the top layer
pop %eax #To extract the required layer
addb $48, %al #To make it into a number symbol
movb %al, (%ebx) #Add the number
ret
Thank you so much in advance for your help. Please keep in mind that this is a school problem so try to explain and not just give working code.
divw
produces 16 bit quotient, and you get an exception if the result doesn't fit. Since you divide by 10, if the high word is not zero you are guaranteed to have an overflow. By the way, the divisor
should be declared as .short
.
Given that you clearly code for 32 bit, you should just use the 32 bit division. In that case the divisor should be an .int
and you should load the dividend into eax
. Don't forget to zero edx
which holds the top 32 bits of the dividend.