指令 | Describe |
---|---|
LDR | 数据加载指令 |
LDRSW | 有符号的数据加载指令,单位:字 |
LDRB | 数据加载指令,单位:字节 |
LDRSB | 有符号的加载指令,单位:字节 |
LDRH | 数据加载指令,单位:半字 |
LDRSH | 有符号的数据加载指令,单位:半字 |
STRB | 数据存储指令,单位:字节 |
STRH | 数据存储指令,单位:半字 |
1 my_data:
2 .quad 0x8a
3 ldr x5, =my_data //使用LDR伪指令加载标签my_data的内存地址
4 ldrb x1, [x5] //8a 前面进行 零扩展
5 ldrsb x2, [x5] // 8a 前面进行 有符号扩展
LDUR Xt, [Xn|SP, #simm] // 不可拓展的数据加载指令
STUR Xt, [Xn|SP, #simm] // 不可拓展的数据存储指令
LDP Xt1, Xt2, [Xn|SP, #simm] //出栈
以 Xn/SP 寄存器的值+simm 地址的值作为内存地址,然后将该内存地址的值给 Xt1, 接着读取 Xn/SP 寄存器的值+simm+8(内存对齐)的值给 Xt2.
STP Xt1, Xt2, [Xn|SP, #simm] //入栈
以 Xn/SP 寄存器的值+simm 地址的值作为内存地址,把 Xt1 寄存器的值存储到这个内存地址中 , 接着将 Xt2 的值存储到 Xn/SP 寄存器的值+simm+8(内存对齐)处。
STP Xt1, Xt2, [Xn|SP, #simm]! //前变基模式
先计算 Xn寄存器的值=Xn/SP 寄存器的值+simm,然后以新的 Xn 寄存器的值为内存地址,把 X1 寄存器的值存储到这个地址处,再把 X2 寄存器的值存储到这个内存地址+8 处。
LDP Xt1, Xt2, <Xn|SP>, <#imm> //后变基模式
Xn 寄存器做为基地址,把 [Xn] 的值存到 Xt1 寄存器中,读取 [Xn + 8] 到 Xt2 中。最后,更新 Xn 寄存器的值为 [Xn] + imm,Xn 寄存器可以使用 SP 寄存器。
注意偏移量 simm 必须要满足
- simm 取值范围为 -512~504
- simm 必须为 8 的倍数
栈通常用来保存以下内容
栈从高低地址往低地址生长,数据出栈,SP 增大,数据入栈,SP 减小,栈空间扩大;数据出栈,SP 增大。栈空间减小。
.globalmain
main:
//栈往下扩展16字节
stp x29, x30, [sp, #-16]!
//把栈继续往下扩展8字节(相当于栈帧向下移一位)
add sp, sp, #-8
mov x8, #1
//x8保存到SP指向的位置上
str x8, [sp]
//释放刚才扩展的8字节的栈空间(栈帧向上移动一位,将X8的值出栈)
add sp, sp, #8
//main函数返回 0
mov w0, 0
//恢复x29和x30寄存器的值,使SP指向原位置(将X29和x30出栈)
ldp x29, x30, [sp], #16
ret
mov <Xd|SP>, <Xn|SP> //寄存器之间的搬移
mov <Xd>, $imm //立即数之间的搬移