| 特性 | LDR 指令 | LDR 偽指令 |
|---|---|---|
| 語法標識 | LDR Rd, [Rn, #offset] 或 LDR Rd, =label (無等號) | LDR Rd, =value (有等號) |
| 功能 | 從內存地址讀取數據到寄存器 | 將 32 位立即數/地址值直接載入寄存器 |
| 數據源 | 內存 | 字面量池 或 mov/mvn 指令 |
| 立即數限制 | 無(訪問內存) | 無(通過字面量池) |
| 編譯器處理 | 直接編碼為機器指令 | 根據值大小優化為 mov/mvn 或 LDR+字面量池 |
ARM 是 RISC (Load/Store 架構):
MOV EAX, [0x1234] 直接內存操作截然不同。LDR R0, [R1, #0x10] ; R0 = *(R1 + 0x10) 基址+偏移 LDR R0, [R1, R2, LSL #2] ; R0 = *(R1 + R2*4) 比例索引 LDR R0, =0x12345678 ; 這是偽指令!見下文
LDR 指令不直接支持 32 位立即數作為地址,地址必須在寄存器中(PC 相對、基址寄存器、或通過偽指令預載入)。
LDR Rd, =exprexpr 可以是:
LDR R0, =0x12345678LDR R0, =_startLDR R0, =buffer+4MOV Rd, #imm 或 MVN Rd, #imm。LDR R0, =0x10 → MOV R0, #0x10LDR R0, =0x12345678 → 字面量池存 0x12345678 → LDR R0, [PC, #offset_to_pool]LTORG 指令顯式控制位置。LTORG 分池。| 指令 | 類型 | 范圍 | 地址類型 | 指令數 | 用途 |
|---|---|---|---|---|---|
| ADR | 偽指令 | ±256B (ARM) / ±1KB (Thumb) | 相對地址 (PC+offset) | 1 (ADD/SUB) | 同段近距離標號 |
| ADRL | 偽指令 | ±4KB (ARM) / ±1MB (Thumb-2) | 相對地址 | 2 (ADD+ADD) | 同段中距離標號 |
| LDR =label | 偽指令 | 全地址空間 (配合字面量池) | 絕對地址 (鏈接時確定) | 1 LDR + 1 池條目 | 跨段、遠距離、需絕對地址 |
| MOV | 指令 | 8 位循環立即數 | 立即數值 | 1 | 小常數、掩碼 |
ADR R0, _start ; R0 = PC + offset_to_start (相對地址,運行時 PC 相關) LDR R0, =_start ; R0 = _start 的鏈接時絕對地址 (需字面量池存儲 32 位地址)
若代碼運行地址 = 鏈接地址(非 PIC),兩者結果相同。若為位置無關代碼 (PIC) 或動態加載,ADR 給出正確相對地址,LDR= 給出鏈接時固定地址(可能錯誤)。
; GPIO 基址 0x20200000,超出 MOV 范圍 LDR R0, =0x20200000 ; 偽指令 → 字面量池 + PC 相對 LDR STR R1, [R0, #0x14] ; 設置 GPIO 輸出
LDR R0, =my_function ; 獲取絕對地址 BLX R0 ; 跳轉調用(支持 Thumb/ARM 切換)
; 大量 LDR= 導致池超出 ±4KB LDR R0, =const1 ... LDR R1, =const100 LTORG ; 強制在這裡生成字面量池,防止後續引用超範圍 LDR R2, =const101
LDR R0, 0x12345678 是語法錯誤,必須 LDR R0, =0x12345678 (偽指令) 或先載入寄存器 LDR R0, [PC, #offset]。LTORG。