寄存器
所谓寄存器(register),它是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。(寄存器是CPU的组成部分,因为在CPU内,所以CPU对其读写速度是最快的,不需要IO传输)。IA-32构架提供了16个基本寄存器,这16个基本寄存器可以归纳为如下几类:
通用寄存器
段寄存器
状态和控制寄存器
指令寄存器
在这里我们主要介绍一下通用寄存器。
通用寄存器(x64)
在 64-bit 模式下,有16个通用寄存器,但是这16个寄存器是兼容32位模式的,32位方式下寄存器名分别为
eax、 ebx、 ecx、edx、 edi、 esi、 ebp、 esp、 r8d – r15d
在64位模式下,他们被扩展为
rax、 rbx、 rcx、rdx、 rdi、rsi、 rbp、 rsp、r8 – r15
通用寄存器在我们的程序运行中所做的事可以简单地总结为每个函数(方法)执行时暂时存放参数和返回值。每个参数对应的寄存器的关系为:
第一个参数:RDI
第二个参数:RSI
第三个参数:RDX
第四个参数: RCX
第五个参数:R8
第六个参数:R9
超过7个以及上的参数会被分配到进程的栈区
返回值: RAX
举个例子:
NSString *myName = @"George";
NSLog("Hello world! I'm%@, i'm %f years old, %@", myName, 22, @"Nice to meet you!");
在运行NSLog这个方法的时候,各寄存器对应的参数是:
RDI =@"Hello world! I'm%@, i'm %f years old, %@";
RSI =@"George";
RDX = 22;
RCX =@"Nice to meet you!";
当NSLog方法执行结束后,这些寄存器里的值会随着其它方法的调用而改变。
OC中的寄存器
我们都知道OC这门语言是使用消息派发机制,大部分的函数方法调用都是通过C函数msg_send实现,对于msg_send的使用,这个函数的第一个参数是消息的发送者,第二个参数是选择器(Selector),接下来就是不定数量的参数。举个例子:
NSString *test = ["My name is" stringByAppendingString:"George"];
对于上面这个表达式,编译器会转换为以下:
msg_send(@"My name is", @"stringByAppendingString", @"George");
在这里方法stringByAppendingString:的第一个参数(只有一个)其实对应的是通用寄存器的第三个--RDX。
因为OC语言特性的原因,通常方法中的参数所对应的寄存器都是从第三个开始递增存储。相比之下,swift并不是使用消息派发机制,因此,第一个参数所对应的寄存器就是RDI。