1. 函數參數超過8個
1.1 源代碼
//參數個數大于8的函數調用
int test(int a, int b, int c, int d,int e,int f,int g, int h, int i) {
return a + b + c + d + e + f + g + h + i;
}
//在viewDidLoad函數中調用這個測試函數,在調用函數的地方打上斷點,連接真機,運行程序,查看匯編代碼。
- (void)viewDidLoad {
[super viewDidLoad];
test(1, 2, 3, 4, 5, 6, 7, 8, 9);
}
1.2 viewDidLoad函數匯編及圖示
- 匯編代碼分析
-[ViewController viewDidLoad]:
;拉伸64字節大小棧空間,棧頂地址保存到sp中
0x100819df8 <+0>: sub sp, sp, #0x40 ; =0x40
;保存寄存器x29,x30的值到棧底的16個字節當中
0x100819dfc <+4>: stp x29, x30, [sp, #0x30]
;設置當前函數調用棧的棧底地址(sp寄存器中保存的地址加上#0x30值保存到寄存器x29中)
0x100819e00 <+8>: add x29, sp, #0x30 ; =0x30
;存儲x0寄存器的值到棧底的第1個8字節存儲空間中
0x100819e04 <+12>: stur x0, [x29, #-0x8]
;存儲x1寄存器的值到棧底的第2個8字節存儲空間中
0x100819e08 <+16>: stur x1, [x29, #-0x10]
;取出靠近棧底的第1個8字節存儲空間的內容到x8寄存器中
0x100819e0c <+20>: ldur x8, [x29, #-0x8]
;x9寄存器保存第6個8字節存儲區域的地址
0x100819e10 <+24>: add x9, sp, #0x10 ; =0x10
;將x8寄存器中的值存儲到第6個8字節的存儲區域中
0x100819e14 <+28>: str x8, [sp, #0x10]
;執行完后x8寄存器的值為0x100822000
0x100819e18 <+32>: adrp x8, 8
;執行完后x8寄存器的值為0x1008222c0
0x100819e1c <+36>: add x8, x8, #0x2c0 ; =0x2c0
;加載0x1008222c0處的值(可能為全局變量、全局常量或字符串的值)到x8寄存器中
0x100819e20 <+40>: ldr x8, [x8]
;存儲 x8寄存器中的值到第5個8字節的存儲區域中
0x100819e24 <+44>: str x8, [x9, #0x8]
;執行后x8寄存器中的值為 0x100822000
0x100819e28 <+48>: adrp x8, 8
;執行后x8寄存器中的值為 0x100822298
0x100819e2c <+52>: add x8, x8, #0x298 ; =0x298
;加載寄存器的值到x1寄存器中
0x100819e30 <+56>: ldr x1, [x8]
;將x9寄存器中的值存儲到x0寄存器中
0x100819e34 <+60>: mov x0, x9
;函數跳轉指令
0x100819e38 <+64>: bl 0x10081a4a4 ; symbol stub for: objc_msgSendSuper2
;將參數1的值存儲到w0寄存器
0x100819e3c <+68>: mov w0, #0x1
;將參數2的值存儲到w1寄存器
0x100819e40 <+72>: mov w1, #0x2
;將參數3的值存儲到w2寄存器
0x100819e44 <+76>: mov w2, #0x3
;將參數4的值存儲到w3寄存器
0x100819e48 <+80>: mov w3, #0x4
;將參數5的值存儲到w4寄存器
0x100819e4c <+84>: mov w4, #0x5
;將參數6的值存儲到w5寄存器
0x100819e50 <+88>: mov w5, #0x6
;將參數7的值存儲到w6寄存器
0x100819e54 <+92>: mov w6, #0x7
;將參數8的值存儲到w7寄存器
0x100819e58 <+96>: mov w7, #0x8
;將sp中的棧頂地址存儲到x8寄存器
0x100819e5c <+100>: mov x8, sp
;將參數9的值存儲到x10寄存器
0x100819e60 <+104>: mov w10, #0x9
;將w10存儲的值(也就是參數9的值)存儲到第8個八字節的存儲區域
0x100819e64 <+108>: str w10, [x8]
;跳轉到test函數執行test函數的指令,并將0x100819e6c存儲到lr寄存器中
0x100819e68 <+112>: bl 0x100819d80 ; test at ViewController.m:27
;現場恢復
0x100819e6c <+116>: ldp x29, x30, [sp, #0x30]
;回收64字節的棧空間
0x100819e70 <+120>: add sp, sp, #0x40 ; =0x40
;繼續執行lr寄存器中存儲的指令地址的指令
0x100819e74 <+124>: ret
-
跳轉text函數之前viewDidLoad函數以及各寄存器存儲值情況:
1.3 test函數匯編代碼及圖示
- 匯編代碼分析
_test:
;拉伸48字節大小棧空間,棧頂地址保存到sp中
0x102e41d80 <+0>: sub sp, sp, #0x30 ; =0x30
;將viewDidLoad函數調用棧中的參數9的值加載到w8寄存器中
0x102e41d84 <+4>: ldr w8, [sp, #0x30]
;將w0中保存的參數1的值存儲到第1個四字節存儲空間
0x102e41d88 <+8>: str w0, [sp, #0x2c]
;將w1中保存的參數2的值存儲到第2個四字節存儲空間
0x102e41d8c <+12>: str w1, [sp, #0x28]
;將w2中保存的參數3的值存儲到第3個四字節的存儲空間
0x102e41d90 <+16>: str w2, [sp, #0x24]
;將w3中保存的參數4的值存儲到第4個四字節的存儲空間
0x102e41d94 <+20>: str w3, [sp, #0x20]
;將w4中保存的參數5的值存儲到第5個四字節的存儲空間
0x102e41d98 <+24>: str w4, [sp, #0x1c]
;將w5中保存的參數6的值存儲到第6個四字節的存儲空間
0x102e41d9c <+28>: str w5, [sp, #0x18]
;將w6中保存的參數7的值存儲到第7個四字節的存儲空間
0x102e41da0 <+32>: str w6, [sp, #0x14]
;將w7中保存的參數8的值存儲到第8個四字節的存儲空間
0x102e41da4 <+36>: str w7, [sp, #0x10]
;將寄存器w8也就是參數9的值存儲到第9個四字節的存儲空間中
0x102e41da8 <+40>: str w8, [sp, #0xc]
;將參數1的值加載到w8寄存器中
0x102e41dac <+44>: ldr w8, [sp, #0x2c]
;將參數2的值加載到w9寄存器中
0x102e41db0 <+48>: ldr w9, [sp, #0x28]
;將w8寄存器中的值與w9寄存器中的值相加存儲到w8寄存器中
0x102e41db4 <+52>: add w8, w8, w9
;將參數3的值加載到w9寄存器中
0x102e41db8 <+56>: ldr w9, [sp, #0x24]
;將w8寄存器中的值與w9寄存器中的值相加存儲到w8寄存器中
0x102e41dbc <+60>: add w8, w8, w9
;將參數4的值加載到w9寄存器中
0x102e41dc0 <+64>: ldr w9, [sp, #0x20]
;將w8寄存器中的值與w9寄存器中的值相加存儲到w8寄存器中
0x102e41dc4 <+68>: add w8, w8, w9
;將參數5的值加載到w9寄存器中
0x102e41dc8 <+72>: ldr w9, [sp, #0x1c]
;將w8寄存器中的值與w9寄存器中的值相加存儲到w8寄存器中
0x102e41dcc <+76>: add w8, w8, w9
;將參數6的值加載到w9寄存器中
0x102e41dd0 <+80>: ldr w9, [sp, #0x18]
;將w8寄存器中的值與w9寄存器中的值相加存儲到w8寄存器中
0x102e41dd4 <+84>: add w8, w8, w9
;將參數7的值加載到w9寄存器中
0x102e41dd8 <+88>: ldr w9, [sp, #0x14]
;將w8寄存器中的值與w9寄存器中的值相加存儲到w8寄存器中
0x102e41ddc <+92>: add w8, w8, w9
;將參數8的值加載到w9寄存器中
0x102e41de0 <+96>: ldr w9, [sp, #0x10]
;將w8寄存器中的值與w9寄存器中的值相加存儲到w8寄存器中
0x102e41de4 <+100>: add w8, w8, w9
;將參數9的值加載到w9寄存器中
0x102e41de8 <+104>: ldr w9, [sp, #0xc]
;將w8寄存器中的值與w9寄存器中的值相加存儲到w0寄存器中
0x102e41dec <+108>: add w0, w8, w9
;回收48字節大小的函數調用棧空間
0x102e41df0 <+112>: add sp, sp, #0x30 ; =0x30
0x102e41df4 <+116>: ret
-
text函數return之前棧空間以及寄存器存儲值情況
2. 函數中的局部變量以及函數中調用其他函數
2.1 源代碼
//測試函數B
int testB(int a, int b) {
return a + b;
}
//測試函數A
int testA(int a, int b) {
int c = 10 + testB(a, b);
int d = 12;
return c + d;
}
- (void)viewDidLoad {
[super viewDidLoad];
//調用測試函數A
testA(1, 2);
}
2.2 viewDidLoad函數部分匯編
- 部分匯編代碼分析
;將testA函數參數1的值存儲到w0寄存器
0x104cb1e60 <+68>: mov w0, #0x1
;將testA函數參數2的值存儲到w1寄存器
0x104cb1e64 <+72>: mov w1, #0x2
;跳轉到testA函數繼續執行testA函數的指令,并將0x104cb1e6c的值存儲到lr寄存器,以便做現場保護
0x104cb1e68 <+76>: bl 0x104cb1dd4 ; testA at ViewController.m:31
0x104cb1e6c <+80>: ldp x29, x30, [sp, #0x20]
0x104cb1e70 <+84>: add sp, sp, #0x30 ; =0x30
0x104cb1e74 <+88>: ret
2.3 testA函數匯編代碼
- 匯編代碼解析
_testA:
;拉伸32字節大小的棧空間
0x104cb1dd4 <+0>: sub sp, sp, #0x20 ; =0x20
;將x29(fp)寄存器存儲的值以及x30(lr)寄存器的值存儲到前兩個8字節空間中
0x104cb1dd8 <+4>: stp x29, x30, [sp, #0x10]
;x29寄存器保存當前棧的棧底地址
0x104cb1ddc <+8>: add x29, sp, #0x10 ; =0x10
;將w0寄存器中的參數1的值存儲到棧底后第1個4字節的存儲空間中
0x104cb1de0 <+12>: stur w0, [x29, #-0x4]
;將w1寄存器中的參數2的值存儲到棧底后第2個4字節的存儲空間中
0x104cb1de4 <+16>: str w1, [sp, #0x8]
;取出參數1的值載入到w0寄存器中
0x104cb1de8 <+20>: ldur w0, [x29, #-0x4]
;取出參數2的值載入到w1寄存器中
0x104cb1dec <+24>: ldr w1, [sp, #0x8]
;跳轉到testB函數執行testB函數中的指令并將0x104cb1df4保存到lr寄存器中(現場保護,調用完testB函數可以回來繼續執行testA中的代碼)
0x104cb1df0 <+28>: bl 0x104cb1db4 ; testB at ViewController.m:27
;將testB函數執行后的返回值加上10,結果存儲到w8寄存器
0x104cb1df4 <+32>: add w8, w0, #0xa ; =0xa
;將w8寄存器的值(也就是局部變量c的值)存儲到棧空間中倒數第2個4字節空間中,將局部變量c的值保護起來,以防后面使用w8寄存器的時候,將局部變量c的值覆蓋掉
0x104cb1df8 <+36>: str w8, [sp, #0x4]
;將局部變量d的值(12)存儲到w8寄存器中
0x104cb1dfc <+40>: mov w8, #0xc
;將w8寄存器的值(也就是局部變量d的值)存儲到倒數第1個4字節的存儲空間中
0x104cb1e00 <+44>: str w8, [sp]
;將局部變量c的值加載到w8寄存器中
0x104cb1e04 <+48>: ldr w8, [sp, #0x4]
;將局部變量d的值加載到w9寄存器中
0x104cb1e08 <+52>: ldr w9, [sp]
;將w8寄存器中的值(局部變量c的值)與w9寄存器中的值(局部變量d的值)相加,結果存儲到寄存器w0中
0x104cb1e0c <+56>: add w0, w8, w9
;現場還原,獲取上viewDidLoad函數的棧底地址存儲到x29寄存器,獲取viewDidLoad函數調用testA后的下一條指令地址存儲到x30寄存器
0x104cb1e10 <+60>: ldp x29, x30, [sp, #0x10]
;回收32字節大小的函數調用棧空間
0x104cb1e14 <+64>: add sp, sp, #0x20 ; =0x20
;函數執行完畢,繼續執行lr所保存的指令地址的指令
0x104cb1e18 <+68>: ret
2.4 testB函數匯編代碼
_testB:
;拉伸16字節的棧空間,sp寄存器保存棧頂地址
0x104cb1db4 <+0>: sub sp, sp, #0x10 ; =0x10
;將w0(_testB函數參數1)中的值存儲到第1個四字節空間中
0x104cb1db8 <+4>: str w0, [sp, #0xc]
;將w2(_testB函數參數2)中的值存儲到第2個四字節空間中
0x104cb1dbc <+8>: str w1, [sp, #0x8]
;將參數1中的值加載到w8寄存器中
0x104cb1dc0 <+12>: ldr w8, [sp, #0xc]
;將參數2中的值加載到w9寄存器中
0x104cb1dc4 <+16>: ldr w9, [sp, #0x8]
;將參數1和參數2的值相加,結果保存到w0寄存器中
0x104cb1dc8 <+20>: add w0, w8, w9
;回收開辟的16字節棧空間
0x104cb1dcc <+24>: add sp, sp, #0x10 ; =0x10
;函數調用結束,執行lr寄存器保存的指令地址的指令
0x104cb1dd0 <+28>: ret
3. 函數返回值等于16字節時
3.1 源代碼
//定義一個結構體
typedef struct TestStruct {
int a;
int b;
int c;
int d;
} TestStruct;
//testB函數定義一個結構體并返回
TestStruct testB(int a, int b) {
TestStruct testStr = { a, b, 7, 4 };
return testStr;
}
//testA函數調用testB函數
int testA(int a, int b) {
TestStruct testStruct = testB(a, b);
int c = 10;
int d = 12;
return c + d + testStruct.d;
}
//viewDidLoad函數調用testA函數,上面的viewDidLoad匯編已經分析過了,就不分析了。
- (void)viewDidLoad {
[super viewDidLoad];
testA(1, 2);
}
3.2 testA函數匯編代碼分析及圖示
testA:
;拉伸48字節的棧空間,sp寄存器保存棧頂地址
0x102549dc4 <+0>: sub sp, sp, #0x30 ; =0x30
;存儲x29(fp)、x30(lr)寄存器的值在靠近棧底的2個8字節空間中
0x102549dc8 <+4>: stp x29, x30, [sp, #0x20]
;將當前棧底的地址保存到x29寄存器中
0x102549dcc <+8>: add x29, sp, #0x20 ; =0x20
;將testA函數參數1的值存儲到靠近棧底的第1個4字節空間中
0x102549dd0 <+12>: stur w0, [x29, #-0x4]
;將testA函數參數2的值存儲到靠近棧底的第2個4字節空間中
0x102549dd4 <+16>: stur w1, [x29, #-0x8]
;加載參數1的值到w0寄存器中
0x102549dd8 <+20>: ldur w0, [x29, #-0x4]
;加載參數2的值到w1寄存器中
0x102549ddc <+24>: ldur w1, [x29, #-0x8]
;跳轉到testB中執行匯編指令
0x102549de0 <+28>: bl 0x102549d88 ; testB at ViewController.m:34
;將testB函數調用的返回值(16字節)存儲到棧空間中
0x102549de4 <+32>: str x0, [sp, #0x8]
0x102549de8 <+36>: str x1, [sp, #0x10]
;將10字面量的值(也就是局部變量c)存儲到w8寄存器
0x102549dec <+40>: mov w8, #0xa
;將w8寄存器中的值存儲到第6個8字節空間的第1個4字節空間中
0x102549df0 <+44>: str w8, [sp, #0x4]
;將12字面量的值(也就是局部變量d)存儲到w8寄存器
0x102549df4 <+48>: mov w8, #0xc
;將w8寄存器中的值存儲到第6個8字節空間的第2個4字節空間中
0x102549df8 <+52>: str w8, [sp]
;獲取局部變量c的值加載到w8寄存器
0x102549dfc <+56>: ldr w8, [sp, #0x4]
;獲取局部變量d的值加載到w9寄存器
0x102549e00 <+60>: ldr w9, [sp]
;將局部變量c的值與局部變量d的值相加,結果存儲到w8寄存器
0x102549e04 <+64>: add w8, w8, w9
;將結構體變量的成員變量d的值加載到w9寄存器
0x102549e08 <+68>: ldr w9, [sp, #0x14]
;將局部變量c的值與局部變量d的值相加獲取的值與結構體變量的成員變量d的值相加,結果存儲到w0寄存器
0x102549e0c <+72>: add w0, w8, w9
;函數調用結束,恢復現場(獲取上個函數的棧底地址保存到x29寄存器,以及下個指令執行的地址保存到lr寄存器)
0x102549e10 <+76>: ldp x29, x30, [sp, #0x20]
;回收48個字節的棧空間,sp寄存器保存viewDidLoad的函數調用棧的棧頂地址
0x102549e14 <+80>: add sp, sp, #0x30 ; =0x30
;執行lr寄存器所保存的指令地址的指令
0x102549e18 <+84>: ret
testA函數返回之前其棧空間圖示
3.3 testB函數匯編分析及圖示
testB:
;拉伸32字節的棧空間,sp寄存器保存棧頂地址
0x102549d88 <+0>: sub sp, sp, #0x20 ; =0x20
;將testB函數的參數1的值存儲到第3個八字節的靠近棧底的4字節空間中
0x102549d8c <+4>: str w0, [sp, #0xc]
;將testB函數的參數2的值存儲到第3個八字節的第2個4字節空間中
0x102549d90 <+8>: str w1, [sp, #0x8]
;加載參數1的值到w8寄存器中
0x102549d94 <+12>: ldr w8, [sp, #0xc]
;存儲參數1的值到第2個八字節的第2個4字節空間中
0x102549d98 <+16>: str w8, [sp, #0x10]
;加載參數2的值到w8寄存器中
0x102549d9c <+20>: ldr w8, [sp, #0x8]
;存儲參數1的值到第2個八字節的第1個4字節空間中
0x102549da0 <+24>: str w8, [sp, #0x14]
;將7的值加載到w8寄存器中
0x102549da4 <+28>: mov w8, #0x7
;存儲w8寄存器中的值到第2個八字節的第2個4字節空間中
0x102549da8 <+32>: str w8, [sp, #0x18]
;將4的值加載到w8寄存器中
0x102549dac <+36>: mov w8, #0x4
;存儲w8寄存器中的值到第2個八字節的第1個4字節空間中
0x102549db0 <+40>: str w8, [sp, #0x1c]
;將結構體中的a,b的值存儲到x0寄存器中
0x102549db4 <+44>: ldr x0, [sp, #0x10]
;將結構體中的c,d的值存儲到x1寄存器中
0x102549db8 <+48>: ldr x1, [sp, #0x18]
;回收棧空間
0x102549dbc <+52>: add sp, sp, #0x20 ; =0x20
;執行lr寄存器中存儲的指令地址的指令
0x102549dc0 <+56>: ret
testB函數返回之前其棧空間圖示
4. 函數返回值大于16字節時
4.1 源代碼
typedef struct TestStruct {
int a;
int b;
int c;
int d;
int e;
} TestStruct;
TestStruct testB(int a, int b) {
TestStruct testStr = { a, b, 7, 4, 20 };
return testStr;
}
int testA(int a, int b) {
TestStruct testStruct = testB(a, b);
int c = 10;
int d = 12;
return c + d + testStruct.e;
}
- (void)viewDidLoad {
[super viewDidLoad];
testA(1, 2);
}
4.2 testA函數匯編分析
testA:
;拉伸64字節的棧空間,sp寄存器保存棧頂地址
0x102ad5dc8 <+0>: sub sp, sp, #0x40 ; =0x40
;存儲x29(fp)、x30(lr)寄存器的值在靠近棧底的2個8字節空間中
0x102ad5dcc <+4>: stp x29, x30, [sp, #0x30]
;將當前棧底的地址保存到x29寄存器中
0x102ad5dd0 <+8>: add x29, sp, #0x30 ; =0x30
;將testA函數的參數1的值存儲到第1個八字節的第1個4字節空間中
0x102ad5dd4 <+12>: stur w0, [x29, #-0x4]
;將testA函數的參數1的值存儲到第1個八字節的第2個4字節空間中
0x102ad5dd8 <+16>: stur w1, [x29, #-0x8]
;將testA函數的參數1的的值加載到w0寄存器中
0x102ad5ddc <+20>: ldur w0, [x29, #-0x4]
;將testA函數的參數2的的值加載到w1寄存器中
0x102ad5de0 <+24>: ldur w1, [x29, #-0x8]
;x8寄存器保存第6個8字節空間的第1個四字節空間地址
0x102ad5de4 <+28>: add x8, sp, #0x14 ; =0x14
;跳轉到testB函數中執行匯編指令
0x102ad5de8 <+32>: bl 0x102ad5d8c ; testB at ViewController.m:35
;將局部變量c(值為10)存儲到w9寄存器
0x102ad5dec <+36>: mov w9, #0xa
;將局部變量c的值存儲到第6個8字節的第2個4字節空間中
0x102ad5df0 <+40>: str w9, [sp, #0x10]
;將局部變量d(值為12)存儲到w9寄存器
0x102ad5df4 <+44>: mov w9, #0xc
;將局部變量d的值存儲到第7個8字節的第1個4字節空間中
0x102ad5df8 <+48>: str w9, [sp, #0xc]
;加載局部變量c的值到w9寄存器中
0x102ad5dfc <+52>: ldr w9, [sp, #0x10]
;加載局部變量d的值到w10寄存器中
0x102ad5e00 <+56>: ldr w10, [sp, #0xc]
;局部變量c的值加上局部變量d的值,結果存儲到w9寄存器中
0x102ad5e04 <+60>: add w9, w9, w10
;加載結構體變量testStruct的結構體的成員變量e的值(20)到寄存器w10中
0x102ad5e08 <+64>: ldr w10, [sp, #0x24]
;局部變量c的值加上局部變量d的值再加上結構體變量testStruct的結構體的成員變量e的值,結果存儲到w0寄存器中,作為函數返回值
0x102ad5e0c <+68>: add w0, w9, w10
;現場還原
0x102ad5e10 <+72>: ldp x29, x30, [sp, #0x30]
;回收棧空間
0x102ad5e14 <+76>: add sp, sp, #0x40 ; =0x40
;執行lr寄存器保存的指令地址的指令
0x102ad5e18 <+80>: ret
返回值大于16字節
4.3 testB函數匯編分析
testB:
;拉伸16字節的棧空間,sp寄存器保存棧頂地址
0x102ad5d8c <+0>: sub sp, sp, #0x10 ; =0x10
;將testB函數的參數1的值存儲到第1個8字節空間中第1個4字節空間中
0x102ad5d90 <+4>: str w0, [sp, #0xc]
;將testB函數的參數2的值存儲到第1個8字節空間中第2個4字節空間中
0x102ad5d94 <+8>: str w1, [sp, #0x8]
;將testB函數的參數1的值加載到w9寄存器中
0x102ad5d98 <+12>: ldr w9, [sp, #0xc]
;將w9中的值存儲到x8寄存器存儲地址第1個4字節空間中
0x102ad5d9c <+16>: str w9, [x8]
;將testB函數的參數2的值加載到w9寄存器中
0x102ad5da0 <+20>: ldr w9, [sp, #0x8]
;將w9中的值存儲到x8寄存器存儲地址第2個4字節空間中
0x102ad5da4 <+24>: str w9, [x8, #0x4]
;將7的值存儲到w9寄存器中
0x102ad5da8 <+28>: mov w9, #0x7
;將w9中的值存儲到x8寄存器存儲地址第3個4字節空間中
0x102ad5dac <+32>: str w9, [x8, #0x8]
;將4的值存儲到w9寄存器中
0x102ad5db0 <+36>: mov w9, #0x4
;將w9中的值存儲到x8寄存器存儲地址第4個4字節空間中
0x102ad5db4 <+40>: str w9, [x8, #0xc]
;將20的值存儲到w9寄存器中
0x102ad5db8 <+44>: mov w9, #0x14
;將w9中的值存儲到x8寄存器存儲地址第4個4字節空間中
0x102ad5dbc <+48>: str w9, [x8, #0x10]
;回收16字節空間棧
0x102ad5dc0 <+52>: add sp, sp, #0x10 ; =0x10
;執行lr寄存器所保存的指令地址的地址
0x102ad5dc4 <+56>: ret
5.總結
由以上的匯編以及圖示,我們可以得到以下結論:
- 在viewDidLoad函數調用test函數時,如果testA函數中的參數不超過8個,就會在viewDidLoad函數的匯編代碼中將test的參數按位置對應一一存儲到w0到w8寄存器中。
- 在viewDidLoad函數調用testB函數時,如果test函數中的參數超過了8個,就會在viewDidLoad函數的匯編代碼中將test的參數按位置對應一一存儲到w0到w8寄存器中,然后剩余的參數會保存到viewDidLoad的棧空間中,然后在test函數體中的代碼執行之前會將w0到w8寄存器中的參數值從棧底的位置地址向下依次進行存儲,然后再通過寄存器獲取viewDidLoad中保存的參數9的值存儲到test函數的調用棧中
- 當在一個函數中調用了其他函數時,一定要在這個函數中保存寄存器x29、x30寄存器的值,做好現場保護,然后在ret指令結束前再恢復之前存儲的x29、x30寄存器的值,做好現場恢復。
- 函數中的返回值是存儲到其棧空間中的。
- 當testA函數在調用testB函數時,如果testB函數值大小為8個字節或以下,就會在testB函數ret指令執行前將函數返回值保存到x0寄存器中,然后繼續執行testA函數代碼時,將x0中的返回值存儲到testA函數的棧空間中。
- 當testA函數在調用testB函數時,如果testB函數值大小為8個字節以上16個字節及以下,就會在testB函數ret指令執行前將函數返回值保存到x0, x1寄存器中,然后繼續執行testA函數代碼時,將x0、x1中的返回值存儲到testA函數的棧空間中。
- 當testA函數在調用testB函數時,如果testB函數值大小為16個字節或以上,就會在testA函數調用棧中開辟一塊區域,使其大小能存儲testB函數的返回值,并使用一個寄存器存儲這塊區域的最低地址位,然后在testB函數ret指令調用之前,依次將返回值的數據存儲到這塊區域中(由低地址向高地址存儲)。