ARM64汇编0B - 函数调用约定

建议先看《CSAPP》的3.7节,讲的很细。我们这里就直接看例子来分析了。

例子

static int func(int a, int b, int c, int d, int e, int f, int g, int h, int i)
{printf("%s\n", "add all");int x = a + b;return a + b + c + d + e + f + g + h + i;
}int main()
{getchar();int result = func(1, 2, 3, 4, 5, 6, 7, 8, 9);printf("result = %d\n", result);return 0;
}

上面的程序,我们写了一个 func 的调用,主要是观察其参数传递时,寄存器的使用以及栈的变化情况。

在ARM64体系结构中,栈是从高地址往低地址生长。栈在函数调用过程中起到非常重要的作用,包括存储函数使用的局部变量、传递参数等。在函数调用过程中,栈是逐步生成的。为单个函数分配的栈空间,即从该函数栈底(高地址)到栈顶(低地址)这段空间称为栈帧(Stack Frame)。

ARM64在函数参数传递时,参数1~参数8 分别保存到 X0~X7 寄存器中 ,剩下的参数从右往左依次入栈,被调用者实现栈平衡,返回值存放在 X0 中。

ARM在参数传递时,参数1~参数4 分别保存到 R0~R3 寄存器中 ,剩下的参数从右往左依次入栈,被调用者实现栈平衡,返回值存放在 R0 中。

我们看下上面程序的反汇编代码,有个地方需要注意,为了观察最原始的汇编代码需要在Applicataion.mk 里面添加一个选项,否则编译器会优化一些逻辑:

APP_OPTIM := debug
.text:0000000000000784 A8 03 5F B8                   LDUR            W8, [X29,#var_10]
.text:0000000000000788 E0 03 08 2A                   MOV             W0, W8                  ; a
.text:000000000000078C A1 C3 5E B8                   LDUR            W1, [X29,#var_14]       ; b
.text:0000000000000790 A2 83 5E B8                   LDUR            W2, [X29,#var_18]       ; c
.text:0000000000000794 A3 43 5E B8                   LDUR            W3, [X29,#var_1C]       ; d
.text:0000000000000798 E4 23 40 B9                   LDR             W4, [SP,#0x40+e]        ; e
.text:000000000000079C E5 1F 40 B9                   LDR             W5, [SP,#0x40+f]        ; f
.text:00000000000007A0 E6 1B 40 B9                   LDR             W6, [SP,#0x40+g]        ; g
.text:00000000000007A4 E7 17 40 B9                   LDR             W7, [SP,#0x40+h]        ; h
.text:00000000000007A8 EA 03 00 91                   MOV             X10, SP
.text:00000000000007AC E9 13 40 B9                   LDR             W9, [SP,#0x40+var_30]
.text:00000000000007B0 49 01 00 B9                   STR             W9, [X10,#0x40+i]       ; i
.text:00000000000007B4 0A 00 00 94                   BL              func

可以看到 a b c d e f g h,这8个参数是存放到了 W0 - W7 中,W 是 X 的32 位形式。

对于参数 i 的处理分3步:

MOV             X10, SP                    ;将sp的值给X10
LDR             W9, [SP,#0x40+var_30]      ;将9赋值给W9
STR             W9, [X10,#0x40+i]          ;将9储存到 sp+offset 中

是先将栈地址赋值给了 X10,然后将 i 的值存放到 W9 指向的地址里面,结合起来理解就是将 i 的值放到了栈里面。

我们动态的调试一下,观察栈变化:

前面的X0到X7的寄存器变化是符合预期的。

继续往下看,断点走到BL处,发现栈变化:

发现,将 9 的值储存到了 sp 的位置,偏移量为0。说明 [X10,#0x40+i] 计算出来的值就是 [X10],我们可以在这里按下Q键,看真实的汇编:

继续往下看,看跳转到 func 函数里面后栈的变化情况。一直走到 func 的 ret 指令,看栈的内容:

0000007FE24A0AE8  0000000900000003  
0000007FE24A0AF0  0000000700000008  
0000007FE24A0AF8  0000000500000006  
0000007FE24A0B00  0000000300000004  
0000007FE24A0B08  0000000100000002  
0000007FE24A0B10  0000007FE24A0B60  [stack]:0000007FE24A0B60
0000007FE24A0B18  000000632CC977B8  main+A4
0000007FE24A0B20  0000000000000009

可以看到,栈底首先储存的是第9个参数。

然后是返回地址,就是函数执行完之后需要执行的下一条指令的地址。

然后接着是栈指针,这个栈指针是 main 函数的栈地址,因为func函数执行完之后,需要将栈指针给还原,mian才好继续执行。

然后接着是参数,这是因为函数的逻辑可能需要使用到 X0 到 X7寄存器。所以先将寄存器的值储存到栈中,方便后续获取。

最后是局部变量,它的值也是放到了栈中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/30634.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java环境变量配置以及“‘javac‘ 不是内部或外部命令”问题的解决方法(2024年6月姆级最新)

😀前言 有很多小伙伴提问这个所以就单独出一个解决教程 java环境变量配置以及“‘javac’ 不是内部或外部命令”问题的解决方法(2024年6月姆级最新) 安装的话可以参考这个 java 安装和环境配置(2024-4月保姆级最新版) 🏠个人主页…

工业园安全生产新保障:广东地区加强可燃气体报警器校准检测

广东,作为我国经济的重要引擎,拥有众多工业园区。 这些工业园区中,涉及化工、制药、机械制造等多个领域,每天都会产生和使用大量的可燃气体。因此,可燃气体报警器的安装与校准检测,对于保障工业园区的安全…

Python 绘制圆欠采样时的数学图形

Python 绘制圆欠采样时的数学图形 正文end_radian 190end_radian 180end_radian 170end_radian 130end_radian 120 正文 今天在绘制圆形的时候遇到了意外,发现了一个有意思的现象,这里特来记录一下。 end_radian 190 import numpy as np import…

可靠性测试及模型计算

双85高温高湿测试 场景描述: 85℃温度 85%湿度 老化测试 目的: 衡量产品使用寿命 反向推导: 如何根据产品寿命及工况计算双85测试时间 模型介绍 本质是化学反应速率(老化的本质是)随温度的变化 温湿度循环测…

【MySQL统计函数count详解】

MySQL统计函数count详解 1. count()概述2. count(1)和count(*)和count(列名)的区别3. count(*)的实现方式 1. count()概述 count() 是一个聚合函数,返回指定匹配条件的行数。开发中常用来统计表中数据,全部数据,不为null数据,或…

Jax的方法

jax方法(.at .set .add .multiply) 位置索引.at 设置新值.set: import jax.numpy as jnp# 创建一个示例数组 a jnp.array([1, 2, 3, 4, 5])# 使用 .at 和 .set 方法将索引为 2 的元素设置为 10 b a.at[2].set(10)print("Original array:", a) #Original array: [1 …

【SpringCloud】负载均衡(Spring Cloud LoadBalancer)

负载均衡 当服务流量增大时,通常会采用增加机器的方式进行扩容。负载均衡就是用来在多个机器或者其他资源中,按照一定的规则合理分配负载。其中的实现可以分成客户端负载均衡和服务端负载均衡。 服务端负载均衡 在服务端进行负载均衡的算法分配。 比…

react学习——02虚拟dom创建的两种方式

1、使用jsx创建虚拟DOM const vdom <h1 id"title" className"red"><span>helloReact</span></h1> /*此处一定不要写引号*/<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8&quo…

【八股系列】点击一个按钮,浏览器会做些什么事情【呈现效果时流程】?(js)

文章目录 1. 事件的启程&#xff1a;捕获与目标识别2. 核心环节&#xff1a;事件处理与JavaScript的魔法2.1. 识别事件源&#xff1a;2.2. 查找事件监听器&#xff1a;2.3. 执行JavaScript代码&#xff1a; 3. 视觉重塑&#xff1a;UI的更新之旅4. 事件的回响&#xff1a;冒泡与…

pip下载越来越慢,需要怎么提速了?

pip下载慢通常是因为默认的Python包索引服务器在国外&#xff0c;国内访问受到网络限制。 为了解决这个问题&#xff0c;可以尝试以下几种方法来提高pip下载速度&#xff1a; 更换镜像源&#xff1a; 中国科技大学、清华大学等国内高校提供了Python包索引的镜像&#xff0c;你…

数据丢失?别怕,EasyRecovery来帮忙!

&#x1f31f; 数据丢失&#xff1f;别怕&#xff0c;EasyRecovery来帮忙&#xff01; 嘿&#xff0c;亲爱的的朋友们&#xff01;&#x1f44b;今天我要和大家分享一款超棒的数据恢复软件——EasyRecovery&#xff01;&#x1f389;你是否曾经遇到过不小心删除了重要文件、照片…

深入理解微服务架构 - Spring Cloud

目录 一 Spring Cloud概述 什么是Spring Cloud? 为什么选择Spring Cloud? 二 Spring Cloud的核心组件 Spring Cloud Config 概述 工作原理 示例代码 Spring Cloud Netflix Eureka 概述 工作原理 示例代码 Spring Cloud Ribbon 概述 工作原理 示例代码 Sprin…

支持向量机介绍

一、引言 1.支持向量机&#xff08;SVM&#xff09;的概念和背景 支持向量机&#xff08;Support Vector Machine&#xff0c;简称SVM&#xff09;是一种起源于统计学习理论的分类和回归算法。20世纪60年代&#xff0c;Vapnik等人提出了支持向量机理论&#xff0c;该理论基…

zip文件上传到linux服务器文件大小发生变化

在传一个文件到服务器的时候&#xff0c;第一次传完看见大小不一样&#xff08;服务器中du命令查看大小796596MB&#xff09;就重传了一下&#xff0c;还是大小不一样&#xff0c;就查了下。 查了下有以下原因&#xff1a; 文件系统的不同&#xff1a; 原因&#xff1a;不同的…

双色球预测算法(Java),——森林机器学习、时间序列

最近AI很火&#xff0c;老想着利用AI的什么算法&#xff0c;干点什么有意义的事情。其中之一便想到了双色球&#xff0c;然后让AI给我预测&#xff0c;结果基本都是简单使用随机算法列出了几个数字。 额&#xff0c;&#xff0c;&#xff0c;&#xff0c;咋说呢&#xff0c;双…

leetcode232用栈实现队列

本文主要讲解用栈实现队列的要点与细节&#xff0c;按照步骤思考更方便理解&#xff0c;同类型队列实现栈 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、pop、peek、empty&#xff09;&#xff1a; 实现 MyQueue 类&#xff1a; vo…

windows 系统根据端口查找进程,杀死进程

在启动项目时&#xff0c;往往设置的端口被占用&#xff0c;这时需要杀死端口所占用的进程&#xff0c;然后再重启项目。 netstat -ano | findstr :8085 taskkill /F /PID 25184 杀死进程后&#xff0c;再执行命令 netstat -ano | findstr :8085 进行查看端口占用情况

STM32多功能交通灯系统:从原理到实现

一、功能说明 本交通灯系统采用先进的stm32f103c8t6微处理器为核心控制单元。系统设置东南西北四个方向各配置两位数码管&#xff0c;用以精准展示5至99秒的时间范围&#xff0c;并且允许用户根据实际需求进行灵活调整。 在信号灯配置方面&#xff0c;每个方向均配备左转、直…

SYD881X读取GATT VALUE的长度

SYD881X读取GATT VALUE的长度 现在具体遇到这样一个需要&#xff0c;机器生产后要更新profile&#xff0c;这个只能够通过升级4K来做&#xff0c;但是需要知道profile是否改变了&#xff0c;这个就要知道profile是否改变来决定是否要升级&#xff0c;这里的做法是增加一个函数&…

肩背筋膜炎怎么治疗最有效

肩背筋膜炎是一种常见的肌肉骨骼疾病&#xff0c;其症状主要包括&#xff1a;肩背区域疼痛&#xff1a;由于筋膜组织受到损伤&#xff0c;肩背部位会出现明显的疼痛&#xff0c;疼痛可能会放射到周围的其他部位&#xff0c;严重时会影响睡眠和休息。肌肉紧张和僵硬&#xff1a;…