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
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
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
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With