第16部分- Linux ARM彙編 ARM64調用標準

第16部分- Linux ARM彙編 ARM64調用標準

本章主要是是一些描述性的內容,我們先來看下4個術語。

  • AArch32 – the legacy 32-bit instruction set architecture (ISA) defined by ARM, including Thumb mode execution.
  • AArch64 – the new 64-bit instruction set architecture (ISA) defined by ARM.
  • ARMv7 – the specification of the "7th generation" ARM hardware, which only includes support for AArch32. This version of the ARM hardware is the first version Windows for ARM supported.
  • ARMv8 – the specification of the "8th generation" ARM hardware, which includes support for both AArch32 and AArch64.

    ARM64中參數1~參數8 分別保存到 X0~X7 寄存器中 ,剩下的參數從右往左一次入棧,被調用者實現棧平衡,返回值存放在 X0 中。調用者保存的

      寄存器x8–x18是每個函數的臨時寄存器。 因此,無法在返回函數時對其值進行任何假設。 實際上,這些寄存器也是調用者保存的。

      寄存器x19–x28是寄存器,如果由函數使用,則必須保留其值,然後在返回函數時將其恢復。 此寄存器稱爲被調用者保存的。

 

非可變參數函數

AArch64體系結構的過程調用標準:

階段A–初始化

在開始處理參數之前,此階段僅執行一次。

下一個通用寄存器號(NGRN)設置爲零。

下一個SIMD和浮點寄存器號(NSRN)設置爲零。

下一個堆棧參數地址(NSAA)設置爲當前堆棧指針值(SP)。

 

B階段–預填充和參數擴展

對於列表中的每個參數,將應用以下列表中的第一個匹配規則。如果沒有規則匹配,則不修改參數。

如果參數類型是一個複合類型,其大小不能同時由調用方和被調用方靜態確定,則將參數複製到內存中,並將該參數替換爲指向副本的指針。 (在C / C ++中沒有這樣的類型,但是它們以其他語言或語言擴展存在)。

如果參數類型是HFA或HVA,則該參數將未經修改地使用。

如果參數類型是大於16個字節的Composite Type,則將參數複製到調用方分配的內存中,並將該參數替換爲指向副本的指針。

如果參數類型爲“複合類型”,則參數的大小將四捨五入爲最接近的8字節倍數。

 

C階段–將參數分配給寄存器和堆棧

對於列表中的每個參數,依次應用以下規則,直到分配了參數爲止。將自變量分配給寄存器時,寄存器中任何未使用的位都具有未指定的值。如果將參數分配給堆棧插槽,則任何未使用的填充字節均具有未指定的值。

如果自變量是半精度,單精度,雙精度或四精度浮點或短向量類型,並且NSRN小於8,則將自變量分配給寄存器v [NSRN]的最低有效位。 NSRN增加1。現在已分配了參數。

如果自變量是HFA或HVA,並且有足夠的未分配SIMD和浮點寄存器(NSRN +成員數≤8),則將自變量分配給SIMD和浮點寄存器,每個成員一個寄存器HFA或HVA。 NSRN增加所用寄存器的數量。現在已分配了參數。

如果參數是HFA或HVA,則將NSRN設置爲8,並且將參數的大小四捨五入到8個字節的最接近倍數。

如果自變量是HFA,HVA,四精度浮點或短向量類型,則將NSAA向上舍入爲8或自變量類型的自然對齊中的較大者。

如果參數是半精度或單精度浮點類型,則參數的大小設置爲8個字節。效果就好像該參數已被複制到64位寄存器的最低有效位,而其餘位則填充了未指定的值。

如果參數是HFA,HVA,半精度,單精度,雙精度或四精度浮點或短向量類型,則將參數複製到調整後的NSAA處的內存中。 NSAA增加自變量的大小。現在已分配了參數。

如果參數是整數或指針類型,則參數的大小小於或等於8個字節,並且NGRN小於8,則將參數複製到x [NGRN]中的最低有效位。 NGRN加1。現在已分配了參數。

如果參數的對齊方式爲16,則NGRN會四捨五入到下一個偶數。

如果參數是整數類型,則參數的大小等於16,並且NGRN小於7,則將參數複製到x [NGRN]和x [NGRN + 1]。 x [NGRN]應包含自變量的內存表示形式的低位尋址雙字。 NGRN增加2。現在已分配了參數。

如果參數是Composite Type,並且參數的雙字大小不超過8減去NGRN,則將參數複製到連續的通用寄存器中,從x [NGRN]開始。傳遞自變量,就好像它已從雙字對齊的地址加載到寄存器中一樣,並帶有適當順序的LDR指令,這些指令會從內存中加載連續的寄存器。該標準未規定寄存器中任何未使用部分的內容。 NGRN增加所用寄存器的數量。現在已分配了參數。

NGRN設置爲8。

NSAA向上舍入爲8或參數類型的自然對齊中的較大者。

如果參數是複合類型,則將參數複製到調整後的NSAA的內存中。 NSAA增加自變量的大小。現在已分配了參數。

如果參數的大小小於8個字節,則參數的大小將設置爲8個字節。效果就好像該參數已複製到64位寄存器的最低有效位,而其餘位都填充有未指定的值。

該參數將複製到調整後的NSAA的內存中。 NSAA增加自變量的大小。 現在已分配了參數。

 

可變參數函數

帶有可變數量參數的函數的處理方式與上面所述不同,如下所示:

所有複合材料均一視同仁; 沒有對HFA或HVA的特殊處理。

不使用SIMD和浮點寄存器。

實際上,將參數分配給虛擬堆棧與遵循規則C.12–C.15相同,其中,堆棧的前64個字節被加載到x0-x7中,而其餘的堆棧參數則被正常放置。

 

返回值

整數值以x0返回。

浮點值將根據需要以s0,d0或v0返回。

HFA和HVA值視情況以s0-s3,d0-d3或v0-v3返回。

根據值返回的類型是否具有某些屬性,將對其進行不同的處理。具有所有這些屬性的類型,

  • 它們是根據C ++ 14標準定義聚合的,也就是說,它們沒有用戶提供的構造函數,沒有私有或受保護的非靜態數據成員,沒有基類,也沒有虛函數,並且
  • 他們有一個簡單的副本分配運算符,並且
  • 他們有一個瑣碎的破壞者,

使用以下返回樣式:

  • 小於或等於8個字節的類型以x0返回。
  • 小於或等於16個字節的類型在x0和x1中返回,其中x0包含低8位字節。
  • 對於大於16個字節的類型,調用方應保留足夠大的內存塊並對齊以保存結果。存儲塊的地址應作爲附加參數傳遞給x8中的函數。被調用方可以在執行子例程的任何時候修改結果存儲塊。被調用方不需要保留存儲在x8中的值。

所有其他類型使用此約定:

調用者應保留足夠大小和對齊的內存塊以保存結果。存儲塊的地址應作爲附加參數傳遞給函數x0,如果$this傳遞x0,則應傳遞x1。被調用方可以在執行子例程的任何時候修改結果存儲塊。被調用方以x0返回存儲塊的地址。

 

按照ARM提出的ABI,堆棧必須始終保持16字節對齊。 AArch64包含一項硬件功能,只要SP不按16字節對齊並且完成了相對於SP的加載或存儲,它就會生成堆棧對齊錯誤。

分配4k或更多堆棧值的函數必須確保依次觸摸最後一頁之前的每一頁。此操作可確保沒有代碼可以“越過” Windows用於擴展堆棧的保護頁。通常,觸摸是由__chkstk幫助程序完成的,該幫助程序具有自定義的調用約定,該約定將x15中的總堆棧分配除以16。

 

紅色區域

當前堆棧指針正下方的16字節區域保留供分析和動態修補方案使用。該區域允許插入精心生成的代碼,該代碼在[sp,#-16]中存儲兩個寄存器,並將它們臨時用於任意目的。

 

函數調用命令

b: (branch)跳轉到某地址(無返回), 不會改變 lr (x30) 寄存器的值;一般是本方法內的跳轉,如 while 循環,if else 等 ,如:

b LBB0_1      ; 直接跳轉到標籤 ‘LLB0_1’ 處開始執行

複製代碼

bl: 跳轉到某地址(有返回),先將下一指令地址(即函數返回地址)保存到寄存器 lr (x30)中,再進行跳轉 ;一般用於不同方法直接的調用 ,如:

bl 0x100cfa754    ; 先將下一指令地址(‘0x100cfa754’ 函數調用後的返回地址)保存到寄存器 ‘lr’ 中,然後再調用 ‘0x100cfa754’ 函數

複製代碼

  blr: 跳轉到 某寄存器 (的值)指向的地址(有返回),先將下一指令地址(即函數返回地址)保存到寄存器 lr (x30)中,再進行跳轉 ;如:

blr x20       ; 先將下一指令地址(‘x20’指向的函數調用後的返回地址)保存到寄存器 ‘lr’ 中,然後再調用 ‘x20’ 指向的函數

複製代碼

  br: 跳轉到某寄存器(的值)指向的地址(無返回), 不會改變 lr (x30) 寄存器的值。

  brk: 可以理解爲跳轉指令特殊的一種。

  ret: 子程序(函數調用)返回指令,返回地址已默認保存在寄存器 lr (x30) 中。或者br x30等同ret指令。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章