1 編程語言的發(fā)展史
1.1 機(jī)器語言
??計(jì)算機(jī)的硬件作為一種電路元件,它的輸出和輸入只能是有電或者沒電,也就是所說的高電平和低電平,所以計(jì)算機(jī)傳遞的數(shù)據(jù)是由“0” 和“1”組成的二進(jìn)制數(shù),所以說二進(jìn)制的語言是計(jì)算機(jī)語言的本質(zhì)。計(jì)算機(jī)發(fā)明之初,人們?yōu)榱巳タ刂朴?jì)算機(jī)完成自己的任務(wù)或者項(xiàng)目,只能去編寫“0”、“ 1”這樣的二進(jìn)制數(shù)字串去控制電腦,其實(shí)就是控制計(jì)算機(jī)硬件的高低電平或通路開路,這種語言就是機(jī)器語言,例如下面的0、1代碼就分別代表了四則運(yùn)算:
加:0100 0000
減:0100 1000
乘:1111 0111 1110 0000
除:1111 0111 1111 0000
??直觀上看,機(jī)器語言十分晦澀難懂,其中的含義往往要通過查表或者手冊(cè)才能理解, 使用的時(shí)候非常痛苦,尤其當(dāng)你需要修改已經(jīng)完成的程序時(shí),這種看起來無序的機(jī)器語言會(huì)讓你無從下手,也很難找到程序的錯(cuò)誤。而且,不同計(jì)算機(jī)的運(yùn)行環(huán)境不同,指令方式操作方式也不盡相同,所以當(dāng)你在這種機(jī)器語言就有了特定性,只能在特定的計(jì)算機(jī)上執(zhí)行,而一旦換了機(jī)器就需要重新編程,這極大的降低了程序的使用和推廣效率。但由于機(jī)器語言具有特定性,完美適配特定型號(hào)的計(jì)算機(jī),故而運(yùn)行效率遠(yuǎn)遠(yuǎn)高過其他語言。機(jī)器語言,也就是第一代編程語言。
1.2 匯編語言
??因此,為了解決以上種種難題,匯編語言就此營(yíng)運(yùn)而生,匯編語言(Assembly Language)是任何一種用于電子計(jì)算機(jī)、微處理器、微控制器或其他可編程器件的低級(jí)語言,亦稱為符號(hào)語言。在匯編語言中,用助記符代替機(jī)器指令的操作碼,用地址符號(hào)或標(biāo)號(hào)代替指令或操作數(shù)的地址。在不同的設(shè)備中,匯編語言對(duì)應(yīng)著不同的機(jī)器語言指令集,通過匯編過程轉(zhuǎn)換成機(jī)器指令。特定的匯編語言和特定的機(jī)器語言指令集是一一對(duì)應(yīng)的,不同平臺(tái)之間不可直接移植。
??例如,四則運(yùn)算在匯編語言中的表現(xiàn)如下形式:
加:INC EAX 對(duì)應(yīng)的機(jī)器語言: 0100 0000
減:DEC EAX 對(duì)應(yīng)的機(jī)器語言: 0100 1000
乘:MUL EAX 對(duì)應(yīng)的機(jī)器語言:1111 0111 1110 0000
除:DIV EAX 對(duì)應(yīng)的機(jī)器語言:1111 0111 1111 0000
1.3 高級(jí)語言
??在編程語言經(jīng)歷了機(jī)器語言,匯編語言等更新之后,人們發(fā)現(xiàn)了限制程序推廣的關(guān)鍵因素——程序的可移植性。需要設(shè)計(jì)一個(gè)能夠不依賴于計(jì)算機(jī)硬件,能夠在不同機(jī)器上運(yùn)行的程序。這樣可以免去很多編程的重復(fù)過程,提高效率,同時(shí)這種語言又要接近于數(shù)學(xué)語言或人的自然語言。在計(jì)算機(jī)還很稀缺的50年代,誕生了第一個(gè)高級(jí)編程語言。當(dāng)時(shí)計(jì)算機(jī)的造價(jià)不菲,但是每天的計(jì)算量又有限,如何有效的利用計(jì)算機(jī)有限的計(jì)算能力成為了當(dāng)時(shí)人們面對(duì)的問題。同時(shí),因?yàn)橘Y源的稀缺, 計(jì)算機(jī)的運(yùn)行效率也成為了那個(gè)年代工程師追尋的目標(biāo)。為了更高效的使用計(jì)算機(jī),人們?cè)O(shè)計(jì)出了高級(jí)編程語言,來滿足人們對(duì)于高效簡(jiǎn)潔的編程語言的追求。
例如:C\C++\Java\OC\Swift,更加接近人類的自然語言
比如C語言:
加:A+B 通過編譯器 0100 0000
減:A-B 通過編譯器 0100 1000
乘:A*B 通過編譯器 1111 0111 1110 0000
除:A/B 通過編譯器 1111 0111 1111 0000
??我們的代碼在終端設(shè)備上是這樣的過程:

其中:
- 匯編語言與機(jī)器語言一一對(duì)應(yīng),每一條機(jī)器指令都有與其對(duì)應(yīng)的匯編指令。
- 匯編語言可以通過編譯得到機(jī)器語言,機(jī)器語言也可以通過反匯編得到匯編語言。(針對(duì)特定平臺(tái)上的機(jī)器指令所對(duì)應(yīng)的匯編指令)
- 高級(jí)語言可以通過編譯得到匯編\機(jī)器語言,但是匯編\機(jī)器語言幾乎不可能還原成高級(jí)語言。(這是因?yàn)椴煌母呒?jí)語言編譯后產(chǎn)生的匯編語言可以相同,同一種高級(jí)語言不同的代碼段產(chǎn)生的匯編語言也可以相同,這就造成了匯編語言反編譯成高級(jí)語言的困難。)
2 匯編語言的特點(diǎn)、用途及種類
2.1 特點(diǎn)
- 可以直接訪問、控制各種硬件設(shè)備,比如存儲(chǔ)器、CPU等,能最大限度地發(fā)揮硬件的功能。
- 能夠不受編譯器的限制,對(duì)生成的二進(jìn)制代碼進(jìn)行完全的控制。
- 目標(biāo)代碼簡(jiǎn)短,占用內(nèi)存少,執(zhí)行速度快。
- 匯編指令是機(jī)器指令的助記符,同機(jī)器指令一一對(duì)應(yīng)。每一種CPU都有自己的機(jī)器指令集\匯編指令集,所以匯編語言不具備可移植性。
- 知識(shí)點(diǎn)過多,開發(fā)者需要對(duì)CPU等硬件結(jié)構(gòu)有所了解,不易于編程、調(diào)試及維護(hù)。
- 不區(qū)分大小寫,比如mov和MOV是一樣的。
2.2 用途
- 編寫驅(qū)動(dòng)程序、操作系統(tǒng)(比如Linux內(nèi)核的某些關(guān)鍵部分)。
- 對(duì)性能要求極高的程序或者代碼片段,可與高級(jí)語言混合使用(內(nèi)聯(lián)匯編)。
- 軟件安全。
- 病毒分析與防治。
- 逆向\加殼\脫殼\破解\外掛\免殺\加密解密\漏洞\黑客。
- 理解計(jì)算機(jī)系統(tǒng)的最佳起點(diǎn)和最有效途徑。
- 為編寫高效代碼打下基礎(chǔ)。
- 弄清代碼的本質(zhì)。
2.3 種類
目前討論比較多的匯編語言有:
8086匯編(8086處理器是16bit的CPU)
Win32匯編
Win64匯編
ARM匯編(嵌入式、Mac、iOS)
??我們iPhone里面用到的是ARM匯編,但是不同的設(shè)備也有差異,因CPU的架構(gòu)不同,如下圖所示:

3. 學(xué)習(xí)匯編語言必備基礎(chǔ)知識(shí)
3.1 CPU硬件結(jié)構(gòu)

3.2 APP/程序執(zhí)行過程圖

其中硬件相關(guān)最為重要的是CPU以及內(nèi)存,在匯編指令集中,大部分指令都是直接對(duì)CPU以及內(nèi)存進(jìn)行操作的。
3.3 總線
3.3.1 總線的工作流程

??總線其實(shí)就是一根根導(dǎo)線的集合,分為:地址總線、數(shù)據(jù)總線以及控制總線。
當(dāng)CPU需要從內(nèi)存中讀寫數(shù)據(jù)的時(shí)候,通過控制總線傳入讀寫內(nèi)存數(shù)據(jù)的操作命令,然后通過地址總線傳入的地址讀寫內(nèi)存中相應(yīng)地址的數(shù)據(jù),如果是讀操作就將獲取到的數(shù)據(jù)通過數(shù)據(jù)總線傳給CPU,如果是寫操作就將數(shù)據(jù)通過數(shù)據(jù)總線存儲(chǔ)到地址總線所記錄的內(nèi)存的地址中,如下圖所示:

3.3.2 地址總線
??地址總線的寬度決定了CPU的尋址能力,8086的地址總線寬度是20,所以尋址能力是1M( 2的20次方 )。也就是說內(nèi)存的大小限制決定了地址總線的寬度,地址總線所讀取的內(nèi)存的最大地址不能超過內(nèi)存存儲(chǔ)數(shù)據(jù)的最大存儲(chǔ)總量。
3.3.3 數(shù)據(jù)總線
??數(shù)據(jù)總線的寬度決定了CPU的單次數(shù)據(jù)傳送量,也就是數(shù)據(jù)傳送速度,8086的數(shù)據(jù)總線寬度是16,所以單次最大傳遞2個(gè)字節(jié)的數(shù)據(jù)。
3.3.4 控制總線
??控制總線的寬度決定了CPU對(duì)其他器件的控制能力、能有多少種控制。
3.4 內(nèi)存



- 內(nèi)存地址空間的大小受CPU地址總線寬度的限制。8086的地址總線寬度為20,可以定位220個(gè)不同的內(nèi)存單元(內(nèi)存地址范圍0x00000~0xFFFFF),所以8086的內(nèi)存空間大小為1MB。
- 0x00000~0x9FFFF:主存儲(chǔ)器??勺x可寫。
- 0xA0000~0xBFFFF:向顯存中寫入數(shù)據(jù),這些數(shù)據(jù)會(huì)被顯卡輸出到顯示器??勺x可寫。
- 0xC0000~0xFFFFF:存儲(chǔ)各種硬件\系統(tǒng)信息。只讀。
3.5 進(jìn)制
3.5.1 如何學(xué)習(xí)進(jìn)制
??在學(xué)習(xí)會(huì)匯編的時(shí)候我們需要經(jīng)常查看指令執(zhí)行的地址,以及一些二進(jìn)制數(shù)據(jù),因此對(duì)于進(jìn)制的學(xué)習(xí)也是非常必要的。
??我們?cè)趯W(xué)習(xí)進(jìn)制的時(shí)候,總是以十進(jìn)制為依托去考慮其他進(jìn)制,需要運(yùn)算的時(shí)候也總是先轉(zhuǎn)換為十進(jìn)制,其實(shí)這種學(xué)習(xí)方法是錯(cuò)誤的,每一種進(jìn)制其實(shí)都是完美的,要向?qū)W號(hào)進(jìn)制首先要忘掉十進(jìn)制,也要忘掉進(jìn)制間的轉(zhuǎn)換。
3.5.2 進(jìn)制的定義
- 八進(jìn)制由8個(gè)符號(hào)組成:0 1 2 3 4 5 6 7 逢八進(jìn)一
- 十進(jìn)制由10個(gè)符號(hào)組成:0 1 2 3 4 5 6 7 8 9 逢十進(jìn)一
- N進(jìn)制就是由N個(gè)符號(hào)組成:逢N進(jìn)一
??其實(shí)這些符號(hào)不一定是寫死的,可以是自己定義的,例如:什么時(shí)候1 + 1等于3呢?
??當(dāng)你如此定義十進(jìn)制的符號(hào)就可以做的:0 1 3 6 9 A B Q X 4 傳統(tǒng)我們定義的十進(jìn)制和定義的十進(jìn)制不一樣,那么這10個(gè)符號(hào)如果我們不告訴別人,別人是無法知道我們這些符號(hào)具體的表示意義的,這樣就可以用來加密。
3.5.3 進(jìn)制的運(yùn)算
- 八進(jìn)制加法表
1+1 = 2
1+2 = 3 2+2 = 4
1+3 = 4 2+3 = 5 3+3 = 6
1+4 = 5 2+4 = 6 3+4 = 7 4+4 = 10
1+5 = 6 2+5 = 7 3+5 = 10 4+5 = 11 5+5 = 12
1+6 = 7 2+6 = 10 3+6 = 11 4+6 = 12 5+6 = 13 6+6 = 14
1+7 = 10 2+7 = 11 3+7 = 12 4+7 = 13 5+7 = 14 6+7 = 15 7+7 = 16 - 八進(jìn)制的乘法表
11 = 1
12 = 2 22 = 4
13 = 3 23 = 6 33 = 11
14 = 4 24 = 10 34 = 14 44 = 20
15 = 5 25 = 12 35 = 17 45 = 24 55 = 31
16 = 6 26 = 14 36 = 22 46 = 30 56 = 36 66 = 44
17 = 7 27 = 16 37 = 25 47 = 34 57 = 43 67 = 52 77 = 61
3.5.4 進(jìn)制的轉(zhuǎn)換
二進(jìn)制:1 0 1 1 1 0 1 1 1 1 0 0
三個(gè)一組轉(zhuǎn)換為八進(jìn)制:101 110 111 100
八進(jìn)制: 5 6 7 4
四個(gè)一組轉(zhuǎn)換為十六進(jìn)制:1011 1011 1100
十六進(jìn)制: b b c
將二進(jìn)制轉(zhuǎn)換為十六進(jìn)制寫起來就沒那么麻煩了,因此,我們經(jīng)常使用十六形式來簡(jiǎn)寫二進(jìn)制。
3.6 數(shù)據(jù)的寬度
??數(shù)學(xué)上的數(shù)字,是沒有大小限制的,可以無限的大。但在計(jì)算機(jī)中,由于受硬件的制約,數(shù)據(jù)都是有長(zhǎng)度限制的(我們稱為數(shù)據(jù)寬度),超過最多寬度的數(shù)據(jù)會(huì)被丟棄。
計(jì)算機(jī)中常見的數(shù)據(jù)寬度
- 位(Bit):1個(gè)位就是1個(gè)二進(jìn)制位,0或者1。
- 字節(jié)(Byte):1個(gè)字節(jié)由8個(gè)Bit組成(8位),內(nèi)存中的最小單元Byte。
- 字(Word):1個(gè)字由2個(gè)字節(jié)組成(16位),這2個(gè)字節(jié)分別稱為高字節(jié)和低字節(jié)。
- 雙字(Doubleword):1個(gè)雙字由兩個(gè)字組成(32位)。