Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MUL instruction doesn't support an immediate value

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
like image 927
Tanner Babcock Avatar asked Dec 25 '10 04:12

Tanner Babcock


4 Answers

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

like image 155
phuclv Avatar answered Oct 19 '22 02:10

phuclv


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

like image 40
Earlz Avatar answered Oct 19 '22 03:10

Earlz


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

like image 26
Madhur Ahuja Avatar answered Oct 19 '22 02:10

Madhur Ahuja


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.

like image 44
Eugene Smith Avatar answered Oct 19 '22 03:10

Eugene Smith