如果本机是32位的,那么对32位的支持是最好的
在很多的书上都能看到类似这样的代码
#include<stdio.h>
void Function(char x,char y)
{
char c=x+y;
}
void main()
{
char a=1;
char b=2;
Function(a,b);
}
我们通过反汇编会发现
1: #include<stdio.h> 2: void Function(char x,char y) 3: { 00401020 push ebp 00401021 mov ebp,esp 00401023 sub esp,44h 00401026 push ebx 00401027 push esi 00401028 push edi 00401029 lea edi,[ebp-44h] 0040102C mov ecx,11h 00401031 mov eax,0CCCCCCCCh 00401036 rep stos dword ptr [edi] 4: char c=x+y; 00401038 movsx eax,byte ptr [ebp+8] 0040103C movsx ecx,byte ptr [ebp+0Ch] 00401040 add eax,ecx 00401042 mov byte ptr [ebp-4],al 5: } 00401045 pop edi 00401046 pop esi 00401047 pop ebx 00401048 mov esp,ebp 0040104A pop ebp 0040104B ret --- No source file ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 0040104C int 3 0040104D int 3 0040104E int 3 0040104F int 3 --- C:\Windows\System32\a.cpp ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 6: void main() 7: { 00401050 push ebp 00401051 mov ebp,esp 00401053 sub esp,48h 00401056 push ebx 00401057 push esi 00401058 push edi 00401059 lea edi,[ebp-48h] 0040105C mov ecx,12h 00401061 mov eax,0CCCCCCCCh 00401066 rep stos dword ptr [edi] 8: char a=1; 00401068 mov byte ptr [ebp-4],1 9: char b=2; 0040106C mov byte ptr [ebp-8],2 10: Function(a,b); 00401070 mov al,byte ptr [ebp-8] 00401073 pusheax 00401074 mov cl,byte ptr [ebp-4] 00401077 pushecx 00401078 call @ILT+0(Function) (00401005) 0040107D add esp,8 11: } 00401080 pop edi 00401081 pop esi 00401082 pop ebx 00401083 add esp,48h 00401086 cmp ebp,esp 00401088 call __chkesp (004010a0) 0040108D mov esp,ebp 0040108F pop ebp 00401090 ret
蓝色部分是传递进去的参数
然后我们发现,尽管定义的是char类型,压栈的却是eax而并不是al。
在32位的系统中,系统默认最合适的数据类型,就是32个bit,即4字节。同理,64位的系统就是8字节。
也就是说,如果使用小于4个字节的局部变量来进行参数传递,vc编译器仍然会按照4个字节来进行传递,但是多余的部分并不会使用。
从上面我们能看到,当创建一个小于4字节局部变量时,编译器为我们分配的内存空间为0x44。
当我们创建两个局部变量时
1: #include<stdio.h> 2: void Function(char x,char y) 3: { 00401020 push ebp 00401021 mov ebp,esp 00401023 sub esp,44h 00401026 push ebx 00401027 push esi 00401028 push edi 00401029 lea edi,[ebp-44h] 0040102C mov ecx,11h 00401031 mov eax,0CCCCCCCCh 00401036 rep stos dword ptr [edi] 4: char c=x+y; 00401038 movsx eax,byte ptr [ebp+8] 0040103C movsx ecx,byte ptr [ebp+0Ch] 00401040 add eax,ecx 00401042 mov byte ptr [ebp-4],al 5: char d; 6: } 00401045 pop edi 00401046 pop esi 00401047 pop ebx 00401048 mov esp,ebp 0040104A pop ebp 0040104B ret --- No source file ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 0040104C int 3 0040104D int 3 0040104E int 3 0040104F int 3 --- C:\Windows\System32\a.cpp ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 7: void main() 8: { 00401050 push ebp 00401051 mov ebp,esp 00401053 sub esp,48h 00401056 push ebx 00401057 push esi 00401058 push edi 00401059 lea edi,[ebp-48h] 0040105C mov ecx,12h 00401061 mov eax,0CCCCCCCCh 00401066 rep stos dword ptr [edi] 9: char a=1; 00401068 mov byte ptr [ebp-4],1 10: char b=2; 0040106C mov byte ptr [ebp-8],2 11: Function(a,b); 00401070 mov al,byte ptr [ebp-8] 00401073 push eax 00401074 mov cl,byte ptr [ebp-4] 00401077 push ecx 00401078 call @ILT+0(Function) (00401005) 0040107D add esp,8 12: } 00401080 pop edi 00401081 pop esi 00401082 pop ebx 00401083 add esp,48h 00401086 cmp ebp,esp 00401088 call __chkesp (004010a0) 0040108D mov esp,ebp 0040108F pop ebp 00401090 ret
缓冲区变为0x48了
再尝试创建一个大于4字节的数
1: #include<stdio.h> 2: void Function(char x,char y) 3: { 00401020 push ebp 00401021 mov ebp,esp 00401023 sub esp,4Ch 00401026 push ebx 00401027 push esi 00401028 push edi 00401029 lea edi,[ebp-4Ch] 0040102C mov ecx,13h 00401031 mov eax,0CCCCCCCCh 00401036 rep stos dword ptr [edi] 4: char c=x+y; 00401038 movsx eax,byte ptr [ebp+8] 0040103C movsx ecx,byte ptr [ebp+0Ch] 00401040 add eax,ecx 00401042 mov byte ptr [ebp-4],al 5: __int64 d; 6: } 00401045 pop edi 00401046 pop esi 00401047 pop ebx 00401048 mov esp,ebp 0040104A pop ebp 0040104B ret --- No source file ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 0040104C int 3 0040104D int 3 0040104E int 3 0040104F int 3 --- C:\Windows\System32\a.cpp ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 7: void main() 8: { 00401050 push ebp 00401051 mov ebp,esp 00401053 sub esp,48h 00401056 push ebx 00401057 push esi 00401058 push edi 00401059 lea edi,[ebp-48h] 0040105C mov ecx,12h 00401061 mov eax,0CCCCCCCCh 00401066 rep stos dword ptr [edi] 9: char a=1; 00401068 mov byte ptr [ebp-4],1 10: char b=2; 0040106C mov byte ptr [ebp-8],2 11: Function(a,b); 00401070 mov al,byte ptr [ebp-8] 00401073 push eax 00401074 mov cl,byte ptr [ebp-4] 00401077 push ecx 00401078 call @ILT+0(Function) (00401005) 0040107D add esp,8 12: } 00401080 pop edi 00401081 pop esi 00401082 pop ebx 00401083 add esp,48h 00401086 cmp ebp,esp 00401088 call __chkesp (004010a0) 0040108D mov esp,ebp 0040108F pop ebp 00401090 ret
这里就变成0x4c,因为__int64是8位的,所以就是0x48+4=0x4c了。
总结:
0x00.在32位系统上创建小于32位的局部变量是不合适的,在空间分配时仍然会按照32位来进行分配。但多余部分并不会使用。所以尽量避免使用小于32位的局部变量。
0x01.在vc6.0中调用函数时,每创建一个小于32位的局部变量,就会分配4个字节的空间。如果创建大于32位的局部变量,就会分配该局部变量实际的空间。
总的来说就是一句话,在32位的windows系统,使用vc6编程时尽量不要创建小于4个字节的局部变量,整数类型的参数,一律int类型。