深入分析S3C2440啟動(dòng)代碼中大小端問題
一、ADS1.2中關(guān)于大小端的設(shè)置以及對(duì)編譯后的代碼的影響
下面是一段代碼在線段模式下編譯,生成的二進(jìn)制文件的內(nèi)容
大端模式下編譯,生成二進(jìn)制文件的內(nèi)容
根據(jù)上面的內(nèi)容可以看出:它們的字節(jié)序是相反的,也就是說,ADS1.2中對(duì)大小端的設(shè)置會(huì)影響最終生成的二進(jìn)制文件的字節(jié)序。
二、S3C2440啟動(dòng)代碼中與大小管相關(guān)的代碼
Option.inc中相關(guān)代碼
本文引用地址:http://m.butianyuan.cn/article/201611/319967.htm
2440init.s中相關(guān)代碼
[plain]view plaincopyprint?
- GBLLENDIAN_CHANGE
- NDIAN_CHANGESETL{FALSE}
- GBLAENTRY_BUS_WIDTH
- NTRY_BUS_WIDTHSETA16
2440init.s中相關(guān)代碼
[plain]view plaincopyprint?
- AREAInit,CODE,READONLY
- ENTRY
- EXPORT__ENTRY
- __ENTRY
- ResetEntry
- ;1)Thecode,whichconvertstoBig-endian,shouldbeinlittleendiancode.
- ;2)ThefollowinglittleendiancodewillbecompiledinBig-Endianmode.
- ;Thecodebyteordershouldbechangedasthememorybuswidth.
- ;3)Thepseudoinstruction,DCDcannotbeusedherebecausethelinkergenerateserror.
- ASSERT:DEF:ENDIAN_CHANGE
- [ENDIAN_CHANGE
- ASSERT:DEF:ENTRY_BUS_WIDTH
- [ENTRY_BUS_WIDTH=32
- bChangeBigEndian;DCD0xea000007
- ]
- [ENTRY_BUS_WIDTH=16
- andeqr14,r7,r0,lsl#20;DCD0x0007ea00
- ]
- [ENTRY_BUS_WIDTH=8
- streqr0,[r0,-r10,ror#1];DCD0x070000ea
- ]
- |
- bResetHandler
- ]
- bHandlerUndef;handlerforUndefinedmode
- bHandlerSWI;handlerforSWIinterrupt
- bHandlerPabort;handlerforPAbort
- bHandlerDabort;handlerforDAbort
- b.;reserved
- bHandlerIRQ;handlerforIRQinterrupt
- bHandlerFIQ;handlerforFIQinterrupt
- ;@0x20
- bEnterPWDN;Mustbe@0x20.
- ChangeBigEndian
- ;@0x24
- [ENTRY_BUS_WIDTH=32
- DCD0xee110f10;0xee110f10=>mrcp15,0,r0,c1,c0,0
- DCD0xe3800080;0xe3800080=>orrr0,r0,#0x80;//Big-endian
- DCD0xee010f10;0xee010f10=>mcrp15,0,r0,c1,c0,0
- ]
- [ENTRY_BUS_WIDTH=16
- DCD0x0f10ee11
- DCD0x0080e380
- DCD0x0f10ee01
- ]
- [ENTRY_BUS_WIDTH=8
- DCD0x100f11ee
- DCD0x800080e3
- DCD0x100f01ee
- ]
- DCD0xffffffff;swinv0xffffffissimilarwithNOPandrunwellinbothendianmode.
- DCD0xffffffff
- DCD0xffffffff
- DCD0xffffffff
- DCD0xffffffff
- bResetHandler
現(xiàn)在,我們?cè)贏DS1.2中設(shè)為打斷模式,并把ENDIAN_CHANGE設(shè)置FALSE設(shè)為TURE,現(xiàn)在問題就來(lái)了,請(qǐng)看下面的分析。
在編譯程序時(shí),根據(jù)ENTRY_BUS_WIDTH宏會(huì)將下面三條指令的之一放在0地址處
b ChangeBigEndian ;DCD 0xea000007
andeq r14,r7,r0,lsl #20 ;DCD 0x0007ea00
streq r0,[r0,-r10,ror #1] ;DCD 0x070000ea
andeq r14,r7,r0,lsl #20 ;DCD 0x0007ea00
streq r0,[r0,-r10,ror #1] ;DCD 0x070000ea
其實(shí)這三條指令的功能都是一樣,只是根據(jù)數(shù)據(jù)帶寬調(diào)整了字節(jié)序,都是跳轉(zhuǎn)到0x24處的ChangeBigEndian執(zhí)行,ChangeBigEndian的作用就是通過協(xié)處理CP15中的寄存器C1來(lái)改變S3C2440的大小端模式。
先來(lái)看一下這三條指令。因?yàn)槲覀円呀?jīng)在ADS中設(shè)置為大端模式,所以這些指令是以大端模式進(jìn)行編譯的,而S3C2440此時(shí)還是小端模式,S3C2440怎么能執(zhí)行大端模式下的指令呢,比如b ChangeBigEndian ;DCD 0xea000007???
原因如下:
如果一個(gè)基于 ARM 芯片將存儲(chǔ)器系統(tǒng)配置為其中一種存儲(chǔ)器格式(如小端) ,而實(shí)際連接的存儲(chǔ)器系統(tǒng)配置為相反的格式(如大端) ,那么只有以字為單位的指令取指、數(shù)據(jù)裝載和數(shù)據(jù)保存能夠可靠實(shí)現(xiàn)。其它的存儲(chǔ)器訪問將出現(xiàn)不可預(yù)期的結(jié)果。也就就是說在32位模式下,大小端模式對(duì)指令取指、數(shù)據(jù)裝載和數(shù)據(jù)保存沒有影響。(注意:如果實(shí)際的存儲(chǔ)器格式與芯片的存儲(chǔ)器格式不符時(shí),只有以字為單位的數(shù)據(jù)存取才正確,否則將出現(xiàn)不可預(yù)期的結(jié)果。)
b ChangeBigEndian在大端模式下機(jī)器碼是0xea000007,這是32位模式下,其四個(gè)字節(jié)從低到高分別是:07 00 00 ea。那沒b ChangeBigEndian這條指令在8位模式下,要被小端模式的S3C2440執(zhí)行,就要人為的修改為0x070000ea。在存儲(chǔ)器中存儲(chǔ)的順序:從低地址到高地址分別是 07 00 00 ea,S3C2440按小端模式取指令時(shí),取得是0xea000007。
b ChangeBigEndian這條指令在16位模式下,要被小端模式的S3C2440執(zhí)行,就要人為的修改為0x0007ea00。在存儲(chǔ)器中存儲(chǔ)的順序:從低地址到高地址分別是 0007 ea00,S3C2440按小端模式取指令時(shí),取得是0xea000007。
后面修改協(xié)處理CP15中的寄存器C1的代碼時(shí)類似的。
評(píng)論