您的位置 首页 资料

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

到目前为止,我们已经具备编写较为复杂的ARM汇编程序的能力,但要编写较为复杂且实用的程序,我们就不得不掌握ARM汇编的伪指令(pseudo-ins

到目前为止,咱们现已具有编写较为杂乱的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、nop

1、ldr

首要咱们来答复“根本寻址方式与根本指令”一文中提出的问题。“假如咱们需求mov r0, #10000这样的指令,应该怎么办?(常数10000不能在机器指令32bit中的低12bit中被表示出来)”。当你进行编译的时分,“Error:All70E”的过错就会呈现,如下图。

其实,这个问题很简单处理,只需求将mov r0, #10000换为ldr r0, =10000即可。为什么这样就可以了呢?由于,这儿的ldr r0, =10000并非咱们现已学过的ldr指令,而是一条伪指令,编译器会将这条伪指令替换为:

ldr r0, [pc, #-4]
DCD 10000

DCD所分配的内存空间中寄存了整数10000,该内存空间被称为literal pool,中文名称“文字池”。由于整个程序都是由编译器编译的(包含文字池的分配),所以很显然编译器可以知道ldr指令在内存中的地址与文字池在内存中的方位之间的偏移量,因而编译器就可以正确地运用以pc为基址,选用相对寻址的ldr指令将文字池中的数取出加载到寄存器r0中。由此可见,编译器关于ldr r0, =10000这条伪指令的处理,其实质是:

在汇编源程序时,LDR伪指令被编译器替换成一条适宜的指令和寄存常数的文字池。汇编器将常量放入文字池,并运用一条程序相对偏移的LDR指令从文字池读出常量。

由于,4byte可以寄存任何int型整数,这样一来,常数就可以是任何int型整数,而不再受制于12bit的约束。当然此刻的常数是寄存在内存中的,而不是寄存在机器指令的32bit编码中的。

额定阐明:

a)、ldr r0, [pc, #-4]中是-4,而不是+4,是由于流水线的原因(拜见“流水线对PC值的影响”一文)。往后关于流水线的这种影响,我将不再予以特别阐明。

b)、从指令方位到文字池的偏移量有必要小于4KB

c)、从语法上来看,与ARM指令的LDR比较,伪指令LDR的参数有“=”号,没有“#”号

d)、假如常数可以被12bit表示出来,例如:ldr r0, =0x100,那么,编译器对该伪指令的处理,是运用MOV(或许MVN)指令替代该LDR伪指令,例如:mov r0, #0x100,而不会选用ldr指令+文字池的方法。

除了 ldr 寄存器, =常数 这种方式外,还有ldr 寄存器, =标号 这种方式也经常被运用,下面我就来解说这种方式的ldr伪指令。

由上图可见:ldr pc, =InitStack这条伪指令的作用是将标号InitStack所代表的地址赋予pc。 这儿会使咱们发生几个疑问:

a)、为什么不运用bl InitStack,而要运用ldr pc, =InitStack?

这是由于bl指令的跳转规模是正负32M,而InitStack所代表的方位有或许间隔ldr pc, =InitStack超越32M,此刻bl就力不从心了。居然存在这么大规模跳转的程序(这好像意味着编译出来的二进制可执行文件的巨细会操作32M),这一点好像令咱们感到十分震动。事实上是:巨细超越32M的可执行程序确实简直不或许呈现,但即使是很小的二进制程序中也或许进行大规模(超越32M)的跳转,这一点在bootloader程序中简直是必定的。

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

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

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

微信扫一扫关注我们

返回顶部