芯片IC單片機解密百科

十年專注單片機解密

一個androids應用程序(hello,word)-用匯編語言來編寫


BBIN导航都熟悉計算機和PC內的程序和處理流程,那麽手機的流程呢?一些app開發的人可能熟悉了,但是其他人可能對此知之甚少,本文中蟲蟲代理大家利用一個簡單的安卓實例來探索安卓中應用的處理流程。 處理研究目的BBIN导航沒有使用移動開發的常用的androids Studio和Java語言,而是使用了底層的匯編語言。

Hello, androids!

問題源於,某個開發群,有人的隨口一個問題:智能手機如何工作的?裏麵有什麽?

BBIN导航利用一個安卓設備Galaxy S6 Edge,該機基於ARM架構(大多數智能手機都是基於ARM CPU這和常見的基於X86 平台 PC或者服務器不一樣)。BBIN导航就以他為例,實現一個匯編版本的"Hello,World"簡單程序,並讓它在該設備商跑起來。


.text

.globl _start

_start:

mov %r0, $1 // file descriptor number 1 (stdout)

ldr %r1, =message

mov %r2, $message_len

mov %r7, $4 // syscall 4 (write)

swi $0

mov %r0, $0 // exit status 0 (ok)

mov %r7, $1 // syscall 1 (exit)

swi $0

.data

message:

.ascii "Hello, World Chongchong "

message_len = . – message

如果你之前從未見過匯編代碼,那麽這個程序可不好理解,但不要擔心,跟著BBIN导航一起進行就好了。

程序解釋

程序分為兩部分: .text 部分:包含機器代碼指令。

.data部分:從第15行開始,包含變量,字符串和其他數據。.text部分通常是隻讀的,而.data部分支持寫入。

在第2行中,BBIN导航定義了一個名為_start的全局函數。這是該工程的注入點。操作係統將從這一點開始運行代碼。該函數的實際定義在第4行。函數有兩個功能:第5-9行將消息打印到屏幕,第11-13行終止程序。實際上11-13行可以省略掉,這時候程序將字符串打印"Hello,World ChongChong"並退出,但退出時候可能會崩潰試圖執行一些隨機無效的指令,它恰好是內存中的下一個。

打印消息(r0,r1,r2寄存器和swi)

通過調用係統調用來打印到屏幕。係統調用是操作係統提供的功能。本程序中BBIN导航調用了write()係統調用,通過將值4賦值給名為r7(第8行)的CPU寄存器中來指示,然後執行"swi $0"指令(第9行),該指令直接調用在androids內部運行的Linux內核。

係統調用的參數通過其他寄存器傳遞:r0表示BBIN导航要打印的文件描述符的編號。BBIN导航給他賦值為1(第5行),這個BBIN导航都熟悉,標號為1的文件描述符實際上就是stdout,標準輸出,這樣就功能在屏幕上打印。

r1表示BBIN导航要載入的數據的內存地址,因此BBIN导航給它賦值為"Hello,World ChongChong"字符串的地址(第6行)。r2告訴androidsBBIN导航要寫入多少字節。BBIN导航將其設置為message_len(第7行)的值,該值在第18行使用特殊的語法計算:點符號表示當前的內存地址,因此". - message"表示當前內存地址減去message的地址。這就計算了message的長度。總之,第5-9行中的代碼相當於以下c代碼:

#define message "Hello, World ChongChong "

write(1, message, sizeof(message));

結束程序(r0,r7)

結束程序要簡單得多,BBIN导航隻需要將退出代碼賦值給r0(第11行),然後BBIN导航將值1(即exit()係統調用的值)賦值給r7(第12行),並且再次調用內核(第13行)。

如果有興趣,你可以參考在安卓源代碼中相關的androids係統調用列表及其編號。你也可以在那裏找到write()和exit()函數的實現,它們調用相應的係統調用,就像BBIN导航一樣。

編譯源碼

為了編譯匯編程序,你需要androids NDK,即Native Development Kit,它包含一組用於ARM平台的編譯器和構建工具。你可以直接從官方網站下載,也可以通過androids Studio安裝:


轉到"SDK工具"並選中"NDK",然後單擊"確定"。另請注意androids SDK位置

獲得NDK後,你需要搜索一個名為arm-linux-androidseabi-as的文件,它是ARM平台的匯編程序。如果你是通過androids Studio下載的,請在androids SDK位置內查找。在我的機器上,它位於:

ndk-bundle oolchainsarm-linux-androidseabi-4.9prebuiltwindows-x86_64in

根據不同的NDK版本和操作係統該路徑會略有變化,根據實際環境選擇。該文件內置了ARM匯編程序。

將源代碼保存為hello.s的文件。然後運行以下命令將編譯為機器代碼:

arm-linux-androidseabi-as -o hello.o hello.s

以上命令會創建一個名為hello.o的可執行文件。

然後再通過調用鏈接器將其轉換為可在你的設備上運行的ELF二進製文件:

arm-linux-androidseabi-ld -o hello hello.o

你現在有一個名為hello的文件,其中包含你的程序,可以運行。

運行程序

安卓應用程序通常以APK格式分發。這是一種特殊的ZIP文件,安卓希望以特定的方式構建,並且應該包含Java類(你可以使用本機C/C++或者其他語言編寫具體的應用代碼,但入口點仍然必須是是Java) 。

為了方便運行BBIN导航的應用程序,BBIN导航使用adb將其複製到她的androids設備的臨時文件夾,然後使用adb shell運行應用程序並查看輸出:

adb push hello /data/local/tmp/hello

adb shell chmod +x /data/local/tmp/hello

最後,運行應用程序:

adb shell /data/local/tmp/hello

Hello World Chongchon

總結

為安卓設備編寫匯編代碼是熟悉ARM體係結構的好方法,幫BBIN导航了解每天使用的APP是如何運行,及其底層的工作原理,我曾經在以前的文章和回答中回答過匯編作為一個必須要技能,BBIN导航不必須要精通但是每個人都需要學習一點,這樣有助於BBIN导航了解計算機體係結果和底層的運行原理。