组装: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扮演了ZF和C1的角色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].
FCOMI
和FUCOMI
的区别在于后者允许无序操作数,即qNaNs。
或者,您仍然可以使用 FCOM
,但随后将条件代码移动到标志中:
fnstsw ax ;FP Not-checked STore Status Word in AX
sahf ;Store AH into flags
英特尔设计 fnstsw
to be compatible with sahf
.
前者将C3、C2、C1分别移动到[=的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。
由于我的主要 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扮演了ZF和C1的角色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].
FCOMI
和FUCOMI
的区别在于后者允许无序操作数,即qNaNs。
或者,您仍然可以使用 FCOM
,但随后将条件代码移动到标志中:
fnstsw ax ;FP Not-checked STore Status Word in AX
sahf ;Store AH into flags
英特尔设计 fnstsw
to be compatible with sahf
.
前者将C3、C2、C1分别移动到[=的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。