您的位置 首页 报告

说说ARM汇编的LDR伪指令

我们知道ARMCPU中有一条被广泛使用的指令LDR,它主要是用来从存储器(确切地说是地址空间)中装载数据到通用寄存器。但不论是ARMASM还是G…

咱们知道ARM CPU中有一条被广泛运用的指令LDR,它主要是用来从存储器(切当地说是地址空间)中装载数据到通用寄存器。但不论是ARMASM仍是GNU ARM AS,都供给了一条与之同名的伪指令LDR,而在实践中运用该伪指令的状况也较多,那他们有什么不同呢?下面我谈谈我的了解。

因为我运用GNU东西链,所以以下的内容都以GNU AS的ARM语法为准。

LDR伪指令的语法方式如下:
LDR , =

这个常量表达式中能够包括Label(在ARM汇编中Label会在衔接时解说为一个常数),且其间的常数前不加#符号。

典范demo.s:

.equ STACK_BASE, 0x0c002000
.equ STACK_SIZE, 0x00001000

.text
ldr sp, = STACK_BASE
ldr sl, = STACK_BASE – STACK_SIZE
ldr pc, = entry

这是一个合法的汇编文件,它把仓库基址设为0x0c002000,栈限设为0x0c001000,然后跳到entry所标识的C程序中履行。

下面咱们假定符号“entry”的地址为0x0c000000。

咱们假如把上面代码写成:

.text
mov sp, #0x0c002000
mov sl, #0x0c001000
mov pc, #0x0c000000

汇编器会报错:
demo.s: Assembler messages:
demo.s:2: Error: invalid constant — `mov sp,#0x0c002000
demo.s:3: Error: invalid constant — `mov sl,#0x0c001000

说起这个过错的原因可就话长了,简而言之是因为RISC有一个重要的概念便是一切指令等长。在ARM指令会集,一切指令长度为4字节(Thumb指令是2字节)。那问题就来了,4字节是不或许一起存的下指令操控码和32位当即数的,那么我要把一个32位当即数(比方一个32位地址值)传送给寄存器该怎么办?

RISC CPU供给一个通用的办法便是把地址值作为数据而不是代码,从存储器中相应的方位读入到寄存器中,待会咱们会看到这样的比方。

此外ARM还供给另一种计划。因为传送类指令的指令操控码部分(cond, opcode, S, Rd, Rn域)占去了20个字节,那能供给给当即数的就只剩12个位了。

ARM并未运用这12个位来直接存一个12位当即数,而是运用了相似有用数字相同的概念,只存8个字节的有用位和一个4位的位偏移量(偏移单位为2)。这个东西在ARM被叫做术语immed_8,有爱好的人能够找材料了解一下,处处都有介绍。

能够看出ARM的这个办法能直接运用的当即数是适当有限的,像0xfffffff0这样的数明显无法支撑。别着急,ARM的传送类指令中还有一个MVN指令能够处理该问题。明显0x0000000f是一个有用当即数,MVN会先将其取反再传送,这样有用当即数的规模又扩大了一倍。

可就算如此仍有许多的32位当即数是无效的,比方上面那个比方中的0x0c002000和0x0c001000。面临这种问题一是运用RISC的通用办法,二是分次载入。

比方能够这样载入0x0c002000:

.text
mov sp, #0x0c000000
add sp, sp, #0x00002000

或许:

.text
mov sp, #0x0c000000
orr sp, sp, #0x00002000

感觉很狡猾是吧,呵呵。可是要留意它和办法一的一大差异:需求多条指令。那么在一些对指令数目有约束的场合就无法运用它,比方反常向量表处要做长跳转(超越±32MB)的话就只能用办法一;还有便是在同步业务中该操作不是原子的,因而或许需求加锁。

扯了这么多再回到LDR伪指令上来。明显上面的内容是杂乱繁琐的,如公然程序员在写程序的时分还要考虑某个数是不是immed_8必定超级费事,因而为了减轻程序员的担负才引入了LDR伪指令。

你必定很猎奇榜首段代码demo.s被GNU AS变成了什么,好,让咱们在Linux环境下履行下面的指令:
arm-elf-as -o demo.o demo.s
arm-elf-objdump -D demo.o

成果:

demo.o: file format elf32-littlearm

Disassembly of section .text:

00000000 <.text>:
0: e59fd004 ldr sp, [pc, #4] ; c <.text+0xc>
4: e59fa004 ldr sl, [pc, #4] ; 10 <.text+0x10>
8: e59ff004 ldr pc, [pc, #4] ; 14 <.text+0x14>
c: 0c002000 stceq 0, cr2, [r0]
10: 0c001000 stceq 0, cr1, [r0]
14: 00000000 andeq r0, r0, r0
Disassembly of section .data:

因为entry还没连上方针地址,objdump反汇编会认为是0,咱们先不管它。别的两条LDR伪指令变成了实践的LDR指令!但方针很古怪,都是[pc, #4]。那好咱们看看[pc, #4]是什么。

咱们知道pc中寄存的是当时指令的下下条指令的方位,也便是. + 8。那么上面的榜首条指令ldr sp, [pc, #4]中的pc便是0x8,pc + 4便是0xc,而[0xc]的内容正是0x0c002000;同理,第二条ldr指令也是如此。明显这儿LDR伪指令选用的是RISC通用的办法。

别的要说的是,假如LDR的是一个immed_8或许immed_8的反码数,则会直接被解说成mov或mvn指令。如ldr pc, = 0x0c000000会被解说成mov pc, 0x0c000000。

最终一点弥补,我发现arm-elf-gcc一般都用累加法。如C句子中的i = 0x100ffc04;会变成相似于以下的句子:
mov r0, #0x10000004
add r0, r0, #0x000ff000
add r0, r0, #0x00000c00

原因不详。

增加的内容:

1 指令LDR

使用举例:

u LDR R0, [R1, #4] ;将内存单元R1+4中的字读取到R0寄存器

其间,R1为基址,#4为偏移地址,R0为方针地址。留意,此刻不更新R1。

u LDR R0, [R1, #-4] ;将内存单元R1-4中的字读取到R0寄存器

u LDR R0, [R1, #4]! ;将内存单元R1+4中的字读取到R0寄存器。一起更新R1,R1=R1+4。

u LDR R0, [R1], #4 ;将地址为R1的内存单元数据读取到R0寄存器,然后R1=R1+4。

2 伪指令LDR

ARM中的伪指令不是真实的ARM指令或许Thumb指令,这些伪指令在汇编编译器对源程序进行汇编处理时,被替换为相应的ARM或许Thumb指令(序列)。

LDR伪指令将一个32位的常数或许一个地址值读取到寄存器中。

语法格局:

LDR{cond} register, =[expr | label-expr]

其间,register为方针寄存器

expr为32位的常量。编译器将依据expr的取值状况,如下处理LDR伪指令:

u 当expr所表明的地址值没有超越MOV或MVN指令中的地址取值规模时,编译器用适宜的MOV或许MVN指令替代LDR伪指令。

使用举例:

将0xFF0读取到R1中

LDR R1, =0xFF0

汇编后得到:

MOV R1, 0xFF0

u 当expr表明的地址值超越了MOV或许MVN指令中的地址的取值规模(第二操作数的取值规模)时,编译器将该常数放在数据缓冲区中,一起用一条根据PC的LDR指令读取该常数。

LDR R1,=0xFFF

汇编后得到:

LDR R1, [PC, OFFSET_TO_LPOOL]

LPOOL DCD 0xFFF

关于label-expr的介绍我不是很了解。不了解其间关于“衔接重定位伪操作”。(P144)

声明:本文为我在学习杜春雷编著的《ARM体系结构与编程》时做的总结笔记,文中摘录了书中的许多内容。

弥补2:

原文地址:http://hi.baidu.com/andylgh/blog/item/17dbdc1f7d102a62f624e4dc.html

gnu下的arm汇编伪指令:.word阐明
2007-04-08 20:14

说说这个.word的效果。

word expression便是在当时方位放一个word型的值,这个值便是expression
举例来说,
_rWTCON:
.word 0x15300000
便是在当时地址,即_rWTCON处放一个值0x15300000

翻译成intel的汇编句子便是:
_rWTCON dw 0x15300000

例如:

ldr r1, _rWTCON

_rWTCON:
.word 0x15300000
不是把地址0x1530 0000 上的内容传递到r1,是把地址_rWTCON上的内容放到r1,而地址_rWTCON上的内容是0x15300000。实践上便是把r1设置为0x15300000

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/ceping/baogao/262671.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部