ARM汇编 - Charles-Charmless/Charles-Charmless.github.io GitHub Wiki
ARM处理器一个显著特征就是可以在操作数进入ALU之前对操作数进行制定位数的左移和右移操作
基本语法格式: {} {S} ,,<shifter_operand>
- :确定具体指令
- S:标识指令是否影响程序状态寄存器CPSR条件标志
- Rd:指令操作的目的寄存器
- Rn:指令第一源操作数
- bit[11:0]: 移位操作
- bir[25]: 被用来区分是立即数移位操作还是寄存器移位操作
Name | Tags |
---|---|
immediate | 立即数寻址 |
Rm | 寄存器寻址 |
Rm,LSL shift_imm | 立即数逻辑左移 |
Rm,LSL Rs | 寄存器逻辑左移 |
Rm,LSR shift_imm | 立即数逻辑右移 |
Rm,LSR Rs | 寄存器逻辑右移 |
Rm,ASR shift_imm | 立即数算数右移 |
Rm,ASR Rs | 寄存器算数右移 |
Rm,ROR shift_imm | 立即数循环右移 |
Rm,ROR Rs | 寄存器玄幻右移,:包含逻辑右移位数的寄存器 |
Rm,RRX | 寄存器扩展循环右移 |
有效性;只有那些通过将一个8bit的立即数循环右移偶数位可以得到的立即数才可以在指令中使用
arm汇编器按照下方的规则来生成立即数的编码:
- 当立即数数值在0-0xFF范围时,令immed_8=,immed_4=0;
- 其他情况下,汇编器使用immed_4数值最小的编码方式
根据内存访问指令的分类,内存访问指令的寻址方式可以分为:
- 字及无符号自己的Load/Store指令的寻址方式
- 杂类 Load/Store 指令的寻址方式
- 批量 Load/Store 指令的寻址方式
- 协处理器 Load/Store 指令的寻址方式
-
指令语法结构: LDR|STR{}{B}{T} ,<addressing_mode>
格式 Tags 描述 Rn, +- offset_12 立即数偏移寻址 内存访问地址为基址寄存器Rn的值加减立即数offset_12 Rn,+-Rm 寄存器偏移寻址 内存访问地址为基址寄存器Rn的值加减偏移寄存器Rm的值 Rn,Rm,shift offset_12 带移位的寄存器偏移寻址 Rn,+-offset_12! 立即数前牵引寻址 同上,但是在操作成功后将访问的内存地址写入到基址寄存器Rn中 Rn,+-Rm! 寄存器前牵引寻址 Rn,Rm, shiftoffset_12! 带移位寄存器前牵引寻址 Rn,+-offset_12 立即数后牵引寻址 使用基址寄存器Rn的值作为实际内存访问地址,当指令的执行条件满足后,将基址寄存器的值嘉奖偏移量产生新的地址写到Rn中 Rn,+-Rm 2 寄存器后牵引寻址 Rn,+-Rm,shiftoffset_12 带移位的寄存器后牵引寻址
: 表示移位操作
LDR|STR{<cond>}{B}{T} <Rd>,<addressing_mode> =
LDR|STR{<cond>}{B}{T} <Rd>,[<Rn>,+-<Rm>,LSL/LSR/ASR/ROR #<offset_12>] =
LDR|STR{<cond>}{B}{T} <Rd>,[<Rn>,+-<Rm>,RRX]
:指令编码的条件域,指示指令在什么条件下执行,当忽略时,指令为无条件执行(cond=AL(always))
语法格式:
- LDR|STR{}H|SH|SB|D ,<addressing_mode>
- 分别表示(有符号/无符号)半字Load/Stroe 指令,有符号字节Load/Store指令和双字Load/store指令
格式 | 模式 |
---|---|
Rn,+-offseet_8 2 | 立即数偏移寻址 |
Rn,+-Rm 3 | 寄存器偏移寻址 |
Rn,+-offset_8! | 立即数前牵引寻址 |
Rn,+-Rm! 2 | 寄存器前牵引寻址 |
Rn,+-offseet_8 | 立即数后牵引寻址 |
Rn,+-Rm 4 | 寄存器后牵引寻址 |
!0C9EA8EB-785D-411D-A01A-B7A1B78377B9.jpeg
替代上图中的<addressing_mode>
- Rn为基址寄存器,包含内存访问的基地址
- 为指令操作的寄存器列表
- <^>表示如果寄存器列表中包含程序计数器PC,是否将spsr拷贝到cpsr
语法格式: {}{L} ,,<addressing_mode>
格式 | 说明 |
---|---|
Rn,+-offset_84 2 | 立即数偏移寻址 |
Rn,+-offset_84! | 前牵引立即数偏移寻址 |
Rn,+-offset_84 | 后牵引立即数偏移寻址 |
Rn,option | 直接寻址 |
<offset_8>: 8位的立即数,该值的4倍为地址偏移量
指令 | 描述 | Files |
---|---|---|
MOV{cond}{S} Rd,shifter_operand | ||
MVN{cond}{S} Rd,shifter_operand |
指令 | 描述 | 语法格式 | 关键点 |
---|---|---|---|
LDR | 把一个字装入寄存器中 | LDR{} ,<addr_mode> | |
STR | 将存储器中的字保存到寄存器中 | STR{} ,<addr_mode> | |
LDRB | 把一个字节装入一个寄存器 | LDR{}B ,<addr_mode> | |
STRB | 把寄存器的低8位字节保存到存储器 | STR{}B ,<addr_mode> | |
LDRH | 把一个半字装入一个寄存器 | LDR{}H ,<addr_mode> | |
STRH | 从寄存器取出指定的16位半字节到寄存器的低16位 | STR{}H ,<addr_mode> | |
LDRBT | 用户模式下将一个字节装入寄存器 | LDR{}BT ,<post_indexd_addressing_mode> | |
STRBT | 用户模式下将寄存器的低8位字节保存到存储器 | STR{}BT ,<post_indexd_addressing_mode> | |
LDRT | 用户模式下把一个字装入一个寄存器 | LDR{}T ,<post_indexd_addressing_mode> | |
STRT | 用户模式下将存储器中的字保存到寄存器 | STR{}T ,<post_indexd_addressing_mode> | |
LDRSB | 把一个有符号字节专题图一个寄存器 | LDR{}SB ,<addr_mode> | |
LDRSH | 把一个有符号半字节装入一个寄存器 | LDR{}SH ,<addr_mode> |
<addr_mode>:确定了指令编码中的I,P,U,W,和<addr_mode>位
<post_indexd_addressing_mode>: 使用后牵引地址模式寻址
指令 | 描述 | 指令系统 |
---|---|---|
LDM | LDM | 装载多个寄存器 |
STM | STM | 保存多个寄存器 |
<address_mode>:指令的寻址方式,确定编码格式中的P,U和W位
!: 设置指令编码中的W位,它使指令执行后将操作数的内存地址写入基址寄存器中
:被加载的寄存器列表,不同的寄存器之间用","隔开,完整的寄存器列表包含在"{}"中,编号低的寄存器对应于内存中的低地址单元,编号高的寄存器对应于内存中的高地址单元
指令 | 描述 | 指令系统 |
---|---|---|
Wiki/Arm linux修炼之路/C语言+汇编/ARM汇编/多寄存器内存字段数据传送指令/LDM | 装载多个寄存器 | LDM{}<addressing_mode> {!},<registers_without_pc> |
Wiki/Arm linux修炼之路/C语言+汇编/ARM汇编/多寄存器内存字段数据传送指令/STM | 保存多个寄存器 | STM{}<addressing_mode> {!},^ |
<registers_without_pc>:被加载的寄存器列表,此列表中不能包含PC寄存器
^: 寄存器列表,只能使用用户模式下的寄存器
指令 | 描述 | 指令系统 |
---|---|---|
Wiki/Arm linux修炼之路/C语言+汇编/ARM汇编/带状态寄存器的多寄存器内存字段数据传送指令/LDM | LDM | 装载多个寄存器 |
- 貌似没什么区别?
LDM{}<模式> {!},<registers_without_pc>
STM{}<模式> {!},<registers_without_pc>
<模式>
- IA:每次传送后地址加4
- IB:每次传送前地址加4
- DA:每次传送后地址减4
- DB:每次传送前地址减4
- FD:满递减堆栈
- ED:空递增堆栈
- FA:满递增堆栈
- EA:空递增堆栈
用于将内存中的一个字单元和一个指定寄存器的值交换
语法格式: SWP{} ,,[]
:包含要存储到内存中的数据
:包含要访问的内存地址
描述: 假设内存单元地址存放在寄存器中,指令将中的数据读取到目的寄存器Rd中,同时将另一个寄存器中的内容写到该内存单元中,,当和位同一个寄存器时,指令交换Rd和Rn的值
SWP{}B ,,[]
B为可选项,若有B,则交换字节,否则交换32位字
把程序状态寄存器的值送到一个通用寄存器
指令:
- MRS{} ,CPSR
- MRS{} ,SPSR
把通用寄存器的值或者是一个立即数传送到程序状态寄存器
指令:
- MSR{} CPSR_,#
- MSR{} CPSR_,
- MSR{} SPSR_,#
- MSR{} SPSR_,
:设置状态寄存器所需要的位,状态寄存器的32位可以分成4个8位的域
- bits[31:24]为条件标志位域,用f表示
- bits[23:16]为状态位域,用s表示
- bits[15:8]为扩展位域,用x表示
- bits[7:0]为控制位域,用c表示
操作码 | 助记符 | 操作 | 操作 1 |
---|---|---|---|
0000 | AND | 逻辑加 | Rd:Rn and op2 |
0001 | EOR | 逻辑异或 | Rd: Rn EOR op2 |
0010 | SUB | 减 | Rd: Rn-op2 |
0011 | RSB | 翻转减 | Rd: op2-Rn |
0100 | ADD | 加 | Rd: Rn+op2 |
0101 | ADC | 带进位的加 | Rd: Rn+op2+C |
0110 | SBC | 带进位的减 | Rd: Rn-op2+C-1 |
0111 | RSC | 带进位的翻转减 | Rd: op2-Rn+C-1 |
1000 | TST | 测试 | Rn AND op2并更新标志位 |
1001 | TEQ | 测试相等 | Rn EOR op2并更新标志位 |
1010 | CMP | 比较 | Rn - op2并更新标志位 |
1011 | CMN | 负数比较 | Rn + op2并更新标志位 |
1100 | ORR | 逻辑或 | Rd: Rn OR op2 |
1110 | BIC | 位清0 | Rd: Rn AND NOT(op2) |
操作指令:
<opcode2>{<cond>} <Rn>,<shifter_operands>
<opcode2>:=CMP|CMN|TST|TEQ
<opcode3>{<cond>}{S} <Rd>,<Rn>,<shifter_operand>
<opcode3>:=ADD|SUB|RSB|ADC|SBC|RSC|AND|BIC|EOR|ORR
Arm数据处理指令使用3地址格式,这意味着分别指定两个源操作数和一个目的寄存器,第一个源操作数总是目的寄存器,第二个源操作数又叫做移位操作数,它可能是寄存器,移位后的寄存器或者立即数,
操作码 | 助记符 | 意义 | 语法格式 | 操作 |
---|---|---|---|---|
000 | MUL | 乘(保留32位结果) | MUL{}{S} ,, | Rd: (Rm*Rs)[31:0] |
001 | MLA | 乘-累加(32位结果) | MLA{}{S} ,,, | Rd: (Rm*Rs+Rn)[31:0] |
100 | UMULL | 无符号长乘 | UMULL{}{S} ,,, | RdHi: RdLo=Rm*Rs |
101 | UMALL | 无符号长乘-累加 | UMALL{}{S} ,,, | RdHi: RdLo+=Rm*Rs |
110 | SMULL | 有符号数长乘 | SMULL{}{S} ,,, | RdHi: RdLo: Rm*Rs |
111 | SMLAL | 有符号数长乘-累加 | SMLAL{}{S} ,,, | RdHi: RdLo+=Rm*Rs |