当前位置: 首页 > 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] 都是…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...