子程序设计:参数传递、局部变量与调用约定

为什么需要子程序?

汇编没有"函数"关键字,但我们可以用 CALLRET 实现同样的效果。

子程序的基本结构


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),转载请注明出处。

    posted @ 2026-06-22 19:28  软件工程师文艺  阅读(1)  评论(0)    收藏  举报