《C++反汇编与逆向分析技术揭秘》笔记-第2章基本数据类型的表现形式

文章详细介绍了不同整数类型如int,long,short,longlong的取值范围和存储方式,包括无符号和有符号整数的特点。同时,阐述了浮点数如float和double的IEEE编码规则以及转换过程。此外,提到了字符和字符串的表示,布尔类型bool,以及指针和常量的特性,包括const修饰的变量在编译期间的检查和#define的差异。
摘要由CSDN通过智能技术生成

2.1整数类型 int(4B)、long(4B)、short(2B)、long long(8B)


无符号整数:表示正数
1)所有位都用来表示数值。
2)以unsigned int为例,取值范围为0x00000000-0xFFFFFFFF,转换十进制为0-4294967295。当无符号整数不足32位时,用0填充剩余高位。
3)在内存中都是以真值的形式存放的,每一位都可以参与数据表达。

有符号整数:负数和正数
1)最高位表示符号(符号位),0表示正数,1表示负数。因此有符号整数的取值范围要比无符号整数取值范围少1位。
2)以int为例,取值范围为0x80000000-0x7FFFFFFF,转换十进制为-2147483648-2147483647。正数表示区间位0x00000000-0x7FFFFFFF,负数表示区间为0x80000000-0xFFFFFFFF,负数在内存中都是以补码形式存放的,补码规则:数值位取反加1。
因为对于任何4字节的数值x,都有x+x(反)=0xFFFFFFFF,于是x+x(反)+1=0(超出了存储范围,进位被舍弃),所以-x=x(反)+1。
3)有符号整数都是以补码形式存储的,因为计算机只会做加法,即x-y=x+y(补)。例如3-2=3+(-2),-2的补码为0xFFFFFFFE,得到0x00000001。
4)负数区间总比正数区间多一个最小值的原因是,没有必要再用负数0。

2.2浮点数类型 float(4B)、double(8B)


1)有符号
2)将浮点数强制转换为整数时,不会采用四舍五入的方式,而是舍弃小数部分。
3)整数类型是将十进制转换成二进制保存在内存中,以十六进制方式显示。浮点类型并不是将一个浮点小数直接转换成二进制数保存,而是将浮点小数转换成的二进制码重新编码,再进行存储。
4)float类型的IEEE编码格式如下。


以12.25f为例
二进制部分:1100.01
科学记数法表示:二进制部分为1.10001,指数部分为3(小数点向左移动,每移动一次,指数加1,移动到数值位最高位为1处,停止移动)
经IEEE转换后:
符号位:0
指数位:十进制3+127=130,转换为二进制为10000010(加127是因为指数可能出现负数)
尾数位:10001(由于尾数位中最高位1是固定值,故忽略不计,只要在转换回十进制数时加1即可) 0000 0000 0000 0000 00(当不足23位时,用0填充剩余低位)
即IEEE浮点编码:01000001010001000000000000000000,转换成十六进制数为0x41440000,内存中为00 00 44 41(内存以小尾方式存放)

以-0.125f为例
二进制部分:0.001
科学记数法表示:二进制部分为1.0,指数部分为-3
经IEEE转换后:
符号位:1
指数位:十进制-3+127=124,转换为二进制为01111100
尾数位:0000 0000 0000 0000 0000 000
即IEEE浮点编码:10111110000000000000000000000000,转换成十六进制数为0xBE000000,内存中为00 00 00 BE。

以1.3f为例(无穷)
二进制部分:1.01001100110011001100110(到23位终止)
科学记数法表示:二进制部分为1.01001100110011001100110,指数部分为0
经IEEE转换后:
符号位:0
指数位:十进制0+127=127,转换为二进制为01111111
尾数位:01001100110011001100110
即IEEE浮点编码:00111111101001100110011001100110,转换成十六进制数为0x3FA66666,内存中为66 66 A6 3F。
注意,再次将这个IEEE编码值转换成十进制小数,得到的值为1.2516582,四舍五入保留一位小数后为1.3。这就解释了为什么C++在比较浮点数值是否为0时,要做一个区间比较而不是直接进行等值比较。

5)double类型的IEEE编码:类似,最高位为符号位,指数位占11位(加1023后用于指数符号判断),尾数位占52位。 

6)常用SSE浮点数指令表如下。

7)x64_vs对应汇编代码如下。

另外,printf函数以浮点数方式输出时(%f),对应参数是8个字节长度。

2.3字符和字符串


1)以'\0'作为字符串结束标志。
2)Unicode是ASCII的升级编码格式。ASCII编码(1B),表示范围0-255,使用char。Unicode编码(2B),表示范围0-65535,使用wchar_t。
3)使用char*、wchar_t*来保存字符串首地址。

4)x64_vs对应汇编代码如下。

2.4布尔类型 bool(1B)

2.5地址、指针和引用


1)由于指针保存的数据是地址,所以无论什么类型的指针,在32位程序里占4B,在64位程序里占8B。
2)指针用类型去解释这个地址中的数据,即指针只保存了存放数据的首地址,根据类型来寻找解释数据的结束地址。
3)指针加法用于地址偏移,运算结果取决于指针类型。因为当指针保存的地址为数组首地址时,为了能够利用指针加1后访问到数组内下一成员,所以加的是类型长度,而非数字1。
4)指针和地址的异同点如下。

5)x64_vs对应汇编代码如下。

输出结果如下。

 注意,p2取出了arr数组以外的数据。

2.6常量


1)#define修饰的符号名称是一个真量数值。
2)const修饰的栈变量,是一个”假“常量,始终是一个变量,只是在编译期间对语法进行了检查,发现代码有对const修饰的变量存在直接修改行为则报错。本质上是可以被修改的,利用指针获取const修饰的栈变量地址,强制将const属性修饰去掉,就可以修改对应数据内容。

3)#define与const区别如下。

4) x64_vs对应汇编代码如下。
另外,由于const修饰的变量n1被赋值5,编译器在编译过程中发现n1的初始值是可知的,所以之后所有使用n1的地方都替换为这个可预知值。即int n2=n1;对应的汇编代码没有将n1赋值给n2,而是用常量值5代替(这是编译器的优化)。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值