Tiny4412裸机程序之代码重定位初体验
轉(zhuǎn)載:http://www.techbulo.com/1412.html
從前面一節(jié)Exynos 4412的啟動過程分析?,我們知道:一上電,exynos4412首先執(zhí)行固化在IROM中的代碼,iROM首先設(shè)置程序運行環(huán)境 (比如關(guān)看門狗、關(guān)中斷、關(guān)MMU 、設(shè)置棧 、設(shè)置棧 、啟動PLL等 ),然后根據(jù)OM引腳確定啟動設(shè)備 (NAND Flash/SD 卡/其他 ),把 BL1從里面讀出存入iRAM的0x02021400地址處,最后啟動 BL1;?BL1從SD卡適當(dāng)?shù)奈恢米x入14K 字節(jié)的數(shù)據(jù),存在iRAM地址0x02023400處,所以BL2不能大于(14K – 4) 字節(jié),這里引出了為什么寫這一節(jié)的原因:如果我們的程序很大,大于14K怎么辦????
下面我們先來介紹兩個概念:
一是程序當(dāng)前所處的地址,即程序在運行時,所處的當(dāng)前地址;二是程序的鏈接地址,即程序運行時應(yīng)該位于的運行地址。編譯程序時,可以指定程序的鏈接地址。
什么是重定位
對于Tiny4412而言,前面我們已經(jīng)說過:啟動時BL1只會從sd等啟動設(shè)備中拷貝14K的代碼到IRAM中,那么當(dāng)我們的程序超過14K怎么辦?那就需要我們在前14K的代碼中將整個程序完完整整地拷貝到DRAM等其他更大存儲空間,然后再跳轉(zhuǎn)到DRAM中繼續(xù)運行我們的代碼,這個拷貝然后跳轉(zhuǎn)的過程就叫重定位。
本章中我們主要學(xué)習(xí)如何重定位,但是并不會涉如何使用到DRAM,而是簡單地將代碼從IRAM的0x02023400處拷貝到IRAM的0x0202a000處,然后跳轉(zhuǎn)到0x0202a000處繼續(xù)運行我們的代碼。
?
一、程序說明
基于上一個實驗的代碼進行修改,修改了start,S文件以及鏈接腳本文件:
在start.S文件中增加如下代碼:
| 1234567891011121314151617181920212223242526272829 | //重定位 - 將代碼從0x02023400處拷貝到鏈接地址0x0202a000處(在鏈接腳本里指定的),并跳轉(zhuǎn)到這個地址去執(zhí)行adr r0, _start //adr指令用于讀取_start在當(dāng)前的運行的物理地址,即0x02023400ldr r1, =_start //讀取_start的鏈接地址,即0x0202a000ldr r2, =bss_start // 讀取bss段的起始地址,用于計算需要拷貝的字節(jié)多少cmp r0, r1beq clean_bss //如果r0=r1,則跳轉(zhuǎn)到clean_bss,說明此時已經(jīng)在鏈接地址處了//如果r0!=r1,則進行如下的拷貝copy_loop:ldr r3, [r0], #4 // 源str r3, [r1], #4 // 目的cmp r1, r2 // 判斷是否已經(jīng)拷貝完bne copy_loop // 如果沒有拷貝完就繼續(xù)拷貝// 清bss段clean_bss:ldr r0, =bss_start //r0保存bss段的起始地址ldr r1, =bss_end //r1保存bss段的起始地址cmp r0, r1beq run_on_dram //如果r0=r1,則跳轉(zhuǎn)到run_on_dram,說明bss段里邊沒有變量mov r2, #0clear_loop:str r2, [r0], #4cmp r0, r1bne clear_loop// 跳轉(zhuǎn)run_on_dram:ldr pc, =main //執(zhí)行完這句話之后,PC就指向了main的鏈接地址 |
這段代碼主要實現(xiàn)了代碼重定位、清除BSS段、以及跳轉(zhuǎn)到鏈接地址繼續(xù)運行,注釋說的已經(jīng)很明白了,有什么的不熟悉的,大家可以留言共同探討。
鏈接腳本reload.lds修改為如下:
| 123456789101112131415 | SECTIONS {. = 0x0202a000;.text : {start.o* (.text)}.data : {* (.data)}bss_start = .;.bss : {* (.bss)}bss_end = .;} |
主要增加了bss段的起始bss_start及結(jié)束bss_end 的定義,這兩個標(biāo)號在start.S中被用到。
二、編譯、燒寫、運行
1.編譯
通過FTP或者其他工具將文件上傳到服務(wù)器上去,輸入make命令進行編譯將得到reload.bin文件。
2.燒寫
將SD卡插入電腦,并讓VmWare里的Ubuntu識別出來,然后執(zhí)行如下命令:
| 1 | sudo ./sd_fusing.sh /dev/sdb ../8_reload/reload.bin |
將SD卡插入Tiny4412開發(fā)板,上電,你會看到和上一節(jié)的運行效果一樣(因為我們沒有修改LED的顯示效果,只是修改了程序的運行地址,這個對外是看不出區(qū)別的)。
三、反匯編文件分析
將反匯編文件reload.dis,從服務(wù)器上下載下來,我們進行簡單分析一下:
反匯編文件1
從上圖可以看出,程序的鏈接地址確實是我們在連接腳本里指定的0x0202a000
反匯編文件2
我們再來看看跳轉(zhuǎn)的那條指令;
| 1 | 202a064: e59ff01c ldr pc, [pc, #28] ; 202a088 <halt_loop+0x18> |
將當(dāng)前PC的值加上28后的地址的內(nèi)容賦給PC,即:
0x202a064 + 8 + 28 = 0x202a088
將0x202a088這個地址的值賦給PC
反匯編文件3
即PC指向0x0202a22c這個地址,我們繼續(xù)往下看,發(fā)現(xiàn):
反匯編文件4
0x0202a22c這個地址正是main函數(shù)的入口地址。
?
上一張運行的圖片:
運行效果
?
完整的程序下載地址(解壓密碼:WWW.techbulo.Com):
下載地址總結(jié)
以上是生活随笔為你收集整理的Tiny4412裸机程序之代码重定位初体验的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ubuntu14.04 wps字体缺失问
- 下一篇: JUSTCTF2020 新生赛(校内)w