1

I'm trying to divide 859091 by 11 to obtain the quotient and the remainder, but I'm getting Floating Point Exception on line:

div bx

This is my code for SASM:

%include "io.inc"
section .data
  dividend dd 859091
  divisor  dw 11

section .text
global CMAIN
CMAIN:
  push ebp
  mov ebp, esp

  xor eax, eax
  xor ebx, ebx
  xor edx, edx

  mov ax, word [dividend]
  mov dx, word [dividend + 2]
  mov bx, word [divisor]    
  test bx, bx
  jz exit

  div bx

exit:
  leave
  ret
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • The quotient from dx:ax divided by bx doesn't fit in a 16-bit register (ax is where the quotient will go) so you get an exception. 859091/11=78099. Highest unsigned value that can fit in 16-bits is 65535. Maybe do the division using 32-bit registers? – Michael Petch Mar 24 '17 at 22:24
  • To divide a 32-bit dword in memory by a 16-bit word in memory you could do `movzx ebx, word [divisor]` `test ebx, ebx` `jz exit` `xor edx, edx` `mov eax, [dividend]` `div ebx` – Michael Petch Mar 24 '17 at 22:35
  • 2
    Floating Point Exception (SIGFPE) is a catch all for arithmetic exceptions not just floating point ones. The error is a bit deceiving. It would be better if it was "Arithmetic Exception" IMHO. On the x86 division overflow and divide by zero map to the same hardware exception. The [single unix specification](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/signal.h.html) now says this about SIGFPE: _SIGFPE Erroneous arithmetic operation._ – Michael Petch Mar 24 '17 at 22:57

1 Answers1

1

You're getting divide overflow because the quotient doesn't fit within a 16 bit integer.

You can split up the dividend into upper and lower halves to produce up to a 32 bit quotient and 16 bit remainder. The remainder of dx = 0000 : ax = upper_dividend / divisor becomes the upper half of 2nd dividend for the 2nd division, so the 2nd division calculates dx = remainder : ax = lower_dividend / divisor, neither of which can't overflow because the remainder is strictly less than the divisor. This process can be extended for longer dividends and quotients, one step per word of dividend and quotient, with the remainder of each divide step becoming the upper half of the partial dividend for the next step.

Example using MASM syntax:

dvnd    dd 859091
dvsr    dw 11
;       ...
;       bx:ax will end up = quotient of dvnd/dvsr, dx = remainder
        mov     di,dvsr
        xor     dx,dx
        mov     ax,word ptr dvnd+2      ;ax = upr dvnd
        div     di                      ;ax = upr quot, dx = rmdr
        mov     bx,ax                   ;bx = upr quot
        mov     ax,word ptr dvnd        ;ax = lwr dvnd
        div     di                      ;ax = lwr quot, dx = rmdr

example for quad word:

dvnd    dq 0123456789abcdefh
dvsr    dw 012h
quot    dq 0
rmdr    dw 0
;       ...
        mov     di,dvsr
        xor     dx,dx                   ;dx = 1st upr half dvnd = 0

        mov     ax,word ptr dvnd+6      ;ax = 1st lwr half dvnd
        div     di                      ;ax = 1st quot, dx = rmdr = 2nd upr half dvnd
        mov     word ptr quot+6,ax

        mov     ax,word ptr dvnd+4      ;ax = 2nd lwr half dvnd
        div     di                      ;ax = 2nd quot, dx = rmdr = 3rd upr half dvnd
        mov     word ptr quot+4,ax

        mov     ax,word ptr dvnd+2      ;ax = 3rd lwr half dvnd
        div     di                      ;ax = 3rd quot, dx = rmdr = 4th upr half dvnd
        mov     word ptr quot+2,ax

        mov     ax,word ptr dvnd        ;ax = 4th lwr half dvnd
        div     di                      ;ax = 4th quot, dx = rmdr
        mov     word ptr quot,ax

        mov     rmdr,dx
rcgldr
  • 27,407
  • 3
  • 36
  • 61