FCOM floating point comparison fails

2020-04-21 08:12发布

I am just getting started with 32-bit assembly and I'm quite confused. I have the following code:

.586
.MODEL FLAT

.STACK 4096

.DATA

.CODE
main PROC

finit
fldpi
fld1
fcom
fstsw ax
sahf
JL jumper

nop

jumper:
nop

nop
main ENDP
END

Now from what I understand, I am pushing pi onto the stack then pushing 1 onto the stack, it should compare pi and 1 and see that 1 is lesser and execute a jump. However the comparison doesn't appear to work. Can someone help?

标签: assembly x86 x87
1条回答
我欲成王,谁敢阻挡
2楼-- · 2020-04-21 08:42

Change JL to JB, since you can only do unsigned comparisons with the FPU flags.

The reason is that 8087 has only 2 equivalent status bits at the same positions as 8086. Those are CF and ZF. When doing a signed comparison, the processor uses OF state from any preceding operation and the 8087 Busy State as the sign bit.

 8087:   [Busy] [ EQ ] [ Top of Stack Ptr ] [UND] [SOF] [ LT ]
                  C3                         C2     C1    C0    <-- C3..C0
 8086:   [Sign] [Zero] [ 0  ] [ AF ] [  0 ] [PF ] [ 1 ] [  C ]

FCOMx Sets the Control bits C3,C2,C0 according to the conditions

 C3 = EQ == equal
 C2 = Undefined == Set if ST or Mem is undefined
 C1 = Marks either Underflow or Overflow of FP Stack (If Overflow Exception == TRUE)
 C0 = True, if ST(i) < ST(1)/Mem

OTOH, the branch codes are implemented as

    JL:   SF != OF
    JB:   CF
    JBE:  CF | ZF
    JA:   !CF && !ZF

Thus: Behaviourally C3/EQ == Zero and C0/LT == Carry

References: Art of Assembly, FLAGS register, Conditional Jumps

查看更多
登录 后发表回答