870 likes | 1.07k Views
ARM 指令集与编程. 总体介绍:指令分类,特点,格式,条件码 数据处理指令:数据传输指令,算术指令,逻辑指令,比较指令,乘法指令 ( 略 ) ,前导零计数 ( 略 ) 程序状态访问指令 跳转指令 单数据访存指令 多数据访存指令 其它指令:信号量操作指令,异常中断产生指令,协处理器指令 ( 略 ) 伪指令 ( 略 ) 基于 ARM 的编程. 1 总体介绍. 指令分类、特点、格式、条件码. 1.1 指令分类. ARM 指令集总体分为 6 类指令 数据处理指令:数据传输指令,算术指令,逻辑指令,比较指令,乘法指令,前导零计数。
E N D
ARM指令集与编程 • 总体介绍:指令分类,特点,格式,条件码 • 数据处理指令:数据传输指令,算术指令,逻辑指令,比较指令,乘法指令(略),前导零计数(略) • 程序状态访问指令 • 跳转指令 • 单数据访存指令 • 多数据访存指令 • 其它指令:信号量操作指令,异常中断产生指令,协处理器指令(略) • 伪指令(略) • 基于ARM的编程 ARM指令集与编程
1 总体介绍 指令分类、特点、格式、条件码
1.1 指令分类 ARM指令集总体分为6类指令 • 数据处理指令:数据传输指令,算术指令,逻辑指令,比较指令,乘法指令,前导零计数。 • 程序状态访问指令:mrs和msr。 • 跳转指令:b和bl。 • 访存指令:单数据访存指令,多数据访存指令,信号量操作指令。 • 异常中断产生指令:swi和bkpt。 • 协处理器指令。 ARM指令集与编程
1.2 指令特点 • 所有指令都是32bit。 • 大多数指令都在单周期内完成。 • 所有指令都可以条件执行。 • load/store体系结构。 • 指令集可以通过协处理器扩展 ARM指令集与编程
31 28 27 25 24 21 20 19 16 15 12 11 8 7 0 Cond 001 Opcode S Rn Rd Operand2 1.3 ARM指令的格式 <Opcode>{<cond>}{s} <Rd>, <Rn>, <Operand2> • Cond:指令的条件码。 • Opcode:指令操作码。 • S:操作是否影响cpsr。 • Rn:包含第一个操作数的寄存器编码。 • Rd:目标寄存器编码。 • Operand2:第2操作数。 ARM指令集与编程
1.3 ARM指令的格式(续) ARM指令集与编程
1.4 ARM指令的条件执行 所有的ARM指令可包含一个可选的条件码,只有在cpsr中的条件标志位满足指定的条件时,指令才会被执行。不符合条件的代码依然占用一个时钟周期(相当于一个NOP指令)。 if ( (a == b) && (c == d) ) { e++; } // r0, r1, r2, r3, r4 : a, b, c, d, e cmp r0, r1 cmpeq r2, r3 addeq r4, r4, #1 ARM指令集与编程
1.4.1 ARM指令的条件域 • EQ/NE: 等于/不等于(equal / not equal) • HS/LO: 无符号数高于或等于/无符号数小于(higher or same/lower) • HI/LS: 无符号数高于/无符号数低于或等于(higher/lower or same) • GE/LT: 有符号数大于或等于/有符号数小于(greater or equal / less than) • GT/LE: 有符号数大于/有符号数小于或等于(greater than / less or equal) • MI/PL: 负/非负 • VS/VC: 溢出/不溢出(overflow set / overflow clear) • CS/CC: 进位/无进位(carry set / carry clear) ARM指令集与编程
1.4.2 ARM指令的条件码 ARM指令集与编程
1.4.2 ARM指令的条件码(续) 注:AL是默认的,NV不建议使用。 ARM指令集与编程
目录 • 总体介绍:指令分类,特点,格式,条件码 • 数据处理指令:数据传输指令,算术指令,逻辑指令,比较指令,乘法指令(略),前导零计数(略) • 程序状态访问指令 • 跳转指令 • 单数据访存指令 • 多数据访存指令 • 其它指令:信号量操作指令,异常中断产生指令,协处理器指令(略) • 伪指令(略) • 基于ARM的编程 ARM指令集与编程
2 数据处理指令 • 数据传输指令:mov和mvn • 算数指令:add、adc、sub、sbc,rsb和rsc • 逻辑指令:and、orr、eor和bic • 比较指令:cmp、cmn、tst和teq ARM指令集与编程
2.1 数据处理指令的特点 • 所有的操作数要么来自寄存器,要么来自立即数,不会来自内存。 • 如果有结果,则结果一定是为32位宽,并且放在一个寄存器中,不会写入内存。(有一个例外:长乘法指令产生64位结果) • 每一个操作数寄存器和结果寄存器都在指令中独立指出,即:ARM指令采用3地址模式:<Operation> Rd, Rn, Rm ARM指令集与编程
31 28 27 25 24 21 20 19 16 15 12 11 8 7 0 Cond 00X opcode S Rn Rd 第 2 操作数 11 8 7 0 方式1:#immed #rot #immed_8 add r0, r1, #0xff 11 4 3 0 方式2:Rm 0 0 0 0 0 0 0 0 Rm 11 8 7 4 3 0 方式3:Rm LSL Rs Rs 0 0 0 0 Rm add r0, r1, r1, LSL r2 11 7 6 4 3 0 方式4:Rm LSL #immed_5 (#immed_5取值范围0-31) #immed_5 shift Rm add r0, r1, r1, LSL #31 2.2 四种寻址方式和s后缀 add r0, r1, r2 ARM指令集与编程
寄存器,可能需要移位。 • 如需移位,移位值可为: • 5bit的无符号整数(0-31) • 在指令的最低字节指定的另一寄存器 • 立即数 • 8比特数 • 8比特数循环右移偶数位 • 右移位数由汇编器自动计算 2.2.1 四种寻址方式的硬件支持 ARM指令集与编程
2.2.2 立即数寻址 • ARM指令中的立即数,由一个8bit的常数循环右移偶数位得到: 立即数 =(0->255) 循环右移 2N位 • 例子: • 合法立即数:0x3fc,0x0,0xf0000000,0xf0000001 • 非法立即数:0x1fe,0xffff,0x1010,0xf0000010 ARM指令集与编程
2.2.2 立即数寻址(续) • 同一个立即数可能有多个表示方法。如: • 0x3f0 = 0x3f 循环右移 28位 • 0x3f0 = 0xfc 循环右移 30位 • 对立即数的编码规则: • 如果立即数在0 – 0xff之间,移位数为0。 • 否则,就取决于编译器了。指令“mov r0, #0x3f0”在ADS1.2中被编译为0xe3a00ffc,在arm-elf-gcc-2.95.3中被编译为0xe3a00e3f。 ARM指令集与编程
2.2.2 立即数寻址(续) • 对于有互补操作的指令,编译器可以做智能的转换,比如: • mvn r1, 0xffffff00 -> mov r1, 0xff • add r1, r1, #0xffffff00 -> sub r1, r1, #0x100 • adc r1, r1, #0xffffff00 -> sbc r1, r1, #0xff • and r1, r1,#0xffffff00 -> bic r1, r1, #0xff 这样,一些原本非法的立即数也可以正常编译通过。如果一个立即数,经过上述转换后是合法的,那么它也可以用在数据操作指令中。 ARM指令集与编程
2.2.3 寄存器移位寻址 ASR 算术右移 LSL 逻辑左移 LSR 逻辑右移 ROR 循环右移 RRX 扩展的循环右移 ARM指令集与编程
2.2.3 寄存器移位寻址(续) • 如果移位的位数由立即数(5bit,取值范围0 - 31)给出,就叫作 immediate specified shift;如果由Rs的低5位决定,就叫做register specified shift。 • Register specified shift的两点问题: • 不能使用pc:如果将pc寄存器用在Rn,Rd,Rm和Rs的位置上时,会产生不可预知的结果。 • 额外代价(overhead):需要更多的周期才能完成指令,因为ARM没有能力一次读取3个寄存器。 • Immediate specified shift 没有上述问题。 ARM指令集与编程
2.2.3 寄存器移位寻址(续) • 在register specified shift寻址方式下使用pc寄存器,编译器提示如下警告: • 在ADS1.2种编译产生如下警告之一: • Warning A1477W:This register combination results in UNPREDICTABLE behavior • Warning : A1320E: Undefined effect (using PC as Rn or Rm in register specified shift) • Warning : A1319E: Undefined effect (using PC as Rs) • 但是在arm-elf-gcc-2.95.3中没有报告错误。 ARM指令集与编程
2.2.4 后缀s • 数据处理指令可以选择s后缀,以影响状态标志。但是比较指令(cmp、cmn、tst和teq)不需要后缀s,它们总会直接影响cpsr中的状态标志。 • 在数据操作指令中,除了比较指令以外,其它的指令如果带有s后缀,同时又以pc为目标寄存器进行操作,则操作的同时从spsr恢复cpsr。比如: • movs pc, #0xff /* cpsr = spsr; pc = 0xff */ • adds pc, r1, #0xffffff00 /* cpsr = spsr; pc = r1 + 0xffffff00 */ • ands pc, r1, r2 /* cpsr = spsr; pc = r1 & r2; */ • 如果在user或者system模式下使用带有s后缀的数据操作指令,同时以pc为目标寄存器,那么会产生不可预料的结果。因为user和system模式下没有spsr。 ARM指令集与编程
2.3 数据传输指令 • 语法 • <Operation>{<cond>}{s} <Rd>, #<immed> • <Operation>{<cond>}{s} <Rd>, <Rm> • <Operation>{<cond>}{s} <Rd>, <Rm>, LSL #<immed_5> • <Operation>{<cond>}{s} <Rd>, <Rm>, LSL <Rs> • 伪代码 if ConditionPassed(cond) then Rd = 第2操作数 if s == 1 and Rd == pc then cpsr == spsr else if s == 1 then set NZCV flags in cpsr ARM指令集与编程
2.3 数据传输指令(续) • 举例 • mov r0, r1 /* r0 = r1,不修改cpsr */ • mov r0, #0x0 /* r0 = 0,不修改cpsr */ • movs r0, #0x0 /* r0 = 0,同时设置cpsr的Z位 */ • movs r0, #-10 /* r0 = 0xfffffff6,同时设置cpsr的N位 */ • mvn r0, r2 /* r0 = NOT r2,不修改cpsr */ • mvn r0, 0xffffffff /* r0 = 0x0,不修改cpsr */ • mvns r0, 0xffffffff /* r0 = 0x0,同时设置cpsr的Z位 */ • mov r0, r1, LSL #1 /* r0 = r1 << 1 */ • mov r0, r1, LSR r2 /* r0 = r1 >> r2 */ ARM指令集与编程
2.3 数据传输指令(续) • 说明 • mvn意为“取反传输”,它把源寄存器的每一位取反,将得到的结果写入结果寄存器。 • movs和mvns指令对pc寄存器赋值时有特殊含义,表示要求在赋值的同时从spsr中恢复cpsr。 • 对于mov和mvn指令,编译器会进行智能的转化。比如指令“mov r1, 0xffffff00”中的立即数是非法的。在编译时,编译器将其转化为“mvn r1, 0xff”,这样就不违背立即数的要求。所以对于mov和mvn指令,可以认为:合法的立即数反码也是合法的立即数。 ARM指令集与编程
2.4 算术指令 • 语法 • <Operation>{<cond>}{s} <Rd>, <Rn>, #<immed> • <Operation>{<cond>}{s} <Rd>, <Rn>, <Rm> • <Operation>{<cond>}{s} <Rd>, <Rn>, <Rm>, LSL #<immed_5> • <Operation>{<cond>}{s} <Rd>, <Rn>, <Rm>, LSL <Rs> • 伪代码(以加法add为例) if ConditionPassed(cond) then Rd = Rn + 第2操作数 if s == 1 and Rd == pc then cpsr = spsr else if s == 1 then set NZCV flags in cpsr ARM指令集与编程
2.4 算术指令(续) • 举例 • add r0, r1, r2 /* r0 = r1 + r2 */ • adc r0, r1, r2 /* r0 = r1 + r2 + carry */ • sub r0, r1, r2 /* r0 = r1 – r2 */ • sbc r0, r1, r2 /* r0 = r1 – r2 + carry -1 */ • rsb r0, r1, r2 /* r0 = r2 – r1 */ • rsc r0, r1, r2 /* r0 = r2 – r1 + carry – 1 */ • add r0, r1, r1, LSL #31 /* r0 = r1 + r1 << 31 */ • add r0, r1, r1, LSL r2 /* r0 = r1 + r1 << r2 */ • 说明 • adds和adcs在进位时将cpsr的C标志置1;否则置0。 • subs和sbcs在产生借位时将cpsr的C标志置0;否则置1。 ARM指令集与编程
2.5 逻辑指令 • 语法 • <Operation>{<cond>}{s} <Rd>, <Rn>, #<immed> • <Operation>{<cond>}{s} <Rd>, <Rn>, <Rm> • <Operation>{<cond>}{s} <Rd>, <Rn>, <Rm> LSL #<immed_5> • <Operation>{<cond>}{s} <Rd>, <Rn>, <Rm> LSL <Rs> • 伪代码(以and为例) If ConditionPassed(cond) then Rd = Rn AND 第2操作数 if s == 1 and Rd == pc then cpsr = spsr else if s == 1 then set NZCV flags in cpsr ARM指令集与编程
2.5 逻辑指令(续) • 举例 • and r0, r1, r2 /* r0 = r1 AND r2 */ • and r1, r1,#0xffffff00 /* r1 = r1 AND 0xffffff00 */ • orr r0, r1, r2 /* r0 = r1 OR r2 */ • eor r0, r1, r2 /* r0 = r1 XOR r2 */ • bic r0, r1, r2 /* r0 = r1 AND NOT r2 */ • bic r1, r1, #0x0f /* 清空r1的低4位 */ • and r0, r1, r1, LSL #31 /* r0 = r1 AND (r1 << 31) */ • and r0, r1, r1, LSR r2 /* r0 = r1 AND (r1 >> r2) */ ARM指令集与编程
2.6 比较指令 • 语法 • <Operation>{<cond>} <Rn>, #<immed> • <Operation>{<cond>} <Rn>, <Rm> • <Operation>{<cond>} <Rn>, <Rm>, LSL #<immed_5> • <Operation>{<cond>} <Rn>, <Rm>, LSL <Rs> • 伪代码(以cmp为例) If ConditionPassed(cond) then alu_out = Rn – 第2操作数 set NZCV flags in cpsr ARM指令集与编程
2.6 比较指令(续) • 举例 • cmp r1, r2 /*根据r1 – r2的结果设置cpsr,结果不写回*/ • cmn r1, r2 /*根据r1 + r2的结果设置cpsr,结果不写回*/ • tst r1, r2 /*根据r1 AND r2的结果设置cpsr,结果不写回*/ • teq r1, r2 /*根据r1 XOR r2的结果设置cpsr,结果不写回*/ • cmp r2, #5 /*根据r2 – 5的结果设置cpsr,结果不写回*/ • cmp r1, r2, LSL #5 /* 根据r1 – (r2 << 5)设置cpsr */ • cmp r1, r2, LSL r3 /* 根据r1 – (r2 << r3)设置cpsr */ • 说明 • 如果不考虑结果的写回,cmp、cmn、tst和teq分别等价于subs、adds、ands和eors。 ARM指令集与编程
目录 • 总体介绍:指令分类,特点,格式,条件码 • 数据处理指令:数据传输指令,算术指令,逻辑指令,比较指令,乘法指令(略),前导零计数(略) • 程序状态访问指令 • 跳转指令 • 单数据访存指令 • 多数据访存指令 • 其它指令:信号量操作指令,异常中断产生指令,协处理器指令(略) • 伪指令(略) • 基于ARM的编程 ARM指令集与编程
3 程序状态访问指令 • 当需要修改cpsr/spsr的内容时,首先要读取它的值到一个通用寄存器,然后修改某些位,最后将数据写回到状态寄存器。 • cpsr/spsr不是通用寄存器,不能使用mov指令来读写。在ARM处理器中,只有mrs指令可以读取cpsr/spsr;只有msr可以写cpsr/spsr。 ARM指令集与编程
3.1 读指令mrs • 语法 • mrs{<cond>} <Rd>, cpsr|spsr • 伪代码 if ConditionPassed(cond) then if R == 1 then Rd = spsr else Rd = cpsr ARM指令集与编程
3.1读指令mrs(续) • 举例 • mrs r0, cpsr /* 读取cpsr到r0 */ • mrs r3, spsr /* 读取spsr到r3 */ • 说明 • user和system模式没有spsr,因此这些模式下不能读取spsr。 ARM指令集与编程
31 28 27 26 25 24 23 22 21 20 19 16 15 12 11 0 cond 0 0 # 1 0 R 1 0 f s x c 1111 操作数 域屏蔽 cpsr/spsr 11 8 7 0 1 #rot 8位立即数 立即数对准 11 4 3 0 0 0 0 0 0 0 0 0 0 Rm 操作数寄存器 3.2 写指令msr的二进制格式 ARM指令集与编程
3.2.1 写指令msr的语法 • msr{<cond>} <psr>_<fields>, #<immed> • msr{<cond>} <psr>_<fields>, <Rm> • <immed>表示合法的立即数:8bit循环右移偶数位 • <psr>代表cpsr或spsr • <fields>指定传送的区域,可进一步细分(只能小写) • c 控制域字节(psr[7:0]) • x 扩展域字节(psr[15:8]) • s 状态域字节(psr[23:16]) • f 标志域字节(psr[31:24]) ARM指令集与编程
3.2.2 写指令msr的伪代码 • 伪代码 if ConditionPassed(cond) then if opcode[25] == 1 operand = 8立即数 Rotate_Right (#rot * 2) else /* opcode[25] == 0 */ operand = Rm if R == 0 then if field_mask[0] == 1 and InAPrivilegeMode() then cpsr[7:0] = operand[7:0] if field_mask[1] == 1 and InAPrivilegeMode() then cpsr[15:8] == operand[15:8] if field_mask[2] == 1 and InAPrivilegeMode() then cpsr[23:16] == operand[23:16] if field_mask[3] == 1 then cpsr[31:24] = operand[31:24] else /* R == 1 */ if field_mask[0] == 1 and CurrentModeHasSPSR() then spsr[7:0] = operand[7:0] if field_mask[1] == 1 and CurrentModeHasSPSR() then spsr[15:8] == operand[15:8] if field_mask[2] == 1 and CurrentModeHasSPSR() then spsr[23:16] == operand[23:16] if field_mask[3] == 1 and CurrentModeHasSPSR() then spsr[31:24] = operand[31:24] ARM指令集与编程
3.2.3 msr举例和说明 • 举例 • msr cpsr_c, #0xd3 /* 切换到SVC模式*/ • msr cpsr_cxsf, r3 /* cpsr = r3 */ • 说明 • user和system模式没有spsr,因此这些模式下不能对spsr操作。 • 由于权限问题,在user模式下对cpsr[23:0]修改无效。 • 如果使用立即数,要使用合法的立即数。 • 程序不能同过“msr修改cpsr的T位”来完成ARM/Thumb态的切换。必须使用bx指令,因为bx属于分支指令,它会打断流水线,实现处理器状态切换。 • 如果要修改读出的值,仅修改必要的位,其它位保持不变,这样保持了最大兼容性。 ARM指令集与编程
目录 • 总体介绍:指令分类,特点,格式,条件码 • 数据处理指令:数据传输指令,算术指令,逻辑指令,比较指令,乘法指令(略),前导零计数(略) • 程序状态访问指令 • 跳转指令 • 单数据访存指令 • 多数据访存指令 • 其它指令:信号量操作指令,异常中断产生指令,协处理器指令(略) • 伪指令(略) • 基于ARM的编程 ARM指令集与编程
4 跳转指令 • 语法 • b{<cond>} label • bl{<cond>} label • 说明 • 寻址范围 +32MB ARM指令集与编程
4 跳转指令(续) • 当转移指令执行时,处理器将指令中的offset(24bit)左移2bit,变成26bit,表示+ 32M的范围。 • pc从新的地址执行,流水线重新填充。 • 如果是“bl”指令,将返回地址写入lr寄存器。子程序返回时只需要用lr恢复pc就可以: • mov pc, lr • “b”指令不影响lr寄存器 ARM指令集与编程
目录 • 总体介绍:指令分类,特点,格式,条件码 • 数据处理指令:数据传输指令,算术指令,逻辑指令,比较指令,乘法指令(略),前导零计数(略) • 程序状态访问指令 • 跳转指令 • 单数据访存指令 • 多数据访存指令 • 其它指令:信号量操作指令,异常中断产生指令,协处理器指令(略) • 伪指令(略) • 基于ARM的编程 ARM指令集与编程
5 单数据访存指令 • 第一类: • 读写字: ldr / str • 读写无符号字节: ldrb / strb • 第二类: • 读写无符号半字: ldrh / strh • 读有符号半字: ldrsh • 读有符号字节: ldrsb ARM指令集与编程
31 28 27 26 25 24 23 22 21 20 19 16 15 12 11 8 7 0 cond 01 I P U B W L Rn Rd 第 2 操作数 0/1 : 立即数(方式1)/寄存器(方式2,3) 0/1 : str/ldr 0/1 : 无/有(!) 0/1 : 后变址/前变址 0/1 : 字/无符号字节 11 0 0/1 : 加/减(第2操作数) 方式1:#immed_12(取值范围0 – 0xfff) 例子:ldr r0, [r1, #+0xfff] #immed_12 11 4 3 0 方式2:Rm 例子:ldr r0, [r1, +r2] 0 0 0 0 0 0 0 0 0 0 Rm 11 7 6 5 4 3 0 方式3:Rm LSL #immed_5(取值范围0-31) 例子:ldr r0, [r1, r2 LSL #31] #immed_5 shift 0 Rm 5.1 第一类指令的指令格式 ARM指令集与编程
5.2 第一类指令的语法 • 语法 • ldr|str{<cond>}{b} <Rd>, [<Rn>, #+<immed_12]{!} • ldr|str{<cond>}{b} <Rd>, [<Rn>, +<Rm>]{!} • ldr|str{<cond>}{b} <Rd>, [<Rn>, +<Rm>, <shift> #<immed_5>]{!} • ldr|str{<cond>}{b} <Rd>, [<Rn>], #+<immed_12 • ldr|str{<cond>}{b} <Rd>, [<Rn>], +<Rm> • ldr|str{<cond>}{b} <Rd>, [<Rn>], +<Rm>, <shift> #<immed_5> • 举例 • ldrb r0, [r1, #+0xfff] /* 把r1+0xfff地址的字节读入r0 */ • ldr r0, [r1, +r2]! /*把r1+r2地址的32比特数读入r0,然后r1= r1+r2 */ • str r0, [r1, +r2, LSL #31] /* 把r0(32bit)写到地址r1+(r2<<31) */ • ldr r0, [r1], #+0xfff /* 把r1地址的数读入r0,然后r1=r1+0xfff */ • ldr r0, [r1], +r2 /* 把r1地址的数读入r0,然后r1=r1+r2 */ • ldr r0, [r1], +r2, LSL #31 /* 把r1地址的数读入r0,然后r1=r1+(r2<<31) */ ARM指令集与编程
5.2 第一类指令说明 • 说明 • ldr / str 读/写一个32bit字到/从一个32bit的寄存器,要求读/写地址字对齐。 • ldrb:读一个8bit字节到一个32bit的寄存器,不要求地址对齐,寄存器的高24位清零。 • strb:将寄存器的低8位,写入内存的某个地址。不要求地址对齐。 ARM指令集与编程
5.3 第二类指令 • 语法 • 同第一类指令 • 说明 • ldrh:读取16bit半字到一个32bit寄存器,要求地址半字对齐,目标寄存的高16bit清零。 • strh:将寄存器的低16bit存放到内存中,要求地址半字对齐。 • ldrsh:将内存中的一个16bit半字读到一个32bit寄存器中,要求地址半字对齐。寄存器高16bit根据符号位扩展。 • ldrsb:将内存中的一个8bit字节读到一个32bit寄存器中,寄存器高24bit根据符号位扩展。不要求地址对齐。 ARM指令集与编程
31 28 27 26 25 24 23 22 21 20 19 16 15 12 11 8 7 0 cond 01 I P U B W L Rn Rd 第 2 操作数 0/1 : 立即数(方式1)/寄存器(方式2,3) 0/1 : str/ldr 0/1 : 无/有(!) 0/1 : 后变址/前变址 0/1 : 字/无符号字节 11 0 0/1 : 加/减(第2操作数) 方式1:#immed_12(取值范围0 – 0xfff) 例子:ldr r0, [r1, #+0xfff] #immed_12 11 4 3 0 方式2:Rm 例子:ldr r0, [r1, +r2] 0 0 0 0 0 0 0 0 0 0 Rm 11 7 6 5 4 3 0 方式3:Rm LSL #immed_5(取值范围0-31) 例子:ldr r0, [r1, r2 LSL #31] #immed_5 shift 0 Rm 5.4 前/后变址 ARM指令集与编程
5.4.1 简单的基址寻址 • 基址寄存器数据访问 • str r0, [r1] ldr r2, [r1] ARM指令集与编程