Author Topic: Multiply and store result in EAX  (Read 15776 times)

Offline mik3ca

  • Jr. Member
  • *
  • Posts: 30
Multiply and store result in EAX
« on: January 13, 2021, 05:16:08 AM »
This is probably simple for everyone but me, but I'm trying to multiply EAX by the contents of a memory location and storing the result in EAX using the following code fragments:

Code: [Select]
   
    mul EAX,[ES:DI+itemoffset]

Code: [Select]
    mov ECX,[ES:DI+itemoffset]
    mul EAX,ECX

but the compiler always complains on the multiply line with "invalid combination of opcode and operands"

How would I fix this? Do I remove the EAX in mul and assume the system knows that EAX is the other register to multiply with and store the result to?

Offline debs3759

  • Global Moderator
  • Full Member
  • *****
  • Posts: 224
  • Country: gb
    • GPUZoo
Re: Multiply and store result in EAX
« Reply #1 on: January 13, 2021, 05:33:15 AM »
If using the contents of a memory address, you need to specify the operand size,  so, for example:

Code: [Select]
    mul EAX,word [ES:DI+itemoffset]
or

Code: [Select]
    mov ECX,word [ES:DI+itemoffset]
    mul EAX,ECX

(obviously, this can also be byte or dword)

nasm doesn't make assumptions about the operand size in most instructions.

I can't remember offhand whether you need to use EDI for the address when the destination is 32-bits. You may be OK, but hopefully Franf or Frederic can clarify that. It's been a while since I actually used nasm, so I'm a little rusty on some stuff.
« Last Edit: January 13, 2021, 05:37:48 AM by debs3759 »
My graphics card database: www.gpuzoo.com

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 373
  • Country: br
Re: Multiply and store result in EAX
« Reply #2 on: January 13, 2021, 03:52:47 PM »
mul instruction don't give you the means to multiply ANY register, except EAX (or derivatives) by its operand... The result will always be in the pair EDX:EAX (or derivatives).

So, if you want to use mul to multiply ECX by the contents of memory (which, both must be the same size), you need to do:

Code: [Select]
  mov eax,ecx
  mul [es:edi+offset]  ; 32 bits effective address.
  ; result is EDX:EAX = EAX * DWORD [ES:EDI+offset]

There is a more flexible multiplication instruction: imul, which takes the signal of the operands in account. This instruction can be used as MUL (using EAX as default source operand and results in EDX:EAX) or when using 2 operands, multiply the source by the second operand and storing the result in the source... There is a third option: the first operand can be the result of the second operand multiplied by a CONSTANT as a third operand:
Code: [Select]
  imul ebx      ; EDX:EAX = EAX * EBX
  imul ebx,ecx ; EBX = EBX * ECX
  imul ebx,ecx,3 ; EBX = ECX * 3
But it is important to notice IMUL will consider the values as SIGNED.

Offline mik3ca

  • Jr. Member
  • *
  • Posts: 30
Re: Multiply and store result in EAX
« Reply #3 on: January 13, 2021, 04:19:06 PM »
Code: [Select]
    mul EAX,word [ES:DI+itemoffset]or
Code: [Select]
    mov ECX,word [ES:DI+itemoffset]
    mul EAX,ECX

Unfortunately those won't work.

mul instruction don't give you the means to multiply ANY register, except EAX (or derivatives) by its operand... The result will always be in the pair EDX:EAX (or derivatives).
...

Code: [Select]
  mov eax,ecx
  mul [es:edi+offset]  ; 32 bits effective address.
  ; result is EDX:EAX = EAX * DWORD [ES:EDI+offset]

Ok, It turns out the best answer in my case is:

Code: [Select]
  mul  dword[es:edi+offset]  ; 32 bits effective address.

Thanks for the offer of imul but I don't want to reserve the MSB strictly for signing because that can also limit the values I can use. Like for example, If I had register AX as a signed register, then my positive values can only go from 0-7FFFh (0 - 32767) where as if it is unsigned, then my positive values can go from 0-FFFFh (0 - 65536)

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 373
  • Country: br
Re: Multiply and store result in EAX
« Reply #4 on: January 13, 2021, 06:26:33 PM »
You can use E?? registers in real mode. If your values are unsigned 16 bits values you can use 32 bits and IMUL instruction (the MSB will always be zero).

In the extreme case, multiplying 0xFFFF to 0xFFFF you'll get 0xFFFE0001, which will be an overflow if you get only the lower 16 bits, but this will happen with MUL as well.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Multiply and store result in EAX
« Reply #5 on: January 13, 2021, 10:14:37 PM »
Hi mlk3ca,

It looks to me like you've got it figured out. You can use imul, but there''s nothing wrong  with mul.

There was, at one time, an instruction set reference in the Nasm manual. This is what's left if it:

http://home.myfairpoint.net/fbkotler/nasmdocr.html

It is badly outdated and still has a few errors. You should have seen it before Debs (and Yuri  and I) worked in it! For example, the description of "push" and "pop" were exactly the same! Debs is a "Nasm Developer" too, but in this case she's got it wrong. If you use a register. Nasm knows the size. I think using "word" with "ecx" would be an error. Try it. Don't be afraid to try stuff! You're doing great!

Best,
Frank