Floating point 当使用软浮点、软浮点、硬浮点时,IEEE 754格式是否相同?
TL;DR:0x400921f4是如何表示3.1415801的IEEE 754的?这是一个软浮动吗?我错过了什么 我目前正在为Raspberry Pi 3和Raspberry Pi Zero W构建自己的交叉编译器的过程中了解这一点(*1) 在阅读了分布在论坛和wiki上的文档后,我了解到RPi3和RPi0编译器需要分别针对不同的ARM体系结构,即ARMv7和ARMv6。但是,这两个soc都有一个浮点单元,所以我想使用硬浮点来匹配其余的Raspberry Pi库 我测试了新构建的armv6 rpi linux gnueabi gcc 6.4.0与arm linux gnueabihf gcc 4.9.3之间的差异,该差异在。我阅读了如何确定可执行文件是否使用硬fp。果然,当我编译下面的最小测试用例时 我使用两个编译器使用Floating point 当使用软浮点、软浮点、硬浮点时,IEEE 754格式是否相同?,floating-point,raspberry-pi,arm,Floating Point,Raspberry Pi,Arm,TL;DR:0x400921f4是如何表示3.1415801的IEEE 754的?这是一个软浮动吗?我错过了什么 我目前正在为Raspberry Pi 3和Raspberry Pi Zero W构建自己的交叉编译器的过程中了解这一点(*1) 在阅读了分布在论坛和wiki上的文档后,我了解到RPi3和RPi0编译器需要分别针对不同的ARM体系结构,即ARMv7和ARMv6。但是,这两个soc都有一个浮点单元,所以我想使用硬浮点来匹配其余的Raspberry Pi库 我测试了新构建的armv6 rp
gcc-O0-omain.c
进行编译。下面是:main.rpi用于我的工具链,main.hf用于预构建的工具链
#include <stdio.h>
int main(int argc, char** argv) {
printf("Hello, world %0.7f", 3.14158f);
return 0;
}
一个奇怪的现象是,rpi本身上的ldd main.rpi
只返回而不是动态可执行文件
,而它列出了ldd main.hf
的依赖项。同样,两者都运行并给出预期的输出objdump-R
(在RPi上运行)为两个可执行文件返回相同的值:
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
0002101c R_ARM_GLOB_DAT __gmon_start__
0002100c R_ARM_JUMP_SLOT printf@GLIBC_2.4
00021010 R_ARM_JUMP_SLOT __libc_start_main@GLIBC_2.4
00021014 R_ARM_JUMP_SLOT __gmon_start__
00021018 R_ARM_JUMP_SLOT abort@GLIBC_2.4
这让我担心我使用了soft
或softfp
而不是hard
浮点。因此,我使用objdump-d
(在RPi上运行)查看了两个可执行文件中的反汇编列表:
当float被传递到printf()时,它将被提升为double,并且编译器已经优化了转换。
(double)(3.14158f)
的表示形式为0x400921f4c0000000
。MS部分进入r3,LS部分进入r2
此外,由于printf()是可变的,因此在这两种情况下,FP值都是使用整数寄存器传递的(软浮点样式)。当浮点传递给printf()时,它将升级为双精度,并且编译器已优化了转换。
(double)(3.14158f)
的表示形式为0x400921f4c0000000
。MS部分进入r3,LS部分进入r2
此外,由于printf()是可变的,因此在这两种情况下,FP值都使用整数寄存器传递(软浮点样式)
带硬浮子
00000000 <fun>:
0: eddf 7a02 vldr s15, [pc, #8] ; c <fun+0xc>
4: ee30 0a27 vadd.f32 s0, s0, s15
8: 4770 bx lr
a: bf00 nop
c: 3f9df3b6 svccc 0x009df3b6
00000000:
0:eddf 7a02 vldr s15,[pc,#8];C
4:ee30 0a27 vadd.f32 s0、s0、s15
8:4770 bx lr
a:bf00不
c:3f9df3b6 SVCC 0x009df3b6
带软浮子
00000000 <fun>:
0: b508 push {r3, lr}
2: f24f 31b6 movw r1, #62390 ; 0xf3b6
6: f6c3 719d movt r1, #16285 ; 0x3f9d
a: f7ff fffe bl 0 <__aeabi_fadd>
e: bd08 pop {r3, pc}
00000000:
0:b508推送{r3,lr}
2:f24f 31b6 movw r1,#62390;0xf3b6
6:f6c3 719d移动r1,#16285;0x3f9d
a:f7ff fffe bl 0
e:bd08 pop{r3,pc}
相同的常数是正确的常数
但正如我在得到我的答案之前得到的答案所指出的那样。除非另有规定,否则C中的浮点是双精度的,请注意常量末尾的F,否则编译器必须升级为双精度以执行操作(因为这是我通过不放置F告诉它的,否则常量被视为双精度),然后转换回单精度以返回
00000000 <fun>:
0: b508 push {r3, lr}
2: f7ff fffe bl 0 <__aeabi_f2d>
6: a304 add r3, pc, #16 ; (adr r3, 18 <fun+0x18>)
8: e9d3 2300 ldrd r2, r3, [r3]
c: f7ff fffe bl 0 <__aeabi_dadd>
10: f7ff fffe bl 0 <__aeabi_d2f>
14: bd08 pop {r3, pc}
16: bf00 nop
18: c8b43958 ldmgt r4!, {r3, r4, r6, r8, r11, r12, sp}
1c: 3ff3be76 svccc 0x00f3be76
00000000:
0:b508推送{r3,lr}
2:f7ff fffe bl 0
6:a304增加r3,pc,#16;(adr r3,18)
8:E9D32300 ldrd r2,r3,[r3]
c:f7ff fffe bl 0
10:f7ff fffe bl 0
14:bd08 pop{r3,pc}
16:bf00无
18:c8b43958 ldmgt r4!,{r3,r4,r6,r8,r11,r12,sp}
1c:3ff3be76 SVCC 0x00f3be76
带硬浮子
00000000 <fun>:
0: eddf 7a02 vldr s15, [pc, #8] ; c <fun+0xc>
4: ee30 0a27 vadd.f32 s0, s0, s15
8: 4770 bx lr
a: bf00 nop
c: 3f9df3b6 svccc 0x009df3b6
00000000:
0:eddf 7a02 vldr s15,[pc,#8];C
4:ee30 0a27 vadd.f32 s0、s0、s15
8:4770 bx lr
a:bf00不
c:3f9df3b6 SVCC 0x009df3b6
带软浮子
00000000 <fun>:
0: b508 push {r3, lr}
2: f24f 31b6 movw r1, #62390 ; 0xf3b6
6: f6c3 719d movt r1, #16285 ; 0x3f9d
a: f7ff fffe bl 0 <__aeabi_fadd>
e: bd08 pop {r3, pc}
00000000:
0:b508推送{r3,lr}
2:f24f 31b6 movw r1,#62390;0xf3b6
6:f6c3 719d移动r1,#16285;0x3f9d
a:f7ff fffe bl 0
e:bd08 pop{r3,pc}
相同的常数是正确的常数
但正如我在得到我的答案之前得到的答案所指出的那样。除非另有规定,否则C中的浮点是双精度的,请注意常量末尾的F,否则编译器必须升级为双精度以执行操作(因为这是我通过不放置F告诉它的,否则常量被视为双精度),然后转换回单精度以返回
00000000 <fun>:
0: b508 push {r3, lr}
2: f7ff fffe bl 0 <__aeabi_f2d>
6: a304 add r3, pc, #16 ; (adr r3, 18 <fun+0x18>)
8: e9d3 2300 ldrd r2, r3, [r3]
c: f7ff fffe bl 0 <__aeabi_dadd>
10: f7ff fffe bl 0 <__aeabi_d2f>
14: bd08 pop {r3, pc}
16: bf00 nop
18: c8b43958 ldmgt r4!, {r3, r4, r6, r8, r11, r12, sp}
1c: 3ff3be76 svccc 0x00f3be76
00000000:
0:b508推送{r3,lr}
2:f7ff fffe bl 0
6:a304增加r3,pc,#16;(adr r3,18)
8:E9D32300 ldrd r2,r3,[r3]
c:f7ff fffe bl 0
10:f7ff fffe bl 0
14:bd08 pop{r3,pc}
16:bf00无
18:c8b43958 ldmgt r4!,{r3,r4,r6,r8,r11,r12,sp}
1c:3ff3be76 SVCC 0x00f3be76
虽然没有必要这样做,但我还没有看到编译器在硬浮点和软浮点之间来回切换时使用不同的格式。但也许那些编译器就在那里。嗯。。。尽管有这些答案,ISTM认为0x400921F4
是构成8字节双精度3.1415801
的字节的十六进制表示的一部分(全十六进制值:0x400921F4BF5A1D83
)。3.1415801f
的4字节浮点值是0x40490FA6
。虽然没有必要这样做,但我还没有看到编译器在硬浮点和软浮点之间来回切换时使用不同的格式。但也许那些编译器就在那里。嗯。。。尽管有这些答案,ISTM认为0x400921F4
是构成8字节双精度3.1415801
的字节的十六进制表示的一部分(全十六进制值:0x400921F4BF5A1D83
)。3.1415801f
i的4字节浮点值
00000000 <fun>:
0: b508 push {r3, lr}
2: f24f 31b6 movw r1, #62390 ; 0xf3b6
6: f6c3 719d movt r1, #16285 ; 0x3f9d
a: f7ff fffe bl 0 <__aeabi_fadd>
e: bd08 pop {r3, pc}
00000000 <fun>:
0: b508 push {r3, lr}
2: f7ff fffe bl 0 <__aeabi_f2d>
6: a304 add r3, pc, #16 ; (adr r3, 18 <fun+0x18>)
8: e9d3 2300 ldrd r2, r3, [r3]
c: f7ff fffe bl 0 <__aeabi_dadd>
10: f7ff fffe bl 0 <__aeabi_d2f>
14: bd08 pop {r3, pc}
16: bf00 nop
18: c8b43958 ldmgt r4!, {r3, r4, r6, r8, r11, r12, sp}
1c: 3ff3be76 svccc 0x00f3be76