ARM晶片詳解[翻譯]
標 題:ARM晶片詳解[翻譯]
發信人:nbw
時 間:2004-12-20,19:45
詳細資訊:
ARM晶片詳解
作者:不詳
翻譯:nbw
譯者注:這篇文章主要介紹了Risc結構的PDA晶片組成和彙編程式,翻譯不周,肯定有錯誤,請多包涵,另外我忘記了出處,這裡向作者表示歉意。
RISC處理器被廣泛應用在小型裝置上,例如PDA,行動電話,智慧熱水器等。有很多關於RISC處理器的彙編程式,但最常見的還是ARM。
下面我要談的是ARM 7,因為我研究的是這個。
讓我們先了解一下ARM的架構。ARM處理器包含37個暫存器:31個通用的32位暫存器,以及6個狀態暫存器。暫存器的設定取決於處理器狀態。ARM狀態執行32位指令,Thumb狀態執行16位指令集。
在ARM狀態,有18個暫存器可用:可供直接儲存的R0―R15,CPSR(當前程式狀態暫存器),SPSR(被儲存程式狀態)。其中3個可直接儲存器被稱為服務暫存器。
(R13)SP DD堆疊指標
(R14)LRDD連線暫存器,用來儲存呼叫過程的函式地址(譯註:可簡單理解為過程返回地址)。並且,LR並非儲存在堆疊中-它存在於暫存器中。
(R15)PCDD當前指令指標。用一般的mov指令就可以改變它的值,從而執行它所指向的命令。
在Thumb 狀態,有13個暫存器可用:R0-R8, R13-R15, CPSR, SPSR
狀態的改變,不會影響暫存器內容的變化。
如果想進入Thumb狀態,可以先將操作暫存器的狀態位設為1(bit 1),然後執行BX指令。如果想進入ARM (譯註:原文誤為APM)狀態,可以先將操作暫存器的狀態位設為0(bit 0),然後執行BX指令。
2種狀態的指令集是不同的,但是很多指令都是類似的。Thumb指令集長度為2bytes,ARM-4bytes。關於2種狀態指令的具體資料可以參考: http://www.atmel.com/dyn/resources/prod_documents/doc0673.pdf
有趣的是很多指令可以同時操作多個暫存器。例如:
ADD R3, SP, #4 相當於: R3:=SP+4
或者,用來儲存暫存器入棧的指令:
PUSH {R2-R4, R7, LR} 這和x86彙編裡面的pushad指令不同,在ARM彙編裡面,這種將暫存器存入堆疊的方式是可行的。
記憶體中,資料儲存方式可以是低位儲存(例如Intel暫存器)或者高位儲存(例如Motorola暫存器)。所以,寫程式碼時候,有必要指明資料存放方式。
下面是一些ARM編譯器的資料:
http://heanet.dl.sourceforge.net/sourceforge/gnude/gnude-arm-win.exe - GNU compiler with all consequences - all through command line + debugging through gdb.
http://www.goldroad.co.uk/grARM.html - unpretentious ARM assembler.
http://www.arm.com/support/downloads/index.html - official tools for ARM’s develpment. Here you can only buy them.
http://www.iar.com/ - alternative to IDA for ARM. 30-day's trial version is offered.
下面講解一下由C++的ARM編譯器生成的ARM彙編程式。
一般地,分析不同程式的時候,經常碰到的並不是純粹的組合語言,而是由C++編譯器生成的程式碼。當然,x86彙編程式設計師一般不會如此。
函式呼叫:
這裡不存在函式引數呼叫約定(例如cdecl,stdcall 等)!所有的函式呼叫約定類似於Borland的fastcall。引數由暫存器傳入,如果數目不夠,由堆疊傳入。
例如:
ROM:0001F4E2 MOV R0, SP
ROM:0001F4E4 MOV R2, *6
ROM:0001F4E6 ADD R1, R4, *0
ROM:0001F4E8 BL memcmp
引數的傳遞順序對應於暫存器編號,R0為第一個,R1為第二個,R2為第三個(譯註:比較有意思)。相當於:
int memcmp (
const void *buf1,
const void *buf2,
size_t count
);
buf1 = R0
buf2 = R1
count = R2
函式返回值被存放在R0中:
ROM:0001F4E2 MOV R0, SP
ROM:0001F4E4 MOV R2, *6
ROM:0001F4E6 ADD R1, R4, *0
ROM:0001F4E8 BL memcmp
ROM:0001F4EC CMP R0, *0
ROM:0001F4EE BNE loc_1F4F4
下面是一個利用堆疊傳遞引數的例子:
ROM:000BCDEC MOV R2, *0
ROM:000BCDEE STR R2, [SP]
ROM:000BCDF0 MOV R2, *128
ROM:000BCDF2 MOV R3, *128
ROM:000BCDF4 MOV R1, *14
ROM:000BCDF6 MOV R0, *0
ROM:000BCDF8 BL FillBoxColor
上面,R0-R3儲存座標,第5個引數(色彩)被存放在堆疊中。
只有透過分析才可以確定運算元的數目。我們可以分析函式和它的呼叫部分。有時候,引數資訊可以透過對暫存器和堆疊的操作觀察出來。例如,在Thumb狀態下,程式對R0-R7和服務暫存器的操作。所以,如果看到類似於下面的程式碼:
ROM:00059ADA getTextBounds
ROM:00059ADA PUSH {R4-R7, LR},
可以認為它的引數被存放在R0,R1,R2,R3和SP。如果見到:
ROM:0005924E ADD R0, SP, *0x14
ROM:00059250 ADD R1, SP, *0x6C
ROM:00059252 ADD R2, SP, *0x68
ROM:00059254 ADD R3, SP, *0x64
ROM:00059256 BL getTextBounds
我們看到只有R0-R3被使用,就是說只有4個引數被傳遞過來。
轉移(Transitions )
一般,轉移分為條件轉移和無條件轉移。轉移目標可以存放在暫存器或者其他處。暫存器轉移一般用於Thumb/ARM 狀態轉換。無條件短轉移指令為B(branch)命令。長跳轉指令-BX(交換轉移)。函式呼叫採用BL(連線轉移),且呼叫時將返回地址存入LR暫存器。當然,改變PC暫存器內容也可以改變轉移地址:
ADD PC, *0x64
但是C編譯器通常不這樣處理,它們在轉移的時候,只是以寫入命令改變PC暫存器。
分支(Branches)
也稱為轉換,一般用法如下:
ROM:0027806E CMP R2, *0x4D; 'M'
ROM:00278070 BCS loc_27807A
ROM:00278072 ADR R3, word_27807C
ROM:00278074 ADD R3, R3, R2
ROM:00278076 LDRH R3, [R3, R2]
ROM:00278078 ADD PC, R3
ROM:0027807 A
ROM:0027807 A loc_27807A
ROM:0027807 A B loc_278766
ROM:0027807 C word_27807C DCW 0xAA, 0xBE, 0xC6, 0x180, 0x186; 0
ROM:0027807 C DCW 0x190, 0x1A0, 0x1A8, 0x1DE, 0x1E4; 5
ROM:0027807 C DCW 0x1B0, 0x212, 0x276, 0x1FE, 0x294; 10
首先,檢查跳轉標記,該標記必須小於0x40,如果大於,則跳到預設處理位置,即:loc_27807A。
然後執行位於word_27807C 的轉移控制表。這個表裡面存放的是偏移,並非地址。隨後,根據跳轉標記,取表中的偏移,擴充套件之,加操作放入PC暫存器。比如,如果跳轉標記為0,將會跳轉到地址:
0x278078 (current value PC) +0xAA (offset from the table) + 0x4 (!!!) = 0x278126
之所以加4,是因為ARM處理器的特徵:操作PC暫存器時,其值應該比預先確定的數值大4(在文件“to ensure it is word aligned ”中有說明)。
記憶體存取
在Thumb狀態,處理器可以存取256 位元組的空間。因此,無法直接存取記憶體,而需要利用暫存器來引導。也就是無法直接定位到0x974170,而需要採用暫存器。例如:
ROM:00277FF6 LDR R0, =unk_974170
ROM:00277FF8 LDR R0, [R0]
我們獲得了0x974170處的資料,但是事情還沒有結束!該有效地址(0x974170)處於有效的正負256 位元組中:
ROM:00278044 off_278044 DCD unk_974170
這樣,就是說,LDR指令的機器碼中儲存了該命令當前的地址。(譯註:就是說0x974170雖然看起來比較大,實際上還是那+-256位元組內,只不過透過LDR指令來定位)
這裡存在一個很藝術的最佳化方法:如果一個地址和該函式中另外一個被用到的地址有關聯,那麼這個地址可以透過算術運算指令或者間接存取來獲取。舉例來說,如果一個函式需要用到0x100000處的變數,並且需要用到0x100150處的另外一個變數,那麼,編譯器可以將這2個變數建立關聯,或者採用以下程式碼:
LDR R0, =0x100000
ADD R0, *0xFF
ADD R0, *0x51
LDR R0, [R0]
在x86裡面,這種方法應用於結構中獲取子結構介面。但是此處,卻是一個常用的最佳化,這有什麼好處呢?可以減小記憶體儲存,並且算術運算比資料載入快得多。可以認為整個ARM彙編程式充滿了不同的暫存器間算術運算。事實上,有多達16個暫存器用來進行此操作-減少記憶體和堆疊定位頻度。因此,只有在非常大的函式中才需要用堆疊儲存變數。對堆疊的操作和x86處理堆疊的方式一樣。
IDA中的程式碼分析
既然ARM檔案沒有統一格式,那麼在載入ARM二進位制映像的時候,有必要先載入該檔案。在載入的時候,需要確定處理器型別。如果處理器規定程式碼必須按照處理器模組處理順序,那麼你可以載入映像檔案並且指定需要的處理方式,ARM處理方式(低位處理)或者ARMB(高位處理)。並且,有必要建立ROM或者RAM段。總之沒有固定的處理方式,具體的處理有賴於映像和每個ARM處理器的架構。例如,在ARM7中,記憶體一般有如下格式:
0x0 - 0x8000 of RAM processor
0x8000 - 0x1000000 ROM
0x1000000 - 0x..... - SRAM (這裡看出自身數目)
現在就可以分析程式碼了,在很多裝置中(一般都是行動電話),程式碼的入口設定為0x8000。ARM模式下的程式碼從0x8000開始執行,所以,開始執行的指令和該處的一樣。處理器的IDA模組可以簡單地分析此類switching語句,然後Thumb 程式碼在ARM中執行。如果手工修改跳轉,可以按ALT-G,然後修改檔案中的標記,如果為ARM檔案,設為0,Thumb檔案,設為1。
相關文章
- 晶片行業內 die 的翻譯及詞解2024-08-21晶片行業
- JavaScript 事件迴圈詳解(翻譯)2019-03-04JavaScript事件
- ARM 詳解2023-04-06
- [Java 8 Tutorial翻譯系列]Java forEach詳解2019-05-14Java
- Flux 深度解讀(翻譯)2019-03-04UX
- 比譯 for mac - 便捷的翻譯和詞典應用 支援M1晶片2021-10-11Mac晶片
- 翻譯2020-12-29
- Python反反爬蟲實戰,JS解密入門案例,詳解呼叫有道翻譯2020-10-22Python爬蟲JS解密
- 操作指南|最詳盡文件翻譯志願指南2022-01-26
- 蝴蝶書-task2: 文字推理、摘要、糾錯 transformers實現翻譯 OpenAI翻譯 PyDeepLX翻譯 DeepLpro翻譯2024-04-29ORMOpenAI
- Ubuntu安裝劃詞翻譯軟體Goldendict 單詞翻譯 句子翻譯2021-01-05UbuntuGo
- 如何完成中文翻譯日文線上翻譯2019-09-23
- 【譯】LiveData 使用詳解2019-03-04LiveData
- ARC186A 官方題解-ChatGPT翻譯2024-10-29ChatGPT
- ARM 之主流編譯器2020-11-06編譯
- 騰訊互動翻譯的坑爹翻譯2024-12-10
- Laravel 谷歌翻譯 /Bing 翻譯擴充套件包2019-06-11Laravel谷歌套件
- OpenCV翻譯專案總結二——Mat翻譯2019-07-13OpenCV
- 文件翻譯器怎麼用?如何翻譯Word文件?2019-08-15
- TailWind文件翻譯說明以及每日翻譯進度2021-01-19AI
- 有道雲詞典--翻譯/螢幕取詞翻譯2020-12-12
- 使用google翻譯 api 翻譯中文成其他語言2018-08-06GoAPI
- socket中文翻譯2024-11-09
- 歌詞翻譯2024-09-13
- bulma中文翻譯2024-08-31
- 翻譯軟體2019-05-03
- 翻譯|Thinking Statefully2019-04-27ThinkingStatefully
- 翻譯介面整理2018-11-14
- MPAndroidChart文件翻譯2019-02-19Android
- Python 谷歌翻譯2018-08-14Python谷歌
- Strategy Analytics:蘋果ARM架構晶片對PC晶片市場的影響2020-06-26蘋果架構晶片
- 詞典翻譯 英譯漢2018-07-21
- Arctime怎麼翻譯字幕?Arctime批次翻譯字幕的技巧2020-07-14
- Google 谷歌翻譯 Mac 客戶端(Mac翻譯軟體)2022-03-23Go谷歌Mac客戶端
- Python 使用白嫖網易翻譯 API 進行翻譯2020-04-11PythonAPI
- QT TS檔案翻譯,部分不能正確被翻譯2021-01-02QT
- OfficialKaldi(一)| 關於Kaldi專案(翻譯註解)2020-12-02
- samesite-cookie詳解(譯文)2020-10-18Cookie
- [譯] Java 橋接方法詳解2019-02-27Java橋接