lucasasecas
lucasasecas

Reputation: 964

division between integers in assembly x86

I'm developing a compiler and I have an issue when I try to generate the assembly code from the following custom language code

b:=-2;
c:=-4;
a:=c/b;

to test this result I use a if condition asking if a == 2 but is not.

this is the piece of code generated from the code avobe

mov ax, 1
mov _a, ax

mov ax, -2
mov _b, ax

mov ax, -4
mov _c, ax


mov dx, 0
mov ax, _c   
mov bx, _b
cmp bx, 0
JE label_div0Excp  // jump to division by 0 message
idiv bx  
mov @aux0, ax

mov ax, @aux0
mov _a, ax

mov ax, _a
cmp ax,2

JNE label_1

invoke MessageBox, NULL, addr _message0, addr _message0, MB_OK  //_message0 say that result == 2

Can enybody help me with that?

thanks

Upvotes: 2

Views: 2791

Answers (2)

I. J. Kennedy
I. J. Kennedy

Reputation: 25809

The IDIV BX instruction does a signed divide of DX:AX by BX. DX:AX is two 16-bit registers glued together and treated as one 32-bit value. You have zeroed DX, but zeroing DX is not sufficient for signed arithmetic. You need to sign extend AX into DX. In other words, if AX is positive, DX should be 0, but if AX is negative, then DX needs to be -1, aka 0xFFFF. Conveniently, there is an instruction that does this sign extension without explicit compares or jumps: CWD (convert word to double).

Try this instead:

mov ax, _c   
cwd              //  <--------------
mov bx, _b
cmp bx, 0
JE label_div0Excp  // jump to division by 0 message
idiv bx

Upvotes: 5

Michael
Michael

Reputation: 58427

IDIV does signed division, so it expects the dividend in DX:AX to be a signed doubleword. Instead of clearing DX prior to the division you should therefore sign-extend AX into DX:AX. This can be done with the CWD instruction.

From Intel's manual: "The CWD instruction can be used to produce a doubleword dividend from a word before word division."

Upvotes: 7

Related Questions