《汇编及嵌入式C语言-第二章.ppt》由会员分享,可在线阅读,更多相关《汇编及嵌入式C语言-第二章.ppt(128页珍藏版)》请在三一办公上搜索。
1、ARM处理器及嵌入式C语言,第二章 ARM编程模型和指令集介绍,2.1 ARM编程模型2.1.1 指令长度及数据类型 指令集可以是以下任一种32 bits 长(ARM状态)16 bits 长(Thumb状态),特别说明:Thumb指令集可以看作是ARM指令压缩形式的子集,它是为减小代码量而提出,具有16bit的代码密度。Thumb指令体系并不完整,只支持通用功能,必要时仍需要使用ARM指令,如进入异常时。其指令的格式与使用方式与ARM指令集类似,而且使用并不频繁,Thumb指令集作一般了解。,ARM7TDMI 支持3种数据类型 字节(8-bit)半字(16-bit)字(32-bit)字必须被排
2、成4个字节边界对齐,半字必须被排列成2个字节边界对齐,2.1.2 ARM处理器的工作状态 ARM微处理器的工作状态一般有两种:ARM状态处理器执行32位的字对齐的ARM指令;Thumb状态处理器执行16位的、半字对齐的Thumb指令。ARM和Thumb指令集均有切换处理器状态的指令,在程序的执行过程中,处理器可以随时在两种状态之间切换,并且处理器工作状态的转变并不影响处理器的工作模式和相应寄存器中的内容,但是有些场合中系统只能使用ARM指令。,只能使用ARM指令的场合:1.如果对于速度有比较高的要求,ARM指令在宽存储器中会提供更高的性能;2.某些功能只能由ARM指令来实现,比如:访问CPSR
3、寄存器来使能/禁止中断或者改变处理器工作模式;访问协处理器CP15;执行C代码不支持的DSP算术指令;3.异常中断(Exception)处理。在进入异常中断后,内核自动切换到ARM状态。即在异常中断处理程序入口的一些指令是ARM指令,然后根据需要程序可以切换到Thumb状态,在异常中断处理程序返回前,程序再切换到ARM状态。4.ARM处理器总是从ARM状态开始执行。因而,如果要在调试器中运行Thumb程序,必须为该Thumb程序添加一个ARM程序头,然后再切换到Thumb状态,调用该Thumb程序。,Thumb状态和ARM状态切换的实现:BX Rn Rn可以是寄存器R0R15中的任意一个,指令
4、可以通过将寄存器Rn的内容拷贝到程序计数器PC来完成在4Gbyte地址空间中的绝对跳转,而状态切换是由寄存器Rn的最低位来指定的,如果操作数寄存器的状态位Bit0=0,则进入ARM状态,如果Bit0=1,则进入Thumb状态。,Thumb状态和ARM状态切换的实现:,CODE32/ARM状态下的代码 LDR R0,=Into_Thumb+1/产生跳转地址并且设置最低位 BX R0/Branch Exchange 进入Thumb状态 CODE16/Thumb状态下的子函数 Into_Thumb LDR R3,=Back_to_ARM/产生字对齐的跳转地址,最低位被清除 BX R3/Branch
5、Exchange 返回到ARM状态 CODE32/ARM状态下的子函数 Back_to_ARM,2.1.3 ARM体系结构的存储器格式 ARM体系结构将存储器看作是从0地址开始的字节的线性组合。从0字节到3字节放置第一个存储的字数据,从第4个字节到第7个字节放置第二个存储的字数据,依次排列。作为32位的微处理器,ARM体系结构所支持的最大寻址空间为4GB。ARM体系结构可以用两种方法存储字数据,称之为大端格式和小端格式。,小端格式,大端格式,问题:32bits宽的数0 x12345678存放 在0 xb00d40000 xb00d4003存 储器中,在大端模式如何放置?在小端模式又如何放置?,
6、2.1.4 处理器模式 ARM处理器支持7种运行模式:,除用户模式外,其它模式均为特权模式。ARM内部寄存器和一些片内外设在硬件设计上只允许(或者可选为只允许)特权模式下访问。此外,特权模式可以自由的切换处理器模式,而用户模式不能直接切换到别的模式。,这五种模式称为异常模式。它们除了可以通过程序切换进入外,也可以由特定的异常进入。当特定的异常出现时,处理器进入相应的模式。每种异常模式都有一些独立的寄存器,以避免异常退出时用户模式的状态不可靠。,这两种模式都不能由异常进入,而且它们使用完全相同的寄存器组。系统模式是特权模式,不受用户模式的限制。操作系统在该模式下访问用户模式的寄存器就比较方便,而
7、且操作系统的一些特权任务可以使用这个模式访问一些受控的资源。,2.1.5 寄存器组织 ARM处理器共有37个32位的寄存器,其中包括1个用作PC、一个用作CPSR、5个用作SPSR和30个通用寄存器,在ARM状态下,任意时刻可编程访问的有16个通用寄存器和1-2个状态寄存器。寄存器被安排成部分重叠的组。在不同的工作模式和处理器状态下,程序员可以访问的寄存器也不尽相同。分组的寄存器在处理器异常和特权操作时可得到快速的上下文切换。,所有的37个寄存器,分成两大类:31个通用32位寄存器;6个状态寄存器。,在汇编语言中寄存器R0R13为保存数据或地址值的通用寄存器。它们是完全通用的寄存器,不会被体系
8、结构作为特殊用途,并且可用于任何使用通用寄存器的指令。,其中R0R7为未分组的寄存器,也就是说对于任何处理器模式,这些寄存器都对应于相同的32位物理寄存器。,寄存器R8R14为分组寄存器。它们所对应的物理寄存器取决于当前的处理器模式,几乎所有允许使用通用寄存器的指令都允许使用分组寄存器,寄存器R8R12有两个分组的物理寄存器。一个用于除FIQ模式之外的所有寄存器模式,另一个用于FIQ模式。这样在发生FIQ中断后,可以加速FIQ的处理速度。,寄存器R13、R14分别有6个分组的物理寄存器。一个用于用户和系统模式,其余5个分别用于5种异常模式。,寄存器R13常作为堆栈指针(SP)。在ARM指令集当
9、中,没有以特殊方式使用R13的指令或其它功能,只是习惯上都这样使用。但是在Thumb指令集中存在使用R13的指令。,R14为链接寄存器(LR),在结构上有两个特殊功能:在每种模式下,模式自身的R14版本用于保存子程序返回地址;当发生异常时,将R14对应的异常模式版本设置为异常返回地址(有些异常有一个小的固定偏移量)。,MOV PC,LR,R14(地址A),1.程序A执行过程中调用程序B;,操作流程,2.程序跳转至标号Lable,执行程序B。同时硬件将“BL Lable”指令的下一条指令所在地址存入R14;,3.程序B执行最后,将R14寄存器的内容放入PC,返回程序A;,R14寄存器与子程序调用
10、,R14寄存器与异常发生,异常发生时,程序要跳转至异常服务程序,对返回地址的处理与子程序调用类似,都是由硬件完成的。区别在于有些异常有一个小常量的偏移。当发生异常嵌套时,这些异常之间可能会发生冲突。例如:如果用户在用户模式下执行程序时发生了IRQ中断,用户模式寄存器不会被破坏。但是如果允许在IRQ模式下的中断处理程序重新使能IRQ中断,并且发生了嵌套的IRQ中断时,外部中断处理程序保存在R14_irq中的任何值都将被嵌套中断的返回地址所覆盖。,a,return,地址A,1.执行用户模式下的程序;,2.发生IRQ中断,硬件将某个地址存入IRQ模式下的R14_irq寄存器,用户模式下的R14没有被
11、破坏;,3.IRQ服务程序A执行完毕,将R14_irq寄存器的内容减去某个常量后存入PC,返回之前被中断的程序;,未被破坏,a,地址A,1.执行用户模式下的程序;,2.发生IRQ中断,硬件将某个地址存入IRQ模式下的R14_irq寄存器,用户模式下的R14没有被破坏;,3.IRQ服务程序A执行完毕,将R14_irq寄存器的内容减去某个常量后存入PC,返回之前被中断的程序;,未被破坏,a,return,地址B,4.如果在IRQ处理程序中打开IRQ中断,并且再次发生IRQ中断,或者调用子程序;,5.硬件将返回地址保存在R14_irq寄存器中,原来保存的返回地址将被覆盖,造成错误;,被破坏,6.在程
12、序B返回到程序A,然后在返回到用户模式下被中断的程序时,发生错误,将不能正确返回;,return,return,解决办法:确保R14的对应版本在发生中断嵌套时不再保存任何有意义的值(将R14入栈),或者切换到其它处理器模式下。,寄存器R15为程序计数器(PC),它指向正在取指的地址。可以认为它是一个通用寄存器,但是对于它的使用有许多与指令相关的限制或特殊情况。如果R15使用的方式超出了这些限制,那么结果将是不可预测的。,读R15的限制,正常操作时,从R15读取的值是处理器正在取指的地址,即当前正在执行指令的地址加上8个字节(两条ARM指令的长度)。由于ARM指令总是以字为单位,所以R15寄存器
13、的最低两位总是为0。,读R15的限制,当使用STR或STM指令保存R15时,会有一个例外。这些指令可能将当前指令地址加8字节或加12字节保存(将来可能还有其它数字)。偏移量是8还是12取决于具体的ARM芯片,但是对于一个确定的芯片,这个值是一个常量。所以最好避免使用STR和STM指令来保存R15,如果很难做到,那么应当在程序中计算出该芯片的偏移量。,读R15的限制,计算偏移量程序代码:,SUBR1,PC,#4;R1=下面STR指令的地址STRPC,R0;保存STR指令地址+偏移量LDRR0,R0;然后重装SUBR0,R0,R1;计算偏移量,读R15的限制,正常操作时,写入R15 的值被当作一个
14、指令地址,程序从这个地址处继续执行(相当于执行一次无条件跳转)。,读R15的限制,由于ARM指令以字节为边界,因此写入R15的值最低两位通常为0b00。具体的规则取决于内核结构的版本:在ARM结构V3版及以下版本中,写入R15的值的最低两位被忽略,因此跳转地址由指令的实际目标地址(写入R15的值)和0 xFFFFFFFC相与得到;在ARM结构V4版及以上版本中,写入R15的值的最低两位为0,如果不是,结果将不可预测。,寄存器CPSR为当前程序状态寄存器,在异常模式中,另外一个寄存器“备份程序状态寄存器(SPSR)”可以被访问。每种异常都有自己的SPSR,在因为异常事件而进入异常时它保存CPSR
15、的当前值,异常退出时可通过它恢复CPSR。,CPSR反映了当前处理器的状态:个条件代码标志;2个中断控制位;5个对当前处理器模式进行编码的位;1个指示当前执行指令的工作状态位;保留位。,SPSR:备份程序状态字,保存异常事件发生之前的CPSR,每个异常模式带有一个备份程序状态寄存器,用于保存在异常事件发生之前的CPSR;CPSR和SPSR通过特殊指令进行访问。,2.1.6 程序状态寄存器CPSR和SPSR,程序状态寄存器CPSR和SPSR,当用两个补码表示的带符号数进行运算时,结果为负数时N=1,结果为正数或零时N=0;,指令结果为0时Z=1(表示比较结果“相等”),否则Z=0;,当进行加法运
16、算,并且最高位产生进位时C=1,否则C=0。当进行减法运算,并且最高位产生借位时C=0,否则C=1。对于移位操作指令,C为从最高位最后移出的值,其它指令C通常不变;,当进行加法/减法运算,并且发生有符号溢出时V=1,否则V=0,其它指令V通常不变。,ARMv5及以上版本的E系列中,用Q标志位指示增强的DSP运算指令是否发生溢出,其他版本该位无定义。,保留位被保留将来使用。为了提高程序的可移植性,当改变CPSR标志和控制位时,请不要改变这些保留位。另外,请确保您程序的运行不受保留位的值影响,因为将来的处理器可能会将这些位设置为1或者0。,最低8位为控制位,当发生异常时,这些位被硬件改变。当处理器
17、处于一个特权模式时,可用软件操作这些位。,中断禁止位I、F:置1时禁止IRQ中断和FIQ中断,T标志位:T=1时运行于Thumb状态;T=0时运行于ARM状态。在程序中,不能修改此bit位。,运行模式位M4:0的具体含义,注意:不是所有模式位的组合都定义了有效的处理器模式,如果使用了错误的设置,将引起一个无法恢复的错误。,2.1.7 异常 只要正常的程序流被暂时中止,处理器就进入异常模式。例如响应一个来自外设的中断。在处理异常之前,处理器内核保存当前的处理器状态,这样当处理程序结束时可以恢复执行原来的程序。如果同时发生两个或更多异常,那么将按照固定的顺序来处理异常,详见“异常优先级”部分。当系
18、统运行时,异常可能会随时发生,为了保证异常发生时处理器不会处于未知状态,在异常向量表中的特定位置放置一条跳转指令,当异常发生时,PC会被强制设置为对应的异常向量,从而跳转到异常处理程序。,异常向量表,进入异常 1.在适当的LR中保存下一条指令的地址;2.将CPSR复制到相应的SPSR中;3.根据异常类型,强制设置CPSR的运行模式位;4.强制PC从相应的异常向量地址取下一条指令执行,从而跳转到相应的异常处理程序处。注意:ARM7TDMI内核在中断异常时置位中断禁止标志,这样可以防止不受控制的异常嵌套。异常总是在ARM状态中进行处理。当处理器处于Thumb状态时发生了异常,在异常向量地址装入PC
19、时,会自动切换到ARM状态。,1.程序在系统模式下运行用户程序,假定当前处理器状态为Thumb状态、允许IRQ中断;,2.用户程序运行时发生IRQ中断,硬件完成以下动作:,置位I位(禁止IRQ中断)清零T位(进入ARM状态)设置MOD位,切换处理器模式至IRQ模式,将下一条指令的地址存入IRQ模式的LR寄存器,将CPSR寄存器内容存入IRQ模式的SPSR寄存器,将跳转地址存入PC,实现跳转,BackAddr,JumpAddr,“?”表示对该位不关心,进入异常的过程,退出异常 将LR中的值减去偏移量后存入PC,偏移量根据异常的类型而有所不同;2.将SPSR的值复制回CPSR;3.若在进入异常处理
20、时设置了中断禁止位,要在此清除注意:恢复CPSR的动作会将T、F和I位自动恢复为异常发生前的值。,在异常处理结束后,异常处理程序完成以下动作:,将SPSR寄存器的值复制回CPSR寄存器;,将LR寄存的值减去一个常量后复制到PC寄存器,跳转到被中断的用户程序。,BackAddr,JumpAddr,return,BackAddr-4,“?”表示对该位不关心,退出异常的过程,快速中断请求(FIQ):快速中断请求(FIQ)适用于对一个突发事件的快速响应,这得益于在ARM状态中,快中断模式有8个专用的寄存器可用来满足寄存器保护的需要(这可以加速上下文切换的速度)。不管异常入口是来自ARM状态还是Thum
21、b状态,FIQ处理程序都会通过执行下面的指令从中断返回:SUBS PC,R14_fiq,#4 在一个特权模式中,可以通过置位CPSR中的F位来禁止FIQ异常。,中断请求(IRQ):IRQ异常属于正常的中断请求,可通过对处理器的nIRQ引脚输入低电平产生(在具体的芯片中,nIRQ由片内外设拉低,nIRQ是内核的一个信号,对用户不可见)。IRQ的优先级低于FIQ,对于FIQ它是被屏蔽的。不管异常入口是来自ARM状态还是Thumb状态,FIQ处理程序都会通过执行下面的指令从中断返回:SUBS PC,R14_fiq,#4 在一个特权模式下,都可通过置位CPSR中的I位来禁止IRQ。,中止(Abort)
22、:中止发生在对存储器的访问不能完成时,中止包含两种类型:指令预取中止 发生在指令预取过程中数据中止 发生在对数据访问时指令预取中止 当发生指令预取中止时,处理器内核将预取的指令标记为无效,但在指令到达流水线的执行阶段时才进入异常。如果指令在流水线中因为发生分支而没有被执行,中止将不会发生。在确定了中止的原因并处理后,无论是ARM还是Thumb状态,处理程序都会执行下面的指令从指令预取中止模式返回:SUBS PC,R14_abt,#4,数据中止 当发生数据中止时,说明系统的响应与指令的类型有关。在修复产生中止的原因后,不管处于哪种处理器操作状态,处理程序都必须执行下面的返回指令:SUBS PC,
23、R14_abt,#8,软件中断(SWI)软件中断(SWI)指令用于进入管理模式,通常用于请求执行特定的管理功能。SWI处理程序通过执行下面的指令返回:MOVS PC,R14_svc 这个动作恢复了PC和CPSR并返回到SWI之后的指令。,未定义指令 当ARM处理器遇到一条自己和系统内任何协处理器都无法处理的指令时,ARM内核执行未定义指令陷阱。软件可使用这一机制通过模拟未定义的协处理器指令来扩展ARM指令集。在模拟处理了失败的指令后,陷阱程序执行下面的指令恢复了PC和CPSR并返回到未定义指令之后的指令:MOVS PC,R14_svc,异常优先级 当多个异常同时发生时,一个固定的优先级系统决定
24、它们被处理的顺序:,优先级降低,异常优先级 未定义的指令和SWI异常互斥,因为同一条指令不能既是未定义的,又能产生有效的软件中断;当FIQ使能,并且FIQ和数据中止异常同时发生时,处理器内核首先进入数据中止处理程序,然后立即跳转到FIQ向量。在FIQ处理结束后返回到数据中止处理程序。数据中止的优先级必须高于FIQ以确保数据转移错误不会被漏过。,2.2 ARM处理器的指令格式 2.2.1 ARM处理器的指令格式,S,其中:Opcode 指令助记符;Cond 指令执行的条件码 S 决定指令的操作数是否影响CPSR的值,选择时影响CPSR的值 Rd 目标寄存器 Rn 包含第1个操作数的寄存器 Ope
25、rand2 表示第2个操作数,第2个操作数 灵活的使用第2个操作数“operand2”能够提高代码效率。它有如下的形式:#immed_8r常数表达式;Rm寄存器方式;Rm,shift寄存器移位方式;,第2个操作数#immed_8r常数表达式;该常数必须对应8位位图,即一个8位的常数通过循环右移偶数位得到。,循环右移10位,8位常数,请判断以下8位图数据的正误,并说明明原因:0 x5f00000 x2080 x1010 x4000000a0 x204000000 x10200000,第2个操作数 Rm寄存器方式 在寄存器方式下,操作数即为寄存器的数值。例如:SUBR1,R1,R2,第2个操作数
26、Rm,shift寄存器移位方式 将寄存器的移位结果作为操作数(移位操作不消耗额外的时间),但Rm值保持不变,移位方法如下:,第2个操作数,第2个操作数 Rm,shift寄存器移位方式,LSL移位操作:,LSR移位操作:,ASR移位操作:,ROR移位操作:,RRX移位操作:,C,C,C,C,C,第2个操作数 Rm,shift寄存器移位方式 ADDR1,R1,R1,LSL#3;R1=R1+(R1R3)MOV R0,R1,ROR#2;将R1中的内容循环 右移2位后传送到R0 MOVR0,R1,RRX;将R1中的内容进行带 扩展的循环右移一位 后送到R0,如果R4=0X80000000,R2=0 x5
27、,R1=0 x7,CPSR=0 x10,那么经过以下操作后,R3为多少?CPSR又是多少呢?MOVS R3,R4,ASR#4MOV R3,R2,LSL#7MOVS R3,R1,ROR#2,0 xf8000000,CPSR=0 x800000100 x00000280 0 xc0000001,CPSR=0 xa0000010,2.2.2 指令的条件码 使用条件码“cond”可以实现高效的逻辑操作(节省跳转和条件语句),提高代码效率。所有的ARM指令都可以条件执行,而Thumb指令只有B(跳转)指令具有条件执行功能。如果指令不标明条件代码,将默认为无条件执行。,S,举例如下:,C代码:If(a b
28、)a+;Elseb+;,对应的汇编代码:CMPR0,R1;R0(a)与R1(b)比较ADDHIR0,R0,#1;若R0R1,则R0=R0+1ADDLSR1,R1,#1;若R0R1,则R1=R1+1,2.3 ARM指令寻址方式 2.3.1 字及无符号字节的Load/Store指令的寻址方式 LDR指令用于从内存中读取单一字或字节数据存入寄存器中,STR指令用于将寄存器中的单一字或字节数据保存到内存。指令格式如下:LDRcondT Rd,;将指定地址上的字数据读入Rd STRcondT Rd,;将Rd中的字数据存入指定地址 LDRcondBT Rd,;将指定地址上的字节数据读入Rd,高24位清零
29、STRcondBT Rd,;将Rd中的字节数据存入指定地址,最低字节有效,LDR/STR指令寻址非常灵活,它由两部分组成,其中一部分为一个基址寄存器,可以为任何一个通用寄存器;另一部分为一个地址偏移量。地址偏移量有以下3种格式:立即数。立即数可以是一个无符号的数,这个数 可以加到基址寄存器,也可以从基址寄存器中减去。如:LDR R1,R0,#0 x12;R1 R0+0 x12 LDR R3,R2,#-4;R3 R2-4 LDR R6,R7;R6 R7,寄存器。寄存器中的数值可以加到基址寄存器,也可以从基址寄存器中减去。如:LDR R1,R0,R2;R1 R0+R2 LDR R1,R0,-R2;
30、R1 R0-R2 寄存器及移位常数。寄存器移位后的值可以加到基址寄存器,也可以从基址寄存器中减去这个数值。如:LDR R1,R0,R2,LSL#2;R1 R0+R2*4 LDR R3,R4,-R5,LSR#4;R3 R4-R5/16,从寻址方式的地址计算方法分,Load/Store指令有以下三种形式:偏移量方法。基址寄存器中的数值和地址偏移量作加/减运算,生成操作数的地址。如:LDR R1,R0,#4;R1 R0+4 事先更新方法。基址寄存器中的数值和地址偏移量做加或减的运算,生成操作数的地址,指令执行后,生成的操作数地址被写入到基址寄存器。如:LDR R0,R1,#4!;R0 R1+4,R1
31、=R1+4 LDR R0,R1,-R2!;R0 R1-R2,R1=R1-R2,事后更新方法。基址寄存器中的数值作为操作数的地址执行内存访问,基址寄存器的值和地址偏移量作加/减运算,生成操作数的地址,指令执行后,这个生成的操作数地址被写入到基址寄存器。如:LDR R0,R1,#4;R0 R1,R1=R1+4 LDR R0,R1,-R2;R0 R1,R1=R1-R2 LDR R0,R1,R2,LSL#2;R0 R1,R1=R1+R2*4,如果0 x80=0 x8,0 x84=0 x7,0 x88=0 x10,那么顺序执行以下操作后,R2、R3和R4中的内容是多少呢?LDR R4,=0 x80LDR
32、 R3,R4,#4LDR R2,R4,#4!LDR R1,R3,R2,LSL#8,2.3.2 杂类Load/Store指令的寻址方式 这类LDR/STR指令可以加载带符号字节、加载带符号半字、加载/存储无符号半字。指令格式如下:LDRcondSB Rd,;加载指定地址上的数据(带符号字节),放入Rd中 LDRcondSH Rd,;加载指定地址上的数据(带符号半字),放入Rd中 LDRcondH Rd,;加载半字数据,放入Rd中,高16位清零 STRcondH Rd,;存储半字数据,要存储的数据在Rd,最低16位有效,说明:带符号位半字/字节加载是指符号位扩展到32位;无符号位半字加载是指零扩展
33、到32位,举例如下:LDRSB R1,R0,R3;R1 R0+R3字节数据,高24位用符号位扩展 LDRSH R1,R9;R0 R9半字数据,高16位用符号位扩展 LDRH R6,R2,#2;R6 R2半字数据,高16位用零扩展,R2=R2+2 STRH R1,R0,#2!;R0+2 R1,只存储低2位字节数据,R0=R0+2,这类LDR/STR指令可以加载/存储两个相邻的寄存器,64位双字。指令格式如下:LDRcondD Rd,;加载指定地址上的数据放入Rd中,加载(指定地址+4)地址上的数据放入R(d+1)中 STRcondD Rd,;将Rd的数据存储到指定地址上,将R(d+1)的数据存储
34、到(指定地址+4)的地址上 注意:Rd 加载/存储寄存器中的一个,另一个是R(d+1)。Rd必须是偶数寄存器,且不是R14。,举例如下:LDRD R6,R11;R6 R11,R7 R11+4 STRD R4,R9,#24;R4 R9+24,R5 R9+28 LDRD R0,R2,#2;R0 R2,R1 R2+4,R2=R2+2 STRD R2,R0,#2!;R0+2 R2,R0+6 R3,R0=R0+2,2.3.3 批量Load/Store指令的寻址方式 多寄存器加载/存储指令可以实现在一组寄存器或一块连续的内存单元之间传输数据。LDM为加载多个寄存器;STM为存储多个寄存器。允许一条指令传送
35、16个寄存器的任何子集或所有寄存器。它们主要用于现场保护、数据复制、常数传递等。,指令格式如下:LDMcond Rn!,reglist STMcond Rn!,reglist cond:指令执行的条件;模式:控制地址的增长方式,一共有8种模式;!:表示在操作结束后,将最后的地址写回Rn中;reglist:表示寄存器列表,可以包含多个寄存器,它们使用“,”隔开,如R1,R2,R6-R9,寄存器由小到大排列;,指令格式如下:LDMcond Rn!,reglist STMcond Rn!,reglist:可选后缀,允许在用户模式或系统模式下使用。它有以下两个功能:1)若是LDM且寄存器列表包含PC时
36、,那么除了正常的数据传送外,还将SPSR也复制到CPSR中。可用于异常处理返回。2)数据传入或传出的是用户模式下的寄存器,而不是当前模式下的寄存器。,多寄存器加载/存储指令的8种模式如下表所示,右边四种为堆栈操作、左边四种为数据传送操作。,2.3.3 批量Load/Store指令的寻址方式 进行数据复制时,先设置好源数据指针和目标指针,然后使用块拷贝寻址指令LDMIA/STMIA、LDMIB/STMIB、LDMDA/STMDA、LDMDB/STMDB进行读取和存储。进行堆栈操作操作时,要先设置堆栈指针(SP),然后使用堆栈寻址指令STMFD/LDMFD、STMED/LDMED、STMFA/LD
37、MFA和STMEA/LDMEA实现堆栈操作。,2.3.3 批量Load/Store指令的寻址方式 数据块传送指令操作过程如下图所示,其中R1为指令执行前的基址寄存器,R1则为指令执行后的基址寄存器。,2.3.3 批量Load/Store指令的寻址方式,2.3.3 批量Load/Store指令的寻址方式 举例如下:LDMIA R0,R1-R4;R1 R0,R2 R0+4,R3 R0+8,R4 R0+12 LDMIA R0!,R1-R4;R1 R0,R2 R0+4,R3 R0+8,R4 R0+12 R0=R0+16 STMDB R0,R1-R4;R0-4 R4,R0-8 R3,R0-12 R2,R
38、0-16 R1 STMIA R0,R1-R4;R0 R1,R0+4 R2,R0+8 R3,R0+12 R4,2.3.3 批量Load/Store指令的寻址方式 举例如下:STMEA R13,R5-R8;R13 R5,R13+4 R6,R13+8 R7,R13+12 R8 STMED R13,R5-R8;R13 R8,R13-4 R7,R13-8 R6,R13-12 R5 STMFD R13,R5-R8;R13-4 R8,R13-8 R7,R13-12 R6,R13-16 R5 LDMED R13,R5-R8;R5 R13+4,R6 R13+8,R7 R13+12,R8 R13+16 LDMFA
39、 R13,R5-R8;R8 R13,R7 R13-4,R6 R13-8,R5 R13-12,2.3.3 批量Load/Store指令的寻址方式 两段代码的执行结果是一样的,但是使用堆栈指令的压栈和出栈操作编程很简单(只要前后一致即可),而使用数据块指令进行压栈和出栈操作则需要考虑空与满、加与减对应的问题。,2.3.3 批量Load/Store指令的寻址方式 写出下面程序执行的过程:,LDR SP,=0 x3ff0000 LDR R0,=0 x1LDR R1,=0 x2LDR R2,=0 x3STMEA R13!,R0-R2LDR R0,R3,R2,LSL#2LDR R2,R0,#3LDMEA
40、R13!,R0-R2,2.4 ARM指令集介绍2.4.1 跳转指令 在ARM中有两种方式可以实现程序的跳转,一种是使用跳转指令,另一种则是直接向PC寄存器写入跳转地址值。跳转指令有以下四种:跳转指令B;带返回的跳转指令BL;带状态切换的跳转指令BX;带返回和状态切换的跳转指令BLX。,2.4.1 跳转指令 分支指令B指令,该指令跳转范围限制在当前指令的32M字节地址内(ARM指令为字对齐,最低2位地址固定为0)。指令格式如下:Bcond Label 应用示例:B WAITA;跳转到WAITA标号处 B 0 x1234;跳转到绝对地址0 x1234处,2.4.1 跳转指令 带返回的跳转指令BL指
41、令,适用于子程序调用,使用该指令跳转之前,下一条指令的地址被拷贝到R14(即LR)连接寄存器中,然后跳转到指定地址运行程序。指令格式如下:BLcond Label,Addr1,Addr2,1.当程序执行到BL跳转指令时,硬件将下一条指令的地址Addr2装入LR寄存器,并把跳转地址装入程序计数器(PC),2.程序跳转到目标地址Label继续执行,当子程序执行结束后,将LR寄存器内容存入PC,返回调用函数继续执行,2.4.1 跳转指令 带状态切换的跳转指令BX指令,该指令可以根据跳转地址(Rm)的最低位来切换处理器状态。指令格式如下:BXcond Rm,2.4.1 跳转指令 带返回和状态切换的跳转
42、指令BLX指令,该指令跳转到指令中所指定的目标地址时,将处理器的工作状态由ARM状态切换到Thumb状态,使用该指令跳转之前,下一条指令的地址被拷贝到R14(即LR)连接寄存器中。指令格式如下:BLX LabelBLXcond Rm,2.4.2 数据处理指令 数据处理指令的作用是通过寄存器来对操作数进行计算,大致可分为3类:数据传送指令;算术逻辑运算指令;比较指令。数据处理指令只能对寄存器的内容进行操作,而不能对内存中的数据进行操作。所有ARM数据处理指令均可选择使用S后缀,以影响状态标志。比较指令CMP、CMN、TST和TEQ不需要后缀S,它们会直接影响状态标志。,数据传送指令,MOV MO
43、V指令将8位图立即数或寄存器传送到目标寄存器(Rd),可用于移位运算等操作。指令格式如下:MOVcondS Rd,operand2 举例如下:MOV R11,#0 xF000000B;R11=0 xF000000B MOV R0,R1;R0=R1 MOVS R3,R1,LSL#2;R3=R12,并影响标志位 MOV PC,LR;PC=LR,子程序返回,MVN MVN指令将8位图立即数或寄存器(operand2)按位取反后传送到目标寄存器(Rd),因为其具有取反功能,所以可以装载范围更广的立即数。指令格式如下:MVNcondS Rd,operand2 举例如下:MVN R1,#0 xFF;R1=
44、0 xFFFFFF00 MVN R1,R2;将R2按位取反,结果存到R1,算术运算指令,注:这些指令影响N,Z,C和V标志位。,加法运算指令ADD ADD指令将operand2的值与Rn的值相加,结果保存到Rd寄存器。指令格式如下:ADDcondS Rd,Rn,operand2 举例如下:ADDS R1,R1,#0 x1020;R1=R1+0 x1020 ADD R1,R1,R2,LSL#2;R1=R1+R24,减法运算指令SUB SUB指令用寄存器Rn减去operand2,结果保存到Rd中。指令格式如下:SUBcondS Rd,Rn,operand2 举例如下:SUB R1,R1,#0 x2
45、40;R1=R1-0 x240 SUBS R2,R1,R2;R2=R1-R2,逆向减法运算指令RSB RSB指令用operand2减去寄存器Rn,结果保存到Rd中。指令格式如下:RSBcondS Rd,Rn,operand2 举例如下:RSB R3,R1,#0 xff00;R3=0 xff00-R1 RSBS R1,R2,R2,LSL#2;R1=(R22)-R2=R23,带进位加法指令ADC ADC指令用operand2的值与寄存器Rn的值相加,再加上CPSR中的C条件标志位,结果保存到Rd中。指令格式如下:ADCcondS Rd,Rn,operand2 举例如下(使用ADC实现64位加法,第
46、一个数存放在寄存器R1和R0中,第二个数存放在寄存器R3和R2中,结果存于R1(高32位)和R0(低32位)中):ADDS R0,R0,R2;R0=R0+R2 ADC R1,R1,R3;R1=R1+R3+C,带进位减法指令SBC SBC指令用寄存器Rn减去operand2,再减去CPSR中的C条件标志位的非,结果保存到Rd中。指令格式如下:SBCcondS Rd,Rn,operand2 举例如下(使用SBC实现64位减法,第一个数存放在寄存器R1和R0中,第二个数存放在寄存器R3和R2中,结果存于R1(高32位)和R0(低32位)中):SUBS R0,R0,R2;R3=R0-R2 SBC R1
47、,R1,R3;R1=R1-R3-(C),带进位逆向减法指令RSC RSC指令用operand2减去寄存器Rn,再减去CPSR中的C条件标志位,结果保存到Rd中。指令格式如下:RSCcondS Rd,Rn,operand2 举例如下(使用RSC实现求64位数值的负数):RSBS R2,R0,#0;R2=-R0 RSC R3,R1,#0;R3=-R1-(C),逻辑运算指令,注:当后缀S时,这些指令根据结果更新标志N和Z,在计算Operand2时更新标志C,不影响标志V。,逻辑与操作指令AND AND指令将operand2的值与寄存器Rn的值按位作逻辑“与”操作,结果保存到Rd中。指令格式如下:AN
48、DcondS Rd,Rn,operand2 举例如下:ANDS R0,R0,#0 x1;R0=R0R2=R1&R3,逻辑或操作指令ORR ORR指令将operand2的值与寄存器Rn的值按位作逻辑“或”操作,结果保存到Rd中。指令格式如下:ORRcondS Rd,Rn,operand2 举例如下:ORR R0,R0,#0 xf;R0=R0|0 xf MOV R1,R2,LSR#24 ORR R3,R1,R3,LSL#8,使用ORR指令将R2的高8位数据移入到R3低8位中,逻辑异或操作指令EOR EOR指令将operand2的值与寄存器Rn的值按位作逻辑“异或”操作,结果保存到Rd中。指令格式如
49、下:EORcondS Rd,Rn,operand2 举例如下:EOR R0,R0,#0 xf;将R0的低4位取反 EOR R2,R1,R0 EOR R0,R5,#0 x01,位清除指令BIC BIC指令将寄存器Rn的值与operand2的值的反码按位作逻辑“与”操作,结果保存到Rd中。指令格式如下:BICcondS Rd,Rn,operand2 举例如下:BIC R1,R1,#0 xf;将R1的低4位清零 BIC R2,R1,R0,练习:MOV R1,#0 x3f000000MOV R11,R1ADD R2,R1,#0 x4LDR R10,=0 xc0fffff7MVN R3,R10MOV R
50、10,#0 x1STR R10,R1RSB R10,R10,#0 x3STR R10,R2MOV R10,R1,LSR#28ORR R11,R10,R11,LSL#8EOR R11,R11,#0 xfBIC R11,R11,#0 xfSTR R11,R3,比较指令,注:这些指令影响N,Z,C和V标志位。,比较指令CMP CMP指令将寄存器Rn的值减去operand2的值,根据操作结果更新CPSR中的相应条件标志位(N/Z/C/V),以便后面的指令根据相应的条件标志来判断是否执行。CMP与SUBS的区别在于CMP指令不保存运算结果。指令格式如下:CMPcond Rn,operand2 举例如下: