《C++反汇编与逆向分析技术揭秘》--数据类型
- 浮点数类型
IEEE标准从逻辑上采用一个三元组{S, E, M}来表示一个数N,它规定基数为2,符号位S用0和1分别表示正和负,尾数M用原码表示,阶码E用移码表示。根据浮点数的规格化方法,尾数域的最高有效位总是1,由此,该标准约定这一位不予存储,而是认为隐藏在小数点的左边,因此,尾数域所表示的值是1.M(实际存储的是M),这样可使尾数的表示范围比实际存储多一位。为了表示指数的正负,阶码E通常采用移码方式来表示,将数据的指数e 加上一个固定的偏移量后作为该数的阶码,这样做既可避免出现正负指数,又可保持数据的原有大小顺序,便于进行比较操作。IEEE 754规定了四种表示浮点数值的方式:单精确度(32位)、双精确度(64位)、延伸单精确度(43比特以上,很少使用)与延伸双精确度(79比特以上,通常以80位实现)。只有32位模式有强制要求,其他都是选择性的。大部分编程语言都有提供IEEE浮点数格式与算术,但有些将其列为非必需的。例如,IEEE 754问世之前就有的C语言,有包括IEEE算术,但不算作强制要求(C语言的float通常是指IEEE单精确度,而double是指双精确度)。整体呈现二进制浮点数是以符号数值表示法的格式存储——最高有效位被指定为符号位(sign bit);“指数部分”,即次高有效的e个比特,存储指数部分;最后剩下的f个低有效位的比特,存储“有效数”(significand)的小数部分(在非规约形式下整数部分默认为0,其他情况下一律默认为1)。指数偏移值指数偏移值(exponent bias),是指浮点数表示法中的指数域的编码值为指数的实际值加上某个固定的值,IEEE 754标准规定该固定值为,其中的
为存储指数的比特的长度。
以单精度浮点数为例,它的指数域是8个比特,固定偏移值是。此为有号数的表示方式,单精度浮点数的指数部分实际取值是从-127到128。例如指数实际值为
,在单精度浮点数中的指数域编码值为,即
。
采用指数的实际值加上固定的偏移值的办法表示浮点数的指数,好处是可以用长度为 e个比特的无符号整数来表示所有的指数取值,这使得两个浮点数的指数大小的比较更为容易,实际上可以按照字典序比较两个浮点表示的大小。这种移码表示的指数部分,中文称作阶码。

正单浮点数:
- 25: float fFloat0 = 12.25f;
- 0130723E F3 0F 10 05 CC 2E 3A 01 movss xmm0,dword ptr [__real@41440000 (013A2ECCh)]
- 01307246 F3 0F 11 45 F8 movss dword ptr [fFloat0],xmm0
负单浮点数:

无穷转换二进制:
双浮点数:
浮点数使用:
- 54: // 浮点数使用
- 55: float fFloat = (float)argc;
- 01307272 F3 0F 2A 45 08 cvtsi2ss xmm0,dword ptr [argc]
- 01307277 F3 0F 11 45 C4 movss dword ptr [fFloat],xmm0 //movss 保存单浮点数
- 56: printf("%f", fFloat);//单浮点数作为参数时,需要先转换为双浮点数。
- 0130727C F3 0F 5A 45 C4 cvtss2sd xmm0,dword ptr [fFloat] //cvtsi2ss 单浮点数-->双浮点数
- 01307281 83 EC 08 sub esp,8 //开辟8字节,以保存转换结果
- 01307284 F2 0F 11 04 24 movsd mmword ptr [esp],xmm0 //movsd 保存双浮点数
- 01307289 68 50 2E 3A 01 push offset string "%f" (013A2E50h)
- 0130728E E8 32 A1 FF FF call _printf (013013C5h)
- 01307293 83 C4 0C add esp,0Ch
- 57: argc = (int)fFloat;
- 01307296 F3 0F 2C 45 C4 cvttss2si eax,dword ptr [fFloat] //cvttss2si 单浮点数-->整形
- 57: argc = (int)fFloat;
- 0130729B 89 45 08 mov dword ptr [argc],eax
- 58: printf("%d", argc);
- 0130729E 8B 45 08 mov eax,dword ptr [argc]
- 013072A1 50 push eax
- 013072A2 68 54 2E 3A 01 push offset string "%d" (013A2E54h)
- 013072A7 E8 19 A1 FF FF call _printf (013013C5h)
- 013072AC 83 C4 08 add esp,8
- 59:
- 60: fFloat = GetFloat();
- 013072AF E8 77 C2 FF FF call GetFloat (0130352Bh)
- 013072B4 D9 5D C4 fstp dword ptr [fFloat] //ST(0)出栈,存入[fFloat]
- 61: printf("%f", fFloat);
- 013072B7 F3 0F 5A 45 C4 cvtss2sd xmm0,dword ptr [fFloat] //单浮点数作为参数,转换为双浮点数
- 013072BC 83 EC 08 sub esp,8
- 013072BF F2 0F 11 04 24 movsd mmword ptr [esp],xmm0
- 61: printf("%f", fFloat);
- 013072C4 68 50 2E 3A 01 push offset string "%f" (013A2E50h)
- 013072C9 E8 F7 A0 FF FF call _printf (013013C5h)
- 013072CE 83 C4 0C add esp,0Ch
GetFloat():
- 6: float GetFloat()
- 7: {
- 01307130 55 push ebp
- 01307131 8B EC mov ebp,esp
- 01307133 81 EC C0 00 00 00 sub esp,0C0h
- 01307139 53 push ebx
- 0130713A 56 push esi
- 0130713B 57 push edi
- 0130713C 8D BD 40 FF FF FF lea edi,[ebp-0C0h]
- 01307142 B9 30 00 00 00 mov ecx,30h
- 1: // DataType.cpp : Defines the entry point for the console application.
- 2: //
- 3:
- 4: #include "stdafx.h"
- 5: #include <stdio.h>
- 6: float GetFloat()
- 7: {
- 01307147 B8 CC CC CC CC mov eax,0CCCCCCCCh
- 0130714C F3 AB rep stos dword ptr es:[edi]
- 8: return 12.25f;
- 0130714E D9 05 CC 2E 3A 01 fld dword ptr [__real@41440000 (013A2ECCh)] //关键就这一句,将浮点数存入ST(0)
- 9: }
- 01307154 5F pop edi
- 01307155 5E pop esi
- 01307156 5B pop ebx
- 01307157 8B E5 mov esp,ebp
- 01307159 5D pop ebp
- 0130715A C3 ret
- 字符与字符串
- 布尔类型
- 71: // 布尔类型
- 72: bool bBool;
- 73: if (argc > 0)
- 013072ED 83 7D 08 00 cmp dword ptr [argc],0
- 013072F1 7E 06 jle main+0D9h (013072F9h)
- 74: {
- 75: bBool = true;
- 013072F3 C6 45 A3 01 mov byte ptr [bBool],1 //bool类型占用1字节,true 1;false 0;
- 76: }
- 77: else
- 013072F7 EB 04 jmp main+0DDh (013072FDh)
- 78: {
- 79: bBool = false;
- 013072F9 C6 45 A3 00 mov byte ptr [bBool],0
- 80: }
- 81:
- 82:
- 83: if (bBool == false)
- 013072FD 0F B6 45 A3 movzx eax,byte ptr [bBool]
- 80: }
- 81:
- 82:
- 83: if (bBool == false)
- 01307301 85 C0 test eax,eax
- 01307303 75 0D jne main+0F2h (01307312h)
- 84: {
- 85: printf("布尔类型\r\n");
- 01307305 68 A0 2E 3A 01 push offset string "\xb2\xbc\xb6\xfb\xc0\xe0\xd0\xcd\r\n" (013A2EA0h)
- 0130730A E8 B6 A0 FF FF call _printf (013013C5h)
- 0130730F 83 C4 04 add esp,4
- 86: }
- 地址、指针和引用
- 对指针取内容:
- 89:
- 90: // 对指针取内容
- 91: int nVar = 0x12345678;
- 00E6723E C7 45 F8 78 56 34 12 mov dword ptr [nVar],12345678h
- 92: int *pnVar = &nVar;
- 00E67245 8D 45 F8 lea eax,[nVar] //引用-- 取地址
- 00E67248 89 45 EC mov dword ptr [pnVar],eax //指针变量保存地址
- 93: char *pcVar = (char*)&nVar;
- 00E6724B 8D 45 F8 lea eax,[nVar]
- 00E6724E 89 45 E0 mov dword ptr [pcVar],eax
- 94: short *psnVar = (short*)&nVar;
- 00E67251 8D 45 F8 lea eax,[nVar]
- 00E67254 89 45 D4 mov dword ptr [psnVar],eax
- 95: printf("%08x \r\n", *pnVar);
- 00E67257 8B 45 EC mov eax,dword ptr [pnVar]
- 00E6725A 8B 08 mov ecx,dword ptr [eax] //*pnVar 取4字节类型变量
- 00E6725C 51 push ecx
- 00E6725D 68 50 2E F0 00 push offset string "%08x \r\n" (0F02E50h)
- 00E67262 E8 5E A1 FF FF call _printf (0E613C5h)
- 00E67267 83 C4 08 add esp,8
- 96: printf("%08x \r\n", *pcVar);
- 00E6726A 8B 45 E0 mov eax,dword ptr [pcVar]
- 00E6726D 0F BE 08 movsx ecx,byte ptr [eax] //1字节类型变量
- 00E67270 51 push ecx
- 00E67271 68 50 2E F0 00 push offset string "%08x \r\n" (0F02E50h)
- 00E67276 E8 4A A1 FF FF call _printf (0E613C5h)
- 00E6727B 83 C4 08 add esp,8
- 97: printf("%08x \r\n", *psnVar);
- 00E6727E 8B 45 D4 mov eax,dword ptr [psnVar]
- 00E67281 0F BF 08 movsx ecx,word ptr [eax] //2字节类型变量
- 00E67284 51 push ecx
- 00E67285 68 50 2E F0 00 push offset string "%08x \r\n" (0F02E50h)
- 00E6728A E8 36 A1 FF FF call _printf (0E613C5h)
- 00E6728F 83 C4 08 add esp,8
- 指针偏移:
- //指针偏移
- 100: char cVar[5] = {0x01, 0x23, 0x45, 0x67, 0x89};
- 00217238 C6 45 F0 01 mov byte ptr [cVar],1
- 0021723C C6 45 F1 23 mov byte ptr [ebp-0Fh],23h
- 00217240 C6 45 F2 45 mov byte ptr [ebp-0Eh],45h
- 00217244 C6 45 F3 67 mov byte ptr [ebp-0Dh],67h
- 00217248 C6 45 F4 89 mov byte ptr [ebp-0Ch],89h
- 101:
- 102: int *pnVar = (int*)cVar;
- 0021724C 8D 45 F0 lea eax,[cVar]
- 0021724F 89 45 E4 mov dword ptr [pnVar],eax
- 103: char *pcVar = (char*)cVar;
- 00217252 8D 45 F0 lea eax,[cVar]
- 00217255 89 45 D8 mov dword ptr [pcVar],eax
- 104: short *psnVar = (short*)cVar;
- 00217258 8D 45 F0 lea eax,[cVar]
- 104: short *psnVar = (short*)cVar;
- 0021725B 89 45 CC mov dword ptr [psnVar],eax
- 105: //x86 下指针变量都占4字节
- 106: pnVar += 1;
- 0021725E 8B 45 E4 mov eax,dword ptr [pnVar]
- 00217261 83 C0 04 add eax,4 //int指针指向的变量类型大小为4字节
- 00217264 89 45 E4 mov dword ptr [pnVar],eax //相当于指向cVar[4],
- 107: pcVar += 1;
- 00217267 8B 45 D8 mov eax,dword ptr [pcVar]
- 0021726A 83 C0 01 add eax,1 //char指针指向的变量类型大小为1字节
- 0021726D 89 45 D8 mov dword ptr [pcVar],eax //指向元素cVar[1]
- 108: psnVar += 1;
- 00217270 8B 45 CC mov eax,dword ptr [psnVar]
- 00217273 83 C0 02 add eax,2
- 00217276 89 45 CC mov dword ptr [psnVar],eax //指向元素cVar[2]
- 109:
- 110: printf("%08x \r\n", *pnVar);
- 00217279 8B 45 E4 mov eax,dword ptr [pnVar]
- 109:
- 110: printf("%08x \r\n", *pnVar);
- 0021727C 8B 08 mov ecx,dword ptr [eax]
- 0021727E 51 push ecx
- 0021727F 68 50 2E 2B 00 push offset string "%08x \r\n" (02B2E50h)
- 00217284 E8 3C A1 FF FF call _printf (02113C5h)
- 00217289 83 C4 08 add esp,8
- 111: printf("%08x \r\n", *pcVar);
- 0021728C 8B 45 D8 mov eax,dword ptr [pcVar]
- 0021728F 0F BE 08 movsx ecx,byte ptr [eax]
- 00217292 51 push ecx
- 00217293 68 50 2E 2B 00 push offset string "%08x \r\n" (02B2E50h)
- 00217298 E8 28 A1 FF FF call _printf (02113C5h)
- 0021729D 83 C4 08 add esp,8
- 112: printf("%08x \r\n", *psnVar);
- 002172A0 8B 45 CC mov eax,dword ptr [psnVar]
- 002172A3 0F BF 08 movsx ecx,word ptr [eax]
- 002172A6 51 push ecx
- 002172A7 68 50 2E 2B 00 push offset string "%08x \r\n" (02B2E50h)
- 002172AC E8 14 A1 FF FF call _printf (02113C5h)
- 002172B1 83 C4 08 add esp,8
- 引用类型:
- //引用类型
- 115: int nVar = 0x12345678;
- 0086717E C7 45 F8 78 56 34 12 mov dword ptr [nVar],12345678h
- 116: //引用类型定义
- 117: int &nVarTpye = nVar;
- 00867185 8D 45 F8 lea eax,[nVar]
- 00867188 89 45 EC mov dword ptr [nVarTpye],eax
- 118: //调用函数,参数为引用类型
- 119: Add(nVar);
- 0086718B 8D 45 F8 lea eax,[nVar]
- 0086718E 50 push eax
- 0086718F E8 AF A6 FF FF call Add (0861843h)
- 00867194 83 C4 04 add esp,4
add():
- 11: void Add(int &nVar)
- 12: {
- 008670E0 55 push ebp
- 008670E1 8B EC mov ebp,esp
- 008670E3 81 EC C0 00 00 00 sub esp,0C0h
- 008670E9 53 push ebx
- 008670EA 56 push esi
- 008670EB 57 push edi
- 008670EC 8D BD 40 FF FF FF lea edi,[ebp-0C0h]
- 008670F2 B9 30 00 00 00 mov ecx,30h
- 008670F7 B8 CC CC CC CC mov eax,0CCCCCCCCh
- 008670FC F3 AB rep stos dword ptr es:[edi]
- 13: nVar++;
- 008670FE 8B 45 08 mov eax,dword ptr [nVar]
- 00867101 8B 08 mov ecx,dword ptr [eax]
- 00867103 83 C1 01 add ecx,1
- 00867106 8B 55 08 mov edx,dword ptr [nVar]
- 00867109 89 0A mov dword ptr [edx],ecx
- 14: }
- 0086710B 5F pop edi
- 0086710C 5E pop esi
- 0086710D 5B pop ebx
- 0086710E 8B E5 mov esp,ebp
- 00867110 5D pop ebp
- 00867111 C3 ret
- 常量
- //const常量修改
- 132:
- 133: const int nConst = 5;
- 00867197 C7 45 E0 05 00 00 00 mov dword ptr [nConst],5
- 134: int *pConst = (int*)&nConst;
- 0086719E 8D 45 E0 lea eax,[nConst]
- 008671A1 89 45 D4 mov dword ptr [pConst],eax
- 135: *pConst = 6;
- 008671A4 8B 45 D4 mov eax,dword ptr [pConst]
- 008671A7 C7 00 06 00 00 00 mov dword ptr [eax],6
- 136: int nVar1 = nConst;
- 008671AD C7 45 C8 05 00 00 00 mov dword ptr [nVar1],5 //由于const修饰的变量nConst被赋值一个数字常量5,
//编译器在编译过程中发现nConst的初值是可知的,并且被修饰为const。之后所有使用nConst的地方都以这个可预知值替换,
//故int nVar=nConst;对应的汇编代码没有将nConst赋值给nVar,而是用常量值5代替。如果nConst的值为一个未知值,那么编译器将不会做此优化。
#define是一个真常量,而const却是由编译器判断实现的常量,是一个假常量。在实际中,使用const定义的变量,最终还是一个变量,只是在编译器内进行了检查,发现有修改则报错。
由于编译器在编译期间对const变量进行检查,因此被const修饰过的变量是可以修改的。利用指针获取到const修饰过的变量地址,强制将指针的const修饰去掉,就可以修改对应的数据内容

《C++反汇编与逆向分析技术揭秘》--数据类型的更多相关文章
- C++反汇编与逆向分析技术揭秘
C++反汇编-继承和多重继承 学无止尽,积土成山,积水成渊-<C++反汇编与逆向分析技术揭秘> 读书笔记 一.单类继承 在父类中声明为私有的成员,子类对象无法直接访问,但是在子类对象的 ...
- 《C++反汇编与逆向分析技术揭秘》--算术运算和赋值
一.加法 1.Debug下: 14: int nVarOne0 = 1 + 5 - 3 * 6;//编译时计算得到结果 00C0550E C7 45 F8 F4 FF FF FF mov dword ...
- 《C++反汇编与逆向分析技术揭秘》--认识启动函数,找到用户入口
<C++反汇编与逆向分析>和<程序员的自我修养>都是以VC6的代码作为例子讲解的.这里是在vs2017下,CRT代码有些区别,但整体流程上都是初始化环境,设置参数,最后转到用户 ...
- 《C++反汇编与逆向分析技术揭秘》——基本数据类型的表现形式
---恢复内容开始--- 基本的浮点数指令 示例代码: Visual Studio 2013的反汇编代码是: 对于movss,表示移动标量单精度浮点值 将标量单精度浮点值从源操作数(第二个操作数)移到 ...
- 《C++反汇编与逆向分析技术揭秘》——观察各种表达式的求值过程
---恢复内容开始--- 加法: 示例: 常量相加,则在编译期间就计算出两个常量相加后的结果,直接将这个结果参与运算,减少了运行期的计算.当有变量参与运算时,会先取出内存中的数据,放入通用寄存器中,再 ...
- 《C++反汇编与逆向分析技术揭秘》之十——构造函数
对象生成时会自动调用构造函数.只要找到了定义对象的地方,就找到了构造函数调用的时机.不同作用域的对象的生命周期不同,如局部对象.全局对象.静态对象等的生命周期各不相同,只要知道了对象的生命周期,便可以 ...
- 《C++反汇编与逆向分析技术揭秘》——函数的工作原理
各种调用方式的考察 示例: cdecl方式是调用者清空堆栈: 如果执行的是fastcall: 借助两个寄存器传递参数: 参数1和2借助局部变量来存储: 返回值 如果返回值是结构体: 返回值存放在eax ...
- 《C++反汇编与逆向分析技术揭秘》——流程控制语句的识别
if...else...语句 示例: if构成多分支语句 switch 有序线性的switch: 3E82D8位置存放了一个表,标明了要跳转到的地址: 这里的每四字节都标明的是每个case块的首地址: ...
- 《C++反汇编与逆向分析技术揭秘》之12——继承
识别类和类之间的关系 在父类中声明为私有的成员,虽然子类对象无法直接访问,但是在子类对象的内存结构中,父类私有的成员数据依然存在. 在没有提供构造函数的时候,系统会尝试提供默认的构造函数: 当子类中没 ...
随机推荐
- UI Design & App & Free Icons
UI Design & App & Free Icons icons8 https://icons8.com https://icons8.com/ouch Ouch可以帮助那些不进行 ...
- Flutter Hackathon 2020
Flutter Hackathon 2020 https://flutterhackathon.com/#/ Flutter Day https://mp.weixin.qq.com/s/ux17-A ...
- shit mint-ui & navbar click event bug
shit mint-ui & navbar click event bug # Vue 2.0 npm install mint-ui -S // 引入全部组件 import Vue from ...
- 小程序 in action
小程序 in action https://github.com/xgqfrms/xcx-taro taro https://taro-docs.jd.com/taro/docs/README.htm ...
- HTML5 & custom element & template
HTML5 & custom element & template template https://codepen.io/xgqfrms/pen/eYYExvp https://cs ...
- js {}与class属性描述符的区别
let data = { name: "ajanuw", change() { this.name = "Ajanuw"; }, get message() { ...
- 聊一下PBN程序图例中的XTT
PBN航路点的定位容差用XTT与ATT来表示,ATT=0.8*XTT.保护区半宽用1.5*XTT+BV计算得到,BV值在不同的航段取值不同. 对于A至E类航空器,距ARP 30nm以外BV值为2 ...
- 联童科技基于incubator-dolphinscheduler从0到1构建大数据调度平台之路
联童科技是一家智能化母婴童产业平台,从事母婴童行业以及互联网技术多年,拥有丰富的母婴门店运营和系统开发经验,在会员经营和商品经营方面,能够围绕会员需求,深入场景,更贴近合作伙伴和消费者,提供最优服务产 ...
- c/c++ 之静态库
静态库 编译成目标文件(未链接) g++ -c a.cc b.cc c.cc d.cc #生成 a.o b.o c.o d.o 将目标文件打包为静态库 ar rs libxxx.a a.o b.o c ...
- Python数据结构与算法_删除排序数组中的重复项(06)
给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成. ...