嵌入式期末复习--day3(第三章 ARM指令系统)

如有错误,欢迎指正~

目录

一、知识点总结

1、ARM的指令分类及格式

(1)ARM指令分类

(2)ARM指令格式

(3)条件码

2、ARM指令寻址方式

(1)寄存器寻址

(2)立即寻址

(3)寄存器移位寻址

(4)寄存器间接寻址

(5)变址寻址

1)前变址方式

2)自动变址方式

3)后变址方式

(6)多寄存器寻址

(7)堆栈寻址

(8)块复制寻址

(9)相对寻址

3、常用ARM指令

(1)数据处理指令(除比较指令,其余均可加S)

1)数据传送指令

2)算术运算指令

3)逻辑运算指令

4)比较指令(没有Rd,只用作更新条件标志位N、Z、C、V,所以不用加S)

5)乘法指令

(2)程序(PSR)访问指令

1)读状态寄存器指令

2)写状态寄存器指令

(3)分支指令

1)转移指令

2)带链接的转移指令

3)带状态切换的转移指令

4)BLX指令

(4)访存指令

1)单数据访存

2)多数据访存

3)数据交换访存

(5)异常指令

(6)协处理器指令

4、ARM汇编伪指令与伪操作

(1)ARM汇编伪指令

(2)ARM汇编伪操作

1)符号定义伪操作

2)数据定义伪操作

3)汇编控制常用伪操作

4)其他常用伪操作

二、课后习题

1、ARM指令的寻址方式有几种?试分别举例说明。

2、ARM指令的条件码有多少个?默认条件码是什么?

3、ARM指令中的第二操作数有哪几种形式?试举例说明。

4、在ARM汇编程序如何实现子程序的调用和返回?试举例说明。

5、汇编程序设计中常用的伪操作有哪几类?各有什么作用?

6、试编写实现2+4+6+8+……+100的汇编程序,并在ADS1.2或MDK环境下调试运行。


一、知识点总结

1、ARM的指令分类及格式

(1)ARM指令分类

        ARM指令可分为6种:数据处理指令、程序状态访问指令、分支指令、访存指令、异常指令、协处理器指令。

(2)ARM指令格式

格式以数据处理指令为例:
        

 书写格式也以数据处理指令为例:

        <操作码>{<条件码>}{s} <目标寄存器或编码>,<第一操作数或编码>,<第二操作数>{<;注释>}

其中<>中的为必需的,{}为可选的。

(3)条件码

条件码一共有16种,如下表所示:
 

指令条件码
条件码助记符含义标志
0000EQ相等Z=1
0001NE不相等Z=0
0010CS/HS无符号大于或等于C=1
0011CC/LO无符号小于C=0
0100MI负数N=1
0101PL非负数N=0
0110VS溢出V=1
0111VC没有溢出V=0
1000HL无符号大于C=1且Z=0
1001LS无符号小于或等于C=0或Z=1
1010GE有符号大于或等于N=V
1011LT有符号小于N!=V
1100GT有符号大于Z=0且N=V
1101LE有符号小于或等于Z=1或N!=V
1110AL无条件执行任意
1111保留v5以下版本总执行,v5及以上版本有用

2、ARM指令寻址方式

(1)寄存器寻址

        指令中给出的是操作数所在的寄存器编号。

例:mov r0,r1  

(2)立即寻址

        指令中给出的就是操作数本身(立即数要以#为前缀)。

例:mov r0,#0

这里的立即数并不是任意的数,要作为立即数也要判断一下是否合法,那么该如何去判断呢?

结合老师讲的,总结下来就是:判断里面的二进制数是否<=8位,这8位数可能不是连起来的,但是只要是能够向右移动偶数位从而得到8位数,即可。

也可以总结为:

  1. 判断里面的二进制数是否<=8位
  • 若<8位,则合法。
  • 若=8位,则判断最左侧的1在奇数位还是偶数位,若为奇数位,则不合法;若为偶数位,则合法。
  • 若>8,则不合法。

例1:0x0103C000

因为要判断的是二进制数,所以将上面给出的十六进制数转换为二进制数,则为:
0000 0001 0000 0011 1100 0000 0000 0000

分析上面的数,发现有效位超过8位,所以这个立即数一定不合法

例2:0x102

将该数转为二进制为:0001 0000 0010

分析上面的数,发现有效位数为8位但无法通过移动偶数位使其8位数作为最后的8位(或者可以理解为有效位数在奇数位)(因为对于该数,若要补充位32位,那么应该往前面填充,要求是移动偶数位,后面只有一个0,无法移动,所以并不满足条件)

所以,这个立即数也是不合法的。

例3:0x104

将该数转为二进制为:0001 0000 0100

分析上面的数,发现有效位小于8位,所以这个立即数合法

那么,既然合法,就应该能向右移动偶数位,得到8位图(ARM中立即数又称8位位图),得到的数是多少呢?

  • 右移两位,可以得到,0000 0100 0001,即0x41

例4:0x3680

将该数转换为二进制,为:0011 0110 1000 0000

  • 右移6位,得到0000 0000 1101 1010,即0xDA

(3)寄存器移位寻址

        ARM指令集特有的寻址方式。首先将第二操作数按要求进行移位操作,然后在进行寄存器寻址,这里的移位位数可以是立即数,也可以是寄存器方式。

ARM中常用的移位操作指令如下(图片来自百度搜索):

  1. 算数右移ASR:该操作数为带符号数,移位操作不变符号。所以,当移位操作数为正数时,寄存器的高端位补0;为负数时,寄存器的低端位补1。
  2. 逻辑左移LSL:寄存器中的高端位送至C标志位,低端补0。
  3. 逻辑右移LSR:寄存器中的低端位送至C标志位,高端补0。
  4. 循环右移ROR:寄存器低端移出的位填入到寄存器高端的空出位上(a图)。
  5. 扩展的循环右移RRX:进行带进位位的循环右移(d图)。与循环右移的区别就是,带C一起移。

  1. mov r0,r1,LSL #3   ;LSL为逻辑左移,即先将r1循环左移三位(左移乘以2的相应次方,右移除以二的相应次方,所以这里是*2的3次方,即*8),然后将r1的值给r0。
  2. mov r0,r1,ROR r2  ;ROR为循环右移,即先将r1中的值循环右移r2中的值位,然后将r1的值给r0。

(4)寄存器间接寻址

        指令中给出的为寄存器的编号,而该编号下的寄存器里存放的是操作数所在的地址,而不是操作数,通过该地址,可以找到相应的操作数。

:LDR R0,[R1]     ;[R1]→R0

(5)变址寻址

        就是将基址寄存器的内容与指令中给出的偏移量相加,形成操作数的有效地址。寄存器间接寻址是偏移量为0的基址加便宜寻址。

有3种加偏移量(偏移地址)的变址寻址方式。

1)前变址方式

        先将基地址加上偏移地址,然后在进行指令指定的操作。

: LDR R0,[R1,#4]   ;将R1寄存器中的值(作为地址)加上偏移量#4,然后从得到的地址处加载一个32位数据到R0寄存器中

2)自动变址方式

       先执行前变址的操作,然后再自动修改基址寄存器。

例:LDR R0,[R1,#4] !

!表示写回或更新基址寄存器。

3)后变址方式

        先进行指令指定的操作,再将及地址加上偏移地址。

: LDR R0,[R1] ,#4   ;将R1中的地址处加载一个32位数据到R0寄存器中,然后将R1寄存器中的值(作为地址)加上偏移量#4

(6)多寄存器寻址

        一条指令传送多个寄存器的值。

:LDM R1,{R0,R2,R5} ;将R1所指的连续的3个存储单元中的内容分别送到R0,R2,R5中。

(7)堆栈寻址

        堆栈是一种按照顺序进行存取的存储区。

堆栈可以分为两种:递增堆栈(地址向高地址方向生长)和递减堆栈(地址向低地址方向生长)。

根据SP指向的位置,又可以分为满堆栈(SP指向最后压入的有效数据单元)和空堆栈(SP指向最后压入的有效数据单元的下一个空单元)。

ARM处理器支持4中堆栈工作模式:

  • 满递增堆栈FA:SP指向最后压入的数据单元,且有低地址向高地址生成。
  • 满递减堆栈FD:SP指向最后压入的数据单元,且有高地址向低地址生成。
  • 空递增堆栈EA:SP指向下一个将要存放数据的空单元,且由低地址向高地址生成。
  • 空递减堆栈ED:SP指向下一个将要存放数据的空单元,且由高地址向低地址生成。

:STMFD sp!,{r4-r7,lr}  ;将r4~r7、lr入栈,满递减堆栈

        LDMFD sp!,{r4-r7,pc}   ;数据出栈,放入r4~r7、pc中。

在使用满递减堆栈时,STMFD相当于STMFD

(8)块复制寻址

     把存储器中的一个数据块加载到多个多个寄存器中,或者是把多个寄存器中的内容保存到存储器中。

  • IA:先传后加4
  • IB:先加4后传
  • DA:先传后减4
  • DB:先减4后传

例:STMIA r10,{r0,r1,r4}

(9)相对寻址

        与基址变址寻址方式相类似,相对寻址以程序计数器PC的当前值(R15中的值)为基地址,指令中的地址标号作为偏移量,将两者相加后得到操作数有效地址

3、常用ARM指令

(1)数据处理指令(除比较指令,其余均可加S)

1)数据传送指令
  • mov     mov{<cond>}{S} rd,operand2
  • mvn:先取反后传送
2)算术运算指令
  • ADD:加    ADD{<cond>}{S} Rd,Rn,Operand2
  • SUB:减
  • RSB:逆向减法   例:RSB R1,R2,R3   ;R3-R2的值传送给R1
  • ADC:带进位加法
  • SBC:带借位减法
  • RSC:带借位逆向减法

注意:后有S,那么根据运算结果更新标志N,Z,C,V

若R15作Rn使用,则使用的值是当前指令的地址加8

若R15作Rd使用,则执行完指令后,程序将转移到结果对应的地址处,若还有S,则将CPSR的值复制到SPSR。利用该特性从异常返回。

再有寄存器控制移位的任何数据处理指令中,不能将R15作为任何操作数来使用。

3)逻辑运算指令
  • AND:与
  • ORR:或
  • EOR:异或
  • BIC:位清除  BIC{<cond>}{S} Rd,Rn,Operand2  ;Rn&(not Operand2)的结果给Rd

注意:若加有后缀S,这些指令执行完后将根据结果更新标志N和Z,在计算operand2时会更新标志C,不影响V。

4)比较指令(没有Rd,只用作更新条件标志位N、Z、C、V,所以不用加S)
  • CMP:比较    CMP{<cond>}  Rn,operand2
  • CMN:负数比较
  • TST:位测试,Rn和operand2的各位按位与。常与条件码EQ,NE配合使用,测试位均为0,EQ有效,否则,NE有效。
  • TEQ:相等测试,Rn和operand2的各位按位异或。与EORS的区别在于,TEQ不保存运算结果。常与条件码EQ,NE配合使用,两个数据相等,EQ有效,否则,NE有效。
5)乘法指令

ARM有两类乘法指令:32位的乘法指令(乘法操作为32位)和64位的乘法指令。

例:MUL R1,R2,R3      ;R1=R2*R3

MLA R1,R2,R3,R0           ;R1=R2*R3+R0

UMULL R0,R1,R5,R8       ;R5*R8→(R1,R0)

(2)程序(PSR)访问指令

1)读状态寄存器指令
        M RS{<cond>} Rd,psr    ;Rd不允许为R15,psr为CPSR或SPSR
2)写状态寄存器指令
        M SR{<cond>} psr_fields,Rd/#immed       ;fields为指定的传送区域,可以是c,x,s,f中的一种或多种且字母为小写。c表控制域(即psr[7……0]),x,s均暂未使用,f表标志位域(即psr[31……24])。
修改状态寄存器一般是通过“读取-修改-写回”3个步骤实现的,即先使用MRS读,再使用前面学过的指令修改,最后使用MSR写回。
注意:只有再特权模式下才能修改状态寄存器的控制域psr[7……0],以实现处理器模式转换,或设置开/关异常中断。
        对于T控制位,不能通过MSR指令直接修改以实现工作状态的转换,必须使用BX指令完成。
        用户模式下只能修改“标志位域”,不能对CPSR[23:0]做修改。

(3)分支指令

1)转移指令

        B{<cond>} label        ;默认为无条件跳转,跳转限制在当前指令的+-32MB的范围内。

2)带链接的转移指令

        BL{<cond>} label      ;将BL下一条指令给LR,label给PC。常用于子程序的调用。

3)带状态切换的转移指令

        BX{cond} Rm   ;Rm&0xfffffffe,T=Rm[0]&1

        这个转移指令是为了进行工作状态的切换。若当前为ARM状态,则将T标志位置1,转为 Thumb状态;若当前状态为Thumb,则将T标志位置0,转为ARM状态。详细的解释我也不是很懂,这样理解应该足够了。

还有一个是书上没有,但是老师提到的。

4)BLX指令

        BLX  目标地址

  • 如果目标地址的最低位(T位)为0,BLX指令将转移到ARM状态下的地址,并将下一条指令的地址保存在LR寄存器中。
  • 如果目标地址的最低位(T位)为1,BLX指令将转移到Thumb状态下的地址,并将下一条指令的地址保存在LR寄存器中。

总结一下,BLX指令在ARM处理器中用于实现带链接的分支跳转,并且可以根据目标地址的状态位(T位)自动切换ARM状态或Thumb状态。

(4)访存指令

1)单数据访存

        在ARM指令中,读指令又叫加载指令,是从存储器到寄存器;写指令又叫存储指令,是从寄存器到存储器。

第一类用于存储或加载字、无符号字节。

  • LDR:加载字数据
  • LDRB:加载无符号字数据
  • LDRT:以用户模式加载字数据
  • LDRBT:以用户模式加载无符号字数据
  • STR :存储字数据       
  • STRB:存储无符号字数据
  • STRT:以用户模式存储字数据
  • STRBT:以用户模式存储无符号字数据

带T后缀说明:处于特权模式,存储系统也会看作是用户模式下;

        用于存储器保护;

        不能与前变址寻址、自动变址寻址一起使用;

        在用户模式下无效。

LDR/STR属于变址寻址。

第二类是指加载或存储无符号半字,加载有符号半字、有符号字节。

  • LDRH:加载无符号半字
  • STRH:存储无符号半字
  • LDRSB:加载有符号字节
  • LDRSH:加载有符号半字
2)多数据访存

可以实现一组(1~16)寄存器和一块(4~64字节)连续内存单元之间的数据传输。

LDM|STM{<cond>}<type>  <Rn>{!},<Regs>{^}

type表类型,用于数据的存储与加载时有一下4种方式:

  • IA:事后递增(每次传送后地址值增加)
  • IB:先增
  • DA:后减
  • DB:先减

用于堆栈操作时有以下4种方式:

  • FD:满递减堆栈
  • ED:空递减堆栈
  • FA:满递增堆栈
  • EA:空递增堆栈

{^}为可选后缀,当指令为LDM且寄存器列表包含PC,表除了正常的多寄存器传送外,还要将SPSR复制到CPSR中,;当不包含时,加载/存储的是用户模式的寄存器,而非当前模式。

        LDM/STM指令寻址是按字对齐的,即忽略地址为[1:0]。LDM/STM用途是现场保护、数据复制和参数传送等。

3)数据交换访存
  •  SWP:字数据交换指令 ,SWP{<cond>}{S} Rd,Rm,[Rn],实现将Rn的值给Rd,Rm给Rn。
  • SWPB:字节数据交换指令

例:SWP R1,R2,[R3]  

        SWP R1,R1,[R2]   ;将R1寄存器中的内容与R3存储器中的内容互换。

        SWPB R1,R2,[R0]  ;将R0指的存储单元的内容读取1字节到R1(高24位置0),并将R2的内容写入到该内存单元中(最低字节有效)。

(5)异常指令

  • SWI:软件中断指令
  • BKPT:断点指令(v5T及以上版本)
  • CLZ:前导0计数(v5T及以上版本)

(6)协处理器指令

4、ARM汇编伪指令与伪操作

伪指令:是汇编程序例的特殊指令助记符,是为了方便编程而定义的,在汇编时被合适的机器指令替代;

伪操作:为汇编程序所用,在源程序进行汇编时由汇编程序处理,只在汇编过程起作用,不参与程序运行。

(1)ARM汇编伪指令

  • ADR:小范围的地址读取伪指令。ADR{cond}reg,expr
  • ADRL:中等范围的地址读取伪指令
  • LDR:大范围的地址读取伪指令。 LDR{cond} reg,=expr,用于加载32位立即数或一个地址值到指定的寄存器。
  • NOP:空操作伪指令,可用于软件延时操作。

(2)ARM汇编伪操作

1)符号定义伪操作

详情可阅读这篇文章(侵权联系删除):

嵌入式:ARM符号定义伪操作详解-腾讯云开发者社区-腾讯云 (tencent.com)

  • GBLA,GBLL,GBLS  声明全局变量

    GBLA伪操作声明一个全局的算术变量,并将其初始化成0

    GBLL伪操作声明一个全局的逻辑变量,并将其初始化成{FALSE}

    GBLS伪操作声明一个全局的字符串变量,并将其初始化成空串“”

  • LCLA,LCLL,LCLS    声明局部变量
  • SETA,SETL,SETS    给变量赋值
  • RLIST  给通用寄存器列表定义名称

例:

2)数据定义伪操作
  • LTORG:声明一个数据缓冲池
  • SPACE:分配一块字节内存单元,并用0初始化
  • DCB:定义且初始化一个或多个字节的内存区域。DCB也可用=代替。
  • DCD,DCDU:DCD分配一段字对齐的内存单元,并初始化。DCD可用&表示。DCDU分配一段非严格字对齐的内存单元。
  • DCW:分配半字存储单元
3)汇编控制常用伪操作
  • IF,ELSE及ENDIF
  • WHILE 及WEND
  • MACRO,MEND及MEXIT  宏定义
4)其他常用伪操作
  • AREA:定义一个代码段或数据段。例:AREA  名称,CODE,READONLY
  • CODE16和CODE32:CODE16表后面为Thumb指令;CODE32表后面为ARM指令。
  • ENTRY:指定程序入口点。一个程序至少有一个,一个源程序最多只能有一个。
  • ALIGN:通过填充0将当前位置以某种形式对齐。
  • END:源程序结尾
  • EXPORT和GLOBAL:声明一个源程序中的符号,以便使该符号能被其他源文件引用。
  • IMPORT和EXTERN:声明一个符号是在其他源文件中定义的。
  • GET和INCLUDE:将一个源文件包含到当前源文件中,并将被包含的文件在其当前位置进行汇编处理。
  • INCBIN:将一个源文件包含到当前源文件中,并将被包含的文件在其当前位置不进行汇编处理。

二、课后习题

1、ARM指令的寻址方式有几种?试分别举例说明。

        有9种,分别为寄存器寻址方式、立即数寻址、寄存器移位寻址、寄存器间接寻址、变址寻址、多寄存器寻址、块复制寻址、堆栈寻址、相对寻址。

       分别举例如下:mov r0,r1 、 mov r1,#1   、mov r0,r1,LSL #2、mov r0,[r1]、mov r0,[r1,#2]、

LDM R1,{R0,R2,R5}、STMIA r10,{r0,r1,r4}、STMFD sp!,{r4-r7,lr} 、BLE label_less(并没有给出直接跳转的地址,所以采用了相对寻址的方式)。

2、ARM指令的条件码有多少个?默认条件码是什么?

        16个,默认为AL(无条件跳转)

3、ARM指令中的第二操作数有哪几种形式?试举例说明。

        立即数、寄存器、寄存器移位。

       mov r1,#1   、  mov r0,r1 、 mov r0,r1,LSL #2、

4、在ARM汇编程序如何实现子程序的调用和返回?试举例说明。

在ARM汇编语言中,子程序的调用和返回主要涉及到BL(Branch with Link)指令和BX LRMOV PC, LR指令。以下是具体的说明和示例:

子程序的调用

子程序的调用通常使用BL指令。BL指令会跳转到指定的地址执行,并将当前的指令地址(即返回地址)保存到链接寄存器LR(Link Register)中,以便子程序执行完毕后能够返回到正确的位置。

子程序的返回

子程序的返回可以通过BX LRMOV PC, LR指令来实现。这两条指令都会将程序计数器PC(Program Counter)设置为链接寄存器LR中的值,从而实现返回到调用点的功能。

示例

下面是一个简单的ARM汇编程序示例,展示了如何调用和返回子程序:

AREA MyProgram, CODE, READONLY  
ENTRY  
START  
    ; 调用子程序  
    BL MySubroutine  
    ; 子程序返回后的代码  
    B .   ; 无限循环,防止程序跑飞  
  
; 子程序定义  
MySubroutine  
    ; 子程序的代码,比如打印一条消息等  
    ; ...  
      
    ; 子程序返回  
    BX LR  
END

在这个示例中:

  • START标签下的代码是主程序部分。
  • 使用BL MySubroutine指令调用名为MySubroutine的子程序。
  • 在子程序MySubroutine中执行必要的操作。
  • 使用BX LR指令从子程序返回。

注意:在实际应用中,子程序可能会更复杂,并且可能会涉及到参数传递和返回值处理等问题。此外,为了优化性能和代码结构,还可以使用其他高级技术,如寄存器传递参数、堆栈处理等。但这个示例提供了一个基本的框架来理解ARM汇编中子程序的调用和返回机制。

5、汇编程序设计中常用的伪操作有哪几类?各有什么作用?

        有符号定义伪操作、数据定义伪操作、汇编控制伪操作和其他的伪操作。符号定义伪操作用于声明全局变量和局部变量、给变量赋值、给通用寄存器列表定义名称等;数据定义伪操作用于声明数据缓冲池、分配内存单元等;汇编控制伪操作用以设置条件选择、循环汇编、宏定义汇编等;其他的伪操作可以用来定义数据段或代码段、指定程序入口点、结束】或者声明符号等。

6、试编写实现2+4+6+8+……+100的汇编程序,并在ADS1.2或MDK环境下调试运行。

		area ZY3_6,code,readonly
		entry 
		code32

		mov r0,#0
		mov r1,#2
		
loop
		add r0,r0,r1
		add r1,r1,#2
		cmp r1,#102
		blt loop
		
		end

ok,暂时就先这样吧。

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ARM微控制器和嵌入系统是两个密切相关的概念。ARM微控制器是一种基于ARM架构的微处理器,常用于嵌入系统中。嵌入系统是一种被嵌入在其他设备中的计算机系统,用于控制和管理该设备的各种功能。 ARM微控制器是一种非常常见的微处理器架构,具有低功耗、高性能和高可靠性的特点。它被广泛用于各种嵌入应用中,比如智能手机、平板电脑、家用电器等。ARM架构具有良好的兼容性,可以支持不同的软件开发工具和操作系统,如Android、Linux等。 嵌入系统是一种专门设计用于控制和管理设备的计算机系统。它通常由硬件和软件两部分组成,硬件部分包括处理器、存储器、输入输出接口等,软件部分包括操作系统和应用程序。嵌入系统通常需要满足一些特定需求,如实时性、低功耗、小体积等。 在嵌入系统中,ARM微控制器被广泛应用。它具有丰富的外围接口和强大的计算能力,可以满足各种设备的控制和管理需求。ARM微控制器的软硬件资源丰富,可供开发人员进行灵活的开发和定制。同时,ARM的生态系统也非常完善,有各种开发工具和支持资源可供选择。 清华MOOC是清华大学开设的在线教育平台,其中也有关于ARM微控制器和嵌入系统的相关课程。通过学习清华MOOC中的课程,可以深入了解ARM微控制器和嵌入系统的原理和应用,掌握相应的开发技能。这对于希望从事嵌入系统开发的人而言,是一种很好的学习资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值