TL:DR:使用高于/低于条件(如无符号整数)来测试比较结果。
对于各种historical reasons(映射from FP status word to FLAGS via fcom / fstsw / sahf,fcomi(PPro 中的新功能)匹配),FP 比较集合 CF,而不是 OF / SF。另见http://www.ray.masmcode.com/tutorial/fpuchap7.htm
这一切都来自 Intel 64 and IA-32 Architectures Software Developer's Manuals的第2卷。
FCOMI 只设置CMP 所做的一些标志。您的代码有%st(0) == 9 和%st(1) == 10。 (因为它们被加载到堆栈上),参考第 2A 卷中第 3-348 页的表格,您可以看到这是“ST0 JG 的意思是“如果更大(ZF=0 和 SF=OF)则跳短”。换句话说,它正在测试符号、溢出和零标志,但FCOMI 没有设置符号或溢出!
根据你想跳的条件,你应该看看可能的比较结果,然后决定你想跳的时间。
+--------------------+---+---+---+
|比较结果 | Z |磷 | C |
+--------------------+---+---+---+
| ST0 > ST(i) | 0 | 0 | 0 |
| ST0
我制作了这张小桌子,以便更容易弄清楚:
+--------------+---+---+------+-------- ----------------+
|测试 | Z | C | Jcc |笔记 |
+--------------+---+---+------+-------- ----------------+
| ST0 = ST(i) | X | 0 | JAE |只要CF清楚我们就很好|
| ST0 > ST(i) | 0 | 0 | JA | CF和ZF都必须清楚 |
+--------------+---+---+------+-------- ----------------+
图例:X:不关心,0:清除,1:设置
换句话说,条件代码与使用无符号比较的条件代码相匹配。如果您使用的是FMOVcc,情况也是如此。
如果fcomi 的一个(或两个)操作数是NaN,则设置ZF=1 PF=1 CF=1。 (FP 比较有 4 种可能的结果:>、<、== 或无序)。如果您关心代码对 NaN 的作用,您可能需要额外的 jp 或 jnp。但并非总是如此:例如,ja 仅在 CF=0 且 ZF=0 时为真,因此在无序情况下将不取。如果你想让无序的case采用与下面相同或相等的执行路径,那么ja就是你所需要的。
如果你想打印,你应该使用JA(即if (!(f2 > f1)) { puts("hello"); }),如果你不想打印,你应该使用JBE(对应于if (!(f2 <= f1)) { puts("hello"); })。 (请注意,这可能有点令人困惑,因为我们只在不跳转时才打印)。
关于您的第二个问题:默认情况下 fcomi 不会弹出任何内容。你想要它的近亲fcomip,它弹出%st0。您应该在使用后始终清除 fpu 寄存器堆栈,因此假设您希望打印消息,您的程序最终会像这样结束:
.section .rodata
msg: .ascii "Hallo\n\0"
f1: .float 10.0
f2: .float 9.0
.globl main
.type main, @function
main:
flds f1
flds f2
fcomip
fstp %st(0) # to clear stack
ja leb # won't jump, jbe will
pushl $msg
call printf
addl $4, %esp
leb:
pushl $0
call exit