-
-
[原创]从反汇编的角度学C/C++之浮点数,结构体与联合体
-
发表于:
2021-9-27 18:19
7670
-
[原创]从反汇编的角度学C/C++之浮点数,结构体与联合体
在C/C++中,浮点数分别用float和double来表示。其中,float占4个字节,double占8个字节。由于计算机只能存储整数,不能存储小数。所有浮点数在计算机中的保存与使用是使用了特殊的编码方式,即IEEE编码。这里不讨论IEEE编码,仅仅从反汇编的角度看看浮点数的存储与使用。
首先,与普通的数据类型不同,对于浮点数的操作是通过一组特殊的寄存器来实现的。这组特殊的寄存器就是x87 FPU寄存器,这组寄存器一共有八个用来存储浮点数的寄存器,分别是ST(0)-ST(7),每个寄存器都是八位寄存器。而对于这组寄存器的操作也是通过一组特殊的浮点数指令来进行操作。常见的浮点数指令表如下图所示,而对于其他的指令和基础指令的差别只是多了一个F,如fsub,fdiv,fmul。
其次,这一组浮点寄存器是以栈的形式使用,ST(0)是栈顶,ST(7)是栈底。也就是说当ST(0)有值的时候,如果我们在往里面放数据的话,计算机就会把ST(0)的数据放入ST(1),在把我们的数据放入ST(0),当要取出数据的时候,也是首先从ST(0)中取出数据。下面根据一个实例来看看这些指令是如何应用的,其中的iNum是传入的整型参数。
C/C++程序员可以通过使用结构体来自定义一组由程序员自己指定的不同类型的数据,那么他在内存中是如何保存的呢?考虑如下的结构体,为了方便展示,我们用#pragma pack(1)是指定对齐长度为1。
之后我们对结构体进行初始化和赋值。
从上述的反汇编代码我们可以看出,当在程序中声明了一个结构体的变量,程序就会在内存中开辟一个足够将结构体中所有变量都容纳进去的内存,并按照声明顺序从低地址到高地址存储我们的变量,而test则是这个结构体的地址。
当程序运行到00BE1113的时候,如果查看test地址对应的内存可以看到如下结果。
可以看到我们的数据按照声明顺序放入了内存中。
既然test代表了地址,那么结构体的赋值操作是否只是地址的复制呢?请看下面的示例:
可以看到对于结构体的赋值操作,程序会把对应的结构体的值全部赋值过去。当程序执行到0x00BE1145的时候,查看ebp-0x2C,即test2地址的内存时候可以看到如下结果。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2021-10-20 11:14
被1900编辑
,原因: