组装:JA 和 JB 工作不正确

Assembly: JA and JB work incorrectly

由于我的主要 OS 是 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.

来自this page

FCOM compares ST0 with the given operand, and sets the FPU flags accordingly.

但是您的 JA midi 正在测试 CPU 标志。

继续:

FCOMI and FCOMIP work like the corresponding forms of FCOM and FCOMP, but write their results directly to the CPU flags register rather than the FPU status word, so they can be immediately followed by conditional jump or conditional move instructions.

这是一个常见的陷阱,FCOM 不在标志寄存器中设置标志,而是在 FPU 状态字中设置条件代码标志。
来自 Intel manual 2:

Compares the contents of register ST(0) and source value and sets condition code flags C0, C2, and C3 in the FPU status word according to the results (see the table below)

哪里可以看到C3扮演了ZFC1的角色CF

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

Performs an unordered comparison of the contents of registers ST(0) and ST(i) and sets the status flags ZF, PF, and CF in the EFLAGS register according to the results [Table is identical to the above, where C2 is PF].

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


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

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

英特尔设计 fnstsw to be compatible with sahf.
前者将C3C2C1分别移动到[=的bit6、bit2、bit0 20=].
后者将标志设置为 RFLAGS(SF:ZF:0:AF:0:PF:1:CF) ← AH.


你也可以test ax directly after the fnstsw ax as suggested in Section 8.3.6.1 Branching on the x87 FPU Condition Codes of manual 1