Some instructions act on registers or even memory locations that are not stated in a list of operands. These instruction does do in fact have operands, but they represent assumptions made by the instruction. Implicit operands dose not change and cannot be changed. Most of the instruction that have implicit opeands dose have explicit operands as well.
The MUL
instruction multiplies two values and returns the product. However, multiplication has a special problem: It generates output values that are often hugely lager than the input values. think of 0xffffffff * 0xffffffff.
So to solve this problem the MUL
instructison uses an implicit operands to store the product: by using two registers to hold our product.
Note
The implicit operands for MUL
instruction depend on the explicit operand (size)
Instruction | Explicit operand (a.k.a. factor 1) | Implicit operand (a.k.a factor 2) | Implicit operand (a.k.a product) |
---|---|---|---|
MUL r/m8 | r/m8 | AL | AX |
MUL r/m16 | r/m16 | AX | DX:AX |
MUL r/m32 | r/m32 | EAX | EDX:EAX |
MUL r/m64 | r/m64 | RAX | RDX:RAX |
The first factor is given in the single explicit operand, which can be either in a register or in a memory location. The second foctor is implicit and always in the
A
general-purpose register appropriate to the size of the first operand.
Note
DX
registers are drafted to hold the high-ordr portion of the product.
I.e. if you multiply two 16-bit values and the product is 0x2A46FH, register AX
will contain 0x456FH, and DX
will contain 0x2AH.
Note
Even in cases when the product is small enough to fit in entirely in the first emplicit operand(A
GPR), the high-orrder register whether AH
, DX
, EDX
, or RDX
) is zerod out. So you can't use them even if you'r sure that MUL
instruction will not need them.
mov bl, 21
mov al, 2
mul bl ; al = 0x2a
Note
You cannot use the immediate vales as an operand.
The MUL
instruction will sets the Carry flag CF when the value of the product overflowss the low-order register.so you can ignore the high-order register when CF
isn't set.
mov eax, 0ffff_ffffh
mov ebx, 03b72h
mul ebx ; OF will set
The DIV
instruction divides one unsigned value by another and gives you a quotient and a remainder.
In division, you don't have the problem that multiplication has, of generating largo output value. However, it would be useful to be able to divide very large numbers, so we use the same trick as MUL
but in reverse.
Instruction | Explicit operand(a.k.a. Divisor) | Implicit operand(a.k.a. Dividend) | Result(Quotient) | Result(Remainder) |
---|---|---|---|---|
DIV r/m8 | r/m8 | AX | AL | AH |
DIV r/m16 | r/m16 | DX:AX | AX | DX |
DIV r/m32 | r/m32 | EDX:EAX | EAX | EDX |
DIV r/m64 | r/m64 | RDX:RAX | RAX | RDX |
Note
DIV
instruction dose not place any useful data in any of the flags. And it will leave OF
, SF
, ZF
, AF
, PF
, AND CF
in undifined statate.
mov rax, 327
mov rbx, 2
div rbx ; sets RAX to 0xA3, and RDX to 0x1
Warning
If you endup divideng by zero, the kernel will send a SIGFPE
signel to your process and termnate it.
mov rax, 525
mov rbx, 0
mul rbx