我期待通過本教程:http://www.cl.cam.ac.uk/freshers/raspberrypi/tutorials/os/ok01.html爲什麼在ARM程序集中使用MOV上的LDR(反之亦然)?
組件的第一行是:
ldr r0,=0x20200000
第二個是:
mov r1,#1
我想ldr
是用於加載值從存儲器到寄存器。但似乎=
意味着0x20200000是一個值而不是內存地址。兩條線似乎都加載了絕對值。
我期待通過本教程:http://www.cl.cam.ac.uk/freshers/raspberrypi/tutorials/os/ok01.html爲什麼在ARM程序集中使用MOV上的LDR(反之亦然)?
組件的第一行是:
ldr r0,=0x20200000
第二個是:
mov r1,#1
我想ldr
是用於加載值從存儲器到寄存器。但似乎=
意味着0x20200000是一個值而不是內存地址。兩條線似乎都加載了絕對值。
這是一個技巧/快捷方式。比方說
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來鼓勵彙編程序找到一個地方。
感謝您的回答,我很喜歡裝配。所以我們的答案稍高於我。對於'ldr',你的意思是這個值會被彙編器「存儲」爲數據,然後在執行時從內存中加載,而對於'mov',這個值實際上是指令的一部分?所以如果這個值太大而不適合你的指令,你必須使用'ldr'。 –
mov表示將值移入寄存器。 Ldr表示將值加載到寄存器中。 str,store是從寄存器到內存。和=地址快捷方式沒有意義。 (有意義的做一個ldr =地址將地址放入寄存器,然後存儲到某個寄存器的內容到該地址的內存中) –
也明白「太大」意味着什麼,意味着有多於8位分隔。所以mov rd,#0x21000000是完全有效的,但0x201不是。 –
更短的響應,只是從更接近您的級別的人,希望它有所幫助:在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。
這個問題所以,一個較短的迴應會是'ldr'讓你使用更大的數字? – Yay295
這裏也解釋了這一點,以防萬一http://www.peter-cockerell.net/aalp/html/ch-3.html(請參閱關於直接操作數的部分) – enthusiasticgeek
由於作爲其他的答案都不錯,我想我也許能簡化的答案。
LDR =裝載寄存器
MOV =移動
兩者有效地做同樣的事情,但以不同的方式。
不同的是類似於C語言
#define CONST 5
和
int CONST = 5;
之間的差別很多。
mov確實很快,因爲它具有作爲指令一部分直接存儲的值(以上述答案中描述的12位格式)。由於存儲值的方式,它有一些限制。爲什麼?因爲
LDR,在另一方面,是通用的(主要由於編譯器優化)。它的工作原理是這樣(如在解體例程示出)
如果該值可以在12位來表示&前8位ROR 2 *(最後4位)格式,則編譯器將其改變爲一個mov伴隨該值的指令。
否則,該值被保持作爲數據,加載到RAM中,在一個位置。通過使用來自程序計數器的偏移量從存儲器訪問,將其加載到所需的寄存器中。
我希望它有幫助。
一個相關的[ARM博客文章(http://community.arm.com/groups/processors/blog/2010/07/27/how-to-load-constants-in-assembly-for-arm-architecture )。 –
[論壇帖子](https://www.raspberrypi.org/forums/viewtopic.php?&t = 16528)問完全相同的問題。 –