提纲 第四章 ARM指令分类及寻址方式 1 ARM 微处理器指令的分类 2 ARM 微处理器指令的条件域 3 ARM 微处理器指令的寻址方式
ARM微处理器的指令系统 ARM微处理器指令的分类 数据处理指令 程序状态寄存器(PSR)处理指令 加载/存储指令 跳转指令 异常产生指令 协处理器指令
ARM微处理器指令表-1 ARM微处理器指令的分类 助记符 指令功能描述 ADC 带进位加法指令 ADD 加法指令 AND 逻辑与指令 B 跳转指令 BIC 位清零指令 BL 带返回的跳转指令 BLX 带返回和状态切换的跳转指令 BX 带状态切换的跳转指令
ARM微处理器指令表-2 ARM微处理器指令的分类 助记符 指令功能描述 CDP 协处理器数据操作指令 CMN 比较反值指令 CMP 比较指令 EOR 异或指令 LDC 存储器到协处理器的数据传输指令 LDM 加载多个寄存器指令 LDR 存储器到寄存器的数据传输指令 MCR ARM寄存器到协处理器寄存器数据传输
ARM微处理器指令表-3 ARM微处理器指令的分类 助记符 指令功能描述 MLA 乘加运算指令 MOV 数据传送指令 MRC MRS 传送CPSR或SPSR的内容到通用寄存器 MSR 传送通用寄存器到CPSR或SPSR的指令 MUL 32位乘法指令 32位乘加指令 MVN 数据取反传送指令
ARM微处理器指令表-4 ARM微处理器指令的分类 助记符 指令功能描述 ORR 逻辑或指令 RSB 逆向减法指令 RSC 带借位的逆向减法指令 SBC 带借位减法指令 STC 协处理器寄存器写入存储器指令 STM 批量内存字写入指令 STR 寄存器到存储器的数据传输指令 SUB 减法指令
ARM微处理器指令表-5 ARM微处理器指令的分类 助记符 指令功能描述 SWI 软件中断指令 SWP 交换指令 TEQ 相等测试指令 TST 位测试指令
ARM微处理器指令的条件域 指令的条件域 当处理器工作在ARM状态时,几乎所有的指令均根据CPSR中条件码的状态和指令的条件域有条件的执行。当指令的执行条件满足时,指令被执行,否则指令被忽略。 每一条ARM指令包含4位的条件码,位于指令的最高4位[31:28]。条件码共有16种,每种条件码可用两个字符表示,这两个字符可以添加在指令助记符的后面和指令同时使用。例如,跳转指令B可以加上后缀EQ变为BEQ表示“相等则跳转”,即当CPSR中的Z标志置位时发生跳转。
指令的条件域表-1 ARM微处理器指令的条件域 条件码 后缀 标 志 含 义 0000 EQ Z置位 相等 0001 NE Z清零 不相等 0010 CS C置位 无符号数大于或等于 0011 CC C清零 无符号数小于 0100 MI N置位 负数 0101 PL N清零 正数或零 0110 VS V置位 溢出 0111 VC V清零 未溢出
指令的条件域表-2 ARM微处理器指令的条件域 条件码 后缀 标 志 含 义 1001 LS C清零Z置位 无符号数小于或等于 1010 GE N等于V 带符号数大于或等于 1011 LT N不等于V 带符号数小于 1100 GT Z清零且(N等于V) 带符号数大于 1101 LE Z置位或(N不等于V) 带符号数小于或等于 1110 AL 忽略 无条件执行
ARM指令的寻址方式 ARM微处理器指令的寻址方式 ARM指令系统支持如下几种常见的寻址方式: 立即寻址 寄存器寻址 寄存器间接寻址 基址变址寻址 堆栈寻址 多寄存器寻址 相对寻址
ARM微处理器指令的寻址方式 立即寻址 立即寻址也叫立即数寻址,这是一种特殊的寻址方式,操作数本身就在指令中给出,只要取出指令也就取到了操作数。这个操作数被称为立即数,对应的寻址方式也就叫做立即寻址。例如以下指令: ADD R0,R0,#1 /*R0←R0+1*/ ADD R0,R0,#0x3f /*R0←R0+0x3f*/ 在以上两条指令中,第二个源操作数即为立即数,要求以“#”为前缀,对于以十六进制表示的立即数,还要求在“#”后加上“0x”。
ARM微处理器指令的寻址方式 寄存器寻址 寄存器寻址就是利用寄存器中的数值作为操作数,这种寻址方式是各类微处理器经常采用的一种方式,也是一种执行效率较高的寻址方式。以下指令: ADD R0,R1,R2 /*R0←R1+R2*/ 该指令的执行效果是将寄存器R1和R2的内容相加,其结果存放在寄存器R0中。
寄存器间接寻址 ARM微处理器指令的寻址方式 寄存器间接寻址就是以寄存器中的值作为操作数的地址,而操作数本身存放在存储器中。例如以下指令: ADD R0,R1,[R2] /*R0←R1+[R2]*/ LDR R0,[R1] /*R0←[R1]*/ STR R0,[R1] /*[R1]←R0*/ 在第一条指令中,以寄存器R2的值作为操作数的地址,在存储器中取得一个操作数后与R1相加,结果存入寄存器R0中; 第二条指令将以R1的值为地址的存储器中的数据传送到R0中。 第三条指令将R0的值传送到以R1的值为地址的存储器中。
基址变址寻址 ARM微处理器指令的寻址方式 基址变址寻址就是将寄存器(该寄存器一般称作基址寄存器)的内容与指令中给出的地址偏移量相加,从而得到一个操作数的有效地址。变址寻址方式常用于访问某基地址附近的地址单元。采用变址寻址方式的指令常见有以下几种形式,如下所示: LDR R0,[R1,#4] ;R0←[R1+4] LDR R0,[R1,#4]! ;R0←[R1+4]、R1←R1+4 LDR R0,[R1] ,#4 ;R0←[R1]、R1←R1+4 LDR R0,[R1,R2] ;R0←[R1+R2] 在第一条指令中,将寄存器R1的内容加上4形成操作数的有效地址,从而取得操作数存入寄存器R0中。 在第二条指令中,将寄存器R1的内容加上4形成操作数的有效地址,从而取得操作数存入寄存器R0中,然后,R1的内容自增4个字节。 在第三条指令中,以寄存器R1的内容作为操作数的有效地址,从而取得操作数存入寄存器R0中,然后,R1的内容自增4个字节。 在第四条指令中,将寄存器R1的内容加上寄存器R2的内容形成操作数的有效地址,从而取得操作数存入寄存器R0中。
ARM微处理器指令的寻址方式 堆栈寻址 堆栈是一种数据结构,按先进后出(First In Last Out,FILO)的方式工作,使用一个称作堆栈指针的专用寄存器指示当前的操作位置,堆栈指针总是指向栈顶。 当堆栈指针指向最后压入堆栈的数据时,称为满堆栈(Full Stack),而当堆栈指针指向下一个将要放入数据的空位置时,称为空堆栈(Empty Stack)。
ARM微处理器指令的寻址方式 堆栈寻址 根据堆栈的生成方式,又可以分为递增堆栈(Ascending Stack)和递减堆栈(Decending Stack),当堆栈由低地址向高地址生成时,称为递增堆栈,当堆栈由高地址向低地址生成时,称为递减堆栈。这样就有四种类型的堆栈工作方式 满递增堆栈:堆栈指针指向最后压入的数据,且由低地址向高地址生成。 满递减堆栈:堆栈指针指向最后压入的数据,且由高地址向低地址生成。 空递增堆栈:堆栈指针指向下一个将要放入数据的空位置,且由低地址向高地址生成。 空递减堆栈:堆栈指针指向下一个将要放入数据的空位置,且由高地址向低地址生成
多寄存器寻址 ARM微处理器指令的寻址方式 采用多寄存器寻址方式,一条指令可以完成多个寄存器值的传送。这种寻址方式可以用一条指令完成传送最多16个通用寄存器的值。以下指令: LDMIA R0,{R1,R2,R3,R4} ;R1←[R0] ;R2←[R0+4] ;R3←[R0+8] ;R4←[R0+12] 该指令的后缀IA表示在每次执行完加载/存储操作后,R0按字长度增加,因此,指令可将连续存储单元的值传送到R1~R4。
ARM微处理器指令的寻址方式 相对寻址 与基址变址寻址方式相类似,相对寻址以程序计数器PC的当前值为基地址,指令中的地址标号作为偏移量,将两者相加之后得到操作数的有效地址。以下程序段完成子程序的调用和返回,跳转指令BL采用了相对寻址方式: BL NEXT ;跳转到子程序NEXT处执行 …… NEXT MOV PC,LR ;从子程序返回
第四章 ARM指令系统及汇编程序设计 提纲 1 ARM 指令系统 2 THUMB 指令系统 3 ATPCS 介绍 4 系统控制协处理器的寄存器允许对系统的高级控制,如转换表的位置。他们也用来 为ARM 提供内存异常的状态信息。 4 ARM和THUMB混合调用
数据处理指令 ARM 指令系统 数据处理指令可分为数据传送指令、算术逻辑运算指令和比较指令等。 数据传送指令用于在寄存器和存储器之间进行数据的双向传输。 算术逻辑运算指令完成常用的算术与逻辑的运算,该类指令不但将运算结果保存在目的寄存器中,同时更新CPSR中的相应条件标志位。 比较指令不保存运算结果,只更新CPSR中相应的条件标志位。 — MOV 数据传送指令 — MVN 数据取反传送指令 — CMP 比较指令 — CMN 反值比较指令 — TST 位测试指令 — TEQ 相等测试指令 — ADD 加法指令 — ADC 带进位加法指令 — SUB 减法指令 — SBC 带借位减法指令 — RSB 逆向减法指令 — RSC 带借位的逆向减法指令 — AND 逻辑与指令 — ORR 逻辑或指令 — EOR 逻辑异或指令 — BIC 位清除指令
数据处理指令—灵活的第二操作数 ARM 指令系统 如:ADD{cond}{S} Rd, Rn, Operand2 #immed_8r Rm{,shift} ADD r0, r1, #100 ADD r0, r1, r2 ADD r0, r1, r2, ASR #1 若指定S,则根据操作结果更新条件码标志 R0 = r1 + 100 R0 = r1 + r2 数据处理指令可分为数据传送指令、算术逻辑运算指令和比较指令等。数据传送指令用于寄存器和存储器之间进行数据的双向传输;算术逻辑运算指令完成常用的算术与逻辑运算,该类指令不但将运算结果保存在目的寄存器中,同时更新CPSR 中的相应条件标志位。比较指令不保存运算结果,只更新CPSR 中相应的条件标志位。 R0 = r1 + (r2算术右移一位)
数据处理指令—Shift 移位模式 ARM 指令系统 ASR n 算术右移n位(1<=n<=32) LSL n 逻辑左移n位(1<=n<=32) LSR n 逻辑右移n位(1<=n<=32) ROR n 循环右移n位(1<=n<=32) RRX 带扩展的循环右移1位 type Rs type = ASR/LSL/LSR/ROT BX 指令跳转到指令中所指定的目标地址,目标地址处的指令既可以是ARM 指令,也可以是Thumb 指令。并且将根据Rm的第0位来决定模式切换,为1时切换为THUMB,为0时切换为ARM。 如果使用第一种格式,Rm的第0位不用作地址的一部分。Rm的第0位为1,则指令将CPSR中的标志T置位,且将目标地址的代码解释为THUMB代码,即进行模式切换。 对于第二种格式,BLX 指令从ARM 指令集跳转到指令中所指定的目标地址,并将处理器的工作状态由ARM 状态切换到Thumb 状态。 该指令同时将PC 的当前内容保存到寄存器R14 中。同时,子程序的返回可以通过将寄存器R14 值复制到PC 中来完成。 算术右移保持符号位不变的右移; 逻辑左右移,补0 ROR,桶式移位 RRX,带进位位的移位
ASR ARM 指令系统 算术右移n位即Rm中的内容除以2的n次方。将原来的位[31]拷贝到寄存器左边的n位中,即空出的最高位补符号位。 BX 指令跳转到指令中所指定的目标地址,目标地址处的指令既可以是ARM 指令,也可以是Thumb 指令。并且将根据Rm的第0位来决定模式切换,为1时切换为THUMB,为0时切换为ARM。 如果使用第一种格式,Rm的第0位不用作地址的一部分。Rm的第0位为1,则指令将CPSR中的标志T置位,且将目标地址的代码解释为THUMB代码,即进行模式切换。 对于第二种格式,BLX 指令从ARM 指令集跳转到指令中所指定的目标地址,并将处理器的工作状态由ARM 状态切换到Thumb 状态。 该指令同时将PC 的当前内容保存到寄存器R14 中。同时,子程序的返回可以通过将寄存器R14 值复制到PC 中来完成。 算术右移保持符号位不变的右移; 逻辑左右移,补0 ROR,桶式移位 RRX,带进位位的移位
LSR和LSL ARM 指令系统 逻辑右移n位,即将Rm的内容除以2的n次方。寄存器左边的n位清零。 BX 指令跳转到指令中所指定的目标地址,目标地址处的指令既可以是ARM 指令,也可以是Thumb 指令。并且将根据Rm的第0位来决定模式切换,为1时切换为THUMB,为0时切换为ARM。 如果使用第一种格式,Rm的第0位不用作地址的一部分。Rm的第0位为1,则指令将CPSR中的标志T置位,且将目标地址的代码解释为THUMB代码,即进行模式切换。 对于第二种格式,BLX 指令从ARM 指令集跳转到指令中所指定的目标地址,并将处理器的工作状态由ARM 状态切换到Thumb 状态。 该指令同时将PC 的当前内容保存到寄存器R14 中。同时,子程序的返回可以通过将寄存器R14 值复制到PC 中来完成。 算术右移保持符号位不变的右移; 逻辑左右移,补0 ROR,桶式移位 RRX,带进位位的移位
ROR ARM 指令系统 循环右移n位,把寄存器右边的n位移动到结果的左边n位。 BX 指令跳转到指令中所指定的目标地址,目标地址处的指令既可以是ARM 指令,也可以是Thumb 指令。并且将根据Rm的第0位来决定模式切换,为1时切换为THUMB,为0时切换为ARM。 如果使用第一种格式,Rm的第0位不用作地址的一部分。Rm的第0位为1,则指令将CPSR中的标志T置位,且将目标地址的代码解释为THUMB代码,即进行模式切换。 对于第二种格式,BLX 指令从ARM 指令集跳转到指令中所指定的目标地址,并将处理器的工作状态由ARM 状态切换到Thumb 状态。 该指令同时将PC 的当前内容保存到寄存器R14 中。同时,子程序的返回可以通过将寄存器R14 值复制到PC 中来完成。 算术右移保持符号位不变的右移; 逻辑左右移,补0 ROR,桶式移位 RRX,带进位位的移位
RRX ARM 指令系统 带扩展的循环右移将Rm的内容循环右移一位。进位标志拷贝到Rm的位31。 BX 指令跳转到指令中所指定的目标地址,目标地址处的指令既可以是ARM 指令,也可以是Thumb 指令。并且将根据Rm的第0位来决定模式切换,为1时切换为THUMB,为0时切换为ARM。 如果使用第一种格式,Rm的第0位不用作地址的一部分。Rm的第0位为1,则指令将CPSR中的标志T置位,且将目标地址的代码解释为THUMB代码,即进行模式切换。 对于第二种格式,BLX 指令从ARM 指令集跳转到指令中所指定的目标地址,并将处理器的工作状态由ARM 状态切换到Thumb 状态。 该指令同时将PC 的当前内容保存到寄存器R14 中。同时,子程序的返回可以通过将寄存器R14 值复制到PC 中来完成。 算术右移保持符号位不变的右移; 逻辑左右移,补0 ROR,桶式移位 RRX,带进位位的移位
MOV指令 ARM 指令系统 MOV指令的格式为: MOV{条件}{S} 目的寄存器,源操作数 MOV指令可完成从另一个寄存器、被移位的寄存器或将一个立即数加载到目的寄存器。其中S选项决定指令的操作是否影响CPSR中条件标志位的值,当没有S时指令不更新CPSR中条件标志位的值。指令示例: MOV R1,R0 MOV R1,R0,LSL #3
MVN指令 ARM 指令系统 MVN指令的格式为: MVN{条件}{S} 目的寄存器,源操作数 MVN指令可完成从另一个寄存器、被移位的寄存器、或将一个立即数加载到目的寄存器。与MOV指令不同之处是在传送之前按位被取反了,即把一个被取反的值传送到目的寄存器中。其中S决定指令的操作是否影响CPSR中条件标志位的值,当没有S时指令不更新CPSR中条件标志位的值。 MVN R0,#0
CMP指令 ARM 指令系统 CMP指令的格式为: CMP{条件} 操作数1,操作数2 CMP指令用于把一个寄存器的内容和另一个寄存器的内容或立即数进行比较,同时更新CPSR中条件标志位的值。该指令进行一次减法运算,但不存储结果,只更改条件标志位。标志位表示的是操作数1与操作数2的关系(大、小、相等),例如,当操作数1大于操作操作数2,则此后的有GT 后缀的指令将可以执行。 CMP R1,R0 CMP R1,#100
CMN指令 ARM 指令系统 CMN指令的格式为: CMN{条件} 操作数1,操作数2 CMN指令用于把一个寄存器的内容和另一个寄存器的内容或立即数取反后进行比较,同时更新CPSR中条件标志位的值。该指令实际完成操作数1和操作数2相加,并根据结果更改条件标志位。 CMN R1,R0 CMN R1,#100
TST指令 ARM 指令系统 TST指令的格式为: TST{条件} 操作数1,操作数2 TST指令用于把一个寄存器的内容和另一个寄存器的内容或立即数进行按位的与运算,并根据运算结果更新CPSR中条件标志位的值。操作数1是要测试的数据,而操作数2是一个位掩码,该指令一般用来检测是否设置了特定的位。 TST R1,#1 TST R1,#0xffe
TEQ指令 ARM 指令系统 TEQ指令的格式为: TEQ{条件} 操作数1,操作数2 TEQ指令用于把一个寄存器的内容和另一个寄存器的内容或立即数进行按位的异或运算,并根据运算结果更新CPSR中条件标志位的值。该指令通常用于比较操作数1和操作数2是否相等。 TEQ R1,R2
ADD指令 ARM 指令系统 ADD指令的格式为: ADD{条件}{S} 目的寄存器,操作数1,操作数2 ADD R0,R1,R2 ADD R0,R1,#256 ADD R0,R2,R3,LSL#1
ADC指令 ARM 指令系统 ADC指令的格式为: ADC{条件}{S} 目的寄存器,操作数1,操作数2 ADC指令用于把两个操作数相加,再加上CPSR中的C条件标志位的值,并将结果存放到目的寄存器中。操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。 以下指令序列完成两个128位数的加法,第一个数存放在寄存器R7~R4,第二个数存放在寄存器R11~R8,运算结果存放在寄存器R3~R0: ADDS R0,R4,R8 ; 加低端的字 ADCS R1,R5,R9 ; 加第二个字,带进位 ADCS R2,R6,R10 ; 加第三个字,带进位 ADC R3,R7,R11 ; 加第四个字,带进位
SUB指令 ARM 指令系统 SUB指令的格式为: SUB{条件}{S} 目的寄存器,操作数1,操作数2 SUB R0,R1,R2 ; R0 = R1 - R2 SUB R0,R1,#256 ; R0 = R1 - 256 SUB R0,R2,R3,LSL#1 ; R0 = R2 - (R3 << 1)
SBC指令 ARM 指令系统 SBC指令的格式为: SBC{条件}{S} 目的寄存器,操作数1,操作数2 SBC指令用于把操作数1减去操作数2,再减去CPSR中的C条件标志位的反码,并将结果存放到目的寄存器中。操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。 SUBS R0,R1,R2
RSB指令 ARM 指令系统 RSB指令的格式为: RSB{条件}{S} 目的寄存器,操作数1,操作数2 RSB R0,R1,R2 RSB R0,R1,#256 RSB R0,R2,R3,LSL#1
RSC指令 ARM 指令系统 RSC指令的格式为: RSC{条件}{S} 目的寄存器,操作数1,操作数2 RSC指令用于把操作数2减去操作数1,再减去CPSR中的C条件标志位的反码,并将结果存放到目的寄存器中。操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。该指令使用进位标志来表示借位,这样就可以做大于32位的减法,注意不要忘记设置S后缀来更改进位标志。 RSC R0,R1,R2
AND指令 ARM 指令系统 AND指令的格式为: AND{条件}{S} 目的寄存器,操作数1,操作数2 AND R0,R0,#3
ORR指令 ARM 指令系统 ORR指令的格式为: ORR{条件}{S} 目的寄存器,操作数1,操作数2 ORR R0,R0,#3
EOR指令 ARM 指令系统 EOR指令的格式为: EOR{条件}{S} 目的寄存器,操作数1,操作数2 EOR R0,R0,#3
BIC指令 ARM 指令系统 BIC指令的格式为: BIC{条件}{S} 目的寄存器,操作数1,操作数2 BIC R0,R0,#0x0b
ARM 指令系统 乘法指令与乘加指令 ARM微处理器支持的乘法指令与乘加指令共有6条,可分为运算结果为32位和运算结果为64位两类,与前面的数据处理指令不同,指令中的所有操作数、目的寄存器必须为通用寄存器,不能对操作数使用立即数或被移位的寄存器,同时,目的寄存器和操作数1必须是不同的寄存器。 乘法指令与乘加指令共有以下6条: MUL 32位乘法指令 MLA 32位乘加指令 SMULL 64位有符号数乘法指令 SMLAL 64位有符号数乘加指令 UMULL 64位无符号数乘法指令 UMLAL 64位无符号数乘加指令
MUL指令 ARM 指令系统 MUL指令的格式为: MUL{条件}{S} 目的寄存器,操作数1,操作数2 MUL指令完成将操作数1与操作数2的乘法运算,并把结果放置到目的寄存器中,同时可以根据运算结果设置CPSR中相应的条件标志位。其中,操作数1和操作数2均为32位的有符号数或无符号数。 MUL R0,R1,R2 MULS R0,R1,R2
MLA指令 ARM 指令系统 MLA指令的格式为: MLA{条件}{S} 目的寄存器,操作数1,操作数2,操作数3 MLA指令完成将操作数1与操作数2的乘法运算,再将乘积加上操作数3,并把结果放置到目的寄存器中,同时可以根据运算结果设置CPSR中相应的条件标志位。其中,操作数1和操作数2均为32位的有符号数或无符号数。 MLA R0,R1,R2,R3 MLAS R0,R1,R2,R3
SMULL指令 ARM 指令系统 SMULL指令的格式为: SMULL{条件}{S} 目的寄存器Low,目的寄存器High,操作数1,操作数2 SMULL指令完成将操作数1与操作数2的乘法运算,并把结果的低32位放置到目的寄存器Low中,结果的高32位放置到目的寄存器High中,同时可以根据运算结果设置CPSR中相应的条件标志位。其中,操作数1和操作数2均为32位的有符号数。 SMULL R0,R1,R2,R3
SMLAL指令 ARM 指令系统 SMLAL指令的格式为: SMLAL{条件}{S} 目的寄存器Low,目的寄存器High,操作数1,操作数2 SMLAL指令完成将操作数1与操作数2的乘法运算,并把结果的低32位同目的寄存器Low中的值相加后又放置到目的寄存器Low中,结果的高32位同目的寄存器High中的值相加后又放置到目的寄存器High中,同时可以根据运算结果设置CPSR中相应的条件标志位。其中,操作数1和操作数2均为32位的有符号数。 对于目的寄存器Low,在指令执行前存放64位加数的低32位,指令执行后存放结果的低32位。 对于目的寄存器High,在指令执行前存放64位加数的高32位,指令执行后存放结果的高32位。 SMLAL R0,R1,R2,R3
UMULL指令 ARM 指令系统 UMULL指令的格式为: UMULL{条件}{S} 目的寄存器Low,目的寄存器低High,操作数1,操作数2 UMULL指令完成将操作数1与操作数2的乘法运算,并把结果的低32位放置到目的寄存器Low中,结果的高32位放置到目的寄存器High中,同时可以根据运算结果设置CPSR中相应的条件标志位。其中,操作数1和操作数2均为32位的无符号数。 UMULL R0,R1,R2,R3
UMLAL指令 ARM 指令系统 UMLAL指令的格式为: UMLAL{条件}{S} 目的寄存器Low,目的寄存器低High,操作数1,操作数2 UMLAL指令完成将操作数1与操作数2的乘法运算,并把结果的低32位同目的寄存器Low中的值相加后又放置到目的寄存器Low中,结果的高32位同目的寄存器High中的值相加后又放置到目的寄存器High中,同时可以根据运算结果设置CPSR中相应的条件标志位。其中,操作数1和操作数2均为32位的无符号数。 对于目的寄存器Low,在指令执行前存放64位加数的低32位,指令执行后存放结果的低32位。 对于目的寄存器High,在指令执行前存放64位加数的高32位,指令执行后存放结果的高32位。 UMLAL R0,R1,R2,R3
跳转指令 ARM 指令系统 跳转指令用于实现程序流程的跳转,在ARM程序中有两种方法可以实现程序流程的跳转: 使用专门的跳转指令。 直接向程序计数器PC写入跳转地址值。 ARM指令集中的跳转指令可以完成从当前指令向前或向后的32MB的地址空间的跳转,包括以下4条指令: B 跳转指令 BL 带返回的跳转指令 BLX 带返回和状态切换的跳转指令 BX 带状态切换的跳转指令
B指令 ARM 指令系统 B指令的格式为: B{条件} 目标地址 B指令是最简单的跳转指令。一旦遇到一个 B 指令,ARM 处理器将立即跳转到给定的目标地址,从那里继续执行。注意存储在跳转指令中的实际值是相对当前PC值的一个偏移量,而不是一个绝对地址,它的值由汇编器来计算。它是24位有符号数,左移两位后有符号扩展为 32 位,表示的有效偏移为 26 位(前后32MB的地址空间)。如: B Label /*程序无条件跳转到标号Label处执行*/
BL指令 ARM 指令系统 BL指令的格式为: BL{条件} 目标地址 BL 是另一个跳转指令,但跳转之前,会在寄存器R14中保存PC的当前内容,因此,可以通过将R14 的内容重新加载到PC中,来返回到跳转指令之后的那个指令处执行。该指令是实现子程序调用的一个基本但常用的手段。以下指令: BL Label /*当程序无条件跳转到标号Label处执行时,同时将当前的PC值保存到R14中 */
BLX指令 ARM 指令系统 BLX指令的格式为: BLX 目标地址 BLX指令从ARM指令集跳转到指令中所指定的目标地址,并将处理器的工作状态由ARM状态切换到Thumb状态,该指令同时将PC的当前内容保存到寄存器R14中。因此,当子程序使用Thumb指令集,而调用者使用ARM指令集时,可以通过BLX指令实现子程序的调用和处理器工作状态的切换。同时,子程序的返回可以通过将寄存器R14值复制到PC中来完成。
BX指令 ARM 指令系统 BX指令的格式为: BX{条件} 目标地址 BX指令跳转到指令中所指定的目标地址,目标地址处的指令既可以是ARM指令,也可以是Thumb指令。
ARM 指令系统 程序状态寄存器访问指令 ARM微处理器支持程序状态寄存器访问指令,用于在程序状态寄存器和通用寄存器之间传送数据,程序状态寄存器访问指令包括以下两条: MRS 程序状态寄存器到通用寄存器的数据传送指令 MSR 通用寄存器到程序状态寄存器的数据传送指令
程序状态寄存器(PSR)处理指令 MRS/MSR ARM 指令系统 程序状态寄存器(PSR)处理指令 MRS/MSR MRS 状态寄存器的内容读取到通用寄存器 MSR 立即数或通用寄存器内容写到状态寄存器的指定区域 MSR {cond} <PSR>_<fields>, #immed_8r MSR {cond} <PSR>_<fields>, rm fields: c 控制域(PSR[7:0]) x 扩展域(PSR[15:8]) s 状态域(PSR[23:16]) f 标志域(PSR[31:24])
MRS指令 ARM 指令系统 MRS指令的格式为: MRS{条件} 通用寄存器,程序状态寄存器(CPSR或SPSR) 当在异常处理或进程切换时,需要保存程序状态寄存器的值,可先用该指令读出程序状态寄存器的值,然后保存。 MRS R0,CPSR MRS R0,SPSR
MSR指令 ARM 指令系统 MSR指令的格式为: MSR{条件} 程序状态寄存器(CPSR或SPSR)_<域>,操作数 位[31:24]为条件标志位域,用f表示; 位[23:16]为状态位域,用s表示; 位[15:8]为扩展位域,用x表示; 位[7:0]为控制位域,用c表示; 该指令通常用于恢复或改变程序状态寄存器的内容,在使用时,一般要在MSR指令中指明将要操作的域。 MSR CPSR,R0 MSR CPSR_c,R0
加载/存储指令及批量数据加载/存储指令 ARM 指令系统 LDR 字数据加载指令 LDRB 字节数据加载指令 LDRH 半字数据加载指令 STR 字数据存储指令 STRB 字节数据存储指令 STRH 半字数据存储指令 LDM 批量数据加载指令 STM 批量数据存储指令
加载/存储指令(LDR/STR/LDM/STM) ARM 指令系统 加载/存储指令(LDR/STR/LDM/STM) LDR/STR:采用寄存器间接寻址和基变址寻址的方式 零偏移; LDR r0, [r1] STR r0, [r1] 程序相对偏移; LDR r0, =0x12345678 后索引偏移; LDR r0, [r13], #0x04 LDR r1, [r13], #0x04
加载/存储指令(LDR/STR/LDM/STM) ARM 指令系统 加载/存储指令(LDR/STR/LDM/STM) 前索引偏移; OP{cond} Rd, [Rn, offset] {!} Offset 就是数据处理指令中的第二操作数; !为一个可选的后缀,即是否修改Rn Rn为R15时不能选择该后缀; LDR r0, [r1, #0x04] LDR r0, [r1, #0x04]! LDR r0, [r1, r2, ASR #2]!
LDM/STM可以传送R0-R15的任意组合 ARM 指令系统 OP {cond} mode Rn{!}, reglist{^} mode: IA 每次传送后地址加1 FD 满递减堆栈 IB 每次传送前地址加1 ED 空递减堆栈 DA 每次传送后地址减1 FA 满递增堆栈 DB 每次传送前地址减1 EA 空递增堆栈
LDM/STM后缀描述 ARM 指令系统 ! 回写使能标志 ^ 是否拷贝SPSR到CPSR LDMIA r0, {r1, r2, r3, r4} LDMIA r0!, {r1, r2, r3, r4} STMFD r13!, {r0, r4-r7, LR} ;子程序入口 LDMFD r13!, {r0, r4-r7, PC} ;子程序返回
LDR指令 ARM 指令系统 LDR指令的格式为: LDR{条件} 目的寄存器,<存储器地址> LDR指令用于从存储器中将一个32位的字数据传送到目的寄存器中。该指令通常用于从存储器中读取32位的字数据到通用寄存器,然后对数据进行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。该指令在程序设计中比较常用,且寻址方式灵活多样,请读者认真掌握。 LDR R0,[R1] LDR R0,[R1,R2] LDR R0,[R1,#8] LDR R0,[R1,R2] ! LDR R0,[R1,#8] ! LDR R0,[R1],R2 LDR R0,[R1,R2,LSL#2]! LDR R0,[R1],R2,LSL#2
LDRB指令 ARM 指令系统 LDRB指令的格式为: LDR{条件}B 目的寄存器,<存储器地址> LDRB指令用于从存储器中将一个8位的字节数据传送到目的寄存器中,同时将寄存器的高24位清零。该指令通常用于从存储器中读取8位的字节数据到通用寄存器,然后对数据进行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。 LDRB R0,[R1] LDRB R0,[R1,#8]
LDRH指令 ARM 指令系统 LDRH指令的格式为: LDR{条件}H 目的寄存器,<存储器地址> LDRH指令用于从存储器中将一个16位的半字数据传送到目的寄存器中,同时将寄存器的高16位清零。该指令通常用于从存储器中读取16位的半字数据到通用寄存器,然后对数据进行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。 LDRH R0,[R1] LDRH R0,[R1,#8] LDRH R0,[R1,R2] ;将存储器地址为R1+8的半字数据读入寄存器R0,并将R0的高16位清零。 ;将存储器地址为R1+R2的半字数据读入寄存器R0,并将R0的高16位清零。
STR指令 ARM 指令系统 STR指令的格式为: STR{条件} 源寄存器,<存储器地址> STR指令用于从源寄存器中将一个32位的字数据传送到存储器中。该指令在程序设计中比较常用,且寻址方式灵活多样,使用方式可参考指令LDR。 STR R0,[R1],#8 STR R0,[R1,#8] ;将R0中的字数据写入以R1为地址的存储器中,并将新地址R1+8写入R1。 ;将R0中的字数据写入以R1+8为地址的存储器中。
STRB指令 ARM 指令系统 STRB指令的格式为: STR{条件}B 源寄存器,<存储器地址> STRB R0,[R1] STRB R0,[R1,#8] ;将寄存器R0中的字节数据写入以R1为地址的存储器中。 ;将寄存器R0中的字节数据写入以R1+8为地址的存储器中。
STRH指令 ARM 指令系统 STRH指令的格式为: STR{条件}H 源寄存器,<存储器地址> STRH R0,[R1] STRH R0,[R1,#8] ;将寄存器R0中的半字数据写入以R1为地址的存储器中。 ;将寄存器R0中的半字数据写入以R1+8为地址的存储器中。
ARM 指令系统 批量数据加载/存储指令 ARM微处理器所支持批量数据加载/存储指令可以一次在一片连续的存储器单元和多个寄存器之间传送数据,批量加载指令用于将一片连续的存储器中的数据传送到多个寄存器,批量数据存储指令则完成相反的操作。常用的加载存储指令如下: LDM 批量数据加载指令 STM 批量数据存储指令
LDM(或STM)指令 ARM 指令系统 LDM(或STM)指令的格式为: LDM R0!, {r0-r4}
ARM 指令系统 {类型}为以下几种情况 IA 每次传送后地址加1; IB 每次传送前地址加1; DA 每次传送后地址减1; DB 每次传送前地址减1; FD 满递减堆栈; ED 空递减堆栈; FA 满递增堆栈; EA 空递增堆栈;
后缀 ARM 指令系统 {!}为可选后缀,若选用该后缀,则当数据传送完毕之后,将最后的地址写入基址寄存器,否则基址寄存器的内容不改变。 基址寄存器不允许为R15,寄存器列表可以为R0~R15的任意组合。 {∧}为可选后缀,当指令为LDM且寄存器列表中包含R15,选用该后缀时表示:除了正常的数据传送之外,还将SPSR复制到CPSR。同时,该后缀还表示传入或传出的是用户模式下的寄存器,而不是当前模式下的寄存器。 STMFD R13!,{R0,R4-R12,LR} LDMFD R13!,{R0,R4-R12,PC} ;将寄存器列表中的寄存器(R0,R4到R12,LR)存入堆栈。;将堆栈内容恢复到寄存器(R0,R4到R12,LR)。
数据交换指令 ARM 指令系统 ARM微处理器所支持数据交换指令能在存储器和寄存器之间交换数据。数据交换指令有如下两条: SWP 字数据交换指令 SWPB 字节数据交换指令
SWP指令 ARM 指令系统 SWP指令的格式为: SWP{条件} 目的寄存器,源寄存器1,[源寄存器2] SWP R0,R1,[R2] SWP R0,R0,[R1] ;将R2所指向的存储器中的字数据传送到R0,同时将R1中的字数据传送到R2所指向的存储单元。 ;该指令完成将R1所指向的存储器中的字数据与R0中的字数据交换。
SWPB指令 ARM 指令系统 SWPB指令的格式为: SWP{条件}B 目的寄存器,源寄存器1,[源寄存器2] SWPB R0,R1,[R2] SWPB R0,R0,[R1] ;将R2所指向的存储器中的字节数据传送到R0,R0的高24位清零,同时将R1中的低8位数据传送到R2所指向的存储单元。 ;该指令完成将R1所指向的存储器中的字节数据与R0中的低8位数据交换。
ARM 指令系统 异常产生指令 ARM微处理器所支持的异常指令有如下两条: SWI 软件中断指令 BKPT 断点中断指令
SWI指令 ARM 指令系统 SWI指令的格式为: SWI{条件} 24位的立即数 SWI指令用于产生软件中断,以便用户程序能调用操作系统的系统例程。操作系统在SWI的异常处理程序中提供相应的系统服务,指令中24位的立即数指定用户程序调用系统例程的类型,相关参数通过通用寄存器传递,当指令中24位的立即数被忽略时,用户程序调用系统例程的类型由通用寄存器R0的内容决定,同时,参数通过其他通用寄存器传递。 SWI 0x02 ;该指令调用操作系统编号位02的系统例程。
ARM 指令系统 BKPT指令 BKPT指令的格式为: BKPT 16位的立即数 BKPT指令产生软件断点中断,可用于程序的调试。
ARM 指令系统 协处理器指令 ARM微处理器可支持多达16个协处理器,用于各种协处理操作,在程序执行的过程中,每个协处理器只执行针对自身的协处理指令,忽略ARM处理器和其他协处理器的指令。 ARM的协处理器指令主要用于ARM处理器初始化ARM协处理器的数据处理操作,以及在ARM处理器的寄存器和协处理器的寄存器之间传送数据,和在ARM协处理器的寄存器和存储器之间传送数据。ARM协处理器指令包括以下5条: CDP 协处理器数操作指令 LDC 协处理器数据加载指令 STC 协处理器数据存储指令 MCR 寄存器到协处理器寄存器的数据传送指令 MRC 协处理器寄存器到寄存器的数据传送指令
CDP指令 ARM 指令系统 CDP指令的格式为: CDP指令用于ARM处理器通知ARM协处理器执行特定的操作,若协处理器不能成功完成特定的操作,则产生未定义指令异常。其中协处理器操作码1和协处理器操作码2为协处理器将要执行的操作,目的寄存器和源寄存器均为协处理器的寄存器,指令不涉及ARM处理器的寄存器和存储器。 CDP P3,2,C12,C10,C3,4 ;该指令完成协处理器P3的初始化
LDC指令 ARM 指令系统 LDC指令的格式为: LDC{条件}{L} 协处理器编码,目的寄存器,[源寄存器] LDC P3,C4,[R0] ;将ARM处理器的寄存器R0所指向的存储器中的字数据传送到协处理器P3的寄存器C4中。
STC指令 ARM 指令系统 STC指令的格式为: STC{条件}{L} 协处理器编码,源寄存器,[目的寄存器] STC P3,C4,[R0] ;将协处理器P3的寄存器C4中的字数据传送到ARM处理器的寄存器R0所指向的存储器中。
MCR指令 ARM 指令系统 MCR指令的格式为: MCR指令用于将ARM处理器寄存器中的数据传送到协处理器寄存器中,若协处理器不能成功完成操作,则产生未定义指令异常。其中协处理器操作码1和协处理器操作码2为协处理器将要执行的操作,源寄存器为ARM处理器的寄存器,目的寄存器1和目的寄存器2均为协处理器的寄存器。 MCR P3,3,R0,C4,C5,6 ;该指令将ARM处理器寄存器R0中的数据传送到协处理器P3的寄存器C4和C5中。
MRC指令 ARM 指令系统 MRC指令的格式为: MRC指令用于将协处理器寄存器中的数据传送到ARM处理器寄存器中,若协处理器不能成功完成操作,则产生未定义指令异常。其中协处理器操作码1和协处理器操作码2为协处理器将要执行的操作,目的寄存器为ARM处理器的寄存器,源寄存器1和源寄存器2均为协处理器的寄存器。 MRC P3,3,R0,C4,C5,6 ;该指令将协处理器P3的寄存器中的数据传送到ARM处理器寄存器中。
Thumb指令集 THUMB 指令系统 Thumb指令集是针对代码密度的问题而提出的。可以看作是ARM指令集的子集。 所有Thumb指令均有对应的ARM指令,而Thumb编程模型也对应于Thumb模型。 Thumb是一个不完整的体系结构,不能指望处理器只执行Thumb代码而不支持ARM指令集。一般Thumb代码只需支持通用功能,必要时可以借助ARM指令集(例:所有异常自动进入ARM模式) 应用程序可以灵活的将ARM指令和Thumb程序混合,以便提高性能和代码密度。同时达到降低功耗、节约成本和提高性能的目的。
Thumb指令集的执行 THUMB 指令系统 在任何时刻,对指令流的解释取决于CPSR的第5位,即位T,若T置位,则认为指令流为16位的Thumb指令;否则为标准的ARM指令。 并不是所有的ARM处理器都支持Thumb指令。只有在命名中有字母T的才支持,例如以上提到的ARM7TDMI。
Thumb模式的进入和退出 THUMB 指令系统 复位后,ARM启动并执行ARM指令。转向执行Thumb指令的通常方法是执行一条交换转移指令BX。若BX指令指定的寄存器的最低位为1,则将T置位,并将程序计数器切换为寄存器其他位给出的地址。 异常返回也可以将微处理器从ARM状态转换为Thumb状态。通常这种指令用于返回到进入异常前所执行的指令流,而不是特地用于转换到Thumb模式。 执行Thumb BX指令可以显式地返回到ARM指令流。
THUMB 指令系统 Thumb转移指令 ARM指令有一个大的(24位)偏移域(offsetfield),这不可能在16位Thumb指令格式中表示。为此,Thumb指令集有多种方法实现其于功能。 格式 B {cond} <lable> B <lable> BL <lable> BLX <lable> B{L}X Rm 转移指令的典型用法如下: 1)短距离条件转移指令可用于控制循环的退出。 2)中等距离的无条件转移指令用于实现goto功能。 3)长距离子程序调用.
Thumb转移指令 — B <label>指令 B {cond} <label> /*8位偏移,目标为Thumb代码 */ B <label> /*11位偏移,目标为Thumb代码 */ 这两种格式是条件域和偏移长度的折衷。指令首先将偏移值左移1位,实现16位对齐,然后扩展到32位,因此他们的偏移量分别为±256字节和±2K字节。
Thumb转移指令 — BL <label>指令 BL <label> /*11位偏移,目标为Thumb代码 */ 转移链接子程序通常需要一个大的范围,很难用16位指令 格式实现.为此,Thumb采用两条这样格式的指令组合成22位半字偏移(符号扩展为32位),使指令转移范围为±4MB。 为了使这两条转移指令相互独立,以致使他们之间也能响应中断等,将链接寄存器LR作为暂存器使用,LR在这两条指令执行完成后会被覆盖,因此,LR中不能装有有效内容。这个指令对的操作如下: (第一条) LR:=PC+(偏移量左移12后符号扩展至32位) (第二条) PC:=LR+(偏移量左移1位) LR=oldPC+3 这里,oldPC是第2条指令的地址;加3使产生的地址指向下一条指令,并且使最 低位置位以指示这是一个Thumb程序。
Thumb转移指令 — BLX <label>指令 BLX <label> /*目标为ARM代码 */ 该指令只在v5T结构中有效。它使用与上面BL指令同样的第一步,即 (第一条) LR:=PC+(偏移量左移12后符号扩展至32位) (第二条) PC:=LR+(偏移量左移1位) &0xffff_fffc LR=oldPC+3 Thumb位清0。 应注意转移的目标是ARM指令,偏移地址只需要10位,而且PC值的位[1]可能为1,因此,必须进行清0操作。
Thumb转移指令 — BLX Rm指令 THUMB 指令系统 B{L}X Rm 目标为ARM代码或Thumb代码 与上一条代码不同的就是r14的值为后续地址加1,以表示被Thumb代码调用。
Thumb软中断指令 THUMB 指令系统 Thumb软中断指令的行为与ARM等价指令完全相同。进入异常的指令使微处理器进入ARM执行状态。 该代码使用8位立即数,这将会把Thumb代码的SWI指令限制到前256种,而ARM的SWI指令可以达到l 600万种。
Thumb数据处理指令 THUMB 指令系统 Thumb数据处理指令包括一组高度优化且相当复杂的指令,范围涵盖编译器通常需要的大多数操作。 在Thumb指令集中有等价指令的ARM数据处理指令如下所列: 使用低8个通用寄存器(r0-r7)的指令: ARM指令 Thumb指令 MOVS Rd.#<#imm8> MOV Rd,#<#imm8> MVNS Rd,Rm MVN Rd,Rm CMP Rn.#<#imm8> CMP Rn,#<#imm8>
Thumb数据处理指令与等价的 ARM指令 ARM指令 Thumb指令 CMP Rn,Rm CMP Rn,Rm CMN Rn,Rm CMN Rn,Rm TST Rn,Km TST Rn,Rm ADDS Rd,Rn,#<#Imm3> ADD Rd,Rn,#<#imm3> ADDS Rd,Rd,#<#lmm8> ADD Rd,#<#imm8> ADDS Rd,Rn,Rm ADD Rd,Rn,Rm ADCS Rd,Rd,Rm ADC Rd,Rm SUBS Rd, Rn,#<#imm3> SUB Rd,Rn,#<#imm3> SUBS Rd,Rd,#<#imm8> SUB Rd,#<#imm8>
Thumb数据处理指令与等价的 ARM指令 ARM指令 Thumb指令 SUBS Rd,Rn,Rm SUB Rd,Rn,Rm SBCS Rd,Rd.Rm SBC Rd,Rm RSBS Rd,Rn,#0 NEG Rd.Rn MOVS Rd,Rm,LSL #<#sh> LSL Rd,Rm.#<#sh> MOVS Rd,Rd,LSL Rs LSL Rd,R9 MOVS Rd,Rm,LSR#<#sh> LSR Rd,Rm,#<#sh> MOVS Rd,Rd,LSR Rs LSR Rd,Rs MOVS Rd,Rm, ASR#<#sh> ASR Rd,Rm,#<#sh> MOVS Rd,Rd,ROR Rs ASR Rd, Rs
Thumb数据处理指令与等价的 ARM指令 ARM指令 Thumb 指令 MOVS Rd,Rd,ROR Rs ROR Rd, Rs ANDS Rd,Rd,Rm AND Rd, Rm EORS Rd,Rd,Rm EOR Rd,Rm ORRS Rd,Rd.Rm ORR Rd,Rm BICS Rd,Rd,Rm BIC Rd,Rm MULS Rd,Rm,Rd MUL Rd,Rm
Thumb数据处理指令与等价的 ARM指令 使用高8个寄存器(r8~r15)的指令,在有些情况下结合低8个寄存器使用: ARM指令 Thumb 指令 ADD Rd,Rd,Rm ADD Rd,Rm(1/2 Hi regs) CMP Rn,Rm CMP Rn,Rm(1/2 Hi regs) MOV Rd,Rm ADD Rd,Rm(1/2 Hi regs) ADD Rd, pc,#<#imm8> ADD Rd,pc,#(#imm8> ADD Rd,sp,#<#imm8> ADD Rd,sp,#<#imm8> ADD sp,sp,#<#imm8> ADD sp,sp,#<#imm8> SUB sp,sp,#<#imm8> SUB sp,sp,#<#imm8>
Thumb数据处理指令与等价的 ARM指令 注意事项: 所有对低8个寄存器操作的数据处理指令都更新条件码位(等价的ARM指令位s置位)。 对高8个寄存器操作的指令不改变条件码位。CMP指令除外,它只改变条件码。 上面的指令中“1/2 Hi regs"表示至少有1个寄存器操作数是高8位寄存器。 #imm3、#imm7、#imm8分别表示3位、7位和8位立即数域。#sh表示5位的移位数域。
Thumb单寄存器数据传送指令 THUMB 指令系统 LDR|STR{B} Rd,[Rn, #off5] LDRH | STRH Rd,[Rn,#off5] LDR|STR{S}{H|B} Rd,[Rn,Rm] LDR Rd, [pc, #off8] LDR |STR Rd,[sp,#off8] 说 明 这些指令是从ARM单寄存器传送指令中精心导出的子集,并且与等价的ARM指令有严格相同的语义。 在所有的指令中,对偏移量需要根据数据类型按比例调整。例如,5位偏移量的范围在字节Load和Store指令中是32字节,在半字Load和Store指令中是64字节,在字Load和Store指令中是128字节
Thumb多寄存器数据传送指令 THUMB 指令系统 同ARM指令一样,Thumb多寄存器数据传送指令可以用于过程调用与返回以及存储器块拷贝。但为了编码的紧凑性,这两种用法由分开的指令实现,其寻址方式的数量也有所限制,在其他方面,这些指令的性质与等价的ARM指令相同。 LDMIA Rn!,{<reg list>} STMIA Rn!,{<reg Iist>} POP {<reg list> {,pc}} PUSH {<reg list> {,1r}}
Thumb多寄存器数据传送指令 THUMB 指令系统 指令的块拷贝形式使用LDMIA和STMlA寻址模式。寄存器 (低8个寄存器r0~r7)中的任何一个可以作为基址寄存器。 寄存器列表可以是这些寄存器的任意子集,但不应包括基址寄存器,因为总是选择回写。 堆栈形式使用SP(r13)作为基址寄存器,并且也总是使用回写。堆栈的模式也固定为满栈递减。寄存器列表除了可以是8个Lo寄存器外,链接寄存器LR可以出现在PUSH指令中,PC可以出现在POP指令中,以优化过程调用及返回程序。
Thumb的应用 THUMB 指令系统 高端的32位ARM系统可以用Thumb代码实现特定的非关键程序,以节省功耗或降低对存储器的需求。 低端的16位系统可以有小规模的32位片上RAM供运行ARM代码的关键程序使用,所有非关键程序使用片外Thumb代码。 上面第二种情况或许更接近于Thumb所适宜的应用。在移动电话和寻呼机的应用中,需要ARM最大处理能力的实时信号处理(DSP)功能.但这些程序可以紧凑编码井放在小规模的片上存储器中。那些控制用户界面、电池管理系统等等复杂的比较长的代码是非实时的,可由Thumb代码放在片外ROM中,由8位或16位总线就可以得到好的性能,同时降低成本和延长电池寿命。
ATPCS介绍 ATPCS 为了使单独编译的c语言程序和汇编程序之间能够相互调用,必须为程序间的调用规定一定的规则。ATPCS就是ARM程序和Thumb程序中子程序调用的基本规则。 ATPCS规定了一些子程序间调用的基本规则。这些基本规则包括子程序调用过程中寄存器的使用规则,数据栈的使用规则,参数的传递规则。 为适应一些特定的需要,对这些基本的调用规则进行一些修改得到几种不同的子程序调用规则。这些特定的调用规则包括:
ATPCS介绍 支持数据栈限制检查的ATPCS。 支持只读段位置无关(ROPl)的ATPCS。 支持可读写段位置无关(RWPl)的ATPCS。 支持ARM程序和Thumb程序混合使用的ATPCS。 处理浮点运算的ATPCS。 有调用关系的所有子程序必须遵守同一·种ATPCS。编译器或者汇编器在ELF格式的目标文件中设置相应的属性,标识用户选定的ATPCS类型。 对应于不同类型的ATPCS规则,有相应的c语言库,连接器根据用户指定的ATPCS类型连接相应的c语言库。
ATPCS介绍 使用C语言编泽器编译的C语言子程序满足用户指定的ATPCS类型.而对于汇编语言程序来说,完全要依赖用户来保证各子程序满足选定的ATPCS类型。具体来说,汇编语言子程序必须满足下面3个条件: 在于程序编写时必须遵守相应的ATPCS规则。 数据栈的使用要遵守相应的ATPCS规则. 在汇编编译器中使甩—atpcs选项。
基本ATPCS ATPCS介绍 基本ATPCS规定了在子程序调用时的一些基本规则,包括下面3方面的内容: 各寄存器的使用规则及其相应的名称。 数据栈的使用规则。 参数传递的规则。
ATPCS介绍 相对于其他类型的ATPCS,满足基本ATPCS的程序的执行速度更快,所占用的内存更少。但是它不能提供以下的支持: ARM程序和Thumb程序相互调用。 数据以及代码的位置无关的支持。 子程序的可重入性。 数据栈检查的支持。 而派生的其他几种特定的ATPCS就是在基本ATPCS的基础上再添加其他的规则而形成的。其目的就是提供上述的功能。
寄存器的使用规则 ATPCS介绍 寄存器的使用必须满足下面的规则: 子程序间通过寄存器 R0一R3来传递参数,这时,寄存器R0~R3可以记作A1-A4。被调用的子程序在返回前无需恢复寄存器R0~R3的内容。 在子程序中,使用寄存器R4~R11来保存局部变量.这时,寄存器 R4 ~ R11可以记作V1 ~ V8。如果在子程序中使用到了寄存器V1~V8中的某些寄存器,子程序进入时必须保存这些寄存器的值,在返回前必须恢复这些寄存器的值;对于子程序中没有用到的寄存器则不必进行这些操作。在Thumb程序中,通常只能使用寄存器R4~R7来保存局部变量。
ATPCS介绍 寄存器R12用作子程序间scratch寄存器(用于保存SP,在函数返回时使用该寄存器出栈),记作ip。在子程序间的连接代码段中常有这种使用规则。 寄存器R13用作数据栈指针,记作sp。在子程序中寄存器R13不能用作其他用途。寄存器sp在进入子程序时的值和退出子程序时的值必须相等。 寄存器R14称为连接寄存器,记作lr。它用于保存子程序的返回地址。如果在子程序中保存了返回地址,寄存器R14则可以用作其他用途。 寄存器R15是程序计数器,记作pc。它不能用作其他用途。
ATPCS中各寄存器的使用规则及其名称 ATPCS介绍 别名 特殊名称 使用规则 R15 Pc 程序计数器 R14 Lr 连接寄存器 R13 Sp 数据栈指针 R12 ip 于程序内部调用的scratch寄存器 R11 v8 ARM状态局部变量寄存器8 R10 V7 si ARM状态局部变量寄存器7,在支持数据栈检查的ATPCS中为数据栈限制指针
ATPCS介绍 寄存器 别名 特殊名称 使用规则 R9 v6 sb ARM状态局部变量寄存器6,在支持RWPI的ATPCS中为静态基址寄存器 v6 sb ARM状态局部变量寄存器6,在支持RWPI的ATPCS中为静态基址寄存器 R8 v5 ARM状态局部变量寄存器5 R7 V4 wr 局部变量寄存器4,Thumb状态工作寄存器 R6 V3 局部变量寄存器3 R5 v2 局部变量寄存器2 R4 v1
ATPCS介绍 寄存器 别名 特殊名称 使用规则 R3 A4 参数/结果/scratch寄存器4 R2 A3 参数/结果/scratch寄存器4 R2 A3 参数/结果/scratch寄存器3 R1 A2 参数/结果/scratch寄存器2 R0 A1 参数/结果/scratch寄存器1
ATPCS介绍 数据栈使用规则 栈指针通常可以指向不同的位置。当栈指针指向栈顶元素(即最后一个入栈的数据元素)时,称为FULL栈;当栈指针指向与栈顶元素(即最后一·个入栈的数据元素)相邻的一个可用数据单元时,称为EMPTY栈。 数据栈的增长方向也可以不同。当数据栈向内存地址减小的方向增长时,称为DESCENDING栈,当数据栈向内存地址增加的方向增长时,称为ASCENDING栈。 综合这两种特点可以有以下4种数据栈。 FD Full Descending ED Empty Descending FA Full Ascending EA Empty Ascending
ATPCS介绍 ATPCS规定数据栈为FD类型,并且对数据栈的操作是8字节对齐的。 异常中断的处理程序可以使用被中断程序的数据钱,这时用户要保证中断的程序的数
ATPCS介绍 参数传递规则 根据参数个数是否固定可以将子程序分为参数个数固定的(nonvariadic)子程序和参数个数可变的(variadic)子程序。这两种子程序的参数传递规则是不同的 参数个数可变的子程序参数传递规则: 对于参数个数可变的子程序,当参数不超过4个时,可以使用寄存器R0~R3来传递参数;当参数超过4个时,还可以使用数据栈来传递参数。 在参数传递时,将所有参数看作是存放在连续的内存字单元中的宇数据。然后,依次将各字数据传送到寄存器R0、Rl、R2、R3中,如果参数多于4个,将剩余的字数据传送到数据栈中,入栈的顺序与参数顺序相反,即最后一个字数据先入栈。
参数个数固定的子程序参数传递规则 ATPCS介绍 对于参数个数固定的子程序,参数传递与参数个数可变的子程序参数传递规则不同。 如果系统包含浮点运算的硬件部件,浮点参数将按照下面的规则传递: 各个浮点参数按顺序处理。 为每个浮点参数分配FP寄存器。 分配的方法是,满足该浮点参数需要的且编号最小的一组连续的FP寄存器。 第一个整数参数,通过寄存器R0~R3来传递。其他参数通过数据栈传递。
子程序结果返回规则 ATPCS介绍 结果为一个32位的整数时,可以通过寄存器R0返回。 结果为一个64位整数时,可以通过寄存器R0和R1返回,依次类推。 结果为一个浮点数时,可以通过浮点运算部件的寄存器f0、d0或者s0来返回。 结果为复合型的浮点数(如复数)时,可以通过寄存铅f0~fn或者d0~dn来返回。 对于位数更多的结果,需要通过内存来传递。
ARM程序和Thumb程序混合使用的ATPCS 在编译和汇编时,使用/interwork告诉编译器生成的目标代码遵守支持ARM程序和Thumb程序混合使用的ATPCS。它用在以下场合: 程序中存在ARM程序调用Thumb程序的情况。 程序中存在Thumb程序调用ARM程序的情况。 需要连接器来进行ARM状态和Thumb状态切换的情况。 在下述情况下,使用选项/nointerwork。 程序中不包含Thumb程序。 用户自己进行ARM状态和Thumb状态切换。 其中,选项/nointerwork是默认的选项。 需要注意的是,在同一个C/C++源程序中不能同时包含ARM指令和Thumb指令,但汇编可以。
ARM程序和Thumb程序混合使用 ARM和THUMB混合调用 如果程序遵守支持ARM程序和Thumb程序混合使用的ATPCS,则程序中ARM子程序和Thumb子程序可以相互调用。对于C/C++源程序而言,只要在编译时指定apcs/interwork选项,编译器生成的代码会自动遵守支持ARM程序和Thumb程序混合使用的ATPCS。而对于汇编源程序而言,必须保证编写的代码遵守支持ARM程序和Thumb程序混合使用的ATPCS。
在汇编语言程序中通过用户代码支持interwork ARM和THUMB混合调用 在汇编语言程序中通过用户代码支持interwork 在版本4中可以实现程序状态切换的指令是BX。 从版本5开始,下面的指令也可以实现程序状态的切换: ● BLX ● LDR、LDM及POP
进行状态切换的汇编程序实例 ARM和THUMB混合调用 .ARM ADR r0,ThumbProg+1 BX r0 /*跳到ThumbProg,程序切换到Thumb状志*/ .THUMB /*THUMB指示编译器后面的为Thumb指令*/ ThumbProg: ... ADR r0,ARMProg BX r0 /*跳转到ARMProg,程序切换到ARM状态*/ .ARM /*.ARM指示编译器后面的为ARM指令*/ ARMProg: MOV r4, #4