在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            ARM芯片詳解翻譯

            作者: 時(shí)間:2016-11-20 來源:網(wǎng)絡(luò) 收藏
            譯者注:這篇文章主要介紹了Risc結(jié)構(gòu)的PDA芯片組成和匯編程序,翻譯不周,肯定有錯(cuò)誤,請(qǐng)多包涵,另外我忘記了出處,這里向作者表示歉意。

            RISC處理器被廣泛應(yīng)用在小型設(shè)備上,例如PDA,移動(dòng)電話,智能熱水器等。有很多關(guān)于RISC處理器的匯編程序,但最常見的還是ARM。
            下面我要談的是ARM7,因?yàn)槲已芯康氖沁@個(gè)。
            讓我們先了解一下ARM的架構(gòu)。ARM處理器包含37個(gè)寄存器:31個(gè)通用的32位寄存器,以及6個(gè)狀態(tài)寄存器。寄存器的設(shè)置取決于處理器狀態(tài)。ARM狀態(tài)執(zhí)行32位指令,Thumb狀態(tài)執(zhí)行16位指令集。
            在ARM狀態(tài),有18個(gè)寄存器可用:可供直接存儲(chǔ)的R0―R15,CPSR(當(dāng)前程序狀態(tài)寄存器),SPSR(被存儲(chǔ)程序狀態(tài))。其中3個(gè)可直接存儲(chǔ)器被稱為服務(wù)寄存器。

            (R13)SP??堆棧指針
            (R14)LR??連接寄存器,用來存儲(chǔ)調(diào)用過程的函數(shù)地址(譯注:可簡(jiǎn)單理解為過程返回地址)。并且,LR并非存儲(chǔ)在堆棧中-它存在于寄存器中。
            (R15)PC??當(dāng)前指令指針。用一般的mov指令就可以改變它的值,從而執(zhí)行它所指向的命令。

            在Thumb狀態(tài),有13個(gè)寄存器可用:R0-R8,R13-R15,CPSR,SPSR

            狀態(tài)的改變,不會(huì)影響寄存器內(nèi)容的變化。
            如果想進(jìn)入Thumb狀態(tài),可以先將操作寄存器的狀態(tài)位設(shè)為1(bit1),然后執(zhí)行BX指令。如果想進(jìn)入ARM(譯注:原文誤為APM)狀態(tài),可以先將操作寄存器的狀態(tài)位設(shè)為0(bit0),然后執(zhí)行BX指令。
            2種狀態(tài)的指令集是不同的,但是很多指令都是類似的。Thumb指令集長(zhǎng)度為2bytes,ARM-4bytes。關(guān)于2種狀態(tài)指令的具體資料可以參考:http://www.atmel.com/dyn/resources/p...ts/doc0673.pdf
            有趣的是很多指令可以同時(shí)操作多個(gè)寄存器。例如:
            ADDR3,SP,#4相當(dāng)于: R3:=SP+4
            或者,用來存儲(chǔ)寄存器入棧的指令:
            PUSH{R2-R4,R7,LR} 這和x86匯編里面的pushad指令不同,在ARM匯編里面,這種將寄存器存入堆棧的方式是可行的。
            內(nèi)存中,數(shù)據(jù)存儲(chǔ)方式可以是低位存儲(chǔ)(例如Intel寄存器)或者高位存儲(chǔ)(例如Motorola寄存器)。所以,寫代碼時(shí)候,有必要指明數(shù)據(jù)存放方式。
            下面是一些ARM編譯器的資料:
            http://heanet.dl.sourceforge.net/sou...de-arm-win.exe-GNUcompilerwithallconsequences-allthroughcommandline+debuggingthroughgdb.

            http://www.goldroad.co.uk/grARM.html-unpretentiousARMassembler.

            http://www.arm.com/support/downloads/index.html-officialtoolsforARM’sdevelpment.Hereyoucanonlybuythem.

            http://www.iar.com/-alternativetoIDAforARM.30-daystrialversionisoffered.
            下面講解一下由C++的ARM編譯器生成的ARM匯編程序。
            一般地,分析不同程序的時(shí)候,經(jīng)常碰到的并不是純粹的匯編語(yǔ)言,而是由C++編譯器生成的代碼。當(dāng)然,x86匯編程序員一般不會(huì)如此。
            函數(shù)調(diào)用:
            這里不存在函數(shù)參數(shù)調(diào)用約定(例如cdecl,stdcall等)!所有的函數(shù)調(diào)用約定類似于Borland的fastcall。參數(shù)由寄存器傳入,如果數(shù)目不夠,由堆棧傳入。
            例如:
            ROM:0001F4E2MOVR0,SP

            ROM:0001F4E4MOVR2,*6

            ROM:0001F4E6ADDR1,R4,*0

            ROM:0001F4E8BLmemcmp
            參數(shù)的傳遞順序?qū)?yīng)于寄存器編號(hào),R0為第一個(gè),R1為第二個(gè),R2為第三個(gè)(譯注:比較有意思)。相當(dāng)于:
            intmemcmp(

            constvoid*buf1,

            constvoid*buf2,

            size_tcount

            );
            buf1=R0

            buf2=R1

            count=R2

            函數(shù)返回值被存放在R0中:
            ROM:0001F4E2MOVR0,SP

            ROM:0001F4E4MOVR2,*6

            ROM:0001F4E6ADDR1,R4,*0

            ROM:0001F4E8BLmemcmp

            ROM:0001F4ECCMPR0,*0

            ROM:0001F4EEBNEloc_1F4F4
            下面是一個(gè)利用堆棧傳遞參數(shù)的例子:
            ROM:000BCDECMOVR2,*0

            ROM:000BCDEESTRR2,[SP]

            ROM:000BCDF0MOVR2,*128

            ROM:000BCDF2MOVR3,*128

            ROM:000BCDF4MOVR1,*14

            ROM:000BCDF6MOVR0,*0

            ROM:000BCDF8BLFillBoxColor
            上面,R0-R3存儲(chǔ)坐標(biāo),第5個(gè)參數(shù)(色彩)被存放在堆棧中。

            只有通過分析才可以確定操作數(shù)的數(shù)目。我們可以分析函數(shù)和它的調(diào)用部分。有時(shí)候,參數(shù)信息可以通過對(duì)寄存器和堆棧的操作觀察出來。例如,在Thumb狀態(tài)下,程序?qū)Γ遥埃遥泛头?wù)寄存器的操作。所以,如果看到類似于下面的代碼:
            ROM:00059ADAgetTextBounds

            ROM:00059ADAPUSH{R4-R7,LR},
            可以認(rèn)為它的參數(shù)被存放在R0,R1,R2,R3和SP。如果見到:
            ROM:0005924EADDR0,SP,*0x14

            ROM:00059250ADDR1,SP,*0x6C

            ROM:00059252ADDR2,SP,*0x68

            ROM:00059254ADDR3,SP,*0x64

            ROM:00059256BLgetTextBounds
            我們看到只有R0-R3被使用,就是說只有4個(gè)參數(shù)被傳遞過來。

            轉(zhuǎn)移(Transitions)
            一般,轉(zhuǎn)移分為條件轉(zhuǎn)移和無條件轉(zhuǎn)移。轉(zhuǎn)移目標(biāo)可以存放在寄存器或者其他處。寄存器轉(zhuǎn)移一般用于Thumb/ARM狀態(tài)轉(zhuǎn)換。無條件短轉(zhuǎn)移指令為B(branch)命令。長(zhǎng)跳轉(zhuǎn)指令-BX(交換轉(zhuǎn)移)。函數(shù)調(diào)用采用BL(連接轉(zhuǎn)移),且調(diào)用時(shí)將返回地址存入LR寄存器。當(dāng)然,改變PC寄存器內(nèi)容也可以改變轉(zhuǎn)移地址:
            ADDPC,*0x64
            但是C編譯器通常不這樣處理,它們?cè)谵D(zhuǎn)移的時(shí)候,只是以寫入命令改變PC寄存器。

            分支(Branches)
            也稱為轉(zhuǎn)換,一般用法如下:
            ROM:0027806ECMPR2,*0x4D;M

            ROM:00278070BCSloc_27807A

            ROM:00278072ADRR3,word_27807C

            ROM:00278074ADDR3,R3,R2

            ROM:00278076LDRHR3,[R3,R2]

            ROM:00278078ADDPC,R3

            ROM:0027807A

            ROM:0027807Aloc_27807A

            ROM:0027807ABloc_278766

            ROM:0027807Cword_27807CDCW0xAA,0xBE,0xC6,0x180,0x186;0

            ROM:0027807CDCW0x190,0x1A0,0x1A8,0x1DE,0x1E4;5

            ROM:0027807CDCW0x1B0,0x212,0x276,0x1FE,0x294;10
            首先,檢查跳轉(zhuǎn)標(biāo)記,該標(biāo)記必須小于0x40,如果大于,則跳到默認(rèn)處理位置,即:loc_27807A。
            然后執(zhí)行位于word_27807C的轉(zhuǎn)移控制表。這個(gè)表里面存放的是偏移,并非地址。隨后,根據(jù)跳轉(zhuǎn)標(biāo)記,取表中的偏移,擴(kuò)展之,加操作放入PC寄存器。比如,如果跳轉(zhuǎn)標(biāo)記為0,將會(huì)跳轉(zhuǎn)到地址:
            0x278078(currentvaluePC)+0xAA(offsetfromthetable)+0x4(!!!)=0x278126
            之所以加4,是因?yàn)椋粒遥吞幚砥鞯奶卣鳎翰僮鳎校眉拇嫫鲿r(shí),其值應(yīng)該比預(yù)先確定的數(shù)值大4(在文檔“toensureitiswordaligned”中有說明)。

            內(nèi)存存取

            在Thumb狀態(tài),處理器可以存取+/-256字節(jié)的空間。因此,無法直接存取內(nèi)存,而需要利用寄存器來引導(dǎo)。也就是無法直接定位到0x974170,而需要采用寄存器。例如:
            ROM:00277FF6LDRR0,=unk_974170

            ROM:00277FF8LDRR0,[R0]
            我們獲得了0x974170處的數(shù)據(jù),但是事情還沒有結(jié)束!該有效地址(0x974170)處于有效的正負(fù)256字節(jié)中:
            ROM:00278044off_278044DCDunk_974170
            這樣,就是說,LDR指令的機(jī)器碼中存儲(chǔ)了該命令當(dāng)前的地址。(譯注:就是說0x974170雖然看起來比較大,實(shí)際上還是那+-256字節(jié)內(nèi),只不過通過LDR指令來定位)
            這里存在一個(gè)很藝術(shù)的優(yōu)化方法:如果一個(gè)地址和該函數(shù)中另外一個(gè)被用到的地址有關(guān)聯(lián),那么這個(gè)地址可以通過算術(shù)運(yùn)算指令或者間接存取來獲取。舉例來說,如果一個(gè)函數(shù)需要用到0x100000處的變量,并且需要用到0x100150處的另外一個(gè)變量,那么,編譯器可以將這2個(gè)變量建立關(guān)聯(lián),或者采用以下代碼:
            LDRR0,=0x100000

            ADDR0,*0xFF

            ADDR0,*0x51

            LDRR0,[R0]
            在x86里面,這種方法應(yīng)用于結(jié)構(gòu)中獲取子結(jié)構(gòu)接口。但是此處,卻是一個(gè)常用的優(yōu)化,這有什么好處呢?可以減小內(nèi)存存儲(chǔ),并且算術(shù)運(yùn)算比數(shù)據(jù)加載快得多??梢哉J(rèn)為整個(gè)ARM匯編程序充滿了不同的寄存器間算術(shù)運(yùn)算。事實(shí)上,有多達(dá)16個(gè)寄存器用來進(jìn)行此操作-減少內(nèi)存和堆棧定位頻度。因此,只有在非常大的函數(shù)中才需要用堆棧存儲(chǔ)變量。對(duì)堆棧的操作和x86處理堆棧的方式一樣。

            IDA中的代碼分析

            既然ARM文件沒有統(tǒng)一格式,那么在加載ARM二進(jìn)制映像的時(shí)候,有必要先加載該文件。在加載的時(shí)候,需要確定處理器類型。如果處理器規(guī)定代碼必須按照處理器模塊處理順序,那么你可以加載映像文件并且指定需要的處理方式,ARM處理方式(低位處理)或者ARMB(高位處理)。并且,有必要建立ROM或者RAM段??傊疀]有固定的處理方式,具體的處理有賴于映像和每個(gè)ARM處理器的架構(gòu)。例如,在ARM7中,內(nèi)存一般有如下格式:
            0x0-0x8000ofRAMprocessor

            0x8000-0x1000000ROM

            0x1000000-0x.....-SRAM(這里看出自身數(shù)目)
            現(xiàn)在就可以分析代碼了,在很多設(shè)備中(一般都是移動(dòng)電話),代碼的入口設(shè)定為0x8000。ARM模式下的代碼從0x8000開始執(zhí)行,所以,開始執(zhí)行的指令和該處的一樣。處理器的IDA模塊可以簡(jiǎn)單地分析此類switching語(yǔ)句,然后Thumb代碼在ARM中執(zhí)行。如果手工修改跳轉(zhuǎn),可以按ALT-G,然后修改文件中的標(biāo)記,如果為ARM文件,設(shè)為0,Thumb文件,設(shè)為1。


            關(guān)鍵詞: ARM芯片詳

            評(píng)論


            技術(shù)專區(qū)

            關(guān)閉