【问题标题】:nasm compare floating point valuesnasm 比较浮点值
【发布时间】:2015-06-25 12:23:13
【问题描述】:

我已经尝试了几个小时,但我不明白为什么它不起作用。这是我使用的代码,从不进入sort.swap

sort:
  ; ...
.inner1
  ; load data[i] into st0
.inner2
  ; load data[j] into st0, data[i] now in st1
.test:
  fcomi      ; compare st0 (data[j]) with st1 (data[i]), status on cpu
  fcom       ; the same, but on the fpu status flag (just to compare in GDB)
  jl .swap
  ffreep st0 ; pop st0 (data[j])
  jmp .inner2
.swap:
  ; ...

在 GDB 中我会这样做

b sort.test
r
si   // fcomi
si   // fcom
i float
i r

样本输出 1

我认为这个行为符合预期,因为 0.5327 小于 0.5262,因此它不应该转到 sort.swap

(gdb) b sort.test
Breakpoint 1 at 0x804881b
(gdb) r
Starting program: /home/niklas/Desktop/erapraktikum/ss15-g52/Projekt1/Implementierung/build/read -v ../Testdaten/zufall-100.txt
Reading from input files ../Testdaten/zufall-100.txt ...
Read 100 entries.
calc.asm: calc(100, 0x804c170, 0x804d178, 0x804e180, 0x804f188)

Breakpoint 1, 0x0804881b in sort.test ()
(gdb) si
0x0804881d in sort.test ()
(gdb) si
0x0804881f in sort.test ()
(gdb) disass
Dump of assembler code for function sort.test:
   0x0804881b <+0>:     fcom   %st(1)
   0x0804881d <+2>:     fcomi  %st(1),%st
=> 0x0804881f <+4>:     jl     0x8048825 <sort.swap>
   0x08048821 <+6>:     ffreep %st(1)
   0x08048823 <+8>:     jmp    0x8048801 <sort.inner2>
End of assembler dump.
(gdb) i float
  R7: Valid   0x3ffe86b87e0000000000 +0,5262526273727416992     
=>R6: Valid   0x3ffe8862d40000000000 +0,5327579975128173828     
  R5: Empty   0x00000000000000000000
  R4: Empty   0x00000000000000000000
  R3: Empty   0x00000000000000000000
  R2: Empty   0x00000000000000000000
  R1: Empty   0x00000000000000000000
  R0: Empty   0x00000000000000000000

Status Word:         0x3020                  PE                        
                       TOP: 6
Control Word:        0x037f   IM DM ZM OM UM PM
                       PC: Extended Precision (64-bits)
                       RC: Round to nearest
Tag Word:            0x0fff
Instruction Pointer: 0x00:0x0804881d
Operand Pointer:     0x00:0x0804e184
Opcode:              0x0000
(gdb) i r
eax            0x804e184        134537604
ecx            0x1      1
edx            0x0      0
ebx            0x5573e000       1433657344
esp            0xffffc868       0xffffc868
ebp            0xffffc878       0xffffc878
esi            0x804e30c        134537996
edi            0x0      0
eip            0x804881f        0x804881f <sort.test+4>
eflags         0x202    [ IF ]
cs             0x23     35
ss             0x2b     43
ds             0x2b     43
es             0x2b     43
fs             0x0      0
gs             0x63     99
(gdb) si
0x08048821 in sort.test ()
(gdb) disass
Dump of assembler code for function sort.test:
   0x0804881b <+0>:     fcom   %st(1)
   0x0804881d <+2>:     fcomi  %st(1),%st
   0x0804881f <+4>:     jl     0x8048825 <sort.swap>
=> 0x08048821 <+6>:     ffreep %st(1)
   0x08048823 <+8>:     jmp    0x8048801 <sort.inner2>
End of assembler dump.

样本输出 2

然而,在这里,我预计会跳到 sort.swap,因为 0.4657 小于 0.5262。但事实并非如此。

(gdb) disass
Dump of assembler code for function sort.test:
=> 0x0804881b <+0>:     fcom   %st(1)
   0x0804881d <+2>:     fcomi  %st(1),%st
   0x0804881f <+4>:     jl     0x8048825 <sort.swap>
   0x08048821 <+6>:     ffreep %st(0)
   0x08048823 <+8>:     jmp    0x8048801 <sort.inner2>
End of assembler dump.
(gdb) si
0x0804881d in sort.test ()
(gdb) 
0x0804881f in sort.test ()
(gdb) i float
  R7: Valid   0x3ffe86b87e0000000000 +0,5262526273727416992     
=>R6: Valid   0x3ffdee7c3c0000000000 +0,4657915830612182617     
  R5: Empty   0x00000000000000000000
  R4: Empty   0x00000000000000000000
  R3: Empty   0x00000000000000000000
  R2: Empty   0x00000000000000000000
  R1: Empty   0x00000000000000000000
  R0: Empty   0x00000000000000000000

Status Word:         0x3120                  PE             C0         
                       TOP: 6
Control Word:        0x037f   IM DM ZM OM UM PM
                       PC: Extended Precision (64-bits)
                       RC: Round to nearest
Tag Word:            0x0fff
Instruction Pointer: 0x00:0x0804881d
Operand Pointer:     0x00:0x0804e188
Opcode:              0x0000
(gdb) i r
eax            0x804e188        134537608
ecx            0x2      2
edx            0x0      0
ebx            0x5573e000       1433657344
esp            0xffffc868       0xffffc868
ebp            0xffffc878       0xffffc878
esi            0x804e30c        134537996
edi            0x0      0
eip            0x804881f        0x804881f <sort.test+4>
eflags         0x203    [ CF IF ]
cs             0x23     35
ss             0x2b     43
ds             0x2b     43
es             0x2b     43
fs             0x0      0
gs             0x63     99
(gdb) si
0x08048821 in sort.test ()
(gdb) 
0x08048823 in sort.test ()
(gdb) disass
Dump of assembler code for function sort.test:
   0x0804881b <+0>:     fcom   %st(1)
   0x0804881d <+2>:     fcomi  %st(1),%st
   0x0804881f <+4>:     jl     0x8048825 <sort.swap>
   0x08048821 <+6>:     ffreep %st(0)
=> 0x08048823 <+8>:     jmp    0x8048801 <sort.inner2>
End of assembler dump.

这是什么原因,我怎样才能让它发挥作用?谢谢!

【问题讨论】:

    标签: x86 gdb nasm


    【解决方案1】:

    来自Intel's manual第2卷对Jcc的描述:

    JL rel8   Jump short if less (SF≠ OF).
    

    还有来自FCOMI的描述:

    对寄存器ST(0)ST(i)的内容进行无序比较,并设置状态标志ZFPFCF 根据结果在EFLAGS 寄存器中。

    FCOMI/FCOMIPFUCOMI/FUCOMIP 指令EFLAGS 寄存器中将 OFSFAF 标志设置为零

    因此,SFFCOMI 之后总是等于OF,因此永远不会满足JL 跳转的条件。


    根据FCOMI 描述中的表3-31,如果ST(0) &lt; ST(i)(或jbjc 的另一个名称),您可以使用jc 跳转。

    【讨论】:

    • 谢谢迈克尔,我在 NASM 手册中找不到这些说明 :( 但它有效 :)
    • 我链接到的英特尔手册是 x86 指令集的权威资源。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多