由于我的主要操作系统是linux并且在visual studio上有项目,所以我决定使用在线编译器来实现它。我找到了许多人建议的this。所以这是我的代码:
#include <iostream>
using namespace std;
int main(void) {
float a = 1;
float b = 20.2;
float res = 0;
float res1 = 0;
_asm {
FLD a
FCOM b
JA midi
JMP modi
midi:
FST res
JMP OUT
modi:
FST res1
JMP OUT
}
OUT:
cout << "res = " << res << endl;
cout << "res1 = " << res1 << endl;
return 0;
}
我的目标很简单,如果a
大于b
而不是a
中的res
,则res1
。但似乎我在变量a
中的任何内容都始终跳到midi
,结果总是res = whatever is in a
。希望你能帮忙。对不起,如果我的问题很愚蠢,我就开始学习装配了。谢谢 :)
的 P.S
同样的事情与JB
相同,但恰恰相反。它始终打印res1 = whatever is in b
。
答案 0 :(得分:5)
来自this page:
FCOM将ST0与给定的操作数进行比较,并设置 FPU 标志 相应
但您的JA midi
正在测试 CPU 标记。
继续:
FCOMI和FCOMIP的工作方式类似于FCOM和FCOMP的相应形式, 但是将结果直接写入 CPU 标志寄存器 而不是 FPU 状态字,因此可以立即跟随它们 条件跳转或条件移动指令。
答案 1 :(得分:4)
这是一个常见的陷阱,FCOM
没有设置标志寄存器中的标志,它在FPU状态字中设置条件代码标志。
来自Intel manual 2:
比较寄存器
ST(0)
和源值的内容,并设置条件代码标志 C0 , C2 和 C3 FPU 根据结果显示状态字(见下表)
您可以看到 C3 扮演 CF 的 ZF 和 C1 的角色。
使用FCOMI
/FUCOMI
(和变体)相应地设置标志。
执行寄存器ST(0)和ST(i)的内容的无序比较,并设置状态标志ZF,PF和 根据结果在EFLAGS寄存器中的CF [表与上面的相同,其中 C2 是 PF ]。
FCOMI
和FUCOMI
之间的区别在于后者允许无序操作数,即qNaNs。
或者您仍然可以使用FCOM
,但随后将条件代码移动到标志:
fnstsw ax ;FP Not-checked STore Status Word in AX
sahf ;Store AH into flags
英特尔设计fnstsw
与sahf
兼容
前者将 C3 , C2 和 C1 分别移动到AH
的bit6,bit2和bit0。
后者将标志设置为RFLAGS(SF:ZF:0:AF:0:PF:1:CF) ← AH
。
您也可以ax
之后直接test
fnstsw ax
按照 8.3.6.1分支{x 3上的x87 FPU条件代码一节中的建议}。