2012-12-26 58 views
20

我期待通過本教程:http://www.cl.cam.ac.uk/freshers/raspberrypi/tutorials/os/ok01.html爲什麼在ARM程序集中使用MOV上的LDR(反之亦然)?

組件的第一行是:

ldr r0,=0x20200000 

第二個是:

mov r1,#1 

我想ldr是用於加載值從存儲器到寄存器。但似乎=意味着0x20200000是一個值而不是內存地址。兩條線似乎都加載了絕對值。

+0

一個相關的[ARM博客文章(http://community.arm.com/groups/processors/blog/2010/07/27/how-to-load-constants-in-assembly-for-arm-architecture )。 –

+0

[論壇帖子](https://www.raspberrypi.org/forums/viewtopic.php?&t = 16528)問完全相同的問題。 –

回答

17

這是一個技巧/快捷方式。比方說

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來鼓勵彙編程序找到一個地方。

+0

感謝您的回答,我很喜歡裝配。所以我們的答案稍高於我。對於'ldr',你的意思是這個值會被彙編器「存儲」爲數據,然後在執行時從內存中加載,而對於'mov',這個值實際上是指令的一部分?所以如果這個值太大而不適合你的指令,你必須使用'ldr'。 –

+2

mov表示將值移入寄存器。 Ldr表示將值加載到寄存器中。 str,store是從寄存器到內存。和=地址快捷方式沒有意義。 (有意義的做一個ldr =地址將地址放入寄存器,然後存儲到某個寄存器的內容到該地址的內存中) –

+2

也明白「太大」意味着什麼,意味着有多於8位分隔。所以mov rd,#0x21000000是完全有效的,但0x201不是。 –

6

更短的響應,只是從更接近您的級別的人,希望它有所幫助:在ARM中,指令有32位。一些位用於標識操作,一些用於標識操作數,另外一些用於MOV指令,其中一些用於立即值(例如#1)。

正如你可以看到here(第33頁),只有12位可用於立即值。該指令不是將每個位用作數字(範圍從0到2^12-1〜4095),而是通過向右旋轉(ROR)前4位中指定的前兩位數的前8位來計算立即數。那就是,immediate = first 8 bits ROR 2*(last four bits)

通過這種方式,我們可以獲得比4096更多的數字(請參閱第34頁,瞭解可能的立竿見影的簡要概述)。

以防萬一,我們的數目不能被轉換成像前一個指令(257不能被表示爲8位旋轉兩次的任何4個比特),然後,我們必須使用LDR R0,= 257

在這種情況下,編譯器保存在存儲器中的數257,靠近該程序代碼,所以它可以相對於該PC加以解決,並且從存儲器加載它,正如dwelch詳細說明。

注意:如果您按照教程,那麼當你嘗試「使」與MOV R0,#257,你會得到一個錯誤,你必須嘗試手動LDR R0 = 257。

+1

這個問題所以,一個較短的迴應會是'ldr'讓你使用更大的數字? – Yay295

+0

這裏也解釋了這一點,以防萬一http://www.peter-cockerell.net/aalp/html/ch-3.html(請參閱關於直接操作數的部分) – enthusiasticgeek

0

由於作爲其他的答案都不錯,我想我也許能簡化的答案。

LDR =裝載寄存器

MOV =移動

兩者有效地做同樣的事情,但以不同的方式。

不同的是類似於C語言

#define CONST 5 

int CONST = 5; 

之間的差別很多。

mov確實很快,因爲它具有作爲指令一部分直接存儲的值(以上述答案中描述的12位格式)。由於存儲值的方式,它有一些限制。爲什麼?因爲

  • 12位不足以存儲巨大的數字,如32位內存地址。
  • 前8位ROR 2 *(最後4位)不能代表只是任何數量,即使是在12位的範圍。

LDR,在另一方面,是通用的(主要由於編譯器優化)。它的工作原理是這樣(如在解體例程示出)

  • 如果該值可以在12位來表示&前8位ROR 2 *(最後4位)格式,則編譯器將其改變爲一個mov伴隨該值的指令。

  • 否則,該值被保持作爲數據,加載到RAM中,在一個位置。通過使用來自程序計數器的偏移量從存儲器訪問,將其加載到所需的寄存器中。

我希望它有幫助。

相關問題