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