`
咖啡猪猪
  • 浏览: 16714 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

GCC中关于浮点运算的问题

阅读更多

 

最近读书《深入理解计算机系统》里第二章中的“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)
分享到:
评论

相关推荐

    浅谈linux kernel对于浮点运算的支持

    对于带有FPU的处理器,如X86架构,Linux内核默认使用`-msoft-float`编译选项,这意味着内核编译为软浮点程序,即依赖于GCC编译器模拟浮点运算。然而,这并不意味着内核本身的性能受到影响,因为内核代码中通常较少...

    ARM处理器Linux下浮点运算单元运用

    例如,PXA系列核心板没有硬件FPU,但GCC编译器提供了基于Intel Integer SIMD extension (iWMMXt)的优化软浮点运算仿真功能。 #### 4. 编译器选项 编译器选项对于正确生成针对特定硬件的代码至关重要。以下是一些...

    gcc4.8.2及其依赖包.zip

    在GCC中,MPC库用于处理复数浮点运算,确保了精度和正确性。 4. MPFR 2.4.2:MPFR库是一个提供精确浮点计算的库,它基于GMP,遵循IEEE 754标准。MPFR库支持多种浮点精度,可以进行可靠的浮点运算,这对于科学计算、...

    GCC 11.2 离线安装包

    与GMP类似,MPFR也是GCC处理高精度浮点运算的重要组件。 4. **mpc-1.0.3.tar.gz**:MPC,即Multiple Precision Complex,是用于复数的高精度计算库。它结合了GMP和MPFR的功能,为GCC提供复数运算的精确性。 5. **...

    arm-linux-gcc和arm-elf-gcc 区别

    newlib 实现了许多复杂的功能,包括字符串支持,浮点运算,内存分配和 I/O流函数。 在为 ARM 交叉编译 gcc 编译器时,对 gcc 指定不同的配置选项时,使用的 C 语言库就不同,gcc 编译器默认使用 Glibc,也可以使用 ...

    gcc5.5.zip

    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 ...

    升级GCC4.4.7到GCC4.8.2所有依赖包

    在升级GCC到4.8.2的过程中,我们需要MPFR支持新版本的浮点运算特性。文件`mpfr-2.4.2.tar.bz2`包含了MPFR库的源代码,同样需要按照步骤进行安装。 MPC是处理复数运算的库,尤其在科学计算和工程应用中非常重要。...

    linux系统gcc离线安装包

    6. `mpfr-3.1.1-4.el7.x86_64.rpm`:MPFR库,一个浮点计算的多精度库,为GCC提供了高精度浮点运算的支持。 7. `libmpc-1.0.1-3.el7.x86_64.rpm`:多精度复数库,是GCC处理复数运算时使用的库。 在安装这些包时,...

    gcc解压缩安装依赖包

    这些依赖包分别对应于GMP(GNU Multiple Precision Arithmetic Library)、MPFR(Multiple Precision Floating-Point Reliable Library)和MPC(GNU Multiple ...,它们是GCC编译高精度计算和浮点运算所必需的库...

    centos7源码更新gcc-9.3

    3. `mpfr`:多精度浮点算术库,提供可精确控制精度的浮点运算。 4. `mpc`:用于复数计算的库,与MPFR结合使用。 5. `zlib`:压缩库。 6. `ncurses`:用于开发终端用户界面的库,编译过程中的部分工具可能需要。 7. `...

    gcc_c++11.tar.gz

    4. **mpfr-4.0.1**:MPFR(Multiple Precision Floating-Point Reliable)是一个用于浮点计算的库,提供了可调整精度的浮点数操作,对于需要精确控制浮点运算的程序特别有用。 5. **isl-0.20**:Integer Set ...

    gcc安装的依赖包

    GCC(GNU Compiler Collection)是GNU项目的一个重要组成部分,它是一个开源的、跨平台的编译器集合,用于将源代码转换为机器可...这对于开发数学软件、科学计算工具以及需要高精度浮点运算的任何应用都是至关重要的。

    gcc-8.3.0安装包及依赖包.rar

    2. **性能提升**:优化了编译器的内部结构,提高了代码生成的效率,尤其是对于浮点运算和多线程代码。 3. **错误和警告信息**:增强了错误和警告信息的清晰度,帮助开发者更快地定位问题。 4. **诊断增强**:增加了...

    GUI计算器【无浮点运算】_stm32_classA_

    【标题】:“GUI计算器【无浮点运算】_stm32_classA_”是指一个基于STM32微控制器的图形用户界面(GUI)计算器项目,它不支持浮点数计算,仅处理整数运算。STM32是意法半导体公司(STMicroelectronics)推出的一种...

    redhat5.3gcc安装所需rpm包及安装顺序

    - mpfr:多精度浮点计算库,用于GCC的浮点运算支持。 - gmp:大整数运算库,为GCC提供大整数支持。 - isl:用于优化GCC的isl库。 - cloog-ppl:用于生成GIMPLE中间表示的代码生成器。 - gcc:GCC编译器本身。 ...

    gcc-11.3.0及其依赖包

    这些库提供了高级数学运算和浮点计算的精确支持,是编译器的基础组件。 6. **调试信息**:GCC 11.3.0可能改进了调试信息的生成,使得开发者使用GDB等调试工具时能够获得更准确、更详尽的信息,帮助定位和解决问题。...

    GCC4.8.2依赖.zip

    MPFR 2.4.2版本提供了精确度和性能的平衡,确保在GCC中进行浮点运算时能获得可靠的精度。 MPC,全称Multiple Precision Complex,是基于GMP和MPFR的复数计算库。它扩展了GMP和MPFR的功能,允许进行复数的任意精度...

    gcc_solaris10安装GCC依赖_

    对于编译需要浮点运算支持的程序来说,这是必不可少的。 4. **MPC**:MPC 库处理复数运算,对需要复数运算的编译有重要作用。 在开始安装之前,确保系统已安装了必要的开发工具,如 make、autoconf、automake、...

Global site tag (gtag.js) - Google Analytics