<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          ARM芯片詳解翻譯

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

          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è)寄存器可用:可供直接存儲的R0―R15,CPSR(當(dāng)前程序狀態(tài)寄存器),SPSR(被存儲程序狀態(tài))。其中3個(gè)可直接存儲器被稱為服務(wù)寄存器。

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

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

          狀態(tài)的改變,不會影響寄存器內(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指令集長度為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
          或者,用來存儲寄存器入棧的指令:
          PUSH{R2-R4,R7,LR} 這和x86匯編里面的pushad指令不同,在ARM匯編里面,這種將寄存器存入堆棧的方式是可行的。
          內(nèi)存中,數(shù)據(jù)存儲方式可以是低位存儲(例如Intel寄存器)或者高位存儲(例如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)常碰到的并不是純粹的匯編語言,而是由C++編譯器生成的代碼。當(dāng)然,x86匯編程序員一般不會如此。
          函數(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)于寄存器編號,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存儲坐標(biāo),第5個(gè)參數(shù)(色彩)被存放在堆棧中。

          只有通過分析才可以確定操作數(shù)的數(shù)目。我們可以分析函數(shù)和它的調(diào)用部分。有時(shí)候,參數(shù)信息可以通過對寄存器和堆棧的操作觀察出來。例如,在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)命令。長跳轉(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編譯器通常不這樣處理,它們在轉(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,將會跳轉(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ī)器碼中存儲了該命令當(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)存存儲,并且算術(shù)運(yùn)算比數(shù)據(jù)加載快得多??梢哉J(rèn)為整個(gè)ARM匯編程序充滿了不同的寄存器間算術(shù)運(yùn)算。事實(shí)上,有多達(dá)16個(gè)寄存器用來進(jìn)行此操作-減少內(nèi)存和堆棧定位頻度。因此,只有在非常大的函數(shù)中才需要用堆棧存儲變量。對堆棧的操作和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模塊可以簡單地分析此類switching語句,然后Thumb代碼在ARM中執(zhí)行。如果手工修改跳轉(zhuǎn),可以按ALT-G,然后修改文件中的標(biāo)記,如果為ARM文件,設(shè)為0,Thumb文件,設(shè)為1。


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

          評論


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

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();