?? vivi的代碼問題.txt
字號:
#endif
#if 0
@ SVC
mrs r0, cpsr
bic r0, r0, #0xdf
orr r1, r0, #0xd3
msr cpsr_all, r1
#endif
@ set GPIO for UART
mov r1, #GPIO_CTL_BASE
add r1, r1, #oGPIO_H
ldr r2, gpio_con_uart
str r2, [r1, #oGPIO_CON]
ldr r2, gpio_up_uart
str r2, [r1, #oGPIO_UP]
bl InitUART
#ifdef CONFIG_DEBUG_LL
@ Print current Program Counter
ldr r1, SerBase
mov r0, #'\r'
bl PrintChar
mov r0, #'\n'
bl PrintChar
mov r0, #'@'
bl PrintChar
mov r0, pc
bl PrintHexWord
#endif
#ifdef CONFIG_BOOTUP_MEMTEST
@ simple memory test to find some DRAM flaults.
bl memtest
#endif
#ifdef CONFIG_S3C2410_NAND_BOOT
bl copy_myself
@ jump to ram
ldr r1, =on_the_ram
add pc, r1, #0
nop
nop
1: b 1b @ infinite loop
on_the_ram:
#endif
#ifdef CONFIG_DEBUG_LL
ldr r1, SerBase
ldr r0, STR_STACK
bl PrintWord
ldr r0, DW_STACK_START
bl PrintHexWord
#endif
@ get read to call C functions
ldr sp, DW_STACK_START @ setup stack pointer
mov fp, #0 @ no previous frame, so fp=0
mov a2, #0 @ set argv to NULL
bl main @ call main
mov pc, #FLASH_BASE @ otherwise, reboot
@
@ End VIVI head
@
下面有幾個問題請教你。
1、
按照一般的彙編格式(應該是x86,以前就接觸過x86的),一般是定義數據段、代碼段,然後是start,。。。。。。,最後以end start結束。我看上面這段代碼並沒有遵循這種格式,不知其格式是不是跟x86是不一樣的?它的格式具體是如何?
2、
程序中有如下代碼:
@ VIVI magics
@
@ 0x20: magic number so we can verify that we only put
.long 0
@ 0x24:
.long 0
@ 0x28: where this vivi was linked, so we can put it in memory in the right place
.long _start
@ 0x2C: this contains the platform, cpu and machine id
.long ARCHITECTURE_MAGIC
@ 0x30: vivi capabilities
.long 0
是不是在定義幾個數據?.long是不是定義長整型數據?
3、
對於arm來說是基於流水線形式工作,指令存在「裝入空當」(Load Delay Slot)問題,gcc編譯器是不是可以對基於ARM的指令進行響應的優化操作?
4、
程序中
ENTRY(_start)
ENTRY(ResetEntryPoint)
是不是作為程序的入口?對於ENTRY的具體用法如何?
不好意思,問題有可能問的有些菜。謝謝。
Re: 請問linux的啟動程序vivi的代碼問題。
1。這個問題實際上比較簡單。據我所知arm上的bootloader一般都是先編譯成elf格式,然後用arm-linux-objcopy變成raw binary格式。raw binary格式其實就是一種平面格式,它會將elf中需要保留的section予以保留。其中數據節和代碼節是需要保留的。但是正如你所說,一般linux上的彙編源文件都不是按照標準的數據節,代碼節的規範寫,這就造成編譯器會從頭到尾的認為這個彙編程序就是一個代碼節。因此向這樣的代碼:
@ 0x1c: FIQ(Fast Interrupt Request) exception
FIQEntryPoint:
b HandleFIQ
@
@ VIVI magics
@
@ 0x20: magic number so we can verify that we only put
.long 0
@ 0x24:
.long 0
raw binay文件中會把那兩個。long定義的數據當作機器指令排在b HandleFIQ 的機器指令之後。
這種寫法好處就是不拘泥與格式,不用為內存分配考慮太多,頂多就是在類似.long這樣的數據聲明之前用絕對跳轉指令跳走就行了,儘管彙編器把.long當作代碼了,但是我們誰也不希望它會被執行吧(但是這種好處就是可以通過用數據的方式來表現機器指令,在x86的引導代碼中,就有一個地方是這麼做的)。如果你偏愛嚴格的節寫法,你可以在一開始就寫:
.text 0
直到遇到第一個數據聲明,這時用.data 0,然後再遇上第一個彙編代碼,寫.text 1。。。。。以此類推。
像你說的start,。。。。。。,end start這些都是彙編偽指令,彙編語句本身就和彙編器的聯繫相當緊密,所以不同的彙編器都會實現類似的偽指令,但語法上可能並不相同。
2。是在定義幾個數據 。.long嚴格說是字長,32位機是4字節;64位是8字節,這個你得info as,會有更詳細的說明(包括節的使用方法,原理等)
3。 這個我就不懂了 ^^
4.是入口點,ENTRY最長用的語法就是這樣,括號中加一個符號名,不過往往都要配合ld鏈接腳本使用。參見info ld,你會獲得更詳細的說明
Re: 請問linux的啟動程序vivi的代碼問題。
再次對growlanser表示感謝!
我一直在找關於vivi裡彙編格式的資料,是不是看info AS就可以了?我手頭就有BSD的info AS,是不是一樣的?
另外,對於ENTRY,代碼中
ENTRY(_start)
ENTRY(ResetEntryPoint)
其中的_start是後面.long _start所定義的嗎?
ResetEntryPoint呢?我在程序中沒找到。它是什麼意思?
Re: 請問linux的啟動程序vivi的代碼問題。
不是,_start這個符號是在鏈接腳本中被賦值的,你需要看一下編譯vivi時用到的那個Makefile,其中應該有類似 ld -T XXXX。lds這樣的語句,其中-T就是指定使用的鏈接腳本的名字,那裡定義了_start真正的物理地址。至於.long _start ,這句話相當於把_start這個符號的值讀出來,然後把該值存在這個位置,供以後使用。
ResetEntryPoint看字面意思就是復位以後的執行的位置吧,這個你得用grep去搜索了,另外同樣不要放過Makefile和鏈接腳本,ResetEntryPoint的信息可能也會在這兩個文件中提供。關於鏈接腳本的知識,得看info ld了
Re: 請問linux的啟動程序vivi的代碼問題。
謝謝growlanser
「至於.long _start ,這句話相當於把_start這個符號的值讀出來,然後把該值存在這個位置,供以後使用。 」
這裡是指把_start的物理地址保存嗎?那這裡可以不保存,直接引用該值,它這麼做不是多此一舉了嗎?
Re: 請問linux的啟動程序vivi的代碼問題。
1、
程序中有如下代碼:
LDR r3, =0x8000000
請問=在這裡的作用是什麼,是不是把0x8000000變成地址,上面的代碼意思是不是把0x8000000里面的內容存入r3中。
2、
是不是在gcc的彙編中可以採用一些C裡面約定的運算符,比如>> ,|等。
Re: 請問linux的啟動程序vivi的代碼問題。
建議看一下<<arm 體系結構與編程>> 這本書,裡面講得很清楚
Re: 請問linux的啟動程序vivi的代碼問題。
你問的是很基本的問題,你可以通過看書來更快的掌握,不用在論壇等人回答這麼辛苦。
arm architechure reference,用google搜索一下,很多地方都有的。
info as , info ld 看一下彙編器和鏈接器的文檔,那些什麼 .long 的你就明白了。
good luck
Re: 請問linux的啟動程序vivi的代碼問題。
謝謝答覆。
我也在看這本書,但是裡面滿多的格式和vivi裡面的是不一樣的。我主要是為了確認這些不同的地方。現在發現好多的編寫格式,搞得我暈頭啊。
Re: 請問linux的啟動程序vivi的代碼問題。
謝謝你的指點。
Re: 請問linux的啟動程序vivi的代碼問題。
請growlanser幫忙指點。謝謝
1、
程序中有如下代碼:
LDR r3, =0x8000000
請問『=』在這裡的作用是什麼,是不是把0x8000000變成地址,上面的代碼意思是不是把0x8000000里面的內容存入r3中。
2、
是不是在gcc的彙編中可以採用一些C裡面約定的運算符,比如>> ,|等。
Re: 請問linux的啟動程序vivi的代碼問題。
1。 出於編程方便的考慮,你在寫彙編的時候允許你只用一條指令就能將一個地址加載到指定的寄存器,但是你要以特殊的格式來寫,這樣編譯器才知道這個常數需要多條指令來處理,如果不以特殊格式寫,彙編器會報錯。這個特殊寫法就是常數前面的=.
比如:
ldr r2, =0xdeaddead
這裡的r2將保存0xdeaddead這個值。
你會說這樣作幹什麼。由於arm彙編訪內指令只有兩條,所以在對內存訪問的時候喜歡用基址+偏址的方式。比如你用了上面的ldr指令,緊接著你可能就要這麼用:
ldr r3, [r2, #0x01]
ldr r4, [r2, #0x02]
ldr r5, [r2, #0x03]
意思就是順次把0xdeaddead+1,+2,+3位置的寄存器或內存的值讀出來。這是一個習慣用法。
你也可以一下彙編器究竟是怎麼處理ldr r2, =0xdeaddead的
2.
可以。
ldr r2, =0xdeaddead >> 1這樣是允許的
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -