如何通过一文搞懂ARM 64系列函数调用传参与返回值?
摘要:函数调用涉及到传参与返回值,下面就来看下ARM 64中,参数与返回值的传递机制。 1 整数型参数传递 这里的整数型并不单指int类型,或者NSInteger类型,而是指任何能够使用整数表示的数据类型,包括char、BOOL、指针等。 对于整
函数调用涉及到传参与返回值,下面就来看下ARM 64中,参数与返回值的传递机制。
1 整数型参数传递
这里的整数型并不单指int类型,或者NSInteger类型,而是指任何能够使用整数表示的数据类型,包括char、BOOL、指针等。
对于整数型参数,需要分成参数个数<=8个和>8个两种情形来看。
如果参数个数 <=8个,那么参数全部使用Xn寄存器传递。
比如,一个函数的参数只有4个,那么就是用X0 X1 X2 X3寄存器传递。如果这个函数的参数为8个,那么就使用X0 X1 X2 X3 X4 X5 X6 X7寄存器传递。
换句话说,寄存器X0~X7就是用来在参数个数<=8个时,传递参数的。
// 1. 接受 4 个整型参数的函数
NSInteger add4(NSInteger zero, NSInteger one, NSInteger two, NSInteger three) {
return zero + one + two + three;
}
@implementation ViewController
- (void)viewDidLoad {
// 2. 调用函数 add4
NSInteger result = add4(0, 1, 2, 3);
NSLog(@"%ld", result);
}
@end
上面代码注释1定义了一个接受4个参数的函数add4.
代码注释2在viewDidLoad函数中调用了函数add4。
下面来看viewDidLoad函数的汇编代码:
// ARMAssemble`-[ViewController viewDidLoad]:
...
0x102e142b0 <+28>: mov x1, #0x1
...
0x102e142bc <+40>: mov x0, #0x0
0x102e142c0 <+44>: mov x2, #0x2
0x102e142c4 <+48>: mov x3, #0x3
0x102e142c8 <+52>: bl 0x102e14000 ; add4 at ViewController.m:10
...
上面代码前面4行将参数写入了对应的寄存器,最后一行调用了函数add4。
函数add4的汇编代码如下:
ARMAssemble`add4:
-> 0x102e14000 <+0>: sub sp, sp, #0x20
0x102e14004 <+4>: str x0, [sp, #0x18]
0x102e14008 <+8>: str x1, [sp, #0x10]
0x102e1400c <+12>: str x2, [sp, #0x8]
0x102e14010 <+16>: str x3, [sp]
...
上面代码第1行分配栈空间,后面4行代码就将参数值存储到了对应的栈空间。
如果参数个数 >8个,那么寄存器X0~X7负责传递前8个参数,剩下的参数使用栈来传递。
// 1. 定义接受 10 个参数的函数 add10
NSInteger add10(NSInteger zero, NSInteger one, NSInteger two, NSInteger three, NSInteger four, NSInteger five, NSInteger six, NSInteger seven, NSInteger eight, NSInteger nine) {
return zero + one + two + three + four + five + six + seven + eight + nine;
}
@implementation ViewController
- (void)viewDidLoad {
// 2. 调用 add10
NSInteger result = add10(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
NSLog(@"%ld", result);
}
@end
上面代码注释1定义了一个接受10个参数的函数add10。
代码注释2在viewDidLoad函数中调用了函数add10。
