Tetramputechture
Tetramputechture

Reputation: 2921

x86 Assembly (NASM): Floating Point Exception, not dividing by 0?

I'm trying to compute the expression A * B + ( A + B ) / ( A - B ), where A and B are integers input by the user. I'm using the ALong32 library on a linux kernel.

%include "along32.inc"

section .data
msg1    db      'Enter A: ', 0
msg2    db      'Enter B: ', 0
msg3    db      'Result: ' , 0
err     db      'Error: cannot divide by 0', 0
A       resb    4
B       resb    4

section .text

global main

main:
    mov     edx,    msg1
    call    WriteString
    call    ReadInt
    mov     [A],    eax  ; move the input into A

    mov     edx,    msg2
    call    WriteString
    call    ReadInt      ; move the next number into eax

    cmp     eax,    [A]  ; compare A and eax (B)

    je      error        ; if A and B are equal, error

    mov     [B],    eax  ; move eax into B 

    mov     eax,    [A]
    add     eax,    [B]
    mov     ebx,    eax ; ebx = A + B

    mov     eax,    [A]
    sub     eax,    [B] ; eax = A - B

    div     ebx        

    mov     ebx,    eax ; ebx = (A + B) / (A - B)

    mov     ecx,    [B]
    mov     eax,    [A]
    mul     ecx        
    mov     ecx,    eax ; ecx = A * B

    add     eax,    ecx ; eax = A * B + (A + B) / (A - B)

    mov     edx,    msg3
    call    WriteString
    call    WriteInt

    jmp end

error:
    mov     edx,    err
    call    WriteString
    jmp end

end:
    mov     eax,    1
    int     0x80

I feel like I've commented what I'm doing pretty well, but I'll explain what I'm doing more in depth if that's needed.

When I run this code, after I input both numbers, I get a floating point exception, and the program exits.

Why is this happening? I check for division by 0.

Upvotes: 4

Views: 6205

Answers (1)

Sep Roland
Sep Roland

Reputation: 39166

I see 2 problems with your program.

  • The div ebx instruction uses EDX:EAX as the dividend and you fail to set it up. Just insert an xor edx,edx

    xor   edx, edx ; <--------------------------------- Add this !
    div   ebx        
    mov   ebx, eax ; ebx = (A + B) / (A - B)
    
  • After the division you store the quotient in EBX but you never pick it up again to display the result!

    mov   ecx, [B]
    mov   eax, [A]
    mul   ecx
    mov   ecx, eax ; ecx = A * B
    mov   eax, ebx ; <--------------------------------- Add this !
    add   eax, ecx ; eax = A * B + (A + B) / (A - B)
    

The 2nd issue can be solved in a shorter way:

mov   ecx, [B]
mov   eax, [A]
mul   ecx
add   eax, ebx ; eax = A * B + (A + B) / (A - B)

EDIT (late catch, sorry)

I check for division by 0.

A * B + ( A + B ) / ( A - B )

You've based your check on the divider being (A - B) and thus exit if A is equal to B.
Correct, but the program code erroneously calculates (A - B) / (A + B) and so is using (A + B) as the divider!

This is my version of calculating A * B + ( A + B ) / ( A - B ):

mov     ebx, [A]
sub     ebx, [B]    ; EBX = (A - B)
jz      error       ; Guard against division by zero!

mov     eax, [A]
add     eax, [B]    ; EAX = (A + B)

xor     edx, edx    ; EDX:EAX = (A + B)
div     ebx         ; EAX = (A + B) / (A - B)

mov     ebx, [A]
imul    ebx, [B]    ; EBX = A * B

add     eax, ebx    ; EAX = A * B + (A + B) / (A - B)

Upvotes: 7

Related Questions