@[TOC](IOS 逆向開(kāi)發(fā)(二十一) 匯編-基礎(chǔ))
1. 匯編簡(jiǎn)介
- 為啥要需要學(xué)習(xí)匯編?
- 大學(xué)都學(xué)習(xí)過(guò)匯編語(yǔ)言,那時(shí)候覺(jué)得匯編晦澀難懂,而且工作后實(shí)際開(kāi)發(fā)中也一般都用高級(jí)語(yǔ)言,很少直接接觸到匯編。但是理解匯編相關(guān)知識(shí)后,你會(huì)更加深入的理解高級(jí)語(yǔ)言的函數(shù)為啥要那樣寫(xiě),怎么寫(xiě)才能效率性能最高,有時(shí)候你調(diào)式代碼可以通過(guò)下符號(hào)斷點(diǎn)直接查看跟蹤匯編代碼。如果能讀懂匯編代碼,一切都不難題。
- 在逆向開(kāi)發(fā)中,非常重要的一個(gè)環(huán)節(jié)就是靜態(tài)分析.首先我們是逆向iOS系統(tǒng)上面的APP.那么我們知道,一個(gè)APP安裝在手機(jī)上面的可執(zhí)行文件本質(zhì)上是二進(jìn)制文件.因?yàn)閕Phone手機(jī)本質(zhì)上執(zhí)行的指令是二進(jìn)制.是由手機(jī)上的CPU執(zhí)行的.所以靜態(tài)分析是建立在分析二進(jìn)制上面。理解匯編,我們就能自己通過(guò)匯編來(lái)調(diào)用相關(guān)代碼。
- 越底層越單純!真正的程序員都需要了解的一門(mén)非常重要的語(yǔ)言,匯編!
- 匯編是什么?
匯編執(zhí)行指令是機(jī)器指令的符號(hào)化表示,其操作碼用記憶符表示,地址碼直接用標(biāo)號(hào)、變量名字、常數(shù)等表示。匯編執(zhí)行指令經(jīng)匯編程序翻譯為機(jī)器指令,二者之間基本上保持一一對(duì)應(yīng)的關(guān)系。匯編偽指令又稱作匯編指示,用于向匯編程序提供用戶自定義的符號(hào)、數(shù)據(jù)的類型、數(shù)據(jù)空間的長(zhǎng)度,以及目標(biāo)程序的格式、存放位置等提示性信息,其作用是指示匯編程序如何進(jìn)行匯編。使用匯編語(yǔ)言編寫(xiě)的源代碼,需要通過(guò)使用相應(yīng)的匯編程序?qū)⑺鼈冝D(zhuǎn)換成可執(zhí)行的機(jī)器代碼。這一過(guò)程被稱為匯編過(guò)程。
1.1 匯編語(yǔ)言發(fā)展過(guò)程
- 匯編的發(fā)展過(guò)程?
匯編程序的雛型是在電子離散時(shí)序自動(dòng)計(jì)算機(jī) EDSAC上研制成功的。這種系統(tǒng)的特征是用戶程序中的指令由單字母指令碼、十進(jìn)制地址和終結(jié)字母組成。第一個(gè)匯編程序是符號(hào)優(yōu)化匯編程序(SOAP)系統(tǒng),它是50年代中期為IBM650計(jì)算機(jī)研制的。這種計(jì)算機(jī)用磁鼓作存儲(chǔ)器,每條指令指出后繼指令在磁鼓中的位置。當(dāng)初研制SOAP系統(tǒng)的動(dòng)機(jī)不是引入?yún)R編語(yǔ)言的符號(hào)化特色,而是為了集中解決指令在磁鼓中合理分布的問(wèn)題,以提高程序的運(yùn)行效率。IBM704計(jì)算機(jī)的符號(hào)匯編程序(SAP)是匯編程序發(fā)展中的一個(gè)重要里程碑。此后的匯編程序大都以這一系統(tǒng)為模型,其主要特征未發(fā)生本質(zhì)的變化。隨著計(jì)算機(jī)軟件的高速發(fā)展和廣泛應(yīng)用,匯編程序又吸收了宏加工程序、高級(jí)語(yǔ)言翻譯程序等系統(tǒng)的一些優(yōu)點(diǎn),相繼研制出宏匯編程序、高級(jí)匯編程序 。
- 機(jī)器語(yǔ)言
由0和1組成的機(jī)器指令.
加:0100 0000
減:0100 1000
乘:1111 0111 1110 0000
除:1111 0111 1111 0000
- 匯編語(yǔ)言(assembly language)
使用助記符代替機(jī)器語(yǔ)言
如:
加:INC EAX 通過(guò)編譯器 0100 0000
減:DEC EAX 通過(guò)編譯器 0100 1000
乘:MUL EAX 通過(guò)編譯器 1111 0111 1110 0000
除:DIV EAX 通過(guò)編譯器 1111 0111 1111 0000
- 高級(jí)語(yǔ)言(High-level programming language)
C\C++\Java\OC\Swift,更加接近人類的自然語(yǔ)言
比如C語(yǔ)言:
加:A+B 通過(guò)編譯器 0100 0000
減:A-B 通過(guò)編譯器 0100 1000
乘:A*B 通過(guò)編譯器 1111 0111 1110 0000
除:A/B 通過(guò)編譯器 1111 0111 1111 0000
-
我們的代碼在終端設(shè)備上是這樣的過(guò)程:
編譯過(guò)程
- 匯編語(yǔ)言與機(jī)器語(yǔ)言一一對(duì)應(yīng),每一條機(jī)器指令都有與之對(duì)應(yīng)的匯編指令.
- 匯編語(yǔ)言可以通過(guò)編譯得到機(jī)器語(yǔ)言,機(jī)器語(yǔ)言可以通過(guò)反匯編得到匯編語(yǔ)言.
- 高級(jí)語(yǔ)言可以通過(guò)編譯得到匯編語(yǔ)言 \ 機(jī)器語(yǔ)言,但匯編語(yǔ)言\機(jī)器語(yǔ)言幾乎不可能還原成高級(jí)語(yǔ)言.
1.2 匯編特點(diǎn)
可以直接訪問(wèn)、控制各種硬件設(shè)備,比如存儲(chǔ)器、CPU等,能最大限度地發(fā)揮硬件的功能。
能夠不受編譯器的限制,對(duì)生成的二進(jìn)制代碼進(jìn)行完全的控制。
目標(biāo)代碼簡(jiǎn)短,占用內(nèi)存少,執(zhí)行速度快。
匯編指令是機(jī)器指令的助記符,同機(jī)器指令一一對(duì)應(yīng)。每一種CPU都有自己的機(jī)器指令集\匯編指令集,所以匯編語(yǔ)言不具備可移植性。
知識(shí)點(diǎn)過(guò)多,開(kāi)發(fā)者需要對(duì)CPU等硬件結(jié)構(gòu)有所了解,不易于編寫(xiě)、調(diào)試、維護(hù)。
不區(qū)分大小寫(xiě),比如mov和MOV是一樣的。
1.3 匯編語(yǔ)言的種類
- 目前討論比較多的匯編語(yǔ)言有:
- 8086匯編(8086處理器是16bit的CPU)
- Win32匯編
- Win64匯編
- ARM匯編(嵌入式、Mac、iOS)
- 我們iPhone里面用到的是ARM匯編,但是不同的設(shè)備也有差異.因CPU的架構(gòu)不同.
架構(gòu) | 設(shè)備 |
---|---|
armv6 | iPhone, iPhone2, iPhone3G, 第一代、第二代 iPod Touch |
armv7 | iPhone3GS, iPhone4, iPhone4S,iPad, iPad2, iPad3(The New iPad), iPad mini, iPod Touch 3G, iPod Touch4 |
armv7s | iPhone5, iPhone5C, iPad4(iPad with Retina Display) |
arm64 | iPhone5S 以后 iPhone13 , iPad Air, iPad mini2以后 |
1.4 匯編程序的種類
- 簡(jiǎn)單匯編程序
簡(jiǎn)單匯編程序 又稱“裝入并執(zhí)行”式匯編程序。由于簡(jiǎn)便而得到廣泛使用。這種匯編程序的特點(diǎn)是匯編后的機(jī)器語(yǔ)言程序直接放在內(nèi)存之中準(zhǔn)備執(zhí)行。目標(biāo)程序所占據(jù)的存儲(chǔ)位置是在匯編時(shí)固定的,并且以后不能改變,所以這種工作方式不能將多個(gè)獨(dú)立匯編的子程序合并為一個(gè)完整的程序,而且只能調(diào)用位置與目標(biāo)程序不沖突的程序庫(kù)中的子程序。
- 模塊匯編程序
模塊匯編程序 為適應(yīng)模塊程序設(shè)計(jì)方法而研制的。它除了克服簡(jiǎn)單匯編程序的缺點(diǎn)之外,還提供并行設(shè)計(jì)、編碼和調(diào)試不同程序模塊的能力,而且更改程序時(shí)只更改有關(guān)的模塊即可。每個(gè)匯編后的程序模塊稱為目標(biāo)模塊,多個(gè)目標(biāo)模塊經(jīng)連接裝配程序組合成一個(gè)完整的可執(zhí)行的程序。
- 條件匯編程序
條件匯編程序 主要特點(diǎn)是具有選擇匯編某些程序段的能力。它適用于編寫(xiě)選擇性較大的程序或程序包,以便根據(jù)用戶的需要和設(shè)備的配置情況剪裁、編制適當(dāng)?shù)能浖?。這種匯編語(yǔ)言通常要引入“條件轉(zhuǎn)移”、“轉(zhuǎn)移”等匯編指示,以便根據(jù)用戶指定的匯編條件有選擇地匯編某些程序段或控制匯編程序的加工路徑。
- 宏匯編程序
宏匯編程序 主要特點(diǎn)是在匯編程序中增加宏加工功能。它允許用戶方便地定義和使用宏指令,適用于程序中多處出現(xiàn)、具有一定格式、可以通過(guò)少數(shù)參數(shù)調(diào)節(jié)改變的程序段落的場(chǎng)合。采用這種方法不僅減少程序的長(zhǎng)度,增加可讀性,而且程序段落的格式需要改變時(shí),只須改動(dòng)定義處,而不必改動(dòng)每一使用處。
- 高級(jí)匯編程序
高級(jí)匯編程序 采用高級(jí)程序設(shè)計(jì)語(yǔ)言的控制語(yǔ)句結(jié)構(gòu)的匯編程序。它不僅保持匯編語(yǔ)言表達(dá)能力強(qiáng)、程序運(yùn)行效率高的優(yōu)點(diǎn),而且能充分吸收高級(jí)語(yǔ)言書(shū)寫(xiě)簡(jiǎn)單和易讀的長(zhǎng)處。這是由于高級(jí)匯編程序允許用戶使用高級(jí)程序設(shè)計(jì)語(yǔ)言的控制語(yǔ)句(如條件語(yǔ)句、循環(huán)語(yǔ)句、函數(shù)和過(guò)程)編寫(xiě)程序中的控制部分,而且還允許用戶直接利用匯編語(yǔ)言直接控制存儲(chǔ)分配、存取寄存器硬件,描述高級(jí)語(yǔ)言難于表達(dá)的算法。第一個(gè)高級(jí)匯編程序是N.沃思為IBM360系統(tǒng)研制的PL/360語(yǔ)言匯編程序,其特點(diǎn)是程序的控制部分采用高級(jí)語(yǔ)言的控制語(yǔ)句編寫(xiě),而數(shù)據(jù)加工部分采用IBM360匯編指令編寫(xiě)。自此以后,又相繼出現(xiàn)了類似ALGOL的匯編程序,類似FORTRAN的匯編程序FAT 。
2. 匯編學(xué)習(xí)必要知識(shí)
- 要想學(xué)好匯編,首先需要了解CPU等硬件結(jié)構(gòu),需要理解APP/程序的執(zhí)行過(guò)程;其中硬件相關(guān)最為重要是CPU/內(nèi)存。在匯編中,大部分指令都是和CPU與內(nèi)存相關(guān)的。
2.1 app程序執(zhí)行過(guò)程
-
APP/程序的執(zhí)行過(guò)程?
APP/程序的執(zhí)行過(guò)程
2.2 總線
- 每一個(gè)CPU芯片都有許多管腳,這些管腳和總線相連,CPU通過(guò)總線跟外部器件進(jìn)行交互
- 總線:一根根導(dǎo)線的集合
- 總線的分類
- 地址總線
- 數(shù)據(jù)總線
控制總線
微型計(jì)算機(jī)基本結(jié)構(gòu)
-
實(shí)例1:CPU從內(nèi)存的3號(hào)單元讀取數(shù)據(jù)
CPU從內(nèi)存的3號(hào)單元讀取數(shù)據(jù) - 地址總線
- 它的寬度決定了CPU的尋址能力
8086的地址總線寬度是20,所以尋址能力是1M( 220 )
地址總線內(nèi)存地址
- 數(shù)據(jù)總線
- 它的寬度決定了CPU的單次數(shù)據(jù)傳送量,也就是數(shù)據(jù)傳送速度
- 8086的數(shù)據(jù)總線寬度是16,所以單次最大傳遞2個(gè)字節(jié)的數(shù)據(jù)
- 控制總線
它的寬度決定了CPU對(duì)其他器件的控制能力、能有多少種控制。
- 實(shí)例2:
- 一個(gè)CPU 的尋址能力為8KB,那么它的地址總線的寬度為13__
- 8080,8088,80286,80386 的地址總線寬度分別為16根,20根,24根,32根.那么他們的尋址能力分別為多少__64__KB, __1__MB,___16_MB,__4__GB?
- 8080,8088,8086,80286,80386 的數(shù)據(jù)總線寬度分別為8根,8根,16根,16根,32根.那么它們一次可以傳輸?shù)臄?shù)據(jù)為:___1_B,__1__B,__2__B,__2__B,__4__B,
- 從內(nèi)存中讀取1024字節(jié)的數(shù)據(jù),8086至少要讀512次,80386至少要讀取256次.
2.3 內(nèi)存
- 內(nèi)存地址空間的大小受CPU地址總線寬度的限制。8086的地址總線寬度為20,可以定位220個(gè)不同的內(nèi)存單元(內(nèi)存地址范圍0x00000~0xFFFFF),所以8086的內(nèi)存空間大小為1MB
- 0x00000~0x9FFFF:主存儲(chǔ)器??勺x可寫(xiě)
- 0xA0000~0xBFFFF:向顯存中寫(xiě)入數(shù)據(jù),這些數(shù)據(jù)會(huì)被顯卡輸出到顯示器??勺x可寫(xiě)
- 0xC0000~0xFFFFF:存儲(chǔ)各種硬件\系統(tǒng)信息。只讀
2.4 CPU
CPU除了有控制器、運(yùn)算器還有寄存器。其中寄存器的作用就是進(jìn)行數(shù)據(jù)的臨時(shí)存儲(chǔ)。
CPU的運(yùn)算速度是非??斓?,為了性能CPU在內(nèi)部開(kāi)辟一小塊臨時(shí)存儲(chǔ)區(qū)域,并在進(jìn)行運(yùn)算時(shí)先將數(shù)據(jù)從內(nèi)存復(fù)制到這一小塊臨時(shí)存儲(chǔ)區(qū)域中,運(yùn)算時(shí)就在這一小快臨時(shí)存儲(chǔ)區(qū)域內(nèi)進(jìn)行。我們稱這一小塊臨時(shí)存儲(chǔ)區(qū)域?yàn)榧拇嫫鳌?/p>
對(duì)于arm64系的CPU來(lái)說(shuō), 如果寄存器以x開(kāi)頭則表明的是一個(gè)64位的寄存器,如果以w開(kāi)頭則表明是一個(gè)32位的寄存器,在系統(tǒng)中沒(méi)有提供16位和8位的寄存器供訪問(wèn)和使用。其中32位的寄存器是64位寄存器的低32位部分并不是獨(dú)立存在的。
2.4.1 高速緩存
- iPhoneX上搭載的ARM處理器A11它的1級(jí)緩存的容量是64KB,2級(jí)緩存的容量8M.
- CPU每執(zhí)行一條指令前都需要從內(nèi)存中將指令讀取到CPU內(nèi)并執(zhí)行。而寄存器的運(yùn)行速度相比內(nèi)存讀寫(xiě)要快很多,為了性能,CPU還集成了一個(gè)高速緩存存儲(chǔ)區(qū)域.當(dāng)程序在運(yùn)行時(shí),先將要執(zhí)行的指令代碼以及數(shù)據(jù)復(fù)制到高速緩存中去(由操作系統(tǒng)完成).CPU直接從高速緩存依次讀取指令來(lái)執(zhí)行.
2.5 進(jìn)制
很多人學(xué)不好進(jìn)制,原因是總以十進(jìn)制為依托去考慮其他進(jìn)制,需要運(yùn)算的時(shí)候也總是先轉(zhuǎn)換成十進(jìn)制,這種學(xué)習(xí)方法是錯(cuò)誤的.
我們?yōu)槭裁匆欢ㄒD(zhuǎn)換十進(jìn)制呢??jī)H僅是因?yàn)槲覀儗?duì)十進(jìn)制最熟悉,所以才轉(zhuǎn)換.
每一種進(jìn)制都是完美的,想學(xué)好進(jìn)制首先要忘掉十進(jìn)制,也要忘掉進(jìn)制間的轉(zhuǎn)換!
2.5.1 進(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)一
- 1 + 1 在什么情況下等于 3 ?
- 十進(jìn)制由10個(gè)符號(hào)組成: 0 1 3 2 8 A B E S 7 逢十進(jìn)一
- 如果這樣定義十進(jìn)制: 1 + 1 = 3!就對(duì)了!
- 十進(jìn)制由十個(gè)符號(hào)組成,逢十進(jìn)一,符號(hào)是可以自定義的!!
傳統(tǒng)我們定義的十進(jìn)制和自定義的十進(jìn)制不一樣.那么這10個(gè)符號(hào)如果我們不告訴別人這個(gè)符號(hào)表,別人是沒(méi)辦法拿到我們的具體數(shù)據(jù)的!這樣我們可以將自定義的十進(jìn)制符號(hào)用于加密!
2.5.2 進(jìn)制的乘法表
- 如果現(xiàn)在讓你做一個(gè)8進(jìn)制的運(yùn)算題,如果只給你一支筆,你多久可以計(jì)算出答案呢?
計(jì)算下面兩個(gè)8進(jìn)制數(shù)據(jù)的加減乘除運(yùn)算:
2 + 3 = __ ,
2 * 3 = __ ,
4 + 5 = __ ,
4 * 5 = __.
277 + 333 = __ ,
276 * 54 = __ ,
237 - 54 = __ ,
234 / 4 = __ .
- 如果把上面的8題目改成10進(jìn)制,相信很多童鞋都是可以很快計(jì)算出來(lái)的,這是因?yàn)槲覀冃W(xué)的時(shí)候就背了99乘法表。如果沒(méi)有借助乘法表,我們也是很難計(jì)算10進(jìn)制的乘除法的。
- 所以我們計(jì)算其他進(jìn)制的運(yùn)算也是需要通過(guò)乘法表來(lái)計(jì)算的。
2.5.3 進(jìn)制的運(yùn)算
- 八進(jìn)制加法表
0 1 2 3 4 5 6 7
10 11 12 13 14 15 16 17
20 21 22 23 24 25 26 27
...
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)制乘法表
0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20 21 22 23 24 25 26 27...
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
- 實(shí)例3: 四則運(yùn)算
277 236 276 234
+ 333 - 54 * 54 / 4
-------- -------- -------- --------
2.5.4 二進(jìn)制
- 二進(jìn)制的簡(jiǎn)寫(xiě)形式
二進(jìn)制: 1 0 1 1 1 0 1 1 1 1 0 0
三個(gè)二進(jìn)制一組: 101 110 111 100
八進(jìn)制: 5 6 7 4
四個(gè)二進(jìn)制一組: 1011 1011 1100
十六進(jìn)制: b b c
二進(jìn)制:從0 寫(xiě)到 1111
0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
這種二進(jìn)制使用起來(lái)太麻煩,改成更簡(jiǎn)單一點(diǎn)的符號(hào):
0 1 2 3 4 5 6 7 8 9 A B C D E F 這就是十六進(jìn)制了
2.5.6 數(shù)據(jù)的寬度
- 數(shù)學(xué)上的數(shù)字,是沒(méi)有大小限制的,可以無(wú)限的大。但在計(jì)算機(jī)中,由于受硬件的制約,數(shù)據(jù)都是有長(zhǎng)度限制的(我們稱為數(shù)據(jù)寬度),超過(guò)最多寬度的數(shù)據(jù)會(huì)被丟棄。
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int test(){
int cTemp = 0x1FFFFFFFF;
return cTemp;
}
int main(int argc, char * argv[]) {
printf("%x\n",test());
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
2.5.7 計(jì)算機(jī)中常見(jiàn)的數(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位)
無(wú)符號(hào)數(shù),直接換算!
有符號(hào)數(shù):
正數(shù): 0 1 2 3 4 5 6 7
負(fù)數(shù): F E D B C A 9 8
-1 -2 -3 -4 -5 -6 -7 -8
2.5.8 自定義進(jìn)制符號(hào)
- 實(shí)例4:現(xiàn)在有10進(jìn)制數(shù) 10個(gè)符號(hào)分別是:2,9,1,7,6,5,4, 8,3 , A 逢10進(jìn)1 那么: 123 + 234 = ____
十進(jìn)制: 0 1 2 3 4 5 6 7 8 9
自定義: 2 9 1 7 6 5 4 8 3 A
92 99 91 97 96 95 94 98 93 9A
12 19 11 17 16 15 14 18 13 1A
72 79 71 77 76 75 74 78 73 7A
62 69 61 67 66 65 64 68 63 6A
52 59 51 57 56 55 54 58 53 5A
42 49 41 47 46 45 44 48 43 4A
82 89 81 87 86 85 84 88 83 8A
32 39 31 37 36 35 34 38 33 3A
922
那么剛才通過(guò)10進(jìn)制運(yùn)算可以轉(zhuǎn)化10進(jìn)制然后查表!但是如果是其他進(jìn)制.我們就不能轉(zhuǎn)換,要直接學(xué)會(huì)查表
- 實(shí)例5: 現(xiàn)在有9進(jìn)制數(shù) 9個(gè)符號(hào)分別是:2,9,1,7,6,5,4, 8,3 逢9進(jìn)1 那么: 123 + 234 = ____
十進(jìn)制: 0 1 2 3 4 5 6 7 8
自定義: 2 9 1 7 6 5 4 8 3
92 99 91 97 96 95 94 98 93
12 19 11 17 16 15 14 18 13
72 79 71 77 76 75 74 78 73
62 69 61 67 66 65 64 68 63
52 59 51 57 56 55 54 58 53
42 49 41 47 46 45 44 48 43
82 89 81 87 86 85 84 88 83
32 39 31 37 36 35 34 38 33
922
2.6 寄存器
2.6.1 寄存器簡(jiǎn)介
- 什么是寄存器
- 寄存器是CPU內(nèi)部用來(lái)存放數(shù)據(jù)的一些小型存儲(chǔ)區(qū)域,用來(lái)暫時(shí)存放參與運(yùn)算的數(shù)據(jù)和運(yùn)算結(jié)果。其實(shí)寄存器就是一種常用的時(shí)序邏輯電路,但這種時(shí)序邏輯電路只包含存儲(chǔ)電路。寄存器的存儲(chǔ)電路是由鎖存器或觸發(fā)器構(gòu)成的,因?yàn)橐粋€(gè)鎖存器或觸發(fā)器能存儲(chǔ)1位二進(jìn)制數(shù),所以由N個(gè)鎖存器或觸發(fā)器可以構(gòu)成N位寄存器。寄存器是中央處理器內(nèi)的組成部分。寄存器是有限存儲(chǔ)容量的高速存儲(chǔ)部件,它們可用來(lái)暫存指令、數(shù)據(jù)和位址。
- 寄存器的功能是存儲(chǔ)二進(jìn)制代碼,它是由具有存儲(chǔ)功能的觸發(fā)器組合起來(lái)構(gòu)成的。一個(gè)觸發(fā)器可以存儲(chǔ)1位二進(jìn)制代碼,故存放n位二進(jìn)制代碼的寄存器,需用n個(gè)觸發(fā)器來(lái)構(gòu)成。
- 按照功能的不同,可將寄存器分為基本寄存器和移位寄存器兩大類。基本寄存器只能并行送入數(shù)據(jù),也只能并行輸出。移位寄存器中的數(shù)據(jù)可以在移位脈沖作用下依次逐位右移或左移,數(shù)據(jù)既可以并行輸入、并行輸出,也可以串行輸入、串行輸出,還可以并行輸入、串行輸出,或串行輸入、并行輸出,十分靈活,用途也很廣。
- 在計(jì)算機(jī)領(lǐng)域,寄存器是CPU內(nèi)部的元件,包括通用寄存器、專用寄存器和控制寄存器。寄存器擁有非常高的讀寫(xiě)速度,所以在寄存器之間的數(shù)據(jù)傳送非???。
-
內(nèi)部部件之間由總線連接
內(nèi)部部件之間由總線連接
- 對(duì)程序員來(lái)說(shuō),CPU中最主要部件是寄存器,可以通過(guò)改變寄存器的內(nèi)容來(lái)實(shí)現(xiàn)對(duì)CPU的控制
- 不同的CPU,寄存器的個(gè)數(shù)、結(jié)構(gòu)是不相同的
- 寄存器的特點(diǎn)
- 寄存器最起碼具備以下4種功能:
①清除數(shù)碼:將寄存器里的原有數(shù)碼清除。
②接收數(shù)碼:在接收脈沖作用下,將外輸人數(shù)碼存人寄存器中。
③存儲(chǔ)數(shù)碼:在沒(méi)有新的寫(xiě)入脈沖來(lái)之前,寄存器能保存原有數(shù)碼不變。
④輸出數(shù)碼:在輸出脈沖作用下,才通過(guò)電路輸出數(shù)碼。- 僅具有以上功能的寄存器稱為數(shù)碼寄存器;有的寄存器還具有移位功能,稱為移位寄存器
寄存器有串行和并行兩種數(shù)碼存取方式。將凡位二進(jìn)制數(shù)一次存人寄存器或從寄存器中讀出的方式稱為并行方式。將n位二進(jìn)制數(shù)以每次l位,分成n次存人寄存器并從寄存器讀出,這種方式稱為串行方式。并行方式只需一個(gè)時(shí)鐘脈沖就可以完成數(shù)據(jù)操作,工作速度快,但需要n根輸入和輸出數(shù)據(jù)線。串行方式要使用幾個(gè)時(shí)鐘脈沖完成輸入或輸出操作,工作速度慢,但只需要一根輸入或輸出數(shù)據(jù)線,傳輸線少,適用于遠(yuǎn)距離傳輸。
控制寄存器
- 寄存器的結(jié)構(gòu)
- 在數(shù)字電路中,用來(lái)存放二進(jìn)制數(shù)據(jù)或代碼的電路稱為寄存器。寄存器是由具有存儲(chǔ)功能的觸發(fā)器組合起來(lái)構(gòu)成的。一個(gè)觸發(fā)器可以存儲(chǔ)1位二進(jìn)制代碼,存放門(mén)位二進(jìn)制代碼的寄存器需用竹個(gè)觸發(fā)器來(lái)構(gòu)成
- 對(duì)寄存器中的觸發(fā)器只要求它們具有置1,置0的功能即可,因而無(wú)論是用電平觸發(fā)的觸發(fā)器,還是用脈沖觸發(fā)或邊沿觸發(fā)的觸發(fā)器,都可以組成寄存器。
- 74HC175則是用CMOS邊沿觸發(fā)器組成的4位寄存器,根據(jù)邊沿觸發(fā)的動(dòng)作特點(diǎn)可知,觸發(fā)器輸出端的狀態(tài)僅僅取決于CLK上升沿到達(dá)時(shí)刻D端的狀態(tài)??梢?jiàn),雖然74LS75和74HC175都是4位寄存器,但由于采用了不同結(jié)構(gòu)類型的觸發(fā)器,所以動(dòng)作特點(diǎn)是不同的
- 為了增加使用的靈活性,在有些寄存器電路中還附加了一些控制電路,使寄存器又增添了異步置零、輸出三態(tài)控制和保持等功能。這里所說(shuō)的保持,是指CLK信號(hào)到達(dá)時(shí)觸發(fā)器不隨D端的輸入信號(hào)而改變狀態(tài),保持原來(lái)的狀態(tài)不變。
上面介紹的兩個(gè)寄存器電路中,接收數(shù)據(jù)時(shí)所有各位代碼都是同時(shí)輸入的,而且觸發(fā)器中的數(shù)據(jù)是并行地出現(xiàn)在輸出端的,因此將這種輸入、輸出方式稱為并行輸入、并行輸出方式。
4位寄存器
2.6.2 寄存器類型
2.6.2.1 通用寄存器
通用寄存器組包括AX、BX、CX、DX4個(gè)16位寄存器,用以存放16位數(shù)據(jù)或地址。也可用作8位寄存器。用作8位寄存器時(shí)分別記為AH、AL、BH、BL、CH、CL、DH、DL。只能存放8位數(shù)據(jù),不能存放地址。它們分別是AX、BX、CX、DX的高八位和低八位。若AX=1234H,則AH=12H,AL=34H。通用寄存器通用性強(qiáng),對(duì)任何指令,它們具有相同的功能。為了縮短指令代碼的長(zhǎng)度,在8086中,某些通用寄存器用作專門(mén)用途。例如,串指令中必須用CX寄存器作為計(jì)數(shù)寄存器,存放串的長(zhǎng)度,這樣在串操作指令中不必給定CX的寄存器號(hào),縮短了串操作指令代碼的長(zhǎng)度。
- AX(AH、AL):累加器。有些指令約定以AX(或AL)為源或目的寄存器。輸入/輸出指令必須通過(guò)AX或AL實(shí)現(xiàn),例如:端口地址為43H的內(nèi)容讀入CPU的指令為INAL,43H或INAX,43H。目的操作數(shù)只能是AL/AX,而不能是其他的寄存器。
- BX(BH、BL):基址寄存器。BX可用作間接尋址的地址寄存器和基地址寄存器,BH、BL可用作8位通用數(shù)據(jù)寄存器。
- CX(CH、CL):計(jì)數(shù)寄存器。CX在循環(huán)和串操作中充當(dāng)計(jì)數(shù)器,指令執(zhí)行后CX內(nèi)容自動(dòng)修改,因此稱為計(jì)數(shù)寄存器。
- DX(DH、DL):數(shù)據(jù)寄存器。除用作通用寄存器外,在1/O指令中可用作端口地址寄存器,乘除指令中用作輔助累加器。
- ARM64擁有有31個(gè)64位的通用寄存器 x0 到 x30,這些寄存器通常用來(lái)存放一般性的數(shù)據(jù),稱為通用寄存器(有時(shí)也有特定用途)
那么w0 到 w28 這些是32位的. 因?yàn)?4位CPU可以兼容32位.所以可以只使用64位寄存器的低32位.
比如 w0 就是 x0的低32位!
通用寄存器代碼調(diào)試
通常,CPU會(huì)先將內(nèi)存中的數(shù)據(jù)存儲(chǔ)到通用寄存器中,然后再對(duì)通用寄存器中的數(shù)據(jù)進(jìn)行運(yùn)算
-
假設(shè)內(nèi)存中有塊紅色內(nèi)存空間的值是3,現(xiàn)在想把它的值加1,并將結(jié)果存儲(chǔ)到藍(lán)色內(nèi)存空間
CPU存儲(chǔ)
CPU首先會(huì)將紅色內(nèi)存空間的值放到X0寄存器中:mov X0,紅色內(nèi)存空間
然后讓X0寄存器與1相加:add X0,1
最后將值賦值給內(nèi)存空間:mov 藍(lán)色內(nèi)存空間,X0
2.6.2.2 段寄存器
- 8086/8088CPU可直接尋址1MB的存儲(chǔ)器空間,直接尋址需要20位地址碼,而所有內(nèi)部寄存器都是16位的,只能直接尋址6KB,因此采用分段技術(shù)來(lái)解決。將1MB的存儲(chǔ)空間分成若干邏輯段,每段最長(zhǎng)64KB,這些邏輯段在整個(gè)存儲(chǔ)空間中可浮動(dòng)。
- 8086/8088CPU內(nèi)部設(shè)置了4個(gè)16位段寄存器,它們分別是代碼段寄存器CS、數(shù)據(jù)段寄存器DS、堆棧段寄存器SS、附加段寄存器ES、由它們給出相應(yīng)邏輯段的首地址,稱為“段基址”。段基址與段內(nèi)偏移地址組合形成20位物理地址,段內(nèi)偏移地址可以存放在寄存器中,也可以存放在存儲(chǔ)器中。
- 例如:代碼段寄存器CS存放當(dāng)前代碼段基地址,IP指令指針寄存器存放了下一條要執(zhí)行指令的段內(nèi)偏移地址,其中CS=2000H,IP=001AH。通過(guò)組合,形成20位存儲(chǔ)單元的尋址地址為2001AH。
- 代碼段內(nèi)存放可執(zhí)行的指令代碼,數(shù)據(jù)段和附加段內(nèi)存放操作的數(shù)據(jù),通常操作數(shù)在現(xiàn)行數(shù)據(jù)段中,而在串指令中,目的操作數(shù)指明必須在現(xiàn)行附加段中。堆棧段開(kāi)辟為程序執(zhí)行中所要用的堆棧區(qū),采用先進(jìn)后出的方式訪問(wèn)它。各個(gè)段寄存器指明了一個(gè)規(guī)定的現(xiàn)行段,各段寄存器不可互換使用。程序較小時(shí),代碼段、數(shù)據(jù)段、堆棧段可放在一個(gè)段內(nèi),即包含在64KB之內(nèi),而當(dāng)程序或數(shù)據(jù)量較大時(shí),超過(guò)了64KB,那么可以定義多個(gè)代碼段或數(shù)據(jù)段、堆棧段、附加段。現(xiàn)行段由段寄存器指明段地址,使用中可以修改段寄存器內(nèi)容,指向其他段。有時(shí)為了明確起見(jiàn),可在指令前加上段超越的前綴,以指定操作數(shù)所在段。
2.6.2.3 指令指針寄存器
pc寄存器(program counter)
- 為指令指針寄存器,它指示了CPU當(dāng)前要讀取指令的地址
- 在內(nèi)存或者磁盤(pán)上,指令和數(shù)據(jù)沒(méi)有任何區(qū)別,都是二進(jìn)制信息
- CPU在工作的時(shí)候把有的信息看做指令,有的信息看做數(shù)據(jù),為同樣的信息賦予了不同的意義
比如 1110 0000 0000 0011 0000 1000 1010 1010
可以當(dāng)做數(shù)據(jù) 0xE003008AA
也可以當(dāng)做指令 mov x0, x8
- CPU根據(jù)什么將內(nèi)存中的信息看做指令?
CPU將pc指向的內(nèi)存單元的內(nèi)容看做指令
如果內(nèi)存中的某段內(nèi)容曾被CPU執(zhí)行過(guò),那么它所在的內(nèi)存單元必然被pc指向過(guò)
-
8086/8088CPU中設(shè)置了一個(gè)16位指令指針寄存器IP,用來(lái)存放將要執(zhí)行的下一條指令在現(xiàn)行代碼段中的偏移地址。程序運(yùn)行中,它由BIU自動(dòng)修改,使IP始終指向下一條將要執(zhí)行的指令的地址,因此它是用來(lái)控制指令序列的執(zhí)行流程的,是一個(gè)重要的寄存器。8086程序不能直接訪問(wèn)IP,但可以通過(guò)某些指令修改IP的內(nèi)容。例如,當(dāng)遇到中斷指令或調(diào)用子程序指令時(shí),8086自動(dòng)調(diào)整IP的內(nèi)容,將IP中下一條將要執(zhí)行的指令地址偏移量人棧保護(hù),待中斷程序執(zhí)行完畢或子程序返回時(shí),可將保護(hù)的內(nèi)容從堆棧中彈出到IP,使主程序繼續(xù)運(yùn)行。在跳轉(zhuǎn)指令時(shí),則將新的跳轉(zhuǎn)目標(biāo)地址送入IP,改變它的內(nèi)容,實(shí)現(xiàn)了程序的轉(zhuǎn)移。寄存器
2.6.2.4 指針和變址寄存器
BP( Base Pointer regilter):基址指針寄存器。
SP( Stack Pointer Register):堆棧指針寄存器。
SI( Source Index register):源變址寄存器。
DI( Destination Index Register):目的變址寄存器。
這組寄存器存放的內(nèi)容是某一段內(nèi)地址偏移量,用來(lái)形成操作數(shù)地址,主要在堆棧操作和變址運(yùn)算中使用。BP和SP寄存器稱為指針寄存器,與SS聯(lián)用,為訪問(wèn)現(xiàn)行堆棧段提供方便。通常BP寄存器在間接尋址中使用,操作數(shù)在堆棧段中,由SS段寄存器與BP組合形成操作數(shù)地址即BP中存放現(xiàn)行堆棧段中一個(gè)數(shù)據(jù)區(qū)的“基址”的偏移量,所以稱BP寄存器為基址指針。
SP寄存器在堆棧操作中使用,PUSH和POP指令是從SP寄存器得到現(xiàn)行堆棧段的段內(nèi)地址偏移量,所以稱SP寄存器為堆棧指針,SP始終指向棧頂。
寄存器SI和DI稱為變址寄存器,通常與DS一起使用,為訪問(wèn)現(xiàn)行數(shù)據(jù)段提供段內(nèi)地址偏移量。在串指令中,其中源操作數(shù)的偏移量存放在SⅠ中,目的操作數(shù)的偏移量存放在DI中,SI和DI的作用不能互換,否則傳送地址相反。在串指令中,SI、DI均為隱含尋址,此時(shí),SI和DS聯(lián)用,D和ES聯(lián)用。
2.6.2.5 標(biāo)志寄存器FR寄存器
- 標(biāo)志寄存器FR也稱程序狀態(tài)字寄存器。
- FR是16位寄存器,其中有9位有效位用來(lái)存放狀態(tài)標(biāo)志和控制標(biāo)志。狀態(tài)標(biāo)志共6位,CF、PF、AF、ZF、SF和OF,用于寄存程序運(yùn)行的狀態(tài)信息,這些標(biāo)志往往用作后續(xù)指令判斷的依據(jù)。控制標(biāo)志有3位,IF、DF和TF,用于控制CPU的操作,是人為設(shè)置的。
2.6.2.6 數(shù)據(jù)地址寄存器
- 數(shù)據(jù)地址寄存器通常用來(lái)做數(shù)據(jù)計(jì)算的臨時(shí)存儲(chǔ)、做累加、計(jì)數(shù)、地址保存等功能。定義這些寄存器的作用主要是用于在CPU指令中保存操作數(shù),在CPU中當(dāng)做一些常規(guī)變量來(lái)使用。
ARM64中
64位: X0-X30, XZR(零寄存器)
32位: W0-W30, WZR(零寄存器)
注意:
之前講解8086匯編中有一種特殊的寄存器段寄存器:CS,DS,SS,ES四個(gè)寄存器來(lái)保存這些段的基地址,這個(gè)屬于Intel架構(gòu)CPU中.在ARM中并沒(méi)有
2.6.2.7 浮點(diǎn)和向量寄存器
因?yàn)楦↑c(diǎn)數(shù)的存儲(chǔ)以及其運(yùn)算的特殊性,CPU中專門(mén)提供浮點(diǎn)數(shù)寄存器來(lái)處理浮點(diǎn)數(shù)
- 浮點(diǎn)寄存器 64位: D0 - D31 32位: S0 - S31
現(xiàn)在的CPU支持向量運(yùn)算.(向量運(yùn)算在圖形處理相關(guān)的領(lǐng)域用得非常的多)為了支持向量計(jì)算系統(tǒng)了也提供了眾多的向量寄存器.
- 向量寄存器 128位:V0-V31
2.6.2.8 狀態(tài)寄存器
- CPU內(nèi)部的寄存器中,有一種特殊的寄存器(對(duì)于不同的處理器,個(gè)數(shù)和結(jié)構(gòu)都可能不同).這種寄存器在ARM中,被稱為狀態(tài)寄存器就是CPSR(current program status register)寄存器
- CPSR和其他寄存器不一樣,其他寄存器是用來(lái)存放數(shù)據(jù)的,都是整個(gè)寄存器具有一個(gè)含義.而CPSR寄存器是按位起作用的,也就是說(shuō),它的每一位都有專門(mén)的含義,記錄特定的信息.
注:CPSR寄存器是32位的
- CPSR的低8位(包括I、F、T和M[4:0])稱為控制位,程序無(wú)法修改,除非CPU運(yùn)行于特權(quán)模式下,程序才能修改控制位!
- N、Z、C、V均為條件碼標(biāo)志位。它們的內(nèi)容可被算術(shù)或邏輯運(yùn)算的結(jié)果所改變,并且可以決定某條指令是否被執(zhí)行!意義重大!
N(Negative)標(biāo)志
- CPSR的第31位是 N,符號(hào)標(biāo)志位。它記錄相關(guān)指令執(zhí)行后,其結(jié)果是否為負(fù).如果為負(fù) N = 1,如果是非負(fù)數(shù) N = 0.
注意,在ARM64的指令集中,有的指令的執(zhí)行時(shí)影響狀態(tài)寄存器的,比如add\sub\or等,他們大都是運(yùn)算指令(進(jìn)行邏輯或算數(shù)運(yùn)算);
Z(Zero)標(biāo)志
- CPSR的第30位是Z,0標(biāo)志位。它記錄相關(guān)指令執(zhí)行后,其結(jié)果是否為0.如果結(jié)果為0.那么Z = 1.如果結(jié)果不為0,那么Z = 0.
- 對(duì)于Z的值,我們可以這樣來(lái)看,Z標(biāo)記相關(guān)指令的計(jì)算結(jié)果是否為0,如果為0,則Z要記錄下是0這樣的肯定信息.在計(jì)算機(jī)中1表示邏輯真,表示肯定.所以當(dāng)結(jié)果為0的時(shí)候Z = 1,表示結(jié)果是0.如果結(jié)果不為0,則Z要記錄下不是0這樣的否定信息.在計(jì)算機(jī)中0表示邏輯假,表示否定,所以當(dāng)結(jié)果不為0的時(shí)候Z = 0,表示結(jié)果不為0。
C(Carry)標(biāo)志
- CPSR的第29位是C,進(jìn)位標(biāo)志位。一般情況下,進(jìn)行無(wú)符號(hào)數(shù)的運(yùn)算。
- 加法運(yùn)算:當(dāng)運(yùn)算結(jié)果產(chǎn)生了進(jìn)位時(shí)(無(wú)符號(hào)數(shù)溢出),C=1,否則C=0。
- 減法運(yùn)算(包括CMP):當(dāng)運(yùn)算時(shí)產(chǎn)生了借位時(shí)(無(wú)符號(hào)數(shù)溢出),C=0,否則C=1。
-
對(duì)于位數(shù)為N的無(wú)符號(hào)數(shù)來(lái)說(shuō),其對(duì)應(yīng)的二進(jìn)制信息的最高位,即第N - 1位,就是它的最高有效位,而假想存在的第N位,就是相對(duì)于最高有效位的更高位。如下圖所示:
C(Carry)標(biāo)志
進(jìn)位
- 我們知道,當(dāng)兩個(gè)數(shù)據(jù)相加的時(shí)候,有可能產(chǎn)生從最高有效位想更高位的進(jìn)位。比如兩個(gè)32位數(shù)據(jù):0xaaaaaaaa + 0xaaaaaaaa,將產(chǎn)生進(jìn)位。由于這個(gè)進(jìn)位值在32位中無(wú)法保存,我們就只是簡(jiǎn)單的說(shuō)這個(gè)進(jìn)位值丟失了。其實(shí)CPU在運(yùn)算的時(shí)候,并不丟棄這個(gè)進(jìn)位制,而是記錄在一個(gè)特殊的寄存器的某一位上。ARM下就用C位來(lái)記錄這個(gè)進(jìn)位值。比如,下面的指令
mov w0,#0xaaaaaaaa;0xa 的二進(jìn)制是 1010
adds w0,w0,w0; 執(zhí)行后 相當(dāng)于 1010 << 1 進(jìn)位1(無(wú)符號(hào)溢出) 所以C標(biāo)記 為 1
adds w0,w0,w0; 執(zhí)行后 相當(dāng)于 0101 << 1 進(jìn)位0(無(wú)符號(hào)沒(méi)溢出) 所以C標(biāo)記 為 0
adds w0,w0,w0; 重復(fù)上面操作
adds w0,w0,w0
借位
- 當(dāng)兩個(gè)數(shù)據(jù)做減法的時(shí)候,有可能向更高位借位。再比如,兩個(gè)32位數(shù)據(jù):0x00000000 - 0x000000ff,將產(chǎn)生借位,借位后,相當(dāng)于計(jì)算0x100000000 - 0x000000ff。得到0xffffff01 這個(gè)值。由于借了一位,所以C位 用來(lái)標(biāo)記借位。C = 0.比如下面指令:
mov w0,#0x0
subs w0,w0,#0xff ;
subs w0,w0,#0xff
subs w0,w0,#0xff
V(Overflow)溢出標(biāo)志
- CPSR的第28位是V,溢出標(biāo)志位。在進(jìn)行有符號(hào)數(shù)運(yùn)算的時(shí)候,如果超過(guò)了機(jī)器所能標(biāo)識(shí)的范圍,稱為溢出。
正數(shù) + 正數(shù) 為負(fù)數(shù) 溢出
負(fù)數(shù) + 負(fù)數(shù) 為正數(shù) 溢出
正數(shù) + 負(fù)數(shù) 不可能溢出
2.6.3 寄存器工作原理
- 在計(jì)算機(jī)及其他計(jì)算系統(tǒng)中,寄存器是一種非常重要的、必不可少的數(shù)字電路苛件,它通常由觸發(fā)器(D觸發(fā)器)組成,主要作用是用來(lái)暫時(shí)存放數(shù)碼或指令。一個(gè)觸發(fā)器司以存放一位二進(jìn)制代碼,若要存放N位二進(jìn)制數(shù)碼,則需用N個(gè)觸發(fā)器。
- 寄存器應(yīng)具有接收數(shù)據(jù)、存放數(shù)據(jù)和輸出數(shù)據(jù)的功能,它由觸發(fā)器和門(mén)電路組成。只有得到“存人脈沖”(又稱“存入指令”、“寫(xiě)入指令”)時(shí),寄存器才能接收數(shù)據(jù);在得到“讀出”指令時(shí),寄存器才將數(shù)據(jù)輸出。
- 寄存器存放數(shù)碼的方式有并行和串行兩種。并行方式是數(shù)碼從各對(duì)應(yīng)位輸入端同時(shí)輸入到寄存器中;串行方式是數(shù)碼從一個(gè)輸入端逐位輸入到寄存器中。
- 寄存器讀出數(shù)碼的方式也有并行和串行兩種。在并行方式中,被讀出的數(shù)碼同時(shí)出現(xiàn)在各位的輸出端上;在串行方式中,被讀出的數(shù)碼在一個(gè)輸出端逐位出現(xiàn)
2.6.4 寄存器尋址
- 寄存器尋址就是利用寄存器中的數(shù)值作為操作數(shù),這種尋址方式是各類微處理器經(jīng)常采用的一種方式,也是一種執(zhí)行效率較高的尋址方式。
- 寄存器尋址是指操作數(shù)存放在CPU內(nèi)部的寄存器中,指令中給出操作數(shù)所在的寄存器名。寄存器操作數(shù)可以是8位寄存器AH、AL、BH、BL、CH、CL、DH、DL,也可以是16位寄存器AX、BX、CX、DX、SP、BP、SI、DI等。因?yàn)榧拇嫫鲗ぶ凡恍枰ㄟ^(guò)總線操作訪問(wèn)存儲(chǔ)器,所以指令執(zhí)行速度比較快。
- 寄存器尋址( Register Addressing)是以通用寄存器的內(nèi)容作為操作數(shù)的尋址方式,在該尋址方式下,操作數(shù)存放在寄存器中。寄存器尋址方式的尋址對(duì)象為:A,B,DPTR,RO~R7。其中,B僅在乘除法指令中為寄存器尋址,在其他指令中為直接尋址。A可以按寄存器尋址又可以直接尋址,直接尋址時(shí)寫(xiě)成ACC。
2.6.5 ARM處理器的寄存器
- ARM微處理器共有37個(gè)32位寄存器,其中31個(gè)為通用寄存器,6個(gè)為狀態(tài)寄存器。但是這些寄存器不能被同時(shí)訪問(wèn),具體哪些寄存器是可編程訪問(wèn)的,取決于微處理器的工作狀態(tài)及具體的運(yùn)行模式。但在任何時(shí)候,通用寄存器R14~R0、程序計(jì)數(shù)器PC、一個(gè)或兩個(gè)狀態(tài)寄存器都是可訪問(wèn)的。
- ARM9處理器共有37個(gè)32位長(zhǎng)的寄存器,這些寄存器包括:
(1) RO~R12:均為32位通用寄存器,用于數(shù)據(jù)操作。但是注意:絕大多數(shù)16位Thumb指令只能訪問(wèn)R0~R7,而32位Thumb -2指令可以訪問(wèn)所有寄存器。
(2)堆棧指針:堆棧指針的最低兩位永遠(yuǎn)是O,這意味著堆棧總是4字節(jié)對(duì)齊的。
(3)鏈接寄存器:當(dāng)呼叫一個(gè)子程序時(shí),由R14存儲(chǔ)返回地址。
(4)程序計(jì)數(shù)器:指向當(dāng)前的程序地址,如果修改它的值,就能改變程序的執(zhí)行流。
(5)6個(gè)狀態(tài)寄存器(1個(gè)CPSR、5個(gè)SPSR),用以標(biāo)識(shí)CPU的丁作狀態(tài)及程序的運(yùn)行狀態(tài),均為32位,目前只使用了其巾的一部分。
3. 常用匯編指令
3.1 bl指令
CPU從何處執(zhí)行指令是由pc中的內(nèi)容決定的,我們可以通過(guò)改變pc的內(nèi)容來(lái)控制CPU執(zhí)行目標(biāo)指令
ARM64提供了一個(gè)mov指令(傳送指令),可以用來(lái)修改大部分寄存器的值,比如
mov x0,#10、mov x1,#20但是,mov指令不能用于設(shè)置pc的值,ARM64沒(méi)有提供這樣的功能
ARM64提供了另外的指令來(lái)修改PC的值,這些指令統(tǒng)稱為轉(zhuǎn)移指令,最簡(jiǎn)單的是bl指令
bl指令實(shí)例:
現(xiàn)在有兩段代碼!假設(shè)程序先執(zhí)行A,請(qǐng)寫(xiě)出指令執(zhí)行順序.最終寄存器x0的值是多少?
_A:
mov x0,#0xa0
mov x1,#0x00
add x1, x0, #0x14
mov x0,x1
bl _B
mov x0,#0x0
ret
_B:
add x0, x0, #0x10
ret