微机原理与接口技术 第三章 ARM寻址方式与指令系统 主讲人:鞠 雷 山东大学 计算机科学与技术学院 内容提要 ARM编程模型 ARM指令格式和寻址方式 ARM指令集 Thumb指令集 思考题 2 3.3 ARM指令集 3.3.1 数据处理指令 3.3.2 跳转指令 3.3.3 Load/Store指令 3.3.4 程序状态寄存器指令 3.3.5 协处理器指令 3.3.6 异常中断指令 3 3.3.1 数据处理指令 1. MOV数据传送指令 (Move) MOV{<cond>}{S} <Rd>,<op1>; Rd—目的寄存器 op1-寄存器或立即数,若为寄存器可以先移位。 功能:将操作数op1表示的值传送到目的寄存器Rd中。 如果 R15 是目的寄存器,将修改程序计数器或标志。用于返 例如: 指定相同的寄存器来实现 NOP 指令的效果,还可以专门移 回到调用代码,方法是把连接寄存器的内容传送到 R15: 位一个寄存器: MOV R0,#5; R0=5 MOV R0,R1; R0=R1 MOV MOV PC,R0, R14R0; ; ;退出到调用者 R0 = R0... NOP MOV R0,R1,LSL#5; MOVS MOV PC, R0, R14 R0, LSL ;退出到调用者并回复标志位 #3 ; R0 = R0 * 8 R0= R1左移5位 4 Move Immediate Value The data processing instruction format has 12 bits available for operand2 If used directly this would only give a range of 4096 Instead it is used to store 8 bit constants, giving a range of 0 255. These 8 bits can then be rotated right through an even number of positions (i.e. RORs by 0, 2, 4,..30). 4 bits to control the 16 possible ROR rotation numbers This gives a much larger range of constants that can be directly loaded, though some constants will still need to be loaded from memory Move Immediate Value This gives us: 0 - 255 [0 - 0xff] 256,260,264,..,1020 [0x100-0x3fc, step 4, 0x40-0xff ROR 30] 1024,1040,1056,..,4080 [0x400-0xff0, step 16, 0x40-0xff ROR 28] 4096,4160, 4224,..,16320 [0x1000-0x3fc0, step 64, 0x40-0xff ROR 26] These can be loaded using, for example: MOV r0, #0x40, ROR 26 ; => MOV r0, #0x1000 (i.e. 4096) To make this easier, the assembler will convert to this form for us if simply given the required constant: MOV r0, #4096 ; => MOV r0, #0x1000 (i.e. 0x40 ROR 26) MVN数据取反传送指令 2. MVN数据取反传送指令(Move Negative) MVN{<cond>}{S} <Rd>,<op1>; 功能:将op1表示的值按位取反传送到目的寄存器Rd中 (logical negation)。 Rd = !op1 例: MVN R0, R2 ; R0 = !(R2) MVN R0, #0 ; R0 = -1 ? 7 ADD加法指令 3. ADD加法指令(Addition) ADD{<cond>}{S} <Rd>,<Rn>,<op2>; Op2为寄存器或立即数,若为 功能:ADD 将把两个操作数加起来,把结果放置到目的寄 寄存器可以先移位。 存器中。 Rd = Rn + op2 例: ADD R0, R1, #5 ; ADD R0, R1, R2 ; ADD R0, R2, R3, LSL#1 ; R0 = R1 + 5 R0 = R1 + R2 R0 = R2 + (R3 ) X 2 8 ADC带进位加法指令 4. ADC带进位加法指令 (Addition with Carry) ADC{<cond>}{S} <Rd>,<Rn>,<op2>; 功能:将寄存器Rn、操作数op2表示的值以及进位标志位三者相 加,然后把结果存入目的寄存器Rd中。 进位标志值 Rd= Rn + op2 + carry 9 ADC带进位加法指令 下列例子实现两个 64位数的加法运算。 64 位结果: 寄存器 R0、R1;低位存在R0 第一个 64 位数: 寄存器 R2、R3;低位存在R2 第二个 64 位数: 寄存器 R4、R5。低位存在R4 ADDS R0, R2, R4 ; ADC R1, R3, R5 ; 加低位的字 加下一个字,不带进位 注意:相加时,应设置 S 后缀来更改进位标志。 10 SUB减法指令 5. SUB减法指令(Subtraction) SUB{<cond>}{S} <Rd>,<Rn>,<op2>; Op2为寄存器或立即数,若为 功能:SUB 用操作数 Rn 减去操作数 op2,把结果放置 寄存器可以先移位。 到目的寄存器中。 Rd = Rn - op2 例: SUB R0, R1, #5; R0 = R1 - 5 SUB R0, R1, R2; R0 = R1 – R2 SUB R0, R1, R2,LSL#5 ; R0 = R2 - (R2) X 32 11 RSB反向减法指令 6. RSB反向减法指令(Reverse Subtraction) RSB{<cond>}{S} <Rd>,<Rn>,<op2>; Op2为寄存器或立即数,若为 寄存器可以先移位。 功能:SUB 用操作数 op2 减去操作数 Rn,把结果放置 到目的寄存器中 。Rd = op2 – Rn 例: RSB R0, R1, R2 ; R0 = R2 - R1 RSB R0, R1, #256 ; R0 = 256 - R1 RSB R0, R2, R3,LSL#1 ; R0 = (R3 << 1) - R2 12 SBC带借位减法指令 7. SBC带借位减法指令:(Subtraction with Carry) SBC{<cond>}{S} <Rd>,<Rn>,<op2>; 功能:用寄存器Rn的值减去操作数op2表示的值,再减去 进位标志取反的值,然后把结果存入目的寄存器Rd中。 Rd= Rn - op2 - !carry 注意: 减法有借位,carry=0 。 13 SBC带借位减法指令 该指令用于实现超过32位的数的减法。 例如: 第一个64位操作数存放在寄存器R2,R3中;低位存在R2 第二个64位操作数存放在寄存器R4,R5中;低位存在R4 64位结果存放在R0,R1中。 SUBS R0,R2,R4; 低32位相减,S表示结果影响条件 标志位的值 SBC R1,R3,R5; 高32位相减 14 RSC带借位的反向减法指令 8. RSC带借位的反向减法指令(Reverse Subtraction with Carry)( 不要求) RSC{<cond>}{S} <Rd>,<Rn>,<op2>; 功能:同于SBC,但倒换了两个操作数的前后位置。 Rd = op2 - Rn - !carry 例如:第一个64位操作数存放在寄存器R2,R3中; 第二个64位操作数存放在寄存器R4,R5中; 64位结果存放在R0,R1中。低位在R2、R4、R0 SUBS R0,R2,R4; 低32位相减,S表示结果影响 寄存器CPSR的值 RSC R1, R5,R3; 高32位相减(或 SBC R1,R3,R5) 15 MUL32位乘法指令 9.MUL32位乘法指令(Multiplication) MUL{<cond>}{S} <Rd>,<Rn>,<op2>; 功能:MUL 提供 32位整数乘法。该指令根据S标志,决 定操作是否影响CPSR的值,有S影响N、Z位。 Rn和op2的值为32位无符号数, op2 -必须为寄存器。 Rd = Rn * op2 仅保留最低32位 例如: MULS R0,R1,R2; 器CPSR的值 R0=R1×R2,结果影响寄存 16 Using a multiplication instruction to multiply by a constant means first loading the constant into a register and then waiting a number of internal cycles for the instruction to complete. A more optimum solution can often be found by using some combination of MOVs, ADDs, SUBs and RSBs with shifts. Multiplications by a constant equal to a ((power of 2) ± 1) can be done in one cycle. Example: r0 = r1 * 5 Example: r0 = r1 + (r1 * 4) ADD r0, r1, r1, LSL #2 Example: r2 = r3 * 105 Example: r2 = r3 * 15 * 7 Example: r2 = r3 * (16 - 1) * (8 - 1) RSB r2, r3, r3, LSL #4 RSB r2, r2, r2, LSL #3 ; r2 = r3 * 15 ; r2 = r2 * 7 MLA 32位乘加指令 10.MLA 32位乘加指令 (Multiplication with Accumulate) MLA{<cond>}{S} <Rd>,<Rn>,<op2>,<op3>; 功能: MLA 的行为同于 MUL,但它把操作数 3 的值加到结 果上,其中op2,op3必须为寄存器 。 Rd =( Rn * op2) + op3,这在求总和时有用 Rn、op2和op3的值为32位的有符号数或无符号数。 例如: MLA R0,R1,R2,R3; R0=R1×R2+R3 18 ARM中除法的实现 嵌入式计算机CPU运算速度慢尽量避免除法 1. offset=(Offset+increment)%buffer_size; (50cycle) 2. offset+=increment; if(offset>=buffer_size) offset-=buffer_size;(3cycle) ARM中除法的实现 V7之前的ARM处理器:函数形式(如C库函数,20-100 cycles) ARM v7 Cortex-M系列,硬件除法器 (2-12 cycles) Cortex-R系列,硬件除法器 Cortex-A系列,协处理器(VFP,NEON) AND逻辑与指令 11.AND逻辑与指令(logical AND) AND{<cond>}{S} <Rd>,<Rn>,<op2>; 功能:AND 将在两个操作数上按位进行逻辑与,把结果放 置到目的寄存器中; Rd = Rn AND op2。对屏蔽某些位很 有用。 例如: AND R0, R0, #5 ; R0 = 保持 R0 的位 0 和 2,其余位清0 ANDS R0, R0, #0x01 ; 取R0的最低位 21 ORR逻辑或指令 12.ORR逻辑或指令(logical OR) ORR{<cond>}{S} <Rd>,<Rn>,<op2>; 功能:OR 将在两个操作数上按位进行逻辑或,把结果放 置到目的寄存器中,Rd = Rn OR op2 ;对设置特定的位有 用。 例如: ORR R0, R0, #5 ; R0 中的位 0 和 2置1 ,其余位不变 ORR R0, R0, #0x0F; R0低四位置1 MOV R1,R2,LSR #8 ; ORR R3,R1,R2,LSL#8; 注释有错 22 EOR逻辑异或指令 13. EOR逻辑异或指令(logical Exclusive OR) EOR{<cond>}{S} <Rd>,<Rn>,<op2>; 功能:EOR 将在两个操作数上按位进行逻辑异或,把结果放 置到目的寄存器中,Rd = Rn EOR op2 ;对反转特定的位有 用。 例如: EOR R0, R0, #5 ; R0 中的位 0 和 2取反 EOR R1, R1, #x0F; 将R1的低4位取反 EOR R2, R1, R0; EORS R0, R5, #0x01; R0, 并影响标志位z. R2=R1^R0 R5低位变反,结果保存到 23 BIC位清除指令 14.BIC位清除指令(Bit Clear) BIC{<cond>}{S} <Rd>,<Rn>,<op2>; 功能:BIC 是在一个字中清除位的一种方法,与 OR 位设 置是相反的操作。 Rd = Rn AND (!op_2) 操作数2是一个32位位掩码(mask)。掩码中某位为1,则清除 Rn中的此位。掩码中为0的位, Rn中此位保持不变。 BIC R0, R0, #0x5 ; 清除 R0 中的位 0和位2。其余位不变 BIC R1, R1, #0x0F; 清除R1的低四位,其余位不变 BIC R1, R2, R3; R1= R2 AND (!R3) 24 CMP比较指令 15.CMP比较指令 (Compare) CMP{<cond>} <Rn>,<op1>; 功能:将寄存器Rn的值和操作数op1所表示的值进行比较, 根据结果更新CPSR中条件标志位的值,但不储存结果。 status = Rn – op1 操作数op1为寄存器或立即数。 该指令进行一次减法运算,但不存储结果,只更改条件标 志位,后面的指令就可以根据条件标志位来决定是否执行。该 指令不需要显式的指定S后缀来更改状态标志。 CMP R0,#5; 计算R0-5,根据结果设置条件标志位 ADDGT R0,R0,#5; 于,则执行ADDGT指令 如果前次带符号比较结果为大 TST位测试指令 16.TST位测试指令(Test bits) TST{<cond>} <Rn>,<op1>; 功能:将寄存器Rn的值和操作数op1所表示的值按位做逻 辑与操作,根据结果更新CPSR中条件标志位的值,但不储 存结果。用于检查寄存器Rn是否设置了op1中相应的位。 Status = Rn AND op1 操作数 Rn 是要测试的数据字,操作数 op1是一个位掩码。 经过测试后,设置 Zero 标志。不需要指定 S 后缀。 TST R0,#5; TST R0, #0x01; 判断R0的最低位是否为0 TST R1, #0x0F; 判断R1的低4位是否全为0 BEQ 测试R0中第0位和第2位是否为0 equal; 26 3.3.2 跳转指令 B{<cond>} <addr>; 31 28 27 Cond 25 24 23 0 1 0 1 L Offset Link bit 0 = Branch 1 = Branch with link Condition field 功能:B是最简单的跳转指令。遇到一个B指令,ARM处理器 将立即跳转到给定的地址addr,从那里继续执行。 例如: 注意:addr的值是相对当前PC(即寄存器R15) 的值的一个偏 移量;而不是一个绝对地址。它是24位有符号数。实际地址的 值由汇编器来计算 B。addr的值有符号扩展为32位后,左移两 exit; 程序跳转到标号 位,然后与PC值相加,即得到跳转的目的地址。跳转的范围为 exit处 -32M~+32M。 …… exit…… 27 B跳转指令 addr的计算: 0x0000 0000 ADD R0 R1 R2 0x0000 0004 B exit 0x0000 0008 SUB R0 R2 R3 0x0000 000c MOV R4 R0 … 0x0000 001c exit: ADD R0 R1 R4 汇编器计算exit的值: What happens to the following two instructions? 1. In DSP and older RISCs (MIPS,SPARC…): branch delay slot (executed, automatic re-ordered by assembler) 2. In ARM, PowerPC, Alpha: pipeline refill with 3 cycle penalty (not executed) 偏移量 = 0x 0000 001c – 0x0000 0004 - 8 (由于流水线造成) = 0x 0000 0010 exit = 0b 0000 0000 0000 0000 0000 0100 = 0x 000004 实际执行时寻找跳转地址过程: 0x000004 0x000000040x00000010+PC(0x0000000b) BL带返回的跳转指令 2. BL带返回的跳转指令 PC-4 BL{<cond>} <addr>; 功能:同B指令,但BL指令执行跳转操作的同时,还将PC (寄存器R15)的值保存到LR寄存器(寄存器R14)中。该 指令用于实现子程序调用 。程序的返回可通过把LR寄存 器的值复制到PC寄存器中来实现 例如: BL func; 调用子程序func …… func …… MOV R15,R14; 子程序返回 29 分支执行 if (a != 5){ LDR r0 [a] a = a + 1; CMP r0 #5 LDR r0 [a] CMP r0 #5 ADDNE R0 R0 #1 } BEQ Bypass MOV r0 #5 Bypass: a = 5; ADD R0 R0 #1 Bypass: MOV r0 #5 1. 减少指令数量较小的内存占用 2. 更流畅的流水线执行(pipeline refill penalty = 3 cycles when BEQ is executed) 分支执行 if((a==b)&&(c==d)) e++; 假设a, b, c ,d, e已经被分别载入到r0, r1, r2, r3, r4, 执行该程序段最少 需要几条汇编指令? CMP r0,r1 CMPEQ r2,r3 ADDEQ r4,r4,#1 习题及答案 R0,R1带符号数,R2,R3无符号数 R3>R2, 转去EXCEED R1>R0, 转去EXCEED CMP R1, R0; BGT EXCEED; R2= 0,转去EXCEED CMP R3 R2; BHI EXCEED; CMP R2, #0; BEQ ZERO; R0 = R1, 转去EQU CMP R0, R1; BEQ EQU; 总结: 无符号数比较: >= CS, <= CC, > HI, < LS 有符号数比较: >= QE, <= LE , < LT, > GT CPSR中V位的设置 以下4中情况V设为1 (以4位数字运算为例) 正数+正数=负数 (0100+0100=1000) (同时设C=0) 负数+负数=正数 (1000+1001 = 0001) (同时设C=1) 正数-负数=负数 (0111-1111 = 1000)(同时设C=0) 负数-正数=正数 (1011-0111 = 0100) (同时设C=1) 乘法运算? 3.3.3 Load/Store指令 Load/Store指令用于寄存器和内存间数据的传送,Load用于把内 存中的数据装载到寄存器中,而Store则用于把寄存器中的数据 存入内存。 Load/Store指令分为三类: 单一数据传送指令(LDR和STR等); 多数据传送指令(LDM和STM); 数据交换指令(SWP和SWPB)。 34 LDR字数据加载指令 [Rn +偏移/ Rm]所指数据装入后, Rn不变 1.LDR字数据加载指令: LDR Rd,[Rn] ; 把内存中地址为Rn的字数据装入 LDR{<cond>} <Rd>,<addr>; 寄存器Rd中; 功能:把addr所表示的内存地址中的字数据装载到目标寄 LDR Rd,[Rn,Rm] ; 将内存中地址为Rn+Rm的 存器Rd中,同时还可以把合成的有效地址写回到基址寄存 字数据装入寄存器Rd中; 器。 LDR Rd,[Rn,#index] ; 将内存中地址为 Addr寻址方式: Rn+index的字数据装入寄存器Rd中; LDR Rd,[Rn,Rm,LSL#5] ;将内存中地址为Rn+ Rn表示基址寄存器,Rm表示变址寄存器,index表示偏 Rm×32的字数据装入寄存器Rd; 移量(变址),为12位的无符号数。 1、操作数地址为基址加变址,执行后基址不变。 addr: [Rn,Rm] ((Rn)+(Rm))->(Rd);执行后Rn不变 35 LDR字数据加载指令 2、操作数地址为基址加变址,执行后基址改变 addr:[Rn,Rm]! ((Rn)+(Rm))->(Rd); 执行后 (Rn)+(Rm)->(Rn); [Rn +偏移/ Rm]所指数据装入后, Rn= Rn+偏移/ Rm LDR Rd,[Rn,Rm] !; 将内存中地址为Rn+Rm的字数据 装入寄存器Rd,并将新地址Rn+Rm写入Rn; LDR Rd,[Rn,#index] !;将内存中地址为Rn+index的字 数据装入寄存器Rd,并将新地址Rn+index写入Rn; LDR Rd,[Rn,Rm,LSL#5]!;将内存中地址为Rn+ Rm×32的字数据装入寄存器Rd,并将新地址Rn+Rm×32写入 Rn 36 LDR字数据加载指令 3、操作数地址为基址,执行后基址改变 addr:[Rn],Rm ((Rn))-> (Rd);执行后 (Rn)+(Rm)->(Rn); [Rn]所指数据装入后, Rn= Rn+偏移/ Rm LDR Rd,[Rn],Rm ;将内存中地址为Rn的字数据装入寄 存器Rd,并将新地址Rn+Rm写入Rn; LDR Rd,[Rn],#index ;将内存中地址为Rn的字数据装入 寄存器Rd,并将新地址Rn+index写入Rn; LDR Rd,[Rn],Rm,LSL#5;将内存中地址为Rn的字数据 装入寄存器Rd,并将新地址Rn+Rm×32写入Rn。 37 LDR字数据加载指令 LDR R0,[R1,R2,LSL#5]!; ((R1)+(R2) X 32)->R0 ; (R1)+(R2) X 32)-> R1 LDR R1,[R0,#0x12]; ((R0)+(12)->R1 ; (R0)不变 LDR R1, [R0, -R2]; ((R0)-(R2)->R1 ; (R0)不变 LDR R1, [R0] ((R0))->R1 ; (R0)不变 LDR R1, localdata; 直接寻址,localdata为内存变量的符号地址。 (localdata)-> R1 LDR R0, [R1], R2, LSL #2; ((R1))-> R0,执行后 (R1)+(R2) X 4-> R1 MOV R1, #UARTADD; 地址UART ADD装入R1 LDR R0, [R1];将外设端口数据输入到R0 38 STR字数据存储指令 3. STR字数据存储指令: STR{<cond>} <Rd>,<addr>; 地址addr寻址方式同LDR指令。 功能:把寄存器Rd中的字数据(32位)保存到addr所表示的 例如: 内存地址中,同时还可以把合成的有效地址写回到基址寄存 STR R0, [R1,#5]! 器。 STR R2,[R1, #16] STR R0, [R7], #-8 STR R2, [R9, #consta-struc];consta-struc是一个常量表达式, 范围为-4096~4095(12位有符号数) MOV R1, #UARTADD;将外设端口地址UARTADD装入R1中 STR R0, [R1]; 将数据输出到外设端口寄存器中; 39 Effect of endianess The ARM can be set up to access its data in either little or big endian format. Little endian: Least significant byte of a word is stored in bits 0-7 of an addressed word. Big endian: Least significant byte of a word is stored in bits 24-31 of an addressed word. This has no real relevance unless data is stored as words and then accessed in smaller sized quantities (halfwords or bytes). Which byte / halfword is accessed will depend on the endianess of the system involved. Endianess Example r0 = 0x11223344 31 24 23 11 22 16 15 87 33 0 44 STR r0, [r1] 31 24 23 11 22 16 15 87 33 0 31 Memory 44 24 23 44 16 15 33 87 22 0 11 r1 = 0x100 r1 = 0x100 Little-endian Big-endian LDRB r2, [r1] 31 24 23 00 00 16 15 87 00 r2 = 0x44 0 44 31 24 23 00 16 15 00 87 00 r2 = 0x11 0 11 应用举例:(1) 用ARM指令实现x=(a+b)-c: LDR R4, =a; (R4)=a,a为内存变量地址 LDR R0, [R4];((R4))->R0, (a)-> R0 LDR R5, =b; LDR R1, [R5] ; ((R5))->R1, (b)->R1 ADD R3, R0, R1; (a)+(b)->R3 LDR R4, =c LDR R2, [R4] ; ((R4))->R2, (c)->R2 SUB R3, R3, R2; LDR R4, =x STR R3, [R4] a+b-c -> R3 ;(R4)=x ; (a+b)- c存入x变量 42 (2) 用ARM指令实现x=a*(b+c) ADR R4, b; 变量b的地址装入R4中;LDR R4,=b LDR R0, [R4] ;(b)->R0 ADR R4, c LDR ; LDR R4,=c R1, [R4] ; (c)->R1 ADD R2, R0,R1 ;b+c ->R2 ADR R4, a LDR ;LDR R4,=a R0, [R4] ; (a)->R0 MUL R2, R2,R0; (b+c)*a->R2 ADR R4, x STR R2, [R4] ;LDR R4,=x ; (b+c)*a->x 43 批量数据加载/存储指令 内存操作: IA IB DA DB 5. LDM批量数据加载指令: 堆栈操作: FA FD EA ED LDM{<cond>}{<type>} <Rn>{!},<regs>{^}; Rn:保存内存单元的起始地址。 功能:从一片连续的内存单元读取数据到各个寄存器中,内 Regs:寄存器列表,由若干 存单元的起始地址为基址寄存器Rn的值,各个寄存器由寄存 个寄存器组成,寄存器之间 器列表regs表示。该指令一般用于多个寄存器数据的出栈。 以“,”或“-”分隔。 {!}:若选用了此后缀,则当指令执行完毕后,将最后的地 址写入基址寄存器。 ‘^’ 不带^表示用户和系统模式寄存器; 带有^表示异常模式寄存器,此时若LDM包含R15,装载 R15 时恢复 SPSR至CPSR 位。 44 批量数据加载/存储指令 6. STM批量数据存储指令: STM{<cond>}{<type>} <Rn>{!},<regs>{^}; 功能:将各个寄存器的值存入一片连续的内存单元中, 批量数据存储、加载时,低编号寄存器对应低地址存储 内存单元的起始地址为基址寄存器Rn的值,各个寄存器 单元,与寄存器在指令中出现的次序无关。 由寄存器列表regs表示。该指令一般用于多个寄存器数 据的入栈。 45 批量数据加载/存储指令 指令中,type字段有以下几种: 满栈(Full):栈顶存储单元含有有效数据。 4种类型的堆栈 空栈(Empty):栈顶存储单元不含有有效数据。 递增( Aaccumulate ):入栈指针加4,出栈指针减 FD:满递减堆栈;Full decrease 4。 入栈指针先减再入栈,出栈先出指针再加 递减( Decrease ):入栈指针减4,出栈指针加4。 入栈:STMFD R13!,{R0,R1} 出栈:LDMFD R13!,{R2,R3} FA:满递增堆栈;Full accumulate 入栈指针先加再入栈,出栈先出指针再减 入栈:STMFA 出栈:LDMFA ED:空递减堆栈;Empty decrease 入栈先入栈指针再减,出栈指针先加再出栈 EA:空递增堆栈;Empty accumulte 入栈先入栈指针再加,出栈指针先减再出栈 46 批量数据加载/存储指令 指令中,type字段有以下几种: 4种内存操作 IA:STM/LDM每次传送后地址加4;Increase after STMIA R13!,{R0,R1} LDMIA R13!,{R2,R3} IB:STM/LDM每次传送前地址加4;Increase before STMIB R13!,{R0,R1} LDMIB R13!,{R2,R3} DA:STM/LDM每次传送后地址减4;Decrease after STMDA R13!,{R0,R1} LDMDA R13!,{R2,R3} DB:STM/LDM每次传送前地址减4;Decrease before STMIDB LDMDB R13!,{R0,R1} R13!,{R2,R3} 47 批量数据加载/存储指令 IA、IB、DA、DB指定了地址加还是减,是传送前还是传送 后 。例如:LDMIA/IB/DA/DB R13!,{R0-R1,R3};各指令 STMIA/IB/DA/DB 地址变化与 执行完后,结果如图所示: LDMIA/IB/DA/DB 相同. R13 0x12345684 0x123456a0 36338832 0x12345690 14543862 0x1234568c 15548545 0x12345688 54693645 0x12345684 66663333 0x12345680 00008888 0x1234567c 59595959 0x12345678 26262626 LDMIA:每次传送后地址加4; LDMDB:每次传送前地址减4; LDMIB:每次传送前地址加 4; LDMDA:每次传送后地址减4; 15548545 14543862 R3 54693645 15548545 R1 00008888 R3 66663333 54693645 66663333 R0 59595959 R1 00008888 59595959 26262626 内存中的数据 48 R0 批量数据加载/存储指令 FD、ED、FA、和EA指定是满栈还是空栈,是升序栈还是降序 栈,用于堆栈寻址。一个满栈的栈指针指向上次写的最后一 个数据单元,而空栈的栈指针指向第一个空闲单元。一个降 序栈是在内存中反向增长而升序栈在内存中正向增长。如下 图所示,数据以16进制存储。 EA:空递增堆栈; 36338832 FA:满递增堆栈; 0x123456a0 0x123456a0 ED:空递减堆栈; STM入栈 ↑ LDM出栈 ↓ FD:满递减堆栈; 0x123456a0 14543862 0x12345690 STM STM入栈 入栈 ↑ ↓LDM出栈 LDM出栈 ↓↑ 0x12345690 0x12345690 栈指针 ↓LDM出栈 ↑ 15548545 STM入栈 0x1234568c 0x1234568c 0x1234568c 0x12345688 0x12345688 0x12345688 0x12345684 0x12345684 0x12345684 0x12345680 0x12345680 0x12345680 0x1234567c 0x1234567c 0x1234567c 0x12345678 0x12345678 0x12345678 54693645 54693645 66663333 66663333 栈指针 栈指针 栈指针 00008888 59595959 26262626 49 批量数据加载/存储指令 例如:使用LDM/STM进行现场寄存器保护,常在子程序中或异常处理使用: SENDBYTE STMFD SP!,{R0-R7, LR}; 例如: ...... 寄存器入栈 1、STMEA R13!, {R0-R12,PC};将寄存器R0~R12以及程序计数器PC的值 BL DELAY; 调用DELAY子程序 保存到R13指示的堆栈中。 2、使用LDM/STM进行数据复制: DELAY ...... ...... ...... LDR R0,=SrcData; 设置源数据地址 LDMFD SP!,{R0-R7, PC}; 恢复寄存器,并返回 LDR R1,=DstData; 设置目标地址 LDMIA R0, {R2-R9}; 加载8字数据到寄存器R2~R9 STMIA R1, {R2-R9}; 存储寄存器R2~R9到目标地址 50 LDMIA/STMIA LDMIA/STMIA Rn!, {reglist} Rn is the register containing the base address. Rn mustbe in the range r0-r7. reglist is a comma-separated list of low registers or low-register ranges. Usage Registers are loaded stored and in numerical order, with the lowest numbered register at the address initially in Rn. The value in Rn is incremented by 4 times the number of registers in reglist. If Rn is in reglist: for an LDMIA instruction, the final value of Rn is the value loaded, not the incremented address for an STMIA instruction, the value stored for Rn is: – the initial value of Rn if Rn is the lowest-numbered register in reglist – unpredictable otherwise. Incorrect examples LDMIA r3!,{r0,r9} ; high registers not allowed STMIA r5!, {} ; must be at least one register in list STMIA r5!,{r1-r6} ; value stored from r5 is unpredictable 寻址方式对应关系 寻址方式 说明 pop =LDM push =STM FA 递增满 LDMFA LDMDA STMFA STMIB FD 递减满 LDMFD LDMIA STMFD STMDB EA 递增空 LDMEA LDMDB STMEA STMIA ED 递减空 LDMED LDMIB STMED STMDA ARM编译器默认 使用方式 LDM/STM指令格式 LDM/STM指令格式 LDMFD R0! {R1, R5, R2} LDR R1,[R0],#4 LDR R2,[R0],#4 LDR R5,[R0],#4 3.3.6 异常中断指令 ARM处理器支持两条异常中断指令:软件中断指令SWI和断 点中断指令 BKPT。 1. SWI软件中断指令: SWI{条件} 24位的立即数(系统例程类型) ; 功能:产生软件中断,并调用操作系统的例程。 指令中24位的立即数指定系统例程的类型,其他入口 参数通过通用寄存器传递. 例如:SWI 0X05; 该指令用于调用编号为05的系统例程 57 SWI软件中断指令 指定系统例程类型的2种方式: 1、指令中24位的立即数(值为0~16777215之间的整数) 指定用户程序调用系统例程的类型,其参数通过通用寄 存器传递。 MOV R0, #34; 设置子功能号为34,作为入口参数 SWI 12; 调用12号软中断 2、当24位的立即数被忽略时,系统例程类型由寄存器R0 指定,其参数通过其他通用寄存器传递。 MOV R0, #12; 调用12号软中断,类型为12。 MOV R1, #34; 设置子功能号为34 SWI 0; 中断立即数为0,类型由R0指定。 58 BKPT断点中断指令 2. BKPT断点中断指令: BKPT 16位的立即数; 功能:用于产生软件断点中断,以便软件调试时使用。 16位的立即数:额外的断点信息,可有可无。 59 内容提要 ARM编程模型 ARM指令格式和寻址方式 ARM指令集 Thumb指令集 思考题 60 举例 例1:写出执行以下计算的指令序列,其中,X,Y,Z,R,W 均为32位无符号数,两数乘积不超出32位数范围。 (1) ZW-(X+6)-(R+9) (2) Z(W*X)/16 例2: 假定R0、R1中的内容为带符号数,R2、R3中的内容 为无符号数,写出指令实现以下判断: 若R3的内容超过R2的内容,则转去执行EXCEED. 若R1的内容超过R0的内容,则转去执行EXCEED. 若R2的内容等于零,则转去执行ZERO. 若R1的内容和R2的内容相等,则转去执行EQU. 61