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

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.

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.

Yeah, you always have to do that first:

xor edx,edx

It clears the remainder

xor edx,edx

It clears the remainder

Quote

Performs unsigned Multiplication DX:AX = AX × CX

Yet, DX is not cleared before use.

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

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.

Raymond is correct, clearing DX/EDX would only apply for division. Seeing DX:AX threw me off greatly for some reason :|

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.

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

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

What is the definition of reminder of multiplication?

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

**be a multiplier, but doesn't**

*can***to be. The multiplier just needs to be a valid r/m32 operand.**

*have*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.)

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.

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.

`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.

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.

"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.

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 ;))

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

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

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_register4) 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).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.

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.

I wouldn't do that without first including this instruction:

Xor EDX,EDX

Happy New Year :P

Xor EDX,EDX

Happy New Year :P

a 2-byte NOP :roll:

Happy New Year :P

I sincerely wish you the same.

AND also to everyone else.

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:)

I found this:

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

and this:

from PDF doc: vsl-IA-32.pdf

A good reason to always clear EDX first ;)

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.

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 signicant bits in EDX, and the least signicant

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.

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 signicant bits in EDX, and the least signicant

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 ;)