ARM汇编中的LDR及ADR的区别及其在UBOOT中的应用

合集下载

ARM汇编总结

ARM汇编总结

转载自:/xiwangsll123@126/blog/static/168698140201092242738669/今天的任务是研究嵌入式汇编程序,最重要的是明白如何让一个操作系统在ARM开发板运行起来,需要进行哪些底层操作:任务的第一步是,首先熟悉汇编程序的编写,同时明白操作系统底层操作实现原理。

今天有一个心得就是,对一个大项目进行总结分析时,首先要针对各个难点各个击破,然后再系统的总结(有条理的总结)。

首先,针对汇编语言中出现的重难点知识进行以下总结:1.LDR R1,=COUNT意思是将COUNT变量的地址放到R1中LDR R1,COUNT意思是将COUNT变量地址里面的内容赋给R12.Load-Store结构——这个应该是RISC设计中比较有特点的一部分。

在RISC中,CPU并不会对内存中的数据进行操作,所有的计算都要求在寄存器中完成。

而寄存器和内存的通信则由单独的指令来完成。

而在CSIC中,CPU是可以直接对内存进行操作的,这也是一个比较特别的地方。

所以,在ARM中,cpu只能通过寄存器来对内存的数据访问和更改。

LDR Rd,(地址)STR Rd,(地址)LDMIA Rn!,reglistSTMIA Rn!,reglist注意上面LDR/STR和LDMIA/STMIA的区别,LDR/STR命令使用时,寄存器在前,地址在后。

而在LDMIA/STMIA使用时,地址在前,寄存器在后。

这就决定了LDR和LDM同为加载命令,但操作顺序是不同的,同理STR/STM。

但有一点他们是相同的,即加载LDR/LDM的意思是把内存的数据(即上面的地址)加载到寄存器;存储STR/STM的意思是把寄存器的内容存储到内存(即上面的地址)。

这样比较之后也就全明白了,只需明白那部分是寄存器,那部分是地址(内存),然后区别是加载还是存储,就可以知道操作方向。

3.LDM/STMIA/IB,DA,DB数据块传输FD/ED,EA/FA堆栈操作LDMIA Rn!,reglistSTMIA Rn!,reglist其中Rn加载/存储的起始地址寄存器,Rn必须为R0~R7Reglist加载/存储的起始寄存器列表,寄存器必须为R0~R74.在汇编程序中!的使用,意思是回写,比如:ldr r1,[sp,#S_PSR]ldr lr,[sp,#S_PC]!其中!用来控制基址变址寻址的的最终新地址是否进行回写操作此条语句的意思是执行ldr之后sp被回写成sp+#S_PC基址变址寻址的新地址5.arm堆栈的组织结构是满栈降的形式,满栈即sp是要停留在最后一个进栈元素,降,就是堆栈的增长方向是从高地址向低地址发展。

ARM编程进阶之一-ARM汇编伪指令

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 这条伪指令的处理,其实质是:。

uboot 汇编指令

uboot 汇编指令

U-Boot(Universal Boot Loader)是一个开源的、通用的引导加载程序,支持多种处理器架构和嵌入式系统。

在U-Boot中,汇编指令的使用主要涉及对硬件的低级操作和优化。

以下是一些常见的U-Boot汇编指令及其作用:
1.ldr:这是一个加载指令,用于从内存中读取数据并将其加载到寄存器中。

例如,ldr r0,=0x12345678将把地址0x12345678处的值加载到寄存
器r0中。

2.str:这是一个存储指令,用于将数据从寄存器存储到内存中。

例如,str r0,[r1]将把寄存器r0中的值存储到r1指向的内存地址中。

3.mov:这是一个移动指令,用于将数据从一个位置移动到另一个位置,而不对数据进行任何操作。

例如,mov r0,r1将把寄存器r1的值复制到寄存
器r0中。

4.add和sub:这些是算术指令,用于对数据进行加法或减法操作。

例如,add r0,r1,r2将把寄存器r1和r2的值相加,结果存储在寄存器r0中。

5.cmp:这是一个比较指令,用于比较两个值的大小。

它不保存结果,但会设置条件标志,这可以用于控制程序流。

例如,cmp r0,r1将比较寄存器
r0和r1中的值。

6.and、orr、eor等:这些是逻辑指令,用于执行逻辑与、或、异或等操作。

这些只是U-Boot汇编语言中的一部分指令,还有许多其他指令和语法结构。

建议查阅U-Boot的官方文档或参考手册以获取更详细的信息和示例。

LDR指令详解(转载)

LDR指令详解(转载)

LDR指令详解(转载)展开全文LDR指令详解(转载)2010-01-19 16:27:25| 分类:单片机学习 |字号订阅LDR指令详解(2009-10-27 11:26:31)标签:杂谈分类:ARM ARM指令集中,LDR通常都是作加载指令的,但是它也可以作伪指令。

(1)LDR r0,=name,像这种带等号的是伪指令,而不是ARM指令,LDR 伪指令用于加载立即数或一个地址值到指定寄存器.*如果name是立即数的话:LDR R0,=0X123;//将0X123存入R0 *如果name是个标识符:LDR R0,=NAME;//将NAME的地址存入R0相当于:LDR R0,LABEL;LABEL DCB NAME;//分配内存并用NAME初始化(LABEL为内存的起始地址?)(2)LDR R1,[R0] ;如果没有等号,LDR 指令用于从内存中读取数据放入寄存器中.该指令是将R0 地址处的数据读出,保存到R1 中(零偏移)。

转个帖子:/axx1611/archive/2008/04/27/2335410.aspx说说ARM汇编的LDR伪指令收藏我们知道ARM CPU中有一条被广泛使用的指令LDR,它主要是用来从存储器(确切地说是地址空间)中装载数据到通用寄存器。

但不论是ARMASM还是GNU ARM AS,都提供了一条与之同名的伪指令LDR,而在实际中使用该伪指令的情况也较多,那他们有什么不同呢?下面我谈谈我的理解。

由于我使用GNU工具链,所以以下的内容都以GNU AS的ARM 语法为准。

LDR伪指令的语法形式如下:LDR <reg>, = <constant-expression>这个常量表达式<constant-expression>中可以包含Label(在ARM汇编中Label会在连接时解释为一个常数),且其中的常数前不加#符号。

范例demo.s: .equ STACK_BASE, 0x0c002000.equ STACK_SIZE, 0x00001000.textldr sp, = STACK_BASEldr sl, = STACK_BASE - STACK_SIZEldr pc, = entry这是一个合法的汇编文件,它把堆栈基址设为0x0c002000,栈限设为0x0c001000,然后跳到entry所标识的C程序中执行。

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,这就是⼀个寄存器和内存交换⼤量数据的⽰例,在⼀个周期内完成了多个内存地址和多个寄存器的操作。

android 逆向中常用的arm汇编指令基础知识

android 逆向中常用的arm汇编指令基础知识

android 逆向中常用的arm汇编指令基础知识在Android 逆向工程中,了解ARM 汇编指令的基础知识对于理解和分析应用程序的底层行为至关重要。

以下是一些常用的ARM 汇编指令及其简要说明:数据移动指令:MOV:将源操作数的值复制到目标寄存器。

STR:将寄存器的值存储到内存中。

LDR:从内存中加载值到寄存器。

算术指令:ADD:加法。

SUB:减法。

MUL:乘法。

DIV:除法。

AND:位与。

ORR:位或。

XOR:位异或。

NOT:位非。

比较指令:CMP:比较两个值,并根据结果设置条件标志。

TST:测试寄存器的位,并根据结果设置条件标志。

条件分支指令:B:无条件分支。

BEQ:当相等时分支。

BNE:当不相等时分支。

BGT:当大于时分支。

BLT:当小于时分支。

BGE:当大于或等于时分支。

BLE:当小于或等于时分支。

堆栈操作指令:PUSH:将寄存器值压入堆栈。

POP:从堆栈中弹出值到寄存器。

加载/存储指令:LDM:从内存加载多个寄存器。

STM:将多个寄存器存储到内存。

交换指令:SWP:交换寄存器的值与内存中的值。

程序控制指令:BL:带返回的分支。

BX:跳转到寄存器指定的地址。

了解这些指令可以帮助你在逆向工程中识别和分析关键代码段,例如函数入口、出口、条件跳转等。

此外,对于某些特定的逆向工程技术,如hooking、代码注入等,对ARM 汇编的深入理解也是必不可少的。

请注意,ARM 架构有多个版本(如ARMv7、ARMv8 等),不同版本可能具有不同的指令集和特性。

因此,在具体的应用中,你可能需要参考特定版本的ARM 架构文档来获取更详细和准确的信息。

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常用的数据传送指令

ARM指令集中的数据传送指令主要用于在寄存器和内存之间传输数据。

以下是一些常用的数据传送指令:
1. LDR - 加载寄存器指令。

用于从内存加载数据到寄存器。

2. STR - 存储寄存器指令。

用于将数据从寄存器存储到内存。

3. LDRB - 加载字节指令。

用于从内存加载一个字节的数据到寄存器。

4. STRB - 存储字节指令。

用于将一个字节的数据从寄存器存储到内存。

5. LDRH - 加载半字指令。

用于从内存加载一个半字的数据到寄存器。

6. STRH - 存储半字指令。

用于将一个半字的数据从寄存器存储到内存。

7. LDRD - 加载双字指令。

用于从内存加载一个双字的数据到寄存器。

8. STRD - 存储双字指令。

用于将一个双字的数据从寄存器存储到内存。

9. PUSH - 入栈指令。

用于将寄存器的值推送到堆栈中。

10. POP - 出栈指令。

用于从堆栈中弹出值并将其存储到寄存器中。

这些指令可以配合使用 ARM 的地址计算和跳转指令来完成更复杂的内存操作和数据处理任务。

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

ARM汇编常用命令备注 LDR adr LDR=的用法含义

ARM汇编常用命令备注 LDR adr LDR=的用法含义

ARM汇编常用命令备注:1、标签标签就是在某行程序代码前作一个标记,标签代表的是这行代码的地址。

_undefined_instruction: .word undefined_instruction_undefined_instruction是一个标号,处理到这里时,asm会把undefined_instruction的值按16bit 的形式放在此标号处。

ldr pc, _undefined_instruction就是从_undefined_instruction处取值,即undefined_instruction,并设置到pc中。

.word就是在这个地方放一个值。

相当于在这里定义一个数据变量。

用.word定义了一个16bit 的数据。

并将underfined_instruction的值本身放在这里,因此,pc=undefined_instruction,实现跳转。

ldr 是把数据从存储器传输到寄存器上,格式如下:ldr(条件) 目的寄存器,<存储器地址>Ex1:.globl _start.globl _armboot_start_start:b reset_armboot_start:.word _startldr r2, _armboot_start.word expression就是在当前位置放一个word型的值,这个值就是expression ,此处的含义就是建立一个全局标签_armboot_start,在这个位置上放置_start的值(可以这样理解,_armboot_start是一个地址,这个地址中的内容是_start),则下面的语句会把地址_armboot_start处的内容(_start)装载到r2中。

Ex2:ldr r1, _rWTCON_rWTCON:.word 0x15300000是把地址_rWTCON上的内容放到r1(不是把地址0x1530 0000 上的内容传递到r1),而地址_rWTCON上的内容是0x15300000。

汇编LDR、LDM和STR、STM的区别

汇编LDR、LDM和STR、STM的区别

汇编LDR、LDM和STR、STM的区别
(1)LDR:L 表示LOAD,LOAD 的含义应该理解为:Load from memory into register。

下面这条语句就说明的很清楚:LDRR1,[R2]
R1 就是把R2 所指向的存储单元的内容的值(一个memory 地址内的值),读
取到R1 中(一个register)
(2)STR:S 表示STORE,STORE 的含义应该理解为:Store from a register into memory。

下面这条语句表示的很清楚:
STRR1,[R2]
R1>[R2]
就是把寄存器R1 中的内容保存到R2 所指向的存储的单元中(一个memory
地址)。

显然,这两条语句都有个特点,就是寄存器写在前面(左边)而内存地址写
在后面(右边),数据传送的方向则是恰好相反的。

下面对LDM 和STM 介绍,使用sp 来介绍,因为实际使用中,和sp 一起使
用更多。

(3)LDM:L 的含义仍然是LOAD,即是Load from memory into register。

虽然貌似是LDR 的升级,但是,千万要注意,这个指令运行的方向和LDR
是不一样的,是从左到右运行的。

该指令是将内存中堆栈内的数据,批量的赋
值给寄存器,即是出栈操作;其中堆栈指针一般对应于SP,注意SP 是寄存器
R13,实际用到的却是R13 中的内存地址,只是该指令没有写为[R13],同时,LDM 指令中寄存器和内存地址的位置相对于前面两条指令改变了,下面的例。

ARM指令集详解资料(000001)

ARM指令集详解资料(000001)

ARM指令集详解ARM可以用两套指令集:ARM指令集和Thumb指令集。

本文介绍ARM指令集。

在介绍ARM 指令集之前,先介绍指令的格式。

1 指令格式(1)基本格式<opcode>{<cond>}{S} <Rd>,<Rn>{,<opcode2>}其中,<>内的项是必须的,{}内的项是可选的,如<opcode>是指令助记符,是必须的,而{<cond>}为指令执行条件,是可选的,如果不写则使用默认条件AL(无条件执行)。

opcode 指令助记符,如LDR,STR 等cond 执行条件,如EQ,NE 等S 是否影响CPSR 寄存器的值,书写时影响CPSR,否则不影响Rd 目标寄存器Rn 第一个操作数的寄存器operand2 第二个操作数指令格式举例如下:LDR R0,[R1] ;读取R1 地址上的存储器单元内容,执行条件ALBEQ DATAEVEN ;跳转指令,执行条件EQ,即相等跳转到DATAEVENADDS R1,R1,#1 ;加法指令,R1+1=R1 影响CPSR 寄存器,带有SSUBNES R1,R1,#0xD;条件执行减法运算(NE),R1-0xD=>R1,影响CPSR 寄存器,带有S (2)第2个操作数在ARM 指令中,灵活的使用第2个操作数能提高代码效率,第2个操作数的形式如下:#immed_8r常数表达式,该常数必须对应8 位位图,即常数是由一个8 位的常数循环移位偶数位得到。

合法常量0x3FC、0、0xF0000000、200、0xF0000001等都是合法常量。

非法常量0x1FE、511、0xFFFF、0x1010、0xF0000010等都是非法常量。

常数表达式应用举例如下:MOV R0,#1 ;R0=1AND R1,R2,#0x0F ;R2 与0x0F,结果保存在R1LDR R0,[R1],#-4 ;读取R1 地址上的存储器单元内容,且R1=R1-4Rm寄存器方式,在寄存器方式下操作数即为寄存器的数值。

ARM中的ldr指令与adr、ldr伪指令之间的区别

ARM中的ldr指令与adr、ldr伪指令之间的区别

ARM中的ldr指令与adr、ldr伪指令之间的区别ARM 汇编语言中有ldr 指令和ldr、adr 伪指令,他们都可以将标号表达式作为操作数。

区别如下:ldr 指令和adr、ldr 伪指令的区别:ldr 指令属于load- store 指令,用于读取标号地址中的值;adr、ldr 伪指令用于获取标号的地址。

adr 和ldr 伪指令的区别:adr 是获取相对PC 的地址,与程序当前运行的位置相关,是小范围的地址读取伪指令;ldr 是获取绝对地址,绝对地址是在link 的时候确定的,它与程序当前运行位置无关,是大范围读取地址伪指令。

下面通过分析一段代码以及对应的反汇编接过来说明他们的区别。

ldr r0,_startadr r0,_startldr r0,=_start_start:b _start编译的时候设置r0 为0x30000000,下面是反汇编的结果:0x00000000:e59f0004ldr r0,[pc,#4];0xc0x00000004:e28f0000add r0,pc,#0;0x00x00000008:e59f0000ldr r0,[pc,#0];0x100x0000000c:eafffffeb0xc0x00000010:3000000candcc r0,r0,ip这是一条指令,从内存地址_start 的位置装载该地址存放的数据。

在这里_start 是一个标号(是一个相对程序的表达式),汇编程序计算相对于PC 的偏移量,并生成相对于PC 的前索引的指令:ldr r0,[pc,#4]。

指令执行后,r0=0xeafffffe(计算方法:r0 = [pc(0x00000000+8)+4]= [0x0000000c] =。

ARM伪指令之地址读取:ADR ADRL LDR

ARM伪指令之地址读取:ADR ADRL LDR

ARM 伪指令之地址读取:ADR ADRL LDR
1、ADR 伪指令--- 小范围的地址读取
ADR 伪指令将基于PC 相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。

在汇编编译器编译源程序时,ADR 伪指令被编译器替换成一条合适的指令。

通常,编译器用一条ADD 指令或SUB 指令来实现该ADR 伪指令的功能,若不能用一条指令实现,则产生错误,编译失败。

ADR 伪指令格式:ADR{cond} register, expr
地址表达式expr 的取值范围:
当地址值是字节对齐时,其取指范围为: +255 ~255B;
当地址值是字对齐时,其取指范围为: -1020 ~1020B;
2、ADRL 伪指令----中等范围的地址读取
ADRL 伪指令将基于PC 相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中,比ADR 伪指令可以读取更大范围的地址。

在汇编编译器编译源程序时,ADRL 伪指令被编译器替换成两条合适的指令。

若不能用两条指令实现,则产生错误,编译失败。

ADRL 伪指令格式:ADRL{cond} register, expr
地址表达式expr 的取值范围:
当地址值是字节对齐时,其取指范围为: -64K~64K;
当地址值是字对齐时,其取指范围为: -256K~256K;
3、LDR 伪指令-----大范围的地址读取
LDR 伪指令用于加载32 位的立即数或一个地址值到指定寄存器。

在汇编编译源程序时,LDR 伪指令被编译器替换成一条合适的指令。

若加载的常数未超出MOV 或MVN 的范围,则使用MOV 或MVN 指令代替该LDR 伪指令,否。

adr和ldr的区别

adr和ldr的区别
ldr r0,[pc,#0],对应文字池中的地址以及值为:0x00000010:3000000c,因此该伪指令执行后r0的值为0x3000000c。
因此可以看出,不管这段代码将来在什么地方运行,它的结果都是r0=0x3000000c。
由于ldr r0,=_start取得的是_start的绝对地址,这句代码可以在_start标号的绝对位置不变的情况下移动,如使用寄存器pc在程序中可以实现绝对转移。
0x00000008:e59f0000 ldr r0,[pc,#0] ;0x10
0x0000000c:eafffffe b 0xc
0x00000010:3000000c andcc r0,r0,ip
1.ldr r0,_start
这是一条指令,从内存地址_start的位置装载该地址存放的数据。
通过这一点可以判断程序在什么地方运行。U-Boot中那段relocate代码就是通过adr实现当前程序是在RAM中还是FLASH中。
3.ldr r0,地址(也即运行地址)。
这个绝对地址是在链接的时候确定的,它占用2个32bit的空间,一条是指令,另一条是文字池中存放_start的绝对地址。在此例中生成的指令为:
ldr是获取绝对地址,绝对地址是在link的时候确定的,它与程序当前运行位置无关,是大范围读取地址伪指令。
下面通过分析一段代码以及对应的反汇编接过来说明他们的区别。
ldr r0,_start
adr r0,_start
ldr r0,=_start
ARM汇编语言中有ldr指令和ldr、adr伪指令,他们都可以将标号表达式作为操作数。区别如下:
ldr指令和adr、ldr伪指令的区别:ldr指令属于load-store指令,用于读取标号地址中的值;adr、ldr伪指令用于获取标号的地址。

ARM-汇编指令集(总结)

ARM-汇编指令集(总结)

ARM-汇编指令集(总结)ARM汇编指令集指令、伪指令(汇编)指令:是机器码的助记符,经过汇编器编译后,由CPU执⾏。

(汇编)伪指令:⽤来指导指令执⾏,是汇编器的产物,最终不会⽣成机器码。

有两种不同风格的ARM指令1).ARM官⽅的ARM汇编风格:指令⼀般⽤⼤写,Windows中的IDE开发环境。

2).GNU风格的ARM汇编:指令⼀般⽤⼩写。

ARM汇编的特点1. LDR/STR架构1).ARM采⽤RISC架构,CPU本⾝不能直接读取内存,⽽需要先将内存中内容加载⼊CPU中通⽤寄存器中才能被CPU处理。

2).ldr(load register)指令将内存内容加载⼊通⽤寄存器。

3).str(store register)指令将寄存器内容存⼊内存空间中。

4).ldr/str组合⽤来实现 ARM CPU和内存数据交换。

2. ⾄此8种寻址⽅式1).寄存器寻址mov r1, r2。

2).⽴即(⽴即数)寻址 mov r0, #0xFF00。

3).寄存器移位寻址 mov r0, r1, lsl #3。

4).寄存器间接寻址 ldr r1, [r2] 表⽰内存,内存地址存在r2这个寄存器中,把内存地址⾥的值给r1。

5).基址变址寻址ldr r1, [r2, #4]内存地址在r2+4⾥⾯。

6).多寄存器寻址 ldmia r1!, {r2-r7, r12}⼀次访问多个寄存器。

7).堆栈寻址 stmfd sp!, {r2-r7, lr}。

8).相对寻址 beq flag。

3. 指令后缀同⼀指令经常附带不同后缀,变成不同的指令。

经常使⽤的后缀有:B(byte)功能不变,操作长度变为8位H(half word)功能不变,长度变为16位S(signed)功能不变,操作数变为有符号如 ldr ldrb ldrh ldrsb ldrshS(S标志)功能不变,影响CPSR标志位如 mov和movs movs r0, #04. 条件执⾏后缀条件后缀是否成⽴取决于当前代码的前⾯的代码。

ARM汇编指令对比记忆(整理)

ARM汇编指令对比记忆(整理)

ARM汇编指令对比记忆(整理)1.RichardBlum,ProfeionalAemblyLanguage一.Linu某汇编行结构Linu某ARM汇编中,任何以冒号结尾的标识符都被认为是一个标号,而不一定非要在一行的开始。

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

.ection.te某t,“某”1.LDRLDRR0,=0某3FF5000;伪指令,把0某3FF5000这个地址送给R0LDRR0,0某FF;把立即数0某ff送给R0LDRR0,=&FF;&相当于0某BICR0,R0,#11;.#表示立即数,%表示二进制LDRR1,=0某3ff5000;伪指令R1=0某3FF5000LDRR1,0某3ff5000;存储器访问指令R1=[0某3ff5000]2.adr与ldr比较adrr0,InitSytem;ldrr1,=InitSytem;伪指令adrr0,InitSytem编译时汇编成:ubr0,PC,#offettoInitSytemLDRr1,=InitSytem,这种方式读取的地址值在连接时已经被固定了,这种代码不是位置无关的。

遇到LDR伪指令时,汇编编译器将该地址值保存到一个缓冲区(literalpool)中,然后将该LDR伪指令处理成一条基于PC到该数据缓冲区单元的LDR指令,从而将该地址值读取到寄存器总,这时,要求该数据缓冲区到PC的距离小于4KB。

如果该目标地址值为一个外部地址值或者不在本数据段内,则汇编译器在目标文件中插入一个地址重定位伪操作,当连接器进行连接时生成该地址值。

LDRr1,=InitSytem汇编成:LDRR1,[PC,#offettoLitpool1]------------------------------------------------------adr用来加载地址,例如adrr0,var1ldr用来加载地址处的内容,例如ldrr0,var1上面的这种语法只能从.te某t段中加载但ldrr0,=var1可从任意段中加载地址ldr有伪指令和非伪指令,伪指令后面的立即数前加=ADR在编译时会被替换成一条add或者ub指令,如果替换不了则报错。

ARM汇编中的LDR指令总结

ARM汇编中的LDR指令总结

ARM汇编中的LDR指令总结
ARM是RISC结构,数据从内存到CPU之间的移动只能通过L/S 指令来完成,也就是ldr/str指令。

比如想把数据从内存中某处读取到寄存器中,只能使用ldr
比如:
ldr r0, 0x12345678
就是把0x12345678这个地址中的值存放到r0中。

而mov不能干这个活,mov只能在寄存器之间移动数据,或者把立即数移动到寄存器中,这个和x86这种CISC架构的芯片区别最大的地方。

x86中没有ldr这种指令,因为x86的mov指令可以将数据从内存中移动到寄存器中。

另外还有一个就是ldr伪指令,虽然ldr伪指令和ARM的ldr指令很像,但是作用不太一样。

ldr伪指令可以在立即数前加上=,以表示把一个地址写到某寄存器中,比如:
ldr r0, =0x12345678
这样,就把0x12345678这个地址写到r0中了。

所以,ldr伪指令和mov是比较相似的。

只不过mov指令限制了立即数的长度为8位,也就是不能超过512。

而ldr伪指令没有这个限制。

如果使用ldr 伪指令时,后面跟的立即数没有超过8位,那么在实际汇编的时候该ldr伪指令是被转换为mov指令的。

arm汇编数据加载指令

arm汇编数据加载指令

arm汇编数据加载指令ARM汇编是一种常用的低级编程语言,用于编写嵌入式系统和移动设备的底层程序。

在ARM汇编中,数据加载是一项常见的操作,用于将数据从内存中加载到寄存器中进行处理或计算。

本文将介绍几种常用的ARM汇编数据加载指令及其使用方法。

一、LDR指令LDR指令用于将数据从内存加载到寄存器中。

它有多种形式,根据操作数的不同可以分为三种情况:立即数加载、寄存器加载和寄存器间接加载。

1. 立即数加载LDR指令的立即数加载形式使用一个立即数作为操作数,将该立即数加载到寄存器中。

例如:LDR R0, =0x12345678这条指令将立即数0x12345678加载到R0寄存器中。

2. 寄存器加载LDR指令的寄存器加载形式使用一个寄存器作为操作数,将该寄存器中存储的数据加载到目标寄存器中。

例如:LDR R1, [R0]这条指令将R0寄存器中存储的数据加载到R1寄存器中。

3. 寄存器间接加载LDR指令的寄存器间接加载形式使用一个寄存器和一个偏移量作为操作数,将寄存器中存储的内存地址加上偏移量后的数据加载到目标寄存器中。

例如:LDR R2, [R1, #4]这条指令将R1寄存器中存储的内存地址加上偏移量4后的数据加载到R2寄存器中。

二、LDRB指令LDRB指令用于将字节数据从内存加载到寄存器中。

与LDR指令类似,LDRB指令也有立即数加载、寄存器加载和寄存器间接加载三种形式。

1. 立即数加载LDRB指令的立即数加载形式使用一个立即数作为操作数,将该立即数加载到寄存器中。

例如:LDRB R3, =0xFF这条指令将立即数0xFF加载到R3寄存器中。

2. 寄存器加载LDRB指令的寄存器加载形式使用一个寄存器作为操作数,将该寄存器中存储的字节数据加载到目标寄存器的低8位中。

例如:LDRB R4, [R2]这条指令将R2寄存器中存储的字节数据加载到R4寄存器的低8位中。

3. 寄存器间接加载LDRB指令的寄存器间接加载形式使用一个寄存器和一个偏移量作为操作数,将寄存器中存储的内存地址加上偏移量后的字节数据加载到目标寄存器的低8位中。

arm汇编 内存操作函数

arm汇编 内存操作函数

arm汇编内存操作函数在ARM汇编语言中,有很多内存操作函数可用来对内存进行读写和操作。

以下是一些常用的内存操作函数:1. LDR和STR:用于从内存中加载(LDR)和存储(STR)数据。

例如,LDR r0, [r1]将从内存地址r1处读取数据,并将其放入寄存器r0中;STR r0, [r1]将寄存器r0中的数据存储到内存地址r1处。

2. LDM 和STM:用于从内存中加载多个寄存器(LDM)和存储多个寄存器(STM)。

例如,LDM r0, {r1-r3}将从内存地址r0处加载连续的三个字,并将它们分别放入寄存器r1,r2和r3中;STM r0, {r1-r3}将寄存器r1,r2和r3中的数据存储到连续的三个字的内存地址r0处。

3. LDRB和STRB:类似于LDR和STR,但用于读写单字节数据。

例如,LDRB r0, [r1]将从内存地址r1处读取一个字节的数据,并将其放入寄存器r0中;STRB r0, [r1]将寄存器r0中的一个字节的数据存储到内存地址r1处。

4. LDRH和STRH:类似于LDR和STR,但用于读写半字(16位)数据。

例如,LDRH r0, [r1]将从内存地址r1处读取一个半字的数据,并将其放入寄存器r0中;STRH r0, [r1]将寄存器r0中的一个半字的数据存储到内存地址r1处。

5. LDRD和STRD:类似于LDR和STR,但用于读写双字(32位)数据。

例如,LDRD r0, r1, [r2]将从内存地址r2处读取两个字的数据,并将它们分别放入寄存器r0和r1中;STRD r0, r1, [r2]将寄存器r0和r1中的数据存储到内存地址r2处。

6. LDRSB和LDRSH:用于将带符号的单字节(LDRSB)或带符号的半字(LDRSH)数据扩展为32位寄存器中的字长数据。

这些函数提供了灵活的内存操作方式,可以根据需要选择合适的函数进行数据读写和操作。

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

ARM汇编中的LDR及ADR的区别及其在UBOOT中
的应用
我在看U-BOOT 的lowlevel_init.S 文件时看到以下代码:lowlevel_init:ldr
r0, =SMRDATAldr r1, _TEXT_BASEsub r0, r0, r1ldr r1, =BWSCONadd r2, r0, #13*40:ldr r3, [r0], #4str r3, [r1], #4cmp r2, r0bne 0bmov pc, lr
这段代码实现了U-BOOT 的内存控制器部分的寄存器初始化,一共13 个寄
存器,对U-BOOT 来最重要的就是SDRAM 的初始化,显然没有这部分代码,
当U-BOOT 从NAND FLASH 中启动的时候,START.S 文件是无法完成代码的relocate 的。

因为SDRAM 没初始化,用不了。

要理解这段代码主要是搞清楚LDR 的两种用法。

ldr r0, =SMRDATA 的作用是让r0 等于U-BOOT 编译时已经确定下来的SMRDATA 这块内存缓冲池的起始地址。

ldr r1, _TEXT_BASE 的作用则是让r1
等于_TEXT_BASE 这个标号所在的内存里面的内容,也就是TEXT_BASE。

对于MINI2440 开发板来说这个值等于TEXT_BASE =
0x33F80000(\board\samsung\mini2440\config.mk)这个地址是由于
TEXT_BASE 实际的地址现在应该是FLASH 的0 地址(或者内部4KSRAM 的0
地址),所以第三条指令sub r0, r0, r1 ,实现了计算SMRDATA 当前在arm 地
址空间里的实际访问地址。

接下去就是通过ldr r3, [r0], #4 ;从r0 这个地址里
取一个32bit 的数据,放到r3,并将r0+4,指向下一个内存池里的数据。

str r3, [r1], #4 ;这条指令实现了把r3 里的数据赋值给r1 所标示的地址。

r1 的地址通
过下面这几句实现。

以此配置完从0x48000000 开始的CPU 内部寄存器的值。

这样SDRAM 就开始工作了。

以后就是正常访问0x30000000 开始的地址空间
了。

#define BWSCON 0x48000000ldr r1, =BWSCON /* Bus Width Status。

相关文档
最新文档