深入浅出Go语言编程
上QQ阅读APP看书,第一时间看更新

1.6.1 寄存器

寄存器是CPU内部存储容量有限的高速存储部件,可临时存放参与运算的指令、数据和地址。

与amd64有关的通用寄存器都可以在plan9操作系统中使用,应用代码级别的通用寄存器主要是rax、rbx、rcx、rdx、rdi、rsi、r8~r15这14个,管理栈顶和栈底的则为bp和sp,不建议使用这两个寄存器进行运算。

在plan9操作系统中使用寄存器时不需要带r或e前缀,例如rax,只需要写成AX即可,示例命令如下:

MOVQ $101, AX = mov rax, 101

表1-3是在x64和plan9操作系统中通用寄存器名字的对照表。

表1-3 在x64与plan9操作系统中通用寄存器名字的对照表

图片表格

常用汇编指令的对应关系如下(左边为plan9,右边为x64):

plan9  ->  x64
MOVB $1, DI -> mov dil, 0x1    // 将 1 字节的立即数 0x1 存入寄存器 DI 的低 8 位
MOVW $0x10 BX -> mov bx, 0x10 // 将 2 字节的立即数 0x10 存入寄存器 BX 中
MOVD $100, DX -> mov edx, 100  // 将 4 字节的立即数 100 存入寄存器 DX 中
MOVQ $-10, AX -> mov rax, -10  // 将 8 字节的立即数 -10 存入寄存器 AX(RAX)中
ADDL $5, CX -> add ecx, 5 // 将寄存器 CX(ECX)的值加上立即数 5
SUBQ $20, SP -> sub rsp, 20 // 将寄存器 SP(RSP)的值减去立即数 20
ANDW $0xFF, SI -> and si, 0xFF // 将寄存器 SI 与立即数 0xFF 进行按位与操作
ORL $0xF0F0, DI -> or edi, 0xF0F0 // 将寄存器 DI(EDI)与立即数 0xF0F0 进行按位或操作

可以看到,plan9汇编操作数的方向与AT&T类似,与Intel的相反。

Go语言的汇编还引入了4个伪寄存器,分别如下。

FP(Frame Pointer):帧指针,用于指向当前函数栈帧的基址。在Go语言的汇编中,FP可用于访问局部变量和函数的参数。通常,FP会指向栈帧的底部(高地址处),而局部变量和参数都位于FP以下的地址中。

PC(Program Counter):程序计数器,用于表示当前正在执行的指令地址。在Go语言的汇编中,PC通常用于计算相对跳转地址。这个伪寄存器主要用于控制程序的流程,如条件跳转、循环等。

SB(Static Base Pointer):静态基址指针,主要用于访问全局变量和静态变量。在Go语言的汇编中,全局变量和静态变量的地址都是相对于SB的偏移量。SB使得访问这些变量更加方便,同时避免了硬编码绝对地址。

SP(Stack Pointer):栈指针,用于指向当前栈帧的栈顶(低地址处)。在Go语言的汇编中,SP用于管理函数栈帧,如分配临时变量、调用其他函数等。SP和FP一起维护了函数调用过程中的栈结构。