嵌入式体系结构与应用 第三章-ARM指令系统(ARMv4T)
ARM9(ARMv4T)指令系统 ARM汇编程序结构 ARM9指令集 ARM汇编语言伪操作与伪指令 ARM汇编语言与C语言混编程序
ARM汇编程序结构-基本知识(1) 以程序段为单位组织代码,段有名称 段分为代码段和数据段两种 代码段-内容为执行代码 数据段-内容为代码运行时用到的数据 一个汇编程序至少包含一个代码段 多个代码段和数据段在编译链接时生成一个可执行映像文件
ARM汇编语言程序结构-示例 AREA Init, CODE, READONLY 一个代码段:Init 两种指令:汇编指令和伪指令 ENTRY start MOV R0,#0x3FF5000 MOV R1,#0xFF STR R1,[R0] … END 一个代码段:Init 两种指令:汇编指令和伪指令 三种寻址方式:立即、寄存器、寄存器间接
ARM汇编程序结构-什么是伪指令 机器指令—能够直接被处理器识别,执行的指令。汇编指令和机器指令之间为一一对应关系 伪指令—只在汇编编译过程中起作用,为完成程序的汇编做准备,或者汇编编译程序会将伪指令编译为相应的指令 伪指令完成的操作称为伪操作。 即:伪指令是被编译器执行的,而机器指令是由处理器执行的。
ARM汇编程序结构 ——对示例的段定义的说明 AREA Init, CODE, READONLY; 定义名为 Init的段 属性1为CODE-表明为代码段 属性2为READONLY-为只读 段定义伪指令 格式: AREA 段名,属性1,属性2,… EX: AREA BlockData, DATA,READWRITE 一个可执行文件,必须包含至少一个只读代码段,零个或者多个可读/写的数据段。
ARM汇编程序结构 —对程序入口ENTRY的说明 用于指明程序的入口点,供编译链接使用 一个完整的源程序可包含多个源文件 一个完整的源程序至少应有一个ENTRY (有多个ENTRY时,由链接器指定入口) 一个源文件最多只能有一个ENTRY (可以没有ENTRY)
ARM汇编程序结构 —对于汇编语句格式的说明 start MOV R0,#0x3FF5000 汇编语言语句格式: {标号} {指令或伪指令} {;注释} ARM汇编对大小写敏感,对于指令/伪指令,寄存器名称,可全部为大写或小写,但不可大小写混用。 单行语句过长时,可以使用“\”换行,代表下行为此行的续行。 标号顶格书写,所有的指令和伪指令都不能顶格书写。
ARM汇编程序结构 —对源程序结束END的说明 通知汇编编译器,源程序结束 所有的汇编源文件都要以END结束 包括*.INC文件,否则编译器会警告
ARM9指令集 ARM指令格式 ARM寻址方式 ARM指令分类 ARM指令集
ARM指令一般格式 <opcode> {cond}{s} <Rd>,<Rn>{,operand2} s—CPSR修改位,可选 Rd—目的寄存器 Rn—源寄存器,操作数1,仅需一个源时,省略 operand2—源操作数2,多种寻址方式,可选 注:<>内为必须有的,{}内为可选项 E.G ADDS R0,R1,R2
ARM指令的一般格式—条件域 COND – arm指令的条件执行 条件码位于每条ARM指令的前四位,即[31:28] 条件码紧跟助记符后面,由两个字符表示 条件码共有16种,其中1种保留,即使用15种 满足cond要求 指令执行 当前CPSR中的标志位 不满足cond要求 指令不执行
ARM指令一般格式—条件码列表 助记符 条件码 含义 标志位 EQ 0000 相等 Z置位 NE 0001 不相等 Z清零 CS 0010 无符号数≥ C置位 CC 0011 无符号数< C清零 MI 0100 负数 N置位 PL 0101 正数或零 N清零 VS 0110 溢出 V置位 VC 0111 未溢出 V清零
ARM指令集一般格式-条件码列表 助记符 条件码 含义 标志位 HI 1000 无符号数> C置位且Z清零 LS 1001 无符号数≤ GE 1010 带符号数≥ N等于V LT 1011 带符号数< N不等于V GT 1100 带符号数> Z清零且(N等于V) LE 1101 带符号数≤ Z置位或(N不等于V) AL 1110 无条件 无条件执行
ARM指令寻址方式 立即寻址 寄存器寻址 寄存器移位寻址 寄存器间接寻址 new new 基址寻址 多寄存器寻址 堆栈寻址 相对寻址 new
ARM指令寻址方式-说明(1) 立即寻址 寄存器寻址 例:MOV R0, #0xff SUB R0, R0, #&ff; 不能做目的操作数寻址; 12位/8位的立即数,不能超过这个范围 以“#”号作前缀 十六进制表达方式,以“0x”或者“&”表示 操作数位于寄存器中 寄存器寻址方式使用频率高,执行效率高 寄存器寻址 例:MOV RO,R1 SUB R0,R1,R2
ARM指令寻址方式-说明(2) 寄存器移位寻址 例:MOV R0, R1,LSL #2 ------------------------ ADD R2,R1,R1,LSL R3 寄存器移位寻址 ARM指令集特有 桶形移位器实现 Operand2在进行指令指定的操作前 可首先根据移位次数进行移位操作 支持5种移位方式 移位次数可由立即数或者寄存器给出 减少运算复杂度,提高处理速度
ARM指令寻址方式-说明(2)续 寄存器移位寻址 可采用的移位方式包括: LSL:逻辑左移,低位补0 LSR:逻辑右移,高位补0 注:如果指令带有S后缀CPSR的C标志 = 移位操作移出的最后一位 MOVS R0,R1,LSR #3 可采用的移位方式包括: LSL:逻辑左移,低位补0 LSR:逻辑右移,高位补0 ASR:算术右移,高位补符号位 ROR:循环右移,移出的低位补入高位 RRX:带扩展的循环右移,带C位 C ROR RRX
ARM指令寻址方式-说明(3) 寄存器间接寻址 操作数的地址存放在任意一个通用寄存器(R0-R14)中 访存寻址方式 ARM指令集中,只有LOAD和STORE两种可访存 Error! ADD R0,R1,[R0]; 例:LDR R1,[R0] ;将R0指向的内存单元的值取出到R1中 ------------------------------- STR R1,[R0] ;将R1的内容存入R0指向的内存单元中
ARM指令寻址方式-说明(4) 基址寻址方式 访存寻址方式(仅适用于LOAD/STORE类指令) 操作数的地址 = 基址寄存器的内容+偏移量 基址寄存器可以是任意一个通用寄存器 偏移量可以为正也可以为负,通过立即数或寄存器表达 主要用于对连续地址的访问,如数组、查表操作 基址寻址形式: [Rm]{, {-}shift} [Rm{, {-}shift} ] --------------------- Shift形式: #常量表达式 Rx Rx, 移位方式 次数 后索引 前索引 Pre indexing- add offset before transfer; Post indexing – add offset after transfer 立即数 寄存器 寄存器移位
ARM指令寻址方式-说明(4)续 !-决定前索引是否修改基址寄存器的值; 前索引-先基址+偏移量访存,后,修改基址寄存器 LDR R0,[R1,#4] LDR R0,[R1,#4]! LDR R0,[R1],#4 ;[R1+4]->R0 基址修改符‘ ;[R1+4]->R0,R1+4->R1 ;[R1]->R0,R1+4->R1 后索引 前索引-先基址+偏移量访存,后,修改基址寄存器 后索引-先基址访存,后,基址+偏移量修改基址寄存器 !-决定前索引是否修改基址寄存器的值;
ARM指令寻址方式-说明(4)续 基址寻索引方式 LDR R0,[R1,R2] LDR R0,[R1],R2 LDR R0,[R1,R2,LSL #1] LDR R0,[R1,R2,LSL #1]! LDR R0,[R1],-R2, LSL #1 ;[R1+R2]->R0 ;[R1]->R0, R1+R2 ->R1 ;[R1+2*R2]->R0 ;[R1+2*R2]->R0, R1+2*R2->R1 ; [R1]->R0 ; R1-2*R2->R1 访问单位不同,支持的基址寻址形式有差异 字节、半字,不支持偏移量的移位操作 立即数表达的偏移量8位/12位
ARM指令寻址方式-说明(5) 多寄存器寻址方式 堆栈寻址方式 寻址模式-地址的改变方式 通过一条指令,完成存储器与多个寄存器之间的数据交换 LDM XX – 从内存取多个数据至多寄存器 <LDM|STM >{cond}<寻址模式 ><Rn>{!},<{Registers}> {^} STM XX – 将多个寄存器的值存到内存指定位置 寄存器数量为1至16个,范围为所有通用寄存器R0-R15 表达方式: 不连续,逗号分割,如 {R0,R5,R6} 连续,横杠表示之间所有寄存器,如{R0-R14}
ARM指令寻址方式-说明(5) 多寄存器寻址方式 I - Increase D – Decrease A - After Eg. STMIA R0!, {R2-R5} ---------------------------- ; R2->[R0] ; R3->[R0+4] ; R4->[R0+8] ; R5->[R0+12] ; R0+16 ->R0 多寄存器寻址方式 LDM/STM对存储器连续空间的访问 I - Increase D – Decrease A - After B – Before IA - 地址从低到高增长,且先访问,再修改地址 IB – 地址从低到高增长,且先修改地址,再访问 DA - 地址从高到低增长,且先访问,再修改地址 DB – 地址从高到低增长,且先修改地址,再访问
ARM指令寻址方式-说明(6) 堆栈寻址方式 例: LDMFD SP!,{R1-R7,LR} 满递减堆栈,常见堆栈类型 LDMxx – 出栈操作 STM xx – 入栈操作 堆栈-后进先出 栈顶指针 SP– R13 栈顶指针位置 栈生长方向 堆栈类型 满堆栈 (Full) 递增堆栈 (Ascending) 满递增 FA 满递减 FD 空堆栈 (Empty) 递减堆栈 (Dscending) 空递增 EA 空递减 ED
ARM指令寻址方式-说明(6)续 堆栈寻址方式 满递减堆栈FD-压栈操作示意 STMFD SP!,{Rx} 栈增长方向 x y z x y 低地址 x y z x y z x y z SP SP Rx SP 高地址 SP<—SP-4 Rx ->[SP]
ARM寻址方式-说明(6)续 堆栈寻址方式 空递增堆栈EA-出栈操作示意 LDMEA SP!,{Rx} 栈增长方向 x y z x y z 低地址 x y z x y z x y z SP SP SP 高地址 SP<—SP-4 [SP]—>Rx
ARM指令寻址方式-说明(7) 相对寻址方式 PC作为基址寄存器,加上指令中给出的偏移量,得到有效目的地址。 跳转指令B,BL使用了相对寻址 例: BL subr1 BEQ loop … loop MOV R6,#1 subr1 此处,loop和Subr1标号书写错误,出现了大小写不一致问题,供大家思考
ARM指令集-分类 数据处理指令 分支(跳转)指令 程序状态寄存器处理指令 寄存器存储/加载指令 协处理器指令 异常产生指令 共6类
ARM指令集-数据处理指令 goEx 数据处理指令是ARM指令集中包含指令最多的一类。 包括4种类型: 数据传送指令 2条,用于寄存器之间进行数据传送 算术/逻辑指令 10条,算术/逻辑运算,三操作数 比较指令 4条,对两操作数作算术逻辑运算,结果不保存,只修改CPSR 乘法指令 6条,分为结果为32位/64位两种 goEx
----------------------- 恢复pc断点,同时将spsr拷贝回cpsr 特殊用法: ----------------------- 已知X求 –X MVN取反,加1即可 中断返回 MOVS pc ,lr 恢复pc断点,同时将spsr拷贝回cpsr ARM指令集-数据处理指令 数据传送指令 实现立即数、寄存器、寄存器移位到目的寄存器的数据传送 助记符 指令格式 操作 MOV MOV{cond}{s}<Rd>,<operand> Rd=op MVN MVN{cond}{s}<Rd>, <operand> Rd=0xFFFFFFFF xor op Operand可以是立即数、寄存器或寄存器移位寻址方式 MVN指令对operand取反后,传送到目的寄存器 MOV/MVN,在加上后缀“S”后,可根据传送数据影响CPSR标志位 – N、Z、C(如果operand使用移位寻址)
ARM指令集-数据处理指令 算术指令列表 助记符 指令格式 操作 指令格式统一,operand2允许三种寻址方式: ADD ADD{cond}{s}<Rd>,<Rn>,<operand2> Rd=Rn+op2 ADC ADC{cond}{s}<Rd>,<Rn>,<operand2> Rd=Rn+op2+C SUB SUB {cond}{s}<Rd>,<Rn>,<operand2> Rd=Rn-op2 SBC SUC {cond}{s}<Rd>,<Rn>,<operand2> Rd=Rn-op2-1+C RSB RSB{cond}{s}<Rd>,<Rn>,<operand2> Rd=op2-Rn RSC RSC{cond}{s}<Rd>,<Rn>,<operand2> Rd=op2-Rn-1+C 指令格式统一,operand2允许三种寻址方式: 立即数,寄存器,寄存器移位
ARM指令集-指令应用举例 e.g 使用寄存器移位寻址,优化简单乘法 ;r0 = 10 ×r1 e.g 实现两个128位数据的加/减 已知 X, 利用减法求-X e.g 使用寄存器移位寻址,优化简单乘法 ;r0 = 10 ×r1 MOV r0, r1, LSL #3 ADD r0, r0, r1,LSL #1 e.g 实现两个128位数据的加/减 首先将第一个数放在R4,5,6,7中,第二个数放在R8,9,10,11中,结果存放在R0,1,2,3中 ADDS R0,R4,R8 ADCS R1,R5,R9 ADCS R2,R6,R10 ADCS R3,R7,R10 请大家写减法程序段
----------------------- 特殊用法: ----------------------- 对数据的指定位置1 ORR r1,r1, #指定位为1,其余位为0 对数据的指定位清0 BIC r1, r1, #指定位为1,其余位为0 对数据的指定位取反 EOR r1, r1, #指定位为1,其余位为0 ARM指令集-数据处理指令 逻辑指令列表 助记符 指令格式 操作 AND AND{cond}{s}<Rd>,<Rn>,<operand2> Rd=Rn and op2 ORR ORR{cond}{s}<Rd>,<Rn>,<operand2> Rd=Rn or op2 EOR EOR{cond}{s}<Rd>,<Rn>,<operand2> Rd=Rn xor op2 BIC BIC{cond}{s} <Rd>,<Rn>,<operand2> Rd=Rn and (!op2) 寄存器 立即数 寄存器移位 指令格式与算术指令相同,operand2支持三种寻址 逻辑指令,(加上后缀”S”)根据结果影响CPSR的N和Z标志,如果operand2采用寄存器移位寻址,最后移出位进入C,不影响溢出标志位V
ARM指令集-数据处理指令 比较指令列表 只影响CPSR标志 不保存运算结果 助记符 指令格式 操作 TST/TEQ不影响V标志 CMP CMP{cond} <Rn>,<operand> CPRS flag=Rn - op CMN CMN{cond} <Rn>,<operand> CPRS flag=Rn + op TST TST{cond} <Rn>,<operand> CPRS flag=Rn and op TEQ TEQ{cond} <Rn>,<operand> CPRS flag=Rn xor op TST/TEQ不影响V标志 CMP/CMN –C 进位/~借位 TST/TEQ -C op移位,最后移出位 op可以为立即数,寄存器,寄存器移位寻址 通常,CMP指令后,紧跟条件执行的语句/分支转移 CMP和CMN是算术运算,TST和TEQ是逻辑运算,所以这两类指令影响的标志有些差异。
ARM指令集-指令应用举例 求一个数的绝对值,设该数存放在R0中 CMP R0,#0 RSBMI R0,R0,#0 TEQ R0,#0 MVNMI R0,R0 ADD R0,R0,#1 MOVS R1,R0 RSBMI R0,R0,#0 条件码 ,MI- 负数 minus sign 负号 PL- 正数 plus sign 正号
ARM指令集-数据处理指令 乘法指令列表 助记符 指令格式 操作 MUL MUL{cond}{s}<Rd>,<Rm>,<Rs> Rd=Rm*Rs (Rd≠Rm) MLA MLA{cond}{s}<Rd>,<Rm>,<Rs>,<Rn> Rd=Rm*Rs+Rn (Rd≠Rm) UMULL UMULL {cond}{s}<RdLo>,<RdHi>,<Rm>,<Rs> (RdHi,RdLo)= Rm*Rs UMLAL UMLAL{cond}{s} <RdLo>,<RdHi>,<Rm>,<Rs> (RdHi,RdLo)=Rm*Rs+ (RdHi,RdLo) SMULL SMULL{cond}{s} <RdLo>,<RdHi>,<Rm>,<Rs> SMLAL SMLAL{cond}{s} <RdLo>,<RdHi>,<Rm>,<Rs> RdHi,RdLo)=Rm*Rs+ (RdHi,RdLo) multiplication
ARM指令集-数据处理指令(IV) 乘法指令说明 64位乘加溢出测试-无符号 -------------------------- UMULL RdLo,RdHi,Rm,Rn ADDS RdLo,RdLo,Ra1 ADCS RdHi,RdHi,Ra2 BCS overflow ARM指令集-数据处理指令(IV) 乘法指令说明 乘法指令包括两种: ①结果为32位—MUL和MLA ②结果为64位—UMUL和UMLA,SMUL和SMLA 乘法指令对标记位的影响: ①根据结果影响标记位N和Z ②对C的影响无意义,对V无影响 乘法指令所有的操作数只能采用寄存器寻址方式,且不能使用R15 目的寄存器,操作数1不能使用同一寄存器 ①Rd,Rm(MUL,MLA)不能相同 ②RdLo,RdHi,Rm(UMUL,UMLA,SMUL,SMLA)不能相同 32位乘法溢出测试-无符号 -------------------------- UMULL RdLo,RdHi,Rm,Rn TEQ RdHi,#0 BNE overflow 32位乘法溢出测试-有符号 -------------------------- SMULL RdLo,RdHi,Rm,Rn TEQ RdHi,RdLo, ASR #31 BNE overflow
ARM指令集-分支指令 用于改变程序流向和进行子程序调用。共4条: B 跳转指令 BL 带返回的跳转指令 BX 带状态切换的跳转指令 BLX 带状态切换的跳转指令 指令格式: B{<cond>} Label BL{<cond>} Label BX{<cond>} Rm BLX{<cond>} Label | Rm 条件/无条件转移 子程序调用 关于偏移量及寻址方式和指令格式的讲解,需要结合 编码结构图 尤其是BLX的两种格式 BLX Label; BLX<cond> Rm;
ARM指令集-分支指令 指令格式:B(L){cond} Label ;BL指令 … ;B指令 CMP r0,r1 BL func MOVEQ r1,#0 func MOV pc,lr ;B指令 CMP r0,r1 BLS less MOV r2,#1 B next less MOV r2,#0 next … Label标号采用相对寻址,保存的是一个24位的相对于当前PC的偏移量,决定跳转范围±32MB 通过cond条件位,实现各种条件转移 BL与B的区别是,跳转同时,保存当前PC到LR(R14),所以子程序可以利用LR返回 可以使用MOV指令,直接修改PC值,同样实现跳转功能。 问题: 为什么24位偏于量,范围是+- 32MB , +-32MB 26位 因为ARM 强制边界对准,ARM指令地址的最低两位一定为0,所以便宜地址不表示最低两个0 if(r0>r1) r2 = 1; else r2 =0;
ARM指令集-指令应用举例 当R1=5或者R4=9时,跳转到标号Label执行 CMP R1,#5 BEQ Label CMP R4,#9 CMPNE R4,#9 BEQ Label 等价 使用指令条件码
ARM指令集-分支转移BX 指令格式:B(L)X{cond} Rm ADR R0,IntoTHUMB+1 BX R0 CODE16 … MOV R0,BackToARM BX R0 CODE32 BackToARM ARM指令集-分支转移BX 指令格式:B(L)X{cond} Rm BX根据Rm寄存器的内容转移 BX根据Rm的最低位进行状态切换,即: THUMB状态,Rm[0]=1 ARM状态, Rm[0]=0 ADR R0,IntoTHUMB+1 BX R0 CODE16 IntoTHUMB … ADR R0,BackToARM BX R0 CODE32 BackToARM
ARM指令集-指令应用举例 R0的值根据R1的值,分别实现乘4,乘5,乘6 MOV R2,R0,LSL #2 CMP R1,#4 BEQ stop CMP R1,#5 ADDEQ R2,R2,R0 ADDNE R2,R2,R0,LSL#1 stop
ARM指令集—状态寄存器处理指令 状态寄存器处理指令包括以下两条: MRS{<cond>} <Rd>,<PSR> MSR{<cond>} <PSR>,<op> MRS指令:通过该指令,可以将CPSR或者SPSR保存到某一通用寄存器。 MSR指令:通过该指令,可以将通用寄存器或者立即数写入CPSR或者SPSR。 因此,MRS和MSR常配对使用,用于对PSR的读—修改—写序列 注:Rd,op不能使用R15
ARM指令集—状态寄存器处理指令 MSR指令,通过对PSR内容的重新加载,可以修改PSR。 PSR划分为4个域:[31-24]-条件域F [23-16]-状态域S(保留) [15-8]-扩展域X(保留) [7-0]-控制域C MSR CPSR_F,R0;传送R0到CPSR,但只修改条件域 注:①MSR的源操作数可以是寄存器或者立即数 ②用户模式下,只能修改条件域 ③SPSR为当前模式下的SPSR,而USR/SYS模式无SPSR CPSR结构
ARM指令集—状态寄存器处理指令 ③ MRS/MSR使用示例 MRS和MSR示例 MRS R0,CPSR;读 ①用户模式下 MSR CPSR,R0 MSR CPSR_cxsf,R0 ;只能修改条件域 ②特权模式下 MSR CPSR_f,RO ;两者不同 第一条将CPSR全部修改 第二条只修改标志位 ③ MRS/MSR使用示例 MRS R0,CPSR;读 MOV R1,R0 AND R1,R1,#0x1F TEQ R1,#0x10 ;? BICNE R0,R0,#0x1F ORRNE R0,R0,#0x1F; MSR CPSR, R0; 运行模式表 MOV R1,0x13 MSREQ CPSR,R1 也可以用指令 MSREQ CPSR,#0x13代替 练习:控制开/关中断程序段 将运行模式切换至管理模式
ARM指令集—寄存器存储/加载指令 LOAD/STORE类指令 该类为存储器访问指令,包括: 单寄存器加载/存储指令 LDR/STR 唯一的一类 可访存指令 LOAD/STORE类指令 该类为存储器访问指令,包括: 单寄存器加载/存储指令 LDR/STR 多寄存器加载/存储指令 LDM/STM 交换指令 SWP 其中一个操作数为寄存器or寄存器列表,另一个操作数则为访存寻址方式。
ARM指令集—寄存器存储/加载指令 LDR/STR 单寄存器加载/存储 LDR{cond}{B|H|SB|SH}<Rd>,<address_mode> STR{cond}{B|H}<Rd>,<address_mode> 字/字节/半字加载指令LDR 单位:B-字节,H-半字,无后缀-字 加载方式: B – 加载1个字节到寄存器的低位,高位补0 H – 加载2个字节道寄存器的低位,高位补0 SB -加载1个字节到寄存器的低位,高位补符号 SH -加载2个字节到寄存器的低位,高位补符号 当满足相等条件时,执行取半字指令,指令为: LDREQSH R0,[R1]
ARM指令集—寄存器存储/加载指令 LDR/STR 单寄存器加载/存储 STR{cond}{B|H}<Rd>,<address_mode> 字/字节/半字存储指令STR 单位:B-字节,H-半字,无后缀-字 存储方式: B – 将寄存器的最低1个字节存储到指定地址单元 H – 将寄存器的最低2个字节存储到指定地址单元
ARM指令集—寄存器存储/加载指令 LDR/STR 单寄存器加载/存储 操作数2地址形式列举: LDR R1,[R0] 最基本访存地址形式 LDR R1,[R0,#0x12] ① LDR R1,[R0,#-0x12] ② LDR R1,[R0,#0x12]! ③ LDR R1,[R0],#0x12 ④ LDR R1,[R0,R2] ① LDR R1,[R0,-R2] ② LDR R1,[R0,R2]! ③ LDR R1,[R0],R2 ④ LDR R1,[R0,R2,LSL #2] ⑤ 偏移量为立即数 偏移量存放在寄存器中
ARM指令集—寄存器存储/加载指令 LDM/STM 多寄存器加载/存储 LDM{cond}{type}<Rn>{!},<reglist>{^} STM{cond}{type}<Rn>{!},<reglist>{^} 多寄存器存储/加载指令,可将寄存器列表中的多个寄存器到内存的一片连续的区域之间进行数据传送。 多用于堆栈的压栈/出栈操作 注意: ①cond的位置,即LDMEQIA,而不是LDMIAEQ ②当Rn在reglist中时,同时有!后缀,会导致Rn存储和加载的数值不可预知。
ARM指令集—寄存器存储/加载指令 LDM/STM 多寄存器加载/存储 Type类型共8种,用于指示地址变化方式,包括 IA,IB,DA,DB, 四种用于数据块传输 FD,ED,FA,EA, 四种用于堆栈操作 ^后缀,不能用于SYS和USR模式,因为^后缀的作用是,当 LDM(加载)指令中,寄存器列表包含PC时,在加载PC的 同时,恢复SPSR到CPSR,一般用于异常的返回。 例:STMFD R13! ,{R0-R12,R14};STM将寄存器组压入堆栈 LDMFD R13! ,{R0-R12,PC}^;LDM出栈,同时恢复CPSR
ARM指令集—寄存器存储/加载指令 SWP交换指令 (0x0020) = 3; ----------------------- MOV R0,#0x0020; SWP R1,R2,[R0] SWP交换指令 原子操作-常用于信号量操作 SWP{cond}{B}<Rd>,<Rm>,[<Rn>] 该指令,将Rn指向内存的一个单元读入Rd,同时将Rm的值写入Rn指向的内存单元。 当Rm与Rd相同时? 0x0020 Rn 0x0020 Rn 0x0020 0x0024 0x0028 … 3 0x0020 0x0024 0x0028 … 8 7 Rd Rd 3 8 Rm 8 Rm
ARM指令集—寄存器存储/加载指令 SWP交换指令 ------------------- ;SWP 存放信号量的寄存 器,ON/OFF, 信号量 (原子操作,不需要进临 界区) MOV r1, =semphore MOV r2, #ON SWP r3, r2,[r1] 伪代码 ------------------- ;关中断,进入临界区 ;访问信号量(存储器) ;置1(ON),清零(OFF) ;回写信号量(存储器) 开中断,退出临界区 SWP指令,当目的寄存器Rd与Rm为同一寄存器时,实际上,就是将寄存器的值与Rn所指向的内存单元作交换 信号量操作示例: 控制资源互斥访问,检查信号量,如果>0,减一操作,此时需要进入临界区,以防止被破坏。
ARM指令集—协处理器指令 协处理器指令 coproc:协处理器名,标准名P#,#为0~15 opcode:协处理器执行操作的操作码 CR:协处理器中的寄存器 协处理器指令 CDP{cond}<coproc>,<opcode1>,<CRd>,<CRn>,<CRm>,{<opcod2>} 协处理器数据处理 – 在协处理器内部进行数据处理 MCR|MRC {cond}<coproc>,<opcode1>,<Rd>,<CRn>,<CRm>,{<opcod2>} 协处理器寄存器传输 – 寄存器与协处理器内寄存器之间的数据交换 LDC|STC {cond}{L}<coproc>,<CRd>,<Address> 协处理器内存传输 – 从协处理器装载/存储一个内存数据块
ARM指令集—协处理器指令 协处理器数据操作-CDP CDP{cond}<coproc>,<opcode1>,<CRd>,<CRn>,<CRm>,{<opcod2>} 协处理器数据处理 – 在协处理器内部进行数据处理 该指令是否得以操作取决于协处理器,如果协处理器不支持该操作,则产生未定义(UND)异常 如: CDP p15,10,c1,c2,c3; 该操作请求P1协处理器对c2,c3作操作10,结果存放到c1中。
ARM指令集—协处理器指令 协处理器寄存器传送-MCR|MRC MCR{cond}<coproc>,<opcode1>,<Rd>,<CRn>,<CRm>,{<opcod2>} Rd-ARM内核寄存器内容,传送到协处理器寄存器CRn MCR p15,0,Rd,c1,c0,0; 协处理器CP15,使用Rd的内容对c1控制寄存器进行赋值操作 MRC{cond}<coproc>,<opcode1>,<Rd>,<CRn>,<CRm>,{<opcod2>} CRn、CRm协处理器寄存器内容,传送到ARM内核寄存器Rd MRC p15,0,Rd,c1,c0,0; 协处理器CP15的控制寄存器c1的内容传送到Rd中
ARM指令集—协处理器指令 协处理器与存储器数据交换-LDC/STC LDC{cond} <coproc>,<CRd>,<Address> 从内存Address地址读取数据,传送到协处理器CRd寄存器中 LDC p1,c2,table; 从标号table处读取一个数据至协处理器1的c2寄存器 STC{cond}{L}<coproc>,<CRd>,<Address> 将协处理器寄存器CRd内容,存储到内存Address地址单元中 STCEQL p2,c3,[R5,#24]!; 满足相等条件,执行将2号协处理器的c3寄存器中传送至内存,且L表示传送多个数据
ARM指令集-异常产生指令 软中断指令-SWI SWI {cond} SWI_number; 软中断号,最长24b 操作: CPSR模式控制位 = SVC 模式;模式切换 PC = 0x08; 转向向量表中SWI异常向量位置 CPSR_I = 1; 屏蔽普通IRQ中断; LR_SVC = SWI的下一条指令地址;自动保存断点到LR寄存器 SPSR_SVC = CPSR;自动保存CPSR到SPSR寄存器 常用于用户模式(USR)下,进行操作系统的功能调用,软中断号是功能调用号,可以通过指定寄存器传递参数
ARM指令集-异常产生指令 软中断指令-SWI 例程: SWI_handler: STMFD sp!,{r0-r12, lr} ;保护通用寄存器 ; … LDR r10, [lr, #-4]; lr-4为SWI指令地址,取SWI指令到r0 BIC r10,#0xff000000; SWI指令低24位为软中断号 ;… BL service_routine ; 根据软中断号,跳到相应功能入口 LDMFD sp!,{r0-r12,pc}^; 恢复现场,中断返回
附图1-程序状态寄存器意义示图
附1-处理器运行模式控制位值列表 M[4]~M[0] 运行模式 10000 用户USR 10001 快速中断FIQ 10010 外部中断IRQ 10011 管理 SVC 10111 中止 ABT 11011 未定义 UND 11111 系统SYS
附2-- 桶形移位器 In[3] In[2] In[1] In[0] 0= 开关矩阵 Out[3] O[2] O[1] O[0] 左移1位 每根输出线与所有的输入线都有交点,最终输出值取决于移动控制信号控制的开关到底闭合于哪一处,因此支持所有的多位数的左、右移操作。 图示,4位移位器,支持左、右移1-3位。 如果左移1位,控制信号有效,对应开关闭合,Out[1]=In[0],Out[2] =In[1],Out[3] = In[2] ,Out[0]补0。