GNUARM汇编指令.
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标准汇编与GNU汇编

ARM标准汇编与GNU汇编前段时间看arm的汇编,发现很多有一个小点,但是借来的书上的语法却没有,问同学也不知道,于是在网上查了一番才发现我书上看到的是arm的标准汇编,而有小点的是GNU汇编,于是将收集到的资料整理后放到这里来。
GNU汇编语言结构,主要包括三个常用的段:data 数据段声明带有初始值的元素bss 数据段声明使用0或者null初始化的元素text 正文段包含的指令, 每个汇编程序都必须包含此段使用.section 指令定义段, 如:.section .data .section .bss .section .text起始点:GNU汇编器使用_start标签表示默认的起始点, 此外如果想要汇编内部的标签能够被外部程序访问,需要使用.globl 指令,如:.globl _start使用通用库函数时可以使用:ld -dynamic-linker /lib/ld-linux.so.21, data段使用.data声明数据段,这个段中声明的任何数据元素都保留在内存中并可以被汇编程序的指令读取。
此外还可以使用.rodata声明只读的数据段, 在声明一个数据元素时, 需要使用标签和命令。
标签:用做引用数据元素所使用的标记,它和c语言的变量很相似,它对于处理器是没有意义的,它只是用做汇编器试图访问内存位置时用做引用指针的一个位置。
指令:指示汇编器为通过标签引用的数据元素保留特定数量的内存,声明命令之后必须给出一个或多个默认值。
声明指令:.ascii 文本字符串.asciz 以空字符结尾的字符串.byte 字节值.double 双精度浮点值.float 单精度浮点值.int 32位整数.long 32位整数, 和int相同.octa 16字节整数.quad 8字节整数.short 16位整数.single 单精度浮点数(和float相同)例子:output:.ascii "hello world."pi:.float 2.14声明可以在一行中定义多个值, 如:ages:.int 20, 10, 30, 40定义静态符号:使用.equ命令把常量值定义为可以在文本段中使用的符号,如:.section .data.equ LINUX_SYS_CALL, 0x80.section .textmovl $LINUX_SYS_CALL, %eax2, bss段和data段不同, 无需声明特定的数据类型, 只需声明为所需目的保留的原始内存部分即可。
GNUARM汇编

GNUARM汇编GNU ARM 汇编GNU:维基百科上说:GNU,一个类UNIX的操作系统,由GNU计划推动,目标在于建立一个完全相容于UNIX的自由软件环境。
这里GNU代表了一种平台,一类开发环境,更是一种汇编程序设计的语法格式。
我们这里可以认为他代表一类组织,有自己的独特的程序设计规范,就是AT&T规范,一般称之为AT&T汇编,提到AT&T汇编,就应该知道这是另一种汇编语法格式,汇编指令是由处理器决定的。
跟语法格式无关。
ARM:代表一类处理器,比如INTEL处理器,ARM处理器。
不同公司设计的CPU核心,一般指令格式也不同。
不同体系结构的CPU,指令集一般也不同,因为体系结构对应指令集。
汇编:指的是汇编语言。
在汇编语言中,用助记符(Memoni)代替操作码,用地址符号(Symbol)或标号(Label)代替地址码。
这样用符号代替机器语言的二进制码,就把机器语言变成了汇编语言。
于是汇编语言亦称为符号语言。
用汇编语言编写的程序,机器不能直接识别,要由一种程序将汇编语言翻译成机器语言,这种起翻译作用的程序叫汇编程序,汇编程序是系统软件中语言处理的系统软件。
GNU有自己的一套独立的编译环境,所遵从的C语言、汇编语言等程序设计的语法格式也是不同的。
如,PC机上,对于x86系列处理器,有AT&T汇编和INTEL汇编两种语法格式。
这两种格式的汇编,有指令大小写、操作数赋值方向、前缀、后缀、寻址方式等区别。
因为是一类处理器,X86系列,指令是一样的。
下面的比较转自别人总结。
AT&T与INTEL的汇编语言语法的区别2007-06-25 9:381、大小写INTEL格式的指令使用大写字母,而AT&T格式的使用小写字母。
例:INTEL AT&TMOV EAX,EBX movl %ebx,%eax2、操作数赋值方向在INTEL语法中,第一个表示目的操作数,第二个表示源操作数,赋值方向从右向左。
GNUARM汇编指令(注意是GNU,区别与armasm)

thumb
(7) .thumb_s, .thumb_func
(8) .ltorg
(literal pool) ,
(9) .pool .ltorg
(10).space <number_of_bytes>{,<fill_byte>}
number_of_bytes
fill_byte
.rept
.endr @ :
.rept 3 .byte 0x23 .endr 8 .equ/.set: , : .equ(.set) ,
: .equ abc 3 @ abc=3
2. 1 ,:
:
, .global
C
2
:
a1-a4
r0 r3
f0-f3(
)
r0
APCS
.global
f0 sp r13 fp r11 sl r10 lr
. Linux ARM
.byte .short .long .quad .float .string/.asciz/.ascii '\0')
.rept\.endr( ) .equ/.set (ascii
.align .end .include .if .global/ .globl .type
gas , ARM .reg .unreq .code .thumb .thumb_func .thumb_set .ltorg .pool
4.GNU /u1/37614/showart_390095.html
5.GNU
/blog-htm-do-showone-uid-34335-itemid-81387-type-
blog.html
6. GNU ARM /liren0@126/blog/static/32897598200821211144696/
GNU ARM 汇编快速入门

GNU ARM 汇编快速入门任何汇编行都是如下结构:[<label>:] [<instruction or directive>} @ comment[<标签>:] [<指令>} @ 注释GNU ARM 汇编中,任何以冒号结尾的都被认为是一个标签,而不一定非要在一行的开始。
下面是一个简单的例子,这段汇编程序定义了一个"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 programGNU ARM汇编伪指令下面列出了一些GNU ARM汇编伪指令,并给出了相应说明。
.ascii “<string>” 在汇编中定义字符串并为之分配存储空间(与armasm中的DCB功能类似)。
.asciz “<string>” 和.ascii类似, 但不分配存储空间。
.balign <power_of_2> {,<fill_value> {,<max_padding>} }以某种排列方式在内存中填充数值。
(该指令与armasm中的ALIGN类似)。
power_of_2表示排列方式,其值可为4,8,16或32,单位是byte;fill_value是要填充的值;max_padding最大的填充界限,请求填充的bytes数超过该值,将被忽略。
.byte <byte1> {,<byte2>} … 定义一个或多个Byte,并为之分配空间(与armasm 的DCB类似)。
.code <number_of_bits> 设定指令宽度,16表示Thumb,32表示ARM assembly (和armasm中的CODE16,CODE32相同)。
GCC-ARM汇编

标签:GNU ASMGNU-ARM 汇编指令第一部分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指令集详解--汇编1. 汇编1.1. 通⽤通⽤寄存器37个寄存器,31个通⽤寄存器,6个状态寄存器,R13指针sp,R14返回指针,R15为PC指针, cpsr_c代表的是这32位中的低8位,也就是控制位CPSR有4个8位区域:标志域(F)、状态域(S)、扩展域(X)、控制域(C)MSR - Load specified fields of the CPSR or SPSR with an immediate constant, orfrom the contents of a general-purpose register. Syntax: MSR{cond} _, #immed_8rMSR{cond} _, Rm where: cond is an optional condition code. is either CPSR orSPSR. specifies the field or fields to be moved. can be one or more of: ccontrol field mask byte (PSR[7:0]) x extension field mask byte (PSR[15:8]) sstatus field mask byte (PSR[23:16) f flags field mask byte (PSR[31:24]).immed_8r is an expression evaluating to a numeric constant. The constant mustcorrespond to an 8-bit pattern rotated by an even number of bits within a32-bit word. Rm is the source register.C 控制域屏蔽字节(psr[7:0])X 扩展域屏蔽字节(psr[15:8])S 状态域屏蔽字节(psr[23:16])F 标志域屏蔽字节(psr[31:24])CPSR寄存器FIQ和IRQ的区别?MODE(以下为⼆进制)10000⽤户模式PC,CPSR,R0~R1410001FIQ PC,CPSR,SPSR_fiq,R14_fiq~R8_fiq,R7~R010010IRQ PC,CPSR,SPSR_irq,R14_irq~R13_irq,R12~R010011管理模式(svc)PC,CPSR,SPSR_svc,R14_svc~R13_svc,R12~R010111终⽌模式PC,CPSR,SPSR_abt,R14_abt~R13_abt,R12~R011011未定义PC,CPSR,SPSR_und,R14_und~R13_und,R2~R011111系统模式(sys)PC,CPSR,R14 ~R01.2. 指令格式1) 基本格式<opcode>{<cond>}{S} <Rd>,<Rn>{,<opcode2>}其中,<>内的项是必须的,{}内的项是可选的,如<opcode>是指令助记符,是必须的,⽽{<cond>}为指令执⾏条件,是可选的,如果不写则使⽤默认条件AL(⽆条件执⾏)。
第3章 ARM汇编语言程序设计-GNU 汇编

.macro SHIFTLEFT a,b .if \b<0 MOV \a,\a,ASR #-\b .exitm .endif MOV \a,\a,LSL #\b .endm
.string/.asciz/.ascii
语法格式 .string/.asciz/.ascii 表达式{,表达式}... 作用
... ADR ... Delay MOV ... R0,r14 0x64 R0,Delay 0x20 ... ADD ... ... MOV ... r0,r14 r0,pc,#0x3c
使用伪指令将程序标号 Delay的地址存入R0
ADR伪指令被汇编成一条指令
ARM伪指令——小范围的地址读取
ADR伪指令将基于PC相对偏移的地址值或基于寄存器相对偏移的 地址值读取到寄存器中。在汇编编译器编译源程序时,ADR伪指令被 编译器替换成一条合适的指令。通常,编译器用一条ADD指令或SUB 指令来实现该ADR伪指令的功能,若不能用一条指令实现,则产生错 误,编译失败。 应用示例2(查表): ADR LDRB … DISP_TAB: .word 0xC0,0xF9,0xA4,0xB0,0x99, 0x92,0x82,0xF8 R0,DISP_TAB R1,[R0,R2] ; 加载转换表地址 ; 使用R2作为参数,进行查表
① 符号由大小写字母、数字及下画线组成,符号不 能用数字开头。 ② 符号区分大小写,同名的大、小写符号会被编译 器认为是两个不同的符号。 ③ 符号在其作用范围内必须唯一。 ④ 自定义的符号名不能与系统的保留字相同。 ⑤ 符号名不应与指令或伪指令同名。
伪操作(Directive)是ARM汇编语言程序里的一 些特殊的指令助记符,其作用主要是为完成汇编程 序做各种准备工作,对源程序运行汇编程序处理, 而不是在计算机运行期间由处理器执行。不同的编 译程序所使用的伪操作有所不同。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
GNU ARM 汇编指令(2008-10-29 00:16:10)转载标签:linuxgnuarm汇编指令it 分类:技术文摘第一部分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,.ltorg ,.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)函数的编写应当遵循如下规则:-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, 但如果没有必要的话不推荐那样做。