堆栈操作深度解析:PUSH/POP 与函数调用的秘密

栈是什么?

栈(Stack)是一种 后进先出(LIFO) 的数据结构。在汇编中,它由 SS:SP 指向。

PUSH 与 POP


PUSH AX    ; SP = SP - 2, [SS:SP] = AX
POP  BX    ; BX = [SS:SP], SP = SP + 2
  • **PUSH**:先将 SP 减 2,再写入数据
  • **POP**:先读取数据,再将 SP 加 2
  • 栈帧结构

    函数调用时,栈中会形成栈帧

    
    高地址
      +----------------+
      |    参数 2      |
      +----------------+
      |    参数 1      |
      +----------------+
      |  返回地址      | ← CALL 自动压入
      +----------------+
      |  旧 BP         | ← PUSH BP
      +----------------+ ← BP (当前栈帧基址)
      |  局部变量 1    |
      +----------------+
      |  局部变量 2    |
      +----------------+ ← SP (栈顶)
    低地址
    

    函数调用流程

    
    ; 调用者
    PUSH 参数 2
    PUSH 参数 1
    CALL FUNC
    
    ; 被调用者 FUNC:
    PUSH BP        ; 保存旧栈帧
    MOV BP, SP     ; 设置新栈帧
    SUB SP, 4      ; 分配局部变量空间
    
    ; ... 函数体 ...
    
    MOV SP, BP     ; 恢复 SP
    POP BP         ; 恢复旧栈帧
    RET            ; 弹出返回地址并跳转
    

    为什么需要栈?

    1. 保存返回地址CALL 自动将下一条指令地址压栈

    2. 传递参数:通过栈传递,避免寄存器不够用

    3. 保存上下文:子程序可以随意使用寄存器,退出前恢复

    4. 局部变量:每个函数有独立的栈帧,互不干扰

    总结

    理解栈,就理解了程序执行的"时间线"。每一次函数调用,都是在栈上翻开新的一页。

    下一篇:《标志位详解:CF/ZF/SF/OF 如何影响程序流程》


    原文链接:https://wenyiblog.top/2026/06/asm-07-stack-operations/

    首发于文艺技术笔记(wenyiblog.top),转载请注明出处。

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