汇编:JA和JB工作不正常

时间:2016-12-26 16:50:37

标签: c++ assembly x86 fpu

由于我的主要操作系统是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

2 个答案:

答案 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   根据结果​​显示状态字(见下表)

Condition codes set by FCOM

您可以看到 C3 扮演 CF ZF C1 的角色。

使用FCOMI/FUCOMI(和变体)相应地设置标志。

  

执行寄存器ST(0)和ST(i)的内容的无序比较,并设置状态标志ZF,PF和   根据结果​​在EFLAGS寄存器中的CF [表与上面的相同,其中 C2 PF ]。

FCOMIFUCOMI之间的区别在于后者允许无序操作数,即qNaNs。

或者您仍然可以使用FCOM,但随后将条件代码移动到标志:

fnstsw ax        ;FP Not-checked STore Status Word in AX
sahf             ;Store AH into flags

英特尔设计fnstswsahf兼容 前者将 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条件代码一节中的建议}。

manual 1