x86-64寄存器
一个x86-64的中央处理单元(CPU)包含一组16个储64位值的通用目的寄存器。 这些寄存器用来存储整数数据和指针图3-2显示了这16个寄存器。它们的名字都以 %r 开头,不过后面还跟着一些不同的命名规则的名字,这是由于指令集历史演化造成的。最 初的8086中有8个16位的寄存器,即图3-2中%ax到%bp。每个寄存器都有特殊的用 途,它们的名字就反映了这些不同的用途。扩展到IA32架构时;这些寄存器也扩展成32 位寄存器,标号从%eax到%ebp。扩展到x86-64后,原来的8个寄存器扩展成64位,标 号从%rax到%rbp。除此之外,还增加了8个新的寄存器,它们的标号是按照新的命名规 则制定的:从%r8到%r15。
63 | 31 | 15 | 7 | 0 |
---|---|---|---|---|
%rax | %eax | %ax | %al | 返回值 |
%rbx | %ebx | %bx | %bl | 被调用者保存 |
%rcx | %ecx | %cx | %cl | 第四个参数 |
%rdx | %edx | %dx | %dl | 第三个参数 |
%rsi | %esi | %si | %sil | 第二个参数 |
%rdi | %edi | %di | %dil | 第一个参数 |
%rbp | %ebp | %bp | %bpl | 被调用者保存 |
%rsp | %esp | %sp | %spl | 栈指针 |
%r8 | %r8d | %r8w | %r8b | 第五个参数 |
%r9 | %r9d | %r9w | %r9b | 第六个参数 |
%r10 | %r10d | %r10w | %r10b | 调用者保存 |
%r11 | %r11d | %r11w | %r11b | 调用者保存 |
%r12 | %r12d | %r12w | %r12b | 被调用者保存 |
%r13 | %r13d | %r13w | %r13b | 被调用者保存 |
%r14 | %r14d | %r14w | %r14b | 被调用者保存 |
%r15 | %r15d | %r15w | %r15b | 被调用者保存 |
图3-2 整数寄存器。所有的16个寄存器的低位部分都可以作为字节,字(16位),双字(32位),四字(64位)数字来访问。
如图中嵌套的方框标明的,指令可以对这16个寄存器的低位字节中存放的不同 大小的数据进行操作。(字节级操作可以访问最低的字节,16位操作可以访问最低的2个字 节32位操作可以访问最低的4个字节,而64位操作可以访问整个寄存器。 在后面的内容中,我们会展现很多指令,复制和生成1字节、2字节、4字节和8字 节值。当这些指令以寄存器作为目标时,对于生成小8字节结果的指令,寄存器中剩下 的字节会怎么样,对此有两条规则:(生成1字节和2字节数字的指令会保持剩下的字节不 变生成4字节数字的指令会把高位4个字节置为0.)后面这条规则是作为从IA32到
x86-64的扩展的一部分而采用的。 就像图右边的解释说明的那样,在常见的程序里不同的寄存器扮演不同的角色其中最特别的是栈指针%rsp用来指明运行时栈的结束位置有些程序会明确地读写这个寄存器。另外15个寄存器的用法更灵活。少量指令会使用某些特定的寄存器。更重要的是,有一组标准的编程规范控制着如何使用寄存器来管理栈,传递函数参数,从函数的返回值,以及存储局部和临时数据。