nasm 比较浮点值
nasm compare floating point values
我已经尝试了几个小时了,但我不明白为什么它不起作用。这是我使用的代码 never 进入 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.
这是什么原因,我该如何让它发挥作用?谢谢!
来自 Intel's manual 第 2 卷 Jcc
的描述:
JL rel8 Jump short if less (SF≠ OF).
并且根据 FCOMI
的描述:
Performs an unordered comparison of the contents of registers ST(0)
and ST(i)
and sets the status flags ZF
, PF
, and
CF
in the EFLAGS
register according to the result.
The FCOMI/FCOMIP
and FUCOMI/FUCOMIP
instructions set the OF
, SF
and AF
flags to zero in the EFLAGS
register
因此,SF
在 FCOMI
之后将始终等于 OF
,因此永远不会满足 JL
跳转的条件。
根据Table 3-31在FCOMI
的描述你可以使用jc
跳转如果ST(0) < ST(i)
(或jb
,这是jc
的不同名称)。
我已经尝试了几个小时了,但我不明白为什么它不起作用。这是我使用的代码 never 进入 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.
这是什么原因,我该如何让它发挥作用?谢谢!
来自 Intel's manual 第 2 卷 Jcc
的描述:
JL rel8 Jump short if less (SF≠ OF).
并且根据 FCOMI
的描述:
Performs an unordered comparison of the contents of registers
ST(0)
andST(i)
and sets the status flagsZF
,PF
, andCF
in theEFLAGS
register according to the result.
TheFCOMI/FCOMIP
andFUCOMI/FUCOMIP
instructions set theOF
,SF
andAF
flags to zero in theEFLAGS
register
因此,SF
在 FCOMI
之后将始终等于 OF
,因此永远不会满足 JL
跳转的条件。
根据Table 3-31在FCOMI
的描述你可以使用jc
跳转如果ST(0) < ST(i)
(或jb
,这是jc
的不同名称)。