版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
主要内容1ARM指令集概述
2ARM汇编语言设计ARM指令集ARM指令集主要包括6大类指令:数据处理指令:如ADD、SUB、AND等加载-存储(Load-Store)指令:如LDR等分支指令:如B、BL等状态寄存器访问指令:如MRS、MSR等协处理器指令:如LDC、STC等异常处理指令:如SWI等ARM指令集ARM指令集的特点所有ARM指令都是32位定长的加载-存储(Load-Store)架构
提供功能强大的一次加载和存储多个寄存器的指令
CPU内核硬件中提供了桶型(barrel)移位器,移位操作可以内嵌在其他指令中所有的ARM指令都是可以条件执行的
ARM指令集:示例THUMB指令集Thumb指令集是16位的指令集,它对C代码的密度进行了优化,平均达到约ARM代码大小的65%。为了尽量降低指令编码长度,Thumb指令集具体采用了如下约束:不能使用条件执行,而对于标志则一直都是根据指令结果进行设置的源寄存器和目标寄存器是相同的只使用低端寄存器,即不使用寄存器R8-R12对指令中出现的常量有大小的限制不能在指令中使用内嵌的桶型移位器(inlinebarrelshifter)THUMB-2指令集Thumb-2指令集主要是对Thumb指令集架构的扩展,其设计目标是以Thumb的指令密度达到ARM的性能。它具有如下特性增加了32位的指令,因而实现了几乎ARM指令集架构的所有功能完整保留了16位的Thumb指令集编译器可以自动地选择16位和32位指令的混合具有ARM态的行为,包括可以直接处理异常、访问协处理器以及完成v5TE的高级数据处理功能通过If-Then(IT)指令,1-4条紧邻的指令可以条件执行JAZELLE
Jazelle技术使得ARM核可以执行8位的Java字节码,约95%的JAVA字节码可以由硬件执行,从而使效率显著提高。汇编指令用处嵌入式系统的初始化代码需要用汇编指令来编写。初始化代码通常包括处理器的初始化、内存初始化等,其中涉及一些比较特殊的操作,比如设置处理器在不同工作模式下的堆栈指针,需要使用特殊的访问处理器状态寄存器的指令,强制处理器切换到不同模式下进行操作;一些中断例程尤其是作为一种异常被响应的第一级中断派发程序需要用汇编指令来编写,以提高效率;在软件的调试过程中,熟悉汇编指令更有助于查找疑难问题;某些指令本身就是不能直接由编译器产生的,而需要人工编写。可以直接控制在C语言编程时不能有效使用的3个优化工具:指令调整-----调整一段代码中的指令序列,以避免处理器的暂停等待。ARM指令执行是在指令流水线中进行的,所以一条指令执行的时间会受其相邻指令的影响。寄存器分配-----决定如何分配变量给ARM寄存器或者堆栈,以获得最好的性能。目标是要使访问存储器的次数降到最少。条件执行-----可以使用ARM条件代码和条件指令的全部功能。通过在指令后加上合适的条件标志位,ARM指令可以条件执行通过减少前向的分支数目,增强了指令的代码密度和指令性能
CMPr0,r1ADDGTr2,r2,#1ADDLEr3,r3,#1默认情况下,数据处理指令不会影响条件标志位,但是,可在指令后加“s”(或其它条件位)后缀,以实现标志位的置位。loopADDr2,r2,r3SUBSr1,r1,#0x01 BNE
loop
r2=r2+r3
如果
Z标志清除则分支跳转
r1减1并设置标志位
r0-r1,比较
r0和r1并设置标志位
if>r2=r2+1标志位保持不变
if<=r3=r3+1标志位保持不变条件执行和标志位条件执行的例子if(r0==0){r1=r1+1;}else{r2=r2+1;}C代码
5条指令
占据5个字
5个或者6个时钟周期
3条指令
占据3个字
3个时钟周期
CMPr0,#0BNEelseADDr1,r1,#1BendelseADDr2,r2,#1end...ARM指令
非条件执行
CMPr0,#0ADDEQr1,r1,#1ADDNEr2,r2,#1...条件执行指令条件码不相等无符号高于或相同无符号低于为负相等溢出无溢出无符号高于无符号低于或相同为正或零小于大于小于或等于总是大于或等于EQNECS/HSCC/LOPLVSHILSGELTGTLEALMIVC后缀描述Z=0C=1C=0Z=1被测试的标志N=1N=0V=1V=0C=1&Z=0C=0orZ=1N=VN!=VZ=0&N=VZ=1orN=!V可能的指令条件码如下所示注意:AL是默认的,不需要被特别指出。
数据处理指令由以下指令组成:算术运算: ADD ADC SUB SBC RSB RSC逻辑运算: AND ORR EOR BIC比较运算: CMP CMN TST TEQ数据传送: MOV MVN这些指令仅对存放于寄存器的数据操作,对内存数据是无效的.语法:
<Operation>{<cond>}{S}Rd,Rn,Operand2第二个操作数可以为一个寄存器或者一个立即数SUBr0,r1,r2 ANDr1,r4,#0xFF
比较指令仅仅设置了条件标志位
–无需指定RdCMPr0,r3数据传送指令并不指定RdMOVr0,r1第二个操作数通过桶型移位器传输到ALU寄存器方式,可附加移位操作移位的值可为以下的两种:5位的无符号整数(0-31)其它寄存器的最低字节用来实现乘以一个常数ADDr0,r5,r5LSL1
r0=r5x3立即数范围在0-255的8位立即数或者该8位立即数循环右移偶数位得到的数允许32位的常数直接加载到寄存器中结果操作数1桶型移位器操作数
2ALU第二个操作数移位操作DestinationCF0DestinationCFLSL:
逻辑左移ASR:
算术右移相当于乘2相当于除以2,保留符号位DestinationCF...0DestinationCFLSR:
逻辑右移ROR:
循环右移相当于除以2最低有效位旋转至最高有效位DestinationRRX:
扩展的循环右移寄存器数值右移一位,C标志位填补空出的位,移出的位代替C标志位CF以下的移位操作是数据处理指令的一部分.移位的范围为0-31位,对指令的性能不会造成太大的影响ARM指令不能包含一个
32位的立即数常数ARM指令都是32位定长的在数据处理指令的格式中,第二个操作数有12位来对应4位的移位数乘以2组成了步长为2,范围在0-30的移位值立即数法则:
“8位的常数循环右移偶数位得到”07118immed_8Shifter
RORrotx2小测试:
指令:0xe3a004ff
MOVr0,#???立即数常数为了加载更大的立即数,汇编器提供了伪指令:LDRrd,=const这将:产生一条
MOV
或者MVN
指令或者产生一条
PC相对寻址的LDR
指令将立即数从literalpool(嵌入在代码中的常数域)里读出来举例LDRr0,=0xFF => MOVr0,#0xFFLDRr0,=0x55555555
=>
LDRr0,[PC,#Imm12]
…
…
DCD0x55555555推荐用这种方式将常数加载到寄存器加载32位的常数有两类乘法-分别产生32位和64位的结果32位的这类乘法在ARM7TDMI会执行
2-5时钟周期MULr0,r1,r2 ;r0=r1*r2MLAr0,r1,r2,r3
;r0=(r1*r2)+r364位的乘法提供了两种乘法指令:无符号和有符号乘这类指令有两个目标寄存器[U|S]MULLr4,r5,r2,r3 ;r5:r4=r2*r3[U|S]MLALr4,r5,r2,r3 ;r5:r4=(r2*r3)+r5:r4大多数的ARM核不提供整数除法指令除法操作由c的库函数例程或者移位操作实现乘法和除法分支指令分支跳转指令有如下的格式:B{L}{<cond>}label子函数调用可加上{L}实现在指令编码中,存在一个
24位的地址域在执行时它被左移两位
(因为ARM指令是字对齐的),产生一个26位的偏移地址,由此可知跳转的范围大体在-32MB~+32MB之间引起了流水线清空
Bstart.. startPC相对寻址的标号“start”跳转到此处继续执行:BLfunc2::BXlrfunc1func2voidfunc1(void){
: func2(); :}子程序实现一个传统的子程序调用需要两个步骤:保存返回地址跳转到子程序的首地址这些步骤可以由一条指令完成,BL返回地址被保存在链接寄存器
(lr/r14)分支跳转到
+/-32MB范围内的任何地址重新加载链接寄存器的内容至PC寄存器即可实现返回转移类型返回指令(推荐)注BLMOVPC,R14此时PC具有BL/SWI/und/Pabt指令的地址undMOVSPC,R14_undSWIMOVSPC,R14_svcPabtSUBSPC,R14_abt,#4IRQSUBSPC,R14_irq,#4此时PC从IRQ或FIQ处取得断点地址FIQSUBSPC,R14_fiq,#4DabtSUBSPC,R14_abt,#8PC是产生Dabt指令(预取)的地址Reset--R14的内容未知各种子程序的返回指令单寄存器数据传输(加载/存储指令)
LDR STR
字
LDRB STRB
字节
LDRH STRH
半字
LDRSB
有符号的字节加载
LDRSH
有符号的半字加载存储系统必须支持所有的访问尺寸语法:LDR{<cond>}{<size>}Rd,<address>STR{<cond>}{<size>}Rd,<address>举例LDREQB
地址寻址方式被LDR/STR指令访问的地址通过一个基址寄存器和一个偏移量来指定对于字和无符号的字节访问,偏移量可以为:一个无符号的12位立即数(i.e.0-4095bytes)
LDRr0,[r1,#8]寄存器,可附加的对其进行移位
LDRr0,[r1,r2]
LDRr0,[r1,r2,LSL#2]对于半字和有符号的字节访问,偏移量可以为:一个8位的立即数(i.e.0-255bytes)一个寄存器(不可以被移位)基址寄存器的地址可加也可减:
LDRr0,[r1,#-8]
LDRr0,[r1,-r2,LSL#2]是前序还是后序寻址是否更新基址寄存器
(仅限于前序寻址)
LDRr0,[r1,#-8]!
0x7r10x300基址寄存器0x300r00x7源寄存器偏移量80x308r10x300初始的基址寄存器0x300r00x7源寄存器偏移量80x308r10x308更新后的基址寄存器更新基址寄存器形式:
STRr0,[r1,#8]!
;计算地址并传送,地址寄存器也更新前序(前索引)寻址和后序(后索引)寻址前序寻址:
STRr0,[r1,#8];
计算地址并传送,地址寄存器不更新后序寻址:
STRr0,[r1],#8;先直接传送数据,后更新地址寄存器0x780x7基址寄存器的更新使编写简单的块拷贝例程成为可能举例:后序寻址可用来拷贝一个内存块;r5源数据块的起始指针;r6源数据块的结束指针;r8目的数据块的起始指针loop LDR r0,[r5],#4 ;加载4个字节
STR r0,[r8],#4 ;存储至目标地址
CMP r5,r6 ;检查是否完毕
BLT loop ;循环在这个例子中每次循环拷贝一个字内存块的拷贝(1)内存增长方向r6r5r8批量加载/存储指令语法:<LDM|STM>{<cond>}<addressing_mode>Rb{!},<registerlist>4种地址模式:LDMIA/STMIA
;increment
after,地址后加
LDMIB/STMIB
;
incrementbefore,地址先加
LDMDA/STMDA
;decrement
after,地址后减
LDMDB/STMDB
;decrement
before,地址先减IAr2地址增长方向r3r1r2r3r1r2r3r1r2r3r1r0IBDADBLDMxxr0,{r1,r2,r3}STMxxr0,{r1,r2,r3}基址寄存器(Rb)STM/LDM不仅可用于堆栈操作,它们也可以用来进行内存块拷贝举例;r5源数据块的起始指针;r6源数据块的结束指针;r8目的数据块的起始指针loop LDMIA r5!,{r0-r3} ;加载16个字节
STMIA r8!,{r0-r3} ;存储至目标地址
CMP r5,r6 ;检查拷贝是否完毕
BLT loop ;循环在这个例子中每次循环拷贝8个字内存块的拷贝(2)内存增长方向r6r5r81、r5!与r5不同,r5!自动更新地址2、{rx列表}中的寄存器编码序号大小,决定了对应的存储器地址高低。堆栈操作LDMFDsp!,{r4-r7,pc}SP100FF1234AOBE80341010123484209753r41r514544r60r712lr9048pc9020r4100100FFr5FF1234r61234A0BEr7A0BE8034pc8034r4100r5FFr61234r7A0BElr8034ABCD8765102E16FFFF1010123484209753TopofMemorySPSP100FF1234A0BE8034SPOldSP100FF1234A0BE8034ARM堆栈操作由块数据传输指令:STMFD
(Push) 批存储–满递减堆栈
[STMDB]LDMFD
(Pop) 批加载–满递减堆栈
[LDMIA]注意:寄存器在压栈时的顺序始终是最低编号寄存器的内容压入最低地址的堆栈空间,被指定的寄存器顺序是无效的.STMFDsp!,{r4-r7,lr}软中断指令(SWI)引起了一个异常自陷,跳转到软中断异常向量软中断处理例程检查软中断号以决定如何处理该号中断通过软中断这种机制,操作系统可以实现一个优先操作集合,它们可被用户模式下的应用代码调用.语法:
SWI{<cond>}<SWInumber>283124270
Cond1111SWI号(被处理器忽略)23条件域类型含义入口地址优先级复位Reset引脚复位0x001数据中止DataAbort(Dabt)数据地址不存在,或该地址不许当前指令访问,发生此异常0x102快速中断请求FastInterruptRequest(FIQ)快速中断引脚nFIQ请求中断低电平有效(且CPSR的F位=0时)产生。0x1c3外部中断请求InterruptRequest(IRQ)系统外设通过外部中断引脚nIRQ请求中断(CPSR的I位=0时)产生。0x184指令预取中止PrefechAbort(Pabt)指令预取失败,存储器发出Abort信号,CPU仍然执行此失效指令时,发生此异常0x0c5软中断SoftwareInterrupt(SWI)用户执行SWI指令,以实现调用系统的特权指令和功能0x086未定义指令UndefinedInstruction(und)CPU遇到不认得的指令,利用此异常机制进行软件仿真调试0x046程序状态寄存器访问指令MRS/MSR指令用于在CPSR/SPSR寄存器与通用寄存器之间传输数据MSR指令允许全部或部分的寄存器内容被更新通过写CPSR寄存器,可以开关中断、改变处理器模式典型的是使用一个读/修改/写的操作序列:MRSr0,CPSR ;将CPSR的内容读至r0BICr0,r0,#0x80 ;将第7位清零以允许IRQ中断MSRCPSR_c,r0 ;将修改后的值仅写入‘c’字节在用户模式下,所有的位都可以被读出来,但是仅有条件标志位(f)可以被改变fsxc2731NZCVQ2867IFTmode1623
15
54024J108919GE[3:0]
EA
ITcond_abcde协处理器指令ARM体系支持16个协处理器每个协处理器的指令集都占据了ARM指令集的固定部分如果系统中没有某个协处理器,那么就会触发未定义指令异常有三种协处理器指令协处理器数据操作指令CDP
:初始化协处理器的数据处理操作协处理器寄存器与ARM处理器寄存器数据传输指令MRC:协处理器寄存器到ARM处理器寄存器的数据传输指令MCR:ARM处理器寄存器到协处理器寄存器的数据传输指令协处理器寄存器和内存的数据传输指令
LDC:协处理器数据加载指令STC:协处理器数据存储指令TRmRs
BTBW选项16161616321632/6432/64Rd(RdHi,RdLo)Rn(RdHi,RdLo)符号乘法操作指令SMULxy{cond}Rd,Rm,RsSMULWy{cond}Rd,Rm,RsSMLAxy{cond}Rd,Rm,Rs,RnSMLAWy{cond}Rd,Rm,Rs,RnSMLALxy{cond}RdLo,RdHi,Rm,RsSMLA
指令会影响Q标志位x,y
代表高半字(Top)或者低半字(Bottom)W
代表选择48位乘积的高32位不要去影响NZCV标志位(指令后加‘S’后缀是不允许的)饱和运算指令饱和运算向0x7FFFFFFF加1导致了正值向负值的转变从0x80000000减1导致负值向正值的转变在电信领域中,一些DSP算法要求饱和度可以保证G.723.1–VoIP(IP语音技术)AMR-AdaptiveMultiRate(自适应多码率)
QSUB{cond}Rd,Rm,Rn
;Rd=saturate(Rm-Rn)
QADD{cond}Rd,Rm,Rn ;Rd=saturate(Rm+Rn)
QDSUB{cond}Rd,Rm,Rn ;Rd=saturate(Rm-saturate(Rn
2))
QDADD{cond}Rd,Rm,Rn ;Rd=saturate(Rm+saturate(Rn
2))在这些指令的执行中,如果饱和发生,那么Q标志位就会被置位0x00x7FFFFFFF0x80000000-ve+ve断点指令断点指令-BKPT<#imm16>执行该指令或将引起一个预取指令异常,或者使处理器进入调试状态若有调试软件,它将该指令处理为断点若有调试硬件,那么将被直接作为一个断点处理立即数的值将被处理器忽略V6的新特性ARM的V6版本包含了
81条新的指令几类附加的指令打包数据SIMD(单指令多数据处理)绝对差值求和操作饱和运算对混合端(大/小端)的支持异常入口与返回指令不同于以前对原指令集的扩充(例如BLXoffset),V6扩充的指令几乎都是条件执行的SIMD–加法&减法(1)<prefix><Operation><size>{<cond>}Rd,Rn,RmADD16&SUB16从第一个操作数中的每个半字上加上或减去第二个操作数对应的半字
ADD8&SUB8从第一个操作数中的每个字节上加上或减去第二个操作数对应的字节前缀:S 有符号SH 有符号平分(减半)U 无符号UH 无符号平分UQ 无符号饱和Q 饱和(有符号)++RmRd++RnGE[3]GE[2]GE[1]GE[0]UADD8Rd,Rn,RmSIMD–加法&减法(2)ADDSUBX&SUBADDX结合的16位加法和减法GE[3:2]GE[1:0]Rd-+RbRaUADDSUBXRd,Ra,Rb根据加法是否产生进位或减法是否产生借位的情况设置GE[3:0]SIMD–乘法SMUAD{X}Rd,Rm,Rs双重乘加(有符号)SMUSD{X}Rd,Rm,Rs双重乘减(有符号)SMLA{L}D{X}Rd,Rm,Rs,Rn双重乘加累加(有符号)SMLS{L}D{X}Rd,Rm,Rs,Rn双重乘减累加(有符号){X}表示在计算前Rs中的两个半字互换{L}表示64位的累加如果发生累加溢出,Q标志位置位xRdRsxRmSMUADRd,Rm,Rs+绝对差值求和指令在许多多媒体数字信号编码算法,尤其是视频运动估计(videomotionestimation)算法中,绝对差值求和运算是主要操作对象素数组数据的运算(通常是8位)ABSDIFFABSDIFFABSDIFFABSDIFF+可选择累加思考题(一)1. 用一条ARM指令分别实现下面的语句: a)r0=16 b)r0=r1/16 (带符号的数) c)r1=r2*3 d)r0=-r02.BIC指令的作用是什么?3. 哪些数据处理指令总是设置条件标志位?思考题(二)1.哪些指令可用于子程序调用的返回?2.要打开或者屏蔽IRQ中断该使用哪些指令?3.
为了克服ARM分支指令只有±32MB范围的局限,应该使用哪些指令?思考题(三)1.CLZ
指令的用途是什么?
2.以下指令的结果是什么? r1=0x7FFFFF00 r2=0x00001000 QADDr0,r1,r23.以下的指令有效吗? LDRDr7,[r2,0x100]4.以下指令的效果是什么? SMULBTr0,r1,r25.如果r1=0x12406700,那么在执行这条语句后r0的值是什么: REVr0,r16.以下指令的意义是什么 SUB16r1,r2,r0思考题(四)1.下面这条Thumb指令的效果是什么? ADDr1,r22.这是一条有效的Thumb指令吗? MSRCPSR_S,r03.Thumb中BL指令的跳转范围是多少?汇编语言源程序格式汇编语言程序的结构1汇编语言的行构成2伪指令3461.汇编语言程序的结构汇编源程序示例第一部分
(test0源程序)
CODE32 ;32位的ARM指令段AREAcodesec,CODE,READONLY;代码段,名称codesec,属性为;只读mainPROC ;函数mainSTMFDsp!,{lr} ;保存必要的寄存器和返回地址;到数据栈ADR r0,strhello ;取标签strhello代表的地址值BL _printf ;调用C运行时库的_printf函数
;打印“Helloworld!”字符串BL welcomefun ;调用子函数welcomfunLDMFD sp!,{pc} ;恢复寄存器值strhello ;strhello代表本地字符串的地址DCB "Helloworld!\n\0";定义一段字节空间ENDP ;函数main结束ARM的汇编语言程序一般由几个段组成,每个段均由AREA伪操作定义。段可以分为多种,如代码段、数据段、通用段,每个段又有不同的属性,象代码段的默认属性为READONLY,数据段的默认属性为READWRITE。本程序定义了两个段,第一个段为代码段codesec;第二个段为数据段constdatasec47汇编源程序示例第二部分welcomefun ;子函数welcomfun STMFDsp!,{lr} ;保存必要的寄存器和返回地;址到数据栈ADRr0,adrstrarm;取adrstrarm的地址放到寄存器r0中LDR r0,[r0,#0] ;将strarm的值放到r0中BL _printf ;调用C运行时库的_printf函数打印
;“WelcomtoARMworld!”字符串
LDMFDsp!,{pc} ;恢复寄存器值adrstrarm ;adrstrarm标签 DCD strarm ;保存strarm的地址
AREAconstdatasec,DATA,READONLY,ALIGN=0;数据段,名称为constdatasec,属性;为只读本程序定义了两个段,第一个段为代码段codesec第二个段为数据段constdatasec48汇编源程序示例第三部分strarmDCB "WelcometoARMworld!\n\0" ;存放“WelcometoARM;world!”字符串
EXPORTmain ;导出main函数供外部调用;引入三个C运行时库函数和ARM库IMPORT_main IMPORT__mainIMPORT_printfIMPORT||Lib$$Request$$armlib||,WEAKEND ;程序结束程序如何结束?(loop源程序)汇编语言源程序格式汇编语言程序的结构1汇编语言的行构成2伪指令3502.汇编语言的行构成格式:
[标签]指令/伪操作操作数[;语句的注释]所有的标签必须在一行的开头顶格写,前面不能留空格,后面也不能跟C语言中的标签一样加上“:”;
ARM汇编器对标识符的大小写敏感,书写标号及指令时字母的大小写要一致;注释使用“;”符号,注释的内容从“;”开始到该行的结尾结束。例:Labeladdaddr0,r0,r1;加法指令Str1 SETS “Thisisastring.”;给字符串Str1赋值512.汇编语言的行构成3.常量:数字常量十进制数,如1、2、123十六进制数,如0x123,0xabc字符常量由单引号及中间的字符组成,包括C语言中的转义字符,如‘a’,‘\n’字符串常量由一对双引号及中间的字符串表示,中间也可以使用C语言中的转义字符,比如:“abcdef\0xa\r\n”逻辑常量{TRUE},{FALSE},注意带大括号523.伪指令没有相对应的操作码或者机器码,通常称为伪指令,它们所完成的操作称为伪操作。作用是为完成汇编程序作各种准备工作的,由汇编程序在源程序的汇编期间进行处理,仅在汇编过程中起作用。有如下几种伪指令:符号定义伪指令数据定义伪指令汇编控制伪指令533.伪指令符号定义伪指令用于定义ARM汇编程序中的变量、对变量赋值以及定义寄存器的别名等。符号定义有如下几种伪指令:
用于定义局部变量的LCLA、LCLL、LCLS;用于定义全局变量的GBLA、GBLL、GBLS;用于对变量赋值的SETA、SETL、SETS
;543.伪指令LCLA、LCLL、LCLS伪指令用于定义一个汇编程序中的局部变量,并初始化
格式:
LCLA/LCLL/LCLS
局部变量名定义一个局部的数字变量,初始化为0定义一个局部的逻辑变量,初始化为F定义一个局部的字符串变量,初始化为空串这三条伪指令用于声明局部变量,在其局部作用范围内变量名必须唯一。553.伪指令GBLA、GBLL、GBLS伪操作定义一个汇编程序中的全局变量,并初始化
格式:GBLA/GBLL/GBLS
变量名定义一个全局的数字变量,并初始化为0定义一个全局的逻辑变量,并初始化为F定义一个全局字符串变量,并初始化为空串这三条伪指令用于定义全局变量,因此在整个程序范围内变量名必须唯一。563.伪指令SETA、SETL、SETS格式:变量名 SETA/SETL/SETS
表达式给一个数字变量赋值给一个逻辑变量赋值给一个字符串变量赋值格式中的变量名必须为已经定义过的全局或局部变量,表达式为将要赋给变量的值。57汇编程序的变量代换AREA||.text||,CODE,READONLY;代码段,名称为||.text||,属性为只读GBLS str1 ;声明str1为全局字符串GBLS str2 ;声明str2为全局字符串GBLL l1 ;声明l1为全局逻辑变量GBLA num1 ;声明num1为全局数字变量l1SETL {TRUE}num1SETA 0x4fstr1SETS "bbb" str2SETS "aaastr1:$str1.l1:$l1,a1:$num1.ccc" ;str2包含了多个变量mainPROC ;函数mainSTMFDsp!,{lr} ;保存必要的寄存器和返回地址到数据栈ADR r0,strhelloBL _printf ;调用C运行时库的_printf函数打印字符串LDMFDsp!,{pc} ;恢复寄存器值strhello ;strhello代表本地字符串的地址DCB "$str2\n\0" ;定义一段字节空间ENDP ;函数main结束运行后结果:aaastr1:bbbl1:T,a1:0000004Fccc58汇编程序的变量代换(续)
EXPORTmain ;导出main函数供外部调用;引入三个C运行时库函数和ARM库IMPORT_main IMPORT__mainIMPORT_printfIMPORT||Lib$$Request$$armlib||,WEAKEND593.伪指令数据定义伪指令用于为数据分配存储单元,同时也可完成已分配存储单元的初始化。数据定义有如下几种伪指令:
DCB DCW/DCWUDCD/DCDUSPACEMAPFIELD603.伪指令DCB
DCB用于分配一块字节单元并用伪指令中指定的表达式进行初始化。
格式:标号/变量DCB
表达式
DCB可用“=”代替表达式可以为使用双引号的字符串或0-255的数字例:Array1DCB1,2,3,4,5 ;数组str1 DCB“Yourarewelcome!”;构造字符串;并分配空间613.伪指令DCW/DCWU
格式:标号/变量DCW/DCWU
表达式
DCW分配一段半字存储单元并用表达式值初始化,它定义的存储空间是半字对齐的DCWU功能跟DCW类似,只是分配的字存储单元不严格半字对齐例:Arrayw1DCW 0xa,-0xb,0xc,-0xd;构造固定数组并分;配半字存储单元623.伪指令DCD/DCDU
格式:标号/变量 DCD/DCDU
表达式
DCD用于分配一块字存储单元并用伪指令中指定的表达式初始化,它定义的存储空间是字对齐的。也可用“&”代替DCDU只是分配的存储单元不严格字对齐例:Arrayd1DCD1334,234,345435;构造固定数组并分配;字为单元的存储单元Label DCDstr1 ;该字单元存放str1的地址633.伪指令SPACE
格式:标号 SPACE
表达式
SPACE用于分配一片连续的存储区域并初始化为0,也可用“%”代替表达式为要分配的字节数例:FreespaceSPACE 1000 ;分配1000字节的存储空间643.伪指令MAP
格式:MAP表达式[,基址寄存器]MAP定义一个结构化的内存表的首地址,可以用“^”来代替表达式可以为程序中的标号或数学表达式基址寄存器为可选项,当基址寄存器选项不存在时,表达式的值即为内存表的首地址,当该选项存在时,内存表的首地址为表达式的值与基址寄存器的和MAP可以与FIELD伪操作配合使用来定义结构化的内存表。例:
MAP0x130,R2 ;内存表首地址为0x130+R2653.伪指令FILED
格式:标号 FIELD
字节数
FIELD用于定义一个结构化内存表中的数据域,可用“#”来代替FILEDFIELD常与MAP配合使用来定义结构化的内存表:FIELD伪指令定义内存表中的各个数据域,MAP则定义内存表的首地址,并为每个数据域指定一个标号以供其他的指令引用。注意:MAP和FIELD伪指令仅用于定义数据结构,并不分配存储单元。663.伪指令汇编控制伪指令汇编控制伪操作用于指引汇编程序的执行流程。有如下几种伪指令:
IF、ELSE、ENDIFWHILE、WEND67其他伪指令AREA
格式:AREA
段名属性,……
AREA用于定义一个代码段、数据段或者特定属性的段属性部分表示该代码段/数据段的相关属性,多个属性可以用“,”分隔。常见属性如下:DATA:定义数据段。
CODE:定义代码段。READONLY:表示本段为只读。READWRITE:表示本段可读写。其他伪指令一个汇编程序至少应该包含一个段,当程序太长时,也可以将程序分为多个代码段和数据段。例:AREA test,CODE,READONLYAREA||.text||,CODE,READONLY6869其他伪指令CODE16、CODE32
格式:CODE16/CODE32
CODE16伪操作指示编译器后面的代码为16位的Thumb指令CODE32伪操作指示编译器后面的代码为32位的ARM指令如果在汇编源代码中同时包含Thumb和ARM指令时,可以用“CODE32”通知编译器其后的指令序列为32位的ARM指令,用“CODE16”伪指令通知编译器其后的指令序列为16位的Thumb指令。在使用ARM指令和Thumb指令混合编程的代码里,这两条伪指令后面的代码类型是不同的,但它们并不能对处理器进行状态的切换。其他伪指令例:CODE32 ;32位的ARM指令AREA ||.text||,CODE,READONLY……LDR R0,=0x8500 BX R0 ;程序跳转,并将处理;器切换到Thumb状态……CODE16 ;16位的Thumb指令ADD R3,R3,1
END ;源文件结束7071其他伪指令ENTRY
格式:ENTRY
ENTRY用于指定汇编程序的入口。在一个完整的汇编程序中至少要有一个ENTRY,也可以有多个。下面的代码使用了ENTRY:AREAsubrout,CODE,READONLYENTRY;指定程序入口startMOVr0,#10;设置参数MOVr1,#3BLdoadd;调用子函数
其他伪指令stopMOVr0,#0x18LDRr1,=0x20026SWI0x123456;调用ARM半主机机制
doaddADDr0,r0,r1;子函数代码MOVpc,lr;子函数返回
END;源文件结束7273其他伪指令END
格式:
END
END告诉编译器已经到了源程序的结尾例:AREA constdata,DATA,READONLY……END ;结尾
74其他伪指令EQU
格式:名称EQU
表达式[,类型]EQU用于将程序中的数字常量、标号、基于寄存器的值赋予一个等效的名称,这一点类似于C语言中的#define,可用“*”代替EQU例:num1 EQU 1234 ;定义num1为1234addr5 EQU str1+0x50 d1 EQU 0x2400,CODE32;定义d1的值为0x2400,且;该处为32位的ARM指令如果表达式为32位的常量,我们可以指定表达式的数据类型,类型域可以有以下三种:CODE16/CODE32/DATA75其他伪指令EXPORT
格式:EXPORT
标号[,WEAK]EXPORT在程序中声明一个全局标号,其他文件中的代码可以引用该标号。用户也可以用GLOBAL代替EXPORT例:AREA ||.text||,CODE,READONLYmain PROC
…… ENDP EXPORTmain ;声明一个可全局引用的函数mainEND[,WEAK]可选项声明其他文件有同名的标号,则该同名标号优先于该标号被引用76其他伪指令IMPORT
格式:IMPORT
标号[,WEAK]IMPORT告诉编译器这个标号要在当前源文件中使用,但标号是在其他的源文件中定义的。不管当前源文件是否使用过该标号,这个标号都会加入到当前源文件的符号表中例:AREA mycode,CODE,READONLYIMPORT _printf;通知编译器当前文件要引用函数_printfEND[,WEAK]选项表示如果所有的源文件都没有找到这个标号的定义,编译器也不会提示错误信息。编译器在多数情况下将该标号置为0,如果这个标号被B或BL指令引用,则将B或BL指令替换为NOP操作77其他伪指令EXTERN
格式:EXTERN
标号[,WEAK]
EXTERN告诉编译器所使用的标号要在当前源文件中引用,但该标号是在其他的源文件中定义的。与IMPORT不同的是,如果当前源文件实际上没有引用该标号,该标号就不会被加入到当前文件的符号表中例:AREA ||.text||,CODE,READONLYEXTERN_printf,WEAK;告诉编译器当前文件要引用标;号,如果找不到,则不提示错误END[,WEAK]选项表示如果所有的源文件都没有找到这个标号的定义,编译器也不会提示错误信息。编译器在多数情况下将该标号置为0,如果这个标号被B或BL指令引用,则将B或BL指令替换为NOP操作78其他伪指令INCBIN
格式:INCBIN
文件名
INCBIN将一个数据文件或者目标文件包含到当前的源文件中,编译时被包含的文件不作任何变动的存放在当前文件中,编译器从后面开始继续处理。例:AREA constdata,DATA,READONLYINCBIN data1.dat ;源文件包含文件data1.datINCBIN E:\DATA\data2.bin;源文件包含文件;E:\DATA\data2.bin ENDARM指令格式用ARM指令助记符表示为:<opcode>{<cond>}{S}<Rd>,<Rn>,<shift_op2>每个域的含义如下。①<opcode>:操作码域,指令编码的助记符。②{<cond>}:条件码域,指令允许执行的条件编码。花括号表示此项可默认。ARM指令格式ARM指令的一个重要特点是可以条件执行,每条ARM指令的条件码域包含4位条件码,共16种。几乎所有指令均根据CPSR中条件码的状态和指令条件码域的设置有条件地执行。当指令执行条件满足时,指令被执行,否则被忽略。ARM指令格式立即寻址立即寻址也叫立即数寻址,操作数本身就在指令中给出,只要取出指令也就取到了操作数例如,以下指令:
ADDR0,R0,#1 ;R3←R0+1
立即数的表示以“#”为前缀,十六进制的立即数在“#”后面加“&”符号,以二进制表示的立即数,要求在“#”后加上“%”。寄存器寻址指令地址码给出寄存器的编号,也是一种执行效率较高的寻址方式。例如,以下指令:
ADDR0,R1,R2 ;R0←R1+R2
寄存器间接寻址寄存器间接寻址就是以寄存器中的值作为操作数的地址,而操作数本身存放在存储器中。例如,以下指令:
LDRR0,[R1] ;R0←[R1]STRR0,[R1] ;[R1]←R0
基址变址寻址基址变址寻址就是将寄存器(该寄存器一般称作基址寄存器)的内容与指令中给出的地址偏移量相加,从而得到一个操作数的有效地址。变址寻址方式常用于访问某基地址附近的地址单元。前索引寻址举例:
LDRR0,[R1,#4] ;R0←[R1+4],不改地址寄存器R1内容
后索引寻址举例:
LDRR0,[R1],#4 ;R0←[R1] ;R1←R1+4带自动索引的前索引寻址举例:LDRR0,[R1,#4]! ;R0←[R1+4] ;R1←R1+4基址加索引寻址举例:
LDRR0,[R1,R2] ;R0←[R1+R2]多寄存器寻址多寄存器寻址是指一次可以传送多个寄存器的值,允许一条指令可以传送16个寄存器的任何子集。例如,以下指令:
LDMIAR0,{R1,R2,R3,R4} ;R1←[R0]
;R2←[R0+4]
;R3←[R0+8]
;R4←[R0+12]
多寄存器指令的后缀含义如下:I:Increment,D:Decrement,A:After,B:Before多个连续的寄存器可以用“-”符号连接;不连续的寄存器用“,”分隔书写,如上例可写成:
LDMIAR0,{R1-R4}LDMIAR0,{R1-R3,R4}寄存器移位寻址移位操作包括如下5种类型。LSL:逻辑左移(LogicalShiftLeft)。寄存器中字的低端空出的位补0。LSR:逻辑右移(LogicalShiftRight)。寄存器中字的高端空出的位补0。ASR:算术右移(ArithmeticShiftRight)。算术移位的对象是带符号数。在移位过程中必须保持操作数的符号不变。若源操作数为正数,则字的高端空出的位补0;若源操作数为负数,则字的高端空出的位补1。ROR:循环右移(ROtateRight)。从字的最低端移出的位填入字的高端空出的位。RRX:扩展为1的循环右移(RotateRighteXtendedby1place)。操作数右移1位,空位(位[31])用原C标志填充相对寻址与基址变址寻址方式相类似,相对寻址以程序计数器PC的当前值为基地址,指令中的地址标号作为偏移量,将两者相加之后得到操作数的有效地址。以下程序段完成子程序的调用和返回,跳转指令BL采用了相对寻址方式:BLLOOP ;跳转到子程序LOOP处执行……LOOP……MOVPC,LR ;从子程序返回堆栈寻址满递增堆栈(FA):堆栈指针指向最后压入的数据,且由低地址向高地址生成。②满递减堆栈(FD):堆栈指针指向最后压入的数据,且由高地址向低地址生成。③空递增堆栈(EA):堆栈指针指向下一个将要放入数据的空位置,且由低地址向高地址生成。④空递减堆栈(ED):堆栈指针指向下一个将要放入数据的空位置,且由高地址向低地址生成。ARM指令集ARM处理器的指令按功能可分为7大类:加载/存储指令(包括批量加载/存储指令)、分支指令、数据处理指令、乘法指令、状态寄存器访问指令、异常中断指令和协处理器指令。加载/存储指令(1)LDR指令格式:LDR目的寄存器,<存储器地址>
LDRR0,[R1] ;将存储器地址为R1的字数据读入寄存器R0LDRR0,[R1,R2] ;将存储器地址为R1+R2的字数据读入寄存器R0LDRR0,[R1,#8] ;将存储器地址为R1+8的字数据读入寄存器R0LDRR0,[R1,R2,LSL#2]!
;将存储器地址为R1+R2×4的数据读入寄存器R0,并将新地址R1+R2×4写入R1LDRR0,[R1],R2,LSL#2;将存储器地址为R1的字数据读入寄存器R0,并将新地址R1+R2×4写入R1加载/存储指令(2)LDRB指令格式:LDRB目的寄存器,<存储器地址>LDRBR0,[R1];将存储器地址为R1的字节数据读入寄存器R0,并将R0的高24位清零(3)LDRH指令格式:LDRH目的寄存器,<存储器地址>(4)STR指令格式:STR源寄存器,<存储器地址>STRR0,[R1],#8;将R0中的字数据写入以R1为地址的存储器中,并将新地址R1+8写入R1加载/存储指令(5)STRB指令格式:STRB源寄存器,<存储器地址>功能:STRB指令用于从源寄存器中将一个8位的字节数据传送到存储器中。该字节数据为源寄存器中的低8位。(6)STRH指令格式:STRH源寄存器,<存储器地址>功能:STRH指令用于从源寄存器中将一个16位的半字数据传送到存储器中。该半字数据为源寄存器中的低16位。批量加载/存储指令格式:LDM(或STM){类型}基址寄存器{!},寄存器列表{∧}功能:LDM(或STM)指令用于从由基址寄存器所指示的一片连续存储器到寄存器列表所指示的多个寄存器之间传送数据,该指令的常见用途是将多个寄存器的内容入栈或出栈。其中,{类型}为以下几种情况。IA:每次传送后地址加1。IB:每次传送前地址加1。DA:每次传送后地址减1。DB:每次传送前地址减1。FD:满递减堆栈。ED:空递减堆栈。FA:满递增堆栈。EA:空递增堆栈。批量加载/存储指令{!}为可选后缀,若选用该后缀,则当数据传送完毕之后,将最后的地址写入基址寄存器,否则基址寄存器的内容不改变。基址寄存器不允许为R15,寄存器列表可以为R0~R15的任意组合。{∧}为可选后缀,当指令为LDM且寄存器列表中包含R15,还将SPSR复制到CPSR。同时,该后缀还表示传入或传出的是用户模式下的寄存器,而不是当前模式下的寄存器。
STMFDR13!,{R0,R4-R12,LR};将寄存器列表中的寄存器(R0,R4到R12,LR)存入堆栈LDMFDR13!,{R0,R4-R12,PC};将堆栈内容恢复到寄存器(R0,R4到R12,LR)分支指令(1)B指令格式:B目标地址功能:B指令是最简单的跳转指令。一旦遇到一个B指令,ARM处理器将立即跳转到给定的目标地址,从那里继续执行。注意存储在跳转指令中的实际值是相对当前PC值的一个偏移量,而不是一个绝对地址,它的值由汇编器来计算(参考寻址方式中的相对寻址)。它是24位有符号数,左移两位后有符号扩展为32位,表示的有效偏移为26位(前后32MB的地址空间),如下所示:
BLabel;程序无条件跳转到标号Label处执行
CMPR1,R0BEQLabel;ifR1=R0,程序跳转到标号Label处执行分支指令(2)BL指令格式:BL目标地址功能:BL是另一个跳转指令,但跳转之前,会在寄存器R14中保存PC的当前内容,因此,可以通过将R14的内容重新加载到PC中,来返回到跳转指令之后的那个指令处执行。该指令是实现子程序调用的一个基本但常用的手段,如下所示:
BLLabel;当程序无条件跳转到标号Label处执行时,同时将当前的PC值保存到R14中分支指令(3)BLX指令格式:BLX目标地址功能:BLX指令从ARM指令集跳转到指令中所指定的目标地址,并将处理器的工作状态由ARM状态切换到Thumb状态,该指令同时将PC的当前内容保存到寄存器R14中。(4)BX指令格式:BX目标地址功能:BX指令跳转到指令中所指定的目标地址,目标地址处的指令既可以是ARM指令,也可以是Thumb指令。数据处理指令数据处理指令可分为数据传送指令、算术逻辑运算指令和比较指令等。(1)MOV指令格式:MOV{S}目的寄存器,源操作数功能:MOV指令可完成从另一个寄存器、被移位的寄存器或将一个立即数加载到目的寄存器。其中,S选项决定指令的操作是否影响CPSR中条件标志位的值,当没有S时指令不更新CPSR中条件标志位的值。MOVR1,R0;将寄存器R0的值传送到寄存器R1MOVPC,R14;将寄存器R14的值传送到PC,常用于子程序返回数据处理指令(2)MVN指令格式:MVN{S}目的寄存器,源操作数MVNR0,#0;将立即数0取反传送到寄存器R0中,完成后R0=−1(3)CMP指令格式:CMP操作数1,操作数2
CMPR1,R0;将寄存器R1的值与寄存器R0的值相减,并根据结果设置CPSR的标志位CMPR1,#100;将寄存器R1的值与立即数100相减,并根据结果设置CPSR的标志位(4)CMN指令格式:CMN操作数1,操作数2功能:CMN指令用于把一个寄存器的内容和另一个寄存器的内容或立即数取反后进行比较,同时更新CPSR中条件标志位的值。该指令实际完成操作数1和操作数2相加,并根据结果更改条件标志位。(5)TST指令格式:TST操作数1,操作数2功能:TST指令用于把一个寄存器的内容和另一个寄存器的内容或立即数进行按位的与运算,并根据运算结果更新CPSR中条件标志位的值。操作数1是要测试的数据,而操作数2是一个位掩码,该指令一般用来检测是否设置了特定的位。(6)TEQ指令格式:TEQ操作数1,操作数2功能:TEQ指令用于把一个寄存器的内容和另一个寄存器的内容或立即数进行按位的异或运算,并根据运算结果更新CPSR中条件标志位的值。该指令通常用于比较操作数1和操作数2是否相等。(7)ADD指令格式:ADD{S}目的寄存器,操作数1,操作数2功能:ADD指令用于把两个操作数相加,并将结果存放到目的寄存器中。操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。例如:
ADDR0,R1,R2 ;R0=R1+R2ADDR0,R1,#100 ;R0=R1+100ADDR0,R1,R2,LSL#1 ;R0=R1+(R2<<(1)(8)ADC指令格式:ADC{S}目的寄存器,操作数1,操作数2功能:ADC指令用于把两个操作数相加,再加上CPSR中的C条件标志位的值,并将结果存放到目的寄存器中。它使用一个进位标志位,这样就可以做比32位大的数的加法,注意不要忘记设置S后缀来更改进位标志。操作数1应是一个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。(9)SUB指令格式:SUB{S}目的寄存器,操作数
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年中国邮电器材集团有限公司招聘备考题库有答案详解
- 2025年“才聚齐鲁成就未来”山东黄河生态发展集团有限公司招聘备考题库及1套参考答案详解
- 2026年中化学数智科技有限公司招聘备考题库及一套参考答案详解
- 2026年平湖市青少年宫劳务派遣制教师招聘备考题库有答案详解
- 2026年佛山市顺德区莘村中学招聘临聘俄语教师备考题库及参考答案详解1套
- 2026年大商所飞泰测试技术有限公司招聘备考题库及完整答案详解1套
- 2026年恒丰银行济南分行社会招聘备考题库带答案详解
- 2026年南方医科大学珠江医院大数据中心招聘数据工程师备考题库及一套答案详解
- 2026年北京科技大学智能科学与技术学院招聘备考题库参考答案详解
- 2026年中冶建筑研究总院有限公司招聘备考题库及答案详解1套
- 2025年国企副总经理年终述职报告
- 2025年广东省第一次普通高中学业水平合格性考试(春季高考)数学试题(含答案详解)
- 卡乐康包衣学校培训资料专家讲座
- GB/T 6075.6-2002在非旋转部件上测量和评价机器的机械振动第6部分:功率大于100kW的往复式机器
- GA/T 1073-2013生物样品血液、尿液中乙醇、甲醇、正丙醇、乙醛、丙酮、异丙醇和正丁醇的顶空-气相色谱检验方法
- 天津市南开中学2022-2023学年高三上学期第三次月考(1月期末考)语文试题 Word版含答案
- 考研考博-英语-上海海事大学考试押题三合一+答案详解4
- 绿色装配式施工方案
- CMA全套文件(质量手册+程序文件+作业指导书+表格)
- 葡萄酒基础知识(中英文)(课堂PPT)
- 光学器件的使用及光路调试技巧课件版
评论
0/150
提交评论