常用ARM v4指令集及汇编
- 格式:docx
- 大小:254.14 KB
- 文档页数:91
ARM常用汇编指令arm 2009-12-19 15:51:59 阅读113 评论0 字号:大中小LDR 和STR——用于字和无符号字节指令格式:LDR/STR{cond}{T} Rd,<地址>LDR/STR{cond}B{T} Rd,<地址>LDR{cond}{T} Rd,<地址> 加载指定地址的字数据到Rd中;STR{cond}{T} Rd,<地址> 存储Rd中的字数据到指定的地址单元中;LDR{cond}B{T} Rd,<地址> 指令加载指定地址的字节数据到Rd的的最低字节中(Rd的高24位清零);STR{cond}B{T} Rd,<地址> 指令存储Rd中的最低字节数据到指定的地址单元中。
T为可选后缀,若有T,那么即使处理器是在特权模式下,存储系统也将访问看成处理器是在用户模式下,T 在用户模式下无效,不能与前索引偏移一起使用T。
地址部分可用的形式有4种:∙零偏移(zero offset) [Rn],Rn的值作为传送数据的地址。
如:LDR R0,[R1];∙前索引偏移(pre-indexed offset) [Rn,Flexoffset]{!}在数据传送之前,将偏移量Flexoffse t加到Rn 中。
其结果作为传送数据的存储器地址。
若使用后缀“!”,则结果写回到Rn 中,且Rn 不允许是R15,如:LDRB R0,[R1,#8]LDR R0,[R1,#8]!∙程序相对偏移(program relative) label(label 必须是在当前指令的土4KB范围内) 。
程序相对偏移是前索引形式的另一种版本。
从PC 计算偏移量,并将PC 作为Rn 生成前索引指令,不能使用后缀“!”,如:LDR R0,place ;place地址装入R0∙后索引偏移(post-indexed offset) [Rn],Flexoffset。
arm汇编逻辑指令-回复ARM汇编逻辑指令ARM汇编逻辑指令是一种基于RISC(Reduced Instruction Set Computing)的指令集架构,在数字电子设备中被广泛使用。
逻辑指令主要用于实现基本的逻辑操作,例如布尔运算、比较和分支跳转等。
本文将深入探讨ARM汇编逻辑指令的各个方面,包括指令格式、操作数和指令示例等。
一、指令格式ARM汇编逻辑指令的指令格式通常包括操作码、目标寄存器和操作数等字段。
下面是一个典型的ARM汇编逻辑指令的格式:<操作码>{xx}{cond} <目标寄存器>, <操作数1>, <操作数2>其中,操作码用于指定具体的逻辑操作,xx字段用于指定操作的类型(例如AND、OR或XOR等),cond字段用于指定条件执行的条件码,目标寄存器用于存储运算结果,操作数1和操作数2分别是参与运算的操作数。
二、操作数ARM汇编逻辑指令的操作数可以是寄存器或立即数。
寄存器是存储在CPU内部的高速存储器单元,用于存储临时数据。
ARM架构通常提供了16个通用寄存器(R0-R15),其中R0-R7用于存储一般性目的数据,R8-R15用于存储特殊用途数据。
立即数是直接写在指令中的常数值,通常用于表示较小的数据。
立即数的宽度取决于具体的指令和操作码。
例如,对于AND指令,立即数可以是8位或32位的。
三、指令示例以下是一些常见的ARM汇编逻辑指令示例:1. AND指令AND指令用于将两个操作数逐位进行与运算,并将结果存储在目标寄存器中。
例如,下面的指令将执行R1 = R2 AND 3:AND R1, R2, 32. OR指令OR指令用于将两个操作数逐位进行或运算,并将结果存储在目标寄存器中。
例如,下面的指令将执行R1 = R2 OR R3:ORR R1, R2, R33. XOR指令XOR指令用于将两个操作数逐位进行异或运算,并将结果存储在目标寄存器中。
算术和逻辑指令ADC : 带进位的加法(Ad dition with C arry)ADC{条件}{S} <dest>, <op 1>, <op 2>dest = op_1 + op_2 + carryADC将把两个操作数加起来,并把结果放置到目的寄存器中。
它使用一个进位标志位,这样就可以做比32 位大的加法。
下列例子将加两个128 位的数。
128 位结果: 寄存器0、1、2、和3第一个128 位数: 寄存器4、5、6、和7第二个128 位数: 寄存器8、9、10、和11。
ADDS R0, R4, R8 ; 加低端的字ADCS R1, R5, R9 ; 加下一个字,带进位ADCS R2, R6, R10 ; 加第三个字,带进位ADCS R3, R7, R11 ; 加高端的字,带进位如果如果要做这样的加法,不要忘记设置S 后缀来更改进位标志。
ADD : 加法(Add ition)ADD{条件}{S} <dest>, <op 1>, <op 2>dest = op_1 + op_2ADD将把两个操作数加起来,把结果放置到目的寄存器中。
操作数 1 是一个寄存器,操作数2 可以是一个寄存器,被移位的寄存器,或一个立即值:ADD R0, R1, R2 ; R0 = R1 + R2ADD R0, R1, #256 ; R0 = R1 + 256ADD R0, R2, R3,LSL#1 ; R0 = R2 + (R3 << 1)加法可以在有符号和无符号数上进行。
AND : 逻辑与(logical AND)AND{条件}{S} <dest>, <op 1>, <op 2>dest = op_1 AND op_2AND将在两个操作数上进行逻辑与,把结果放置到目的寄存器中;对屏蔽你要在上面工作的位很有用。
arm汇编指令作者不详,如果作者看到请与我联系...ARM指令系统特点ARM指令系统属于RISC指令系统。
标准的ARM指令每条都是32位长,有些ARM核还可以执⾏Thmub指令集,该指令集是ARM指令集的⼦集,每条指令只有16位。
1 数据类型ARM处理器⼀般⽀持下列6种数据类型:l8位有符号字节类型数据;l8位⽆符号字节类型数据;l16位有符号半字类型数据;l16位⽆符号半字类型数据;l32位有符号字类型数据;l32位⽆符号字类型数据;有些ARM处理器不⽀持半字和有符号字节数据类型。
在ARM内部,所有指令都是32操作数据。
短的数据数据类型只有在数据传送类指令中才被⽀持当1个字节数据取出后,被扩展到32位,在内部数据处理时,作为32位的什进⾏处理,并且ARM指令以字为边界。
所有Thumb指令都是16位指令时,并且以2个字节为边界。
ARM协处理器可以⽀持另外的数据类型,包括⼀套浮点数据类型,ARM的核并没有明确的⽀持。
2 存储器组织图3-1所⽰为存储器组织。
ARM这的地址的低三下四位必须为00,半字地址的最低位为0。
字的内容在存储器中的存放通常有两种⽅式,即⼩端(little-endian)和⼤端(big-endian),这两种⽅式的不同在于最低位字节的地址是否在最⾼位字节的地址之前。
⼩端⽅式每个字的低位字节在后,例如0x12345678⼩端⽅式存放如下:地址内容A 78A+1 56A+2 34A+3 12⼤端⽅式的存放如下:地址内容A 12A+1 34A+2 56A+3 78⼤多数的ARM处理器芯⽚都不得可以⽀持上⾯两种⽅式,⼀般缺省为⼩端。
2322212019181716word1615141312half-world12 half-word14111098word87654byte6 half-word43210byte3 byte2 byte1 byte02021222316171819word1612131415half-world12 half-word14891011word84567Byte5 half-word6Byte0 byte1 byte2 byte3(a)⼩端存储器组织(b)⼤端存储器组织图3-1 存储器组织3 ARM指令特点1.每条指令的多功能ARM指令⼀个重要的特点是它所有的指令都带有条件,例如⽤户可以测试某个寄存器的什但是直到下次使⽤同⼀条件进⾏测试时,才能有条件的执⾏这些指令。
arm 汇编指令一、arm 汇编简介1.1 什么是 arm 汇编1.2 arm 汇编的应用领域1.3 arm 汇编与高级语言的对比二、arm 汇编基础2.1 寄存器2.1.1 通用寄存器2.1.2 特殊寄存器2.2 数据传输指令2.2.1 加载指令2.2.2 存储指令2.3 算术指令2.3.1 加法指令2.3.2 减法指令三、arm 汇编进阶3.1 分支指令3.1.1 无条件分支3.1.2 有条件分支3.2 比较指令3.2.1 比较指令的作用3.2.2 比较指令的使用方法3.3 位操作指令3.3.1 与操作3.3.2 或操作3.3.3 异或操作四、arm 汇编优化技巧4.1 减少存取操作4.2 使用预处理器4.3 循环展开4.4 减少分支操作4.5 使用内联汇编五、arm 汇编的应用案例5.1 arm 汇编在嵌入式系统中的应用5.2 arm 汇编在图形处理中的应用5.3 arm 汇编在操作系统中的应用六、总结6.1 arm 汇编的优势和不足6.2 arm 汇编的未来发展6.3 arm 汇编学习的建议arm 汇编指令一、arm 汇编简介1.1 什么是 arm 汇编arm 汇编是一种底层的编程语言,用于直接操作处理器的指令集。
它与高级语言相比更接近机器语言,能够更加精细地控制硬件资源。
arm 汇编通常用于需要对性能和资源进行高度优化的场景,如嵌入式系统开发、驱动程序编写和底层图形处理等。
1.2 arm 汇编的应用领域arm 汇编广泛应用于各种领域,包括嵌入式系统、移动设备、游戏开发、图形处理、操作系统等。
由于 arm 汇编的高效性和精确性,它能够在这些领域中发挥重要作用。
例如,在嵌入式系统中,arm 汇编可以直接访问硬件资源,提供更高的执行效率和更低的资源消耗。
1.3 arm 汇编与高级语言的对比arm 汇编与高级语言相比有着明显的区别。
在高级语言中,程序员不需要关注底层的机器细节,只需要编写抽象的代码即可。
必须知道的ARM指令集常用的ARM指令集我们知道CPU能直接识别的是机器码,也就是0和1组合的东东。
不同的组合代表不同的含义,CPU就做不同的事情。
按照道理来说,我们写的代码都应该是0和1组成的东西,但是如果真的是那样,那结果....。
人类是聪明的,发明了汇编语言,汇编语言是用一些助记符,来代替机器码。
当然,汇编语言是不能给CPU识别的,需要编译器将其编译成机器码。
汇编语言是和特定的CPU关联的,不同的CPU对应不同的汇编指令。
好在,现在大多数嵌入式CPU都是使用ARM架构的,这样我们只需要学会ARM的汇编指令集,我们写的汇编程序就可以在这些使用ARM 架构的CPU上运行。
ARM的汇编指令很多,很难将其全部记住,其实也没必要,我们只需要学会一些常用的ARM汇编指令即可。
其他的用到再去查即可。
下面我们就开始,必须知道的ARM指令学习。
一、ARM指令格式ARM指令的基本格式如下:其中<>号内是必须的,{}号内的项是可选的。
各项的说明如下:opcode :指令助记符cond :执行条件S :是否影响CPSR寄存器的值Rd :目标寄存器(一般用来存放指令执行最后的结果)Rn :第1个操作数的寄存器operand2 :第2个操作数1. 其中,我们必须要研究一下operand2这个操作数,它有如下表现形式(1)#immed_8r——常数表达式该常数必须对应8位位图,即一个8位的常数通过循环右移偶数位得到,这个数我们也成立即数。
例如:MOV R0,#1AND R1,R2,#0x0例如:0x04800000它可以拿0x12循环右移位10位得到,所以它是一个合法的立即数。
有人会问,是不是每次我都要去判断一个数是不是立即数,我就需要从0x00~0xff里面找出一个数,将它循环右移偶数个位看是否能的得到,那太麻烦了。
有没有一些快速识别的方法呢?肯定是有的呀,当然也不能完全依赖哦,最好就是拿编译器验证,不是,编译器就会报错。
目的操作数1 + 操作数2 + !C 目的操作数1 + 操作数2目的操作数1 & 操作数2跳转至目的地, PC目标地址(PC R14,跳转)(PC R14,跳转并切换为thumb)目的操作数1 XOR 操作数2 LDC P3,C4,[R0] ;P3: C4 [R0]register MemeryRegister<存储器地址>目的操作数1 * 操作数2 + 操作数3 目的源操作数Register状态寄存器CPSR或SPSR<域> 操作数结果MODE(2^32),目的操作数1 * 操作数2 目的~(取反) 源操作数目的操作数1 OR 操作数2目的操作数2 - 操作数1目的操作数2 - 操作数1 - !C=64目的L(操作1 * 操作2)L+ 目的L 目的H(操作1 * 操作2)H +目的HSTC P3,C4,[R0] ;P3:C4[R0]Mem Register<存储器地址>Register 目的操作数1 –操作数2ARM汇编伪指令ARM条件码CPSR位[31:24]为条件位域,用f表示;位[23:16]为状态位域,用s表示;位[15:8] 为扩展位域,用x表示;位[7:0] 为控制位域,用c表示;与指令MSR相关关于移位中断向量表APCS寄存器使用约定Load and Store指令LDR R0,[R1] ;将存储器地址为R1的字数据读入寄存器R0。
LDR R0,[R1,R2] ;将存储器地址为R1+R2的字数据读入寄存器R0。
LDR R0,[R1,#8] ;将存储器地址为R1+8的字数据读入寄存器R0。
LDR R0,[R1,R2] !;将存储器地址为R1+R2的字数据读入寄存器R0,并将新地址R1+R2写入R1。
LDR R0,[R1,#8] !;将存储器地址为R1+8的字数据读入寄存器R0,并将新地址 R1+8写入R1。
LDR R0,[R1],R2 ;将存储器地址为R1的字数据读入寄存器R0,并将新地址 R1+R2写入R1。
arm汇编移位指令
ARM汇编语言中,移位指令是非常重要的操作之一。
ARM架构的
移位指令允许对操作数进行位移或者逻辑移位操作,常见的移位指
令包括LSL(逻辑左移)、LSR(逻辑右移)、ASR(算术右移)和ROR(循环右移)等。
LSL(Logical Shift Left)指令将操作数向左移动指定的位数,空出的位用0填充。
LSR(Logical Shift Right)指令将操作数向
右移动指定的位数,空出的位同样用0填充。
ASR(Arithmetic
Shift Right)指令将操作数向右移动指定的位数,并在最高位(符
号位)进行扩展,以保持负数的符号不变。
ROR(Rotate Right)指
令将操作数向右循环移动指定的位数,移出的位会重新移动到最高位。
这些移位指令在ARM汇编语言中使用非常广泛,可以用于实现
乘法、除法、逻辑运算等各种功能。
在实际编程中,程序员可以根
据具体的需求选择合适的移位指令来完成相应的操作。
同时,移位
指令还可以和其他指令结合使用,以实现更复杂的功能。
总的来说,移位指令在ARM汇编语言中扮演着重要的角色,能
够灵活地处理数据的位移和逻辑运算,为程序的实现提供了强大的支持。
常用的ARM指令集我们知道CPU能直接识别的是机器码,也就是0和1组合的东东。
不同的组合代表不同的含义,CPU就做不同的事情。
按照道理来说,我们写的代码都应该是0和1组成的东西,但是如果真的是那样,那结果....。
人类是聪明的,发明了汇编语言,汇编语言是用一些助记符,来代替机器码。
当然,汇编语言是不能给CPU识别的,需要编译器将其编译成机器码。
汇编语言是和特定的CPU关联的,不同的CPU对应不同的汇编指令。
好在,现在大多数嵌入式CPU都是使用ARM架构的,这样我们只需要学会ARM的汇编指令集,我们写的汇编程序就可以在这些使用ARM架构的CPU上运行。
ARM的汇编指令很多,很难将其全部记住,其实也没必要,我们只需要学会一些常用的ARM汇编指令即可。
其他的用到再去查即可。
下面我们就开始,必须知道的ARM指令学习。
一、ARM指令格式ARM指令的基本格式如下:其中<>号内是必须的,{}号内的项是可选的。
各项的说明如下:opcode :指令助记符cond :执行条件S :是否影响CPSR寄存器的值Rd :目标寄存器(一般用来存放指令执行最后的结果)Rn :第1个操作数的寄存器operand2 :第2个操作数1. 其中,我们必须要研究一下operand2这个操作数,它有如下表现形式(1)#immed_8r——常数表达式该常数必须对应8位位图,即一个8位的常数通过循环右移偶数位得到,这个数我们也成立即数。
例如:MOV R0,#1AND R1,R2,#0x0例如:0x04800000它可以拿0x12循环右移位10位得到,所以它是一个合法的立即数。
有人会问,是不是每次我都要去判断一个数是不是立即数,我就需要从0x00~0xff里面找出一个数,将它循环右移偶数个位看是否能的得到,那太麻烦了。
有没有一些快速识别的方法呢?肯定是有的呀,当然也不能完全依赖哦,最好就是拿编译器验证,不是,编译器就会报错。
如何判断一个数是否是合法立即数?首先将这个数转换为32bit 16进制形式,例如218=0xDA=0x000000DA1.除零外,仅有一位数为合法立即数。
arm汇编指令集汇编入门第一篇小白也能看懂如今,计算机科学与技术领域发展迅猛,其中包括一门被广泛应用的指令集架构—— ARM(Advanced RISC Machines)汇编指令集。
本文将从小白角度出发,向读者介绍ARM汇编指令集的基本概念和入门知识。
1. ARM汇编简介ARM汇编指令集是一种低级程序设计语言,用于在ARM微处理器上进行编程。
它不同于高级语言如C++或Java,具有较为底层的特性。
掌握ARM汇编指令集可以让开发者更深入地理解计算机内部运行原理,并能进行更加灵活和高效的编程。
2. ARM寄存器ARM汇编指令集使用一组寄存器来存储和处理数据。
其中,常用的寄存器有13个通用寄存器(R0-R12)、程序计数器(PC)、堆栈指针(SP)和链接寄存器(LR),另外还有一些特殊用途的寄存器。
这些寄存器提供了一种基于寄存器的计算模型,使得ARM汇编具有高效处理数据的能力。
3. 指令格式ARM汇编指令集的指令格式一般包括操作码和操作数。
操作码表示具体的操作,如加法、乘法等,而操作数则指定操作所需的寄存器和立即数等。
4. 数据处理指令ARM汇编指令集提供了一系列的数据处理指令,用于对寄存器中的数据进行处理。
这些指令包括基本的算术运算、逻辑运算以及移位操作等,可以实现各种数据处理需求。
5. 分支指令分支指令是ARM汇编指令集中常用的一类指令,用于根据条件进行跳转。
跳转指令可以在程序执行过程中改变程序执行的顺序,实现条件判断和循环等功能。
6. 存储器访问指令存储器访问指令用于在ARM汇编中对内存进行读写操作。
通过这些指令,可以将数据从寄存器中存储到内存中,或者将内存中的数据加载到寄存器中进行处理。
7. 输入输出指令输入输出指令用于实现与外部设备的交互。
例如,通过输入指令可以从键盘或其他输入设备中获取用户输入的数据,而通过输出指令可以将数据输出到显示器或其他输出设备中。
8. 常用例程ARM汇编指令集中有一些常用的例程,可以用于处理常见的编程任务。
ARM汇编指令集与机器码0x00 本⽂⽬标本⽂内容从《ARM Architecture Reference Manual》中截取翻译,可以看作是⼀个重点笔记集。
仅记录博主认为有意思的部分,并加⼊⼀些个⼈理解。
如果发现有不对的地⽅欢迎留⾔指正。
现代的智能⼿机是能进⾏ARM汇编级别交互的最便捷的设备,因此实例分析的内容基于博主的⼩⽶Note+IDA,和某个正在被调试的安卓程序。
该程序加载的SO⽂件使⽤armeabi架构。
0x01 ARM模型与概念ARM⽀持三种数据类型的读写:Byte(8 bits),Halfword(16 bits),Word(32 bits)。
所有内存指令相关的读写操作都会基于这三种数据类型。
ARM使⽤⼩端存储,这意味着例如指令E5 9F 00 90在内存中会反序存储为:0x00a0 90 00 9F E5在读取指令后,会被还原为正序E59F0090。
ARM⼀共⽀持7种处理器模式,程序在编译后所运⾏的绝⼤部分时间⽚中,例如执⾏了⼀段MD5加密函数,都处于usr模式。
寄存器⽰例图,某个程序正在处于调试暂停中。
ARM处理器⼀共有37个之多的寄存器。
在所有的ARM状态模式中,有15个可见寄存器(R0~R14),和1~2个状态寄存器随时可编程交互。
其余没有提到的寄存器,⽤于处理异常、中断等核⼼指令,外部不可见也不能⾃主控制读写。
R0~R7作为不保留寄存器,可以⾃由编程指定其含义。
例如R0~R3最常⽤于参数传递,返回值等保存。
R8~R14是保留寄存器,有⾃⼰的特殊含义,在寄存器实例图中可以看到多半保存和地址相关的值,⼜或者指向了SP地址或LR地址。
通常R13就是SP(Stack Pointer)寄存器,该值指向当前汇编代码段可以使⽤的栈起始地址。
R14作为LR(Link Register)寄存器,保存当前汇编代码段执⾏完毕后,需要回溯到的汇编代码地址。
PC程序计数器是⼀个特殊的寄存器,指向当前正在执⾏的代码地址。
ARM 指令集•寄存器和处理器模式(26-bit 体系)•寄存器和处理器模式(32-bit 体系)•程序状态寄存器和操纵它的指令•寄存器装载和存储指令•算术和逻辑指令•移位操作•乘法指令•比较指令•分支指令•条件执行•软件中断指令•APCS (ARM 过程调用标准)•编写安全的 32-bit 代码的基本规则•IEEE 浮点指令•汇编器伪指令•指令快速查找•ARM 指令格式寄存器和处理器模式ARM 处理器有二十七个寄存器,其中一些是在一定条件下使用的,所以一次只能使用十六个...•寄存器 0 到寄存器 7 是通用寄存器并可以用做任何目的。
不象 80x86 处理器那样要求特定寄存器被用做栈访问,或者象 6502 那样把数学计算的结果放置到一个累加器中,ARM 处理器在寄存器使用上是高度灵活的。
•寄存器 8 到 12 是通用寄存器,但是在切换到 FIQ 模式的时候,使用它们的影子(shadow)寄存器。
•寄存器 13 典型的用做 OS 栈指针,但可被用做一个通用寄存器。
这是一个操作系统问题,不是一个处理器问题,所以如果你不使用栈,只要你以后恢复它,你可以在你的代码中自由的占用(corrupt)它。
每个处理器模式都有这个寄存器的影子寄存器。
•寄存器 14 专职持有返回点的地址以便于写子例程。
当你执行带连接的分支的时候,把返回地址存储到 R14 中。
同样在程序第一次运行的时候,把退出地址保存在 R14 中。
R14 的所有实例必须被保存到其他寄存器中(不是实际上有效)或一个栈中。
这个寄存器在各个处理器模式下都有影子寄存器。
一旦已经保存了连接地址,这个寄存器就可以用做通用寄存器了。
•寄存器 15 是程序计数器。
它除了持有指示程序当前使用的地址的二十六位数之外,还持有处理器的状态。
为更清晰一些... 提供下列图表:User 模式 SVC 模式 IRQ 模式 FIQ 模式 APCSR0 ------- R0 ------- R0 ------- R0 a1R1 ------- R1 ------- R1 ------- R1 a2R2 ------- R2 ------- R2 ------- R2 a3R3 ------- R3 ------- R3 ------- R3 a4R4 ------- R4 ------- R4 ------- R4 v1R5 ------- R5 ------- R5 ------- R5 v2R6 ------- R6 ------- R6 ------- R6 v3R7 ------- R7 ------- R7 ------- R7 v4R8 ------- R8 ------- R8 R8_fiq v5R9 ------- R9 ------- R9 R9_fiq v6R10 ------ R10 ------ R10 R10_fiq slR11 ------ R11 ------ R11 R11_fiq fpR12 ------ R12 ------ R12 R12_fiq ipR13 R13_svc R13_irq R13_fiq spR14 R14_svc R14_irq R14_fiq lr------------- R15 / PC ------------- pc最右侧的列是 APCS 代码使用的名字,关于 APCS 的详情参见这里。
常⽤ARM汇编指令1、相对跳转指令:b, bl 区别在于bl指令除了跳转之外,还将返回地址(bl的下⼀条指令的地址)保存在lr寄存器中。
可跳转范围是当前指令的前后32MB。
2、数据发送指令mov,地址读取伪指令ldr mov指令: mov r1, r2 //r1=r2,把⼀个寄存器的值赋给另⼀个寄存器 mov r1,#358 //r1=4096, 把⼀个常数赋给寄存器 ldr伪指令:(第⼆个参数为“=”时表⽰伪指令,否则表⽰内存访问指令) ldr r1,=358 //把⼀个常数赋给寄存器3、内存访问指令:ldr、str、ldm、stm ldr指令从内存中读取数据到寄存器: ldr r1, [r2, #4] //将地址为r2+4的内存单元数据读取到r1中 ldr r1, [r2] //将地址r2内存中数据读取到r1中 ldr r1, [r2], #4 //将地址为r2的内存中的数据读取到r1中,然后r2=r2+4 str指令把寄存器的值存储到内存中: str r1, [r2, #4] //将r1的数据保存到地址为r2+4的内存单元中 str r1, [r2] //将r1的数据保存到地址r2的内存单元中 str r1, [r2], #4 //将r1的数据保存到r2的内存单元中,然后r2= r2+44、加减指令:add、sub add r1,r2,#1 //表⽰r1 = r2+1 sub r1,r2,#1 //表⽰r1 = r2-15、程序状态访问寄存器:msr、mrs ARM 有⼀个程序状态寄存器(cpsr),⽤来控制处理器的⼯作模式、设置中断的总开关 msr cpsr, r0 //复制r0到cpsr mrs r0,cpsr //复制cpsr到r06、其他汇编指令 .extern main .text .global _start _start: ".extern"定义⼀个外部符号(可以是变量也可以是函数) “.text”表⽰羡慕的语句都属于代码段 “.global”将本⽂件中的某个程序标号定义为全局的,如上表⽰将_start定义为全局函数。
常用ARM v4指令集及汇编前言零零散散用了大概一周的时间,在《常用ARM指令集及汇编》(2003年12月1日)的基础上,大致学习了一遍ARM指令集和汇编,看的过程当中更正了一些错误的地方,并结合其它资料适当添加了一些内容,也做了一些删减,现分享出来,希望能帮助到需要的人。
文中必然还有一些错误还有待改进,有些地方还需要解释的更加详细,本人精力有限,希望有心的读者,订正并增加注释,最好也分享出来,以方便大家对ARM指令的深入理解。
作为刚入行的新手,不谦虚的推荐几本书:《ARM体系结构与编程-杜春雷》,《嵌入式系统体系结构、编程与设计-Raj Kamal著,贾建斌译》,《嵌入式系统:采用公开源代码和StrongARM_XScale处理器-毛德操》。
这几本书到底好不好,看个人需求和喜好吧,仁者见仁智者见智。
最后,感谢《常用ARM指令集及汇编》的原作者和其它资料的作者让我有机会学习我不熟悉的东西,谢谢。
learllp2015-11-09目录常用ARM v4指令集及汇编 (I)前言 ............................................................................................................................. I I 目录 ............................................................................................................................ I II ARM v4指令集及汇编.. (1)一、ARM处理器寻址方式 (1)寄存器寻址 (1)立即寻址 (1)寄存器偏移寻址 (2)寄存器间接寻址 (2)基址寻址 (3)多寄存器寻址 (3)堆栈寻址 (3)块拷贝寻址 (4)相对寻址 (4)二、指令集介绍 (5)ARM指令集 (5)指令格式 (5)基本格式 (5)第2个操作数 (5)1.#immed_8r常数表达式 (5)2.Rm 寄存器方式 (6)3.Rm,shift寄存器移位方式 (6)条件码 (7)ARM 存储器访问指令 (8)◆LDR和STR (8)◆LDM和STM (11)◆SWP (14)ARM 数据处理指令 (15)数据传送指令 (15)算术逻辑运算指令 (16)ARM 跳转指令 (21)ARM 协处理器指令 (22)ARM 杂项指令 (24)ARM 伪指令 (26)Thumb 指令集 (29)Thumb 指令集与ARM 指令集的区别 (29)跳转指令 (29)数据处理指令 (29)单寄存器加载和存储指令 (29)批量寄存器加载和存储指令 (30)Thumb 存储器访问指令 (30)伪指令 (31)符号定义伪指令 (32)数据定义伪指令 (34)报告伪指令 (39)汇编控制伪指令 (41)杂项伪指令 (43)◆AREA (45)◆CODE16 和CODE32 (46)◆END (46)◆ENTRY (46)◆EQU (47)◆EXPORT 和GLOBAL (47)◆IMPORT 和EXTERN (47)◆GET 和INCLUDE (48)◆INCBIN (48)◆KEEP (49)◆NOFP (49)◆REQUIRE (49)◆PEQUIRE8 和PRESERVE8 (49)◆RN (49)◆ROUT (50)ARM 伪指令 (50)◆ADR (50)◆NOP (51)◆LDFD (51)◆LDFS (51)三、ARM汇编程序设计 (51)文件格式 (51)ARM 汇编的一些规范 (52)汇编语句格式 (52)标号 (52)基于PC 的标号 (53)基于寄存器的标号 (53)绝对地址 (53)局部标号 (53)符号 (54)常量 (54)数字常数 (54)字符常量 (54)布尔常量 (55)段定义 (55)宏定义及其作用 (55)子程序的调用 (56)数据比较跳转 (57)循环 (57)数据块复制 (57)栈操作 (58)特殊寄存器定义及应用 (58)散转功能 (58)查表操作 (58)长跳转 (59)对信号量的支持 (59)伪指令使用 (59)一个完整的例子 (59)外围部件控制 (60)四、C与汇编混合编程 (60)内嵌汇编 (60)内嵌汇编的指令用法 (62)内嵌汇编器与armasm 汇编器的差异 (63)内嵌汇编注意事项 (63)访问全局变量 (65)C与汇编相互调用 (65)寄存器的使用规则 (66)堆栈使用规则 (66)参数传递规则 (66)C程序调用汇编程序 (67)调用汇编的C函数: (67)汇编程序调用C程序 (68)五、ARM 指令集列表 (69)ARM 存储器访问指令表列表 (69)ARM 数据处理指令列表 (70)ARM 乘法指令列表 (71)ARM 跳转指令列表 (72)ARM 协处理器指令列表 (73)ARM 杂项指令列表 (74)ARM 伪指令列表 (75)六、Thumb 指令集列表 (120)Thumb 存储器访问指令列表 (120)Thumb 数据处理指令列表 (121)Thumb 跳转指令及软中断指令列表 (122)Thumb 伪指令列表 (123)七、汇编预定义变量及伪指令 (124)预定义的寄存器和协处理器名 (124)通用寄存器 (124)程序状态寄存器 (124)浮点数寄存器 (124)协处理器及协处理器寄存器 (125)八、内置变量列表 (125)九、伪指令列表 (126)十、指令条件码列表 (128)十一、CPSR 和S PSR 分配图 (129)ARM v4指令集及汇编ARM 处理器是基于精简指令集计算机(RISC)原理设计的,指令集和相关译码机制较为简单,具有32 位ARM 指令集和16 位Thumb 指令集。
ARM 指令集效率高,但是代码密度低,而Thumb 指令集具有更好的代码密度,却仍然保持ARM 的大多数性能上的优势,它是ARM 指令集的子集,主要用于编译器设计。
所有ARM 指令都是可以有条件执行的,而Thumb 指令仅有一条指令具备条件执行功能。
ARM 程序和Thumb 程序可相互调用,相互之间的状态切换开销几乎为零。
一、ARM处理器寻址方式寻址方式是根据指令中给出的地址码字段来实现寻找真实操作数地址的方式,ARM 处理器有9 种基本寻址方式。
寄存器寻址操作数的值在寄存器中,指令中的地址码字段指出的是寄存器编号,指令执行时直接取出寄存器值操作。
寄存器寻址指令举例如下:MOV R1,R2 ;R2 -> R1SUB R0,R1,R2 ;R1 - R2->R0立即寻址立即寻址指令中的操作码字段后面的地址码部分就是操作数本身,也就是说,数据就包含在指令当中,取出指令也就取出了可以立即使用的操作数(立即数)。
立即寻址指令举例如下:SUBS R0,R0,#1 ;R0–1 ->R0MOV R0,#0xff00 ;0xff00 ->R0立即数要以“#”为前缀,表示16 进制数值时以“0x”表示。
1寄存器偏移寻址寄存器偏移寻址是ARM 指令集特有的寻址方式,当第 2 操作数是寄存器偏移方式时,第2个寄存器操作数在与第1个操作数结合之前,选择进行移位操作。
寄存器偏移寻址方式指令举例如下:MOV R0,R2,LSL #3 ;R2 的值左移3 位,结果放入R0,即R0 = R2 * 8ANDS R1,R1,R2,LSL R3 ;R2 的值左移R3 位,然后和R1 相与操作,结果放入R1 可采用的移位操作如下:LSL:逻辑左移(Logical Shift Left),寄存器中字的低端空出的位补0。
LSR:逻辑右移(Logical Shift Right),寄存器中字的高端空出的位补0。
ASR:算术右移(Arithmetic Shift Right),移位过程中保持符号位不变,即如果源操作数为正数,则字的高端空出的位补0,否则补1。
ROR:循环右移(Rotate Right),由字的低端移出的位填入字的高端空出的位。
RRX:带扩展的循环右移(Rotate Right extended by 1place),操作数右移一位,高端空出的位用原 C 标志值填充。
各移位操作如下图所示:寄存器间接寻址寄存器间接寻址指令中的地址码给出的是一个通用寄存器编号,所需要的操作数2保存在寄存器指定地址的存储单元中,即寄存器为操作数的地址指针。
寄存器间接寻址指令举例如下:LDR R1,[R2] ;将R2 中的数值作为地址,取出此地址中的数据保存在R1 中SWP R1,R1,[R2];将如中的数值作为地址,取出此地址中的数值与R1 中的值交换基址寻址基址寻址是将基址寄存器的内容与指令中给出的偏移量相加,形成操作数的有效地址,基址寻址用于访问基址附近的存储单元,常用于查表,数组操作,功能部件寄存器访问等。
基址寻址指令举例如下:LDR R2,[R3,#0x0F] ;将R3中的数值加0x0F作为地址,将该地址保存在R2中STR R1,[R0,#-2] ;将R0中的数值减2作为地址,把R1中的内容保存到此地址多寄存器寻址多寄存器寻址就是一次可以传送几个寄存器值,允许一条指令传送16 个寄存器的任何子集或所有寄存器。
多寄存器寻址指令举例如下:LDMIA R1!,{R2-R7,R12} ;将[ R1] 单元中的数据读出到R2-R7,R12,R1自动加1STMIA R0!,{R3-R6,R10} ;将R3-R6,R10中的数据保存到[R0],R0自动加1使用多寄存器寻址指令时,寄存器子集的顺序由小到大的顺序排列,连续的寄存器可用“-”连接,否则用“,”分隔书写。
堆栈寻址堆栈是特定顺序进行存取的存储区,操作顺序分为“后进先出”和“先进后出”,堆栈寻址是隐含的,它使用一个专门的寄存器(堆栈指针)指向一块存储区域(堆栈),指针所指向的存储单元就是堆栈的栈顶。
存储器堆栈可分为两种:向上生长:向高地址方向生长,称为递增堆栈。
向下生长:向低地址方向生长,称为递减堆栈。
堆栈指针指向最后压入堆栈的有效数据项,称为满堆栈;堆栈指针指向下一个要放入的空位置,称为空堆栈。
这样就有4种类型的堆栈表示。
满递增:堆栈通过递增存储器的地址向上增长,堆栈指针指向堆栈内含有效数据项的最高地址。
指令如LDMFA,STMFA 等。
空递增:堆栈通过递增存储器的地址向上增长,堆栈指针指向堆栈内的第一个空位置。
指令如LDMEA,STMEA 等。
3满递减:堆栈通过递减存储器的地址向下增长,堆栈指针指向堆栈内含有效数据项的最低地址。