1

我理解了进位标志和溢出标志的逻辑。但是,当我读到这个程序(写在 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 位有符号数(so -2^15 <= bb <= 2^15-1),并且如果至少一个和(在乘法算法中)打开 / 位,则乘法将/CF位打开。OFCFOF

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

我还注意到,因为,2^15-1=32767如果我设置bb190( 190^2=36100) CF=0如果bb等于200( 200^2=40000) CF=1

这是为什么?有人可以详细解释一下吗?

PS:我用的是EMU8086。

4

2 回答 2

3

如果您在英特尔的文档中查看 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;

CF并且OF要么都设置,要么都清除。因此,您可以在之后检查任一标志IMUL

于 2015-04-26T11:47:34.847 回答
1

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

于 2015-04-26T11:40:58.943 回答