ARM汇编伪指令介绍
ARM汇编伪指令与伪操作
应用示例:
GBLA Test1 Test1 SETA 0xaa GBLL Test2 Test2 SETL {TRUE} GBLS Test3 Test3 SETS “Testing”
4.给通用寄存器列表定义名称RLIST
RLIST伪操作用于给一个通用寄存器列表定义名称, 使用该伪操作定义的名称可以在LDM/STM中使用。
ADRL{cond}
register,expr
目标寄存器
地址表达式
地址表达式expr的取指范围: ➢当地址值是字节对齐时,其取指范围为-64K~64K; ➢当地址值是字对齐时,其取指范围为-256K~256K;
3.小范围地址读取伪指令ADR
ADR伪指令将基于PC相对偏移的地址值或基于寄 存器相对偏移的地址值读取到寄存器中。
操作符
语法格式
ARM 或 ARM
CODE32
CODE32
THUMB 或 THUMB
CODE16
CODE16
功能描述 指示编译器将要处理的是 32 位的 ARM 指令 指示编译器将要处理的是 16 位的 Thumb 指令
[例6-35]
AREA ToThumb,CODE,READONLY ENTRY ARM start ADR R0,into_thumb+1 BX R0 THUMB into_thumb MOVS R0,#10 …
[例6-36]:
AREA Example,CODE,READONLY GET include_s.s GET C:\test\include_init.s …
2.文件原样包含INCBIN
INCBIN伪操作将一个文件包含到当前源 文件中,该文件按原样包含,不进行汇编处理。 可以使用INCBIN来包含可执行文件、文字或 其他数据。
ARM汇编语言伪指令
ARM汇编语言伪指令ARM汇编语言伪指令ARM中伪指令不是真正的ARM指令或者Thumb指令,这些伪指令在汇编编译时对源程序进行汇编处理时被替换成对应的ARM或Thumb指令(序列)。
ARM伪指令包括ADR、ADRL、LDR和NOP等。
1、ADR(小范围的地址读取伪指令)该指令将基于PC的地址值或基于寄存器的地址值读取到寄存器中。
语法格式ADR{cond} register, expr其中,cond为可选的指令执行的条件register为目标寄存器expr为基于PC或者基于寄存器的地址表达式,其取值范围如下:当地址值不是字对齐时,其取值范围为-255~255.当地址值是字对齐时,其取值范围为-1020~1020当地址值是16字节对齐时,其取值范围将更大在汇编编译器处理源程序时,ADR伪指令被编译器替换成一条合适的指令。
通常,编译器用一条ADD指令或SUB指令来实现该ADR伪指令的功能。
因为ADR伪指令中的地址是基于PC或者基于寄存器的,所以ADR读取到的地址为位置无关的地址。
当ADR伪指令中的地址是基于PC时,该地址与ADR伪指令必须在同一个代码段中。
示例start MOV r0,#10 ;因为PC值为当前指令地址值加8字节ADR r4, start ;本ADR伪指令将被编译器替换成SUB r4,pc,#0xc2、ADRL(中等范围的地址读取伪指令)该指令将基于PC或基于寄存器的地址值读取到寄存器中。
ADRL伪指令比ADR伪指令可以读取更大范围的地址。
ADRL伪指令在汇编时被编译器替换成两条指令,即使一条指令可以完成该伪指令的功能。
语法格式ADRL{cond} register,expr示例start MOV r0,#10 ;因为PC值为当前指令地址值加8字节ADRL r4,start+60000 ;本ADRL伪指令将被编译器替换成下面两条指令ADD r4,pc,#0xe800ADD r4,r4,#0x2543、LDR(大范围的地址读取伪指令)LDR伪指令将一个32位的常数或者一个地址值读取到寄存器中语法格式LDR{cond} register, =[expr|label-expr]其中,expr为32位的常量。
ARM编程进阶之一-ARM汇编伪指令
ARM编程进阶之一-ARM汇编伪指令到目前为止,我们已经具备编写较为复杂的ARM 汇编程序的能力,但要编写较为复杂且实用的程序,我们就不得不掌握ARM 汇编的伪指令(pseudo- instruction)。
千万别把汇编伪操作(directive)与汇编伪指令(pseudo- instruction)弄混了,directive 不会被编译器编译为机器指令,但pseudo- instruction 会。
而pseudo-instruction 与指令(instruction)的区别在于,1 条instruction 与1 条机器指令对应,而编译器会把1 条pseudo-instruction 编译为1 条或多条机器指令。
ARM 汇编伪指令共4 条:ldr、adr、adrl、nop1、ldr首先我们来回答基本寻址模式与基本指令一文中提出的问题。
如果我们需要mov r0, #10000 这样的指令,应该怎么办?(常数10000 不能在机器指令32bit 中的低12bit 中被表示出来)。
当你进行编译的时候,Error:All70E 的错误就会出现,如下图。
其实,这个问题很容易解决,只需要将mov r0, #10000 换为ldr r0, =10000 即可。
为什么这样就可以了呢?因为,这里的ldr r0, =10000 并非我们已经学过的ldr 指令,而是一条伪指令,编译器会将这条伪指令替换为:ldr r0, [pc, #-4]DCD 10000DCD 所分配的内存空间中存放了整数10000,该内存空间被称为literal pool,中文名称文字池。
由于整个程序都是由编译器编译的(包括文字池的分配),所以很显然编译器能够知道ldr 指令在内存中的地址与文字池在内存中的位置之间的偏移量,因此编译器就可以正确地使用以pc 为基址,采用相对寻址的ldr 指令将文字池中的数取出加载到寄存器r0 中。
由此可见,编译器对于ldr r0, =10000 这条伪指令的处理,其实质是:。
ARM汇编伪指令详解
ARM汇编伪指令详解(转载)2007-09-13 00:40ARM汇编程序分析过程中,比较难理解的是他的伪操作、宏指令和伪指令。
在读vivi时遇到很多不懂的,所以在此对引导程序中出现伪操作、宏指令和伪指令进行总结,*****************************************************一、GET option.s// GET和INCLUDE功能相同功能:引进一个被编译过的文件。
格式:GET filename其中:fiename 汇编时引入的文件名,可以有路径名。
GET符号在汇编时对宏定义,EQU符号以及存储映射时是很有用的,在引入文件汇编完以后,汇编将从GET符号后开始。
在被引入的文件中可能有GET符号再引入其他的文件。
GET符号不能用来引入目标文件。
*****************************************************二、INTPND EQU 0x01e00004//EQU可以用“*”代替,在阅读源程序时注意。
功能:对一个数字常量赋予一个符号名。
格式:name EQU expression其中:name 符号名。
Expression 寄存器相关或者程序相关的固定值。
使用EQU定义常量,与C语言中用#define定义一个常量相同。
例:num EQU 2 ;数字2赋予符号num*****************************************************三、GBLL THUMBCODE[ {CONFIG} = 16THUMBCODE SETL {TRUE}CODE32|THUMBCODE SETL {FALSE}][ THUMBCODECODE32 ;for start-up code for Thumb mode]//其中[=IF ,|=ELSE ,]= ENDIF, CODE32 表明一下操作都在ARM状态。
ARM汇编语言伪指令
鲁东大学 LUDONG UNIVERSITY
VersionNumber
Example
GBLA VersionNumber SETA 21
Debug
GBLL Debug SETL {TRUE}
GBLS VersionString VersionString SETS "Version 1.0"
鲁东大学 LUDONG UNIVERSITY
MEND
数据定义伪指令
鲁东大学 LUDONG UNIVERSITY
数据定义指令(Data definition directives):用于进行 数据空间分配。
SPACE DCB DCD, DCDU
MAP, FIELD
SPACE
鲁东大学 LUDONG UNIVERSITY
The SPACE directive reserves a zeroed block of memory.
伪指令举例
鲁东大学 LUDONG UNIVERSITY
AREA ThumbSub, CODE, READONLY ENTRY CODE32 ;ARM
header ADR r0, start + 1 CODE16 ;Thumb.
start MOV r0, #10
doadd MOV pc, lr
END
GBLA, GBLL, GBLS LCLA, LCLL, LCLS SETA, SETL,SETS
全局变量声明
鲁东大学 LUDONG UNIVERSITY
GBLA, GBLL, GBLS
-- 声明一个全局的算术、逻辑和串变量
Directives GBLA
Variable Type arithmetic
ARM汇编指令集
ARM汇编指令集汇编指令集的介绍,包括指令和伪指令。
指令和概念指令指令指的是CPU机器指令的助记符,是由CPU的指令集提供的,经过编译之后,会以机器码的形式由CPU读取执⾏伪指令伪指令本质上不是指令,和CPU的机器指令没有任何关系,只是和指令⼀起写在代码中⽽已,是由环境提供的,其⽬的是⽤于指导编译过程,伪指令经过编译后不会⽣成⼆进制机器码,仅仅在编译阶段有效果指令编程风格ARM官⽅风格官⽅风格指令⼀般使⽤⼤写,例如:LDR R0,[R1],Windows中常使⽤这种风格GUN Linux风格指令⼀般使⽤⼩写字母,例如:ldr r0,[r1],Linux环境中常⽤这种风格ARM汇编特点LDR/STR架构1. 采⽤RISC架构,CPU本⾝不能直接读取内存,⽽需要把内存中的数据加载到CPU的通⽤寄存器中,才能被CPU处理2. ldr(load register)将内存中的数据加载到通⽤寄存器3. str(store register)将寄存器内容存⼊内存空间4. ldr和str组合,可以实现ARM CPU和内存的数据交换8种寻址⽅式1. 寄存器寻址:move r1,r2:把r2的值赋值到r1寄存器中2. ⽴即寻址:move r0,#0xFF00:把⽴即数0xFF00赋值给r0寄存器3. 寄存器移位寻址:move r0,r1,lsl #3:把r1左移三位(*8)之后的值赋值给r0寄存器4. 寄存器间接寻址:ldr r1,[r2]:寄存器有中括号,表⽰内存地址对应的数据,所以这⾥r2表⽰⼀个内存地址,[]表⽰取r2指针对应的数据,这句代码的意思是把r2对应的内存中的数据赋值给r15. 基址变址寻址:ldr r1,[r2,#4]:将指针r2的值(内存地址)+4之后指向的数据赋值给r16. 多寄存器寻址:ldmia r1!,{r2 - r7,r12}:这种情况下,r1是⼀个指针,⾥边存放的内存地址,然后以r1⾥边的内存地址为基地址,向后以此加1得到{}⾥的寄存器数量个内存地址,然后将刚才得到的这些内存地址指向的变量的值赋值给{}⾥的对应位置的寄存器,类似从内存中读取数组,然后把数组的元素依次赋值给这些寄存器7. 堆栈寻址:stmfd sp!,{r2 - r7,lr}:和多寄存器类似,区别是将栈SP中连续访问{}数量个字节,然后依次赋值给{}⾥的寄存器8. 相对寻址:beq flag::flag:标号⽤于标记标号后⾯那句指令的地址,常⽤来表⽰⼊⼝点,函数名就是⼀个标号,C语⾔中的goto就可以跳转到⼀个标号,在ARM汇编中⽤指令b flag:就可以跳转到flag:对应的标号处执⾏,和beq flag:是⼀样的,其原理是相对于PC程序位置寄存器做⼀个偏移指令后缀1. ARM中的指令可以带后缀,从⽽丰富该指令的功能,这种形式叫做指令族,常⽤的后缀有:2. B(byte):功能不变,操作长度变为8位(依赖CPU位数,以下相同)3. H(Halfword):功能不变,操作长度变为16位3. H(Halfword):功能不变,操作长度变为16位4. S(signed):功能不变,操作数变为有符号数5. S(S标识):影响CPSR⾥的NZCV标识位,6. 举例:1. ldr指令族:ldrb,ldrh,ldrsb ldrsh,从内存中加载指定长度的数据2. mov指令族:movs r0,#0,结果是0,赋值会影响CPSR的NZCV标识,将Z位置为1条件执⾏后缀1. 条件执⾏后缀⽤于限制该执⾏执⾏的,只有在符合条件之后才能够执⾏该指令2.3. 举例:moveq r0,r1,如果eq成⽴,执⾏mov r0,r1,不成⽴则该条不执⾏,和C语⾔中的条件判断类似4. 条件后缀成⽴与否,不是取决于本条指令,⽽是取决于之前指令运⾏后的结果5. 条件后缀决定了本条指令是否执⾏,不会影响之前和之后指令6. 条件后缀和CPSR的NZCV位相关,例如,如果上⼀句代码执⾏的结果将Z置为1,下⼀句带有eq条件后缀的语句就会被执⾏多级指令流⽔线1. 多级流⽔线⽤于增加处理器处理指令的速度,2. 允许CPU同时异步的执⾏多条指令,⽽⾮上⼀条指令全部执⾏完毕之后才会执⾏下⼀条指令3. 多级可以简单那理解为把⼀条指令分为多个步骤来异步执⾏,例如:1. CPU把⼀条指令分为[取址,解码,执⾏]3个步骤,则为3级指令流⽔线2. 第⼀条指令进⾏取值操作3. 第⼀条指令取值完毕,进⼊解码操作,第⼆条指令紧随其后就开始执⾏取值操作4. 第⼀条指令解码完毕,进⼊执⾏操作,第⼆条指令紧接着进⼊解码操作,同时第三条指令进⼊取值操作5. 第⼀条指令执⾏完毕,第⼆条指令进⼊执⾏操作,第三条指令进⼊解码操作,第四条指令进⼊取值操作,依次类推4. 可见,多级流⽔线可以提⾼同时执⾏指令的数量,从⽽加速指令执⾏5. 需要注意的是,PC指向的是正在取值的指令,⽽⾮正在执⾏的指令,之间的差值就是流⽔线级数和单字节长度的乘积,在中断返回到PC的时候需要注意这个问题ARM指令数据处理指令数据传输指令mov:move,在两个寄存器之间或者⽴即数和寄存器之间传递数据,将后⼀个寄存器上的值或者⽴即数赋值给前⼀个寄存器 例如:mov r1,r0mov r1,#0xFF:将⽴即数0xFF赋值给寄存器r1mvn:和mov⽤法⼀致,区别是mvn会把后⼀个寄存器的值或者⽴即数按位取反后赋值给前⼀个寄存器 例如:mvn r0,#0xFF,则r0的值为0xffffff00(32位数据)算术运算指令add:加法运算sub:减法运算rsb:反减运算adc: 带进位的加法运算sbc: 带进位的减法运算rsc:带进位的反减指令逻辑指令and:与操作orr:或操作eor:异或操作bic:位清除操作⽐较指令cmp:⽐较⼤⼩cmn:取反⽐较tst:按位与运算teq:按位异或运算乘法指令mvl: mla: umull: umlal: smull: smlal:前导0计数clz:统计⼀个数的⼆进制位前⾯有⼏个0CPSR访问指令mrs⽤于读取CPSR和SPSRmsr⽤于写CPSR和SPSRCPSR和SPSRCPSR是程序状态寄存器,整个Soc只有⼀个SPSR在五种异常模式下各有⼀个,⽤于从普通模式进⼊异常模式的时候,保存普通模式下的CPSR,在返回普通模式时可以恢复原来的CPSR跳转分⽀指令b指令: ⽆条件直接跳转,没打算返回bl指令:跳转前把返回地址放⼊lr中,以便返回,常⽤在函数中bx指令:跳转同时切换到ARM模式,⽤于异常处理的跳转内存访问指令ldr:加载指定内存地址的数据到寄存器,按照字节访问str:加载指定寄存器数据到内存地址中,按照字节访问ldm:和ldr功能⼀样,⼀次多字节多寄存器访问stm:和str功能⼀样,⼀次多字节多寄存器访问swp:内存和寄存器互换指令,⼀边读⼀边写,例如:swp r1,r2,[r0]:读取指针r0的数据到r1中,同时把r2的数据赋值给r0指针指向的变量软中断指令swi(software interrupt),在软件层模拟产⽣⼀个中断,这个中断会传送给CPU,常⽤于实现系统调⽤⽴即数⾮法与合法ARM指令都是32为,除了指令标记和操作标记外,只能附带少位数的⽴即数,所以有⾮法与合法之分⾮法⽴即数:合法⽴即数:经过任意位数的移位后,⾮0部分可以⽤8位表⽰就是合法⽴即数协处理器与指令协处理器协处理器属于Soc中另外⼀颗核⼼,⽤于协助主CPU实现某些功能,被主CPU调⽤来执⾏任务,协处理器和MMU,Cache,TLB有功能和管理上的联系ARM设计可以⽀持多达16个协处理器,但是⼀般只实现其中的CP15协处理器指令mrc:读取CP15中的寄存器mcr:向CP15中的寄存器写数据指令⽤法:mcr{<”cond”>} p15,<”opcode_1”>,<”Rd”>,<”Crn”>,<”Crm”>,{<”opcode_2”>} opcode_1:对于CP15永远为0Rd:ARM通⽤寄存器Crn:CP15寄存器,取值范围c0~c15Crm:CP15寄存器,⼀般为c0opcode_2:省略或者为0ldm,stm和栈ldm,stmldr与str只能访问4个字节,当数据较⼤的时候,就会明显的降低效率,这时就需要使⽤到ldm和stm,ldm与stm是⼤量的从寄存器与内存交换数据的⽅式,常⽤于在内存和寄存器之间⼤量读取和写⼊数据:stmia sp {r0 - r12}:stm表⽰进⾏批量数据操作,ia的意思是将r0存⼊SP的内存地址处,然后SP内存地址+4(32位),将r1存⼊该地址,内存地址再+4,存⼊r2,依次存到r12,这就是⼀个寄存器和内存交换⼤量数据的⽰例,在⼀个周期内完成了多个内存地址和多个寄存器的操作。
嵌入式系统原理与应用常用Arm汇编伪指令
常用Arm汇编伪指令
在Arm汇编语言程序中,有一些特殊指令用于对汇编过程进行控制,这些指令不是可执行指令也没有对应的机器码,只用于汇编过程中为汇编程序提供汇编信息,这些指令称为伪指令,它们所完成的操作称为伪操作。
常用的伪指令有以下几种:符号定义伪指令、数据定义伪指令、汇编控制伪指令、信息报告伪指令以及杂项伪指令。
下面列出了上述几种常用的Arm汇编伪指令。
1. 符号定义伪指令
符号定义伪指令用于定义汇编程序中的变量、对变量赋值以及定义寄存器别名等操作。
表2.1 符号定义伪指令
2. 数据定义伪指令
数据定义伪指令一般用于为特定的数据分配存储单元,并可对分配的存储单元进行初始化。
表2.2 数据定义伪指令
3. 汇编控制伪指令
汇编控制伪指令用于控制汇编程序的执行流程。
表2.3 汇编控制伪指令
4. 信息报告伪指令
报告伪指令用于汇编报告指示。
表2.4 信息报告伪指令
5. 杂项伪指令
杂项伪指令是未包含在表2.1至2.4中且在汇编程序设计中常用的伪指令。
表2_5 杂项伪指令。
ARM伪指令介绍
以上三条伪指令用于声明局部变量,在其作用范围内变量名必须唯一。 以上三条伪指令用于声明局部变量,在其作用范围内变量名必须唯一。 9
ARM系统硬件设计基础 第4章 ARM系统硬件设计基础
3、变量赋值伪指令SETA、SETL、SETS 变量赋值伪指令SETA、SETL、 SETA
SETA伪指令可以为一个算术变量赋值; SETA伪指令可以为一个算术变量赋值; 伪指令可以为一个算术变量赋值 SETL伪指令可以为一个逻辑变量赋值; SETL伪指令可以为一个逻辑变量赋值; 伪指令可以为一个逻辑变量赋值 SETS伪指令可以为一个字符串变量赋值。 SETS伪指令可以为一个字符串变量赋值。 伪指令可以为一个字符串变量赋值 语法格式: SETA(SETL或SETS) 语法格式: 变量名 SETA(SETL或SETS) 表达式 例: DATE1 DATE1 GBLA SETA LCLL STATUS SETL GBLS STRNG SETS DATE1 DATE1 0xf2003b*2 xf2003b*2 2003b* STATUS {TRUE} STRING “Linux” ;声明全局算术变量DATE1 声明全局算术变量DATE1 DATE ;为这个变量赋值 ;声明局部逻辑变量STATUS 声明局部逻辑变量STATUS ;为这个逻辑变量赋值 ;声明一个全局字符串变量STRING 声明一个全局字符串变量STRING ;为STRING赋值”Linux” STRING赋值”Linux” 赋值
,=DATA1 LDR R0,=DATA1 (2)方便记忆 =DATA1 LDR R0,=DATA1
直接加载变量123456 LDR R0,=123456 ;直接加载变量123456 =SECTION+04 LDR R1,=SECTION+04 [R1 LDR R0,[R1] (3)方便修改 (4)不必关心存储空间 编译程序会自动安排变量的存储空间 11 ;先加载存储单元地址
四、ARM汇编语言伪指令
字节对准。例如,expression等于10,该段将按1KB对
准。 • CODE 代码段,缺省为READONLY • COMDEF 通用段定义。该段可包括代码和数据,在多 个源文件中同名的COMDEF段必须相同 • COMMON 通用数据段,不能定义任何代码和数据, 通常由链接器初始化为零
TM
12
指导性伪指令
(1)AREA
• DATA 包含数据,但不包含指令,缺省READWRIT。 • INTERWORK 表明代码段可以适用ARM/Thumb
interworking功能。
• NOINIT 表明数据段初始化为零,只为指示符保留空间 • READONLY 表明该段只读。 • READWRITE 表明该段可读可写。
Development Suite (简称RVDS) 的编译器RVCT
与Keil的工程管理、调试仿真工具集成在一起,是 一款非常强大的ARM 微控制器开发工具。
TM
4
2. GNU ARM开发工具
GNU是“GNU„s Not Unix”的递归缩写。在1983年
9月27日由Richard Stallman公开发起GNU计划,
TM
16
数据定义伪指令
(1)DATA 定义此标号是程序内的数据区
例: Thumb-fn AREA example ,CODE ; ; MOV pc ,lr
Thumb-Data
DATA
DCB 1,3,4
TM
17
数据定义伪指令
(2)DCB或“=”
功能:分配一个或多个字节.
(3)DCD或“&” 功能:分配一个或多个字,从4个字节边界开始. (4)DCW 功能:分配一个或多个半字以半字边界开始的内存 区域.
ARM汇编语言伪指令
ARM汇编语言伪指令ARM汇编语言伪指令ARM汇编语言ARM汇编语言源程序语句,一般由指令,伪操作,宏指令和伪指令作成.ARM汇编语言的设计基础是汇编伪指令,汇编伪操作和宏指令.伪操作,是ARM汇编语言程序里的一些特殊的指令助记符,其作用主要是为完成汇编程序做各种准备工作,在源程序运行汇编程序处理,而不是在计算机运行期间有机器执行.也就是说,这些伪操作只是汇编过程中起作用,一旦汇编结束,伪操作的使命也就随之消失.宏指令,是一段独立的程序代码,可以插在程序中,它通过伪操作来定义,宏在被使用之前必须提前定义好,宏之间可以互相调用,也可自己递归调用.通过直接书写宏名来使用宏.并本具宏指令的格式输入输出参数.宏定义本身不产生代码,只是在调用它时把宏体插入到原程序中.宏与C语言中的子函数形参和实参的调用相似,调用宏时通过实际的指令来代替宏体实现相关的一段代码,但宏的调用与子程序的调用有本质的区别,既宏并不会节省程序的空间,其优点是简化程序代码,提高程序的可读性以及宏内容可以同步修改.伪操作,宏指令一般与编译程序有关,因此ARM汇编语言的伪操作,宏指令在不同的编译环境下有不同的编写形式和规则.伪指令也是ARM汇编语言程序里的特殊助记符,也不在处理器运行期间由机器执行,他们在汇编时将被合适的机器指令代替成ARM或Thumb指令,从而实现真正的指令操作.目前常用的ARM编译环境有2种.1. ADS/SDT IDE:ARM公司开发,使用了CodeWarrior公司的编译器.2. 集成了GNU开发工具的IDE开发环境;它由GNU的汇编器as,交叉汇编器gcc和连接器id组成.ADS编译环境下的ARM伪操作和宏指令,可参考北航出版社的<<ARM微控制器基础与实践》(周立功)这里主要讲述ARM GNU常用汇编语言4 ARM GNU常用汇编语言介绍4.1 ARM GNU常用汇编伪指令介绍1. abort.abort: 停止汇编.align absexpr1,absexpr2:以某种对齐方式,在未使用的存储区域填充值. 第一个值表示对齐方式,4, 8,16或32. 第二个表达式值表示填充的值.2. if...else...endif.if.else.endif: 支持条件预编译3. include.include "file": 包含指定的头文件, 可以把一个汇编常量定义放在头文件中.4. comm.comm symbol, length:在bss段申请一段命名空间,该段空间的名称叫symbol, 长度为length. Ld连接器在连接会为它留出空间.5. data.data subsection: 说明接下来的定义归属于subsection数据段.6. equ.equ symbol, expression: 把某一个符号(symbol)定义成某一个值(expression).该指令并不分配空间.7. global.global symbol: 定义一个全局符号, 通常是为ld使用.8. ascii.ascii "string": 定义一个字符串并为之分配空间.9. byte.byte expressions: 定义一个字节, 并为之分配空间.10. short.short expressions: 定义一个短整型, 并为之分配空间.11. int.int expressions: 定义一个整型,并为之分配空间.12 long.long expressions: 定义一个长整型, 并为之分配空间.13 word.word expressions: 定义一个字,并为之分配空间, 4bytes.14. macro/endm.macro: 定义一段宏代码, .macro表示代码的开始, .endm表示代码的结束.15. reqname .req register name: 为寄存器定义一个别名.16. code.code [16|32]: 指定指令代码产生的长度, 16表示Thumb指令, 32表示ARM指令.17. ltorg.ltorg: 表示当前往下的定义在归于当前段,并为之分配空间.4.2 ARM GNU专有符号1. @表示注释从当前位置到行尾的字符.2. #注释掉一整行.3. ;新行分隔符.4.3 操作码1. NOPnop空操作, 相当于MOV r0, r02. LDRldr <register> , = <expression>相当于PC寄存器或其它寄存器的长转移.3.ADRadr <register> <label>相于PC寄存器或其它寄存器的小范围转移. ADRLadrl <register> <label>相于PC寄存器或其寄存器的中范围转移.5 可执行生成说明5.1 lds文件说明5.1.1 主要符号说明1. OUTPUT_FORMAT(bfdname)指定输出可执行文件格式.2. OUTPUT_ARCH(bfdname)指定输出可执行文件所运行CPU平台3. ENTRY(symbol)指定可执行文件的入口段5.1.2 段定义说明1. 段定义格式SECTIONS { ...段名 :{内容}...}文章出处:。
ARM汇编伪指令
ARM汇编伪指令在ARM汇编语言源程序中有些特殊助记符,它们没有相对应的操作码或者机器码,通常称为伪指令,它们所完成的操作称为伪操作。
伪指令在源程序中的作用是为完成汇编程序作各种准备工作的,由汇编程序在源程序的汇编期间进行处理,仅在汇编过程中起作用。
在ARM的汇编程序中,有以下几种伪指令:符号定义伪指令、数据定义伪指令、汇编控制伪指令、宏指令以及其他伪指令。
一、符号定义伪指令作用:用于定义ARM汇编程序中的变量、对变量赋值以及定义寄存器的别名等。
符号定义有如下几种伪指令:用于定义局部变量的LCLA、LCLL和LCLS。
用于定义全局变量的GBLA、GBLL和GBLS。
用于对变量赋值的SETA、SETL和SETS。
为通用寄存器列表定义名称的RLIST。
(1)LCLA、LCLL和LCLS格式:LCLA/LCLL/LCLS 局部变量名说明:LCLA、LCLL和LCLS伪指令用于定义一个汇编程序中的局部变量并初始化。
其中:LCLA定义一个局部的数字变量,初始化为0。
LCLL定义一个局部的逻辑变量,初始化为F。
LCLS定义一个局部的字符串变量,初始化为空串。
这3条伪指令用于声明局部变量,在其局部作用范围内变量名必须惟一,例如在宏内。
例:LCLA num1 ;定义一个局部数字变量,变量名为num1 LCLL I2 ;定义一个逻辑变量,变量名为I2LCLS str3 ;定义一个字符串变量,变量名为str3num1 SETA 0xabcd ;将该变量赋值为0xabcdI2 SETL {FALSE} ;将该变量赋值为真str3 SETS “HELLO”;将该变量赋值为“HELLO”(2)GBLA、GBLL和GBLS格式:GBLA/GBLL/GBLS 变量名说明:GBLA、GBLL和GBLS伪操作定义一个汇编程序中的全局变量并初始化。
其中:GBLA定义一个全局数字变量,并初始化为0。
GBLL定义一个全局逻辑变量,并初始化为F。
介绍12个ARM常用的伪指令
介绍12个ARM常用的伪指令1、AREAAREA 伪指令用于定义一个代码段或数据段。
语法格式:AREA 段名属性1 ,属性2 ,……其中,段名若以数字开头,则该段名需用“ | ” 括起来,如|1_te st| 。
属性字段表示该代码段(或数据段)的相关属性,多个属性用逗号分隔。
常用的属性如下:— CODE 属性:用于定义代码段,默认为READonLY 。
— DATA 属性:用于定义数据段,默认为READWRITE 。
— READonLY 属性:指定本段为只读,代码段默认为READonLY 。
— READWRITE 属性:指定本段为可读可写,数据段的默认属性为R EADWRITE 。
— ALIGN 属性:使用方式为ALIGN表达式。
在默认时,ELF (可执行连接文件)的代码段和数据段是按字对齐的,表达式的取值范围为0 ~31 ,相应的对齐方式为表达式2次方。
— COMMON 属性:该属性定义一个通用的段,不包含任何的用户代码和数据。
各源文件中同名的COMMON段共享同一段存储单元。
一个汇编语言程序至少要包含一个段,当程序太长时,也可以将程序分为多个代码段和数据段。
使用示例:AREA Init ,CODE ,READONLY该伪指令定义了一个代码段,段名为Init ,属性为只读2、ALIGNALIGN 伪指令可通过添加填充字节的方式,使当前位置满足一定的对其方式。
语法格式:ALIGN { 表达式{ ,偏移量}}其中,表达式的值用于指定对齐方式,可能的取值为2的幂,如1 、2 、4 、8 、16 等。
若未指定表达式,则将当前位置对齐到下一个字的位置。
偏移量也为一个数字表达式,若使用该字段,则当前位置的对齐方式为:2 的表达式次幂+偏移量。
使用示例:AREA Init ,CODE ,READonLY ,ALIEN =3 ;指定后面的指令为8字节对齐。
指令序列END3、ENTRYENTRY 伪指令用于指定汇编程序的入口点。
arm伪操作-伪指令-宏指令
可通过下面的 指令访问数据结构中的信息: LDR R0, b ;LDR R0, Datastruc+4
例:判断当前内存的使用情况是否超过程序 分配的可用内存的方法。
startofmem EQU 1000 ;分配内存首地址 endofmem EQU 2000 ;分配内存末地址 MAP startofmem ;内部首地址为startofmem a FIELD 4 ;字段a长度为4,相对位置为0 b FIELD 4 ;字段b长度为4,相对位置为4 x FIELD 8 ;字段x长度为8,相对位置为8 y FIELD 8 ;字段y长度为8,相对位置为16 s FIELD max ;字段s长度为max,相对位置为24 endofstru ASSERT FIELD 0 ;endofstru用于检查内存是否越界
1.1.1两种常见的ARM编译开发环境
ADS/SDT IDE开发环境:它由ARM公司开 发,使用了CodeWarrior公司的编译器; EmbestIDE开发环境:集成了GNU开发工具 的IDE开发环境,由GNU的汇编器as、交叉 编译器gcc、和链接器ld等组成。 这两种开发环境的编译器都完全支持ARM 指令集,但伪指令不同,代码风格不同。
数据定义伪操作
LTORG:声明一个数据缓冲池的开始。 SPACE:分配一块内存单元,并用0初始化。 MAP:定义一个结构化的内存表的首地址。 FIELD:定义结构化内存表中的一个数据域。 DCB:分配一段字节内存单元,并初始化。 DCD、DCDU:分配一段字内存单元,并初始 化。
1、 LTORG 用于声明一个数据缓冲池(文字池)的开始。 语法格式:
LTORG 例:start BL func …… func LDR R1,=0x8000 …… MOV PC,LR LTORG Data SPACE 4200 END 默认数据缓冲池为空
ARM汇编 控制伪指令之一
ARM 汇编控制伪指令之一汇编控制伪指令用于控制汇编程序的执行流程,常用的汇编控制伪指令包括以下几条:IF 、ELSE 、ENDIF WHILE 、WEND MACRO 、MEND MEXIT 1、IF、ELSE、ENDIF 语法格式:IF 逻辑表达式指令序列1 ELSE 指令序列2 ENDIF IF 、ELSE 、ENDIF 伪指令能根据条件的成立与否决定是否执行某个指令序列。
当IF 后面的逻辑表达式为真,则执行指令序列 1 ,否则执行指令序列 2 。
其中,ELSE 及指令序列 2 可以没有,此时,当IF 后面的逻辑表达式为真,则执行指令序列 1 ,否则继续执行后面的指令。
IF 、ELSE 、ENDIF 伪指令可以嵌套使用。
使用示例:GBLL Test ;声明一个全局的逻辑变量,变量名为Test IF Test = TRUE 指令序列1 ELSE 指令序列2 ENDIF 2、WHILE、WEND 语法格式:WHILE 逻辑表达式指令序列WEND WHILE 、WEND 伪指令能根据条件的成立与否决定是否循环执行某个指令序列。
当WHILE 后面的逻辑表达式为真,则执行指令序列,该指令序列执行完毕后,再判断逻辑表达式的值,若为真则继续执行,一直到逻辑表达式的值为假。
WHILE 、WEND 伪指令可以嵌套使用。
使用示例:GBLA Counter ;声明一个全局的数学变量,变量名为Counter Counter SETA 3 ;由变量Counter 控制循环次数WHILE Counter 10 指令序列WEND 3、MACRO、MEND 语法格式:$ 标号宏名$ 参数 1 ,$ 参数 2 ,指令序列MEND MACRO 、MEND 伪指令可以将一段代码定义为一个整体,称为宏指令,然后就可以在程序中通过宏指令多次调用该段代码。
其中,$ 标号在宏指令被展开时,标号会被替换为用户定义的符号,宏指令可以使用一个或多个参数,当宏指令被展开时,这些参数被相应的值替换。
ARM·汇编伪指令
ARM·汇编伪指令在ARM 汇编程序中,有如下几种伪指令*符号定义伪指令*数据定义伪指令*汇编控制伪指令*信息报告伪指令*宏指令以及其他伪指令【符号定义伪指令】定义局部变量LCLA,LCLL,LCLS 定义全局变量GBLA,GBLL,GBLS对变量赋值SETA,SETL,SETS【数据定义伪指令】DCBDCW/DCWUDCD/DCDUDCQ/DCDUDCFS/DCFSUDCFD/DCFDUSPACEF IELDMAP*DCB 表达式用于分配一片连续的字节*DCW/DCWU 表达式用于分配一片连续的半字*DCD/DCDU 表达式用于分配一篇连续的字*DCQ/DCQU 表达式用于分配连续的8 个字节*DCFD/DCFDU 表达式用于为双精度浮点数分配一片连续的字存储单元*DCFS/DCFSU 表达式用于为单精度浮点数分配一片连续的字存储单元*SPACE 表达式用于分配一片连续的存储区域并初始化为0,表达式是要分配的字节数*MAP FILEDMAP 定义一个结构化的内存表的首地址[MAP 0x100, R0] 首地址0x100+R0FILED 定义一个结构化内存表中的数据域[MAP 0x30000000A FILED 4B FILED 4C FILED 4] 【汇编控制伪指令】*MACRO MEND 宏名*IF---ELSE---ENDIF [ | ]*WHILE---- WEND*NEXIT 从宏中退出【一些其他的伪指令】*ASSERT 逻辑表达式必须满足这一条件才可以进行编译*ALIGN [表达式[,偏移量]]AREA Init, CODE, READONLY, ALIGN=3*AREA 段名属性DATA 数据段默认READWRITECODE 代码段默认READONLY*NOINIT 内存单元初始化0*ALIGN*COMMON 通用段(不包括数据段和代码段)*ENTRY*END*EQU (NUM EQU 100)(相当于c 语言中的#define)*EXPORT 声明一个全局变量IMPORT IMPORT Main (引用Main 变量,但Main 不是在这个程序中定义的)EXPORT 和IMPORT 一样,但是源文件中若没有引用,则该标号。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
ARM汇编伪指令介绍在ARM汇编语言程序中,有一些特殊指令助记符,这些助记符与指令系统的助记符不同,没有相对应的操作码,通常称这些特殊助记符为伪指令,它们所完成的操作称为微操作。
伪指令在源程序中的作用是为完成汇编程序作各种准备工作的,这些伪指令仅在汇编过程中起作用,一旦汇编结束,伪指令的使命就完成。
在ARM 的汇编程序中,有如下几种伪指令:符号定义伪指令、数据定义伪指令、汇编控制伪指令、宏指令及其它伪指令。
一、符号定义(Symbol Definition)伪指令符号定义伪指令用于定义ARM汇编程序中的变量、对变量赋值以及定义寄存器的别名等操作。
常见的符号定义伪指令有如下几种:—用于定义全局变量的GBLA、GBLL和GBLS。
—用于定义局部变量的LCLA、LCLL和LCLS。
—用于对变量赋值的SETA、SETL、SETS。
—为通用寄存器列表定义名称的RLIST。
1.GBLA、GBLL和GBLS语法格式:GBLA(GBLL或GBLS)全局变量名GBLA、GBLL和GBLS伪指令用于定义一个ARM程序中的全局变量,并将其初始化。
其中:GBLA伪指令用于定义一个全局的数字变量,并初始化为0;GBLL伪指令用于定义一个全局的逻辑变量,并初始化为F(假);GBLS伪指令用于定义一个全聚德字符串变量,并初始化为空;由于以上三条伪指令用于定义全局变量,因此在整个程序范围内变量名必须唯一。
使用示例:GBLA Test1:定义一个全局的数字变量,变量名为Test1Test1 SETA 0xaa:将该变量赋值为0xaaGBLL Test2:定义一个全局的逻辑变量,变量名为Test2Test2 SETL {TRUE};将该变量赋值为真GBLS Test3:定义一个全局的字符串变量,变量名为Test3Test3 SETS “Testing”:将该变量赋值为“Testing”2.LCLA、LCLL和LCLS语法格式:LCLA(LCLL或LCLS)局部变量名LCLA、LCLL和LCLS伪指令用于定义一个ARM程序中的局部变量,并将其初始化。
其中:LCLA伪指令用于定义一个局部的数字变量,并初始化为0;LCLL伪指令用于定义一个局部的逻辑变量,并初始化为F(假);LCLS伪指令用于定义一个全聚德字符串变量,并初始化为空;由于以上三条伪指令用于定义局部变量,因此在其作用范围内变量名必须唯一。
使用示例:LCLA Test4:定义一个局部的数字变量,变量名为Test4Test4 SETA 0xaa:将该变量赋值为0xaaLCLL Test5:定义一个局部的逻辑变量,变量名为Test5Test5 SETL {TRUE};将该变量赋值为真LCLS Test6:定义一个全聚德字符串变量,变量名为Test6Test6 SETS “Testing”:将该变量赋值为”Testing”3.SETA、SETL和SETS语法格式:变量名SETA(SETL或SETS)表达式伪指令SETA、SETL、SETS用于给一个已定义的全局变量或局部变量赋值。
其中:SETA伪指令用于给一个数字变量赋值;SETL伪指令用于给一个逻辑变量赋值;SETS伪指令用于给一个字符串变量赋值;其中,变量名为已经定义过的全局变量或局部变量,表达式为将要付给变量的值。
使用示例:LCLA Test7:定义一个局部的数字变量,变量名为Test7Test7 SETA 0xaa:将该变量赋值为0xaaLCLL Test8:定义一个局部的逻辑变量,变量名为Test8Test8 SETL {TRUE};将该变量赋值为真LCLS Test9:定义一个全聚德字符串变量,变量名为Test9Test9 SETS “Testing”:将该变量赋值为”Testing”4.RLIST语法格式:名称RLIST{寄存器列表}RLIST伪指令可用于对一个通用寄存器列表定义名称,使用该伪指令的名称可在ARM指令LDM/STM中使用。
在LDM/STM指令中,列表中的寄存器访问次序为根据寄存器的编号由低到高。
而与列表中的寄存器排列次序无关。
使用示例:RegList RLIST {R0-R5,R8,R10}:将寄存器列表名称定义为RegList,可在ARM指令LDM/STM中通过该名称访问寄存器列表。
二、数据定义(Data Definition)伪指令数据定义伪指令一般用于为特定的数据分配存储单元。
同时可完成已分配存储单元的初始化。
常见的数据定义伪指令有如下几种:—DCB:用于分配一片连续的字节存储单元并用指定的数据初始化。
—DCW(DCWU):用于分配一片连续的半字存储单元并用指定的数据初始化。
—DCD(DCDU):用于分配一片连续的字存储单元并用指定的数据初始化。
—DCFD(DCFDU):用于为双精度的浮点数分配一片连续的字存储单元并用指定的数据初始化。
—DCFS(DCFSU):用于为单精度的浮点数分配一片连续的字存储单元并用指定的数据初始化。
—DCQ(DCQU):用于分配以8字节为单位的连续的存储单元并用指定的数据初始化。
—SPACE 用于分配一片连续的存储单元。
—MAP 用于定义一个结构化的内存表首地址。
—FIELD 用于定义一个结构化的内存表的数据域。
1.DCB语法格式:标号DCB 表达式DCB伪指令用于分配一片连续的字节存储单元并用伪指令中指定的表达式初始化。
其中,表达式可以为0~255的数字或字符串。
DCB也可用”=”代替。
使用示例:Str DCB “This is a test !”;分配一片连续的字节存储单元并初始化。
2.DCW(或DCWU)语法格式:标号DCW(或DCWU)表达式DCW(或DCWU)伪指令用于分配一片连续的半字存储单元并用伪指令中指定的表达式初始化。
其中,表达式可以为程序标号或数字表达式。
用DCW分配的半字存储单元是半字对齐的,而用DCWU分配的字存储单元并不严格半字对齐。
使用示例:DataTest DCW 1,2,3 ;分配一片连续的半字存储单元并初始化。
3.DCD(或DCDU)语法格式:标号DCD(或DCDU)表达式DCD(或DCDU)伪指令用于分配一片连续的字存储单元并用伪指令中指定的表达式初始化。
其中,表达式可以为程序标号或数字表达式。
DCD也可用”&”代替。
用DCD分配的字存储单元是字对齐的,而用DCDU分配的字存储单元并不严格半字对齐。
使用示例:DataTest DCD 4,5,6 ;分配一片连续的字存储单元并初始化。
4.DCFD(或DCFDU)语法格式:标号DCFD(或DCFDU)表达式DCFD(或DCFDU)伪指令用于为双精度的浮点数分配一片连续的字存储单元并用指定的数据初始化。
每个双精度的浮点数占据两个字单元。
用DCFD分配的字存储单元是字对齐的,而用DCFDU分配的字存储单元并不严格半字对齐。
使用示例:DataTest DCFD 2E115,-5E7 ;分配一片连续的字存储单元并初始化为指定的双精度数。
5.DCFS(或DCFSU)语法格式:标号DCFS(或DCFSU)表达式DCFS(或DCFSU)伪指令用于为单精度的浮点数分配一片连续的字存储单元并用指定的数据初始化。
每个单精度的浮点数占据一个字单元。
用DCFS分配的字存储单元是字对齐的,而用DCFSU分配的字存储单元并不严格半字对齐。
使用示例:DataTest DCFS 2E5,-5E7:分配一片连续的字存储单元并初始化为指定的单精度数。
6.DCQ(或DCQU)语法格式:标号DCQ(或DCQU)表达式DCQ(或DCQU)伪指令用于分配以8字节为单位的连续的存储单元并用指定的数据初始化。
用DCQ分配的存储单元是字对齐的,而用DCQU分配的字存储单元并不严格半字对齐。
使用示例:DataTest DCQ 100 ;分配一片连续的存储单元并初始化为指定的值。
7.SPACE语法格式:标号SPACE 表达式SPACE伪指令用于分配一片连续的存储区域并初始化为0。
其中,表达式为要分配的字节数。
SPACE也可用”%”代替。
使用示例:DataSpace SPACE 100:分配连续100字节的存储单元并初始化为0。
8.MAP语法格式:MAP 表达式{,基址寄存器}MAP伪指令用于定义一个结构化的内存表首地址。
MAP也可用”^”代替。
表达式可以为程序中的标号或数学表达式,基址寄存器为可选项,当基址寄存器选项不存在时,表达式即为内存表的首地址,当该选项存在时,内存表的首地址为表达式的值与基址寄存器的和。
MAP伪指令通常与FIELD伪指令配合使用来定义结构化的内存表,使用示例:MAP 0x100,R0:定义结构化内存表首地址方的值0x100+R0。
9.FIELD语法格式:标号FIELD 表达式FIELD伪指令用于定义一个结构化的内存表中的数据域。
FIELD 也可用”#”代替。
表达式的值为当前数据域在内存表中所占的字节数。
FIELD伪指令通常与MAP伪指令配合使用来定义结构化的内存表,MAP伪指令定义内存表的首地址,FIELD伪指令定义内存表中的各个数据域,并可以为每个数据域指定一个标号供其它的指令引用。
注意MAP和FIELD伪指令仅用于定义数据结构,并不实际分配存储单元。
使用示例:MAP 0x100:定义结构化内存表首地址方的值0x100。
A FIELD 16:定义A的长度为16字节,位置为0x100B FIELD 32:定义B的长度为32字节,位置为0x110B FIELD 64:定义C的长度为64字节,位置为0x130三、汇编控制(Assembly Control)伪指令汇编控制伪指令用于控制汇编程序的执行流程,常用的汇编控制伪指令包括以下几条:—IF、ELSE、ENDIF—WHILE、WEND—MACRO、MEND—MEXIT1.IF、ELSE、ENDIF语法格式:IF 逻辑表达式指令序列1ELSE指令序列2ENDIFIF、ELSE、ENDIF伪指令能根据条件的成立与否决定是否执行某个指令序列。
当IF后面的逻辑表达式为真,则执行指令序列1,否则执行序列2。
其中,ELSE及指令序列2可以没有,此时,当IF后面的逻辑表达式为真,则执行指令序列1,否则继续执行后面的指令。
IF、ELSE、ENDIF伪指令可以嵌套使用。
使用示例:GBLL Test:声明全局变量TestIF Test = TRUE指令序列1ELSE指令序列2ENDIF2.WHILE、ENDW语法格式:WHILE 逻辑表达式指令序列WENDWHILE、WEND伪指令能根据条件的成立与否决定是否循环执行某个指令系列。
当WHILE后面的逻辑表达式为真,则执行指令序列,该指令序列执行完毕后,再判断逻辑表达式的值,若为真则继续执行,一直到逻辑表达式的值为假。