Hi guys.. i need some help here..

I've practically completed the coding..but no matter which ever way i try..i can't get it to print out the values of the multiplication..Can someone review my coding and point out my mistakes ?? thanks a lot..


Posted on 2007-12-30 06:50:05 by zeropulse
Just some quick notes.


LEA AX,PARADATA ;Take first number A in AX register
LEA CX,PARADATA2 ;Take second number B in CX register


LEA = Load Effective Address. It is a confusing instruction, but think of it as a mix of MOV/ADD/MUL in order to quickly calculate semi-complex addresses.

So, essentially, you are multiplying the addresses (pointers) of the two variables instead of the values themselves.


Performs unsigned Multiplication DX:AX = AX CX


Yet, DX is not cleared before use.
Posted on 2007-12-30 11:12:26 by SpooK
Yeah, you always have to do that first:

xor edx,edx

It clears the remainder
Posted on 2007-12-30 12:54:01 by mrgone
Quote
Performs unsigned Multiplication DX:AX = AX CX

Yet, DX is not cleared before use.


Yeah, you always have to do that first:

xor edx,edx

It clears the remainder


There is absolutely no need to clear the DX register before a multiplication. Code such as follows can work just fine:

mov ax,1234
mov dx,5678
mul dx

with the correct answer returned in the DX:AX register pair.
Posted on 2007-12-30 20:19:51 by Raymond
Raymond is correct, clearing DX/EDX would only apply for division. Seeing DX:AX threw me off greatly for some reason :|
Posted on 2007-12-30 20:27:10 by SpooK
clearing DX/EDX would only apply for division


My apology for seeming so picky. But (for newbies) even that statement must not be applied blindly.

- For signed divisions, the DX/EDX register must be sign extended instead of being zeroed.

- Immediately following a multiplication with the result possibly extending into the DX/EDX register (as in the example posted previously), that register must NOT be zeroed if the product must be divided by some other value.
Posted on 2007-12-30 22:24:17 by Raymond
No EBX is the Multiplyer. EDX is the remainder. Always clear EDX

if EDX has value to multiply then:

      mov ebx,05h  ; multiplyer
      mov eax,edx  ; move value to multiply to EAX
      xor edx,edx    ; clear EDX or will be applied toward operation
      mul ebx          ; Answer is EAX:EDX  where EDX is remainder

Posted on 2007-12-31 07:24:16 by mrgone
What is the definition of reminder of multiplication?
Posted on 2007-12-31 12:00:01 by LocoDelAssembly

No EBX is the Multiplyer. EDX is the remainder. Always clear EDX

if EDX has value to multiply then:

      mov ebx,05h  ; multiplyer
      mov eax,edx  ; move value to multiply to EAX
      xor edx,edx    ; clear EDX or will be applied toward operation
      mul ebx          ; Answer is EAX:EDX  where EDX is remainder




Actually, EAX x r/m32 = EDX:EAX, with EDX acting as the high 32-bits and EAX acting as the low 32-bits of a 64-bit number.

Moreover, EBX can be a multiplier, but doesn't have to be. The multiplier just needs to be a valid r/m32 operand.

Raymond is correct, on both accounts, so please yield to his advice ;)

One reason you may want to clear/set EDX, is if you do 16-bit multiplication (result in DX:AX) and you want to use all of EDX after for whatever reason (same concept as MOVZX/MOVSX.)
Posted on 2007-12-31 13:04:35 by SpooK
Ok Ok go ahead get into trouble by not clearing EDX. Go ahead. It's gonna happen.

And yeah "remainder" is division and that will be that part of the result, but EDX will be applied toward your next division or multiplication.

As a general rule of thumb:

Always clear EDX first.
Posted on 2007-12-31 15:07:17 by mrgone
3.2.3  Multiplication Instructions

The 80386 has separate multiply instructions for unsigned and signed
operands. MUL operates on unsigned numbers, while IMUL operates on signed
integers as well as unsigned.

MUL (Unsigned Integer Multiply) performs an unsigned multiplication of the
source operand and the accumulator. If the source is a byte, the processor
multiplies it by the contents of AL and returns the double-length result to
AH and AL. If the source operand is a word, the processor multiplies it by
the contents of AX and returns the double-length result to DX and AX. If the
source operand is a doubleword, the processor multiplies it by the contents
of EAX and returns the 64-bit result in EDX and EAX. MUL sets CF and OF
when the upper half of the result is nonzero; otherwise, they are cleared.

IMUL (Signed Integer Multiply) performs a signed multiplication operation.
IMUL has three variations:

  1.  A one-operand form. The operand may be a byte, word, or doubleword
      located in memory or in a general register. This instruction uses EAX
      and EDX as implicit operands in the same way as the MUL instruction.

  2.  A two-operand form. One of the source operands may be in any general
      register while the other may be either in memory or in a general
      register. The product replaces the general-register operand.

  3.  A three-operand form; two are source and one is the destination
      operand. One of the source operands is an immediate value stored in
      the instruction; the second may be in memory or in any general
      register. The product may be stored in any general register. The
      immediate operand is treated as signed. If the immediate operand is a
      byte, the processor automatically sign-extends it to the size of the
      second operand before performing the multiplication.

The three forms are similar in most respects:

    The length of the product is calculated to twice the length of the
    operands.

    The CF and OF flags are set when significant bits are carried into the
    high-order half of the result. CF and OF are cleared when the
    high-order half of the result is the sign-extension of the low-order
    half.

However, forms 2 and 3 differ in that the product is truncated to the
length of the operands before it is stored in the destination register.
Because of this truncation, OF should be tested to ensure that no
significant bits are lost. (For ways to test OF, refer to the INTO and PUSHF
instructions.)

Forms 2 and 3 of IMUL may also be used with unsigned operands because,
whether the operands are signed or unsigned, the low-order half of the
product is the same.


3.2.4  Division Instructions

The 80386 has separate division instructions for unsigned and signed
operands. DIV operates on unsigned numbers, while IDIV operates on signed
integers as well as unsigned. In either case, an exception (interrupt zero)
occurs if the divisor is zero or if the quotient is too large for AL, AX, or
EAX.

DIV (Unsigned Integer Divide) performs an unsigned division of the
accumulator by the source operand. The dividend (the accumulator) is twice
the size of the divisor (the source operand); the quotient and remainder
have the same size as the divisor, as the following table shows.

Size of Source Operand
      (divisor)            Dividend      Quotient      Remainder

Byte                        AX            AL            AH
Word                        DX:AX          AX            DX
Doubleword                  EDX:EAX        EAX          EDX

Non-integral quotients are truncated to integers toward 0. The remainder is
always less than the divisor. For unsigned byte division, the largest
quotient is 255. For unsigned word division, the largest quotient is 65,535.
For unsigned doubleword division the largest quotient is 2^(32) -1.

IDIV (Signed Integer Divide) performs a signed division of the accumulator
by the source operand. IDIV uses the same registers as the DIV instruction.

For signed byte division, the maximum positive quotient is +127, and the
minimum negative quotient is -128. For signed word division, the maximum
positive quotient is +32,767, and the minimum negative quotient is -32,768.
For signed doubleword division the maximum positive quotient is 2^(31) -1,
the minimum negative quotient is -2^(31). Non-integral results are truncated
towards 0. The remainder always has the same sign as the dividend and is
less than the divisor in magnitude.


That comes from the 80386 manual. What trouble do you see by not clearing EDX before multiplying? MUL/IMUL store something to EDX at most, but never use it to calculate the product (unless it is explicitly specified as operand).

I agree about division, if EDX is not intended to be the high part of the dividend then it must be cleared (or cdq'ed for IDIV) and that if the divisor is too small to produce a quotient that can fit in EAX it will throw an exception. You must also touch EDX if you intend to have modulo 2^32 arithmetic.

PS: Yes, I more or less repeated what Raymond and later SpooK said.
Posted on 2007-12-31 15:37:37 by LocoDelAssembly
How about this part?

"and returns the 64-bit result in EDX and EAX"

or you could take my word for it. Trial & error is the best teacher I admit  :P

Although your research is lacking. You did not find the part that tells you EDX will be applied to next calculation.
Posted on 2007-12-31 16:57:14 by mrgone
Although your research is lacking. You did not find the part that tells you EDX will be applied to next calculation.


What? :|

Remember, I'm trying to convince that EDX takes no part for computing MUL/IMUL despite on DIV/IDIV does ;)

If you meant I'm hiding part of the manual beleave me, I don't, clearing EDX or not makes no difference (except for EFLAGS if you use XOR or SUB to clear) on multiplication (unless EDX is one of the operands but if you clear it then skip the mul/imul and store 0 on dest instead ;))
Posted on 2007-12-31 17:25:45 by LocoDelAssembly
I'm not sure if I understood correctly, but multiplication RETURNS THE RESULT in edx:eax pair. And the result is equal to eax*reg32. There's no edx in the source arguments.
So:
1) Initialize eax to first operand
2) Initialize _ANY_ other GP register (maybe except esp? I don't remember) with second operand
3) perform mul with _the_second_register
4) The result is in edx:eax pair (or, if it didn't overflow, it's in eax and edx is equal to 0)

Why would you have to initialize edx? You have to initialize edx before division, because div divides the contents of edx:eax pair by some other 32-bit register (so woth div, edx hold a part of the source argument - hence, it must be initialized).
Posted on 2007-12-31 17:26:40 by ti_mo_n
mrgone

The architecture of the CPU is such that when it encounters a mul instruction, it send the content of EAX and the content of the other operand to its multiplying unit. That in turn returns the result to the EDX::EAX pair and overwrites whatever was in those two registers.

I have to assume you have used a debugger in the past. Write a short app with only the following instructions and watch what happens with those two registers as you step through the instructions.
mov eax,5
mov edx,7
mul edx

If that small exercise doesn't convince you, I guess nothing will.
Posted on 2007-12-31 20:13:55 by Raymond
  I wouldn't do that without first including this instruction:

Xor EDX,EDX


Happy New Year  :P
Posted on 2007-12-31 20:38:55 by mrgone
a 2-byte NOP  :roll:
Posted on 2007-12-31 20:42:36 by sinsi
Happy New Year  :P


I sincerely wish you the same.
AND also to everyone else.
Posted on 2007-12-31 22:34:43 by Raymond

Happy New Year   :P


I sincerely wish you the same.
AND also to everyone else.



Pardon my boorishness...
Happy New Year to all. It's a hot 38.3C here and the beer is flowing...


I can only think of XOR EDX,EDX before MUL as being as useful as CLC before a CMP - a waste of time (tits...bull... :lol:)
Posted on 2007-12-31 22:55:43 by sinsi
I found this:

These two instructions perform multiplication and division.

Example:


MOV EAX, 10
MOV ECX, 30
MUL ECX
XOR EDX, EDX
MOV ECX, 10
DIV ECX


The examples above first load EAX with 10 and ECX with 30. EAX is always the default multiplicand, and you get to select the other multiplier. When performing a multiplication the answer is in EAX:EDX. It only goes into EDX if the value is larger than the EAX register. When performing a divide you must first clear the EDX register that is what the XOR instruction does by performing an Exclusive OR on itself. After the divide, the answer is in EAX, with the remainder in EDX, if any exists.



here: http://www.gamedev.net/reference/articles/article789.asp

and this:
Integer multiplication and division are a little more awkward, for the reason
that multiplying two moderately large 32-bit numbers often will produce a result
which does not t in a 32-bit register. Thus, the integer multiply and divide
instructions implicitly work with the pair of registers (EDX:EAX), forming a
64-bit value by storing the most signi cant bits in EDX, and the least signi cant
in EAX. The imul (integer multiply) and idiv (integer divide) instructions then
take a single operand which they multiply or divide this 64-bit value by. As we
are only interested in 32-bit precision for our VSL programs, we can happily
use this mechanism to multiply and divide values in EAX without any extra
measures, apart from making sure that the EDX is 0 before doing so.


from PDF doc: vsl-IA-32.pdf

A good reason to always clear EDX first  ;)
Posted on 2008-01-01 10:11:56 by mrgone