arm64 linux 除零正常返回,arm64程序调用规则

前言

这篇主要介绍arm64程序调用规则,详细分析了程序调用过程中,参数是如何传递的。Android、iOS、Linux等基本遵循这些规则,但是各个操作系统平台也有小部分自己特定的规则。下一篇,我将介绍iOS平台的特定规则。

术语介绍

术语

意义

A32

在ARMv7架构中,使用32位固定长度指令的ARM指令集。

A64

AArch64可用时的指令集。

AAPCS64

AArch64程序调用标准。(PCS:Procedure Call Standard)

AArch32

ARMv8中的32位通用寄存器,兼容ARMv7-A。

AArch64

ARMv8中的64位通用寄存器

ABI(Application Binary Interface)

汇编接口规范,跟执行环境相关,比如Linux ABI,说的是Linux环境下的汇编接口规范;

ARM-based

基于ARM

Floating point

根据上下文有这三种意思:(1)遵循IEEE 754 2008的浮点运算; (2)ARMv8浮点指令集; (3)一个被ARMv8浮点指令集和ARMv8 SIMD指令集共享的寄存器组。

Q-o-I

Quality of Implementation

SIMD

Single Instruction Multiple Data 一条指令操作多个数据

T32

T32使用可变16bit和32bit

Routine, subroutine

Routine:调用者;subroutine:被调用者

Procedure

没有返回值的函数

Function

有返回值的函数

PIC, PID

Position-independent code, position-independent data.

Program state

指程序内存和寄存器的值

Caller- saved register

调用者在调用函数之前,保存寄存器(一般入栈),函数返回后恢复寄存器(一般出栈)

Callee-saved register

被调用者(函数内部),在起始地方保存寄存器,在结束时,恢复寄存器

NGRN(The Next General-purpose Register Number )

可以理解为,记录r0-r7(见下文寄存器)使用个数,参数传递前设为0,每放一个参数进入寄存器(整型寄存器),值加1。当等于8时候,说明r0-r7寄存器使用完了,再有参数,只能放入内存了。

NSRN (The Next SIMD and Floating-point Register Number)

同上,记录v0-v7使用个数

NSAA (The next stacked argument address)

记录参数放入内存,参数传递前设为SP,所以内存中参数范围应该是 sp~NSAA。详细见下文参数传递

数据类型和对齐

基本数据类型

Type ClassMachine TypeByte

sizeNatural

Alignment

(bytes)

IntegralUnsigned byte11

Signed byte11

Unsigned half-

word22

Signed half-

word22

Unsigned word44

Signed word44

Unsigned

double-word88

Signed double-

word88

Unsigned quad-

word1616

Signed quad-

word1616

Floating PointHalf precision22

Single precision44

Double

precision88

Quad precision1616

Short vector64-bit vector88

128-bit vector1616

PointerData pointer88

Code pointer88

程序调用规则

寄存器

arm64有两种寄存器:

处理整型和指针的寄存器

通用寄存器和AAPCS64用法

寄存器

别名

意义

SP

Stack Pointer:栈指针

r30

LR

Link Register:在调用函数时候,保存下一条要执行指令的地址。

r29

FP

Frame Pointer:保存函数栈的基地址。

r19...r28

Callee-saved registers(含义见上面术语解释)

r18

平台寄存器,有特定平台解释其用法。如果平台未把其做特殊用途,可当做临时寄存器使用。(iOS平台保留的寄存器,应用不可使用)

r17

IP1

The second intra-procedure-call temporary register (can be used by call veneers and PLT code); at other times may be used as a temporary register.

r16

IP0

The first intra-procedure-call scratch register (can be used by call veneers and PLT code); at other times may be used as a temporary register.

r9...r15

临时寄存器

r8

在一些情况下,返回值是通过r8返回的

r0...r7

r0-r7在函数调用过程中传递参数和返回值

NZCV

状态寄存器:N(Negative)负数 Z(Zero) 零 C(Carry) 进位 V(Overflow) 溢出

arm64有31个通用整型寄存器,r0-r30。当使用64bits时候,命名x0-x30;使用32bits时,命名w0-w30。当寄存器在此程序调用标准中具有固定角色时,使用大写。

SIMD 和 Floating-Point寄存器

ARM64有32个寄存器v0-v31,用于处理SIMD和浮点运算。长度不同称谓也不同,b,h,s,d,q,分别代表byte(8位),half(16位),single(32位),double(64位),quad(128位)。v0-v7在函数调用过程中传递参数和返回值;v8-v15 是Callee-saved registers(见术语解释),且是保存前64bits(更大的位数,调用者负责保存),v0-v7, v16-v31不需要保存或者调用者保存。

进程、内存、栈

一个进程的内存可分为5类:

代码区。只能被进程读,不可些。

可写静态数据。

只读静态数据。

堆。

栈。

可写静态数据可以细分为初始化,零初始化和未初始化数据。 除了栈之外,其它4类内存不需要占用连续的内存。 进程必须具有一些代码和栈,其它3类不是必须有。

堆是由进程管理的内存区域, 通常用于创建动态数据对象。

内存地址

地址空间包括一个或多个不相交的区域。 区域不能跨越零地址,但是可以从零开始。

标记寻址(tagged addressing)的使用是特定平台解释的。 当禁用标记寻址时,指针的所有64位都被传递到地址转换系统。 启用标记寻址时,为了进行地址转换,将忽略指针的前八位。注意:此tagged addressing,非iOS里的Tagged Pointer。

栈是连续的内存空间,可用于存储局部变量和参数传递(用于传递参数的寄存器不够用时候)。栈地址是从高到低,栈的地址保存在SP中。

栈使用限制:

Stack-limit < SP <= stack-base

进程只能访问这个范围内的栈空间:[SP, stack-base – 1]

SP mod 16 = 0

函数调用

A64指令集包含函数调用指令BL和BLR。

执行BL:PC(program counter)顺序的下一个值,也就是返回地址(函数调用完成返回要执行指令的地址),存放到LR中,将跳转地址传给PC。BLR跟BL类似,只不过PC的值是从寄存器中读取。

参数传递

参数可通过r0-r7、v0-v7,栈来传递;如果参数个数不多,且参数可放进寄存器,那仅用寄存器传递参数。

可变参数

可变参数可分为命名参数(已声明的)和匿名参数(可选的参数)。

当可变参数的函数,调用时候,没有可选参数时候(只有已声明的参数),调用过程和固定参数的函数一样的。

参数传递规则

参数传递从概念上可以分为2阶段:

从源语言参数类型到机器类型的映射(不同源语言,映射规则不同)

整理机器类型,生成最终参数列表

参数传递过程分为3个阶段:

阶段A – 初始化

(在开始处理参数之前,该阶段仅执行一次)

NGRN = 0 (NGRN意义,见术语)

NSRN = 0 (NSRN意义,见术语)

NSAA = SP(NSAA意义,见术语)

阶段B - 预填充和扩展参数 (把参数列表中的每一个参数,去匹配下面规则,第一个被匹配到的规则,应用到该参数上。)

如果参数类型是复合类型,调用者和被调用者都不能确定其大小,则将参数复制到内存中,并将参数替换为指向该内存的指针。 (C / C ++语言中没有这样的类型,其它语言存在。)

如果参数是HFA或HVA类型,则参数不修改。

如果参数是大于16个字节的复合类型,调用者申请一个内存,将参数复制到内存里去,并将参数替换为指向该内存的指针。

如果参数是复合类型,则参数的大小向上舍入为最接近8个字节的倍数。(例如参数大小为9字节,修改为16字节)

阶段C- 把参数放到寄存器或栈里 (参数列表中的每个参数,将依次应用以下规则,直到参数放到寄存器或栈里,此参数处理完成,然后再从参数列表中取参数。注: 将参数分配给寄存器时,寄存器中未使用的位的值不确定。 将参数分配给栈时,未填充字节的值不确定。)

(1) 如果参数是half(16bit),single(16bit),double(32bit)或quad(64bit)浮点数或Short Vector Type,并且NSRN小于8,则将参数放入寄存器v[NSRN]的最低有效位。 NSRN增加1。 此参数处理完成。

(2) 如果参数是HFA(homogeneous floating-point aggregate)或HVA(homogeneous short vector aggregate)类型,且NSRN + (HFA或HVA成员个数) ≤ 8,则每个成员依次放入SIMD and Floating-point 寄存器,NSRN=NSRN+ HFA或HVA成员个数。此参数处理完成。

(3) 如果参数是HFA(homogeneous floating-point aggregate)或HVA(homogeneous short vector aggregate)类型,但是NSRN已经等于8(说明v0-v7被使用完毕)。则参数的大小向上舍入为最接近8个字节的倍数。(例如参数大小为9字节,修改为16字节)

(4) 如果参数是HFA(homogeneous floating-point aggregate)、HVA(homogeneous short vector aggregate)、quad(64bit)浮点数或Short Vector Type,NSAA = NSAA+max(8, 参数自然对齐大小)。

(5) 如果参数是half(16bit),single(16bit)浮点数,参数扩展到8字节(放入最低有效位,其余bits值不确定)

(6) 如果参数是HFA(homogeneous floating-point aggregate)、HVA(homogeneous short vector aggregate)、half(16bit),single(16bit),double(32bit)或quad(64bit)浮点数或Short Vector Type,参数copy到内存,NSAA=NSAA+size(参数)。此参数处理完成。

(7) 如果参数是整型或指针类型、size(参数)<=8字节,且NGRN小于8,则参数复制到x[NGRN]中的最低有效位。 NGRN增加1。 此参数处理完成。

(8) 如果参数对齐后16字节,NGRN向上取偶数。(例如:NGRN为2,那值保持不变;假如NGRN为3,则取4。 注:iOS ABI没有这个规则)

(9) 如果参数是整型,对齐后16字节,且NGRN小于7,则把参数复制到x[NGRN] 和 x[NGRN+1],x[NGRN]是低位。NGRN = NGRN + 2。 此参数处理完成。

(10) 如果参数是复合类型,且参数可以完全放进x寄存器(8-NGRN>= 参数字节大小/8)。从x[NGRN]依次放入参数(低位开始)。未填充的bits的值不确定。NGRN = NGRN + 此参数用掉的寄存器个数。此参数处理完成。

(11) NGRN设为8。

(12) NSAA = NSAA+max(8, 参数自然对齐大小)。

(13) 如果参数是复合类型,参数copy到内存,NSAA=NSAA+size(参数)。此参数处理完成。

(14) 如果参数小于8字节,参数设置为8字节大小,高位bits值不确定。

(15) 参数copy到内存,NSAA=NSAA+size(参数)。此参数处理完成。

从上面规则,可以得到经验:

处理完参数列表中所有的参数后,调用者一定知道传递参数用了多少栈空间。(NSAA - SP)

浮点数和short vector types通过v寄存器和栈传递,不会通过r寄存器传递。(除非是小复合类型的成员)

寄存器和栈中,参数未填充满的部分的值,不可确定。

函数返回结果

函数返回方式取决于返回结果的类型。

如果返回是类型T,如下

void func(T arg)

复制代码

arg值通过寄存器(组)传递,返回的结果也是通过相同的寄存器(组)返回。

2. 调用者申请内存(内存大小足够放入返回结果且是内存对齐的),将内存地址放入x8中传递给子函数,子函数运行时候,可以更新x8指向内存的内容,从而将结果返回。

结语

假如文章有不对地方,欢迎大家留言指出;或者给我发邮件(wu_k_k@foxmail.com)。

引用

--EOF-- 转载请保留链接,谢谢

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

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

相关文章

苹方字体 for linux,苹果苹方字体

苹果苹方字体是一款很实用的字体软件&#xff0c;苹果苹方字体是为中国苹果用户打造的全新字体&#xff0c;共有六种字重&#xff0c;使用方便&#xff0c;能够满足用户在阅读时不同的字体需求&#xff0c;并且苹果苹方字体还可以在安卓、Linux 等其他平台和设备上使用&#xf…

linux系统关机half,Linux 学习 (六) 关机与重启命令

JavaScript基础 DOM的操作1.DOM的基本概念 DOM是文档对象模型,这种模型为树模型:文档是指标签文档:对象是指文档中每个元素:模型是指抽象化的东西. 2.Windows对象操作 一.属性和方法: window对象——浏览器 ...推荐《HeadFirst设计模式》相对于国内初版的,HeadFirst真的是更好的…

职坐标c语言,C/C++知识点之hexdump的C语言实现

本文主要向大家介绍了C/C知识点之hexdump的C语言实现&#xff0c;通过具体的内容向大家展示&#xff0c;希望对大家学习C/C知识点有所帮助。1 void hexdump(char *buf, int len)2 {3 int i 0;45 printf("\n----------------------hexdump-----------------------…

C语言编杂志程序,c语言程序错误修改

题目:杂志订阅管理系统使用计算机对一种杂志的订阅进行管理,该杂志最多订户不超过10人,每个订户的信息包括:姓名 性别 地址 电话号码 杂志单价 订阅数 订阅期限(至**年**月)。现要求用菜单选择并完成下述的功能&#xff1a;(1)增加新订户&#xff0c;既将订户的全部信息输入到文…

c语言关键词中英翻译机编程,课程设计--C语言关键字中英翻译机

《课程设计--C语言关键字中英翻译机》由会员分享&#xff0c;可在线阅读&#xff0c;更多相关《课程设计--C语言关键字中英翻译机(21页珍藏版)》请在人人文库网上搜索。1、课课 程程 设设 计计 报报 告告 学院、系&#xff1a; 专业名称&#xff1a; 课程设计科目 所在班级&…

c语言参数不能用 吗,如何在C语言中禁止“未使用的参数”警告?

您可以使用gcc / clang的未使用属性&#xff0c;但是我在标头中使用这些宏&#xff0c;以避免在整个源代码中__attribute__都有gcc特定的属性&#xff0c;而且到处都有点冗长/难看。#ifdef __GNUC__# define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))#else# defin…

c语言龙贝格积分法实验报告,数值作业:龙贝格算法计算积分C语言实现

数值作业:龙贝格算法计算积分C语言实现数值作业:龙贝格算法计算积分C语言实现根据Romberg算法计算定积分&#xff0c;和变步长的Simpson算法的输入都一样&#xff0e;算法基本分析&#xff1a;输入a,b(积分上下限),n为积分区间等分数&#xff0c;eps为计算精度&#xff0c;我这…

软件设计师考c语言,软件设计师教程考点精讲之C语言三大定律

2016下半年软考软件设计师报名即将开始&#xff0c;同学们是否在学习过程中遇到了一些困难&#xff0c;下面由希赛软考学院为打算参加下半年考试的你们准备了一些软件设计师教程考点精讲之Java编程性能措施&#xff0c;希望对大家有所帮助。自己总结的&#xff0c;觉得能帮助初…

用c语言程序算自己的年龄,新手编的小程序:计算年龄和出生后经历的天数的小程序...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼#includeint main(){int i,j,k,t,m,a,b,c0;int x,y,z,n;printf ("请按下面格式输年-月-日\n");printf("请输入现在年月日&#xff1a;\n");scanf ("%d-%d-%d",&i,&j,&k);printf("请…

计算机二级c语言公共基础题,计算机二级C语言笔试公共基础知识课后习题及答案...

全国计算机等级考试二级公共基础知识课后习题及答案1第一章数据结构与算法一.选择题1.算法的时间复杂度是指( )A. 执行算法程序所需要的时间B. 算法程序的长度C. 算法执行过程中所需要的基本运算次数D. 算法程序中的指令条数2.算法的空间复杂度是指( )A. 算法程序的长度B. 算法…

w ndows7文档加密取消,win7文件夹怎么加密?windows7文件加密方法

win7文件夹怎么加密?电脑文件隐私问题一直都是很多用户的关注重点&#xff0c;尤其是自己电脑经常被他人使用的朋友。也许使用第三方软件为文件夹加密比较方便&#xff0c;但如果能够不借助“外力”完成这一任务就更加完美。下面&#xff0c;我们就一起来看看windows7文件加密…

dbscan算法c语言实现,用C++实现DBSCAN聚类算法

这几天由于工作需要&#xff0c;对DBSCAN聚类算法进行了C的实现。时间复杂度O(n^2)&#xff0c;主要花在算每个点领域内的点上。算法很简单&#xff0c;现共享大家参考&#xff0c;也希望有更多交流。数据点类型描述如下&#xff1a;复制代码 代码如下:#include using namespac…

小世界网络模型代码 c 语言,新的小世界网络模型实现文本特征的提取方法与流程...

本发明涉及语义网络技术领域&#xff0c;具体涉及新的小世界网络模型实现文本特征的提取方法。背景技术&#xff1a;目前常用的文本特征提取方法&#xff0c;包括词频-反文档频率方法—TF-IDF、信息增益方法、互信息等方法&#xff1b;TF-IDF的简单结构并不能有效地反映词汇或短…

米4用linux刷机救转,小米4变砖之后如何刷机自救?大神教你小米4线刷救砖方法...

三&#xff1a;使用miflash工具刷机的步骤本工具适用于小米&#xff0c;华为&#xff0c;联想等手机品牌高通版本&#xff0c;不只是小米专用&#xff0c;教程仅供参考&#xff0c;看完一遍后再刷机。第一步&#xff1a;刷机工具安装1.下载小米手机刷机工具MiPhone2015731&…

android动态更新配置文件,Android如何动态修改Manifest文件

修改manifest文件Android Manifest.xml&#xff0c;添加相应的声明。在这里&#xff0c;我们需要将新定义的活动PrefsActivity注册到manifest文件。同前面一样&#xff0c;在Eclipse中打开AndroidManifest.xml文件会默认进入Eclipse提供的图形化编辑界面。单击Application选项卡…

com.android.phone已停止运行怎么解决方法,com.android.phone已停止运行怎么解决

在安卓手机上&#xff0c;不少用户都会遇过com.android.phone已停止的弹窗&#xff0c;尤其经常刷机的最明显。导致的原因实在太多&#xff0c;有刷机步骤不对的&#xff0c;乱改系统文件的&#xff0c;这里小编综合网上的情况以及自身经历&#xff0c;给广大安卓用户一个com.a…

android动画放大后缩小,Android 补间动画 scale(缩放)

今天又遇到了关于Android 动画方面的问题&#xff0c;免不了一番疯狂找资料&#xff0c;所幸解决了自己的问题&#xff0c;为了避免以后遇到同样的问题&#xff0c;再次到处找资料&#xff0c;于是决定写篇随笔记录下来&#xff0c;方便自己方便大家^_^&#xff1b;废话就不说了…

android 生成泛型对象,java android解析多层含有泛型对象的json数据获取不到泛型类型解析失败解决办法...

####问题描述* java 解析多层含有泛型对象的json数据获取不到泛型类型* 如果将泛型改成实际的类型就能正常解析* 如果不改成实际的类型泛型数据被解析成com.google.gson.internal.LinkedTreeMap* 如果强制转换报错:java.lang.ClassCastException: com.google.gson.internal.Lin…

android 机器人动画,Android 5.X与Android4.X版本机器人动画的区别以及制作动画的方法...

今天翻了下墙&#xff0c;解决了一直以来的疑惑问题&#xff1a;为什么Android5.0以及6.0的recovery版本&#xff0c;机器人动画怎么就只有一张图片&#xff1f;这个问题&#xff0c;我百思不得其解&#xff0c;看了很多网文&#xff0c;也只是有了个概念。请参考以下文档&…

android盒子smb,普通安卓盒子smb方法 - 怀旧游戏长廊 - A9VG电玩部落论坛 - Powered by Discuz!...

本帖最后由 slime525 于 2018-10-20 21:00 编辑1安卓下安装盒子伴侣一键自动安装Optware2win下安装Putty&#xff0c;记下盒子ip端口&#xff0c;账户密码分别是&#xff1a;root&#xff0c;toor。小写&#xff01;3然后直接输入&#xff1a;ipkg-opt install samba就会自动下…