34

我正在浏览本教程:http ://www.cl.cam.ac.uk/freshers/raspberrypi/tutorials/os/ok01.html

组装的第一行是:

ldr r0,=0x20200000

第二个是:

mov r1,#1

我以为ldr是为了将内存中的值加载到寄存器中。但似乎这=意味着 0x20200000 是一个值而不是内存地址。两条线似乎都在加载绝对值。

4

3 回答 3

22

这是一个技巧/捷径。例如说

ldr r0,=main

会发生什么情况是汇编器会在指令附近但在指令路径之外分配一个数据字

ldr r0,main_addr
...
b somewhere
main_addr: .data main

现在将该技巧扩展到常量/立即数,尤其是那些不能适应立即移动指令的:

top:
add r1,r2,r3
ldr r0,=0x12345678
eor r1,r2,r3
eor r1,r2,r3
b top

组装然后拆卸

00000000 <top>:
   0:   e0821003    add r1, r2, r3
   4:   e59f0008    ldr r0, [pc, #8]    ; 14 <top+0x14>
   8:   e0221003    eor r1, r2, r3
   c:   e0221003    eor r1, r2, r3
  10:   eafffffa    b   0 <top>
  14:   12345678    eorsne  r5, r4, #125829120  ; 0x7800000

你会看到汇编器已经为你添加了数据字并将 ldr 更改为你的 pc 亲戚。

现在,如果您使用适合 mov 指令的立即数,那么可能取决于汇编程序,当然是我正在使用的 gnu,它对我来说变成了 mov

top:
add r1,r2,r3
ldr r0,=0x12345678
ldr r5,=1
mov r6,#1
eor r1,r2,r3
eor r1,r2,r3
b top


00000000 <top>:
   0:   e0821003    add r1, r2, r3
   4:   e59f0010    ldr r0, [pc, #16]   ; 1c <top+0x1c>
   8:   e3a05001    mov r5, #1
   c:   e3a06001    mov r6, #1
  10:   e0221003    eor r1, r2, r3
  14:   e0221003    eor r1, r2, r3
  18:   eafffff8    b   0 <top>
  1c:   12345678    eorsne  r5, r4, #125829120  ; 0x7800000

所以它基本上是一个打字快捷方式,理解你让汇编程序找到一个地方来粘贴常量,它通常做得很好,有时会抱怨,不确定我是否看到它不能安全地做到这一点。有时您需要在代码中使用 .ltorg 或 .pool 来鼓励汇编程序找到位置。

于 2012-12-26T22:04:50.380 回答
14

来自更接近您水平的人的较短响应,希望对您有所帮助:在 ARM 中,指令具有 32 位。一些位用于标识操作,一些位用于操作数,在 MOV 指令的情况下,一些位可用于立即值(例如#1)。

正如您在此处看到的(第 33 页),立即数只有 12 位可用。该指令不使用每个位作为数字(范围从 0 到 2^12-1~4095),而是通过将前 8 位右移 (ROR) 后 4 位中指定的数量的两倍来计算立即数. 即,immediate = first 8 bits ROR 2*(last four bits)

通过这种方式,我们可以获得比 0 到 4095 范围更广的数字(请参阅第 34 页了解可能的立即数的简要摘要)。但是请记住,对于 12 位,仍然只能指定 4096 个可能的值。

万一我们的数字不能像前一个那样转换成指令(257不能表示为8位旋转任意4位的两倍),那么,我们必须使用LDR r0,=257

在这种情况下,编译器将数字 257 保存在内存中,靠近程序代码,因此可以相对于 PC 对其进行寻址,并从内存中加载它,正如 dwelch 详细解释的那样。

注意:如果您按照该教程进行操作,那么当您尝试使用 mov r0, #257 进行“制作”时,您将收到错误消息,并且您必须手动尝试 ldr r0, =257。

于 2013-07-10T14:31:42.437 回答
6

与其他答案一样好,我想我也许可以简化答案。

ldr = 加载寄存器

移动= 移动

两者都有效地做同样的事情,但方式不同。

区别很像

#define CONST 5

int CONST = 5;

在 C 语言中。

mov非常快,因为它的附带值直接存储为指令的一部分(以上述答案中描述的 12 位格式)。由于它存储值的方式,它有一些限制。为什么?因为

  • 12 位不足以存储像 32 位内存地址这样的大量数字。
  • 前 8 位ROR 2 *(后 4 位)不能代表任何数字,即使在 12 位范围内也是如此。

另一方面,ldr是通用的(主要是由于编译器优化)。它是这样工作的(如反汇编例程所示)

  • 如果该值可以以 12 位和前 8 位ROR 2 *(后 4 位)格式表示,则编译器将其更改为伴随该值的mov指令。

  • 否则,该值将作为数据保存到 RAM 中的某个位置。并通过使用程序计数器的偏移量从内存访问,将其加载到所需的寄存器中。

我希望它有所帮助。

于 2017-03-18T17:04:25.320 回答