汇编的角度分析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

 

posted @ 2021-01-03 17:03  heyhx  阅读(350)  评论(0编辑  收藏  举报