嵌入式系统第三章ARM指令系统.ppt

上传人:本田雅阁 文档编号:2899784 上传时间:2019-06-02 格式:PPT 页数:57 大小:245.52KB
返回 下载 相关 举报
嵌入式系统第三章ARM指令系统.ppt_第1页
第1页 / 共57页
嵌入式系统第三章ARM指令系统.ppt_第2页
第2页 / 共57页
嵌入式系统第三章ARM指令系统.ppt_第3页
第3页 / 共57页
嵌入式系统第三章ARM指令系统.ppt_第4页
第4页 / 共57页
嵌入式系统第三章ARM指令系统.ppt_第5页
第5页 / 共57页
点击查看更多>>
资源描述

《嵌入式系统第三章ARM指令系统.ppt》由会员分享,可在线阅读,更多相关《嵌入式系统第三章ARM指令系统.ppt(57页珍藏版)》请在三一文库上搜索。

1、第三章 ARM指令系统,3.1 数据处理指令 3.2 数据传送指令 3.3 控制流指令 3.4 汇编语言程序,汇编语言的源语句行的一般格式是:,label instruction | directive|pseudoinstruction ;comment 注意: 即使没有标号,指令、伪指令和命令前面也必须有一个空白,例如一个空格或制表符。 源语句行的所有三部分都是可选的。可以使用空行来使代码更具可读性 大小写规则 指令记忆码、命令和符号寄存器名称可以用大写或小写编写,但不能混合使用大小写。,标号: 标号是表示地址的符号。在汇编时计算由标号指定的地址。汇编器计算标号的地址,该地址是相对于所定义

2、标号所在段的原点的。引用相同段内的一个标号时,可以使用程序计数器加上或减去一个偏移量。这被称为相对程序的寻址。 其它段中的标号地址是在链接时计算的,此时链接程序已在存储器中为每个段分配了具体的位置。 注释: 一行中的第一个分号用于标记注释的开始,但不包括出现在一个字符串常数内的分号。行的末尾就是注释的结束。一个注释本身就是一个有效的行。汇编程序将忽略所有注释。,常数: 常数可以数值、布尔值、字符或字符串。 数字 可以接受下列形式的数字常数: 十进制数,如 123 十六进制数,如, 0x7B 布尔值 布尔常数 TRUE和 FALSE 必须书写为 TRUE 和 FALSE。 字符 字符常数由左、右

3、单引号组成,中间括住单个字符或一个转义字符,采用标准的 C 转义字符。 字符串 字符串由左、右双引号括住多个字符或空格而组成。如果在一个字符串内使用了双引号或美元字符作为文字文本字符,则必须用一对适当的字符来表示它们。例如,如果需要在字符串内使用单个 $,则必须使用 $。在字符串常数内可以使用标准的 C 转义序列。,ARM 汇编语言模块的示例 AREA ARMex, CODE, READONLY ; Name this block of code ARMex ENTRY ; Mark first instruction to execute start MOV r0, #10 ; Set up

4、 parameters MOV r1, #3 ADD r0, r0, r1 ; r0 = r0 + r1 stop MOV r0, #0x18 ; angel_SWIreason_ReportException LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit SVC #0x123456 ; ARM semihosting (formerly SWI) END ; Mark end of file,3.1 数据处理指令,ARM的数据处理指令使得程序员能够完成寄存器中数据的算术和逻辑操作。 其他指令只是传送数据和控制程序的顺序。 数据处理指令的典型特征

5、是需要两个操作数,产生单个结果。 所有的操作数是32位,或来自寄存器、或是指令中定义的立即数。 如果有结果,则结果为32位宽并只能在寄存器中。 每一个操作数寄存器和结果寄存器都在指令中独立指定,也即ARM指令使用3地址模式。,ADD r0, r1, r2 ; r0 := r1 + r2,注意指令中操作数的顺序,r0是结果寄存器,然后是第一操作数(r1),最后是第二操作数(r2)。 当指令执行后,对系统状态而言唯一的变化是目的寄存器r0的值。 CPSR中的标志位(N、Z、C、V)也可有选择地变化。,1、算术操作,这类指令对两个32位操作数进行二进制算术操作。 ADD r0 , r1 , r2 ;

6、 r0 := r1 + r2 ADC r0 , r1 , r2 ; r0 := r1 + r2 + C SUB r0 , r1 , r2 ; r0 := r1 - r2 SBC r0 , r1 , r2 ; r0 := r1 - r2 + C - 1,2、逻辑操作,这类指令对输入操作数的对应位进行指定的布尔逻辑操作。 AND r0 , r1 , r2 ;r0 i := r1 i and r2 i ORR r0 , r1 , r2 ;r0 := r1 or r2 EOR r0 , r1 , r2 ;r0 := r1 xor r2 BIC r0 , r1 , r2 ;r0 := r1 and no

7、t r2,3、寄存器传送操作,这些指令无第一操作数(省略),只是简单的将第二操作数传送到结果寄存器。 MOV r0 , r2 ;r0 := r2 MVN r0 , r2 ;r0 := not r2,4、比较操作,这类指令不产生结果(省略结果寄存器),仅影响CPSR中的相应位(N、Z、C、V)。 CMP r1 , r2 ;r1 - r2 cc CMN r1 , r2 ;r1 + r2 cc TST r1 , r2 ;r1 and r2 cc TEQ r1 , r2 ;r1 xor r2 cc,5、立即数操作,因为立即数是在32位指令中编码,所以不可能将32位都作为立即数,只能是一个8位数并按两位

8、数为边界进行的调整。 立即数=(0-255)x 22n 0=n=12 ADD r3 , r3 , #1 ;r3 := r3 + 1 AND r8 , r7 , #r8 := r7 7:0,6、寄存器移位操作,这类指令允许第二个操作数(寄存器)在同第一个操作数(寄存器)运算之前完成移位操作。 ADD r3 , r2 , r1 , LSL #3 ;r3 := r2 + r1 x 8 这是一条在单个时钟周期内执行的ARM指令,许多处理器采用独立的移位操作指令。 LSL(逻辑左移)、LSR(逻辑右移) ASL(算术左移)、ASR(算术右移) ROR(循环右移),7、设置条件码,如果程序员需要,任何数据

9、处理指令都能设置条件码,但必须在指令中显示的提出来(比较指令除外)。 ADDS r2 , r2 , r0 ;r1r0 64位数1,r3r2 64位数2 ADC r3 , r3 , r1 ;结果在r3r2中,3.2 数据传送指令,指在ARM寄存器和存储器、I/O设备之间传送数据。 常用的有2种数据传送指令: 1、单寄存器的Load和Store指令:LDR、STR 2、多寄存器的Load和Store指令:LDRM、STRM ARM的数据传送指令都是基于寄存器间接寻址及各种变化,如基址偏移寻址、基址变址寻址等(没有直接寻址)。 寄存器间接寻址:LDR r0 , r1、STR r0 , r1,LDR

10、r0 , r1 STR r0 , r1 ,在任何情况下都需要有一个ARM寄存器来寄存地址,其他形式的寻址都是建立在这种形式之上的。 寄存器间接寻址利用一个寄存器的值(基址寄存器)作为存储器地址;或在此基础上加上立即数构成基址偏移寻址: LDR r0 , r1 , #4 或加上另一个寄存器偏移量构成基址变址寻址: LDR r0 , r1 , r2 初始化寄存器地址指针,初始化寄存器地址指针,要访问一个特定的存储器单元(因ARM是寄存器间接寻址的),必须把一个寄存器初始化,使之包含存储器单元的地址。 ADR伪指令 COPY ADR r1 , TABLE1 ADR r2 , TABLE2 TABLE

11、1 TABLE2 ,1、单寄存器的Load和Store指令:LDR、STR,这些指令提供最灵活的单数据项传送方式,数据项可以是字节、字、半字。 COPY ADR r1 , TABLE1 ADR r2 , TABLE2 LDR r0 , r1 STR r0 , r2 TABLE1 TABLE2 ,使用数据处理指令为下一次传送修改基址寄存器,即 COPY ADR r1 , TABLE1 ADR r2 , TABLE2 LDR r0 , r1 STR r0 , r2 ADD r1 , r1 , #4 ADD r2 , r2 , #4 TABLE1 TABLE2 ,所有Load和Store指令只能使用

12、这种寄存器间接寻址的简单形式,其他形式均在此基础上变化,其目的是使代码更高效。 基址偏移寻址(修改指针) LDR r0 , r1 , #4 ;r0 := mem r1 + 4 这是一个前变址寻址模式,这种模式可以使用一个基址寄存器来访问位于同一区域的多个存储单元。 可以使用带有自动变址的前变址寻址来实现对基址寄存器的修改,这样可以让程序追踪一个数据表。 LDR r0 , r1 , #4 ! ;r0 := mem r1 + 4 ;r1 := r1 + 4,上面程序中的惊叹号表示在开始传送数据后,基址寄存器将更新。在ARM中自动变址并不花费额外的时间,但它严格的等效于先执行一条简单的寄存器间接Lo

13、ad指令,再执行一条数据处理指令,避免了额外的指令时间和代码空间开销。 LDR r0 , r1+4 ADD r1 , r1 + 4 后变址寻址: LDR r0 , r1 , #4 ;r0 := mem r1 ;r1 := r1 + 4 这是一个后变址寻址模式,它允许基址不加偏移即作为传送地址使用,而后再自动变址。它等同于两条指令,但其速度快且占用较少的代码空间。,COPY ADR r1 , TABLE1 ADR r2 , TABLE2 LOOP LDR r0 , r1 , #4 STR r0 , r2 , #4 ? TABLE1 TABLE2 ,比较: COPY ADR r1 , TABLE1

14、 ADR r2 , TABLE2 LDR r0 , r1 STR r0 , r2 ADD r1 , r1 , #4 ADD r2 , r2 , #4 TABLE1 TABLE2 ,2、多寄存器的Load和Store指令:,为保存和恢复处理器状态以及在存储器中移动数据块提供了一种有效方式。 它节省代码空间,使操作速度比顺序执行等效的单寄存器Load、Store指令快达4倍。 举例: LDMIA r1 , r0 , r2 , r5 ;r0 := r1 ;r2 := r1+4 ;r5 := r1+8 注意:该指令执行完后r1内容不变。 LDMIA r1! , r0 , r2 , r5 ;r0 :=

15、r1 ;r2 := r1+4 ;r5 := r1+8 注意:该指令执行完后r1改变。,堆栈寻址:,堆栈经常作为一个线性的数据结构来实现,当加入数据时它就向下增大存贮空间(递减);而数据移走时,它又缩回来。 堆栈指针总是保持在当前栈顶的地址,它指向最后压入堆栈的有效数据(满栈),或指向一个数据空位(空栈)。 满递减:堆栈随着减小存储器地址而向下增长,基址寄存器指向存储有效数据的最低地址。 STMFD r13! , r2 r9 ;将寄存器压入堆栈 LDMFD r13! , r2 r9 ;从堆栈中恢复 注意:在堆栈操作中几乎总是要指定自动变址,以便保证堆栈指针具有一致的行为。,ARM体系结构中使用多

16、寄存器指令完成堆栈操作。进栈使用STM指令,出栈使用LDM指令。 在使用堆栈时,需要确定堆栈在存储器空间是向上生长还是向下生长的,向上称为递增(Ascending),向下称为(Descending)。 满堆栈是指SP指向最后一个进栈的有效数据。 空堆栈是指SP指向最后一个进栈的有效数据的下一个空地址。 LDM和STM指令往往结合下面一些参数实现堆栈操作。 FD满递减堆栈。 ED空递减堆栈。 FA满递增堆栈。 EA空递增堆栈。,ARM制定了ARM-Thumb过程调用标准(ATPCS),在标准中,堆栈被定义为满递减式。因此,LDMFD和STMFD指令分别用来支持出栈和进栈操作。,块拷贝(多寄存器数

17、据传送寻址模式):,块拷贝概念基于数据被存储到基址寄存器的地址(指针)以上还是以下,以及地址的增(I)减(D)开始于存储了第一个数据之前(B)还是之后(A)。 对于Load、Store操作,这两种概念的映射是不同的(见8086方向标志)。,例如:把8个字从r0指向的位置拷贝到r1指向的位置,即 LDMIA r0 ! , r2 r9 STMIA r1 , r2 r9 执行后,r0增加了32。这是由于“!”使其自动变址8个字节,而r1没有改变。 如果r2-r9含有有用的数据,则可以先把它们压入堆栈,即 STMFD r13 ! , r2 - r9 ; 将寄存器压栈 LDMIA r0 ! , r2 r

18、9 STMIA r1 , r2 r9 LDMFD r13 ! , r2 r9 ;从堆栈中恢复,后缀“FD”表示满递减堆栈寻址模式。注意,在堆栈操作中几乎总是要指定自动变址,以便保证堆栈指针具有一致的行为。 多寄存器Load和Store指令为保存和恢复处理器状态以及在存储器中移动数据块提供了一种有效方式。它节省代码空间,并且其执行速度提高了4倍。 这个重要的优点说明,值得认真考虑数据在存储器中的组织方式,以便增大使用多寄存器传送指令去访问存储器的潜力。,3.3 控制流指令,控制流指令既不处理数据,也不存取数据,它只是确定下一步执行哪一条指令。 转移指令 条件转移 条件执行 转移链接 子程序返回

19、监控程序调用 跳转表,转移指令(无条件转移),将程序的执行从一个位置切换到另一个位置最常用的方法是使用转移(branch)指令, B LABEL LABEL 或 LABEL B LABEL,条件转移,有时想让微处理器决定是否进行转移。 MOV r0 , #0 ;计数器初始化 LOOP ADD r0 , r0, #1 ;循环计数器加一 CMP r0 , #10 ;与循环的限制比较 BNE LOOP ;如不相等则返回 ;否则循环终止,列在表中同一行的一对条件(如和)的含义相同,并得到同样的二进制代码。但两者都是有用的,因在特定的环境中,每一种条件都可能使汇编语言源代码的编译更加容易。 当表中提到有

20、符号数和无符号数的比较时,它并不是要选择比较指令本身,而只是支持操作数选择的解释。,条件执行,ARM指令集有一条不寻常的特征,就是条件执行不仅应用于转移指令,也应用于所有的ARM指令。 CMP r0 , #5 BEQ BYPASS ;if ( r0 != 5 ) ADD r1 , r1 ,r0 ;r1 := r1+ r0 - r2 SUB r1 , r1 ,r2 ; BYPASS 替代为 CMP r0 , #5 ; if ( r0 != 5 ) ADDNE r1 , r1 ,r0 ; r1 := r1+ r0 - r2 SUBNE r1 , r1 ,r2 ; ,要激活条件执行,须在3字符的操作

21、码之后增加2字符的条件码(条件码应在其它任何修正码之前)。 ;if ( ( a = b) CMP r0 , r1 CMPEQ r2 , r3 ADDEQ r4 , r4 , #1 由于第二个比较指令使用了条件执行,从而实现了if语句中的逻辑“与”。,使用条件执行的示例 Euclid (欧几里德)的最大公因子 (gcd) 算法的两种实现方法。它说明了如何能使用条件执行来改进代码密度和执行速度。 在 C 语言中,该算法可以表示如下: int gcd(int a, int b) while (a != b) if (a b) a = a b; else b = b a; return a; ,采用下

22、列代码,可以只用带条件跳转来实现 gcd 函数: gcd CMP r0, r1 BEQ end BLT less SUBS r0, r0, r1 ; could be SUB r0, r0, r1 for ARM B gcd less SUBS r1, r1, r0 ; could be SUB r1, r1, r0 for ARM B gcd end,由于跳转数目的原因,该代码的长度是七条指令。每次获得一个跳转时,处理器必须重填流水线并从新位置继续执行。其它指令和未执行的跳转各使用一个周期。 通过使用 ARM 指令集的条件执行功能,可以仅用四个指令实现 gcd 函数: gcd CMP r0,

23、 r1 SUBGT r0, r0, r1 SUBLE r1, r1, r0 BNE gcd END 除了减小了代码大小之外,此代码在大多数情况下执行速度更快。在这种情况下,用条件执行的所有指令来代替跳转后,可节省三个周期。,当r0 r1 时两种代码的执行周期数相等。在其他情况下,代码的条件执行的执行周期数最少。,转移链接指令:,通常要调用子程序,并且当子程序执行完时能够恢复到原来的代码位置,这就需要把执行转移之前程序计数器r15的值保存下来。 ARM使用转移链接指令BL来提供这一功能。该指令完全像转移指令一样执行转移,并将转移后面紧接的一条指令的地址保存到连接寄存器r14中。 BL SUBR

24、; 转移到SUBR ;返回到这里 ; SUBR ;子程序入口 MOV pc , r14 ;返回,注意:由于返回地址保存在r14寄存器里,子程序不应嵌套,否则,新的返回地址将覆盖原来的返回地址。常规做法是将r14入栈。 BL SUB1 ; 转移到SUB1 ;返回到这里 SUB1 STMFD r13! , r0-r2, r14 ;保存现场 BL SUB2 SUB2 ,子程序返回指令:,为了返回调用程序,必须将转移链接指令保存在r14中的程序计数器值拷贝到程序寄存器。 SUBR ;子程序入口 MOV pc , r14 ;把r14拷贝到r15来返回 对子程序嵌套返回 SUB1 STMFD r13 !

25、, r0-r2 , r14 BL SUB2 LDMFD r13 ! , r0-r2 , pc ,AREA subrout, CODE, READONLY ; Name this block of code ENTRY ; Mark first instruction to execute start MOV r0, #10 ; Set up parameters MOV r1, #3 BL doadd ; Call subroutine stop MOV r0, #0x18 ; angel_SWIreason_ReportException LDR r1, =0x20026 ; ADP_Sto

26、pped_ApplicationExit SVC #0x123456 ; ARM semihosting (formerly SWI) doadd ADD r0, r0, r1 ; Subroutine code BX lr ; Return from subroutine END ; Mark end of file,监控程序调用,监控程序提供了委托访问系统资源的方式,对用户级程序它更像一个专门的子程序入口。指令集包含一个专门的指令SWI,用来调用访问输入输出这类功能。 如:把r0底部字节中的字符送到显示器, SWI SWI_WriteC ;输出r0 7:0 或,把控制从用户程序返回到监控程

27、序, SWI SWI_Exit ;返回到监控程序,跳转表:,跳转表的思想是程序员有时想调用一系列子程序中的一个,但究竟调用哪一个须由程序的计算值确定(如r0)。 如传统的, BL JUMPTAB JUMPTAB CMP r0 , #0 ;假设值在r0 BEQ SUB0 CMP r0 , #1 BEQ SUB1 CMP r0 , #2 BEQ SUB2 ;当子程序列表较长时,该方案非常慢。,一个有效的解决方案是利用程序计数器在通用寄存器文件中的可见性来实现的。 BL JUMPTAB JUMPTAB ADR r1 , SUBTAB CMP r0 , #SUBMAX ;如果OK LDRLS pc ,

28、 r1,r0,LSL #2 ;则进入表中 B ERROR ;否则报警 SUBTAB DCD SUB0 ;子程序表入口 DCD SUB1 DCD SUB2 ,ENTRY ; mark the first instruction to call start MOV r0, #1 ; set up the three parameters MOV r1, #3 MOV r2, #2 BL arithfunc ; call the function stop MOV r0, #0x18 ; angel_SWIreason_ReportException LDR r1, =0x20026 ; ADP_S

29、topped_ApplicationExit SWI 0x123456 ; ARM semihosting SWI arithfunc ; label the function CMP r0, #num ; Treat function code as unsigned integer MOVHS pc, lr ; If code is = num then simply return ADR r3, JumpTable ; Load address of jump table LDR pc, r3,r0,LSL#2 ; Jump to the appropriate routine Jump

30、Table DCD DoAdd DCD DoSub DoAdd ADD r0, r1, r2 ; Operation 0 MOV pc, lr ; Return DoSub SUB r0, r1, r2 ; Operation 1 MOV pc,lr ; Return END ; mark the end of this file,DCD指示汇编器保留一个字,并将它们初始化为右边表达式的值标号的地址。 不管表中有多少子程序,以及它们使用的频度如何互不相关,这种方法的性能不变。 在读跳转表时,若超出了表的末端,结果将是灾难性的,因此,检查越限是必须的。 或 CMP r0 , #SUBMAX BH

31、I EEROR LDR pc , r1 , r0 , LSL #2 ,3.4 汇编语言程序,AREA Hellow, CODE, READONLY ;声明代码区 SWI_Write EQU &0 ;输出r0中的字符 SWI_Exit EQU &11 ;程序结束 ENTRY ;代码入口 START ADR r1 , TEXT ;指针 LOOP LDRB r0 , r1 , #1 ;读下一字节 CMP r0 , #0 ;检查文本终点 SWINE SWI_Write ;打印 BNE LOOP ; SWI SWI_Exit ;执行结束 TEXT = “Hellow,World” , &0a , & 0

32、d , 0 END ;程序结束,这段程序说明了ARM汇编语言和指令集的许多特征: 带有适当属性的代码AREA的声明; 系统调用的定义; 使用ARD伪指令,以便将地址写入基址寄存器; 使用自动变址寻址,以扫描一系列字节; SWI指令的条件执行,以避免额外的转移。 使用字节“0”标记字符串(回车和换行之后)的结束。只要采用循环结构,就必须保证它有结束的条件。,AREA BlkCpy, CODE, READONLY ;块拷贝 SWI_Write EQU &0 ;输出r0中的字符SWI_Exit EQU &11 ;程序结束 ENTRY ADR r1, TABLE1 ADR r2, TABLE2 ADR

33、 r3, T1END LOOP1 LDR r0, r1 , #4 STR r0, r2 , #4 CMP r1, r3 BLT LOOP1 ADR r1, TABLE2 LOOP2 LDRB r0, r1 , #1 CMP r0, #0 SWINE SWI_Write BNE LOOP2 SWI_Exit TABLE1 = “This is the right string!”, &0a , &0d , 0 ;DCB T1END ALIGN ;保证字对齐 TABLE2 = “This is the wrong string!”, 0 END,AREA Hex_Out, CODE, READON

34、LY SWI_Write EQU &0 ;输出r0中的字符SWI_Exit EQU &11 ;程序结束 ENTRY ;代码入口 LDR r1, VALUE ;读取要打印的数据 BL HexOue ;调用16进制输出 SWI SWI_Exit ;结束 VALUE DCD &12345678 ;测试数据 HexOut MOV r2, #8 ;半字节数 LOOP MOV r0, r1 , LSR #28 ;读取顶半字节 CMP r0, #9 ;09还是AF? ADDGT r0, r0, # ”A”-10 ;ASCII字母 ADDLE r0, r0 , #”0” ;ASCII数字 SWI SWI_Write ;打印字符 MOV r1, r1 , LSL #4 ;左移4位 SUBS r2, r2 , #1 ;半字节数减1 BNE LOOP ;若还有 MOV pc , r14 ;返回 END,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1