子程序设计:参数传递、局部变量与调用约定
为什么需要子程序?
汇编没有"函数"关键字,但我们可以用 CALL 和 RET 实现同样的效果。
子程序的基本结构
MyFunc PROC
PUSH BP ; 保存调用者的栈帧
MOV BP, SP ; 建立新栈帧
SUB SP, 4 ; 分配 4 字节局部变量
; 函数体
MOV [BP-2], AX ; 局部变量 1
MOV [BP-4], BX ; 局部变量 2
MOV SP, BP ; 清理局部变量
POP BP ; 恢复调用者栈帧
RET
MyFunc ENDP
参数传递方式
1. 寄存器传参(最快)
; 调用者
MOV AX, 100
MOV BX, 200
CALL AddFunc
; AddFunc
AddFunc PROC
ADD AX, BX ; 结果在 AX 中
RET
AddFunc ENDP
2. 栈传参(适合多参数)
; 调用者
PUSH 200
PUSH 100
CALL AddFunc
ADD SP, 4 ; 清理参数
; AddFunc
AddFunc PROC
PUSH BP
MOV BP, SP
MOV AX, [BP+4] ; 参数 1
MOV BX, [BP+6] ; 参数 2
ADD AX, BX
POP BP
RET
AddFunc ENDP
局部变量的作用
局部变量存储在栈中,每个函数调用有独立的副本:
调用约定
| 约定 | 参数传递 | 栈清理 | 寄存器保护 |
|:--|:--|:--|:--|
| C 调用 | 栈(右到左)| 调用者 | EAX/ECX/EDX 不保护 |
| Pascal | 栈(左到右)| 被调用者 | 所有寄存器保护 |
| fastcall | 寄存器 + 栈 | 调用者 | 混合 |
总结
子程序是汇编走向工程化的关键。掌握栈帧管理,你就能写出结构清晰、可维护的汇编代码。
下一篇:《宏指令与高级汇编技术:代码复用与元编程》
原文链接:https://wenyiblog.top/2026/06/asm-11-subroutines/
首发于文艺技术笔记(wenyiblog.top),转载请注明出处。

浙公网安备 33010602011771号