【反汇编3】基本数据类型的表现形式
参考书籍,《C++反汇编与逆向分析技术揭秘》。
这次主要研究各种数据在计算机里怎么存的,又要涉及补码、科学计数法等基础内容。这些课程计算机专业的都会学,但作为程序员未必有直观的体验,比如java或python程序员,他们不用自己管理内存,也就根本不会接触到这类内容,例如int i = -1; 对于他们也就意味着i这个变量为-1,他们不会去了解,在内存里i这个变量其实是FF FF FF FF。
如果要学反汇编,或作底层C的,这些知识就是很常用且很基础的了。
我作为一个java程序员来通过反汇编学习下,底层大神就请无视好了。
第一段 C代码如下:
# include <stdio.h> void main() { int i = -1; int i1 = 1; int *p = &i; int *p1 = &i1; }
一个无符号的i,一个有符号的i1。使用指针目的是获取到变量地址。
反汇编:
# include <stdio.h> void main() { 009917B0 push ebp 009917B1 mov ebp,esp 009917B3 sub esp,0F0h 009917B9 push ebx 009917BA push esi 009917BB push edi 009917BC lea edi,[ebp-0F0h] 009917C2 mov ecx,3Ch 009917C7 mov eax,0CCCCCCCCh 009917CC rep stos dword ptr es:[edi] int i = -1; 009917CE mov dword ptr [i],0FFFFFFFFh int i1 = 1; 009917D5 mov dword ptr [i1],1 int *p = &i; 009917DC lea eax,[i] 009917DF mov dword ptr [p],eax int *p1 = &i1; 009917E2 lea eax,[i1] 009917E5 mov dword ptr [p1],eax } 009917E8 xor eax,eax 009917EA push edx 009917EB mov ecx,ebp 009917ED push eax 009917EE lea edx,ds:[991804h] 009917F4 call @_RTC_CheckStackVars@8 (09911D1h) 009917F9 pop eax 009917FA pop edx }
单步调试,到指针那里,观察寄存器eax的值(指针的值临时存储在eax)。那就是变量的内存地址。然后查找该地址。可以看到i在内存中为ffffffff。-1的补码(1的反码+1)。
继续单步下去:
可以看到1在内存里存为01000000,这是“小尾”存储的方式,也就是说以字节为单位,低数据存在内存低端,高数据存在内存高端。如果是“大尾"方式,则应为00000001。
float 单精度浮点数 第一位符号位,8位指数,23位尾数。
double 双精度浮点数 第一位符号位,11位指数,52位尾数。
由截图可知,1.01在内存中存为29 5c 8f c2 f5 f0 3f
因为”小尾“实际为 3f f0 f5 c2 8f 5c 29
即为0011 1111 1111 0000 0010 1000 1111 0101 1100 0010 1000 1111 0101 1100 0010 1001
符号0
指数011 1111 1111