MUL instruction doesn't support an immediate value
Asked Answered
E

6

10

I've read a few tutorials and examples, but I cannot wrap my head around how the MUL instruction works. I've used ADD and SUB without problems. So apparently this instruction multiplies its operand by the value in a register.

What register (eax, ebp, esp, etc.) is multiplied by the first operand? And what register is the result stored in, so I can move it to the stack? Sorry, I'm just learning x86 assembly.

When I try to compile this line...

mul     9

I get, Error: suffix or operands invalid for 'mul'. Can anyone help me out?

    global  main
    main:
    push    ebp
    movl    ebp, esp
    sub     esp, byte +8
    mov     eax, 7
    mul     9
    mov     [esp], eax
    call    _putchar
    xor     eax, eax
    leave
    ret
Elsyelton answered 25/12, 2010 at 4:9 Comment(0)
B
13

MUL can't use an immediate value as an argument. You have to load '9' into a register, say,

 movl    $7, %eax
 movl    $9, %ecx
 mull    %ecx

which would multiply eax by ecx and store the 64-bit product in edx:eax.

There's a good comprehensive reference of x86 assembly instructions on the Intel web site, see here

http://www.intel.com/Assets/PDF/manual/253666.pdf

http://www.intel.com/Assets/PDF/manual/253667.pdf

But that is probably far more information that you need now.

Bealle answered 25/12, 2010 at 5:50 Comment(1)
The OP isn't using the EDX high-half result. You should at least mention that x86 does have immediate multiply (added sometime before 386, so 32-bit code can always count on it). imul $9, %eax, %eax. Or better for power-of-2 + 1 lea (%eax, %eax, 8), %eax.Wetterhorn
E
6

If you look at MUL format table you'll notice that it only accepts one register parameter. However turn over to IMUL and you'll see there are many forms of it that accept an immediate

6B /r ib         IMUL r16, r/m16, imm8   word register ← r/m16 ∗ sign-extended immediate byte.
6B /r ib         IMUL r32, r/m32, imm8   doubleword register ← r/m32 ∗ sign-extended immediate byte.
REX.W + 6B /r ib IMUL r64, r/m64, imm8   Quadword register ← r/m64 ∗ sign-extended immediate byte.
69 /r iw         IMUL r16, r/m16, imm16  word register ← r/m16 ∗ immediate word.
69 /r id         IMUL r32, r/m32, imm32  doubleword register ← r/m32 ∗ immediate doubleword.
REX.W + 69 /r id IMUL r64, r/m64, imm32  Quadword register ← r/m64 ∗ immediate doubleword.

So to multiply eax by 9 you can do like this

mov eax, 7
imul eax, eax, 9 ; eax = eax*9

Look closer and you can also observe that those versions are non-widening. In fact nowadays imul is exclusively used for almost all multiplications, because non-widening multiplication is the same for signed and unsigned values and multiplication in high-level languages are non-widening (i.e. the output type and input operands' types are the same) unless you cast the operands to a wider type. As a result, modern x86 CPUs are often optimized for imul and it also has many more forms than mul

Exigent answered 29/1, 2019 at 4:8 Comment(1)
In this power-of-2 + 1 case, lea eax, [eax + eax*8] is even better than an immediate imul. But yes, +1, I can't believe all these answers suggesting mov into a register when the OP clearly isn't using the high half result.Wetterhorn
M
3

I'm not an expert but I think your problem is that mul will not accept a direct operand in your case the decimal constant 9 so try putting 9 in let's say register bx like this:

mov bx, 9
mul bx

To answer your question about mul in general it looks like this:

mul     reg/memory

and does that:

dx:ax := ax*reg/mem

So with words it expects a single operand which should either be a register or a memory location (storing the value to be multiplied so essentially a variable) and multiplies it by ax and then depending on how long the register/memory (so the operand you gave) was stores it in either ax or dx:ax or edx:eax

I hope I helped you there pal!

Mainstream answered 19/5, 2011 at 20:59 Comment(0)
T
2

http://siyobik.info/index.php?module=x86&id=210

the destination operand is an implied operand located in register AL, AX or EAX (depending on the size of the operand); the source operand is located in a general-purpose register or a memory location

The result is stored in register AX, register pair DX:AX, or register pair EDX:EAX (depending on the operand size), with the high-order bits of the product contained in register AH, DX, or EDX, respectively. If the high-order bits of the product are 0, the CF and OF flags are cleared; otherwise, the flags are set.

In your source it should be mul instead of mull

Toothsome answered 25/12, 2010 at 4:12 Comment(0)
M
0

I'll give you a link to my favorite easy-to-read, but complete, reference for x86: http://www.ousob.com/ng/iapx86/ng1840d.php

Mephitis answered 25/12, 2010 at 6:4 Comment(1)
this doesn't answer the question in anyway. And link-only answers are discouragedExigent
D
0

How to read on the Intel manual to see that it is not possible

First download the Intel manual. Current download page is: http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html but just Google "intel x86 manual" as that is bound to change.

What we want is the Combined Volume 2 Instruction Set Reference A-Z which contains all instructions.

In that manual, find the documentation for DIV. We see that DIV has the following forms under the Instruction column:

  • DIV r/m8
  • DIV r/m16
  • DIV r/m32
  • DIV r/m64

r/mX means that it can take a register or memory location of size X.

Therefore, there is no form that takes immX, which is an immediate value, or literal.

So it is not possible to encode that instruction to the processor, and now we know that the only way to go is pass through registers or memory.

Registers are faster, so we use them of course if possible.

Droll answered 20/9, 2015 at 21:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.