簡體   English   中英

ARM 組件中的 LDR 和 EQU

[英]LDR and EQU in ARM Assembly

這是我的匯編代碼。

a EQU 0x20000000 
b EQU 0x20000004 
c EQU 0x20000008 
LDR R4, =a 
LDR R0, [R4] 
LDR R4, =b 
LDR R1, [R4] 
LDR R4, =c 

我有兩個問題。 LDR R0, [R4]之后是什么R[4]里面是什么? 0x20000000或 memory 在0x20000000的內容?
其次,在最后一行之后, R4里面有什么? c或 memory 在0x20000008的內容?

我在網上搜索了 EQU 和 LDR,我自己的猜測是,對於所有問題,它都是 memory 的內容,但我很困惑,因為我的朋友告訴我不,我上面提到的十六進制數字存儲在R[4]


更新:對不起,我的意思是:在LDR R0, [R4]之后R0里面有什么? 0x20000000或 memory 在0x20000000的內容?

R4里面有什么? 0x20000008或 memory 在0x20000008的內容?

首先,無需搜索整個互聯網,go 源代碼,arm 文檔涵蓋了指令集。 根據說明,這是 arm 或拇指代碼,但不是 aarch64,所以假設 arm ...

接下來的事情是 EQU 是一個指令而不是一個應該相當明顯的指令,處理器如何在匯編語言中使用變量和這樣的指令? 他們沒有。

接下來是匯編語言由匯編程序定義,您使用的工具不是目標(指令集)。 這看起來可能是 ARM 的匯編程序之一。 許多人使用 gnus 工具,兩者都可以。 我有 gnu,所以匯編語言更改為:

.EQU a, 0x20000000
.EQU b, 0x20000004
.EQU c, 0x20000008
LDR R4, =a
LDR R0, [R4]
LDR R4, =b
LDR R1, [R4]
LDR R4, =c

對於 gnu 匯編器,我組裝然后反匯編並得到這個:

arm-none-eabi-as so.s -o so.o
arm-none-eabi-objdump -D so.o

so.o:     file format elf32-littlearm


Disassembly of section .text:

00000000 <.text>:
   0:   e3a04202    mov r4, #536870912  ; 0x20000000
   4:   e5940000    ldr r0, [r4]
   8:   e3a04242    mov r4, #536870916  ; 0x20000004
   c:   e5941000    ldr r1, [r4]
  10:   e3a04282    mov r4, #536870920  ; 0x20000008

=a 類型語法是偽代碼,因此不是真正的指令內容,因此會因匯編程序而異。 正如本頁其他地方所指出的那樣,對該功能的支持取決於工具,並且某些工具的處理方式與其他工具不同。 Gnu 匯編器,似乎是功能最豐富的......讓我跑題了......寄存器是 32 位的,指令是 32 位的,不可能有一個 32 位的立即加載指令和一個 32 位的立即數(固定-length) 指令沒有其他位。 不同的(固定長度)指令集以不同的方式解決了這個問題,arm 有其有趣的解決方案,並且在 arm、thumb 和 thumb2 擴展之間變化,對於 ZF926B3E222D7AFEE57071B225683970偶數位以立即生成..gnu 匯編器將盡最大努力選擇 mov 或 mvn 如果可以,否則它會創建 pc 相對負載並將值放在附近的池中。

在您的情況下,這些常量都可以正常工作,因此 mov 被替換為 ldr = 偽指令。

   0:   e3a04202    mov r4, #536870912  ; 0x20000000
   4:   e5940000    ldr r0, [r4]
   8:   e3a04242    mov r4, #536870916  ; 0x20000004
   c:   e5941000    ldr r1, [r4]
  10:   e3a04282    mov r4, #536870920  ; 0x20000008

正如您應該已經閱讀了 arm 文檔(如果沒有處理器供應商提供的文檔,您根本無法開始學習/閱讀程序集)。 ldr r0,[r4] 表示獲取 r4 中的位並將它們用作地址(先前的指令放置在 r4 中的 0x20000000 因此對於該指令,0x20000000 成為地址),從該地址讀取(加載)並放置結果(來的位返回)在 r0 中。

用於演示目的

.EQU a, 0x20000004
.EQU b, 0x20000200
.EQU c, 0x20000008
LDR R4, =a
LDR R0, [R4]
LDR R4, =b
LDR R1, [R4]
LDR R4, =c

00000000 <.text>:
   0:   e3a04242    mov r4, #536870916  ; 0x20000004
   4:   e5940000    ldr r0, [r4]
   8:   e59f4004    ldr r4, [pc, #4]    ; 14 <a-0x1ffffff0>
   c:   e5941000    ldr r1, [r4]
  10:   e3a04282    mov r4, #536870920  ; 0x20000008
  14:   20000200

0x20000004 可以旋轉,您可以旋轉 0x00000042,例如圍繞偶數位旋轉,看起來就像他們所做的那樣。 但是 0x20000200 不能根據 mov 和 mvn 指令的規則創建,因此使用了 pc 相對負載和附近的值 0x20000200。 由於這不是完整的代碼,處理器會猛烈撞擊該數據,就好像它是一條指令和 go 一樣,直到它最終崩潰或幸運地陷入循環。 對於實際代碼,該池將放置在某種無條件分支之后和/或您告訴它的位置,該池基於匯編程序特定的匯編語言指令。

從技術上講,arm 匯編器的匯編語言不必支持 ldr r0,[r4] 語法,匯編器作者可以自由地做任何他們想做的事情 ldr r0,(r4), ldr [r4],r0 loadw r0,0(r4), bob pickle,[onion],只要它生成正確的機器代碼,它就是一種生成 arm 指令的匯編語言,因此是 arm 匯編語言。 到目前為止,我使用的所有匯編程序都按該順序支持 ldr r0,[r4] 語法,但我認為並非所有人都支持 =address 事物,並且根據 SO 的經驗,並非所有人都以相同的方式支持它有問題和其他人的帖子。

您可以自己進行加載,但您也可以了解匯編語言的特定差異:

.EQU a, 0x20000000
.EQU b, 0x20000000
.EQU c, 0xFFFFFF20
LDR R4, avalue
LDR R0, [R4]
LDR R4, =b
LDR R1, [R4]
LDR R4, =c
avalue: .word a

Disassembly of section .text:

00000000 <avalue-0x14>:
   0:   e59f400c    ldr r4, [pc, #12]   ; 14 <avalue>
   4:   e5940000    ldr r0, [r4]
   8:   e3a04202    mov r4, #536870912  ; 0x20000000
   c:   e5941000    ldr r1, [r4]
  10:   e3e040df    mvn r4, #223    ; 0xdf

00000014 <avalue>:
  14:   20000000

這迫使 pc 相對負載,因為這是我所要求的。 Within the arm targets some assembly languages want colons to mark labels others don't you can see the EQU differences (EQU is similar to a simple #define in C #define a 0x2000000 but unlike C you don't use it for more complicated macros宏語言中可能有匯編器特定的部分)。 大多數理智的匯編程序使用冒號來標記注釋,而用於 arm 的 gnu 匯編程序則沒有(請注意,gnu 匯編程序匯編語言不必在不同目標之間都有共同的規則/功能,假設每個目標都是由不同的人編寫和維護的因此,每種語言在諸如注釋和其他非指令性內容之類的簡單事物方面都是不同的。如果它們重疊,那就這樣吧)。

這是未鏈接的,因此該工具的反匯編從 0 開始,一旦鏈接,則此反匯編 output 將具有不同的地址,但 position 獨立(pc 相對負載是...... pc 相對)機器代碼將保持原樣(對於這些示例)。


EQU 是類似於在 C 中定義的指令,在這種情況下,它允許您取值 0x20000000,而不是鍵入變量或名稱或字符串 a,預處理器將搜索並替換字母 a 的明顯用途使用 0x20000000 (當然,它不會替換 add r0,r1,r2 中的 a)。

LDR 是一系列指令加載寄存器。 提供了位於寄存器中的地址、可能的偏移量和目標寄存器。 LDR R0,[R4] 表示 r4 包含地址(在您的情況下為 0x20000000),而 r0 是保存加載結果的目標寄存器。

ARM 制造內核而不是芯片,根據您提供的內容,沒有理由假設 0x20000000 是“內存”,它可能是外圍設備,處理器不在乎,它只是放在總線上的地址,芯片供應商知道什么該地址表示,並在總線上返回一個值。 處理器不知道它是 memory 還是其他東西。

正如所寫的那樣,假設這不是一些會破壞事物的奇怪匯編程序,第一個 ldr 從地址 0x20000000 進行加載並將結果放入 r0。

第 3 行定義地址 - 這些可以存儲在 memory 的本地池中,但由於它們非常簡單,匯編器可能會在第一次使用時使用幾個MOV指令為您組裝它們。

第 4 行將R4設置為宏 a -> 0x20000000的值(可能通過帶有移位操作的MOV ,但如果匯編程序出於某種原因想要從 memory 池加載,它可能會加載。)

第 5 行從 memory 讀取0x20000000並將從 memory 讀取的值放入R0

第 6 行用0x20000004加載R4 (可能變成MOVADD

第 7 行從 memory 讀取0x20000004並將值放入R1最后一行加載R4 0x2000008 (可能變成MOVADD

簡而言之, LDR R4, =指令僅將存儲在EQU語句中的地址加載到寄存器中。 隨后的R0 / R1加載是從它們指向的地址加載的內容。

現在,如果真正了解匯編的人正在編寫此代碼,那么它可能只會變成 2 條指令:一條0x2MOV並轉移到R4和一條用於處理加載和增量的LDM指令。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM