You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FPU中fcompp与fstsw ax结果异常:AX值随ST栈元素数变化求助

问题原因分析

你观察到的现象是FPU的正常行为,核心原因是fstsw ax返回的AX寄存器存储的是完整的FPU状态字,而非仅比较结果。状态字中包含了随栈元素数量变化的**栈指针(TOP)**字段,导致AX整体值随栈元素数量改变。

关键细节拆解

1. FPU状态字结构

16位的FPU状态字包含多个控制/状态字段,和你问题相关的两个核心部分:

  • TOP字段(位15-12):4位无符号数,表示当前逻辑ST0对应的物理寄存器编号(ST0-ST7)。FPU栈是向下生长的循环栈,每压入一个元素,TOP值减1(模8)。因此栈元素数量越多,TOP值越小:
    • 栈有2个元素 → TOP=6
    • 栈有3个元素 → TOP=5
    • ...
    • 栈有8个元素 → TOP=0
  • 比较条件码(C0、C2、C3):分别对应状态字的位11、位9、位8,用于表示fcompp的比较结果:
    比较结果C0C2C3
    ST0 > ST1000
    ST0 == ST1101
    ST0 < ST1001

2. 测试结果对应逻辑

你看到的AX值变化,是TOP字段和条件码字段的组合结果:

  • TOP字段占据状态字的高4位,直接决定了AX的高字节部分,因此栈元素数量变化时,AX的高位会呈现规律性改变(如你给出的数值中,高字节每次递减0x08)。
  • 条件码字段占据状态字的低几位,决定了AX低位的固定差异(如ST0<ST1时低位为0x01,ST0>ST1时为0x00)。

正确的比较结果判断方式

不要直接使用AX的整数值判断比较结果,应该提取状态字中的条件码位,常用两种方式:

方式1:利用sahf映射到标志位

fcompp       ; 比较ST0和ST1,弹出两个元素
fstsw ax     ; 将FPU状态字存入AX
sahf         ; 将AH的位映射到EFLAGS的SF、ZF、AF、PF、CF
; 直接用跳转指令判断
ja  st0_gt_st1  ; ST0 > ST1
je  st0_eq_st1  ; ST0 == ST1
jb  st0_lt_st1  ; ST0 < ST1

st0_gt_st1:
; 处理ST0大于ST1的逻辑
st0_eq_st1:
; 处理相等的逻辑
st0_lt_st1:
; 处理ST0小于ST1的逻辑

方式2:手动提取条件码位

fcompp
fstsw ax
; 提取C0(位11)和C3(位8)
test ax, 0x400  ; 检查C0位
jnz st0_eq      ; C0=1表示相等
test ax, 0x100  ; 检查C3位
jnz st0_lt      ; C3=1表示ST0<ST1
jmp st0_gt      ; 否则ST0>ST1

st0_eq:
; 相等逻辑
st0_lt:
; 小于逻辑
st0_gt:
; 大于逻辑

内容的提问来源于stack exchange,提问作者Vitaly

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 12:03:07