C++逆向之基本数据类型的表现形式

实验环境为VS2015
#include 

void decodeOprand()
{
    /*
    00C91650  push        ebp
    00C91651  mov         ebp,esp
    00C91653  sub         esp,0C0h              // 默认提高堆栈的大小为C0h;在x86系统中,内存是小端存储方式
    00C91659  push        ebx
    00C9165A  push        esi
    00C9165B  push        edi
    00C9165C  lea         edi,[ebp-0C0h]
    00C91662  mov         ecx,30h
    00C91667  mov         eax,0CCCCCCCCh        // 填充为0CCCCCCCCh,防止中间出现问题,如果出现问题则可以及时的产生中断,以便调试器可以接收到中断
    00C9166C  rep stos    dword ptr es:[edi]
    */

    // 防止被和谐
    // 00C9166E  mov         dword ptr [i],0  
    // 去掉 右键->显示符号名后可以看到
    // 00C9166E  mov         dword ptr [ebp-8],0  
    // 可以证明i <=> ebp-8;即我们声明的变量符号i,在汇编中代表的是地址ebp-8;也可以看出来是栈变量;即局部变量为栈变量
    // 第一个变量的起始地址为ebp-8;
    // int i = 0;   

    // 00F41A75  mov         dword ptr [ebp - 14h], 2
    // 增长的幅度为 0x14h - 0x08h = 0Ch;
    // int b = 2;
    // int c = 3;

    char a = 1;
    // char d = 4;
    // short b = 2;
    int c = 3;
    // short e = 5;

    // 相同的差0Ch,不同之间差0Fh
    // short和int之间是一样的,只是对地址的解释不一样
    // short是将从[]地址解释为word大小;int是将从[]地址解释为dword大小
    // 以有符号整数进行解释
    // 在分析过程中其实无需知道到底是哪个,只需要知道每个内存单元的功能,以及怎么解释的即可
}

void decodePointer()
{
    int nVar = 0x12345678;
    int* pnVar = &nVar;
    char* pcVar = (char*)&nVar;
    short* psnVar = (short*)&nVar;

    printf("%08x \r\n", *pnVar);
    printf("%08x \r\n", *pcVar);
    printf("%08x \r\n", *psnVar);
}

void decodePointerOperator()
{
    // cVar 代表的是数组的第一个数据的首地址 
    // __cdecl调用约定,参数传递为从右到左;调用方负责清理堆栈
    // 00834B48  mov         byte ptr [ebp-10h],1 
    char cVar[5] = { 0x01,0x23,0x45,0x67,0x89 };

    // 01194B5C  lea         eax,[ebp-10h]  
    // 01194B5F  push        eax
    printf("%x\r\n", cVar);
    int* pnVar = (int*)cVar;
    char* pcVar = (char*)cVar;
    short* psnVar = (short*)cVar;

    /*
    00C34B6E  mov         eax,dword ptr [ebp-1Ch]
    00C34B71  add         eax,4
    00C34B74  mov         dword ptr [ebp-1Ch],eax

    00C34B77  mov         eax,dword ptr [ebp-28h]
    00C34B7A  add         eax,1
    00C34B7D  mov         dword ptr [ebp-28h],eax

    00C34B80  mov         eax,dword ptr [ebp-34h]
    00C34B83  add         eax,2
    00C34B86  mov         dword ptr [ebp-34h],eax
    */

    // 首地址 + sizeof(指针type) * n;
    pnVar += 1;
    pcVar += 1;
    psnVar += 1;

    // 每加一个*就是在这个指针的type上减掉一个星

    int a = 1;
    int* i = &a;
    int** pI = &i;
    int*** pPi = &pI;
    int**** p = &pPi;

    /*
    01054C89  mov         eax,dword ptr [ebp-70h]
    // 下面是*的操作,有几句就是几颗*
    01054C8C  mov         ecx,dword ptr [eax]
    01054C8E  mov         edx,dword ptr [ecx]
    01054C90  mov         eax,dword ptr [edx]
    01054C92  mov         ecx,dword ptr [eax]
    */

    printf("%x\r\n",****p);

    // * 的运用:假设int**** p = (int****)&nVar; 那么***p == nVar;
}

void usePointer()
{
    // 要修改被const限制的局部变量i
    const int i = 10;

    int* pnI = (int*)&i;
    *pnI = 20;
    
    // 在内存中其实已经改了,但是为什么输出的还是10呢
    // 答案是常量传播,看反汇编即可明确
    /*
    008B4B64  push        0Ah
    008B4B66  push        8B6C0Ch
    008B4B6B  call        008B1352
    */
    // 经由常量传播,直接吧0Ah传递给了printf函数
    printf("%d %d\r\n",i,*pnI);
}
int main()
{
    decodeOprand();
    decodePointer();
    decodePointerOperator();

    usePointer();
    getchar();
    return 0;
}

你可能感兴趣的:(C++逆向之基本数据类型的表现形式)