連線位址與位置無關指令

2021-09-26 19:07:38 字數 1173 閱讀 9984

在點燈程式中,想看看超過位址空間的結果,於是做了個試驗,修改makefile中的連線位址為0xfffffffc,如下所示。

root@ubuntu:~/work/led_on_c# cat makefile

all:

arm-linux-gcc -c -o led.o led.c

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

arm-linux-ld -ttext 0xfffffffc start.o led.o -o led.elf

arm-linux-objcopy -o binary -s led.elf led.bin

arm-linux-objdump -d led.elf > led.dis

clean:

rm *.bin *.o *.elf *.dis

編譯燒寫到nand中,復位後指示燈仍然能點亮。我認為超過位址空間了cpu就找不到程式執行的位址了,那它就不能正常工作啊,但是實驗結果是它還能正常工作,感覺很奇怪,於是開啟反彙編**,如下所示:

fffffffc <_start>:

fffc: e3a0da01 mov sp, #4096 ; 0x1000

0: address 0x0 is out of bounds.

disassembly of section .comment:

00000000 <.comment>:

0: 43434700 cmpmi r3, #0 ; 0x0

4: 4728203a undefined

8: 2029554e eorcs r5, r9, lr, asr #10

c: 2e342e33 mrccs 14, 1, r2, cr4, cr3,

10: address 0x10 is out of bounds.

如上所示,反彙編有效**只有2行,這是符合我的預期的。但是為什麼還是能正常執行呢?通過查詢資料,有一種說法我認為很有道理,記錄下來。如下:

位置無關指令(比如這裡用的 bl ***x 就是位置無關指令)是將pc加上(或減去)絕對偏移值得到實際指令的位址,再跳到這個位址去執行,它不會管**被連線後指令應該在的位址,也不管程式當前位置處於rom還是ram,它只會加上偏移值(如這裡是pc+8後跳到main處執行)。而位置相關指令(如ldr指令)它是相對偏移,它會將連線位址賦給pc,pc再跳到連線位址處去執行。

鏈結位址與執行位址

32位的處理器,它的每一條指令是4個位元組順序儲存,cpu是順序執行的,只要沒發生什麼跳轉,它會順序進行執行這些指令,編譯器對 中的變數名 函式名等東西進行乙個位址的編排,賦予這些抽象的東西乙個位址,然後在程式中訪問這些變數名 函式名就是在訪問一些位址,這些位址我們稱之為編譯位址。是指程式指令真正執...

嵌入式學習 賦值 編譯 連線位址問題

1 假設p1 0x12345678 需要把第二位置為1,即p1 0x1234567a,在具體賦值時,採用如下方式為常見做法。1.重置 p1 p1 0xfffffff0 2.賦值 p1 p1 0x0000000a 注意按位或 與邏輯或 的區別。2 將p1 0b01011010前4位轉為1100。1.重...

關於SPV210鏈結位址與執行位址的筆記

位置無關碼取值 是通過指令間相對位址取值,而有關碼是通過絕對位址來定址。在arm中最開始的幾句 都是位置無關 採用bl或者b進行跳轉,而有關碼通過ldr pc,lable 進行跳轉,其中lable為鏈結位址。位置有關碼保證鏈結位址與執行位址一致程式才能正常執行。adr r0 start 載入執行位址...