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

合集下载

arm汇编指令积累

arm汇编指令积累

arm汇编指令积累arm 汇编指令积累2011-03-26 14:40 1115人阅读评论(0) 收藏举报一、ldr的确是个复杂的指令,现总结一下:首先要判断我们用的是ldr arm指令还是伪指令。

当我们用的是arm指令时,它的作用不是向寄存器里加载立即数,而是将某个地址里的内容加载到寄存器。

而伪指令ldr的作用就是向寄存器里加载立即数。

(1) ldr伪指令ldr伪指令的格式是 ldr Rn, =expr其中,expr是要加载到Rn中的内容,一般可以是立即数或者label。

如果expr可以用8bit数据向右移偶数位得到,那么这条伪指令就被编译器翻译成mov指令。

具体的移位情况可以去查阅资料。

反之如果立即数很大,超过了12bit的表示范畴,那么就不能用一条mov指令了,毕竟arm指令最大只有32bit的空间可用(RISC的arm所有的指令长度是一致的,效率较高,当然我们并不关心16bit的thumb 指令)。

如果不能用一条32bit的指令乘下来,那么就只能另辟蹊径了,新开一段缓冲,将立即数expr放到里面,然后将其地址(暂时标记为addr)拿来使用:ldr Rn, addrxxx (xxx就是expr)xxx由于编译器一般来说新安排的存储这个立即数expr的缓冲的位置是在相应代码的附近(这个应该可以控制,好像是使用.ltorg伪指令)。

我们从addr地址加载数据到Rn不就可以了。

(2)ldr arm 指令就是将一个地址的内容加载到寄存器。

不能用mov,因为arm里的mov只是在寄存器之间传输数据,不支持在寄出器和memory之间传递数据。

因此就出现了ldr/str指令。

如ldr Rn, addr,注意这里的addr的值也是有限制的。

这个label应该距离当前指令的距离不超过4k。

因为我们知道label在具体使用的时候应该是被翻译成了相对偏移,如果这个label长度不超过12bit,那么就不应超过4k,我们可以这样做:ldr pc, _start_armboot_start_armboot: .word arm_startboot这样label _start_armboot就在指令下方,因此肯定是合法的。

ARM汇编语言指令总结

ARM汇编语言指令总结

ARM汇编语⾔指令总结ARM处理器有9种寻址⽅式:1、寄存器寻址,2、⽴即寻址,3、寄存器器移位寻址,4、寄存器间接寻址,5、基址寻址,6、多寄存器寻址,7、堆栈寻址,8、块拷贝寻址,9、相对寻址。

ARM指令集:ARM指令基本格式如下:{}{S} ,{,}其中<>的内容是必须的,{}的内容是可选的。

OPCODE指令助记符,COND执⾏条件,S是否影响CPSR中的值,Rd⽬标寄存器,Rn 第⼀个操作数的寄存器,OPERAND2第⼆个操作数。

灵活的使⽤第2个操作数“operand2”能够提⾼代码效率。

它有如下的形式:1)#immed_8r ——常数表达式;2)Rm——寄存器⽅式;3)Rm,shift——寄存器移位⽅式(ASR算术右移,LSL逻辑左移,LSR 逻辑右移,ROR循环右移,RRX带扩展的右移1位)。

COND执⾏条件:下⾯介绍ARM指令:1、存储器访问指令。

存储器访问指令分为单寄存器操作指令和多寄存器操作指令。

单寄存器操作指令LDR/STR指令⽤于对内存变量的访问、内存缓冲区数据的访问、查表、外围部件的控制操作等。

LDR:从内存到寄存器,加载数据。

STR:将寄存器的数据存储到内存。

LDRB操作字节,LDRH操作半字,LDRSH操作有符号半字。

多寄存器操作指令LDM为加载多个寄存器;STM为存储多个寄存器。

允许⼀条指令传送16个寄存器的任何⼦集或所有寄存器。

它们主要⽤于现场保护、数据复制、常数传递等。

进⾏数据复制时,先设置好源数据指针和⽬标指针,然后使⽤块拷贝寻址指令LDMIA/STMIA(传送后地址加4)、LDMIB/STMIB(传送前地址加4)、LDMDA/STMDA(传送后地址减4)、LDMDB/STMDB(传送前地址减4)进⾏读取和存储。

进⾏堆栈操作操作时,要先设置堆栈指针(SP),然后使⽤堆栈寻址指令STMFD/LDMFD(满递减堆栈)、STMED/LDMED(空递减堆栈)、STMFA/LDMFA(满递增堆栈)和STMEA/LDMEA(空递增堆栈)实现堆栈操作。

ARM常用汇编指令

ARM常用汇编指令

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中的汇编指令Arm指令,32位的指令集,⼀共有16条的基本指令,每条指令都可以按条件执⾏, 指令都是32bit的,⾼四位是条件码[31:28],Thumb指令,16位的指令集,执⾏效率⽐arm指令集要低,但是节省了系统的存储空间,兼容了16位的数据总线宽度的应⽤体系。

thumb指令,相⽐较与arm代码,储存器的功耗也较低。

thumb指令,基本都是⽆条件的,⼀共有18条基本指令,全部指令都是16bit。

Thumb-2指令,由16bit、32bit的指令混合组成,⼀共有16条基本指令,BIC:ARM指令,对某些位,清零。

先取反再相与。

asm("BIC r2, r2, #0x1f"); ##对R2的低5位清零。

ORR:ARM指令,逻辑或asm("ORR r2, r2, #0x10"); ##R2逻辑与0x10。

MRS:asm("MRS r2, CPSR"); ##将CPSR的值加载到R2中。

MSR:asm("MSR CPSR, r2"); ##将R2的值加载到CPSR中。

asm(" SWI 0x0"); ##跳转到软件中断函数,并转换为SVC模式。

LDR:{条件}⽬的寄存器存储器寄存器。

将存储地址所指的4个字节数据传送到寄存器,其中寻址⽅式会有很多种。

asm("ldr r0,=0xddeeaabb"); ##在这⾥ldr是⼀个伪指令,相当于move指令。

asm("ldr r0, [r1]"); ##将存储器地址为r1的⼀个字的数据加载到r0中。

MRC与MCR:在处理器寄存器与协处理器寄存器之间交换数据。

MRC {cond} coproc, opcode1, Rd, CRn, CRm {,opcode2}asm("mrc p15,0,r0,c1,c1,0"); ##在CRn, CRm均为c1, opcode均为0时,表⽰SCR(Secure Configuration Register),表⽰将c1的值赋值给r0.asm("mcr p15,0,r0,c1,c1,0"); ##将r0的值赋值给c1.asm("mcr p15,0,r0,c12,c0,0"); ##将r0的值赋值给c12,此时c12表⽰VBAR,Vector Base Address Register,存放异常时的⼊⼝地址。

ARM的汇编指令讲解

ARM的汇编指令讲解

汇编知识点的要求:1、能看的懂2、可以做修改3、不需要用汇编直接编写程序汇编代码的应用场合:1、ARM的启动代码必须要汇编,如:uboot最开始初始化硬件的代码2、内核在最开始初始化的位置。

一、ARM汇编指令的编码格式1、编码格式ARM汇编指令编译成机器码以后,机器码的长度是32bits,这32bits的编码有一个固定的格式。

不同ARM 汇编指令,编码格式不同。

2、举例C:if(a==10)a++;elsea--;汇编1:CMP R0, #10;ADDEQ R0,R0,#1SUBNE R0,R0,#1汇编2SUBS R1, R0, #10; //S ---运算的结果会影响条件码标志位:CPSR:NZCVADDEQ R0,R0,#1SUBNE R0,R0,#1提示:空指令NOP,实际上是占用CPU的时间,但是执行后,没有什么意义。

NOP ---- MOV R0,R03、条件码标识10 -10Z = 1C = 0N = 0V = 0=================================================================================二、ARM的寻址方式1、立即数寻址操作数,有立即数。

ADD R0,R0,#1MOV R1,#10ORR R1,R1,#0xf @ R1=R1 | 0xfBIC R1,R1,#0xf @R1 = R1&(~(0xf))错误:ADD R1,#1,#2注意:立即数合法的条件在ARM汇编指令中,并不是所有的立即数,立即数是有一定的限制的。

什么样的立即数是合法的???1、如果一个立即数是小于256的(即该立即数是8bits以内的,0~255),该立即数是合法的。

2、如果一个立即数是大于等于256,该立即数经过循环左移偶数位,可以得到一个小于256的数,则该立即数合法。

256 = 0x100 ------→左移20位0x10000000----→左移4 0x1 合法0x111 非法0x102 非法0x104 合法0xfff0xff000x120000x4500000xab原因:在数据处理指令编码的时候,立即数用12bits来表示:高4bits:循环左移左移偶数位除以2低8bits:循环左移后的结果。

常用ARM指令汇总

常用ARM指令汇总

常用ARM指令集及汇编一、ARM处理器的寻址方式二、指令集学习(一)ARM指令集1.指令格式2.条件码3.ARM存储器访问指令1)LDR/ STR-加载/ 存储指令2)LDM/ STM-多寄存器加载/ 存储指令3)SWP-寄存器和存储器交换指令4.ARM数据处理指令1)数据传送指令a)MOV-数据传送指令b)MVN-数据非传送指令2)算术逻辑运算指令a)ADD-加法运算指令b)SUB-减法运算指令c)RSB-逆向减法指令d)ADC-带进位加法指令e)SBC-带进位减法指令f)RSC-带进位逆向减法指令g)AND-逻辑“与”h)ORR-逻辑“或”i)EOR-逻辑“异或”j)BIC-位清除指令3)比较指令a)CMP-比较指令b)CMN-负数比较指令c)TST-位测试指令d)TEQ-相等测试指令4)乘法指令a)MUL-32位乘法指令b)MLA-32位乘加指令c)UMULL-64位无符号乘法指令d)UMLAL-64位无符号乘加指令e)SMULL-64位有符号乘法指令f)SMLAL-64位有符号乘加指令5.ARM分支指令1)B-分支指令2)BL-带连接的分支指令3)BX-带状态切换的分支指令6.ARM协处理器指令1)CDP-协处理器数据操作指令2)LDC-协处理器数据读取指令3)STC-协处理器数据写入指令4)MCR-ARM处理器到协处理器的数据传送指令5)MRC-协处理器到ARM处理器的数据传送指令7.ARM杂项指令1)SWI-软中断指令2)MRS-读状态寄存器指令3)MSR-写状态寄存器指令8.ARM伪指令1)ADR-小范围的地址读取伪指令2)ADRL-中等范围的地址读取伪指令3)LDR-大范围的地址读取伪指令4)NOP-空操作伪指令(二)Thumb指令集1.Thumb指令集和ARM指令集的区别2.Thumb存储器访问指令1)LDR/ STR-加载/ 存储指令2)PUSH/ POP-寄存器入栈 / 出栈指令3)LDMIA/ STMIA-多寄存器加载/ 存储指令3.Thumb数据处理指令1)数据传送指令a)MOV-数据传送指令b)MVN-数据非传送指令c)NEG-数据取负指令2)算术逻辑运算指令a)ADD-加法运算指令b)SUB-减法运算指令c)ADC-带进位加法指令d)SBC-带进位减法指令e)MUL-乘法运算指令f)AND-逻辑“与”g)ORR-逻辑“或”h)EOR-逻辑“异或”i)BIC-位清除指令j)ASR-算术右移指令k)LSL-逻辑左移指令l)LSR-逻辑右移指令m)ROR-循环右移指令3)比较指令a)CMP-比较指令b)CMN-负数比较指令c)TST-位测试指令4.Thumb分支指令1)B-分支指令2)BL-带连接的分支指令3)BX-带状态切换的分支指令5.Thumb杂项指令1)SWI-软中断指令6.Thumb伪指令1)ADR-小范围的地址读取伪指令2)LDR-大范围的地址读取伪指令3)NOP-空操作伪指令。

arm汇编指令笔记.

arm汇编指令笔记.

ARM assembler guide DUI0068是一个RISC指令结构,因为有一个加载存储结构。

只有load和store可以读取内存。

ARM的处理器模式可以全部大写或小写,不能混标志符表示一个地址常量的定义格式:1230x1C2_1001ARM编译、链接后最终生成一个ELF格式(Executable and Linking Format)的可执行文件(后缀.axf)ELF中是分section部分的,一个ELF section在汇编中定义一个section使用AREA指令。

ENTRY指令指示汇编代码第一条要执行的指令。

start是一个标识符,代表一个地址。

结束的方式是产生一个软件中断,把控制权交给调试器。

END指令指示汇编的结束使用cmd进行调试:Microsoft Windows XP [版本5.1.2600](C) 版权所有1985-2001 Microsoft Corp.C:\Documents and Settings\Administrator>cd D:\Program Files\ARM\ADSv1_2\BinC:\Documents and Settings\Administrator>D;'D' 不是内部或外部命令,也不是可运行的程序或批处理文件。

C:\Documents and Settings\Administrator>D:D:\Program Files\ARM\ADSv1_2\Bin>armsd E:\dsparm\pxa270\project\armex\__image.ax fARM Source-level Debugger, ADS1.2 [Build 805]Software supplied by: Team-EFASoftware supplied by: Team-EFAARM7TDMI, BIU, Little endian, Semihosting, Debug Comms Channel, 4GB, Mapfile, Timer, Profiler, Tube, Millisecond [20000 cycles_per_millisecond], Pagetables,IntCtrl, Tracer, RDI CodesequencesObject program file E:\dsparm\pxa270\project\armex\__image.axfarmsd: helphelp [<keyword>]Display help information on one of the following commands:Registers Fpregisters Coproc CRegisters CREGDefCWrite Step Istep Examine ListQuit Obey Go Break Unbreak Watch UNWatch Print CONtext OUtIN WHere BAcktrace Variable SYmbols LSym LEt Arguments LAnguage HelpType CAll WHIle ALias LOadLOG RELoad REAdsyms FInd PUtfile GEtfile LOCalvar COMment PAuse LOADConfig SElectconfig LISTConfig LOADAgent PROfon PROFOFf PROFClear PROFWrite CCin CCOut PROCessor SYS SETregister TRacetrigger TRACEExtent TRACEWrite TRACEStart TRACESTOp TRACEFlushHELP * gives helps on all available commands. To print the help use the LOGcommand to record the help output into a file & print the file.If the first character of a line is the '!' character the rest of the commandline is executed by a call to system(). If the first character of a line isthe '|' character the rest of the line is a treated as a comment.Note that this help is not intended to replace the printed manual whichexplains ARMSD in much greater detail.armsd: LOG** Error: No log filearmsd: stepStep completed at PC = 0x000080040x00008004: 0xe3a01003 .... : mov r1,#3armsd: Registerr0 = 0x0000000a r1 = 0x00000000 r2 = 0x00000000 r3 = 0x00000000r4 = 0x00000000 r5 = 0x00000000 r6 = 0x00000000 r7 = 0x00000000r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 r11 = 0x00000000r12 = 0x00000000 r13 = 0x00000000 r14 = 0x00000000pc = 0x00008004 cpsr = %nzcvqIFt_SVC spsr = %nzcvqift_Reserved_00armsd: stepStep completed at PC = 0x000080080x00008008: 0xe0800001 .... : add r0,r0,r1armsd: Registerr0 = 0x0000000a r1 = 0x00000003r2 = 0x00000000 r3 = 0x00000000r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 r11 = 0x00000000 r12 = 0x00000000 r13 = 0x00000000 r14 = 0x00000000pc = 0x00008008 cpsr = %nzcvqIFt_SVC spsr = %nzcvqift_Reserved_00 armsd: stepStep completed at PC = 0x0000800c0x0000800c: 0xe3a00018 .... : mov r0,#0x18armsd: LOG** Error: No log filearmsd: Registerr0 = 0x0000000d r1 = 0x00000003 r2 = 0x00000000 r3 = 0x00000000 r4 = 0x00000000 r5 = 0x00000000 r6 = 0x00000000 r7 = 0x00000000 r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 r11 = 0x00000000 r12 = 0x00000000 r13 = 0x00000000 r14 = 0x00000000pc = 0x0000800c cpsr = %nzcvqIFt_SVC spsr = %nzcvqift_Reserved_00 armsd: stepStep completed at PC = 0x000080100x00008010: 0xe59f1000 .... : ldr r1,0x00008018 ; = #0x00020026 armsd: Registerr0 = 0x00000018 r1 = 0x00000003 r2 = 0x00000000 r3 = 0x00000000 r4 = 0x00000000 r5 = 0x00000000 r6 = 0x00000000 r7 = 0x00000000 r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 r11 = 0x00000000 r12 = 0x00000000 r13 = 0x00000000 r14 = 0x00000000pc = 0x00008010 cpsr = %nzcvqIFt_SVC spsr = %nzcvqift_Reserved_00 armsd: stepStep completed at PC = 0x000080140x00008014: 0xef123456 V4.. : swi 0x123456armsd: Registerr0 = 0x00000018 r1 = 0x00020026 r2 = 0x00000000 r3 = 0x00000000 r4 = 0x00000000 r5 = 0x00000000 r6 = 0x00000000 r7 = 0x00000000 r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 r11 = 0x00000000 r12 = 0x00000000 r13 = 0x00000000 r14 = 0x00000000pc = 0x00008014 cpsr = %nzcvqIFt_SVC spsr = %nzcvqift_Reserved_00 armsd: stepProgram terminated normally at PC = 0x000080140x00008014: 0xef123456 V4.. : swi 0x123456armsd: Registerr0 = 0x00000018 r1 = 0x00020026 r2 = 0x00000000 r3 = 0x00000000 r4 = 0x00000000 r5 = 0x00000000 r6 = 0x00000000 r7 = 0x00000000 r8 = 0x00000000 r9 = 0x00000000 r10 = 0x00000000 r11 = 0x00000000 r12 = 0x00000000 r13 = 0x00000000 r14 = 0x00000000pc = 0x00008014 cpsr = %nzcvqIFt_SVC spsr = %nzcvqift_Reserved_00 armsd: quitQuittingD:\Program Files\ARM\ADSv1_2\Bin>使用armsd调试有点像微机原理上调试汇编,爽!MOV叫指令,常数范围是0-255LDR叫伪指令都是将常数放到Reg中#和FIELD指令是一样的符号在汇编程序中代表一个地址,可以用在指令中,汇编程序经过汇编器的处理之后,所有的符号都被替换成它所代表的地址值。

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汇编指令,可以参考相关的教程和手册,并进行实际操作。

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

参考资料:1. Richard Blum,Professional Assembly Language2. GNU ARM 汇编快速入门,/u/31996/showart.php?id=3261463. ARM GNU 汇编伪指令简介,/jb8164/archive/2008/01/22/41661.aspx4. GNU汇编使用经验,/u1/37614/showart_390095.html5. GNU的编译器和开发工具,/blog-htm-do-showone-uid-34335-itemid-81387-type-blog.html6. 用GNU工具开发基于ARM的嵌入式系统,/liren0@126/blog/static/32897598200821211144696/7. objcopy命令介绍,/junhua198310/archive/2007/06/27/1669545.aspx从网上找到一些关于ARM伪指令的资料,现整理如下:一. 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 program1. LDRLDR R0, =0X3FF5000 ;伪指令,把0X3FF5000这个地址送给R0LDR R0, 0XFF ; 把立即数0xff送给R0LDR R0, =&FF ; &相当于0XBIC R0, R0, #%1011 ;.#表示立即数,%表示二进制LDR R1, =0x3ff5000 ;伪指令 R1=0X3FF5000LDR R1, 0x3ff5000 ;存储器访问指令 R1= [0x3ff5000]2. adr与ldr比较adr r0, InitSystem ;ldr r1, =InitSystem ;伪指令adr r0,InitSystem 编译时汇编成:sub r0,PC,#offset to InitSystemLDR r1,=InitSystem ,这种方式读取的地址值在连接时已经被固定了,这种代码不是位置无关的。

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

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

LDR r1,=InitSystem 汇编成:LDR R1,[PC,#offset to Litpool1]------------------------------------------------------adr用来加载地址,例如adr r0,var1ldr用来加载地址处的内容,例如ldr r0,var1上面的这种语法只能从.text段中加载但ldr r0,=var1可从任意段中加载地址ldr有伪指令和非伪指令,伪指令后面的立即数前加=ADR在编译时会被替换成一条add或者sub指令,如果替换不了则报错。

相对PC寻址ADRL会被替换成两条指令,替换不了报错误。

相对PC或者积存器寻址这两条指令依据立即数的对齐方式不同,允许的立即数范围也不同。

LDR则是产生文字池的方式加载常量,基于PC的相对寻址,专用加载32bit立即数.通过反汇编可以很容易看出LDR和ADR区别:假设入口点地址为0x8000AREA LDRlabel, CODE, READONLYENTRY ; Mark first instruction to executestartBL func1 ; Branch to first subroutinestopMOV r0, #0x18 ; angel_SWIreason_ReportExceptionLDR r1, =0x20026 ; ADP_Stopped_ApplicationExitLDR r1,=0xffSWI 0x123456 ; ARM semihosting SWIfunc1LDR r0, =start ; => LDR R0,[PC, #offset to Litpool 1]ADR r2,startLDR r1, =Darea +12 ; => LDR R1,[PC, #offset to Litpool 1]ADR r3,Darea+12MOV pc,lr ; ReturnLTORG ; Literal Pool 1Darea SPACE 8000 ; Clears a 8000 byte area of memory,; starting at the current location,; to zero.END反汇编后:start [0xeb000003] bl func1stop [0xe3a00018] mov r0,#0x1800008008 [0xe59f1018] ldr r1,0x00008028 ; = #0x00020026 0000800c [0xe3a010ff] mov r1,#0xff00008010 [0xef123456] swi 0x123456func1 [0xe59f0010] ldr r0,0x0000802c ; = #0x0000800000008018 [0xe24f2020] sub r2,pc,#0x20 ; #0x80000000801c [0xe59f100c] ldr r1,0x00008030 ; = #0x00008040 00008020 [0xe28f3018] add r3,pc,#0x18 ; #0x804000008024 [0xe1a0f00e] mov pc,r1400008028 [0x00020026] dcd 0x00020026&...0000802c [0x00008000] dcd 0x00008000....00008030 [0x00008040] dcd 0x00008040@...Darea [0x00000000] dcd 0x00000000....00008038 [0x00000000] dcd 0x00000000....0000803c [0x00000000] dcd 0x00000000....00008040 [0x00000000] dcd 0x00000000....00008044 [0x00000000] dcd 0x00000000....……….3. MOVMOV加载8位立即数8位立即数即第2操作数,必须可由一个8位常数循环移位偶数位得到,如0xf0000000,0xf00000001都是合法的4. 数据回写例如:ldr r0,[r1]!stmdb sp!,{r0,r4}!用于前索引方式中表示数据回写,例如:ldr r0,[r1,#4]!后索引方式不用!, 数据始终回写,例如:ldr r0,[r1],#4对堆栈方式中用!, 表示堆栈自动增加或者减少访问内存的LDR/STR指令索引方式ldr r0,[r1,#4]前索引, 先加ldr r0,[r1],#4后索引, 后加5. DCD和SPACEDCD分配一个地址并初始化为指定的表达式如 DCD 0x8000就是分配一个32位的地址,其内容是0x8000如果用上标号label,那么这个label相当于一个变量,如label DCD 0X8000这样引用label就是使用了0x8000这个数值。

SPACE分配一段指定长度的内存空间并初始化为0如label SPACE 0x8000就是分配一段长度为0x8000的空间,并初始化为0Data1 DCD 1,2,3Data2 SPACE 12反汇编后的结果:Data1 [0x00000001] dcd 0x00000001 ....00008040 [0x00000002] dcd 0x00000002 ....00008044 [0x00000003] dcd 0x00000003 ....Data2 [0x00000000] dcd 0x00000000 ....0000804c [0x00000000] dcd 0x00000000 ....00008050 [0x00000000] dcd 0x00000000 ....6. LTORG与LDRLTORG是与LDR联合使用的literal pool,可以在函数尾部声明, 这样相对PC偏移最少, 如果不用LTORG, 则编译器自动在(整个)程序末尾声名,但这样偏移有可能太大而编译不通过.ARM立即数,LDR和MOV的区别Mov 是把立即数赋给一个寄存器,但对立即数的范围有要求。

只能是由8bit 连续有效位通过偶数次移位能得到的数。

如果立即数超出这个范围,就没办法用一条MOV指令给寄存器赋值。

LDR除了普通的读数之外,也有给寄存器赋立即数的功能。

你只要写LDR R0,=0xabcdef它没有立即数范围的限制。

因为这是一条伪指令。

如果立即数在MOV的要求内,那就用一条汇编来实现。

如果不在Mov的范围内,就用其它方式实现,如变成两条指令,或从PC偏移地址读一个32位数给寄存器。

MOV是从一个寄存器或者移位的寄存器或者立即数的值传递到另外一个寄存器从本质上是寄存器到寄存器的传递,为什么会有立即数,其实也是有限制的立即数,不是所有立即数都可以传递的这个立即数要符合一个8位数循环右移偶数位的取值原因是,MOV本身就是一条32bit指令,除了指令码本身,它不可能再带一个可以表示32bit的数字,所以用了其中的12bit来表示立即数,其中4bit表示移位的位数(循环右移,且数值x2),8bit用来表示要移位的一个基数。

还有一点是关于ldr的,其实ldr可以装载一个32bit立即数的说法并不确切,因为实际上并不是这一条语句装载了一个32bit立即数,比如ldr r1,=0x12345678其实真正的汇编代码是将某个地址的值传递给r1,就是说需要一个地址存放0x12345678这个立即数,实际上可以看作是一条伪指令而且如果这个立即数可以用mov指令的形式来表达,会被编译器实际用mov 来代替比如:ldr r1,=0x10会变成mov r1,#0x10ARM是RISC结构,数据从内存到CPU之间的移动只能通过L/S指令来完成,也就是ldr/str指令。

相关文档
最新文档