浮点数:不同的内存存储格式,当整型变量赋值给浮点型变量会发生什么?

问题: 计算机存储中,整型数据是以补码的形式存储在存储介质中,而浮点型数据是遵循IEEE754标准将数据存储在存储介质中。当整型变量赋值给浮点型变量的时候,对于两种不同的存储形式,计算机是怎么完成数据的复制?

首先,编一个简单的C程序,通过编译生成的汇编文件看一下计算机是怎么处理的。

/*文件名:1.c*/
#include <stdio.h>
int main(int argc, const char *argv[])
{
	int a = 9;
	float b = 1.0;
	b = a;
	return 0;
}

生成汇编代码:

gcc -S 1.c -o 1.s

汇编代码:

	.file	"1.c"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushl	%ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	.cfi_def_cfa_register 5
	subl	$16, %esp
	movl	$9, -4(%ebp)   ;初始化a = 9
	movl	.LC0, %eax
	movl	%eax, -8(%ebp) ;初始化b = 1.0
	fildl	-4(%ebp) ;fildl指令用于将整型压入浮点型寄存器FPU的数据寄存器st
	fstps	-8(%ebp) ;将st寄存器准换为单精度数据保存到b变量中,出栈
	movl	$0, %eax
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.section	.rodata
	.align 4
.LC0:
	.long	1065353216     ;这是十进制,表示浮点数1.0,这里根据CPU的情况,将浮点型常量以长整型8个字节进行存储
	.ident	"GCC: (GNU) 4.8.5"
	.section	.note.GNU-stack,"",@progbits

这里需要注意两条指令:
1、fildl -4(%ebp)
;fildl指令用于将整型压入浮点型寄存器FPU,就是将a存储单元内的数据(补码格式)经过硬件转换为浮点型存储格式存储到st数据寄存器中,即从内存中到寄存器中。

FPU的数据寄存器共有8个,每个都是80个位(10字节),如果是浮点型数据复制到80个位寄存器中,不是简单的从最低位开始,逐一进行对应复制,需要根据符号位、阶数位、尾数位进行对应的转换复制。

2、fstps -8(%ebp)
将st数据寄存器中的浮点数保存到b变量中,即从寄存器到内存中,因为st数据寄存器是80位的,一般复制到单精度、双精度会造成数据的数据丢失,导致程序出现奇怪的问题,所以为了稳妥起见,尽量使用变量类型为long double而非float、double型。

在这里插入图片描述
参考资料:
剖析Intel IA32架构下C语言及CPU浮点数机制

通用寄存器

顾名思义,通用寄存器是那些你可以根据自己的意愿使用的寄存器,但有些也有特殊作用,IA32处理器包括8个通用寄存器,分为3组。

1、数据寄存器:

EAX 累加寄存器,常用于运算;在乘除等指令中指定用来存放操作数,另外,所有的I/O指令都使用这一寄存器与外界设备传送数据。
EBX 基址寄存器,常用于地址索引

2、变址寄存器:

ECX 计数寄存器,常用于计数;常用于保存计算值,如在移位指令,循环(loop)和串处理指令中用作隐含的计数器.
EDX 数据寄存器,常用于数据传递。

3、指针寄存器:

EBP为基址指针(Base Pointer)寄存器,存储当前栈帧的底部地址。
ESP为堆栈指针(Stack Pointer)寄存器,一直记录栈顶位置,不可直接访问,push时ESP减小,pop时增大。

指令指针寄存器

EIP 保存了下一条要执行的指令的地址, 每执行完一条指令EIP都会增加当前指令长度的位移,指向下一条指令。用户不可直接修改EIP的值,但jmp、call和ret等指令也会改变EIP的值,jmp将EIP修改为目的指令地址,call修改EIP为被调函数第一条指令地址,ret从栈中取出(pop)返回地址存入EIP。

寄存器详细参考:
汇编速查-IA32寄存器组织

拓展阅读:

AT&T 与 Intel 的汇编语言语法区别

AT&T汇编语言初步

汇编语言学习笔记(十二)-浮点指令

Linux 汇编语言开发

linux下汇编语言开发总结

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值