and if sizeof(edi*69609)>32bits
then eax will be different? (the only eax)
thank you
Buon Giorno
AFAICT, the only real difference between them is how CF and OF are set
following the multiply, where each sets the flags depending on different
criteria.
EAX and EDX (or RAX and RDX), are the same in both cases.
>
edx:eax = edi * eax
edx:eax = edi * 69609
> and this
> "imul eax, edi, 69609"
eax = edi * 69609
> i think not.
They are not the same. But, eax might be identical.
The first stores unsigned mulitply of 64-bit result into edx:eax pair. The
second stores a signed mulitply 64-bit result truncated to 32-bits in eax.
Also, from the documents, it seems "mul" only does unsigned. "imul" does
the same as "mul" for one-operand forms. For two and three operand forms,
it seems "imul" can do both signed and unsigned correctly since on the low
order result (lower 32-bits of 64-bits) is stored, i.e., the signage is
lost.
> and if sizeof(edi*69609)>32bits
> then eax will be different? (the only eax)
I think eax should be the same according to what I read. edx and the
unsaved upper 32-bits of the other form should be different.
BUT, you shouldn't take my word for it. I've almost never used these
instructions. I've only read the manual...
So, code a loop. Multiply values for both. Compare the values. Are they
the same? Rewrite the loop to use constant 000FF000h instead of 10FE9
(69609). Are they still the same? 0FFFFFFFh? FFFFFFFFh? FA23A5A5h?
0000D912h?
+++++++
This is different also:
"imul edi, 69609"
edi = edi * 69609
This is the same as the original "mul" but with "imul", according to the
doc's:
"mov eax, 69609
imul edi"
edx:eax = edi * eax
edx:eax = edi * 69609
Rod Pemberton
?
Only the one-operand form of "imul" sets a register pair such as EDX:EAX.
The two- and three-operand forms, just sets the chosen destination register,
at least according to the doc's I've got. The OP used the three-operand
form of "imul" in the second example above. I.e., EAX and EDX from the
first example can't be the same as in the second example.
RP
for the one operand forms, they are almost the same, but differ in terms of
CF and OF (typically, we don't care about them in this case anyways).
EDX/RDX should not differ, since the general operation is the same either
way (multiplication is equivalent for signed and unsigned integers).
(note that this does not hold for div and idiv, since division is actually
different between the signed and unsigned cases).
for the 2/3 operand forms, they differ, in that only imul has 2 and 3
operand forms...
>> and if sizeof(edi*69609)>32bits
>> then eax will be different? (the only eax)
>
> I think eax should be the same according to what I read. edx and the
> unsaved upper 32-bits of the other form should be different.
>
I don't think they will be different, but experiment tells all...
yeah, I had missed this, and had been thinking of the single-operand form...
>
> RP
>
>
Thank you
No, they aren't. They are the same only for single-width output (as the
2- and 3-operand operations produce), but not for double-width output.
-hpa
I went and tested, and it seems I was incorrect:
the high order bits do seem to differ...
however, I am at a lost as to the reason (ie: what exactly is going on with
the bits as to cause this effect...).
seems if I convert both to 64 bits first (and do a 64 bit multiply), the
result is the same in both cases.
if I manually sign or zero extend them (my guess as to what was going on),
the results differ, but not in the same way as my prior test (manual
sign/zero extension yeilds a 25% match rate, however my initial tests showed
a 50% match rate).
grr...
It's an artifact of 2's-complement representation.
Let the limb base be H, so 32x32->64 mults would have H=2^32.
Consider the 'pure' base case multiplication to be the unsigned one:
A * B -> C*H+D
Now consider what happens if A is a bit-pattern that would be
considered -ve were registers to have signs. So A really
represents A'=(A-H) numerically.
You want (A-H)*B = A*B - H*B
You have A*B = C*H + D from the base case multiplication above.
So A' * B = C*H + D - H*B = (C-B)*H + D
So there clearly is a difference in the top bits only.
This is why architectures (plural? I've only used 1) which support
multiplication but do not support double-width mutliplication only
offer one single-width muliplication operation. There isn't a 2nd
to offer. And all those that offer double-width offer it in two
flavours, signed and unsigned. (Sometimes this is via 3 opcodes -
one mullo, and two separate mulhis.)
Phil
--
Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1
or, another way to think about it:
AB
CD *
____
__BD
_AD_
_BC_
AC__
so, it is a sort of recursive pattern, starting with single bits and
allowing ever bigger multiplies to be constructed from smaller ones...
but, then they have to confuse me by adding sign extension into the mix...
> Now consider what happens if A is a bit-pattern that would be
> considered -ve were registers to have signs. So A really
> represents A'=(A-H) numerically.
>
> You want (A-H)*B = A*B - H*B
> You have A*B = C*H + D from the base case multiplication above.
> So A' * B = C*H + D - H*B = (C-B)*H + D
>
> So there clearly is a difference in the top bits only.
>
> This is why architectures (plural? I've only used 1) which support
> multiplication but do not support double-width mutliplication only
> offer one single-width muliplication operation. There isn't a 2nd
> to offer. And all those that offer double-width offer it in two
> flavours, signed and unsigned. (Sometimes this is via 3 opcodes -
> one mullo, and two separate mulhis.)
>
and somehow I had never really noticed or thought much about the
difference...
next thought:
why then do assemblers not support multi-argument 'mul' forms and simply
alias them to the imul encodings?...
my guess is that there is maybe no good reason to, it may further confuse
the mul/imul issue, or it would cause an issue WRT disassembly (which form
was intended?), ...
in my case, I just typed what the listings said, and noted it as an oddity
but didn't think too much more about it...
...
> > I went and tested, and it seems I was incorrect:
> > the high order bits do seem to differ...
>
> It's an artifact of 2's-complement representation.
>
> Let the limb base be H, so 32x32->64 mults would have H=2^32.
>
> Consider the 'pure' base case multiplication to be the unsigned one:
> A * B -> C*H+D
>
> Now consider what happens if A is a bit-pattern that would be
> considered -ve were registers to have signs. So A really
> represents A'=(A-H) numerically.
>
> You want (A-H)*B = A*B - H*B
> You have A*B = C*H + D from the base case multiplication above.
> So A' * B = C*H + D - H*B = (C-B)*H + D
>
> So there clearly is a difference in the top bits only.
Thanks for explaining this. Does this mean that
imul ebx
and
mul ebx
sub edx, ebx
have the same effect on the bits in edx and eax? It doesn't seem
intuitive.
James
IFF eax was < 0 before mul, then you'd need to subtract ebx from edx.
Likewise, to make a full correct signed multiplier out of the unsigned
one, after that you'd need to do the same in the other direction:
IFF ebx was < 0 before mul, subtract old eax from edx after mul.
Yes, it doesn't seem very intuitive, but that's how it works. Write a
simple test and compare signed multiplication out of the box with thus
constructed.
Alex