如何通过一文搞懂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。
阅读全文