ARM 匯編指令 ADR 與 LDR 使用


簡介

這兩個都是偽指令:ADR 是小范圍的地址讀取偽指令,LDR 是大范圍的讀取地址偽指令。可實際使用的區別是: ADR 是將基於 PC 相對偏移的地址值或基於寄存器相對地址值讀取的偽指令,而 LDR 用於加載 32 位立即數或一個地址到指定的寄存器中。

以下面的匯編代碼為例:

.global _start

_start:
	ldr r0, loop
	adr r0, loop
 	ldr r0, =loop

loop:
 	nop

用以下命令完成匯編、鏈接操作,並輸出反匯編文件

[root@localhost asm]# arm-linux-gcc asm.S -o asm.o -c
[root@localhost asm]# arm-linux-ld -Ttext 0x1004 asm.o -o link.elf
[root@localhost asm]# arm-linux-objdump -D link.elf > link.dis

反匯編代碼如下:

link.elf:     file format elf32-littlearm


Disassembly of section .text:

00001004 <_start>:
    1004:	e59f0004 	ldr	r0, [pc, #4]	; 1010 <loop>
    1008:	e28f0000 	add	r0, pc, #0
    100c:	e59f0000 	ldr	r0, [pc, #0]	; 1014 <loop+0x4>

00001010 <loop>:
    1010:	e320f000 	nop	{0}
    1014:	00001010 	andeq	r1, r0, r0, lsl r0

反匯編文件分析

    ARM9 特性:PC 指向當前指令地址 +8 的位置。

1.ldr r0, loop
    這是一條指令,從內存地址 loop 的位置把值讀入。在這里 loop 是一個標號(是一個相對程序的表達式),匯編程序計算相對於 PC 的偏移量,並生成相對於 PC 的索引指令:ldr r0, [pc, #4]。執行指令后,r0 = e320f000。
    
2.adr r0, loop
    這是一條偽指令,總是會被匯編程序匯編為一個指令。匯編程序嘗試產生單個 ADD 或 SUB 指令來裝載該地址。如果不能在一個指令中構造該地址,則生成一個錯誤,並且匯編失敗。在這里是取得標號 loop 的地址到 r0,該代碼可以在和標號相對位置不變的情況下移動:假如這段代碼在 0x30000000 運行,那么 adr r0, loop 得到 r0 = 0x3000000c;如果在地址 0 運行,就是 0x0000000c 了。

3.ldr r0, =loop
    這是一條偽指令,是一個相對程序的或外部的表達式。匯編程序將相對程序的標號表達式 label-expr 的值放在一個文字池中,並生成一個相對程序的 LDR 指令來從文字池中裝載該值。如果 label-expr 是一個外部表達式,或者未包含於當前段內,則匯編程序在目標文件中放置一個鏈接程序重定位命令,程序取鏈接時生成的地址,因此取得的是標號 loop 的絕對地址,這個絕對地址是在鏈接的時候確定的。它要占用 2 個 32bits 的空間,一條是指令,另一條是文字池中存放 loop 的絕對地址。因此可以看出,不管這段代碼將來在什么地方運行,它的結果都是 r0 = 0x00001010。

參考自:blog.sina.com.cn/s/articlelist_1263669380_0_1.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM