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

关于 ARM64 汇编:调用流程与栈帧结构解析

一、ARM64 函数调用分析(汇编级)

寄存器规则(AArch64 ABI)

用途寄存器
参数传递x0 ~ x7
返回值x0(最多两个:x0、x1)
栈指针sp
链接寄存器x30(lr)
帧指针x29(fp)
临时/通用寄存器x9~x15等

函数调用指令流程

bl target_func     ; 跳转并将返回地址保存到 x30(link register)
ret                ; 返回上一级,等价于 br x30

举例

mov x0, #2
mov x1, #3
bl  add_func        ; 调用 add_func(2, 3)

二、栈帧结构详解

每个函数调用会建立自己的“栈帧”,用于:

  • 保存 caller 的寄存器(尤其是 x29, x30)

  • 为局部变量腾出空间

  • 管理多层调用时的上下文切换

标准函数前后结构

函数入口

stp x29, x30, [sp, #-16]!    ; 保存 fp 和 lr,栈顶向下扩展 16 字节
mov x29, sp                  ; 新帧指针 = 当前栈顶

函数返回

ldp x29, x30, [sp], #16      ; 恢复帧指针和返回地址
ret                          ; 返回上一层

示例完整函数

func:stp x29, x30, [sp, #-16]!    ; 建栈帧mov x29, sp// 函数体ldp x29, x30, [sp], #16      ; 恢复ret

三、栈帧结构图解(栈向下增长)

高地址 ↑
───────────────上一帧 fp      ← x29返回地址(lr) ← x30
───────────────局部变量区参数传递区(x8+)
───────────────当前 sp(栈底)
低地址 ↓

分析技巧:

  • IDA 里找 stp x29, x30, [sp,#-xxx]! 是函数入口特征

  • 栈帧大小往往是 16 的倍数(对齐)


四、系统调用实现(Linux syscall in ARM64)

在裸汇编中实现 syscall 需要:

  • 把 syscall 参数放入 x0~x5

  • 把 syscall 编号放入 x8

  • 执行 svc #0 发起系统调用

系统调用号对照

功能syscall 号
write64
read63
openat56
mmap222
exit93

示例:调用 write 输出字符串

汇编代码(写到 stdout)

.global _start.section .data
msg:    .ascii "Hello ARM64!\n"
len = . - msg.section .text
_start:mov x0, #1              // stdoutldr x1, =msg            // buf addressmov x2, #12             // lengthmov x8, #64             // syscall number: writesvc #0                  // trigger syscall// exit(0)mov x0, #0mov x8, #93             // syscall number: exitsvc #0

编译运行方式(Linux ARM64 模拟器或真机)

aarch64-linux-gnu-as hello.s -o hello.o
aarch64-linux-gnu-ld hello.o -o hello
qemu-aarch64 ./hello

五、逆向视角:系统调用识别

在 IDA 中看到以下指令,基本可以确认是系统调用:

mov x8, #64       ; syscall 编号
svc #0            ; 系统调用

结合调用前的 mov x0, #1, ldr x1, =addr, mov x2, #len 可以还原 syscall 是写 stdout。

汇总图(函数调用 → 栈帧 → syscall)

main:stp x29, x30, [sp, #-16]!      // 保存mov x29, spmov x0, #1                     // arg0: stdoutldr x1, =msg                   // arg1: buffer addrmov x2, #13                    // arg2: lengthmov x8, #64                    // syscall writesvc #0                         // 发起调用ldp x29, x30, [sp], #16        // 恢复ret

六、总结

内容关键点
调用规则x0~x7 传参,x30 返回地址
栈帧结构使用 x29 做帧指针,函数内局部变量/保存寄存器都存在栈
系统调用x0~x5 参数, x8 syscall 号, svc #0 触发
IDA/Ghidra逆向stp/ldp, bl, svc 判断函数入口、调用、syscall
实战环境用 qemu + aarch64 工具链模拟也能练习
http://www.lqws.cn/news/530101.html

相关文章:

  • 酒店智能门锁系统常见问题解决方法——东方仙盟
  • zookeeper总是重启失败
  • Golang是什么
  • AI代码编程工具:开启智能编程新时代
  • uniapp微信小程序:editor组件placeholder字体样式修改
  • Spring Boot 中使用 Jackson 实现全局时间格式处理(支持多格式反序列化)
  • A模块 系统与网络安全 第三门课 网络通信原理
  • Spring AI 入门到实战:我如何用它让系统具备“理解能力”
  • 【机器学习第一期(Python)】梯度提升决策树 GBDT
  • Pycharm无法运行Vue项目的解决办法
  • Java 泛型详解:从入门到实战
  • jdbc实现跨库分页查询demo
  • 人力资源管理系统
  • Spring Cloud Config动态刷新实战指南
  • 用户统计-01.需求分析和设计
  • GNSS位移监测站在大坝安全中的用处
  • 渗透实战:使用隐式转换覆盖toString的反射型xss
  • Day43 复习日 图像数据集——CNN
  • 【PX4-AutoPilot教程-TIPS】PX4系统命令行控制台ConsolesShells常用命令(持续更新)
  • ES文件管理器v4.4.3(ES文件浏览器)
  • 鸿蒙 FoldSplitContainer 解析:折叠屏布局适配与状态管理
  • MySQL之存储函数与触发器详解
  • 多相机人脸扫描设备如何助力高效打造数字教育孪生体?
  • ethers.js express vue2 定时任务每天凌晨2点监听合约地址数据同步到Mysql整理
  • ASIO 避坑指南:高效、安全与稳健的异步网络编程
  • 微服务架构下面临的安全、合规审计挑战
  • Python打卡:Day37
  • 使用 Python 自动化文件获取:从 FTP 到 API 的全面指南
  • 【Bluedroid】蓝牙启动之 btm_acl_device_down 流程源码解析
  • 稳定币技术全解:从货币锚定机制到区块链金融基础设施