ASM Mul and Div

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
dafhi
Posts: 1652
Joined: Jun 04, 2005 9:51

ASM Mul and Div

Post by dafhi »

[2013 Sept 9] - Div code sample updated per MichaelW's correction.

Div and Mul are often confusing for the ASM newb.
I developed these two samples to unconfuse.

Code: Select all

'-----------------'
' ASM DIV EXAMPLE
'-----------------'
Dim As UInteger Numerator, Denominator, edx_, eax_

Numerator = 1003
Denominator = 10

Asm
  mov edi, [Denominator]  'recommended to use edi
  mov eax, [Numerator]   
  cdq                     'extend sign bit of EAX into EDX
  div edi                 'eax by edi
  mov [edx_], edx
  mov [eax_], eax
End Asm

? eax_; "  R: "; edx_

Sleep

Code: Select all

'-----------------'
' ASM MUL EXAMPLE
'-----------------'
Dim As UInteger ThisNum, ByThisNum, edx_, eax_

ThisNum = &hFFFFFFFF        '32 1s multiplied by 2 ..
ByThisNum = 2                '.. the result will carry over into EDX  

Asm
    mov edx, [ByThisNum]    'suggestion: use edx as operand
    mov eax, [ThisNum]
    mul edx
    mov [edx_], edx
    mov [eax_], eax
End Asm

? "edx "; edx_; " :eax "; eax_

Sleep 
Last edited by dafhi on Sep 07, 2013 19:51, edited 2 times in total.
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Post by MichaelW »

You neglected to explain why you zero EDX before you do the division, and to provide an example of signed division.

When the result for a quadword/doubleword division will not fit into EAX the processor generates an exception. For a quadword/doubleword unsigned division, zeroing EDX effectively limits the dividend to the 32-bit value in EAX, ensuring that the quotient will always fit into EAX, regardless of the divisor. It is possible to do quadword/doubleword unsigned divisions where the dividend is a full 64-bit value, without the processor generating an exception, provided that the value in EDX is less than the value of the divisor. For example, this code will not generate an exception, and will produce the correct result:

Code: Select all

asm
    mov edx, 0xfffffffe
    mov eax, 0xffffffff
    mov ecx, 0xffffffff
    div ecx
end asm
Note that for a quadword/doubleword signed division, zeroing EDX will not produce the correct result when the value in EAX is negative. To get the correct result, regardless of the sign of the divisor and dividend, you need to sign extend the EAX value into EDX, using the CDQ instruction provided for this purpose.

Code: Select all

'====================================================================
dim as integer n, d, q, r
'====================================================================

asm
    mov eax, 2147483647
    cdq                   '' extend sign bit of EAX into EDX
    mov [r], edx
end asm
print bin(2147483647,32)
print bin(r,32)

asm
    mov eax, -2147483648
    cdq                   '' extend sign bit of EAX into EDX
    mov [r], edx
end asm
print bin(-2147483648,32)
print bin(r,32)
print

'====================================================================

n = 123
d = 10
asm
    mov ecx, [d]
    mov eax, [n]
    xor edx, edx
    idiv ecx
    mov [q], eax
    mov [r], edx
end asm
print q, r

n = -123
d = 10
asm
    mov ecx, [d]
    mov eax, [n]
    xor edx, edx
    idiv ecx
    mov [q], eax
    mov [r], edx
end asm
print q, r

'====================================================================

n = 123
d = 10
asm
    mov ecx, [d]
    mov eax, [n]
    cdq
    idiv ecx
    mov [q], eax
    mov [r], edx
end asm
print q, r

n = -123
d = 10
asm
    mov ecx, [d]
    mov eax, [n]
    cdq
    idiv ecx
    mov [q], eax
    mov [r], edx
end asm
print q, r

sleep

Post Reply