MUL and DIV How to use the x86 CPU’s multiplication and division instructions

advertisement
MUL and DIV
How to use the x86 CPU’s
multiplication and division
instructions
A comment about addition
• When two register-values are added
add
%al, %bl
their total can sometimes be “too large” to fit in
the destination register:
Example: 150 + 160 = 310
• Both numbers 150 and 160 can be expressed as
8-bit binary values: 150 as 10010110 (base 2)
160 as 10100000 (base 2)
• But not their sum: 310 is 100110110 (base 2)
The Carry-Flag
• The “extra” bit becomes the CF-bit (i.e.,
the ‘Carry’ Flag) in the RFLAGS register
• Programs can “branch” if a carry occurs:
jc
toobig
• Or branch elsewhere if no-carry occurs:
jnc sumok
• Special instruction exists to handle adding
of large numbers: ADC (Add-with-Carry)
A Big Number example
x:
y:
.section
.short
.short
.data
150
160
.section
mov
add
mov
adc
.text
x, %al
y, %al
x+1, %ah
y+1, %ah
“worst-cases” add vs multiply
• Adding two n-bit numbers never requires
more than (n+1)-bits for their total, so the
carry-flag bit suffices for holding the result
• But multiplication is another story!
• Biggest 8-bit number is 255 (= 11111111)
• 255x255 = 65025 (= 1111111000000001)
• So this product requires 16-bits: 0xFE01
MUL
• Using MUL to multiply two 64-bit operands
•
•
•
•
Put the 64-bit ‘multiplicand’ into RAX
Put the 64-bit ‘multiplier’ into a general register
The CPU will produce a 128-bit ‘product’
The product will be in the (RDX:RAX) register-pair
• (You can also put the 64-bit ‘multiplier’ in a
memory-variable if you then use ‘MULQ’)
DIV
• If you put your 128-bit ‘dividend’ into the
RDX:RAX register-pair, then you can put
your 64-bit divisor into a general-register
• The ‘quotient’ will appear in RAX and the
remainder will appear in RDX – unless the
quotient is too large to fit in register RAX
• (You can also put your 64-bit ‘divisor’ in a
memory variable if you then use DIVQ)
Download