伪指令的MOV32 伪指令

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了伪指令的MOV32 伪指令相关的知识,希望对你有一定的参考价值。

参考技术A

将以下项之一加载到寄存器:
一个 32 位常数值
任何地址。
MOV32 始终会生成两个 32 位指令,即一个 MOV、MOVT 对。 您可利用它加载任何 32 位常数或访问整个地址空间。
如果用 MOV32 加载地址,则所生成的代码将与位置有关。 MOV32 Rd, expr
其中:
cond
是一个可选的条件代码(请参阅条件执行)。
Rd
是要加载数据的寄存器。Rd 不可为 sp 或 pc。
expr
可以是下列项之一:
symbol
程序区域中的标签。
constant
任何 32 位常数。
symbol + constant
标签加上 32 位常数。 MOV32 伪指令的主要功能有:
当单个指令中无法生成立即数时,生成文字常数。
将相对于程序的地址或外部地址载入寄存器中。 无论链接器将包含 MOV32 的 ELF 代码段置于何处,该地址始终有效。
Note
以这种方式加载的地址是在链接时确定的,因此代码不是位置无关的。
如果所引用的标签位于 Thumb 代码中,则 MOV32 将会设置该地址的 Thumb 位(位 0)。 此伪指令在 ARMv6T2 和 ARMv7 中的 ARM 和 Thumb 状态下均有效。
LDR 伪指令
将以下项之一载入寄存器:
一个 32 位常数值
一个地址。
Note
本节仅介绍 LDR 伪 指令。 有关 LDR 指令 的详细信息,请参阅 内存访问指令。
有关使用 LDR 伪指令加载常数的信息,请参阅用 LDR Rd, =const 加载。
语法
LDR.w Rt,=[expr | label‑expr]
其中:
cond
是一个可选的条件代码(请参阅条件执行)。
.W
是可选的指令宽度说明符。
Rt
是要加载的寄存器。
expr
取值为一个数值常数:
如果 expr 的值位于范围内,则汇编程序将会生成一个 MOV 或 MVN 指令。
如果 expr 的值不在 MOV 或 MVN 指令的范围内,则汇编程序会将常数放入文字池中,并会生成一个相对于程序的 LDR 指令,该指令可从文字池中读取此常数。
label‑expr
是一个与程序相关的表达式或外部表达式。 汇编程序会将 label‑expr 的值放入文字池中,并会生成一个与程序有关的 LDR 指令,该指令可从文字池中加载该值。
如果 label‑expr 是一个外部表达式,或未包含在当前代码段内,则汇编程序将会在目标文件中放入一个链接器重新定位指令。 链接器将在链接时生成该地址。
如果 label‑expr 是一个局部标签(请参阅局部标签),则汇编程序会在目标文件中放入一个链接器重新定位指令,并会为该局部标签生成一个符号。 该地址将在链接时生成。 如果局部标签引用了 Thumb 代码,则还会设置该地址的 Thumb 位(位 0)。
Note
在 RVCT2.2 中,没有对地址的 Thumb 位进行设置。 如果此设置会影响您的代码,则请使用命令行选项 ‑‑untyped_local_labels 迫使汇编程序在引用 Thumb 代码中的标签时不设置 Thumb 位。
用法
LDR 伪指令的主要功能如下:
当立即数由于超出了 MOV 和 MVN 指令的范围,而不能被移入寄存器中时,生成文字常数。
将相对于程序的地址或外部地址载入寄存器中。 无论链接器将包含 LDR 的 ELF 代码段置于何处,该地址始终有效。
pc 到文字池中的值的偏移量必须小于 ±4KB(ARM、32 位 Thumb‑2),或在 0 到 +1KB(Thumb、16 位 Thumb‑2)范围内。 您必须确保有一个满足范围要求的文字池。 有关详细信息,请参阅LTORG。
如果所引用标签在 Thumb 代码中,LDR 伪指令将会设置 label‑expr 的 Thumb 位(位 0)。
有关如何使用 LDR 的详细说明,以及有关 MOV 和 MVN 的详细信息,请参阅将常数加载到寄存器。
Thumb 代码中的 LDR
对于 ARMv6T2 及更高版本的 Thumb 代码,您可以使用 .W 宽度说明符强制 LDR 生成 32 位指令。LDR.W 始终生成 32 位指令,即使利用 16 位 MOV 就可完成常数的加载,或在 16 位 pc 相对载入范围内有文字池。
如果在第一次汇编时,汇编程序尚不知道常数值的相关信息,则不带 .W 的 LDR 将会在 Thumb 代码中生成 16 位指令,即使这会导致对于可在 32 位 MOV 或 MVN 指令中生成的常数,会通过 16 位 pc 相对加载来完成其加载。 但是,如果在第一次汇编时汇编程序就已经知道了该常数,并且该常数可以通过 32 位 MOV 或 MVN 指令生成,则将会使用 MOV 或 MVN 指令。
LDR 伪指令不会生成 16 位标记设置 MOV 指令。 可使用 ‑‑diag_warning 1727 汇编程序命令行选项来检查是否使用了 16 位指令。
有关如何在不利用文字池加载的情况下来生成常数或地址的信息,请参阅MOV32 伪指令。
示例
LDR r3,=0xff0 ; loads 0xff0 into r3
; => MOV.W r3,#0xff0
LDR r1,=0xfff ; loads 0xfff into r1
; => LDR r1,[pc,offset_to_litpool]
; ...
; litpool DCD 0xfff
LDR r2,=place ; loads the address of
; place into r2
; => LDR r2,[pc,offset_to_litpool]
; ...

ARM指令adr adrl ldr mov

ADR是一条小范围的地址读取伪指令,它将基于PC的相对偏移的地址值读到目标寄存器中。格式:ADR register,exper。

 

编译源程序时,汇编器首先计算当前PC值(当前指令位置)到exper的距离,然后用一条ADD或者SUB指令替换这条伪指令,

例如:ADD register,PC,#offset_to_exper。

注意,标号exper与指令必须在同一代码段。

比如:adr r0, _start ://将指定地址赋到r0中

    .........

_start:
    b _start

r0的值为标号_start与此指令的距离差 + PC值。

 

ADRL:

这是一条中等范围的地址读取伪指令,它将基于PC的相对偏移的地址值读到目标寄存器中。格式:ADRL register,exper。编译源程序时,汇编器会用两条合适的指令替换这条伪指令。

比如:

ADD register,PC,offset1

ADD register,register,offset2  

 

与ADR相比,它能读取更大范围的地址。

注意,标号exper与指令必须在同一代码段。

 

接下来是LDR,首先要说两个家伙,他们都叫LDR。

 

一个是LDR伪指令,一个是LDR指令,名字相同却不是一个东西。

 

区分的方法就是看第二个参数,如果有等号,就是伪指令

 

LDR指令:

例: ldr r0, 0x12345678 

是把0x12345678这个地址中的值存放到r0中。而mov不能干这个活,mov只能在寄存器之间移动数据,或者把立即数移动到寄存器中。

 

LDR伪指令:

例1(立即数): ldr r0, =0x12345678

这样,就把0x12345678这个地址写到r0中了。所以,ldr伪指令和mov是比较相似的。只不过mov指令限制了立即数的长度为8位,也就是不能超过512。而ldr伪指令没有这个限制。如果使用ldr伪指令,后面跟的立即数没有超过8位,那么在实际汇编的时候该ldr伪指令会被转换为mov指令。

 

例2(标号): ldr r0, =_start //将指定标号的值赋给r0

这里取得的是标号_start的绝对地址,这个绝对地址(运行地址)是在链接的时候确定的。它要占用 2 个32bit的空间,一条是指令,另一条是文字池中存放_start 的绝对地址。

 

对比adr r0, _start和 ldr r0, =_start

它们的目的一样,都是把标签的赋给r0,区别---左边是相对地址,右边绝对地址。目的一样,但结果不一定相同。结果是否相同,要看PC值是否和链接地址相同。

 

 

转自百问网

技术分享图片

 

 


以上是关于伪指令的MOV32 伪指令的主要内容,如果未能解决你的问题,请参考以下文章

机器码和伪指令

ARM汇编中LDR伪指令和LDR指令

ARM指令adr adrl ldr mov

8086汇编语言 汇编语言伪指令

arm汇编—ldr加载指令,ldr伪指令

ARM伪指令