## ASM Mul and Div

dafhi
Posts: 1329
Joined: Jun 04, 2005 9:51

### ASM Mul and Div

[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 = 1003Denominator = 10Asm  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_], eaxEnd 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_], eaxEnd 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
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 ecxend 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], edxend asmprint bin(2147483647,32)print bin(r,32)asm    mov eax, -2147483648    cdq                   '' extend sign bit of EAX into EDX    mov [r], edxend asmprint bin(-2147483648,32)print bin(r,32)print'====================================================================n = 123d = 10asm    mov ecx, [d]    mov eax, [n]    xor edx, edx    idiv ecx    mov [q], eax    mov [r], edxend asmprint q, rn = -123d = 10asm    mov ecx, [d]    mov eax, [n]    xor edx, edx    idiv ecx    mov [q], eax    mov [r], edxend asmprint q, r'====================================================================n = 123d = 10asm    mov ecx, [d]    mov eax, [n]    cdq    idiv ecx    mov [q], eax    mov [r], edxend asmprint q, rn = -123d = 10asm    mov ecx, [d]    mov eax, [n]    cdq    idiv ecx    mov [q], eax    mov [r], edxend asmprint q, rsleep`