1、 8位参数传递
void Function(char x,char y,char z) { }
2、16位参数传递
void Function(short x,short y,short z) { }
3、32位参数传递
void Function(int x,int y,int z) { }
通过反汇编可以得到结论,无论是char ,short ,int传入的时候都是四个字节
原因:
1、本机尺寸:如果本机是32位的,那么对32位的数据支持最好,如果是64位的,那么对64位的支持最好
2、编译器遵守了这个规则:char类型或者short类型的参数不但没有节省空间,反而浪费了多余的操作.
结论:整数类型的参数,一律使用int类型
4、思考题
//函数定义: void Plus(int x) { x = x + 1; } //入口函数 int main(int argc, char* argv[]) { int x = 1; Plus(x); printf("%d ",x); return 0; }
思考题: main方法中,int x为局部变量,[ebp-4]中,而在调用的plus中为[ebp+8]中,
最后会把x=x+1的值重新写到ebp+8中。而不会影响main方法堆栈中的ebp-4的值
5、
示例1. void Function() {
00E51760 push ebp
00E51761 mov ebp,esp
00E51763 sub esp,0C0h 分配了 0xC 个空间
00E51769 push ebx
00E5176A push esi
00E5176B push edi
00E5176C lea edi,[ebp-0C0h]
00E51772 mov ecx,30h
00E51777 mov eax,0CCCCCCCCh
00E5177C rep stos dword ptr es:[edi]
00E5177E mov ecx,offset _9B1CD70C_main-2-2@cpp (0E5C008h)
00E51783 call @__CheckForDebuggerJustMyCode@4 (0E5131Bh)
}
示例2.
void Function(int x,int y) {
00671760 push ebp
00671761 mov ebp,esp
00671763 sub esp,0C0h
00671769 push ebx
0067176A push esi
0067176B push edi
0067176C lea edi,[ebp-0C0h]
00671772 mov ecx,30h
00671777 mov eax,0CCCCCCCCh
0067177C rep stos dword ptr es:[edi]
0067177E mov ecx,offset _9B1CD70C_main-2-2@cpp (067C008h)
00671783 call @__CheckForDebuggerJustMyCode@4 (067131void fun3(int i, int j)
{ int x = 4; int y = 5; mov ebp, esp sub sp, 0D8h 多分配了 0x18个字节的空间 这个值在vc6++中是0x8个字节 }
总结:
1、小于32位的局部变量,空间在分配时,按32位分配.
2、使用时按实际的宽度使用.
3、不要定义char/short类型的局部变量.
4、参数与局部变量没有本质区别,都是局部变量,都在栈中分配.
5、完全可以把参数当初局部变量使用
6、
void Function() { int v_0 = 1; int v_1 = 2; int v_2 = 3; int v_3 = 4; int v_4 = 5; int v_5 = 6; int v_6 = 7; int v_7 = 8; int v_8 = 9; int v_9 = 10; } 反汇编: push ebx push esi push edi lea edi,[ebp-68h] mov ecx,1Ah mov eax,0CCCCCCCCh rep stos dword ptr [edi] nt v_0 = 1; mov dword ptr [ebp-4],1 nt v_1 = 2; mov dword ptr [ebp-8],2 nt v_2 = 3; mov dword ptr [ebp-0Ch],3 nt v_3 = 4; mov dword ptr [ebp-10h],4 nt v_4 = 5; mov dword ptr [ebp-14h],5 nt v_5 = 6; mov dword ptr [ebp-18h],6 nt v_6 = 7; mov dword ptr [ebp-1Ch],7 nt v_7 = 8; mov dword ptr [ebp-20h],8 nt v_8 = 9; mov dword ptr [ebp-24h],9 nt v_9 = 10; mov dword ptr [ebp-28h],0Ah pop edi pop esi pop ebx mov esp,ebp pop ebp ret 函数二: void Function() { int arr[10] = {1,2,3,4,5,6,7,8,9,10}; } 反汇编: push ebp mov ebp,esp sub esp,68h push ebx push esi push edi lea edi,[ebp-68h] mov ecx,1Ah mov eax,0CCCCCCCCh rep stos dword ptr [edi] int arr[10] = {1,2,3,4,5,6,7,8,9,10}; mov dword ptr [ebp-28h],1 mov dword ptr [ebp-24h],2 mov dword ptr [ebp-20h],3 mov dword ptr [ebp-1Ch],4 mov dword ptr [ebp-18h],5 mov dword ptr [ebp-14h],6 mov dword ptr [ebp-10h],7 mov dword ptr [ebp-0Ch],8 mov dword ptr [ebp-8],9 mov dword ptr [ebp-4],0Ah pop edi pop esi pop ebx mov esp,ebp pop ebp ret
总结
1、数组就是一组相同类型的变量,为了方便读写,采用另外一种表示形式。在堆栈图中的表现形式是一样的
2、数组在声明的时候,必须用常量来指明长度,不能使用变量.
7、
示例: void Function() { int arr[10] = {1,2,3,4,5,6,7,8,9,10}; int x = 1; int y = 2; int r ; r = arr[1]; r = arr[x]; r = arr[x+y]; r = arr[x*2+y]; r = arr[arr[1]+arr[2]]; r = arr[Add(1,2)]; }
数组的使用总结
1、数组在使用时,可以通过变量来定位数据.
2、数组定位时,可以超过数组的长度,编译不会有错,但读取的数据是错的.