问题
I am trying to figure out how the imul and idiv instructions of the 8086 microprocessor work.
I know this: 1. mul and div are multiplications and division for unsigned numbers 2. imul and idiv, are also multiplications and divisions but for signed numbers
I searched all the web, and what I just wrote above, that's the only info that I've found, but written in different ways.
I have this:
mov AX, 0FFCEh
idiv AH
Because ah it's a byte, AL=AX/AH (the result) and AH=remainder
After the instruction I get AX=0032h, obviously 0 remainder, and the result 32. Can somebody explain how it got to this result ? I need to know how to explain how the instruction works (bit by bit).
Same goes with the imul instruction.
I have:
mov AX, 0FF10h
imul AL
Because AL is a byte, the result of the multiplication will be saved into AX. After the execution of the imul instruction AX=0100h, why isn't it F100h ?
I don't how the CPU actually does mul, div, imul and idiv. If somebody could illustrate for me the differences, would really appreciate it.
Thanks!
回答1:
idiv part of answer
mov AX, FFCE
idiv AH
AX=FFCE
AH=FF
definition of negative is that their highest ranked bit equals 1, so FFCE is negative,
because 1111 1111 1100 1110
and processor cannot work with negatives, we need to have positive, that means we negate this number (or processor does this based on highest ranked bit automaticallly)
NEG FFCE
or
1111 1111 1100 1110 =>
=> 0000 0000 0011 0001 +1 =>
=> 0000 0000 0011 0010 =>
=> 0032h
then next - AH register is FF - also negative and we need positive version, we negate
1111 1111 =>
=> 0000 0000 +1 =>
=> 0000 0001 =>
=> 01h
then when all numbers are positive, we calculate division
32h div 1h, 0h remainder => AL, 32h result => AH
both are negative that means that result is positive and needs no more conversions.
imul part of answer
mov AX, FF10
imul AL
AL=10h
imul/mul uses AL when argument is 8bit (which it is)
so imul AL is same as
AL * AL => 10h * 10h => 0100h = AX
imul part of answer extended
mov AX, FF10
imul AH
AH=FF
AL=10h
so now we have AL * AH => AX
AL = 10h
AH = FF which is negative, we need positive, we negate and get => 01h
multiplication of positives
10h * 01h => 0010h
but as only one of them was negative, we have to negate result, do not lose starting zeros, or your answer will be incorrect
0010h => FFEF +1 => FFF0 = AX
回答2:
Wikipedia's binary multiplication article explains the bit-level details, and has a section about signed multiply. You could find similar bit-level details for division.
But like Hans says, you don't really need to understand the details to solve this problem. You do need to know that unlike add/sub, the bitwise operation of mul and div are different for 2's complement integers vs. unsigned integers, not just the interpretation of the result. Fun fact: for multiplication, the lower half of the full-width result is the same for mul and imul.
So the instruction reference manual's description of the instruction operation is all you need, plus an understanding that e.g. the 2's complement representation of -1 is 0xFF. (See http://www.felixcloutier.com/x86/, or Intel's original PDF: links in the x86 tag wiki)
Interpret the bits in each operand the same way the instruction will, and do the math "normally". e.g.
AX = 0xFFCE => -2^16 + 0xFFCE = -0x32 = -50
AH = 0xFF => -1
-50 / -1 = 50, no remainder
回答3:
The problem you are having is partially spelled out in comments.
mov AX, 0FFCEh
idiv AH
divides FFCE by FF. Thankfully this is signed division or this would raise an error.
Multiply is far easier:
mov AX, 0FF10h
imul AL
will store the result of AL * AL in AX.
Beware of larger than byte multiply and divide; they use the DX register as well.
来源:https://stackoverflow.com/questions/28581981/how-does-imul-and-idiv-really-work-8086