加载和存储指令
#J基地址偏移
LDR X0,[X1,#8]
LDR X0,[X1,#8]!
LDR X0,[X1],#8
#K扩展模式
LDR X0,[X1,X2]
LDR X0,[X1,X2,LSL #3]
LDR X0,[X1,W2,SXTW]
LDR X0,[X1,W2,SXTW #3]
#PC相对地址
my_data:
.word 0x40
#define MY_LABLE 0x20
ldr x0,my_data
ldr x0,=my_data
ldr x0,MY_LABLE
ldr x0,=MY_LABLE
#S上述my_data如果超了PC 1M内,可以这样加载
ldr x5,=my_data
ldr x0,[x5]
#J加载和存储变种
LDRSW 有符号数据加载,4B,32b
LDRB 数据加载,1B,8b
LDRSB 有符号数据加载,1B,8b
LDRH 数据加载,2B
LDRSH 有符号数据加载 2B
STRB 数据存储,1B
STRH 数据存储,2B
my_data
.quad 0x8a
ldr x5,=my_data
ldrb x0,[x5]
ldrsb x1,[x5]
#B不可扩展的加载和存储指令
LDUR <Xt>,[ <Xn|SP>, #<simm> ]
STUR <Xt>,[ <Xn|SP>, #<simm>]
#D多字节内存加载和存储
LDP X1,X2,[ <Xn>|SP {,#<imm>}]
SDP X1,X2,[ <Xn>|SP {,#<imm>}]
LDP X1,X2,[ <Xn>|SP ,#<imm>]!
STP X1,X2,[ <Xn>|SP ,#<imm>]!
LDP X1,X2,[ <Xn>|SP ], #<imm>
STR X1,X2,[ <Xn>|SP ], #<imm>
#D独占内存访问
LDXR X1,[ Xn|SP {,#0} ]
STXR Ws X1,[ Xn|SP {,#0} ]
LDXR X1,X2,[ Xn|SP {,#0} ]
STXR Ws X1,X2,[ Xn|SP {,#0} ]
LDXR 在读内存时,会标记内存
STXR 在写内存时,会清标记,且Ws=0;如果发现内存没有独占,那么就不写内存,并把Ws=1
原子操作原理 伪代码:
LABEL:
LDXR X0,[Xn]
ADD X0,X0,#1
STXR Ws,X0,[Xn]
if(Ws !=0)
goto LABEL
#N内存屏障
LDAR 加载-获取指令,LDAR后面的读写内存指令,必须在LDAR指令之后执行
STLR 存储-释放指令,所有加载和存储指令,都必须在STLR之前完成
#F非特权访问级别的加载、存储
适用于在EL0下的访问
LDTR/LDTRB/LDTRSB/LDTRH/LDTRSH/LDTRSW
STTR/STTRB/STTRH
入栈和出栈
ARM64去掉了PUSH和POP指令
入栈:
str X1,[SP,#-8]!
stp X1,X2,[SP,#-16]!
出栈:
ldr X1,[SP],#8
ldp X1,X2,[SP],#16
MOV
MOV Xn, Xm|SP|#imm
#imm要求:
1) 16位的无符号数(16位的立即数)
2) 16位的立即数左移16位、32位、48位
MOV X1,0x1abcd
MOV X1,ABCD0000
MOVZ:将一个16位立即数移动到寄存器的指定16位位置,其他位清零。
MOVK:将一个16位立即数移动到寄存器的指定16位位置,其他位保持不变。
MOVN:与MOVZ类似,但是将立即数取反后再使用。