理解adr,ldr指令

2021-07-25 15:28:41 字數 2576 閱讀 4261

在閱讀u-bootstart.s時,對adr和ldr指令有些疑惑,經韋老師指點,在參閱了一些網上的博文後,做了這個實驗:

參照韋老師的**和makefile寫了

test_adr.s:

.text

.globl _start

_start:

ldr r0,test

adr r0,test

ldr r0,=test

nop

test:

nopmakefile:

all:test_adr.s

arm-linux-gcc -c -o test_adr.o test_adr.s

arm-linux-ld -ttext 0x00000000 -g test_adr.o -o test_adr_elf

arm-linux-objcopy -o binary -s test_adr_elf test_adr.bin

arm-linux-objdump -d -m arm test_adr_elf > test_adr.dis

clean:

rm -f test_adr.dis test_adr.bin test_adr_elf *.o

對test_adr.s:反彙編得到test_adr.dis

test_adr_elf:

file format elf32-littlearm

disassembly of section .text:

00000000 <_start>:

0: e59f0008 ldr r0, [pc, #8]; 10

4: e28f0004 add r0, pc, #4; 0x4

8: e59f0004 ldr r0, [pc, #4]; 14 <.text+0x14>

c: e1a00000 nop (mov r0,r0)

00000010 :

10:e1a00000 nop (mov r0,r0)

14:00000010 andeq r0, r0, r0, lsl r0

首先很顯然,ldr獲取的是記憶體的值(至於這個記憶體存的是資料還是位址,這個不是問題的重點,先不討論),像指標一樣間接定址(

看到了符號咯)

而adr是得到了乙個與pc有關的值,必定是個位址,韋老師舉了個例子:

adr r0, _start 

時,r0就是_start對應的指令當前的位址

對於「_start

對應的指令當前的位址

」,我理解了很久,終於想清楚,比如在uboot中,_start標號對應的指令(即b reset這條指令)的鏈結位址是0x33f80000這個確鑿無疑。

如果從norflash啟動時,b reset被燒在norflash的0位址,那麼b reset相對於此時的pc來說,它的位址就是0;

所謂「當前

」是以執行時的pc為參照。

下面基於以上理解,分析一下test_adr.dis

00000000 <_start>:

0: e59f0008 ldr r0, [pc, #8]; 10

4: e28f0004 add r0, pc, #4; 0x4

8: e59f0004 ldr r0, [pc, #4]; 14 <.text+0x14>

c: e1a00000 nop (mov r0,r0)

00000010 :

10:e1a00000 nop (mov r0,r0)

14:00000010 andeq r0, r0, r0, lsl r0 1 

先分析第一條指令ldr r0,test別編譯成ldr

r0, [pc, #8],也就是到當前pc+8的儲存器取值,當執行第一條指令時,pc其實已經是8了(流水線決定的)

那麼8+8就等於0x10,所以r0就等於e1a00000,這條指令的作用就是讀取test位址處存放的值。由於此處放了一條nop,那麼就是得到了nop的機器碼而已 2 

第二條adr r0,test被編譯成add r0, pc, #4

這顯然是依賴程式執行到此處時的pc值了。

adr是小範圍的位址讀取偽指令.adr 指令將基於pc 相對偏移的位址值讀取到暫存器中

此指令在4位址,pc就是4+8=0xc再加4,於是r0=0x10

從結果上來看,test自身的值(標號值),被讀到了r0,這個值是以pc為參考的,也就是test對應的指令(第二個nop)當前的位址。

r0=(標號test 的位址與此指令的距離差)+(此指令的位址)=((0x10-0x4=12)+(4))=16=0x10

假如是在0x30000000以上執行,r0=((12)+(0x30000004))=0x30000010

3 ldr r0,=test

被編譯成兩個字,乙個指令,乙個文字池。執行到這裡pc=8,8+8+4=0x14.所以是在14位址取值,編譯器放在14位址處放了0x00000010,0x00000010就是test的值,假如在makefile裡指定連線位址是0x30000000,那麼編譯器放在這裡的就是0x30000010了,可見,這個值是編譯時確定的

andeq

r0, r0, r0, lsl r0

這個東西大概是編譯器的機械動作,把乙個數字也翻譯成了指令

adr,ldr指令的區別

首先來看一段指令和它的彙編結果 area test,code,readonly entry ldr r0,start adr r0,start ldr r0,start nop start nopend 彙編結果如下圖 首先,當執行第一條指令時,pc的指向是0x8008 start的值是0x8010...

int指令理解

以下是王爽老師的 組合語言 中第十五章中的一段程式 其功能是增加9號中斷的功能,當按下esc鍵時螢幕中顯示的字母改變顏色 assume cs codesg,ss stack,ds data data segment dw 0,0 data ends stack segment db 128 dup ...

arm彙編指令理解

blx指令 76 09 00 fa fa 00 09 76 31 30 29 28 27 26 25 24 23 0 1 1 1 1 1 0 1 0 h 0 000 0000 0000 1001 0111 011 0 最高4位表示執行條件 1111無條件執行 101固定指令碼 h 0signed i...