天天看點

深入iOS系統底層之彙編語言

秉心識本源,於事少凝滞。-- 《信行遠修水筒》

要想完全的了解一個系統唯一的方法就是去閱讀這個系統的源代碼實作!這個原則對于一個iOS程式員也是如此。很幸運的是我們現在處于一個開源代碼迸發的美好時代(這裡要感謝理查·馬修·斯托曼以及他的GNU計劃),很多優秀的庫都以源代碼的形式呈現給大家,甚至連iOS這種封閉的系統也迫于某種壓力開放了部分源代碼(雖然開放的部分并不一定和真實的相同),這也已經足以給了我們很多熱情去窺探其内部的一些實作機制。目前網絡上也有非常多的基于蘋果的開源而介紹OC2.0的runtime原理以及runloop實作機制以及類的+load方法執行時機等等方面的文章。

當我們希望走更遠時就會發現有一座大山阻擋着我們的去路。因為系統的閉源特性使得我們無法閱讀到其中所有的源代碼以及核心實作。那麼是否我們就隻能裹足不前了呢?

回答是NO!

源代碼有進階形式的源代碼也有低級形式的源代碼。當我們被進階形式的源代碼所阻時,低級形式的源代碼卻依舊為我們敞開着大門,就看你願不願意去找那把鑰匙并打開它。低級形式的源代碼是什麼呢? 答案就是機器指令!!

我們知道凡是滿足某個作業系統ABI規則的應用程式源代碼最終都會編譯和連結為某種特定格式的一條條機器指令并在CPU上執行。如果說程式的進階語言實作對于一個程式員來說是它的源代碼的話,那麼對于CPU來說一個程式的機器指令序列就是它的源代碼。隻不過機器語言對于很多人來說異常的晦澀難懂而已。

很高興的一件事情就是雖然機器語言晦澀,我們的前輩們發明出了一種所謂機器語言的助記語言:彙編語言

彙編語言中的每條指令雖然幾乎和每條機器指令一一對應,但是卻增強了程式的可讀性,使得我們面臨的不再是一串幹巴巴的二進制數字了。君不見目前很多的反編譯工具以及即使是XCODE上我們都能看到彙編語言的場景。正是因為彙編語言的出現使得我們在閱讀和分析源代碼上就進了一大步!

當你精通彙編語言時!你看到的所有代碼都将是源代碼!

有人說彙編語言相對于進階語言來說依然晦澀難懂,但這其實并不是絕對的。曾記得中國第一代程式員的求伯君以及雷軍這些前輩們最早接觸的就是彙編語言,而且他們也都是用彙編語言進行程式編寫的。就因為彙編語言離機器語言太近了,是以大家都會有一種望而生畏的感覺。誠然這些低級語言并沒有像我們使用的進階語言那樣更加符合自然語義和文法規則,但是它的優點就是非常的直接和單純。當你深入的應用它時就會發現彙編其實并沒有那麼的複雜。在一個程式的機器指令中,大部分的指令代碼所做的事情除了計算外就是将資料在寄存器與寄存器之間以及寄存器與記憶體之間進行移動。在進階語言中我們可以定義非常個性化的變量以及無限制的變量,而在低級語言中我們則隻能使用那幾個有限的寄存器來作為臨時變量,以及像通路數組那樣去通路記憶體位址。

下面的一張圖可以看到實作一個累加功能代碼片段的機器語言和彙編語言以及進階語言之間的差别:

深入iOS系統底層之彙編語言

看上面的代碼時也許你對進階語言所表達的意義一目了然,而對于彙編語言的表達也許仔細多讀幾遍就能了解其意義,而對于機器語言則可能是一頭霧水了。

說了這麼多,也許有人會問彙編語言和我想要深入iOS系統底層有什麼關系!

好問題! 答案就是iOS系統的封閉性,使得我們無法窺探到很多系統的底層實作, 并且當我們被某種問題或者某個實作原理所困擾卻不得其法時,就可以通過對系統進行反編譯而得到彙編語言來了解和閱讀其實作原理;當我們面臨突如其來的運作時崩潰時,就可以通過閱讀彙編語言來了解其産生的原因;當我們的crash并沒有上下文時,就可以通過彙編語言來定位和解決問題;當我們想解決某個問題而想做動态下發更新檔時我們也可以借助彙編語言來完成;當我們想在越獄的機器上hook住某些應用時我們可以通過彙編語言來完成功能;當我們想最大的優化我們的系統以及某些關鍵部分的代碼的性能時我們可以借助彙編語言;當我們想當一個黑客時我們可以借助彙編語言...,我們能借助彙編語言做的事情實在是太多太多了。 現在的應用程式設計語言都是越來越向進階語言發展,而呈現出簡單化、智能化進而導緻進入的門檻越來越低。越進階的語言因為其封裝性就越離底層實作原理越遠,你所能窺探的東西就越少,是以低級語言還是非常具有頑強的生命力和存在必要性的。君不見iOS所開源的runtime的源代碼裡面關于objc_msgSend函數的實作就是用彙編語言來編寫的!這樣的目的就是讓這個函數的性能得到最大的優化。

是以說掌握和了解彙編語言知識不僅是進入iOS系統底層并且也是進入所有系統底層的一把鑰匙,當你精通或者了解一些基礎的彙編語言知識和技巧時,你就打開了通往一切都是源代碼的大門。值得一提的就是我并不打算詳細的去介紹關于彙編的一切,其實我們隻要了解一些基礎的彙編知識就能非常友善的幫助我們解決很多的事情。

敬請期待下一篇:深入iOS系統底層之指令集介紹

一直想寫一些關于系統底層方面的知識點,并且醞釀了很久。後來也跟其他人交流,你為何不出一個系列呢? 不必要一次性把所有的東西都寫完後才發表。我聽說後覺得非常的有道理,是以我想在這裡分享一些介紹iOS系統底層的一系列文章。這是第一篇開頭的引子,雖然自己的水準也很一般,但是想想自己還是有一些積累的,即使是有問題或者是有錯誤也可以發表出來供大家評論和指責嗎。最終的目的是大家共同進步,隻要達到了這一點我也就滿足了。後續的日子我将會争取每周在這個系列中對iOS系統底層進行一系列的展開,先列出一個大概的綱要,當然也許後續會有變化:

目錄

1.深入iOS系統底層之彙編語言

2.深入iOS系統底層之指令集介紹

3.深入iOS系統底層之XCODE對彙編的支援介紹

4.深入iOS系統底層之CPU寄存器介紹

5.深入iOS系統底層之機器指令介紹

6.深入iOS系統底層之指派指令介紹

7.深入iOS系統底層之函數調用介紹

8.深入iOS系統底層之其他常用指令介紹

9.深入iOS系統底層之函數棧介紹

10.深入iOS系統底層之函數棧(二)介紹

11.深入iOS系統底層之不定參數函數實作原理介紹

12.深入iOS系統底層之在進階語言中嵌入彙編語言介紹

13.深入iOS系統底層之常見的彙編代碼片段介紹

14.深入iOS系統底層之OC中的各種屬性以及修飾的實作介紹

15.深入iOS系統底層之ABI介紹

16.深入iOS系統底層之編譯連結過程介紹

17.深入iOS系統底層之可執行檔案結構介紹

18.深入iOS系統底層之MACH-O檔案格式介紹

19.深入iOS系統底層之映像檔案操作API介紹

20.深入iOS系統底層之知名load command結構介紹

21.深入iOS系統底層之程式加載過程介紹

22.深入iOS系統底層之靜态庫介紹

23.深入iOS系統底層之動态庫介紹

24.深入iOS系統底層之framework介紹

25.深入iOS系統底層之基位址介紹

26.深入iOS系統底層之子產品内函數調用介紹

27.深入iOS系統底層之子產品間函數調用介紹

28.深入iOS系統底層之機器指令動态構造介紹

29.深入iOS系統底層之crash問題解決方法

30.深入iOS系統底層之無上下文crash解決方法

31.深入iOS系統底層之常用工具和指令的實作原理介紹

32.深入iOS系統底層之真實的OC類記憶體結構介紹

歡迎大家通路我的github位址和簡書位址