news 2026/4/22 21:00:20

过程调用的代码流程涉及多个关键步骤,确保程序能正确传递参数、执行被调用函数并安全返回

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
过程调用的代码流程涉及多个关键步骤,确保程序能正确传递参数、执行被调用函数并安全返回

过程调用的代码流程涉及多个关键步骤,确保程序能正确传递参数、执行被调用函数并安全返回。其典型流程如下:

  1. 参数传递与调用准备(Caller 侧)

    • 计算并压入实际参数到运行时栈。
    • 保存当前栈指针(SP),用于维护调用者栈帧。
    • 记录参数个数(某些语言或调用约定中需要)。
    • 将返回地址(当前指令的下一条)压栈或存入特定寄存器。
    • 执行JSR(Jump to Subroutine)指令跳转到被调用过程。
  2. 进入被调用过程(Callee 侧)

    • 保存旧的栈基址指针(通常称为 FP 或 BP)。
    • 建立新的栈帧:设置新的 SP 和 FP,构成活动记录(Activation Record)。
    • 分配局部变量所需空间。
    • 可选:保存某些寄存器内容(如临时变量使用的寄存器)。
  3. 执行过程体

    • 执行函数内部语句,可能包括表达式计算、控制流、递归调用等。
    • 使用中间代码(如四元式)进行表示和优化。
  4. 过程返回(Return)

    • 将返回值(如有)存入约定位置(寄存器或栈)。
    • 恢复调用者的栈指针 SP 和基址指针 FP。
    • 获取返回地址并跳转回调用点。
    • 清理栈中参数(由调用者或被调用者完成,取决于调用约定)。

在编译过程中,中间代码优化目标代码生成是后端的关键阶段:

  • 中间代码优化

    • 输入是中间表示(如四元式(op, arg1, arg2, result))。
    • 进行等价变换以提升效率,例如常量折叠、公共子表达式消除、循环不变代码外提、死代码删除等。
    • 目标是在不改变程序语义的前提下减少运行时间和空间开销。
  • 目标代码生成

    • 由代码生成器将优化后的中间代码转换为具体机器的汇编或机器码。
    • 需处理寄存器分配、指令选择、寻址模式匹配等问题。
    • 四元式结构因其接近三地址码,便于映射到目标指令。
      常见的过程调用约定(Calling Convention)定义了函数调用时参数如何传递、栈由谁清理、哪些寄存器需保存等规则。不同平台和编译器使用不同的调用约定,尤其在C/C++中较为显著。以下是几种典型的调用约定及其在参数清理寄存器使用上的主要区别:

1.cdecl(C Declaration)

  • 平台/语言:x86 架构下 GCC 和 MSVC 默认的 C 语言调用约定。
  • 参数传递顺序:从右到左压入栈。
  • 栈清理方调用者(Caller)负责清理栈空间。
  • 寄存器使用
    • EAX,ECX,EDX:调用者保存(caller-saved),被调用函数可自由使用。
    • 其他通用寄存器(如EBX,ESI,EDI)为被调用者保存(callee-saved),若使用需先压栈。
  • 用途:支持可变参数函数(如printf),因为只有调用者知道传了多少参数。

2.stdcall(Standard Call)

  • 平台:Windows API 常用。
  • 参数传递顺序:从右到左压栈。
  • 栈清理方被调用者(Callee)ret n指令中自动弹出参数。
  • 寄存器使用
    • 类似 cdecl,EAX,ECX,EDX为 caller-saved。
    • 其余为 callee-saved。
  • 限制:不适用于变参函数(被调用者无法预知参数个数)。

3.fastcall

  • 目的:提高性能,尽可能通过寄存器传参。
  • 参数传递方式
    • 前两个双字(DWORD)大小的参数通过寄存器传递(通常是ECXEDX)。
    • 剩余参数从右到左压栈。
  • 栈清理方被调用者(Callee)清理栈上参数部分。
  • 寄存器使用
    • ECX,EDX用于传参,属于 callee-saved 的一部分。
    • EAX,EDX也常用于返回值(EAX返回整型,EDX:EAX返回64位值)。
  • 优点:减少内存访问,提升速度。

4.thiscall(C++ 成员函数专用)

  • 平台:Microsoft Visual C++ 使用。
  • 隐含参数this:通过寄存器(ECX)传递。
  • 参数传递:其余参数从右到左压栈。
  • 栈清理方:对于固定参数,由被调用者清理;变参则由调用者清理。
  • 仅用于类成员函数调用

5.System V AMD64 ABI(Unix-like 系统 x86-64)

  • 主流标准:Linux、macOS 等 64 位系统默认。
  • 参数传递
    • 前六个整型/指针参数依次使用寄存器:RDI,RSI,RDX,RCX,R8,R9
    • 前八个浮点参数使用XMM0–XMM7
    • 超出部分通过栈传递。
  • 栈清理方调用者清理栈。
  • 寄存器分类
    • caller-saved:RAX,RCX,RDX,R8–R11
    • callee-saved:RBX,RBP,R12–R15,RSP

总结对比表:

调用约定参数传递顺序栈清理方寄存器传参支持变参典型用途
cdecl右→左CallerC 函数(x86)
stdcall右→左CalleeWindows API
fastcall右→左 + 寄存器Callee是(前两个)性能敏感函数
thiscall右→左Callee*ECX (this)否/是C++ 非静态成员函数
System V x64寄存器优先Caller是(最多6个整型)Linux/macOS 64位程序

*注:thiscall 的清理策略依实现而定。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/22 22:58:11

Docker容器资源限制:控制PyTorch任务GPU占用率

Docker容器资源限制:控制PyTorch任务GPU占用率 在现代AI开发环境中,一个常见的场景是:多个研究人员共享同一台多卡GPU服务器进行模型训练。突然,某位同事启动了一个未经优化的PyTorch任务——几秒钟内,显存被占满&…

作者头像 李华
网站建设 2026/4/23 12:13:48

【Wireshark网络抓包】完整教程 原理+实操+实战 零基础精通

文章目录目录前言一、网络抓包的核心原理(必懂)1.1 抓包的本质1.2 网卡的工作模式1.3 抓包的范围限制1.4 数据包的组成二、Wireshark基础准备2.1 Wireshark安装(全平台)2.2 Wireshark核心界面详解三、Wireshark完整抓包核心流程&a…

作者头像 李华
网站建设 2026/4/16 19:56:39

如何在PyTorch中使用混合精度训练加速模型收敛?

如何在 PyTorch 中使用混合精度训练加速模型收敛? 在当今深度学习项目中,训练一个大型模型动辄需要数小时甚至数天时间。尤其是在图像分类、语言建模等任务中,显存瓶颈和计算延迟常常让开发者望而却步。有没有一种方式,既能不改动…

作者头像 李华
网站建设 2026/4/23 12:57:42

水处理自动化:西门子1500PLC与WinCC7.5的完美结合

西门子1500PLC博途程序加经典Wincc7.5程序案例,水处理项目,具体为滤液生化段处理项目,文件内容有博途V16程序及本项目电气自控图纸。 送WINCC7.5画面:MBR系统,加药系统,电气系统及数据系统。 有电气图纸供参考作为水处…

作者头像 李华
网站建设 2026/4/20 0:31:39

Executors预定义线程池-正确使用姿势

Java线程池的陷阱与救赎:深入剖析Executors预定义线程池的风险与正确使用姿势一、看似便捷的Executors工具类:甜蜜的陷阱在Java并发编程中,Executors工具类为开发者提供了快速创建线程池的便捷方法。只需一行代码,就能获得功能完整…

作者头像 李华