1、嵌入式系统原理及应用,第5章计算机科学学院 于山山主讲,2019年3月19日星期二,曲阜师范大学计算机科学学院,2,第5章 ARM指令集和汇编语言程序,本章主要介绍以下内容: ARM指令集的基本特点 与Thumb指令集的区别 与x86处理器的区别 ARM指令格式 ARM寻址方式 ARM指令集分类详解 ARM汇编语言的指示符 ARM汇编语言语句格式 ARM汇编语言程序格式 ARM汇编语句格式和程序格式进阶 ARM汇编语言程序举例,2019年3月19日星期二,曲阜师范大学计算机科学学院,3,5.1 ARM指令集基本特点,指令集的异同点 ARM、Thumb、x86 ARM指令集的语法 ARM指令集的
2、编码格式 指令条件码表 第2操作数,2019年3月19日星期二,曲阜师范大学计算机科学学院,4,ARM指令集和Thumb指令集 的共同点,ARM指令集和Thumb指令集具有以下共同点: 较多的寄存器,可以用于多种用途。 对存储器的访问只能通过Load/Store指令。 两种指令集的差异特征在下页给出,2019年3月19日星期二,曲阜师范大学计算机科学学院,5,ARM指令集和Thumb指令集 的不同点,2019年3月19日星期二,曲阜师范大学计算机科学学院,6,ARM指令集与x86指令集 的主要不同点,ARM指令集 规整指令格式 即:正交指令格式 三地址指令 由指令的附加位决定运算完毕后是否改变
3、状态标志 状态标志位只有4位 有两种指令密度 无整数除法指令 大多数ARM指令都可以条件执行 有适合DSP处理的乘加指令 Load/Store访存体系结构,x86指令集 非规整指令格式 即:非正交指令格式 二地址指令 指令隐含决定运算完毕后是否改变状态标志 状态标志位有6位 单一指令密度 有整数除法指令 专用条件判断指令进行程序分支 没有适合DSP处理的乘加指令 运算指令能够访问存储器,2019年3月19日星期二,曲阜师范大学计算机科学学院,7,ARM指令集的编码格式,2019年3月19日星期二,曲阜师范大学计算机科学学院,8,ARM指令集的语法,一条典型的ARM指令语法如下所示: S , ,
4、 其中:是指令助记符,决定了指令的操作。例如:ADD表示算术加操作指令。 是指令执行的条件,可选项。 S 决定指令的操作是否影响CPSR的值,可选项。表示目标寄存器,必有项。表示包含第1个操作数的寄存器,当仅需要一个源操作数时可省略。表示第2个操作数,可选项。第2操作数有两种格式:#immed_8r,Rm, Shift,2019年3月19日星期二,曲阜师范大学计算机科学学院,9,ARM数据处理指令中 第2操作数的编码格式图解,2019年3月19日星期二,曲阜师范大学计算机科学学院,10,灵活的第2操作数,立即数型 格式: # 也写成#immed_8r #是取值为数字常量的表达式,并不是所有的3
5、2位立即数都是有效的。 有效的立即数很少。它必须由一个8位的立即数循环右移偶数位得到。原因是32位ARM指令中条件码和操作码等占用了一些必要的指令码位,32位立即数无法编码在指令中。 举例: ADD r3, r7, #1020 ;#immed_8r型第2操作数, ;1020是0xFF循环右移30位后生成的32位立即数;推导:1020=0x3FC=0x000003FC,2019年3月19日星期二,曲阜师范大学计算机科学学院,11,灵活的第2操作数(续1),数据处理指令中留给Operand2操作数的编码空间只有12位,需要利用这12位产生32位的立即数。其方法是:把指令最低8位(bit7:0)立即
6、数循环右移偶数次,循环右移次数由2*bit11:8 (bit11:8是Operand2的高4位)指定。 例如:MOV R4, #0x8000000A;其中的立即数#0x8000000A是由8位的0xA8循环右移0x4位得到。 又例如:MOV R4, #0xA0000002;其中的立即数#0xA0000002是由8位的0xA8循环右移0x6位得到。,2019年3月19日星期二,曲阜师范大学计算机科学学院,12,灵活的第2操作数(续2),寄存器移位型 格式:Rm, Rm是第2操作数寄存器,可对它进行移位或循环移位。用来指定移位类型(LSL,LSR,ASR,ROR或RRX)和移位位数。其中移位位数有
7、两种表示方式,一种是5位立即数(#shift),另外一种是位移量寄存器Rs的值。参看下面的例子。例子中的R1是Rm寄存器。 ADD R5, R3, R1, LSL #2 ;R5R3+R1*4 ADD R5, R3, R1, LSL R4 ;R5R3+R1*2R4;R4是Rs寄存器,Rs用于计算右移次数,2019年3月19日星期二,曲阜师范大学计算机科学学院,13,详解第2操作数 # immed_8r,该常数必须对应8位位图,即常数是由一个8位的常数循环右移位偶数位得到。例如: 合法常量:0x3FC、0、0xF0000000、200、0xF0000001。 非法常量:0x1FE、511、0xFF
8、FF、0x1010、0xF0000010。 常数表达式应用举例: MOV R0,#1 ;R0=1 AND R1,R2,#0x0F ;R2与0x0F,结果保存在R1 LDR R0,R1,# 4 SUB R4,R2,#D4000002;该立即数是0xBE循环右移6位;课堂练习此第2操作数,2019年3月19日星期二,曲阜师范大学计算机科学学院,14,详解第2操作数的Rm寄存器(1),RM寄存器通常是存放第2操作数的寄存器 S , ,RM, shift 举例: SUB R1,R1,R2 ; R1(R1R2)MOV PC,R0 ;PCR0,程序跳转到指定地址LDR R0,R1,-R2;读取R1地址上的
9、存储器单元内容并存入R0,;且R1R1R2,后变址偏移AND R0,R5,R2;R2中存放的是第2操作数;该数据属于寄存器方式的第2操作数,2019年3月19日星期二,曲阜师范大学计算机科学学院,15,详解第2操作数的Rm寄存器(2),ADD R0, R0, R0, LSL #2 ;执行结果R0=5*R0 ADD R5, R3, R1, LSL #2 ;R5R3+R1*4 ADD R5, R3, R1, LSL R4 ;R5R3+R1*2R4,2019年3月19日星期二,曲阜师范大学计算机科学学院,16,寄存器移位方式生成的第2操作数 Rm, shift,将寄存器的移位结果作为操作数,但Rm值
10、保存不变,移位方法如下: LSL # n ;逻辑左移n位(1n31),低端空位补0。 LSR # n ;逻辑右移n位(1n32) ,高端空位补0。 ASR # n ;算术右移n位(1n32),保持符号位不变 ROR # n ;循环右移n位(1n31),低端移出位填入高端。 RRX ;带扩展的循环右移1位,第31位用原进位C填入。,2019年3月19日星期二,曲阜师范大学计算机科学学院,17,桶型移位器移位操作:Type Rs,其中,Type为ASR、LSL、LSR和ROR中的一种;Rs为偏移量寄存器,最低8位有效。若其值大于或等于32,则第2个操作数的结果为0(ASR、LSR例外)。 例如MO
11、VS R3, R1, LSL #7 ;R3R1*128,2019年3月19日星期二,曲阜师范大学计算机科学学院,18,寄存器位移方式生成第2操作数 应用举例,ADD R1, R1, R1, LSL # 3 R1=R1*9,因为R1 R1+R1*8。 SUB R1, R1, R2, LSR # 2 R1R1R24,因为R2右移2位相当于R2除以4。 EOR R11, R12, R3, ASR #5 R11= R12(R332)第2操作数是R3的内容除以32,2019年3月19日星期二,曲阜师范大学计算机科学学院,19,寄存器位移方式生成第2操作数 应用举例(续),MOVS R4, R4, LSR
12、 #32C标志更新为R4的位31,R4清零。 注意 R15为处理器的程序计数器PC,一般不要对其进行操作,而且有些指令是不允许使用R15的,如UMULL指令。,2019年3月19日星期二,曲阜师范大学计算机科学学院,20,ARM处理器的CPSR寄存器和SPSR寄存器的位定义格式图解,参看教材第4.2.3节,2019年3月19日星期二,曲阜师范大学计算机科学学院,21,指令条件码表(1),2019年3月19日星期二,曲阜师范大学计算机科学学院,22,指令条件码表(2),2019年3月19日星期二,曲阜师范大学计算机科学学院,23,5.2 ARM处理器寻址方式,寻址方式是根据指令中给出的地址码字段
13、来实现寻找真实操作数地址的方式。 ARM处理器具有8种基本寻址方式,以下列出: 寄存器寻址 - 立即寻址 寄存器偏移寻址 - 寄存器间接寻址 基址寻址 - 多寄存器寻址 堆栈寻址 - 相对寻址,2019年3月19日星期二,曲阜师范大学计算机科学学院,24,寄存器寻址,操作数的值在寄存器中,指令中的地址码字段指出的是寄存器编号,指令执行时直接取出寄存器值来操作。寄存器寻址指令举例如下: MOV R1,R2 ;读取R2的值送到R1 MOV R0,R0 ;R0=R0,相当于无操作 SUB R0,R1,R2 ;R0R1-R2,将R1的值减去R2的值,;结果保存到R0 ADD R0, R1, R2 ;R
14、0R1+R2 ;这条指令将两个寄存器(R1和R2)的内容相加,结果放入第3个寄存器R0中。必须注意写操作数的顺序:第1个是结果寄存器,然后是第一操作数寄存器,最后是第二操作数寄存器。,2019年3月19日星期二,曲阜师范大学计算机科学学院,25,立即寻址,立即寻址指令中的操作码字段后面的地址码部分即是操作数本身。也就是说,数据就包含在指令当中,取出指令也就取出了可以立即使用的操作数(这样的数称为立即数)。立即寻址指令举例如下: SUBS R0,R0,#1 ;R0减1,结果放入R0,并且影响标志位 MOV R0,#0xFF000 ;将十六进制立即数0xFF000装入R0寄存器 立即数要以“#”号
15、为前缀,16进制数值时以“0x”表示。,2019年3月19日星期二,曲阜师范大学计算机科学学院,26,寄存器偏移寻址,寄存器偏移寻址是ARM指令集特有的寻址方式。当第2作数是寄存器偏移方式时,第2个寄存器操作数在与第1操作数结合之前,选择进行移位操作。 寄存器偏移寻址指令举例如下: MOV R0, R2, LSL #3 ; R2的值左移3位,结果放入R0,即R0R28 ANDS R1, R1, R2, LSL R3 ; R2的值左移R3位,然后与R1相“与” ; 结果放入R1,并且影响标志位。 SUB R11, R12, R3, ASR #5 ; R12-R332,然后存入R11。,2019年
16、3月19日星期二,曲阜师范大学计算机科学学院,27,寄存器偏移寻址(续),可采用的移位操作如下: LSL:逻辑左移(Logical Shift Left),低端空出位补0。 LSR:逻辑右移(Logical Shift Right),高端空出位补0。 ASR:算术右移(Arithmetic Shift Right),移位过程中保持符号位不变,即若源操作数为正数,则字的高端空出的位补0;否则补1。 ROR:循环右移(Rotate Right),由字低端移出的位填入字高端空出的位。 RRX:带扩展的循环右移(Rotate Right extended by l place),操作数右移1位,高端空
17、出的位用原C标志值填充。如果指定后缀“S”,则将Rm原值的位0移到进位标志。,2019年3月19日星期二,曲阜师范大学计算机科学学院,28,移位操作示意图,各种移位操作如下图所示:,2019年3月19日星期二,曲阜师范大学计算机科学学院,29,寄存器间接寻址,寄存器间接寻址指令中的地址码给出的是一个通用寄存器的编号,所需的操作数保存在寄存器指定地址的存储单元中,即寄存器为操作数的地址指针。寄存器间接寻址指令举例如下: LDR R1,R2 将R2指向的存储单元的数据读出,保存在R1中。 SWP R1,R1,R2将寄存器R1的值与R2指定的存储单元的内容交换,2019年3月19日星期二,曲阜师范大
18、学计算机科学学院,30,SWP指令操作图解,2019年3月19日星期二,曲阜师范大学计算机科学学院,31,基址寻址,基址寻址就是将基址寄存器的内容与指令中给出的偏移量相加,形成操作数的有效地址。基址寻址用于访问基址附近的存储单元,常用于查表、数组操作、功能部件寄存器访问等。基址寻址指令举例如下: LDR R2,R3,#0x0C ;前变址, 传数前计算地址; 读取R30x0C地址上的存储单元的内容,放入R2。 STR R1,R0,#4! ; R04R1,R0=R04,符号“!”表明指令在完成数据传送后应该更新基址寄存器,否则不更新;属于回写前变址。,2019年3月19日星期二,曲阜师范大学计算机
19、科学学院,32,基址寻址指令举例,LDR R1,R0,R3,LSL #1 ; 前变址,参看教材第125页 ; 将R0R32地址上的存储单元的内容读出,存入R1。 LDR R0,R1,R2,LSL #2! ; 回写前变址; 将内存起始地址为R1+R2*4的字数据读取到R0中,; 同时修改R1,使得:R1=R1+R2*4。 LDR R0, R1, R2!; 回写前变址; 以R1+R2值为地址,访问内存。将该位置的字数据读; 取到R0中,同时修改R1,使得: R1=R1+R2。,2019年3月19日星期二,曲阜师范大学计算机科学学院,33,多寄存器寻址,多寄存器寻址即是一次可传送几个寄存器值,允许一
20、条指令传送16个寄存器的任何子集或所有寄存器。多寄存器寻址指令举例如下: LDMIA R1!,R2R7,R12 ;将R1指向的单元中的数据读出到R2R7、R12中 ;(R1自动增加) , 参看教材第125页表4-21 STMIA R0!,R2R7,R12 ;将寄存器R2R7、R12的值保存到R0指向的存储单元中, ; (R0自动增加) 使用多寄存器寻址指令时,寄存器子集的顺序是按由小到大的顺序排列,连续的寄存器可用“”连接;否则用“,”分隔书写。,2019年3月19日星期二,曲阜师范大学计算机科学学院,34,多寄存器寻址(续1),多寄存器寻址指令举例 LDMIA R1!, R0, R2, R5
21、 ; ;R0R1 ;R2R1+4 ;R5R1+8 ;R1保持自动增值 ;寄存器列表R0, R2, R5与R2, R0, R5等效 多寄存器指令的执行顺序与寄存器列表次序无关,而与寄存器的序号保持一致。,2019年3月19日星期二,曲阜师范大学计算机科学学院,35,多寄存器指令的执行顺序举例1,通过ADS集成开发环境的AXD调试器窗口观察,2019年3月19日星期二,曲阜师范大学计算机科学学院,36,多寄存器指令的执行顺序举例2,通过ADS集成开发环境的AXD调试器窗口观察,2019年3月19日星期二,曲阜师范大学计算机科学学院,37,多寄存器寻址(续2),下面是多寄存器传送指令STM举例如下:
22、 STMIA R0!,R1R7 ;将R1R7的数据保存到存储器中。存储指针在保存第一 ;个值之后增加,增长方向为向上增长 STMIB R0!,R1R7 ;将R1R7的数据保存到存储器中。存储指针在保存第一 ;个值之前增加,增长方向为向上增长 STMDA R0!, R1R7 ;将R1R7的数据保存到存储器中。存储指针在保存第一 ;个值之后增加,增长方向为向下增长 STMDB R0!,R1R7 ;将R1R7的数据保存到存储器中。存储指针在保存第一 ;个值之前增加,增长方向为向下增长,2019年3月19日星期二,曲阜师范大学计算机科学学院,38,堆栈寻址,存储器堆栈可分为两种: 向上生长:向高地址方
23、向生长,称为递增堆栈。 向下生长:向低地址方向生长,称为递减堆栈。 满堆栈 堆栈指针指向最后压入的堆栈的有效数据项 空堆栈 堆栈指针指向下一个待压入数据的空位置,2019年3月19日星期二,曲阜师范大学计算机科学学院,39,堆栈寻址(续1),有4种类型的堆栈组合 满递增:堆栈通过增大存储器的地址向上增长,堆栈指针指向内含有效数据项的最高地址。指令如LDMFA、STMFA等。 空递增:堆栈通过增大存储器的地址向上增长,堆栈指针指向堆栈上的第一个空位置。指令如LDMEA、STMEA等。 满递减:堆栈通过减小存储器的地址向下增长,堆栈指针指向内含有效数据项的最低地址。指令如LDMFD、STMFD等。
24、 空递减:堆栈通过减小存储器的地址向下增长,堆栈指针指向堆栈下的第一个空位置。指令如LDMED、STMED等。,2019年3月19日星期二,曲阜师范大学计算机科学学院,40,堆栈寻址(续2),堆栈寻址指令举例如下: STMFD SP!,R1R7,LR ;将R1R7、LR入栈(push),满递减堆栈。 LDMFD SP!,R1R7,LR ;数据出栈(pop) ,放入R1R7、LR寄存器。 ;满递减堆栈,2019年3月19日星期二,曲阜师范大学计算机科学学院,41,多寄存器传送指令映射表,STM =将寄存器内容存入内存单元(堆栈操作:入栈) LDM=将内存单元内容存入寄存器(堆栈操作:出栈),20
25、19年3月19日星期二,曲阜师范大学计算机科学学院,42,多寄存器传送指令说明,数据块传送: I =向地址增大方向处理数据传送(Increment) D =向地址减小方向处理数据传送(Decrement) A =先传送数据后改变地址(after) B =先改变地址后传送数据(before) 堆栈操作: F =满栈顶指针(full) E =空栈顶指针(empty) A =堆栈向高地址方向增长(ascending stack) D =堆栈向低地址方向增长(decending stack),2019年3月19日星期二,曲阜师范大学计算机科学学院,43,相对寻址是基址寻址的一种变通。由程序计数器PC提
26、供基准地址,指令中的地址码字段作为偏移量,两者相加后得到的地址即为操作数的有效地址。 相对寻址指令举例如下: BL SUBR1 ;保存子程序返回地址 ;调用到SUBR1子程序 BEQ LOOP ;条件跳转到LOOP标号处 LOOP MOV R6,#1 SUBR1,相对寻址,2019年3月19日星期二,曲阜师范大学计算机科学学院,44,相对寻址举例,BL SUBR ;转移到SUBR. SUBR ;子程序入口MOV PC, R14 ;返回,; R14也就是LR,2019年3月19日星期二,曲阜师范大学计算机科学学院,45,5.3 ARM指令集分类详解,ARM指令集大致分为6类:分支指令、Load/
27、Store指令、数据处理指令、程序状态寄存器指令、异常中断指令、协处理器指令。以下分别介绍其中的主要指令。,2019年3月19日星期二,曲阜师范大学计算机科学学院,46,5.3.1 分支指令,ARM有两种方法可以实现程序分支转移。 跳转指令 所谓的长跳转 直接向PC寄存器(R15)中写入目标地址。 ARM跳转指令有以下4种: B 分支指令,语法 Bcond label BL 带链接分支指令 语法:BLcond label BX 分支并可选地交换指令集 语法:BXcond Rm BLX 带链接分支并可选择地交换指令集。 语法:BLXcond label | Rm,2019年3月19日星期二,曲阜
28、师范大学计算机科学学院,47,BL指令举例,BL指令的意义:Branch and Link 示例: bl MyPro ;调用子程序MyPro MyPro ;子程序MyPro本体 mov PC, LR ;将R14的值送入R15,返回,2019年3月19日星期二,曲阜师范大学计算机科学学院,48,BX指令使用举例,通过使用BX指令可以让ARM处理器内核工作状态在ARM状态和Thumb状态之间进行切换。 参看下例: ;从ARM状态转变为Thumb状态LDR R0, =Sub_Routine+1BX R0 ;从Thumb 状态转变为ARM状态LDR R0, =Sub_RoutineBX R0,2019
29、年3月19日星期二,曲阜师范大学计算机科学学院,49,长跳转,直接向PC寄存器写入目标地址值,可以实现4GB地址空间中的任意跳转。 示例: 以下的两条指令实现了4GB地址空间中的子程序调用。 MOV LR, PC ;保存返回地址 MOV R15, #0x00110000 ;无条件转向绝对地址0x110000;此32位立即数地址应满足单字节循环右移偶数次,2019年3月19日星期二,曲阜师范大学计算机科学学院,50,5.3.2 Load/Store指令,Load/Store指令用于在存储器和处理器之间传输数据。Load用于把内存中的数据装载到寄存器,Store指令用于把寄存器中的数据存入内存。
30、共有3种类型的Load/Store指令: 单寄存器传输指令 多寄存器传输指令 交换指令,2019年3月19日星期二,曲阜师范大学计算机科学学院,51,单寄存器传送指令,2019年3月19日星期二,曲阜师范大学计算机科学学院,52,Load/Store指令变址模式,变址模式有四种:零偏移、前变址、后变址、回写前变址 。,2019年3月19日星期二,曲阜师范大学计算机科学学院,53,单寄存器传送指令举例,LDR R2,R3,#0x0C读取R30x0C地址上的一个字数据内容,放入R2。属前变址。参看教材第125页。 STR R1,R0,#4!R04R1,R0=R04,符号“!”表明指令在完成数据传送
31、后应该更新基址寄存器,否则不更新;属回写前变址。 LDR R1,R0,R3,LSL #1将R0R32地址上的存储单元的内容读出,存入R1。属前变址。,2019年3月19日星期二,曲阜师范大学计算机科学学院,54,5.3.3 数据处理指令,ARM数据处理指令大致分为以下6种类型。 数据传送指令 算术运算指令 逻辑运算指令 比较指令 测试指令 乘法指令,2019年3月19日星期二,曲阜师范大学计算机科学学院,55,ARM数据处理指令,ARM数据处理指令大致可分为3类: 数据传送指令(如MOV、MVN); 算术逻辑运算指令(如ADD、SUB、AND); 比较指令(如CMP、TST)。 参见下面的表格
32、 数据处理指令只能对寄存器的内容进行操作。所有ARM数据处理指令均可选择使用S后缀,以影响状态标志。 比较指令CMP、CMN、TST和TEQ不需要后缀S,它们会直接影响状态标志。,2019年3月19日星期二,曲阜师范大学计算机科学学院,56,ARM数据处理指令集,2019年3月19日星期二,曲阜师范大学计算机科学学院,57,ARM数据处理指令集(续),2019年3月19日星期二,曲阜师范大学计算机科学学院,58,乘法指令,ARM7TDMI(-S)具有3232乘法指令、3232乘加指令,3232结果为64位的乘/乘加指令。ARM乘法指令如下表所列。,2019年3月19日星期二,曲阜师范大学计算机
33、科学学院,59,5.3.4 程序状态寄存器指令,读状态寄存器指令MRS 写状态寄存器指令MSR 指令举例 开中断与关中断,2019年3月19日星期二,曲阜师范大学计算机科学学院,60,读状态寄存器指令MRS,在ARM处理器中,只有MRS指令可以将状态寄存器CPSR或SPSR读出到通用寄存器中。 指令格式如下: MRScond Rd,psr 其中: Rd 目标寄存器。Rd不允许为R15。 psr CPSR或SPSR。 指令举例如下: MRS R1,CPSR ;将CPSR状态寄存器读取,保存到R1中。 MRS R2,SPSR ;将SPSR状态寄存器读取,保存到R2中。,2019年3月19日星期二,
34、曲阜师范大学计算机科学学院,61,写状态寄存器指令MSR,在ARM处理器中,只有MSR指令可以直接设置状态寄存器CPSR或SPSR。 指令格式如下: MSRcond psr_fields,#immed_8r MSRcond psr_fields,Rm 其中: psr CPSR或SPSR。 fields 指定传送的区域。,2019年3月19日星期二,曲阜师范大学计算机科学学院,62,写状态寄存器指令MSR(续),fields可以是以下的一种或多种;(字母必须为小写);c 控制域屏蔽字节 (psr70);x 扩展域屏蔽字节 (psr158); s 状态域屏蔽字节 (psr2316);f 标志域屏蔽
35、字节 (psr3124)。 immed_8r 要传送到状态寄存器指定域的立即数,8位。 Rm 要传送到状态寄存器指定域的数据的源寄存器。,2019年3月19日星期二,曲阜师范大学计算机科学学院,63,MSR指令举例,MSR指令举例如下:MSR CPSR_c,#0xD3 ;CPSR70=0xD3,即切换到管理模式,0b11010011MSR CPSR_cxsf,R3 ;CPSR=R3,2019年3月19日星期二,曲阜师范大学计算机科学学院,64,使能IRQ中断(开中断),ENABLE_IRQMRS R0, CPSRBIC R0, R0, #0x80MSR CPSR_c, R0MOV PC, LR
36、,I位=0 开中断,2019年3月19日星期二,曲阜师范大学计算机科学学院,65,禁能IRQ中断(关中断),DISABLE_IRQ MRS R0 CPSRORR R0, R0, #0x80MSR CPSR_c, R0MOV PC, LR,I位=1 关中断,2019年3月19日星期二,曲阜师范大学计算机科学学院,66,MSR指令说明,程序中不能通过MSR指令直接修改CPSR中的T控制位来实现ARM状态/Thumb状态的切换,必须使用BX指令完成处理器状态的切换(因为BX指令属分支指令,它会打断流水线状态,实现处理器状态切换)。 MRS与MSR配合使用,实现CPSR或SPSR寄存器的读一修改一写操
37、作,可用来进行处理器模式切换、允许/禁止IRQ/FIQ中断等设置,如下面的程序清单所示。,2019年3月19日星期二,曲阜师范大学计算机科学学院,67,堆栈指令初始化,INITSTACK MOV R0,LR ;保存返回地址 MSR CPSR_c,#0xD3 LDR SP,StackSvc ;设置管理模式堆栈,M4:0=0b10011 MSR CPSR_c,#0xD2 LDR SP,StackIrq ;设置中断模式堆栈,M4:0=0b10010 MOV PC,R0,2019年3月19日星期二,曲阜师范大学计算机科学学院,68,5.3.5 软中断指令SWI,SWI指令用于产生软中断,从而实现从用户
38、模式变换到管理模式,CPSR保存到管理模式的SPSR中,执行转移到SWI向量。在其它模式下也可使用SWI指令,处理器同样地切换到管理模式。 指令格式如下: SWIcond immed_24 / Thumb指令是 immed_8 其中: immed_24是24位立即数,值为016,777,215之间的整数。立即数用于指定指令请求的具体SWI服务。 指令举例如下: SWI 0 ;软中断,中断立即数为0 SWI 0x123456 ;软中断,中断立即数为0x123456,2019年3月19日星期二,曲阜师范大学计算机科学学院,69,获得SWI指令的立即数,在SWI异常中断处理程序中,取出SWI立即数的
39、步骤为:首先确定引起软中断的SWI指令是ARM指令还是Thumb指令,这可通过对SPSR访问得到; 然后取得该SWI指令的地址,这可通过访问LR寄存器得到; 接着读出指令,分解出立即数。 程序清单如下所示。,2019年3月19日星期二,曲阜师范大学计算机科学学院,70,获得SWI指令的立即数(续),T_bit EQU 0x20 SWI_HandlerSTMFD SP!,R0R3,R12,LR ;现场保护MRS R0,SPSR ;读取SPSRSTMFD SP!,R0 ;保存SPSRTST R0,#T_bit ;测试T标志位,CPSR第M5位;T=1表明执行Thumb指令,参看讲义上集91页LDR
40、EQH R0,LR,#2 ;若是Thumb指令,则读取指令码(16位)BICEQ R0,R0,#0xFF00 ;取得Thumb指令的8位立即数LDRNE R0,LR,#4 ;若是ARM指令,则读取指令码(32位)BICNE R0, R0, #0xFF000000 ;取得ARM指令的24位立即数LDMFD SP!, R0R3,R12, PC ;SWI异常中断返回,2019年3月19日星期二,曲阜师范大学计算机科学学院,71,5.3.6 ARM协处理器指令,ARM支持协处理器操作。协处理器控制通过协处理器命令实现。,2019年3月19日星期二,曲阜师范大学计算机科学学院,72,ARM协处理器指令(
41、续),2019年3月19日星期二,曲阜师范大学计算机科学学院,73,5.3.7 ARM伪指令,ARM伪指令不是ARM指令集中的指令,只是为了编程方便编译器定义了伪指令。可以像其它ARM指令一样使用伪指令,但在编译时这些指令将被等效的ARM指令代替。 ARM伪指令有4条,分别为ADR伪指令、ADRL伪指令、LDR伪指令和NOP伪指令。,2019年3月19日星期二,曲阜师范大学计算机科学学院,74,ADR伪指令,小范围的地址读取伪指令 该指令将基于PC的地址值或者基于寄存器的地址值读取到寄存器中 语法: ADR register, expr 其中,register为目标寄存器。expr为基于PC或
42、者基于寄存器的地址表达式,其取值范围如下: 当地址值不是字对齐时,其取值范围为-255255。 当地址值是字对齐时,其取值范围为-10201020。 当地址值是16字节对齐时,其取值范围将更大。,2019年3月19日星期二,曲阜师范大学计算机科学学院,75,ADR伪指令使用举例,下面是一个使用ADR伪指令的例子: start MOV R0, #1000ADR R4, start ; 案例ARM处理器是三级流水线,PC值为当前指令地址值加8字节 ; 因此本ADR伪指令将被编译器替换成机器指令 ; SUB R4, PC, #0xC,2019年3月19日星期二,曲阜师范大学计算机科学学院,76,AD
43、RL伪指令,中等范围的地址读取伪指令。该指令将基于PC或基于寄存器的地址值读取到寄存器中。ADRL伪指令比ADR伪指令可以读取更大范围的地址。 ADRL伪指令在汇编时被编译器替换成两条指令。,2019年3月19日星期二,曲阜师范大学计算机科学学院,77,ADRL伪指令语法,语法: ADRL register, expr 其中,register为目标寄存器。expr为基于PC或者基于寄存器的地址表达式,其取值范围如下: 当地址值不是字对齐时 其取值范围为-64KB64KB。 当地址值是字对齐时 其取值范围为-256KB256KB。 当地址值是16字节对齐时 其取值范围将更大。,2019年3月19
44、日星期二,曲阜师范大学计算机科学学院,78,ADRL指示符的代码范例,2019年3月19日星期二,曲阜师范大学计算机科学学院,79,空操作伪指令NOP,NOP伪指令在汇编时将会被替代成ARM中的空操作,比如可能为“MOV R0,R0“指令等。 伪指令格式如下: NOP,2019年3月19日星期二,曲阜师范大学计算机科学学院,80,NOP指令的用法,NOP可用于延时操作,如下面的程序清单所示。 软件延时程序清单 DELAY1 NOP NOP NOP SUBS R1, R1,#1 BNE DELAY1 ,2019年3月19日星期二,曲阜师范大学计算机科学学院,81,大范围地址读取伪指令LDR,LD
45、R伪指令用于加载32位的立即数或一个地址值到指定寄存器。 在汇编编译源程序时,LDR伪指令被编译器替换成一条合适的指令。 若加载的常数未超出MOV或MVN的范围,则使用MOV或MVN指令代替该LDR伪指令; 否则汇编器将常量放入文字池,并使用一条程序相对偏移的LDR指令从文字池读出常量。 与ARM存储器访问指令的LDR相比,伪指令的LDR的参数有“”符号。,2019年3月19日星期二,曲阜师范大学计算机科学学院,82,伪指令LDR格式,伪指令格式如下: LDRcond register,expr/labelexpr 其中: register 加载的目标寄存器。 expr 32位立即数。 Lab
46、elexpr 基于PC的地址表达式或外部表达式。,2019年3月19日星期二,曲阜师范大学计算机科学学院,83,伪指令LDR举例,LDR伪指令举例如下: LDR R0,0x12345678 ;加载32位立即数0x12345678 LDR R0,=DATA_BUF60 ;加载DATA_BUF地址60 LTORG ;声明文字池 ,2019年3月19日星期二,曲阜师范大学计算机科学学院,84,加载32位立即数程序举例,伪指令LDR常用于加载芯片外围功能部件的寄存器地址(32位立即数),以实现各种控制操作,如下面的程序清单所示。 LDR R0,=IOPIN ;加载寄存器IOPIN的地址 LDR R1,R0 ;读取IOPIN寄存器的值 LDR R0,IOSET LDR R1,=0x00500500 STR R1,R0 ;IOSET=0x00500500,2019年3月19日星期二,曲阜师范大学计算机科学学院,85,谢谢大家! 欢迎大家提出宝贵意见和建议!,