寄存器的补充
数据地址寄存器
数据地址寄存器通常用来做数据计算的临时存储、做累加、计数、地址保存等功能。定义这些寄存器的作用主要是用于在 CPU
指令中保存操作数,在 CPU
中当做一些常规变量来使用。
ARM64中
- 64 位:
X0-X30, XZR
(零寄存器) - 32 位:
W0-W30, WZR
(零寄存器)
需要注意的是,8086 汇编中有一种特殊的寄存器段寄存器:
CS, DS, SS, ES
四个寄存器来保存这些段的基地址,这个属于Intel
架构CPU
中,在ARM
中并没有。
浮点和向量寄存器
因为浮点数的存储以及其运算的特殊性,CPU
中专门提供浮点数寄存器来处理浮点数
- 浮点寄存器 64位: D0 - D31,32位: S0 - S31
现在的 CPU
支持向量运算,(向量运算在图形处理相关的领域用得非常的多)为了支持向量计算系统了也提供了众多的向量寄存器。
- 向量寄存器 128位:V0-V31
栈
- 栈:是一种具有特殊的访问方式的存储空间(后进先出,
Last In Out Firt,LIFO
)
SP和FP寄存器
-
sp
寄存器在任意时刻会保存我们栈顶的地址。 -
fp
寄存器也称为x29
寄存器属于通用寄存器,但是在某些时刻我们利用它保存栈底的地址!
注意:
ARM64
开始,取消 32 位的LDM
,STM
,PUSH
,POP
指令! 取而代之的是ldr\ldp str\stp
,ARM64
里面,对栈的操作是 16 字节对齐的。
函数调用栈
常见的函数调用开辟和恢复的栈空间
sub sp, sp, #0x40 ; 拉伸0x40(64字节)空间
stp x29, x30, [sp, #0x30] ;x29\x30 寄存器入栈保护
add x29, sp, #0x30 ; x29指向栈帧的底部
...
ldp x29, x30, [sp, #0x30] ;恢复x29/x30 寄存器的值
add sp, sp, #0x40 ; 栈平衡
ret
关于内存读写指令
注意:读/写 数据是都是往高地址读/写
str(store register)指令
将数据从寄存器中读出来,存到内存中。
ldr(load register)指令
将数据从内存中读出来,存到寄存器中,ldr
和 str
的变种 ldp
和 stp
还可以操作2个寄存器。
堆栈操作练习
使用 32 个字节空间作为这段程序的栈空间,然后利用栈将 x0
和 x1
的值进行交换。
sub sp, sp, #0x20; 拉伸栈空间32个字节
stp x0, x1, [sp, #0x10]; sp往上加16个字节,存放x0 和 x1
ldp x1, x0, [sp, #0x10]; 将sp偏移16个字节的值取出来,放入x1 和 x0
bl和ret指令
bl标号
- 将下一条指令的地址放入
lr(x30)
寄存器 - 转到标号处执行指令
ret
- 默认使用
lr(x30)
寄存器的值,通过底层指令提示CPU
此处作为下条指令地址。
ARM64
平台的特色指令,它面向硬件做了优化处理的。
x30寄存器
x30
寄存器存放的是函数的返回地址,当 ret
指令执行时刻,会寻找 x30
寄存器保存的地址值。
注意:在函数嵌套调用的时候,需要将
x30
入栈。
函数的参数和返回值
ARM64
下,函数的参数是存放在 X0
到 X7
(W0
到 W7
) 这 8 个寄存器里面的,如果超过 8个参数,就会入栈。
函数的返回值是放在 X0
寄存器里面的。
函数的局部变量
函数的局部变量放在栈里面。
网友评论