iOS ABI

前言

上篇文章介紹arm64程序調用規則,這篇介紹iOS平臺上的特定規則。html

iOS ABI

在iOS平臺上,基本是遵循上篇文章上的規則。可是也有幾個不一樣規則。ios

iOS platform designers

  1. x18寄存器爲平臺保留,程序不可用。
  2. wchar_t類型是32bit, long類型是64bit。
  3. x29(FP:保存函數棧的基地址)必須老是有意義的。
  4. 空結構體,在函數調用的參數中被忽略。
    empty-Struct

iOS與官方arm64不一樣點

參數傳遞

  1. 在arm64標準中,當參數是經過棧傳遞時(好比參數超過8個),每一個參數消耗8個字節的倍數。可是iOS中刪除了這個要求。 例如:
void two_stack_args(char w0, char w1, char w2, char w3, char w4, char w5, char w6, char w7, char s0, char s1) {}

複製代碼

s0在sp處佔用1個字節,s1在sp + 1處佔用1個字節。而後填充知足內存對齊(sp必須是16的倍數)。 2. 在arm64標準中,當傳遞16字節對齊的參數時,從偶數寄存器xN開始。可是iOS中,沒有這個要求。例如:bash

void large_type(int x0, __int128 x1_x2) {} 
複製代碼

在iOS平臺,參數x1_x2在x1和x2中傳遞;arm64標準裏,參數應該在x2和x3中傳遞。 3. 在arm64標準中,被調用者負責對少於32bits的參數進行0擴展或者標記;在iOS中,調用者負責擴展至32bits。app

可變參數

iOS ABI和arm64標準徹底不一樣。函數

  1. 可變參數中的匿名參數都是經過棧傳遞的。(每一個可變參數分配8字節倍數棧空間,同時注意sp%16=0),固定參數傳遞方式跟arm64標準一致。 因爲參數傳遞方式不一樣,可變參數函數,是不能直接用函數指針賦值,而後當作固定參數函數調用。 例如:
typedef int __cdecl (*PInvokeFunc) (const char*, int);

int test()
{
    PInvokeFunc fp = (PInvokeFunc)printf;
    fp("Hello World: %d", 10); //不必定打印出Hello World: 10
    return 0;
}
複製代碼

解決辦法是:經過IL2CPP生成包裝函數。post

  1. C語言在函數調用以前,小於int類型的參數,進行提高。注意,棧空間上未填充的bit的值不肯定(arm64標準裏,寄存器和棧上未填充的bit值,也是不肯定的)。
  2. va_list(可變參數函數裏,獲取可變參數列表的類型)就是char* 。

基本C語言類型

  1. long double是double(32bit)精度,而不是quad(64bit)精度。
  2. char 和 wchar_t 有符號的。

數據類型和內存對齊

Data type Size (in bytes) Natural alignment (in bytes)
BOOL, bool 1 1
char 1 1
short 2 2
int 4 4
long 8 8
long long 8 8
pointer 8 8
size_t 8 8
NSInteger 8 8
CFIndex 8 8
fpos_t 8 8
off_t 8 8

引用

  1. infocenter.arm.com/help/topic/…
  2. blog.csdn.net/adaptiver/a…
  3. developer.apple.com/library/arc…
  4. stackoverflow.com/questions/3…

--EOF-- 轉載請保留連接,謝謝ui

相關文章
相關標籤/搜索