ASM8086:mul,imul,携带标志和溢出标志

时间:2015-04-26 10:57:56

标签: assembly integer-overflow carryflag

我理解进位标志和溢出标志的逻辑。 但是,当我读到这个程序(在MASM 8086中写道)时,我感到很困惑。

程序意图是判断二次方程是否有两个区别解,两个等于解或根本没有解。

.model small
.stack
.data
aa dw 2
bb dw 4
cc dw 2
sol_msg    db "There exist two real solutions", CR, NL
no_sol_msg db "No real solutions!            ", CR, NL
sol_coinc  db "The two solutions coincide!   ", CR, NL
.code
.startup
mov ax, bb
imul bb
jc overflow ; I decided to work at most with 16-bit numbers
push ax
mov ax, aa
imul cc
jc overflow
mov bx, 4
imul bx
jc overflow
pop bx
sub bx, ax
jo overflow
js mess2
jz mess3
lea si, sol_msg
jmp next
mess2: lea si, no_sol_msg
jmp next
mess3: lea si, sol_coinc
next: mov bx, LUNG_MSG
mov ah, 2
loop1: mov dl, [si]
INT 21h
inc si
dec bx
jnz loop1
jmp end1
overflow:
nop
end1: 
.exit
end

现在,我怀疑的是:为什么前三个检查已经测试了进位标志,最后一个检查了溢出标志?

因为在最后一个中,我们在两个有符号数之间进行减法(我们认为那些),我们必须检查溢出标志以查看是否存在溢出(即数字是否超出间隔[-2^15,2^15-1])。 但是对于第一个,我们使用(bb)^2进行imul

所以我们认为它们是16位有符号数(所以-2^15 <= bb <= 2^15-1),如果至少有一个和,则乘法设置为CF / OF位(在乘法算法中) )获取CF / OF位。

但是既然我们处理了有符号的数字,我们不应该检查溢出标志吗?

此外,我注意到,自2^15-1=32767起,如果我将bb设置为190190^2=36100CF=0;如果bb等于200200^2=40000CF=1

为什么?有人能详细解释一下这个吗?

P.S。:我正在使用EMU8086。

2 个答案:

答案 0 :(得分:1)

对于IMUL: 当中间产品的有符号整数值与符号不同时,将设置CF和OF标志 扩展操作数大小截断的乘积,否则清除CF和OF标志。为了 当一个操作数形式的指令时,CF和OF标志在有效位被带入上半部分时被置位 当结果完全适合结果的下半部分时结果并清除。 即这些标志在这里几乎相等。 对于SUB: SUB指令执行整数减法。它评估有符号和无符号整数的结果 操作数和设置OF和CF标志分别表示有符号或无符号结果中的溢出。 SF flag表示签名结果的符号。 OF是签名的。检查指令集参考手册。即使对于这个旧代码,它仍然是实际的。 但请参阅x86 flags

答案 1 :(得分:1)

如果你看一下IMUL的伪算法,你会看到

IF OperandSize = 16
THEN
  TMP_XP ← AX ∗ SRC (* Signed multiplication; TMP_XP is a signed integer at twice the width of the SRC *)
  DX:AX ← TMP_XP[31:0];
  SF ← TMP_XP[15];
  IF SignExtend(TMP_XP[15:0]) = TMP_XP
    THEN CF ← 0; OF ← 0;
    ELSE CF ← 1; OF ← 1;
  FI;
FI;

CFOF要么已设置,要么已清除。因此,您可以在IMUL

之后检查任一标记