当前位置: 首页 > article >正文

ARM64基础 -- 栈帧管理示例

ARM64 架构中的栈帧管理示例:x29x30 的使用

以下是一个完整的 ARM64 函数调用示例,展示了 x29(帧指针)和 x30(链接寄存器/返回地址)的使用过程。

1. 函数入口:保存上下文

假设我们有一个简单的函数 foo,在进入函数时使用以下指令:

foo:
    stp x29, x30, [sp, #-16]!  // 保存旧的帧指针和返回地址,并更新 SP
    mov x29, sp                // 设置新的帧指针

初始状态:

  • 假设 sp = 0x1000
  • 寄存器 x29(帧指针)保存了调用者的栈帧基址,例如 x29 = 0x2000
  • 寄存器 x30(返回地址)保存了调用者的返回地址,例如 x30 = 0x3000

执行 stp x29, x30, [sp, #-16]! 后:

  • sp 减少 16 字节sp = 0x1000 - 16 = 0x0FF0
  • 保存 x29x30
    • x29(值为 0x2000)被存储在内存地址 0x0FF0
    • x30(值为 0x3000)被存储在内存地址 0x0FF8

内存布局:

地址      值
0x0FF0:   0x2000  // 保存的旧帧指针(x29)
0x0FF8:   0x3000  // 保存的返回地址(x30)
sp = 0x0FF0

执行 mov x29, sp 后:

  • 更新帧指针x29 = sp = 0x0FF0,此时 x29 指向当前函数的栈帧基址。

2. 函数体:执行代码

在函数 foo 内部可以执行各种操作,期间 spx29 不会改变指向的栈帧。

3. 函数结束:恢复上下文

在函数即将结束时,使用以下指令恢复之前保存的上下文:

    ldp x29, x30, [sp], #16    // 恢复旧的帧指针和返回地址,并更新 SP
    ret                        // 返回到调用者

执行 ldp x29, x30, [sp], #16 前:

  • sp = 0x0FF0
  • 内存布局:
    地址      值
    0x0FF0:   0x2000  // 保存的旧帧指针(x29)
    0x0FF8:   0x3000  // 保存的返回地址(x30)
    

执行 ldp x29, x30, [sp], #16 后:

  • 从内存中恢复 x29x30
    • x29 恢复为 0x2000(旧帧指针)。
    • x30 恢复为 0x3000(返回地址)。
  • sp 增加 16 字节sp = 0x0FF0 + 16 = 0x1000,恢复到调用函数前的值。

内存布局(执行完毕后):

sp = 0x1000

4. 函数返回

最后,执行 ret 指令,跳转到 x30 所保存的返回地址 0x3000,函数执行结束,程序返回到调用者。

5. 总结

  • 函数入口时

    • 使用 stp 指令保存了 x29x30,并将 sp 减少 16 字节以分配新的栈帧。
    • sp0x1000 变为 0x0FF0
    • 栈上存储了 0x2000(旧的 x29)和 0x3000(旧的 x30)。
  • 函数结束时

    • 使用 ldp 指令恢复 x29x30,并将 sp 增加 16 字节以恢复到函数调用前的状态。
    • sp 恢复到 0x1000

这个过程确保了函数执行时保存和恢复了必要的上下文(帧指针和返回地址),以便函数能够正确返回并保持调用栈的完整性。


http://www.kler.cn/news/310947.html

相关文章:

  • 什么是轮播图?如何实现轮播图?有几种方法?
  • 图书馆座位预约系统小程序的设计
  • 1.2 测试基础
  • 小程序组件间通信
  • SQL案例分析:美联储降息前后的复利差距
  • linux-Linux 内核与模块管理-内核基础
  • 最新简洁大方的自动发卡网站源码/鲸发卡v11.61系统源码/修复版
  • 亲测有效,长期有效的RTSP流地址公网RTSP地址,各种类型的视频源
  • Flask-JWT-Extended登录验证, 不用自定义
  • java项目之基于springboot的贸易行业crm系统(源码+文档)
  • Server-Sent Events 服务器发送事件(SSH)
  • 从数据仓库到数据中台再到数据飞轮:我了解的数据技术进化史
  • 传输层协议 —— TCP协议(上篇)
  • 刻意练习:舒尔特方格提升专注力
  • [DOM] Found 2 elements with non-unique id VUE子页面调用父页面以及父页面调用子页面的方法
  • C++中string类的模拟实现
  • JDBC 编程
  • RockPlus Prototype Lab系统,领先的汽车零部件研发实验室管理解决方案
  • Python 引用其他文件的函数
  • 网络高级day01(Modbus 通信协议)
  • 游戏如何应对云手机刷量问题
  • RockTrack:A 3D Robust Multi-Camera-Ken Multi-Object Tracking Framework
  • iptables限制网速
  • CefSharp_Vue交互(Element UI)_WinFormWeb应用(2)---置顶和取消置顶(含示例代码)
  • JAVA虚拟机----JVM
  • 园区物业水电费收取难怎么办
  • 【Java-线程池】
  • 聚焦汽车智能化与电动化,亚洲领先的汽车工业技术博览会 2025年11月与您相约 AUTO TECH 华南展
  • 【WiFi】Qualcomm WCN6856 进入FTM操作说明
  • 初识网络编程