• 汇编的角度分析C语言结构体


    1、定义:结构是 C 编程中另一种用户自定义的可用的数据类型,它允许您存储不同类型的数据项。

    2、结构也可以看做是一种数据类型,与int float short char是平级关系

    3、示例:

      加入开发一款游戏,需要生命值,魔法值,坐标等等的 AA   然后其中包含坐标的结构体Point 

      

    struct Point
    {
         float x;
         float y;
         float z;
       
    }
    
    
    
    struct AA           //定义一个 AA Game;   [0x41234566]   基址
    {                   //一级偏移
          int 生命;     //+4    
          int 魔法;     //+ 8
          Point 坐标     //+10[坐标]
                                         //二级偏移
                                         //+4   float x
                                         //+8   float y   
    }

      

     4、结构体的反汇编分析:

     源码:

    #include "stdafx.h"
    
    
    struct st
    {
        int a;
        char b;
        short c;
    };
    //全局变量
    st x;
    
    void fun()
    {
        x.a=10;
        x.b=20;
        x.c=30;
    }
    
    void fun2()
    {
        int i=x.a;
        int j=x.b;
        int k=x.c;
    
        printf("%d %d %d",i,j,k);
    }
    
    
    
    int main(int argc, char* argv[])
    {
        fun();
        fun2();
        return 0;
    }

    反汇编:(fun 函数的反汇编)

    00401030   push        ebp
    00401031   mov         ebp,esp
    00401033   sub         esp,40h         //初始化堆栈依旧是0x40,没有提升堆栈的空间,和空实现的函数声明的空间一致
    00401036   push        ebx
    00401037   push        esi
    00401038   push        edi
    00401039   lea         edi,[ebp-40h]
    0040103C   mov         ecx,10h
    00401041   mov         eax,0CCCCCCCCh
    00401046   rep stos    dword ptr [edi]
    00401048   mov         dword ptr [x (00427c48)],0Ah                      //int a 数据宽度为 dword 且直接复制到了内存中,而非在堆栈中。全局变量
    00401052   mov         byte ptr [x+4 (00427c4c)],14h    //数据宽度为 byte               
    00401059   mov         word ptr [x+6 (00427c4e)],offset fun+30h (00401060) //数据宽度为 word
    00401062   pop         edi
    00401063   pop         esi
    00401064   pop         ebx
    00401065   mov         esp,ebp
    00401067   pop         ebp
    00401068   ret

    fun2的反汇编代码分析:

    00401080   push        ebp
    00401081   mov         ebp,esp
    00401083   sub         esp,4Ch  //提升了缓冲区的空间,三个变量多提升了 0xCh个字节的空间。
    00401086   push        ebx
    00401087   push        esi
    00401088   push        edi
    00401089   lea         edi,[ebp-4Ch]
    0040108C   mov         ecx,13h
    00401091   mov         eax,0CCCCCCCCh
    00401096   rep stos    dword ptr [edi]
    00401098   mov         eax,[x (00427c48)]     //内存的值取到了寄存器
    0040109D   mov         dword ptr [ebp-4],eax    //寄存器的值给了局部变量,复制到了堆栈中。也就是复制的过程,而内存的值并没有消失
    004010A0   movsx       ecx,byte ptr [x+4 (00427c4c)]   //宽度不到4个字节的,带符号扩展了
    004010A7   mov         dword ptr [ebp-8],ecx     //扩展后,重新复制到堆栈中
    004010AA   movsx       edx,word ptr [x+6 (00427c4e)]
    004010B1   mov         dword ptr [ebp-0Ch],edx
    004010B4   mov         eax,dword ptr [ebp-0Ch]
    004010B7   push        eax
    004010B8   mov         ecx,dword ptr [ebp-8]
    004010BB   push        ecx
    004010BC   mov         edx,dword ptr [ebp-4]
    004010BF   push        edx
    004010C0   push        offset string "%d %d %d" (0042201c)
    004010C5   call        printf (00401150)
    004010CA   add         esp,10h
    004010CD   pop         edi
    004010CE   pop         esi
    004010CF   pop         ebx
    004010D0   add         esp,4Ch
    004010D3   cmp         ebp,esp
    004010D5   call        __chkesp (004011d0)
    004010DA   mov         esp,ebp
    004010DC   pop         ebp
    004010DD   ret

    5、结构体中声明结构体的反汇编

    源码 :

    struct Point    
    {    
        double x;
        double y;
        double z;
    };    
    
    
    struct BB
    {
        int i;
        int j;
        Point p;
        char name[20]; //20字符 10中文
    };
    BB b;
    void fun(){
    
        b.i=3;
        b.j=6;
        b.p.x=13.4;
        b.p.y=17.6;
        b.p.z=21.3;
    
    }
    
    
    
    int main(int argc, char* argv[])
    {
        fun();
        return 0;
    }

    反汇编分析:

    00401020   push        ebp
    00401021   mov         ebp,esp
    00401023   sub         esp,40h
    00401026   push        ebx
    00401027   push        esi
    00401028   push        edi
    00401029   lea         edi,[ebp-40h]
    0040102C   mov         ecx,10h
    00401031   mov         eax,0CCCCCCCCh
    00401036   rep stos    dword ptr [edi]
    00401038   mov         dword ptr [b (0042bfe0)],3
    00401042   mov         dword ptr [b+4 (0042bfe4)],6
    0040104C   mov         dword ptr [b+8 (0042bfe8)],0CCCCCCCDh
    00401056   mov         dword ptr [b+0Ch (0042bfec)],402ACCCCh
    00401060   mov         dword ptr [b+10h (0042bff0)],9999999Ah
    0040106A   mov         dword ptr [b+14h (0042bff4)],40319999h
    00401074   mov         dword ptr [b+18h (0042bff8)],0CCCCCCCDh
    0040107E   mov         dword ptr [b+1Ch (0042bffc)],40354CCCh
    00401088   pop         edi
    00401089   pop         esi
    0040108A   pop         ebx
    0040108B   mov         esp,ebp
    0040108D   pop         ebp
    0040108E   ret

    6、结构体作为参数分析:

    源码:

    struct st    
    {    
        char a;
        short b;
        int c;
        int d;
        int e;
        
    };    
    void Function(st s)    
    {    
        
    }    
    int main(int argc, char* argv[])    
    {    
        st s;
        s.a = 1;
        s.b = 2;
        s.c = 3;
        s.d = 4;
        s.e = 5;
        
        Function(s);
        
        
        return 0;
    }    

    反汇编分析:

    00401040   push        ebp
    00401041   mov         ebp,esp
    00401043   sub         esp,50h        
    00401046   push        ebx
    00401047   push        esi
    00401048   push        edi
    00401049   lea         edi,[ebp-50h]
    0040104C   mov         ecx,14h
    00401051   mov         eax,0CCCCCCCCh
    00401056   rep stos    dword ptr [edi]
    00401058   mov         byte ptr [ebp-10h],1    //char类型一个字节
    0040105C   mov         word ptr [ebp-0Eh],offset main+20h (00401060)    //short类型两个字节
    00401062   mov         dword ptr [ebp-0Ch],3    //int类型
    00401069   mov         dword ptr [ebp-8],4   //int类型
    00401070   mov         dword ptr [ebp-4],5   //int类型
    00401077   sub         esp,10h      //堆栈提升0x10个字节
    0040107A   mov         eax,esp
    0040107C   mov         ecx,dword ptr [ebp-10h]    //main函数第一个局部变量与第二个局部变量存入ecx中
    0040107F   mov         dword ptr [eax],ecx    //把ecx放入到当前栈顶的位置
    00401081   mov         edx,dword ptr [ebp-0Ch]
    00401084   mov         dword ptr [eax+4],edx//把main函数的第三个局部变量复制到当前栈顶+4的地方
    00401087   mov         ecx,dword ptr [ebp-8]
    0040108A   mov         dword ptr [eax+8],ecx//把main函数的第四个局部变量复制到当前栈顶+8的位置
    0040108D   mov         edx,dword ptr [ebp-4]
    00401090   mov         dword ptr [eax+0Ch],edx//把main函数的第五个局部变量复制到当前栈顶+C的位置
    00401093   call        @ILT+10(fun) (0040100f)

    7、结构体作为返回值分析:

      源码:

    struct st    
    {    
        char a;
        short b;
        int c;
        int d;
        int e;
        
    };    
    st Function()    
    {    
        st s;
        s.a = 1;
        s.b = 2;
        s.c = 3;
        s.d = 4;
        s.e = 5;
        
        return s;
    };    
    int main(int argc, char* argv[])    
    {    
        st s = Function();
        
        
        return 0;
    }    

    反汇编分析:

    00410720   push        ebp
    00410721   mov         ebp,esp
    00410723   sub         esp,50h
    00410726   push        ebx
    00410727   push        esi
    00410728   push        edi
    00410729   lea         edi,[ebp-50h]
    0041072C   mov         ecx,14h
    00410731   mov         eax,0CCCCCCCCh
    00410736   rep stos    dword ptr [edi]
    00410738   mov         byte ptr [ebp-10h],1                             
    0041073C   mov         word ptr [ebp-0Eh],offset Function+20h (00410740)    //局部变量赋值
    00410742   mov         dword ptr [ebp-0Ch],3                            
    00410749   mov         dword ptr [ebp-8],4                              
    00410750   mov         dword ptr [ebp-4],5                              
    00410757   mov         eax,dword ptr [ebp+8]                            //main方法压入的一个参数,也就是s的地址
    0041075A   mov         ecx,dword ptr [ebp-10h]
    0041075D   mov         dword ptr [eax],ecx         
    0041075F   mov         edx,dword ptr [ebp-0Ch]
    00410762   mov         dword ptr [eax+4],edx                            //依次把局部变量的值,放入以main方法传进来的地址为首的连续的地址中
    00410765   mov         ecx,dword ptr [ebp-8]
    00410768   mov         dword ptr [eax+8],ecx       
    0041076B   mov         edx,dword ptr [ebp-4]
    0041076E   mov         dword ptr [eax+0Ch],edx     
    00410771   mov         eax,dword ptr [ebp+8]
    00410774   pop         edi
    00410775   pop         esi
    00410776   pop         ebx
    00410777   mov         esp,ebp
    00410779   pop         ebp
    0041077A   ret
  • 相关阅读:
    c# 发送邮件笔记(一)
    windows API(一)
    SubSonic3.0安装
    Node.js安装MongoDB驱动
    JDBC连接数据库方法
    Delphi LiveBindings如何绑定一个对象(二)(转)
    delphi RTTI机制学习(一)
    Delphi LiveBinds组件
    mysql 每个分类各取5条
    mysql in(...) 1次取出当前记录及上1条下1条记录, 且使用了主键作为索引
  • 原文地址:https://www.cnblogs.com/heyhx/p/14219884.html
Copyright © 2020-2023  润新知