LinuxARM汇编.
arm-linux-ld命令

arm-linux-ld命令我们对每个c或者汇编文件进行单独编译,但是不去连接,生成很多.o 的文件,这些.o文件首先是分散的,我们首先要考虑的如何组合起来;其次,这些.o文件存在相互调用的关系;再者,我们最后生成的bin文件是要在硬件中运行的,每一部分放在什么地址都要有仔细的说明。
我觉得在写makefile的时候,最为重要的就是ld的理解,下面说说我的经验:首先,要确定我们的程序用没有用到标准的c库,或者一些系统的库文件,这些一般是在操作系统之上开发要注意的问题,这里并不多说,熟悉在Linux编程的人,基本上都会用ld命令;这里,我们从头开始,直接进行汇编语言的连接。
我们写一个汇编程序,控制GPIO,从而控制外接的LED,代码如下;.text.global _start_start:LDR R0,=0x56000010 @GPBCON寄存器MOV R1,# 0x00000400str R1,[R0]LDR R0,=0x56000014MOV R1,#0x00000000STR R1,[R0]MAIN_LOOP:B MAIN_LOOP代码很简单,就是一个对io口进行设置然后写数据。
我们看它是如何编译的,注意我们这里使用的不是ar m-linux-gcc而是arm-elf-gcc,二者之间没有什么比较大的区别,arm-linux-gcc可能包含更多的库文件,在命令行的编译上面是没有区别。
我们来看是如何编译的:arm-elf-gcc -g -c -o led_On.o led_On.s 首先纯编译不连接arm-elf-ld -Ttext 0x00000000 -g led_On.o -o led_on_elf用Ttext指明我们程序存储的地方,这里生成的是elf文件,还不是我们真正的bin,但是可以借助一些工具可以进行调试。
然后:arm-elf-objcopy -O binary -S led_on_elf led_on.bin生成bin文件。
为什么要反汇编?反汇编文件的生成和解读

为什么要反汇编?反汇编文件的生成和解读为什么要反(汇编)反汇编顾名思义就是汇编的逆过程,将二进制文件反汇编成汇编代码。
(arm)-(linux)-objdump是交叉编译工具链里的一个工具,专门用来反汇编的,将二进制代码反汇编成汇编代码来查看。
为什么要反汇编1.逆向破解。
将可执行程序反汇编得到汇编代码,再根据汇编代码推理出整个程序的逻辑。
这个不是一般人能做的,能看懂大量汇编语言写的程序都很困难了,更别说反推别人的代码逻辑。
2.调试程序时可以帮助我们理解并(检测)生成的可执行程序是否正常,尤其是在理解链接脚本和链接地址等概念时。
3.(C语言)的源代码编译链接生成的可执行文件再反汇编,可以帮助我们理解C语言和汇编语言的对应关系,有助于深入理解C 语言。
反汇编文件的生成和解读反汇编文件的生成:上面是一个简单的Makefile,功能是把源文件.S和.c先编译成.o 文件,再把.o文件链接成.elf的可执行文件。
arm-linux-objdump -D (led).elf > led_elf.dis是将led.elf反汇编成ed_elf.dis。
源文件:star.s是一个汇编文件star.s是一个学习S5PV210开发板时点亮LED的汇编程序,由开始、点亮、延时和死循环组成,在这里并不关注具体实现的功能,重点是和反汇编生成的文件进行对照。
得到的反汇编文件:led_elf.dis解析:1.第一行:led.elf: file f(or)mat elf32-littlearm。
表明此汇编程序是由led.elf生成,程序是32的小端模式。
2.00000000 :前面的00000000是标号的地址,是标号,对应start.s的_start标号。
其实标号就相当于C语言中的函数名,在C语言中也可以用函数名代表函数的首地址,在这里可以得到印证。
反汇编的标号就是由汇编文件得来的,这样可以方便我们找到反汇编文件和汇编文件对应的部分。
arm-linux-objdump反汇编使用指南

以音频和传感器算法为核心的智能可穿戴产品解决方案提供商提供可穿戴智能软硬件解决方案的设计开发和咨询服务
arm-linux-objdump反 汇 编 使 用 指 南
一. arm-linux-objdump常用来显示二进制文件信息,常用来查看反汇编代码 二. 常用选项: 1.-b bfdname 指定目标码格式 2.—disassemble或者-d 反汇编可执行段 3.—dissassemble-all或者-D 反汇编所有段 4.-EB,-EL指定字节序 5.—file-headers或者-f 显示文件的整体头部摘要信息 6.—section-headers,--headers或者-h 显示目标文件中各个段的头部摘要信息 7.—info 或者-I 显示支持的目标文件格式和CPU架构 8.—section=name或者-j name显示指定section 的信息 9.—architecture=machine或者-m machine 指定反汇编目标文件时使用的架构
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-linux-gcc 常用参数讲解 gcc编译器使用方法

arm-linux-gcc常用参数讲解gcc编译器使用方法我们需要编译出运行在ARM平台上的代码,所使用的交叉编译器为arm-linux-gcc。
下面将arm-linux-gcc编译工具的一些常用命令参数介绍给大家。
在此之前首先介绍下编译器的工作过程,在使用GCC编译程序时,编译过程分为四个阶段:1. 预处理(Pre-Processing)2. 编译(Compiling)3. 汇编(Assembling)4. 链接(Linking)Linux程序员可以根据自己的需要让GCC在编译的任何阶段结束,以便检查或使用编译器在该阶段的输出信息,或者对最后生成的二进制文件进行控制,以便通过加入不同数量和种类的调试代码来为今后的调试做好准备。
和其它常用的编译器一样,GCC也提供了灵活而强大的代码优化功能,利用它可以生成执行效率更高的代码。
以文件example.c为例说明它的用法0. arm-linux-gcc -o example example.c不加-c、-S、-E参数,编译器将执行预处理、编译、汇编、连接操作直接生成可执行代码。
-o参数用于指定输出的文件,输出文件名为example,如果不指定输出文件,则默认输出a.out1. arm-linux-gcc -c -o example.oexample.c-c参数将对源程序example.c进行预处理、编译、汇编操作,生成example.0文件去掉指定输出选项"-o example.o"自动输出为example.o,所以说在这里-o加不加都可以2.arm-linux-gcc -S -o example.sexample.c-S参数将对源程序example.c进行预处理、编译,生成example.s文件-o选项同上3.arm-linux-gcc -E -o example.iexample.c-E参数将对源程序example.c进行预处理,生成example.i文件(不同版本不一样,有的将预处理后的内容打印到屏幕上)就是将#include,#define等进行文件插入及宏扩展等操作。
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汇编指令转⾃:https:///zb861359/article/details/81027021?utm_source=app1、 IMPORT和EXPORTIMPORT ,定义表⽰这是⼀个外部变量的标号,不是在本程序定义的EXPORT ,表⽰本程序⾥⾯⽤到的变量提供给其他模块调⽤的。
以上两个在汇编和C语⾔混合编程的时候⽤到。
2、AREA语法格式:AREA 段名属性1 ,属性2 ,……AREA伪指令⽤于定义⼀个代码段或数据段。
其中,段名若以数字开头,则该段名需⽤“|”括起来,如:|1_test|。
属性字段表⽰该代码段(或数据段)的相关属性,多个属性⽤逗号分隔。
常⽤的属性如下:— CODE 属性:⽤于定义代码段,默认为READONLY 。
— DATA 属性:⽤于定义数据段,默认为READWRITE 。
— READONLY 属性:指定本段为只读,代码段默认为READONLY 。
— READWRITE 属性:指定本段为可读可写,数据段的默认属性为READWRITE 。
— ALIGN 属性:使⽤⽅式为ALIGN表达式。
在默认时,ELF(可执⾏连接⽂件)的代码段和数据段是按字对齐的,表达式的取值范围为0~31,相应的对齐⽅式为2表达式次⽅。
— COMMON 属性:该属性定义⼀个通⽤的段,不包含任何的⽤户代码和数据。
各源⽂件中同名的COMMON段共享同⼀段存储单元。
⼀个汇编语⾔程序⾄少要包含⼀个段,当程序太长时,也可以将程序分为多个代码段和数据段。
使⽤⽰例:AREA Init ,CODE ,READONLY ; 该伪指令定义了⼀个代码段,段名为Init ,属性为只读。
3、LDR、LDRB、LDRHARM微处理器⽀持加载/存储指令⽤于在寄存器和存储器之间传送数据,加载指令⽤于将存储器中的数据传送到寄存器,存储指令则完成相反的操作。
常⽤的加载存储指令如下:— LDR 字数据加载指令— LDRB 字节数据加载指令— LDRH 半字数据加载指令1) LDR指令有两种⽤法:a、ldr加载指令LDR指令的格式为:LDR{条件} ⽬的寄存器,<存储器地址>LDR指令⽤亍从存储器中将⼀个32位的字数据传送到⽬的寄存器中。
arm汇编语言
arm汇编语言ARM汇编语言是一种高级汇编语言,用于处理低级语言,它可以在小型处理器和特定硬件上实现高性能和低功耗。
ARM模式是一种抽象的指令集架构,可在大多数中央处理器上实现,主要用于智能手机、电视机顶盒的视频解码、无线网络芯片、嵌入式计算机系统等应用程序。
ARM汇编语言是ARM处理器的指令集,它是为ARM处理器设计的低级语言。
ARM处理器是一种嵌入式处理器,它拥有最低功耗、最高性能的特点。
使用ARM处理器,可以在各种嵌入式系统中实现处理任务。
ARM汇编语言可以描述ARM处理器的指令,并使得程序设计更加简单、高效。
ARM汇编语言由ARM汇编程序设计语言(ALP)组成,它是一种低级语言,但具有更高的抽象能力。
该语言的基本用法包括控制语句、数据类型、数据结构和程序流程控制。
它使用标签来描述跳转,支持嵌套循环,允许程序调用和子过程定义。
ARM汇编语言支持大量实用功能,如查询、更新、移位等,使程序设计更加简单、方便。
ARM汇编语言的发展,为嵌入式系统的应用奠定了坚实的基础。
它不仅大大提高了处理器性能,还改善了程序开发效率。
它使得软件程序员可以更加熟悉处理器指令集,从而更好地掌握程序开发技术。
ARM汇编语言可以用来编写操作系统、驱动程序、硬件驱动程序等程序,从而实现嵌入式系统功能及应用。
ARM汇编语言的发展将给智能手机、嵌入式系统和微机技术带来深远的影响。
通过使用ARM汇编语言,工程师可以在不同的应用程序中实现最大的效率,并获得最佳性能。
ARM汇编语言是专业工程师的必备工具,有助于构建先进的嵌入式系统,实现出色的应用程序性能。
因此,ARM汇编语言在嵌入式系统开发中发挥了非常重要的作用,它不仅可以降低功耗,提高处理器性能,而且可以加快程序开发效率,实现更简单高效的程序设计。
ARM汇编语言的重要性不言而喻,它让嵌入式系统发展迈出了坚实的步伐。
Linux汇编伪指令
(1) .byte:单字节定义,如:.byte 1,2,0b01,0x34,072,'s' ;
(2) .short:定义双字节数据,如:.short 0x1234,60000 ;
(3) .long:定义4字节数据,如:.long 0x12345678,23876565
四. 定义入口点
汇编程序的缺省入口是 start标号,用户也可以在连接脚本文件中用ENTRY标志指明其它入口点。
【例4】定义入口点
.section.data
< initialized data here>
.section .bss
< uninitialized data here>
保存的;
? 如果函数返回一个不大于一个字大小的值,则在函数结束时应该把这个值送到 r0 中;
? 如果函数返回一个浮点数,则在函数结束时把它放入浮点寄存器f0中;
?如果函数的过程改动了sp(堆栈指针,r13)、fp(框架指针,r11)、sl(堆栈限制,r10)、lr(连接寄存器,r14)、v1-v8(变量寄存器,r4 到 r11)和 f4-f7,那么函数结束时这些寄存器应当被恢复为包含在进入函数时它所持有的值。
skip表明是从文件开始跳过skip个字节开始读取文件,count是读取的字数.
4. .if伪操作
根据一个表达式的值来决定是否要编译下面的代码, 用.endif伪操作来表示条件判断的结束, 中间可以使用.else来决定.if的条件不满足的情况下应该编译哪一部分代码。
.if有多个变种:
.ifdef symbol @判断symbol是否定义
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函数。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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 arewelcome!\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, .ltorg ,.pool 1. 数据定义伪操作(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, 但如果没有必要的话不推荐那样做。