Linux_ARM_汇编

合集下载

GNUARM汇编指令---.word

GNUARM汇编指令---.word

GNUARM汇编指令---.word第⼀部分 Linux下ARM汇编语法尽管在Linux下使⽤C或C++编写程序很⽅便,但汇编源程序⽤于系统最基本的初始化,如初始化堆栈指针、设置页表、操作 ARM的协处理器等。

初始化完成后就可以跳转到C代码执⾏。

需要注意的是,GNU的汇编器遵循AT&T的汇编语法,可以从GNU的站点()上下载有关规范。

⼀. Linux汇编⾏结构任何汇编⾏都是如下结构:[:] [} @ comment[:] [} @ 注释Linux ARM 汇编中,任何以冒号结尾的标识符都被认为是⼀个标号,⽽不⼀定⾮要在⼀⾏的开始。

【例1】定义⼀个"add"的函数,返回两个参数的和。

.section .text, “x”.global add @ give the symbol add external linkageadd:ADD r0, r0, r1 @ add input argumentsMOV pc, lr @ return from subroutine@ end of program⼆. Linux 汇编程序中的标号标号只能由a~z,A~Z,0~9,“.”,_等字符组成。

当标号为0~9的数字时为局部标号,局部标号可以重复出现,使⽤⽅法如下:标号f: 在引⽤的地⽅向前的标号标号b: 在引⽤的地⽅向后的标号【例2】使⽤局部符号的例⼦,⼀段循环程序1:subs r0,r0,#1 @每次循环使r0=r0-1bne 1f @跳转到1标号去执⾏局部标号代表它所在的地址,因此也可以当作变量或者函数来使⽤。

三. Linux汇编程序中的分段(1).section伪操作⽤户可以通过.section伪操作来⾃定义⼀个段,格式如下:.section section_name [, "flags"[, %type[,flag_specific_arguments]]]每⼀个段以段名为开始, 以下⼀个段名或者⽂件结尾为结束。

ARM汇编手册

ARM汇编手册
北京顶嵌开源科技有限公司
ARM 汇编手册
版权声明
本手册为北京顶嵌开源科技有限公司内部培训资料,仅 供本公司内部学习使用,在未经本公司授权的情况下,请勿 用作任何商业用途。

400-661-5264
专注嵌入式 Linux 技术
北京顶嵌开源科技有限公司
目录
寄存器装载和存储.............................................................................................................................5 传送单一数据.............................................................................................................................5 传送多个数据.............................................................................................................................7 SWP : 单一数据交换................................................................................................................ 9
乘法指令........................................................................................................................................... 19 MLA : 带累加的乘法..............................................................................................................19 MUL : 乘法..............................................................................................................................19

ARM中常用的汇编指令

ARM中常用的汇编指令

ARM 中常⽤的汇编指令1 处理器内部数据传输指令MSR & MRS⽤于在状态寄存器和通⽤寄存器之间传送数据MRS: 状态寄存器到通⽤寄存器的传送指令。

({R0-R12} <== CPSR,SPSR)MSR: 通⽤寄存器到状态寄存器的传送指令。

MRS:(CPSR,SPSR==>{R0-R12})MOVMOV 指令⽤于将数据从⼀个寄存器拷贝到另外⼀个寄存器,或者将⼀个⽴即数传递到寄存器⾥⾯,使⽤⽰例如下:2 存储器访问指令ARM 不能直接访问存储器,⽐如 RAM 中的数据,⼀般先将要配置的值写⼊到 Rx(x=0~12)寄存器中,然后借助存储器访问指令将 Rx 中的数据写⼊到寄存器中。

指令描述LDR Rd, [Rn , #offset]从存储器 Rn+offset 的位置读取数据存放到 Rd 中STR Rd, [Rn, #offset]将 Rd 中的数据写⼊到存储器中的 Rn+offset 位置LDR 指令LDR 主要⽤于从存储加载数据到寄存器 Rx 中, LDR 也可以将⼀个⽴即数加载到寄存器 Rx中, LDR 加载⽴即数的时候要使⽤“=”,⽽不是“#”。

在嵌⼊式开发中, LDR 最常⽤的就是读取 CPU 的寄存器值。

上述代码就是读取寄存器中的值,读取到的寄存器值保存在 R1 寄存器中,上⾯代码中 offset 是 0,也就是没有⽤到 offset。

STR 指令LDR 是从存储器读取数据, STR 就是将数据写⼊到存储器中LDR 和 STR 都是按照字进⾏读取和写⼊的,也就是操作的 32 位数据,如果要按照字节、半字进⾏操作的话可以在指令“LDR”后⾯加上B 或 H,⽐如按字节操作的指令就是 LDRB 和STRB,按半字操作的指令就是 LDRH 和 STRH。

MRS R0, CPSR @ 将特殊寄存器 CPSR ⾥⾯的数据传递给 R0,即R0=CPSR1MSR CPSR , R0 @ 将 R0 中的数据复制到 CPSR 中,即 CPSR =R01MOV R0, R1 @ 将寄存器 R1 中的数据传递给 R0,即 R0=R1MOV R0, #0X12 @ 将⽴即数 0X12 传递给 R0 寄存器,即 R0=0X1212LDR R0, =0X0209C004 @ 将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004LDR R1, [R0] @ 读取地址 0X0209C004 中的数据到 R1 寄存器中12LDR R0, =0X0209C004 @ 将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004LDR R1, =0X20000002 @ R1 保存要写⼊到寄存器的值,即R1=0X20000002STR R1, [R0] @ 将 R1 中的值写⼊到 R0 中所保存的地址中1233 压栈和出栈指令我们通常会在 A 函数中调⽤ B 函数,当 B 函数执⾏完以后再回到 A 函数继续执⾏。

ARM汇编指令集

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 汇编指令条件执行详解
2.5 条件执行在ARM 模式下,任何一条数据处理指令可以选择是否根据操作的结果来更新CPSR 寄存器中的ALU 状态标志位。

在数据处理指令中使
用S 后缀来实现该功能。

不要在CMP,CMN,TST 或者TEQ 指令中使用S 后缀。

这些比较指令总是会更新标志位。

在Thumb 模式下,所有数据处理指令都更新CPSR 中的标志位。

有一个例外就是:当一个或更多个高寄存器被用在MOV 和ADD 指令时,此时MOV 和ADD 不能更新状态标志.
几乎所有的ARM 指令都可以根据CPSR 中的ALU 状态标志位来条件执行。

参见表2-1 条件执行后缀表。

在ARM 模式下,你可以:
- 根据数据操作的结果更新CPSR 中的ALU 状态标志;
- 执行其他几种操作,但不更新状态标志;
- 根据当前状态标志,决定是否执行接下来的指令。

在Thumb 模式,大多数操作总是更新状态标志位,并且只能使用条件转移指令(B)来实现条件执行。

该指令(B)的后缀和在ARM 模式下是一样的。

其他指
令不能使用条件执行。

2.5.1 ALU 状态标志
CPSR 寄存器包含下面的ALU 状态标志:
2.5.2 执行条件
N,Z,C,V 相关的条件码后缀如下表所列:
举例说明:。

arm 汇编 指令

arm 汇编 指令

arm 汇编指令ARM汇编指令是一种用于编写ARM处理器程序的语言。

ARM处理器广泛应用于嵌入式系统和移动设备等领域。

ARM汇编指令与x86汇编指令有所不同,它基于RISC(精简指令集计算机)架构。

下面是一些基本的ARM汇编指令:1. 数据传输指令:用于在寄存器之间传输数据。

例如:- mov:将数据从一个寄存器传输到另一个寄存器。

- ldr:将数据从内存传输到寄存器。

2. 算术指令:用于执行加法、减法、乘法和除法等操作。

例如:- add:加法操作。

- sub:减法操作。

- mull:乘法操作。

- div:除法操作。

3. 逻辑指令:用于执行逻辑操作,如与、或、非等。

例如:- and:与操作。

- or:或操作。

- xor:异或操作。

4. 移位指令:用于对数据进行左移、右移或无符号右移。

例如:- lsr:无符号右移。

- asr:带符号右移。

- ror:循环右移。

5. 比较指令:用于比较两个寄存器的值。

例如:- cmp:比较两个寄存器的值,若相等则返回0,否则返回1。

6. 跳转指令:用于改变程序的执行流程。

例如:- b:条件跳转。

- bl:无条件跳转。

- bx:带状态跳转。

7. 循环指令:用于实现循环操作。

例如:- loop:内部循环。

- ldp:外部循环。

8. 调用指令:用于实现函数调用。

例如:- blx:带状态调用。

- bx:不带状态调用。

9. 系统调用指令:用于实现与操作系统交互的功能。

例如:- swi:执行系统调用。

10. 存储器访问指令:用于访问内存数据。

例如:- str:将数据存储到内存。

- ldr:从内存中加载数据。

以上仅为ARM汇编指令的一部分,实际上,ARM汇编指令还有很多其他功能。

为了更好地理解和使用ARM汇编指令,可以参考相关的教程和手册,并进行实际操作。

ARM汇编语言的语法知识

ARM汇编语言的语法知识
指令执行的条件码 加载的目标寄存器 地址表达式
地址表达式expr的取值范围: 当地址值不是字对齐时,其取值范围为-64K~64K; 当地址值是字对齐时,其取值范围为-256K~256K; 当地址值是16字节对齐时,其取值范围将更大; 该地址必须与ADRL伪指令在同一个代码段中 .
• ARM伪指令——大范围的地址读取
指令执行的条件码 加载的目标寄存器 地址表达式
地址表达式expr的取值范围: 当地址值不是字对齐时,其取值范围为-255~255字节; 当地址值是字对齐时,其取值范围为-1020~1020字节; 当地址值是16字节对齐时,其取值范围将更大; 该地址必须与ADR伪指令在同一个代码段中.
• ARM伪指令——中等范围的地址读取
;单元,并初始化为0
• ARM汇编语言伪指令----数据定义伪操作
MAP MAP用于定义一个结构化的内存表的首地址.此时,内存 表的位置计数器设置成该地址值.该伪操作可以用"^"代替.
MAP伪操作举例
LTORG伪操作通常放在无条件跳转指令之后,或者子程
序返回指令之后,这样处理器就不会错误地将数据池中的
数据当做指令来执行.
用LTORG伪指令定义数据缓冲池举例
Funel
;子程序
LDR R1, =0x8000;将0x8000加载到R1
MOV PC, LR
LTORG
;定义数据缓冲池,存放0x8000
Data SPACE 40 ;从当前位置开始分配40字节的内存
使用示例:
height DN width SN lower FN
6 ;将VFP双精度寄存器6名称定义为height 16 ;将VFP单精度寄存器16名称定义为width 6 ;将浮点寄存器6名称定义为lower

arm汇编指令格式

arm汇编指令格式

arm汇编指令格式ARM汇编指令格式ARM汇编语言是一种底层程序设计语言,用于直接操控ARM处理器的指令和寄存器。

ARM汇编指令格式是编写ARM汇编程序的基础,本文将一步一步详细解答与ARM汇编指令格式相关的问题。

第一部分:ARM汇编基础在深入理解ARM汇编指令格式之前,我们需要先了解一些基本概念。

ARM 处理器是英国公司ARM Holdings开发的一种低功耗、高性能的处理器体系架构,广泛应用于移动设备、嵌入式系统等领域。

ARM汇编语言是ARM 处理器的机器码的可读形式,用于编写底层程序。

在ARM汇编语言中,指令以二进制形式表示,通常以助记符的形式出现。

每条指令占用一个或多个字(通常一个字等于4个字节),按字节编址。

第二部分:指令格式详解ARM处理器的指令格式包括指令助记符、操作数和操作码等部分。

ARM 汇编指令格式的一般形式如下:[label:] mnemonic{cond}{S} Rd, Rn, Operand2其中,[label:]为可选项,表示标号,用于在程序中跳转或引用;mnemonic为指令的助记符,用于表示具体的操作;{cond}为可选项,表示条件代码,用于指定是否执行指令;{S}为可选项,表示是否更新条件代码;Rd表示目标操作数的寄存器;Rn表示源操作数的寄存器;Operand2为第二个操作数。

指令助记符(mnemonic)代表具体的指令功能,例如ADD表示加法、MOV表示数据传输等。

条件代码(cond)用于指定是否执行指令,常用的条件代码有EQ(等于)、NE(不等于)、GT(大于)等。

这样,我们可以根据需要选择是否在特定条件下执行指令。

更新条件代码(S)表示执行指令后是否更新条件代码寄存器。

如果设置了该标志位,则根据指令的结果设置条件代码寄存器。

目标操作数(Rd)是指令的结果存储的寄存器,源操作数(Rn)是参与指令计算的寄存器。

操作数(Operand2)是指令的第二个操作数,可以是立即数、寄存器的偏移值、寄存器的移位值等。

ARM汇编手册

ARM汇编手册
北京顶嵌开源科技有限公司
ARM 汇编手册
版权声明
本手册为北京顶嵌开源科技有限公司内部培训资料,仅 供本公司内部学习使用,在未经本公司授权的情况下,请勿 用作任何商业用途。

400-661-5264
专注嵌入ห้องสมุดไป่ตู้ Linux 技术
北京顶嵌开源科技有限公司
目录
寄存器装载和存储.............................................................................................................................5 传送单一数据.............................................................................................................................5 传送多个数据.............................................................................................................................7 SWP : 单一数据交换................................................................................................................ 9
协处理器指令...................................................................................................................................23 CDP 指令................................................................................................................................. 23 LDC 指令................................................................................................................................. 23 STC 指令..................................................................................................................................24 MCR 指令................................................................................................................................ 24 MRC 指令...................................................................................................................................24

ARM汇编入门指南

ARM汇编入门指南

ARM汇编⼊门指南本篇⽂章的⽬的是希望以⼀个例⼦的⽅式,能够不那么枯燥的的给⼤家简单介绍⼀下Android或iOS这些移动终端上ARM架构的CPU是如何执⾏ARM汇编指令的。

如果说程序员在学习任何⼀门语⾔的起点都是从学习写helloworld程序开始的,那么本篇⽂章希望的就是成为你学习ARM汇编的那第⼀篇⼊门教程,⼿把⼿的带着你⽤ARM汇编⼿写⼀个helloworld程序。

Hello, ARM⾸先我们这⾥是准备⽤GNU ARM汇编来⼿写⼀个ARM64架构的helloworld程序,那么需要先准备如下⼏个东西:⼀个⽂本编辑器,这⾥我们⽤vim .⼀个ARM64的编译器,这⾥我们⽤的是Android NDK⾥⾯⾃带的clang.伪指令以上准备好了,我们就可以开始新建⼀个⽂件名为main.S的纯⽂本⽂件,然后⽤任意⾃⼰最⼼爱的⽂本编辑器( 对于我⽽⾔它永远是vim) 来打开它,咱们先来起个头:.text.file 'main.c'.globl main // -- Begin function main.p2align 2这⾥我们使⽤是GNU ARM汇编,其中以.开头的是汇编指令 (Assembler Directive ) ⼜或被称为伪指令( Pseudo-operatio),因为它们不属于ARM指令,因此被称为伪指令,这⾥我们先尽量忽略它们,因为我们的主要学习⽬的是学习真正的ARM汇编指令,⽽不是这些伪东西,如果想了解它们可以参考⽂末的附录(伪指令参考表),这⾥只需要看懂其中的⼀句伪指令即可:.globl main这⼀句伪指令它定义了最重要的事情:在我们这个⽂件⾥⾯有⼀个叫做main名称的导出函数,它就是我们helloworld程序的⼊门函数。

main函数然后我们就可以来书写我们的helloworld程序的main函数:.typemain,@functionmain: // @main// %bb.0:subsp, sp, #32 // =32stpx29, x30, [sp, #16] // 16-byte Folded Spilladdx29, sp, #16 // =16movw8, wzrsturwzr, [x29, #-4]adrpx0, .L.straddx0, x0, :lo12:.L.strstrw8, [sp, #8] // 4-byte Folded Spillblprintfldrw8, [sp, #8] // 4-byte Folded Reloadmovw0, w8ldpx29, x30, [sp, #16] // 16-byte Folded Reloadaddsp, sp, #32 // =32ret在GNU ARM汇编⾥⾯所有以:结尾的都会视为标签 ( label ),在这⾥我们定义⼀个叫做main的标签,并且使⽤.type伪指令定义这个标签的类型是⼀个函数(function),到此我们就定义了我们的main函数。

arm的汇编 标准

arm的汇编 标准

arm的汇编标准
ARM的汇编语言规范如下:
1. 汇编语句格式:在ARM汇编中,所有标号必须在一行的顶格书写,其后面不要添加“:”,而所有指令均不能顶格书写。

2. 标识符大小写:ARM汇编器对标识符大小写敏感,书写标号及指令时字
母大小写要一致,一个ARM指令、伪指令、寄存器名可以全部为大写字母,也可以全部为小写字母,但不要大小写混合使用。

3. 注释:注释使用“;”,注释内容由“;”开始到此行结束,注释可以在一行的顶格书写。

4. 格式:格式为[标号] <指令条件S> <操作数>[;注释]。

5. 空行和换行:源程序中允许有空行,适当地插入空行可以提高源代码的可读性。

如果单行太长,可以使用字符“”将其分行,“”后不能有任何字符,包括空格和制表符等。

6. 变量和常量:对于变量的设置,常量的定义,其标识符必须在一行的顶格书写。

以上就是ARM汇编的一些规范,供您参考。

如果需要更多信息,建议查阅相关书籍或咨询专业人士。

linuxarm64启动代码:汇编部分

linuxarm64启动代码:汇编部分

linuxarm64启动代码:汇编部分1. 汇编部分主流程1.1 时序图1.2 代码解析1 ENTRY(stext)2/*3 * Kernel startup entry point.4 * ---------------------------5 *6 * The requirements are:7 * MMU = off, D-cache = off, I-cache = on or off,8 * x0 = physical address to the FDT blob.9 *10 * This code is mostly position independent so you call this at11 * __pa(PAGE_OFFSET + TEXT_OFFSET).12 *13 * Note that the callee-saved registers are used for storing variables14 * that are useful before the MMU is enabled. The allocations are described15 * in the entry routines.16*/17 __HEAD1819/*20 * DO NOT MODIFY. Image header expected by Linux boot-loaders.21*/22 b stext // 跳转到内核初始化中23 .long0// reserved24 .quad TEXT_OFFSET // Image load offset from start of RAM25 .quad 0// reserved26 .quad 0// reserved27 .quad 0// reserved28 .quad 0// reserved29 .quad 0// reserved30 .byte0x41// Magic number, "ARM\x64"31 .byte0x5232 .byte0x4d33 .byte0x6434 .word 0// reserved3536 ENTRY(stext)37 mov x21, x0 // x21=FDT,FDT是bootloader传过来的,是DTS的基地址38 bl __calc_phys_offset // 计算物理地址和物理地址和线性地址偏移x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET39 bl el2_setup // 从el2模式退回到el1模式40 mrs x22, midr_el1 // 获得cpuid x22=cpuid41 mov x0, x2242 bl lookup_processor_type // 搜索处理器类型,在arch/arm64/kernel/cputable.c中定义43 mov x23, x0 // x23=current cpu_table44 cbz x23, __error_p // invalid processor (x23=0)?45 bl __vet_fdt // 检测FDT是否是8字节对齐,位于物理地址的前512MB之内46 bl __create_page_tables // 创建内核页表,x25=TTBR0, x26=TTBR147/*48 * The following calls CPU specific code in a position independent49 * manner. See arch/arm64/mm/proc.S for details. x23 = base of50 * cpu_info structure selected by lookup_processor_type above.51 * On return, the CPU will be ready for the MMU to be turned on and52 * the TCR will have been set.53*/54 ldr x27, __switch_data // 需要注意这⾥,处理器初始化完成后跳转到__switch_data55// 这时候MMU已经打开56 adr lr, __enable_mmu // 初始化完成以后ret的时候返回到__enable_mmu所在的地址57 ldr x12, [x23, #CPU_INFO_SETUP]58 add x12, x12, x28 // cpu_info的地址转换成物理地址59 br x12 // 初始化处理器60 ENDPROC(stext)。

arm汇编语言例子

arm汇编语言例子

arm汇编语言例子ARM汇编语言是一种低级语言,用于编写底层程序和嵌入式系统。

它是一种基于寄存器的体系结构,广泛应用于移动设备、嵌入式系统和嵌入式控制器等领域。

下面是十个符合要求的ARM汇编语言的例子。

1. 加法运算:```ADD R0, R1, R2 ; 将寄存器R1和R2的值相加,结果存放在R0中```2. 减法运算:```SUB R0, R1, R2 ; 将寄存器R2的值从R1中减去,结果存放在R0中```3. 乘法运算:```MUL R0, R1, R2 ; 将寄存器R1和R2的值相乘,结果存放在R0中```4. 除法运算:```SDIV R0, R1, R2 ; 将寄存器R1的值除以R2,结果存放在R0中```5. 位移运算:```LSL R0, R1, #3 ; 将寄存器R1的值左移3位,结果存放在R0中```6. 逻辑运算:```AND R0, R1, R2 ; 将寄存器R1和R2的值进行与运算,结果存放在R0中```7. 条件分支:```CMP R0, #10 ; 将寄存器R0的值与10进行比较BNE label ; 如果不相等,则跳转到label处执行```8. 循环结构:```MOV R0, #0 ; 将寄存器R0的值设为0LOOP: ADD R0, R0, #1 ; 将寄存器R0的值加1CMP R0, #10 ; 将寄存器R0的值与10进行比较BLT LOOP ; 如果小于10,则跳转到LOOP处继续执行```9. 函数调用:```PUSH {R0, R1, R2} ; 将寄存器R0、R1和R2的值压入栈中BL function ; 调用名为function的函数POP {R0, R1, R2} ; 将栈中的值弹出到寄存器R0、R1和R2中```10. 中断处理:```LDR R0, =ISR ; 将中断服务程序的地址加载到寄存器R0中LDR R1, =0x1234 ; 将待处理的中断号加载到寄存器R1中STR R0, [R1] ; 将中断服务程序的地址存储到中断向量表中```这些例子涵盖了ARM汇编语言的基本操作,包括算术运算、位移运算、逻辑运算、条件分支、循环结构、函数调用和中断处理等。

ARM汇编指令集详解

ARM汇编指令集详解

ARM汇编指令集一、跳转指令跳转指令用于实现程序流程的跳转,在ARM程序中有两种方法可以实现程序流程的跳转:Ⅰ.使用专门的跳转指令。

Ⅱ.直接向程序计数器PC写入跳转地址值。

通过向程序计数器PC写入跳转地址值,可以实现在4GB的地址空间中的任意跳转,在跳转之前结合使用MOV LR,PC等类似指令,可以保存将来的返回地址值,从而实现在4GB连续的线性地址空间的子程序调用。

ARM指令集中的跳转指令可以完成从当前指令向前或向后的32MB的地址空间的跳转,包括以下4条指令:1、B指令B指令的格式为:B{条件} 目标地址B指令是最简单的跳转指令。

一旦遇到一个B 指令,ARM 处理器将立即跳转到给定的目标地址,从那里继续执行。

注意存储在跳转指令中的实际值是相对当前PC值的一个偏移量,而不是一个绝对地址,它的值由汇编器来计算(参考寻址方式中的相对寻址)。

它是24 位有符号数,左移两位后有符号扩展为32 位,表示的有效偏移为26 位(前后32MB的地址空间)。

以下指令:B Label ;程序无条件跳转到标号Label处执行CMP R1,#0 ;当CPSR寄存器中的Z条件码置位时,程序跳转到标号Label 处执行BEQ Label2、BL指令BL指令的格式为:BL{条件} 目标地址BL 是另一个跳转指令,但跳转之前,会在寄存器R14中保存PC的当前内容,因此,可以通过将R14 的内容重新加载到PC中,来返回到跳转指令之后的那个指令处执行。

该指令是实现子程序调用的一个基本但常用的手段。

以下指令:BL Label ;当程序无条件跳转到标号Label处执行时,同时将当前的PC值保存到R14中3、BLX指令BLX指令的格式为:BLX 目标地址BLX指令从ARM指令集跳转到指令中所指定的目标地址,并将处理器的工作状态有ARM 状态切换到Thumb状态,该指令同时将PC的当前内容保存到寄存器R14中。

因此,当子程序使用Thumb指令集,而调用者使用ARM指令集时,可以通过BLX指令实现子程序的调用和处理器工作状态的切换。

linux arm的编译命令

linux arm的编译命令

linux arm的编译命令摘要:1.Linux ARM 编译命令概述2.Linux ARM 编译器的安装3.Linux ARM 编译命令的使用4.编译命令的实例正文:1.Linux ARM 编译命令概述Linux ARM 编译命令是指在Linux 系统下,针对ARM 架构处理器进行编译的命令。

ARM 架构处理器广泛应用于嵌入式系统、移动设备等,因此在Linux 系统中进行ARM 编译是非常常见的任务。

2.Linux ARM 编译器的安装要在Linux 系统中使用ARM 编译器,首先需要安装相应的编译器。

一般情况下,我们可以通过以下命令来安装:```bashsudo apt-get install gcc-arm-linux-gnueabi```其中,`gcc`是GNU 编译器集合,`arm-linux-gnueabi`表示针对ARM 架构的Linux 系统。

安装完成后,您可以在终端中输入`gcc -v`来查看编译器的版本信息。

3.Linux ARM 编译命令的使用安装好编译器后,您可以开始编写源代码文件,例如`test.c`。

编写完成后,通过以下命令编译:```bashgcc -o test test.c```其中,`-o`选项用于指定编译后输出文件的名称,`test`是源代码文件名,`test.c`是源代码文件的扩展名。

编译成功后,您可以在当前目录下找到名为`test`的可执行文件。

4.编译命令的实例下面是一个具体的实例,展示如何使用Linux ARM 编译器编译一个简单的C 语言程序。

假设您有一个名为`hello.c`的源代码文件,内容如下:```c#include <stdio.h>int main() {printf("Hello, ARM!");return 0;}```要编译这个程序,您可以使用以下命令:```bashgcc -o hello hello.c```编译成功后,您将在当前目录下找到一个名为`hello`的可执行文件。

arm 汇编 位操作

arm 汇编 位操作

ARM 汇编语言提供了丰富的位操作指令,这些指令可以在位级别上操作数据,从而实现各种位运算和位操作功能。

以下是一些常用的ARM 汇编位操作指令:1. AND 指令:该指令将两个操作数的相应位进行逻辑与操作,并将结果存储在目标寄存器中。

例如:```AND r0, r1, r2 ; 将r1 和r2 的相应位进行逻辑与操作,并将结果存储在r0 中```2. EOR 指令:该指令将两个操作数的相应位进行逻辑异或操作,并将结果存储在目标寄存器中。

例如:```EOR r0, r1, r2 ; 将r1 和r2 的相应位进行逻辑异或操作,并将结果存储在r0 中```3. ORR 指令:该指令将两个操作数的相应位进行逻辑或操作,并将结果存储在目标寄存器中。

例如:```ORR r0, r1, r2 ; 将r1 和r2 的相应位进行逻辑或操作,并将结果存储在r0 中```4. BIC 指令:该指令将目标寄存器的相应位清零,其他位保持不变。

例如:```BIC r0, r1, r2 ; 将r1 的相应位清零,其他位保持不变,并将结果存储在r0 中```5. MVN 指令:该指令将目标寄存器的相应位取反,其他位保持不变。

例如:```MVN r0, r1 ; 将r1 的相应位取反,其他位保持不变,并将结果存储在r0 中```这些是ARM 汇编语言中常用的位操作指令,它们可以帮助您在汇编语言中进行高效的位运算和位操作。

请注意,这些指令的用法可能会因ARM 架构版本和具体的处理器型号而有所不同。

因此,在实际应用中,建议查阅相关ARM 架构文档以了解更详细的信息。

arm汇编指令 组成结构

arm汇编指令 组成结构

arm汇编指令组成结构ARM汇编指令是一种低级程序设计语言,用于编写针对ARM架构的机器码指令。

ARM汇编指令由一系列操作码(opcode)和操作数(operand)组成,用于执行特定的计算和操作。

ARM汇编指令的基本组成结构如下:1. 操作码(Opcode):操作码是指令的核心部分,用于指定要执行的操作类型。

ARM指令集包含多种操作码,如数据处理、分支、加载/存储等。

2. 操作数(Operand):操作数是指令的操作对象,包括寄存器、立即数和内存地址等。

操作数用于指定要操作的数据和存储位置。

3. 寻址模式(Addressing Mode):寻址模式用于确定操作数的存储位置。

ARM架构支持多种寻址模式,如寄存器寻址、立即数寻址、基址寻址、间接寻址等。

4. 条件码(Condition Code):条件码用于指定指令的执行条件。

ARM指令集中的大多数指令都可以根据条件码来选择是否执行。

5. 注释(Comment):注释是对指令的解释和说明,用于提高代码的可读性和可维护性。

注释在汇编代码中以分号(;)开头,可以在指令后面或单独一行进行编写。

下面是一个示例,展示了一条ARM汇编指令的组成结构:```ADD r0, r1, r2 ; 将寄存器r1和r2中的值相加,结果存入r0寄存器```- 操作码:ADD,表示进行加法运算。

- 操作数:r0、r1和r2,分别表示寄存器的编号。

- 寻址模式:无,因为操作数直接使用寄存器。

- 条件码:无,表示无条件执行。

- 注释:"; 将寄存器r1和r2中的值相加,结果存入r0寄存器",用于解释指令的作用。

需要注意的是,ARM汇编指令的具体语法和操作码取决于所使用的ARM架构版本和指令集。

不同的ARM架构版本可能会有不同的指令集和指令格式。

因此,在编写ARM汇编代码时,需要参考相应的ARM架构手册或文档以获取准确的指令信息。

arm常用汇编指令

arm常用汇编指令

arm常用汇编指令ARM的汇编指令是ARM处理器在运行时所执行的基本操作。

汇编指令是一种低级编程语言,它主要是为了直接操作硬件而设计的。

在ARM 汇编指令中,每个指令都是由一个操作码和一些操作数组成的。

操作码就是指令的类型,而操作数则是指令要操作的数据。

下面是一些常用的ARM汇编指令:1. mov指令mov指令是ARM汇编指令中最常用的指令之一。

它用来将一个数据从一个位置复制到另一个位置。

例如,下面的代码将寄存器r1中的值复制到寄存器r2中:mov r2, r12. add指令add指令用来将两个数相加并将结果存放在一个寄存器中。

例如,下面的代码将r1和r2中的值相加并将结果存放在r3中:add r3, r1, r23. sub指令sub指令用来将一个数从另一个数中减去并将结果存放在一个寄存器中。

例如,下面的代码将r2中的值从r1中减去并将结果存放在r3中:sub r3, r1, r24. cmp指令cmp指令用来比较两个数的大小。

它会将两个数相减,并将结果存放在一个特殊的寄存器中。

如果相减结果为0,表示两个数相等;如果结果为正数,表示第一个数大于第二个数;如果结果为负数,表示第一个数小于第二个数。

例如,下面的代码比较r1和r2的大小:cmp r1, r25. beq指令beq指令用来进行条件分支。

如果cmp指令的结果为0,则跳转到指定的地址。

例如,下面的代码如果r1等于r2,就跳到标号my_label处执行:beq my_label6. bne指令bne指令用来进行条件分支。

如果cmp指令的结果不为0,则跳转到指定的地址。

例如,下面的代码如果r1不等于r2,就跳到标号my_label处执行:bne my_label7. ldr指令ldr指令用来从内存中读取一个值并存放到寄存器中。

例如,下面的代码从内存地址0x100处读取一个值并存放到寄存器r1中:ldr r1, [0x100]8. str指令str指令用来将一个值存储到内存中。

arm 编译汇编文件

arm 编译汇编文件

arm 编译汇编文件在ARM 架构上编译汇编文件的过程涉及使用交叉编译器。

以下是一个简单的步骤,以便在Linux 环境中使用ARM 交叉编译器编译ARM 汇编文件:1. 安装交叉编译工具链:在Ubuntu 等Linux 发行版上,你可以使用`apt` 包管理器安装ARM 交叉编译工具链。

例如,对于ARM 64 位架构:```bashsudo apt-get install gcc-aarch64-linux-gnu```对于ARM 32 位架构:```bashsudo apt-get install gcc-arm-linux-gnueabihf```2. 创建汇编文件:创建一个简单的ARM 汇编文件,例如`example.s`:```assembly.section .datamsg: .asciz "Hello, ARM!\n".section .text.global _start_start:@ write syscallmov x8, #64 // syscall number for writeldr x1, =msg // pointer to the messageldr x2, =13 // message lengthmov x0, #1 // file descriptor for stdoutsvc #0@ exit syscallmov x8, #93 // syscall number for exitmov x0, #0 // exit statussvc #0```3. 使用交叉编译器进行编译:对汇编文件使用交叉编译器进行编译:```bashaarch64-linux-gnu-as -o example.o example.s```或者对于ARM 32 位:```basharm-linux-gnueabihf-as -o example.o example.s```4. 链接为可执行文件:使用链接器将目标文件链接为可执行文件:```bashaarch64-linux-gnu-ld -o example example.o```或者对于ARM 32 位:```basharm-linux-gnueabihf-ld -o example example.o```在链接时,你可能需要链接C 库,具体的命令取决于你的需求。

关于arm汇编中的align

关于arm汇编中的align

关于arm汇编中的align经常会看到arm-linux汇编中有如下的指令:.align n它的含义就是使得下面的代码按一定规则对齐,.align n 指令的对齐值有两种方案,n 或2^n ,各种平台最初的汇编器一般都不是gas,采取方案1或2的都很多,gas的目标是取代原来的汇编器,必然要保持和原来汇编器的兼容,因此在gas中如何解释 .align指令会显得有些混乱,原因在于保持兼容。

arm-linu是按照2^n的方案对齐的,需要说明的是这个对齐和ld-script里的对齐不同,不是一会事。

下面的英文就不同平台的对齐进行了说明:版本2.11.92.0.12的gas的info(Mandrake 8.2上的)这样说:The way the required alignment is specified varies from system to system. For the a29k, hppa, m68k, m88k, w65, sparc, and Hitachi SH, and i386 using ELF format, the first expression is the alignment request in bytes. For example `.align 8' advances the location counter until it is a multiple of 8. If the location counter is already a multiple of 8, no change is needed.For other systems, including the i386 using a.out format, and the arm and strongarm, it is the number of low-order zero bits the location counter must have after advancement. For example `.align 3' advances the location counter until it a multiple of 8. If the location counter is already a multiple of 8, no change is needed.从这段文字来看,ARM的.align 5就是2的5次方对齐,也就是4字节对齐,通过反汇编也可以看出对齐方式:.align 5stmfd sp!, {r0 - r3, lr}mov r0, ipldmfd sp!, {r0 - r3, pc}^.align 5stmfd sp!, {r0 - r3, lr}mov r0, ipmov ip, r0ldmfd sp!, {r0 - r3, pc}^反汇编:00000000 <.text>:0: e92d400f stmdb sp!, {r0, r1, r2, r3, lr}4: e1a0000c mov r0, ip8: e8fd800f ldmia sp!, {r0, r1, r2, r3, pc}^...20: e92d400f stmdb sp!, {r0, r1, r2, r3, lr}24: e1a0000c mov r0, ip28: e1a0c000 mov ip, r02c: e8fd800f ldmia sp!, {r0, r1, r2, r3, pc}^30: e1a00000 nop (mov r0,r0)34: e1a00000 nop (mov r0,r0)38: e1a00000 nop (mov r0,r0)3c: e1a00000 nop (mov r0,r0)一些忠告:In the future, everytime when you build an elf file, you need meantime created your map file. And then you will avoid mistakes like th is align.Also, please also pick up some linker script knowlege part. For embedded system, we frequently play the linker script to tune an image, for example, align some special section and so on for protection or/and cache purpose. wish helpful。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第一部分 Linux下ARM汇编语法尽管在Linux下使用C或C++编写程序很方便,但汇编源程序用于系统最基本的初始化,如初始化堆栈指针、设置页表、操作ARM的协处理器等。

初始化完成后就可以跳转到C代码执行。

需要注意的是,GNU的汇编器遵循AT&T的汇编语法,可以从GNU的站点()上下载有关规范。

一. Linux汇编行结构任何汇编行都是如下结构:[:] [} @ comment[:] [} @ 注释Linux ARM 汇编中,任何以冒号结尾的标识符都被认为是一个标号,而不一定非要在一行的开始。

【例1】定义一个"add"的函数,返回两个参数的和。

.section .text, “x”.global add @ give the symbol add external linkageadd:ADD r0, r0, r1 @ add input argumentsMOV pc, lr @ return from subroutine@ end of program二. Linux 汇编程序中的标号标号只能由a~z,A~Z,0~9,“.”,_等字符组成。

当标号为0~9的数字时为局部标号,局部标号可以重复出现,使用方法如下:标号f: 在引用的地方向前的标号标号b: 在引用的地方向后的标号【例2】使用局部符号的例子,一段循环程序1:subs r0,r0,#1 @每次循环使r0=r0-1bne 1f @跳转到1标号去执行局部标号代表它所在的地址,因此也可以当作变量或者函数来使用。

三. Linux汇编程序中的分段(1).section伪操作用户可以通过.section伪操作来自定义一个段,格式如下:.section section_name [,"flags"[, %type[,flag_specific_arguments]]]每一个段以段名为开始, 以下一个段名或者文件结尾为结束。

这些段都有缺省的标志(flags),连接器可以识别这些标志。

(与armasm中的AREA相同)。

下面是ELF格式允许的段标志<标志> 含义a 允许段w 可写段x 执行段【例3】定义段.section .mysection @自定义数据段,段名为“.mysection”.align 2strtemp:.ascii "Temp string \n\0"(2)汇编系统预定义的段名.text @代码段.data @初始化数据段.bss @未初始化数据段.sdata @.sbss @需要注意的是,源程序中.bss段应该在.text之前。

四. 定义入口点汇编程序的缺省入口是 start标号,用户也可以在连接脚本文件中用ENTRY标志指明其它入口点。

【例4】定义入口点.section.data< initialized data here>.section .bss< uninitialized data here>.section .text.globl _start_start:<instruction code goes here>五. Linux汇编程序中的宏定义格式如下:.macro 宏名参数名列表 @伪指令.macro定义一个宏宏体.endm @.endm表示宏结束如果宏使用参数,那么在宏体中使用该参数时添加前缀“\”。

宏定义时的参数还可以使用默认值。

可以使用.exitm伪指令来退出宏。

【例5】宏定义.macro SHIFTLEFT a, b.if \b < 0MOV \a, \a, ASR #-\b.exitm.endifMOV \a, \a, LSL #\b.endm六. Linux汇编程序中的常数(1)十进制数以非0数字开头,如:123和9876;(2)二进制数以0b开头,其中字母也可以为大写;(3)八进制数以0开始,如:0456,0123;(4)十六进制数以0x开头,如:0xabcd,0X123f;(5)字符串常量需要用引号括起来,中间也可以使用转义字符,如: “You are welcome!\n”;(6)当前地址以“.”表示,在汇编程序中可以使用这个符号代表当前指令的地址;(7)表达式:在汇编程序中的表达式可以使用常数或者数值, “-”表示取负数, “~”表示取补,“<>”表示不相等,其他的符号如:+、-、*、 /、%、<、<<、>、>>、|、&、^、!、==、>=、<=、&&、|| 跟C语言中的用法相似。

七. Linux下ARM汇编的常用伪操作在前面已经提到过了一些为操作,还有下面一些为操作:数据定义伪操作: .byte,.short,.long,.quad,.float,.string/.asciz/.ascii,重复定义伪操作.rept,赋值语句.equ/.set ;函数的定义;对齐方式伪操作 .align;源文件结束伪操作.end;.include伪操作;if伪操作;.global/ .globl 伪操作;.type伪操作;列表控制语句;区别于gas汇编的通用伪操作,下面是ARM特有的伪操作:.reg ,.unreq ,.code ,.thumb ,.thumb_func ,.thumb_set, .lt org ,.pool1. 数据定义伪操作(1) .byte:单字节定义,如:.byte 1,2,0b01,0x34,072,'s' ;(2) .short:定义双字节数据,如:.short 0x1234,60000 ;(3) .long:定义4字节数据,如:.long 0x12345678,23876565(4) .quad:定义8字节,如:.quad 0x1234567890abcd(5) .float:定义浮点数,如:.float 0f-314159265358979323846264338327\95028841971.693993751E-40 @ - pi(6) .string/.asciz/.ascii:定义多个字符串,如:.string "abcd", "efgh", "hello!".asciz "qwer", "sun", "world!".ascii "welcome\0"需要注意的是:.ascii伪操作定义的字符串需要自行添加结尾字符'\0'。

(7) .rept:重复定义伪操作, 格式如下:.rept 重复次数数据定义.endr @结束重复定义例如:.rept 3.byte 0x23.endr(8) .equ/.set: 赋值语句, 格式如下:.equ(.set) 变量名,表达式例如:.equ abc 3 @让abc=32.函数的定义伪操作(1)函数的定义,格式如下:函数名:函数体返回语句一般的,函数如果需要在其他文件中调用, 需要用到.global伪操作将函数声明为全局函数。

为了不至于在其他程序在调用某个C函数时发生混乱,对寄存器的使用我们需要遵循APCS准则。

函数编译器将处理为函数代码为一段.global 的汇编码。

(2)函数的编写应当遵循如下规则:a1-a4寄存器(参数、结果或暂存寄存器,r0到r3 的同义字)以及浮点寄存器f0-f3(如果存在浮点协处理器)在函数中是不必保存的;如果函数返回一个不大于一个字大小的值,则在函数结束时应该把这个值送到 r0 中;如果函数返回一个浮点数,则在函数结束时把它放入浮点寄存器f0中;如果函数的过程改动了sp(堆栈指针,r13)、fp(框架指针,r11)、sl (堆栈限制,r10)、lr(连接寄存器,r14)、v1-v8(变量寄存器,r4 到r11)和 f4-f7,那么函数结束时这些寄存器应当被恢复为包含在进入函数时它所持有的值。

3. .align .end .include .incbin伪操作(1).align:用来指定数据的对齐方式,格式如下:.align [absexpr1, absexpr2]以某种对齐方式,在未使用的存储区域填充值. 第一个值表示对齐方式,4, 8,16或 32. 第二个表达式值表示填充的值。

(2).end:表明源文件的结束。

(3).include:可以将指定的文件在使用.include 的地方展开,一般是头文件,例如:.include “myarmasm.h”(4).incbin伪操作可以将原封不动的一个二进制文件编译到当前文件中,使用方法如下:.incbin "file"[,skip[,count]]skip表明是从文件开始跳过skip个字节开始读取文件,count是读取的字数.4. .if伪操作根据一个表达式的值来决定是否要编译下面的代码, 用.endif伪操作来表示条件判断的结束, 中间可以使用.else来决定.if的条件不满足的情况下应该编译哪一部分代码。

.if有多个变种:.ifdef symbol @判断symbol是否定义.ifc string1,string2 @字符串string1和string2是否相等,字符串可以用单引号括起来.ifeq expression @判断expression的值是否为0.ifeqs string1,string2 @判断string1和string2是否相等,字符串必须用双引号括起来.ifge expression @判断expression的值是否大于等于0 .ifgt absolute expression @判断expression的值是否大于0.ifle expression @判断expression的值是否小于等于0 .iflt absolute expression @判断expression的值是否小于0.ifnc string1,string2 @判断string1和string2是否不相等, 其用法跟.ifc恰好相反。

.ifndef symbol, .ifnotdef symbol @判断是否没有定义symbol, 跟.ifdef恰好相反.ifne expression @如果expression的值不是0, 那么编译器将编译下面的代码.ifnes string1,string2 @如果字符串string1和string2不相等, 那么编译器将编译下面的代码.5. .global .type .title .list(1).global/ .globl :用来定义一个全局的符号,格式如下:.global symbol 或者 .globl symbol(2).type:用来指定一个符号的类型是函数类型或者是对象类型, 对象类型一般是数据, 格式如下:.type 符号, 类型描述【例6】.globl a.data.align 4.type a, @object.size a, 4a:.long 10【例7】.section .text.type asmfunc, @function.globl asmfuncasmfunc:mov pc, lr(3)列表控制语句:.title:用来指定汇编列表的标题,例如:.title “my program”.list:用来输出列表文件.6. ARM特有的伪操作(1) .reg: 用来给寄存器赋予别名,格式如下:别名 .req 寄存器名(2) .unreq: 用来取消一个寄存器的别名,格式如下:.unreq 寄存器别名注意被取消的别名必须事先定义过,否则编译器就会报错,这个伪操作也可以用来取消系统预制的别名, 例如r0, 但如果没有必要的话不推荐那样做。

相关文档
最新文档