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

ARMV8 - A64 - 函数调用,内存栈操作

说明

  • 看了下ARM平台上C语言函数调用的反汇编代码,理清楚了其中的内存栈汇编操作,特整理下。
  • 本文环境基于:ARMv8-a架构A53核soc,aarch64状态。

预先了解的知识点

内存栈

  • 栈和栈帧的基本概念
  • 重点:出栈入栈的单位不是单个局部变量,而是栈帧。

相关寄存器

  1. FP:Frame Pointer(栈帧指针),指向当前栈帧的顶部,在A53平台是使用通用寄存器x29保存。
  2. SP:Stack Pointer(栈顶指针),保存当前栈顶地址,在A53平台是一个特殊寄存器,不同异常等级是不同的寄存器,
  3. LR:Link Register(链接寄存器),保存子函数运行结束后的返回地址(跳转指令的下一条指令地址),在A53平台是使用通用寄存器x30充当,详细使用请看bl和ret指令说明。
  • 问题:初次了解,不好理解和区分FP和SP的作用和角色,SP是全局唯一的保存栈顶地址的寄存器,而FP是保存单个函数的栈帧基址,调用新函数,入栈操作结束后,需要将SP的值赋值给FP,类似于:SP是全局变量,而x29是局部变量,虽然大部分时刻两个寄存器值是一样的。

相关汇编指令

  • 函数调用实现原理,跳转和返回指令
  • 内存操作store,load

实例

  • C源码(a.c)
#include <stdio.h>int test1()
{return test(1, 2);
}int test(int a, int b)
{return a+b;
}int main()
{test1();return 0;
}
  • 对应的汇编代码(aarch64-linux-gnu-gcc -S a.c)
    .arch armv8-a.file   "a.c".text.align  2.global test1.type   test1, %function
test1:stp x29, x30, [sp, -16]!add x29, sp, 0mov w1, 2mov w0, 1bl  testldp x29, x30, [sp], 16ret.size   test1, .-test1.align  2.global test.type   test, %function
test:sub sp, sp, #16str w0, [sp, 12]str w1, [sp, 8]ldr w1, [sp, 12]ldr w0, [sp, 8]add w0, w1, w0add sp, sp, 16ret.size   test, .-test.align  2.global main.type   main, %function
main:stp x29, x30, [sp, -16]!add x29, sp, 0bl  test1mov w0, 0ldp x29, x30, [sp], 16ret.size   main, .-main.ident  "GCC: (Linaro GCC 6.3-2017.05) 6.3.1 20170404".section    .note.GNU-stack,"",@progbits

说明

  • 从汇编代码可以看出存在两种不同实现,如下:
  1. 函数调用栈中间函数(test1)
  2. 函数调用栈末端函数(test)

中间函数

test1:stp x29, x30, [sp, -16]! //将栈空间扩大16字节(更改sp寄存器值),再将x29,x30的数据(遗传自父函数)保存到栈顶 add x29, sp, 0 //将栈顶地址(sp)即此函数的栈帧基址保存到x29,...  //函数操作(省略)bl  test //跳转到test函数执行ldp x29, x30, [sp], 16 //将栈顶数据load到x29,x30中,再缩小栈空间16字节(即将sp恢复到父函数的栈顶)ret //返回父函数

末端函数

test:sub sp, sp, #16 //将sp保存的数据减小16字节,即将栈空间扩大16字节... //函数操作(省略)add sp, sp, 16 //将sp保存的数据增加16字节,即将栈空间缩小16字节ret

问题

  1. 为什么中间函数和末端函数实现不同,中间函数需要将x29,x30保存到栈内存中,最后再从栈内存中load到x29,x30中。
  • 是因为中间函数(test1)bl指令调用末端函数(test)时,会覆盖掉x30的数据(原本保存的是父函数main,跳转test1的下一条指令),覆盖后中间函数(test1)的ret指令就跳不回main函数了,因此需要先将x30的数据保存到栈上,从子函数跳转回来后,需要将x29,x30的数据从栈上恢复。
  • x29是栈帧指针,保存是当前函数的frame pointer,是约定俗成,因此需要保存和恢复,但是也不是必须,例如:test函数中就没有使用x29。

注意项

  1. sp 必须16Byte 对齐,扩大和缩小都必须是16字节的倍数。

相关文章:

ARMV8 - A64 - 函数调用,内存栈操作

说明 看了下ARM平台上C语言函数调用的反汇编代码&#xff0c;理清楚了其中的内存栈汇编操作&#xff0c;特整理下。本文环境基于&#xff1a;ARMv8-a架构A53核soc&#xff0c;aarch64状态。 预先了解的知识点 内存栈 栈和栈帧的基本概念重点&#xff1a;出栈入栈的单位不是…...

MyBatis 四大核心组件之 ResultSetHandler 源码解析

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…...

docker-compose 单机容器编排

docker-compose 单机容器编排 Dockerfile&#xff1a;先配置好的文件&#xff0c;然后bulid&#xff0c;镜像容器。 docker-compose 既可以基于dockerfile&#xff0c;也可以基于镜像&#xff0c;一键式拉起镜像和容器。 docker-compose 核心就是yml文件&#xff0c;可以定义…...

springboot项目使用Layui作为前端UI的一系列前后端交互的解决方法

背景&#xff1a; 因为比较喜欢Layui&#xff0c;因为多个项目都是从零开始就使用的layui开发的&#xff0c;并且开发过程中借鉴了很多其他项目&#xff08;如Ruoyi、Pear Admin&#xff09;&#xff0c;因此最终选用大部分Pear Admin的项目中使用的一系列解决方案&#xff0c;…...

【Linux】Firewalld防火墙新增端口、开启、查看等

Linux操作系统中&#xff0c;Firewalld防火墙相关操作如下&#xff1a; 安装 yum install firewalld firewalld-configFirewall开启常见端口命令 新增端口&#xff1a; firewall-cmd --zonepublic --add-port80/tcp --permanentfirewall-cmd --zonepublic --add-port443/tc…...

学习笔记 -- TVS管选型参考

一、TVS管基本工作原理 当TVS管(瞬态电压抑制器)两极受到反向瞬态高能量冲击时&#xff0c;能以纳秒(ns)量级的速度&#xff0c;将两极间的高阻抗变为低阻抗&#xff0c;使两极间的电压箝位于一个预定的值&#xff0c;有效地保护电子线路中的元器件。 在浪涌电压作用下&#xf…...

功能更新|免费敏捷工具Leangoo领歌私有部署新增第三方身份认证和API对接

Leangoo领歌是一款永久免费的专业的敏捷开发管理工具&#xff0c;提供端到端敏捷研发管理解决方案&#xff0c;涵盖敏捷需求管理、任务协同、进展跟踪、统计度量等。 Leangoo支持敏捷研发管理全流程&#xff0c;包括小型团队敏捷开发&#xff0c;规模化敏捷SAFe&#xff0c;Scr…...

重生奇迹mu战士加点

在重生奇迹MU中&#xff0c;战士作为一个近战职业&#xff0c;主要依赖于物理攻击来输出伤害。因此&#xff0c;在加点方面&#xff0c;战士需要优先考虑加强自身的攻击力&#xff0c;同时也要增强自身的生存能力和耐久度。 以下是可参考的战士加点方案&#xff1a; 1.力量&a…...

【数据结构(十一·多路查找树)】B树、B+树、B*树(6)

文章目录 1. 二叉树 与 B树1.1. 二叉树存在的问题1.2. 多叉树 的概念1.3. B树 的基本介绍 2. 多叉树——2-3树2.1. 基本概念2.2. 实例应用2.3. 其他说明 3. B 树、B树 和 B*树3.1. B树 的介绍3.2. B树 的介绍3.2. B*树 的介绍 1. 二叉树 与 B树 1.1. 二叉树存在的问题 二叉树…...

弟弟的作业

问题 G: 弟弟的作业 [命题人 : 外部导入] 时间限制 : 1.000 sec 内存限制 : 128 MB 题目描述 你的弟弟刚做完了“100以内数的加减法”这部分的作业&#xff0c;请你帮他检查一下。每道题目&#xff08;包括弟弟的答案&#xff09;的格式为abc或者a-bc&#xff0c;其中a和b是作…...

代码随想录算法训练营第37天|● 738.单调递增的数字 ● 968.监控二叉树 ● 总结

738. 单调递增的数字 中等 相关标签 相关企业 提示 当且仅当每个相邻位数上的数字 x 和 y 满足 x < y 时&#xff0c;我们称这个整数是单调递增的。 给定一个整数 n &#xff0c;返回 小于或等于 n 的最大数字&#xff0c;且数字呈 单调递增 。 示例 1: 输入: n 10输出: …...

出现 java: 找不到符号 符号: 变量 log 的解决方法

目录 1. 问题所示2. 原理分析3. 解决方法3.1 增加编译参数3.2 增加lombok插件3.3 清楚本地缓存1. 问题所示 使用Springboot启动项目的时候,出现如下bug: java: 找不到符号符号: 变量 log位置: 类 org.springblade.example.consumer.rpc.BlogStu...

大数据机器学习与深度学习—— 生成对抗网络(GAN)

GAN概述 在讲GAN之前&#xff0c;先讲一个小趣事&#xff0c;你知道GAN是怎么被发明的吗&#xff1f;据Ian Goodfellow自己说&#xff1a; 之前他一直在研究生成模型&#xff0c;可能是一时兴起&#xff0c;有一天他在酒吧喝酒时&#xff0c;在酒吧里跟朋友讨论起生成模型。然…...

vue前端访问Django channels WebSocket失败

现象 前端报错&#xff1a;SSH.vue:51 WebSocket connection to ‘ws://127.0.0.1:8000/server/terminal/120.59.88.26/22/1/’ failed: 后端报错&#xff1a;Not Found: /server/terminal/120.79.83.26/22/1/ 原因 django的版本与channels的版本不匹配&#xff08;django…...

厉害了!水浸监控技术有升级啦

水浸监控在今天的社会中变得愈发重要&#xff0c;特别是在各种行业和场所。面对突发的水灾&#xff0c;及时有效的监测和预警系统可以帮助组织减少损失&#xff0c;保障人员和财产的安全。 客户案例 商业办公楼 合肥某大型商业办公楼面临着水灾风险&#xff0c;而传统的监控系…...

【开题报告】基于SpringBoot的大学生心理教育平台的设计与实现

1.研究背景 大学生心理健康问题一直备受关注。随着社会压力的增加、人际关系的复杂化以及学业与就业压力等因素的影响&#xff0c;大学生心理健康问题日益突出。因此&#xff0c;设计并实现基于SpringBoot的大学生心理教育平台具有重要的研究意义和实践价值。 &#xff08;1&…...

376. 摆动序列

376. 摆动序列 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a;_376摆动序列_376摆动序列 错误经验吸取 原题链接&#xff1a; 376. 摆动序列 https://leetcode.cn/problems/wiggle-subsequence/description/ 完成情况&#xff1a; 解题…...

现在个人想上架微信小游戏已经这么难了吗...

引言 大家好&#xff0c;最近我突然想起来我还有一款微信小游戏还没有上架&#xff0c;于是捣鼓了一天把游戏完善了一下&#xff0c;然后准备提交审核&#xff0c;却发现异常的艰难... 1.为什么难&#xff1f; 相信大家都大概知道&#xff0c;自从微信平台宣布 9月1日起&…...

C语言数据结构-----二叉树(2)堆的深入理解及应用、链式二叉树的讲解及代码实现

前言 本篇文章讲述的内容有部分是上一节写过的。重复内容不会再进行说明&#xff0c;大家可以看上一节内容 链接: C语言数据结构-----二叉树(1)认识数、二叉树、堆及堆的代码实现 文章目录 前言1.使用堆解决TOP-K问题2.向下调整堆的时间复杂度与向上调整堆的时间复杂度对比3.堆…...

【算法】【动规】等差数列划分

跳转汇总链接 &#x1f449;&#x1f517;算法题汇总链接 1.2 等差数列划分 &#x1f517;题目链接 如果一个数列 至少有三个元素 &#xff0c;并且任意两个相邻元素之差相同&#xff0c;则称该数列为等差数列。例如&#xff0c;[1,3,5,7,9]、[7,7,7,7] 和 [3,-1,-5,-9] 都是…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...