最近读书《深入理解计算机系统》里第二章中的“Intel IA32 浮点运算”,发现其中给出的测试程序有些问题:
浮点数寄存器使用的是80位的扩展精度格式
float 类型使用的是32位精度格式
double 类型使用的是64位精度格式
书中给出的例子是
#include<stdio.h>
double recip(int denom){
return 1.0/(double) denom;
}
void do_nothing(){}
void test1(int denom){
double r1, r2;
int t1, t2;
r1 = recip(denom);
r2 = recip(denom);
t1 = r1 == r2;
do_nothing();
t2 = r1 == r2;
printf("test1 t1: r1 %f %c= r2 %f\n", r1, t1 ? '=' : '!', r2);
printf("test1 t2: r1 %f %c= r2 %f\n", r1, t2 ? '=' : '!', r2);
}
main(){
test1(10);
}
我的系统是ubuntu9.04
gcc 版本 4.3.3 (Ubuntu 4.3.3-5ubuntu4)
第一步:不带优化的编译
coffee@coffee-laptop:~$ gcc -o test test.c
coffee@coffee-laptop:~$ ./test
test1 t1: r1 0.100000 == r2 0.100000
test1 t2: r1 0.100000 == r2 0.100000
第二步:带有O2优化的编译
coffee@coffee-laptop:~$ gcc -O2 -o test test.c
coffee@coffee-laptop:~$ ./test
test1 t1: r1 0.100000 == r2 0.100000
test1 t2: r1 0.100000 == r2 0.100000
运行结果并不是意料中的
test1 t1: r1 0.100000 != r2 0.100000
test1 t2: r1 0.100000 == r2 0.100000
加入书中给出的函数2
void test2(int denom){
double r1;
int t1;
r1 = recip(denom);
t1 = r1 == 1.0/(double) denom;
printf("test2 t1: r1 %f %c= 1.0/10.0\n", r1, t1 ? '=' : '!');
}
第一步:不带优化的编译
coffee@coffee-laptop:~$ gcc -o test test.c
coffee@coffee-laptop:~$ ./test
test1 t1: r1 0.100000 == r2 0.100000
test1 t2: r1 0.100000 == r2 0.100000
test2 t1: r1 0.100000 != 1.0/10.0
第二步:带有O2优化的编译
coffee@coffee-laptop:~$ gcc -O2 -o test test.c
coffee@coffee-laptop:~$ ./test
test1 t1: r1 0.100000 == r2 0.100000
test1 t2: r1 0.100000 == r2 0.100000
test2 t1: r1 0.100000 == 1.0/10.0
这里主要有两方面的问题
1.是浮点寄存器的使用问题,保存在浮点寄存器中的浮点数并不等于内存中的浮点数
2.GCC对浮点数的支持,特别是在使用了O2优化编译的时候
明天继续研究,今天到此,先休息!
--------------------------------------------------------------------------------------------------------------------
继续 2010-01-30(PS:昨天和同学逛街去了,哇哈哈!)
首先,对源程序的编译采用命令行选项 -ffloat-store,该命令将每一个浮点计算的结果在使用之前都必须存储到存储器中,
测试结果
coffee@coffee-laptop:~$ gcc -ffloat-store -o test3 test.c
coffee@coffee-laptop:~$ ./test3
test1 t1: r1 0.100000 == r2 0.100000
test1 t2: r1 0.100000 == r2 0.100000
test2 t1: r1 0.100000 == 1.0/10.0
查了些资料,国内对这部分的解释还是太少了,通过优编译--反汇编,比较得出的三种不同的反编译的汇编程序,得出结论。原来在不带优化的编译中,浮点计算的结果先是保存在浮点寄存器,采用的是80位的扩展精度格式,即r1;而r2计算的结果已经被转换到64位的double类型,所以比较的结果不同。
参考的反汇编
不带有优化的编译,下面的是函数test2的反汇编代码
da: 55 push %ebp
db: 89 e5 mov %esp,%ebp
dd: 83 ec 28 sub $0x28,%esp
e0: 8b 45 08 mov 0x8(%ebp),%eax
e3: 89 04 24 mov %eax,(%esp)
e6: e8 fc ff ff ff call e7 <test2+0xd>
eb: dd 5d f0 fstpl -0x10(%ebp)
ee: db 45 08 fildl 0x8(%ebp)
f1: d9 e8 fld1
f3: de f1 fdivp %st,%st(1)
f5: dd 45 f0 fldl -0x10(%ebp)
f8: da e9 fucompp
fa: df e0 fnstsw %ax
fc: 9e sahf
fd: 0f 94 c0 sete %al
100: 0f 9b c2 setnp %dl
103: 21 d0 and %edx,%eax
105: 0f b6 c0 movzbl %al,%eax
108: 89 45 fc mov %eax,-0x4(%ebp)
分享到:
相关推荐
对于带有FPU的处理器,如X86架构,Linux内核默认使用`-msoft-float`编译选项,这意味着内核编译为软浮点程序,即依赖于GCC编译器模拟浮点运算。然而,这并不意味着内核本身的性能受到影响,因为内核代码中通常较少...
例如,PXA系列核心板没有硬件FPU,但GCC编译器提供了基于Intel Integer SIMD extension (iWMMXt)的优化软浮点运算仿真功能。 #### 4. 编译器选项 编译器选项对于正确生成针对特定硬件的代码至关重要。以下是一些...
在GCC中,MPC库用于处理复数浮点运算,确保了精度和正确性。 4. MPFR 2.4.2:MPFR库是一个提供精确浮点计算的库,它基于GMP,遵循IEEE 754标准。MPFR库支持多种浮点精度,可以进行可靠的浮点运算,这对于科学计算、...
与GMP类似,MPFR也是GCC处理高精度浮点运算的重要组件。 4. **mpc-1.0.3.tar.gz**:MPC,即Multiple Precision Complex,是用于复数的高精度计算库。它结合了GMP和MPFR的功能,为GCC提供复数运算的精确性。 5. **...
newlib 实现了许多复杂的功能,包括字符串支持,浮点运算,内存分配和 I/O流函数。 在为 ARM 交叉编译 gcc 编译器时,对 gcc 指定不同的配置选项时,使用的 C 语言库就不同,gcc 编译器默认使用 Glibc,也可以使用 ...
3. **mpc-0.8.1.tar.gz**:MPC(Multiple Precision Complex Floating-Point Calculator)是用于复数高精度浮点运算的库,与GMP一起工作,为GCC提供复数运算支持。 4. **mpfr-2.4.2.tar.bz2**:MPFR(Multiple ...
在升级GCC到4.8.2的过程中,我们需要MPFR支持新版本的浮点运算特性。文件`mpfr-2.4.2.tar.bz2`包含了MPFR库的源代码,同样需要按照步骤进行安装。 MPC是处理复数运算的库,尤其在科学计算和工程应用中非常重要。...
6. `mpfr-3.1.1-4.el7.x86_64.rpm`:MPFR库,一个浮点计算的多精度库,为GCC提供了高精度浮点运算的支持。 7. `libmpc-1.0.1-3.el7.x86_64.rpm`:多精度复数库,是GCC处理复数运算时使用的库。 在安装这些包时,...
这些依赖包分别对应于GMP(GNU Multiple Precision Arithmetic Library)、MPFR(Multiple Precision Floating-Point Reliable Library)和MPC(GNU Multiple ...,它们是GCC编译高精度计算和浮点运算所必需的库...
3. `mpfr`:多精度浮点算术库,提供可精确控制精度的浮点运算。 4. `mpc`:用于复数计算的库,与MPFR结合使用。 5. `zlib`:压缩库。 6. `ncurses`:用于开发终端用户界面的库,编译过程中的部分工具可能需要。 7. `...
4. **mpfr-4.0.1**:MPFR(Multiple Precision Floating-Point Reliable)是一个用于浮点计算的库,提供了可调整精度的浮点数操作,对于需要精确控制浮点运算的程序特别有用。 5. **isl-0.20**:Integer Set ...
GCC(GNU Compiler Collection)是GNU项目的一个重要组成部分,它是一个开源的、跨平台的编译器集合,用于将源代码转换为机器可...这对于开发数学软件、科学计算工具以及需要高精度浮点运算的任何应用都是至关重要的。
2. **性能提升**:优化了编译器的内部结构,提高了代码生成的效率,尤其是对于浮点运算和多线程代码。 3. **错误和警告信息**:增强了错误和警告信息的清晰度,帮助开发者更快地定位问题。 4. **诊断增强**:增加了...
【标题】:“GUI计算器【无浮点运算】_stm32_classA_”是指一个基于STM32微控制器的图形用户界面(GUI)计算器项目,它不支持浮点数计算,仅处理整数运算。STM32是意法半导体公司(STMicroelectronics)推出的一种...
- mpfr:多精度浮点计算库,用于GCC的浮点运算支持。 - gmp:大整数运算库,为GCC提供大整数支持。 - isl:用于优化GCC的isl库。 - cloog-ppl:用于生成GIMPLE中间表示的代码生成器。 - gcc:GCC编译器本身。 ...
这些库提供了高级数学运算和浮点计算的精确支持,是编译器的基础组件。 6. **调试信息**:GCC 11.3.0可能改进了调试信息的生成,使得开发者使用GDB等调试工具时能够获得更准确、更详尽的信息,帮助定位和解决问题。...
MPFR 2.4.2版本提供了精确度和性能的平衡,确保在GCC中进行浮点运算时能获得可靠的精度。 MPC,全称Multiple Precision Complex,是基于GMP和MPFR的复数计算库。它扩展了GMP和MPFR的功能,允许进行复数的任意精度...
对于编译需要浮点运算支持的程序来说,这是必不可少的。 4. **MPC**:MPC 库处理复数运算,对需要复数运算的编译有重要作用。 在开始安装之前,确保系统已安装了必要的开发工具,如 make、autoconf、automake、...