汇编中能否不加载至x87栈直接比较内存中的浮点数?
汇编语言中直接比较内存中浮点数的问题
抱歉提出基础问题。在汇编语言中,是否可以直接比较存储在不同固定内存地址的浮点数,无需将其加载至x87栈?除了CMP和JLE指令外,是否还需要使用其他指令?
示例:内存地址[A]当前值为95,内存地址[B]值为90。我想要在[A]小于等于90时执行跳转,以下代码是否足够?CMP DWORD PTR [A], CMP DWORD PTR [B] JLE [Another address]
问题解答
- 普通
CMP指令不能直接用于浮点数比较:CMP是整数比较指令,直接对浮点内存单元使用会把二进制内容当成整数解析,而浮点数采用IEEE754编码,和整数的二进制格式完全不同,会得到错误的比较结果。 - x87架构下必须加载到栈才能比较:x87的浮点运算依赖栈结构,比较浮点数需要以下步骤:
- 用
FLD将第一个浮点数加载到x87栈顶 - 用
FCOM/FCOMP指令与内存中的第二个浮点数比较 - 用
FNSTSW将x87状态字存入AX寄存器,再用SAHF把状态映射到通用标志寄存器 - 最后用
JLE等条件跳转指令判断结果
- 用
你给出的代码存在两个明显问题:
- 语法错误:
CMP指令的格式为CMP 操作数1, 操作数2,不能在操作数位置重复写CMP关键字 - 逻辑错误:用整数比较指令处理浮点数,会导致比较结果完全不符合预期
正确的x87示例代码(单精度浮点数)
FLD DWORD PTR [A] ; 将内存A处的单精度浮点数加载到x87栈顶 FCOM DWORD PTR [B] ; 比较栈顶浮点数与内存B处的浮点数 FNSTSW AX ; 将x87状态寄存器内容存入AX SAHF ; 将AX中的标志位映射到EFLAGS寄存器 JLE AnotherAddress ; 若[A] <= [B],跳转到目标地址
现代SSE指令集的替代方案
如果CPU支持SSE指令集,可以直接比较内存中的浮点数,无需使用x87栈:
CMPSS xmm0, DWORD PTR [A], DWORD PTR [B] ; 比较A和B处的单精度浮点数,结果存入xmm0 JP ErrorHandler ; 可选:处理非数值(NaN)的情况 JLE AnotherAddress ; 根据比较结果跳转
内容的提问来源于stack exchange,提问作者x87-Learner
相关产品推荐
相关产品推荐

