• 四、函数参数的传递规则


    函数参数的传递规则

    函数传递的规则现在一般有两种,一种是WINAPI方式,也就是_stdcall还有一种是_cdecl方式


    _stdcall调用规则:


    (1)参数从右到左进入堆栈
    (2)被调用者在返回前自动清理堆栈


    _cdecl C方式调用规则:


    (1)参数从右到左进入堆栈
    (2)由调用者负责清理堆栈
    生成的程序代码一般会比_stdcall的大。


    C编译器默认采用_cdecl方式,而windows API默认采用_stdcall。

    在windows中,无论哪种方式,返回值都放在eax中,然后返回,外部从eax中得到返回值。


    _cdecl使用的一般过程:
    (1)保持ebp 。ebp总是被我们用来保存这个函数执行前esp的值,执行函数完毕后,用来恢复esp。当然,这个函数的上层函数也是这样做的,所以我们要先把ebp压入堆栈,避免ebp被我们改动。
    (2)保存esp到ebp中
    上面的两步的代码如下:
    push ebp
    mov ebp,esp
    (3)为局部变量申请空间,一般是用sub esp,空间大小 来进行分配,相当于压入堆栈。完成后记得平衡堆栈
    (4)保存其它寄存器的值。ebx、esi、edi压入堆栈,调用完后恢复。
    sub esp,0cch
    push ebp
    push esi
    push edi
    (5)将局部变量区域初始化为0cccccccch,也就是int3指令的机器码。
    lea edi,[ebp-0cch]
    mov ecx,33h
    mov eax,0cccccccch
    rep stos dword ptr [edi]
    (6)做函数要做的事
    (7)恢复ebx、esi、edi、esp、ebp,然后返回
    pop edi
    pop esi
    pop ebx
    mov esp,ebp

    pop ebp
    ret


    对应的c代码:

     1 #include "stdafx.h"
     2 
     3 
     4 int _tmain(int argc, _TCHAR* argv[])
     5 {
     6     void fun(int a,int b);
     7     fun(11,22);
     8     return 0;
     9 }
    10 
    11 void fun(int a,int b)
    12 {
    13     int c=a+b;
    14 }

    对应的函数汇编代码

     1 void fun(int a,int b)
     2 {
     3 00411780  push        ebp  
     4 00411781  mov         ebp,esp  
     5 00411783  sub         esp,0CCh  
     6 00411789  push        ebx  
     7 0041178A  push        esi  
     8 0041178B  push        edi  
     9 0041178C  lea         edi,[ebp-0CCh]  
    10 00411792  mov         ecx,33h  
    11 00411797  mov         eax,0CCCCCCCCh  
    12 0041179C  rep stos    dword ptr es:[edi]  
    13     int c=a+b;
    14 0041179E  mov         eax,dword ptr [a]  
    15 004117A1  add         eax,dword ptr [b]  
    16 004117A4  mov         dword ptr [c],eax  
    17 }
    18 004117A7  pop         edi  
    19 004117A8  pop         esi  
    20 004117A9  pop         ebx  
    21 004117AA  mov         esp,ebp  
    22 004117AC  pop         ebp  
    23 004117AD  ret  

    ..................................

  • 相关阅读:
    取字符串前缀
    分解质因数
    git 常用命令
    微信 iphone端 audio 播放问题
    git入门:创建合并分支 解决冲突 分支管理策略
    git入门:远程仓库 github篇
    git入门:撤销修改 删除文件
    git入门: 工作区暂存区 以及 管理修改
    函数柯里化实现
    转载:深度工作:充分使用每一份脑力
  • 原文地址:https://www.cnblogs.com/tk091/p/2471947.html
Copyright © 2020-2023  润新知