arm64 linux 除零正常返回,arm64程序调用规则
前言
這篇主要介紹arm64程序調(diào)用規(guī)則,詳細(xì)分析了程序調(diào)用過(guò)程中,參數(shù)是如何傳遞的。Android、iOS、Linux等基本遵循這些規(guī)則,但是各個(gè)操作系統(tǒng)平臺(tái)也有小部分自己特定的規(guī)則。下一篇,我將介紹iOS平臺(tái)的特定規(guī)則。
術(shù)語(yǔ)介紹
術(shù)語(yǔ)
意義
A32
在ARMv7架構(gòu)中,使用32位固定長(zhǎng)度指令的ARM指令集。
A64
AArch64可用時(shí)的指令集。
AAPCS64
AArch64程序調(diào)用標(biāo)準(zhǔn)。(PCS:Procedure Call Standard)
AArch32
ARMv8中的32位通用寄存器,兼容ARMv7-A。
AArch64
ARMv8中的64位通用寄存器
ABI(Application Binary Interface)
匯編接口規(guī)范,跟執(zhí)行環(huán)境相關(guān),比如Linux ABI,說(shuō)的是Linux環(huán)境下的匯編接口規(guī)范;
ARM-based
基于ARM
Floating point
根據(jù)上下文有這三種意思:(1)遵循IEEE 754 2008的浮點(diǎn)運(yùn)算; (2)ARMv8浮點(diǎn)指令集; (3)一個(gè)被ARMv8浮點(diǎn)指令集和ARMv8 SIMD指令集共享的寄存器組。
Q-o-I
Quality of Implementation
SIMD
Single Instruction Multiple Data 一條指令操作多個(gè)數(shù)據(jù)
T32
T32使用可變16bit和32bit
Routine, subroutine
Routine:調(diào)用者;subroutine:被調(diào)用者
Procedure
沒(méi)有返回值的函數(shù)
Function
有返回值的函數(shù)
PIC, PID
Position-independent code, position-independent data.
Program state
指程序內(nèi)存和寄存器的值
Caller- saved register
調(diào)用者在調(diào)用函數(shù)之前,保存寄存器(一般入棧),函數(shù)返回后恢復(fù)寄存器(一般出棧)
Callee-saved register
被調(diào)用者(函數(shù)內(nèi)部),在起始地方保存寄存器,在結(jié)束時(shí),恢復(fù)寄存器
NGRN(The Next General-purpose Register Number )
可以理解為,記錄r0-r7(見(jiàn)下文寄存器)使用個(gè)數(shù),參數(shù)傳遞前設(shè)為0,每放一個(gè)參數(shù)進(jìn)入寄存器(整型寄存器),值加1。當(dāng)?shù)扔?時(shí)候,說(shuō)明r0-r7寄存器使用完了,再有參數(shù),只能放入內(nèi)存了。
NSRN (The Next SIMD and Floating-point Register Number)
同上,記錄v0-v7使用個(gè)數(shù)
NSAA (The next stacked argument address)
記錄參數(shù)放入內(nèi)存,參數(shù)傳遞前設(shè)為SP,所以內(nèi)存中參數(shù)范圍應(yīng)該是 sp~NSAA。詳細(xì)見(jiàn)下文參數(shù)傳遞
數(shù)據(jù)類(lèi)型和對(duì)齊
基本數(shù)據(jù)類(lèi)型
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
程序調(diào)用規(guī)則
寄存器
arm64有兩種寄存器:
處理整型和指針的寄存器
通用寄存器和AAPCS64用法
寄存器
別名
意義
SP
Stack Pointer:棧指針
r30
LR
Link Register:在調(diào)用函數(shù)時(shí)候,保存下一條要執(zhí)行指令的地址。
r29
FP
Frame Pointer:保存函數(shù)棧的基地址。
r19...r28
Callee-saved registers(含義見(jiàn)上面術(shù)語(yǔ)解釋)
r18
平臺(tái)寄存器,有特定平臺(tái)解釋其用法。如果平臺(tái)未把其做特殊用途,可當(dāng)做臨時(shí)寄存器使用。(iOS平臺(tái)保留的寄存器,應(yīng)用不可使用)
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
臨時(shí)寄存器
r8
在一些情況下,返回值是通過(guò)r8返回的
r0...r7
r0-r7在函數(shù)調(diào)用過(guò)程中傳遞參數(shù)和返回值
NZCV
狀態(tài)寄存器:N(Negative)負(fù)數(shù) Z(Zero) 零 C(Carry) 進(jìn)位 V(Overflow) 溢出
arm64有31個(gè)通用整型寄存器,r0-r30。當(dāng)使用64bits時(shí)候,命名x0-x30;使用32bits時(shí),命名w0-w30。當(dāng)寄存器在此程序調(diào)用標(biāo)準(zhǔn)中具有固定角色時(shí),使用大寫(xiě)。
SIMD 和 Floating-Point寄存器
ARM64有32個(gè)寄存器v0-v31,用于處理SIMD和浮點(diǎn)運(yùn)算。長(zhǎng)度不同稱(chēng)謂也不同,b,h,s,d,q,分別代表byte(8位),half(16位),single(32位),double(64位),quad(128位)。v0-v7在函數(shù)調(diào)用過(guò)程中傳遞參數(shù)和返回值;v8-v15 是Callee-saved registers(見(jiàn)術(shù)語(yǔ)解釋),且是保存前64bits(更大的位數(shù),調(diào)用者負(fù)責(zé)保存),v0-v7, v16-v31不需要保存或者調(diào)用者保存。
進(jìn)程、內(nèi)存、棧
一個(gè)進(jìn)程的內(nèi)存可分為5類(lèi):
代碼區(qū)。只能被進(jìn)程讀,不可些。
可寫(xiě)靜態(tài)數(shù)據(jù)。
只讀靜態(tài)數(shù)據(jù)。
堆。
棧。
可寫(xiě)靜態(tài)數(shù)據(jù)可以細(xì)分為初始化,零初始化和未初始化數(shù)據(jù)。 除了棧之外,其它4類(lèi)內(nèi)存不需要占用連續(xù)的內(nèi)存。 進(jìn)程必須具有一些代碼和棧,其它3類(lèi)不是必須有。
堆是由進(jìn)程管理的內(nèi)存區(qū)域, 通常用于創(chuàng)建動(dòng)態(tài)數(shù)據(jù)對(duì)象。
內(nèi)存地址
地址空間包括一個(gè)或多個(gè)不相交的區(qū)域。 區(qū)域不能跨越零地址,但是可以從零開(kāi)始。
標(biāo)記尋址(tagged addressing)的使用是特定平臺(tái)解釋的。 當(dāng)禁用標(biāo)記尋址時(shí),指針的所有64位都被傳遞到地址轉(zhuǎn)換系統(tǒng)。 啟用標(biāo)記尋址時(shí),為了進(jìn)行地址轉(zhuǎn)換,將忽略指針的前八位。注意:此tagged addressing,非iOS里的Tagged Pointer。
棧
棧是連續(xù)的內(nèi)存空間,可用于存儲(chǔ)局部變量和參數(shù)傳遞(用于傳遞參數(shù)的寄存器不夠用時(shí)候)。棧地址是從高到低,棧的地址保存在SP中。
棧使用限制:
Stack-limit < SP <= stack-base
進(jìn)程只能訪問(wèn)這個(gè)范圍內(nèi)的棧空間:[SP, stack-base – 1]
SP mod 16 = 0
函數(shù)調(diào)用
A64指令集包含函數(shù)調(diào)用指令BL和BLR。
執(zhí)行BL:PC(program counter)順序的下一個(gè)值,也就是返回地址(函數(shù)調(diào)用完成返回要執(zhí)行指令的地址),存放到LR中,將跳轉(zhuǎn)地址傳給PC。BLR跟BL類(lèi)似,只不過(guò)PC的值是從寄存器中讀取。
參數(shù)傳遞
參數(shù)可通過(guò)r0-r7、v0-v7,棧來(lái)傳遞;如果參數(shù)個(gè)數(shù)不多,且參數(shù)可放進(jìn)寄存器,那僅用寄存器傳遞參數(shù)。
可變參數(shù)
可變參數(shù)可分為命名參數(shù)(已聲明的)和匿名參數(shù)(可選的參數(shù))。
當(dāng)可變參數(shù)的函數(shù),調(diào)用時(shí)候,沒(méi)有可選參數(shù)時(shí)候(只有已聲明的參數(shù)),調(diào)用過(guò)程和固定參數(shù)的函數(shù)一樣的。
參數(shù)傳遞規(guī)則
參數(shù)傳遞從概念上可以分為2階段:
從源語(yǔ)言參數(shù)類(lèi)型到機(jī)器類(lèi)型的映射(不同源語(yǔ)言,映射規(guī)則不同)
整理機(jī)器類(lèi)型,生成最終參數(shù)列表
參數(shù)傳遞過(guò)程分為3個(gè)階段:
階段A – 初始化
(在開(kāi)始處理參數(shù)之前,該階段僅執(zhí)行一次)
NGRN = 0 (NGRN意義,見(jiàn)術(shù)語(yǔ))
NSRN = 0 (NSRN意義,見(jiàn)術(shù)語(yǔ))
NSAA = SP(NSAA意義,見(jiàn)術(shù)語(yǔ))
階段B - 預(yù)填充和擴(kuò)展參數(shù) (把參數(shù)列表中的每一個(gè)參數(shù),去匹配下面規(guī)則,第一個(gè)被匹配到的規(guī)則,應(yīng)用到該參數(shù)上。)
如果參數(shù)類(lèi)型是復(fù)合類(lèi)型,調(diào)用者和被調(diào)用者都不能確定其大小,則將參數(shù)復(fù)制到內(nèi)存中,并將參數(shù)替換為指向該內(nèi)存的指針。 (C / C ++語(yǔ)言中沒(méi)有這樣的類(lèi)型,其它語(yǔ)言存在。)
如果參數(shù)是HFA或HVA類(lèi)型,則參數(shù)不修改。
如果參數(shù)是大于16個(gè)字節(jié)的復(fù)合類(lèi)型,調(diào)用者申請(qǐng)一個(gè)內(nèi)存,將參數(shù)復(fù)制到內(nèi)存里去,并將參數(shù)替換為指向該內(nèi)存的指針。
如果參數(shù)是復(fù)合類(lèi)型,則參數(shù)的大小向上舍入為最接近8個(gè)字節(jié)的倍數(shù)。(例如參數(shù)大小為9字節(jié),修改為16字節(jié))
階段C- 把參數(shù)放到寄存器或棧里 (參數(shù)列表中的每個(gè)參數(shù),將依次應(yīng)用以下規(guī)則,直到參數(shù)放到寄存器或棧里,此參數(shù)處理完成,然后再?gòu)膮?shù)列表中取參數(shù)。注: 將參數(shù)分配給寄存器時(shí),寄存器中未使用的位的值不確定。 將參數(shù)分配給棧時(shí),未填充字節(jié)的值不確定。)
(1) 如果參數(shù)是half(16bit),single(16bit),double(32bit)或quad(64bit)浮點(diǎn)數(shù)或Short Vector Type,并且NSRN小于8,則將參數(shù)放入寄存器v[NSRN]的最低有效位。 NSRN增加1。 此參數(shù)處理完成。
(2) 如果參數(shù)是HFA(homogeneous floating-point aggregate)或HVA(homogeneous short vector aggregate)類(lèi)型,且NSRN + (HFA或HVA成員個(gè)數(shù)) ≤ 8,則每個(gè)成員依次放入SIMD and Floating-point 寄存器,NSRN=NSRN+ HFA或HVA成員個(gè)數(shù)。此參數(shù)處理完成。
(3) 如果參數(shù)是HFA(homogeneous floating-point aggregate)或HVA(homogeneous short vector aggregate)類(lèi)型,但是NSRN已經(jīng)等于8(說(shuō)明v0-v7被使用完畢)。則參數(shù)的大小向上舍入為最接近8個(gè)字節(jié)的倍數(shù)。(例如參數(shù)大小為9字節(jié),修改為16字節(jié))
(4) 如果參數(shù)是HFA(homogeneous floating-point aggregate)、HVA(homogeneous short vector aggregate)、quad(64bit)浮點(diǎn)數(shù)或Short Vector Type,NSAA = NSAA+max(8, 參數(shù)自然對(duì)齊大小)。
(5) 如果參數(shù)是half(16bit),single(16bit)浮點(diǎn)數(shù),參數(shù)擴(kuò)展到8字節(jié)(放入最低有效位,其余bits值不確定)
(6) 如果參數(shù)是HFA(homogeneous floating-point aggregate)、HVA(homogeneous short vector aggregate)、half(16bit),single(16bit),double(32bit)或quad(64bit)浮點(diǎn)數(shù)或Short Vector Type,參數(shù)copy到內(nèi)存,NSAA=NSAA+size(參數(shù))。此參數(shù)處理完成。
(7) 如果參數(shù)是整型或指針類(lèi)型、size(參數(shù))<=8字節(jié),且NGRN小于8,則參數(shù)復(fù)制到x[NGRN]中的最低有效位。 NGRN增加1。 此參數(shù)處理完成。
(8) 如果參數(shù)對(duì)齊后16字節(jié),NGRN向上取偶數(shù)。(例如:NGRN為2,那值保持不變;假如NGRN為3,則取4。 注:iOS ABI沒(méi)有這個(gè)規(guī)則)
(9) 如果參數(shù)是整型,對(duì)齊后16字節(jié),且NGRN小于7,則把參數(shù)復(fù)制到x[NGRN] 和 x[NGRN+1],x[NGRN]是低位。NGRN = NGRN + 2。 此參數(shù)處理完成。
(10) 如果參數(shù)是復(fù)合類(lèi)型,且參數(shù)可以完全放進(jìn)x寄存器(8-NGRN>= 參數(shù)字節(jié)大小/8)。從x[NGRN]依次放入?yún)?shù)(低位開(kāi)始)。未填充的bits的值不確定。NGRN = NGRN + 此參數(shù)用掉的寄存器個(gè)數(shù)。此參數(shù)處理完成。
(11) NGRN設(shè)為8。
(12) NSAA = NSAA+max(8, 參數(shù)自然對(duì)齊大小)。
(13) 如果參數(shù)是復(fù)合類(lèi)型,參數(shù)copy到內(nèi)存,NSAA=NSAA+size(參數(shù))。此參數(shù)處理完成。
(14) 如果參數(shù)小于8字節(jié),參數(shù)設(shè)置為8字節(jié)大小,高位bits值不確定。
(15) 參數(shù)copy到內(nèi)存,NSAA=NSAA+size(參數(shù))。此參數(shù)處理完成。
從上面規(guī)則,可以得到經(jīng)驗(yàn):
處理完參數(shù)列表中所有的參數(shù)后,調(diào)用者一定知道傳遞參數(shù)用了多少棧空間。(NSAA - SP)
浮點(diǎn)數(shù)和short vector types通過(guò)v寄存器和棧傳遞,不會(huì)通過(guò)r寄存器傳遞。(除非是小復(fù)合類(lèi)型的成員)
寄存器和棧中,參數(shù)未填充滿的部分的值,不可確定。
函數(shù)返回結(jié)果
函數(shù)返回方式取決于返回結(jié)果的類(lèi)型。
如果返回是類(lèi)型T,如下
void func(T arg)
復(fù)制代碼
arg值通過(guò)寄存器(組)傳遞,返回的結(jié)果也是通過(guò)相同的寄存器(組)返回。
2. 調(diào)用者申請(qǐng)內(nèi)存(內(nèi)存大小足夠放入返回結(jié)果且是內(nèi)存對(duì)齊的),將內(nèi)存地址放入x8中傳遞給子函數(shù),子函數(shù)運(yùn)行時(shí)候,可以更新x8指向內(nèi)存的內(nèi)容,從而將結(jié)果返回。
結(jié)語(yǔ)
假如文章有不對(duì)地方,歡迎大家留言指出;或者給我發(fā)郵件(wu_k_k@foxmail.com)。
引用
--EOF-- 轉(zhuǎn)載請(qǐng)保留鏈接,謝謝
總結(jié)
以上是生活随笔為你收集整理的arm64 linux 除零正常返回,arm64程序调用规则的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 计算机刚过国家线能调剂到哪些学校,202
- 下一篇: 日本屎宴会百度百科(日本屎宴)