Search code examples
assemblyatt

Why do I get an arithmetic exception when using divw?


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.


Solution

  • 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.