汇编角度看C语言的参数传递、返回值,局部变量以及数组的反汇编

 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\n",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、数组定位时,可以超过数组的长度,编译不会有错,但读取的数据是错的.

 

posted @ 2020-12-31 18:14  heyhx  阅读(487)  评论(0编辑  收藏  举报