我理解进位标志和溢出标志的逻辑。 但是,当我读到这个程序(在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
设置为190
(190^2=36100
)CF=0
;如果bb
等于200
(200^2=40000
)CF=1
。
为什么?有人能详细解释一下这个吗?
P.S。:我正在使用EMU8086。
答案 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;
CF
和OF
要么已设置,要么已清除。因此,您可以在IMUL