ARMV8 - A64 - 函数调用,内存栈操作
说明
- 看了下ARM平台上C语言函数调用的反汇编代码,理清楚了其中的内存栈汇编操作,特整理下。
- 本文环境基于:ARMv8-a架构A53核soc,aarch64状态。
预先了解的知识点
内存栈
- 栈和栈帧的基本概念
- 重点:出栈入栈的单位不是单个局部变量,而是栈帧。
相关寄存器
- FP:Frame Pointer(栈帧指针),指向当前栈帧的顶部,在A53平台是使用通用寄存器x29保存。
- SP:Stack Pointer(栈顶指针),保存当前栈顶地址,在A53平台是一个特殊寄存器,不同异常等级是不同的寄存器,
- 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
说明
- 从汇编代码可以看出存在两种不同实现,如下:
- 函数调用栈中间函数(test1)
- 函数调用栈末端函数(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
问题
- 为什么中间函数和末端函数实现不同,中间函数需要将x29,x30保存到栈内存中,最后再从栈内存中load到x29,x30中。
- 是因为中间函数(test1)bl指令调用末端函数(test)时,会覆盖掉x30的数据(原本保存的是父函数main,跳转test1的下一条指令),覆盖后中间函数(test1)的ret指令就跳不回main函数了,因此需要先将x30的数据保存到栈上,从子函数跳转回来后,需要将x29,x30的数据从栈上恢复。
- x29是栈帧指针,保存是当前函数的frame pointer,是约定俗成,因此需要保存和恢复,但是也不是必须,例如:test函数中就没有使用x29。
注意项
- sp 必须16Byte 对齐,扩大和缩小都必须是16字节的倍数。
相关文章:
ARMV8 - A64 - 函数调用,内存栈操作
说明 看了下ARM平台上C语言函数调用的反汇编代码,理清楚了其中的内存栈汇编操作,特整理下。本文环境基于:ARMv8-a架构A53核soc,aarch64状态。 预先了解的知识点 内存栈 栈和栈帧的基本概念重点:出栈入栈的单位不是…...
MyBatis 四大核心组件之 ResultSetHandler 源码解析
🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot 🌺 仓库主页: Gitee 💫 Github 💫 GitCode 💖 欢迎点赞…...
docker-compose 单机容器编排
docker-compose 单机容器编排 Dockerfile:先配置好的文件,然后bulid,镜像容器。 docker-compose 既可以基于dockerfile,也可以基于镜像,一键式拉起镜像和容器。 docker-compose 核心就是yml文件,可以定义…...
springboot项目使用Layui作为前端UI的一系列前后端交互的解决方法
背景: 因为比较喜欢Layui,因为多个项目都是从零开始就使用的layui开发的,并且开发过程中借鉴了很多其他项目(如Ruoyi、Pear Admin),因此最终选用大部分Pear Admin的项目中使用的一系列解决方案,…...
【Linux】Firewalld防火墙新增端口、开启、查看等
Linux操作系统中,Firewalld防火墙相关操作如下: 安装 yum install firewalld firewalld-configFirewall开启常见端口命令 新增端口: firewall-cmd --zonepublic --add-port80/tcp --permanentfirewall-cmd --zonepublic --add-port443/tc…...
学习笔记 -- TVS管选型参考
一、TVS管基本工作原理 当TVS管(瞬态电压抑制器)两极受到反向瞬态高能量冲击时,能以纳秒(ns)量级的速度,将两极间的高阻抗变为低阻抗,使两极间的电压箝位于一个预定的值,有效地保护电子线路中的元器件。 在浪涌电压作用下…...
功能更新|免费敏捷工具Leangoo领歌私有部署新增第三方身份认证和API对接
Leangoo领歌是一款永久免费的专业的敏捷开发管理工具,提供端到端敏捷研发管理解决方案,涵盖敏捷需求管理、任务协同、进展跟踪、统计度量等。 Leangoo支持敏捷研发管理全流程,包括小型团队敏捷开发,规模化敏捷SAFe,Scr…...
重生奇迹mu战士加点
在重生奇迹MU中,战士作为一个近战职业,主要依赖于物理攻击来输出伤害。因此,在加点方面,战士需要优先考虑加强自身的攻击力,同时也要增强自身的生存能力和耐久度。 以下是可参考的战士加点方案: 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以内数的加减法”这部分的作业,请你帮他检查一下。每道题目(包括弟弟的答案)的格式为abc或者a-bc,其中a和b是作…...
代码随想录算法训练营第37天|● 738.单调递增的数字 ● 968.监控二叉树 ● 总结
738. 单调递增的数字 中等 相关标签 相关企业 提示 当且仅当每个相邻位数上的数字 x 和 y 满足 x < y 时,我们称这个整数是单调递增的。 给定一个整数 n ,返回 小于或等于 n 的最大数字,且数字呈 单调递增 。 示例 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之前,先讲一个小趣事,你知道GAN是怎么被发明的吗?据Ian Goodfellow自己说: 之前他一直在研究生成模型,可能是一时兴起,有一天他在酒吧喝酒时,在酒吧里跟朋友讨论起生成模型。然…...
vue前端访问Django channels WebSocket失败
现象 前端报错:SSH.vue:51 WebSocket connection to ‘ws://127.0.0.1:8000/server/terminal/120.59.88.26/22/1/’ failed: 后端报错:Not Found: /server/terminal/120.79.83.26/22/1/ 原因 django的版本与channels的版本不匹配(django…...
厉害了!水浸监控技术有升级啦
水浸监控在今天的社会中变得愈发重要,特别是在各种行业和场所。面对突发的水灾,及时有效的监测和预警系统可以帮助组织减少损失,保障人员和财产的安全。 客户案例 商业办公楼 合肥某大型商业办公楼面临着水灾风险,而传统的监控系…...
【开题报告】基于SpringBoot的大学生心理教育平台的设计与实现
1.研究背景 大学生心理健康问题一直备受关注。随着社会压力的增加、人际关系的复杂化以及学业与就业压力等因素的影响,大学生心理健康问题日益突出。因此,设计并实现基于SpringBoot的大学生心理教育平台具有重要的研究意义和实践价值。 (1&…...
376. 摆动序列
376. 摆动序列 原题链接:完成情况:解题思路:参考代码:_376摆动序列_376摆动序列 错误经验吸取 原题链接: 376. 摆动序列 https://leetcode.cn/problems/wiggle-subsequence/description/ 完成情况: 解题…...
现在个人想上架微信小游戏已经这么难了吗...
引言 大家好,最近我突然想起来我还有一款微信小游戏还没有上架,于是捣鼓了一天把游戏完善了一下,然后准备提交审核,却发现异常的艰难... 1.为什么难? 相信大家都大概知道,自从微信平台宣布 9月1日起&…...
C语言数据结构-----二叉树(2)堆的深入理解及应用、链式二叉树的讲解及代码实现
前言 本篇文章讲述的内容有部分是上一节写过的。重复内容不会再进行说明,大家可以看上一节内容 链接: C语言数据结构-----二叉树(1)认识数、二叉树、堆及堆的代码实现 文章目录 前言1.使用堆解决TOP-K问题2.向下调整堆的时间复杂度与向上调整堆的时间复杂度对比3.堆…...
【算法】【动规】等差数列划分
跳转汇总链接 👉🔗算法题汇总链接 1.2 等差数列划分 🔗题目链接 如果一个数列 至少有三个元素 ,并且任意两个相邻元素之差相同,则称该数列为等差数列。例如,[1,3,5,7,9]、[7,7,7,7] 和 [3,-1,-5,-9] 都是…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
