在點燈程式中,想看看超過位址空間的結果,於是做了個試驗,修改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 載入執行位址...