前言
最近準(zhǔn)備學(xué)習(xí)匯編,然后在B站上看到叫iOS小賢的作者發(fā)的視頻挺不錯(cuò),打算跟著學(xué),文章是看視頻的筆記,最后有原視頻鏈接,想看視頻的可以看看通過(guò)鏈接查看視頻。
寄存器

- 內(nèi)部部件之間由總線連接
- 對(duì)程序員來(lái)說(shuō),CPU中最主要部件是寄存器,可以通過(guò)改變寄存器的內(nèi)容來(lái)實(shí)現(xiàn)對(duì)CPU的控制
- 不同的CPU,寄存器的個(gè)數(shù)、結(jié)構(gòu)是不相同的(8086是16位結(jié)構(gòu)的CPU)
通用寄存器
-
ARM64擁有有31個(gè)64位的通用寄存器 x0 到 x30,這些寄存器通常用來(lái)存放一般性的數(shù)據(jù),稱為通用寄存器(有時(shí)也有特定用途)
- 那么w0 到 w28 這些是32位的. 因?yàn)?4位CPU可以兼容32位.所以可以只使用64位寄存器的低32位.
- 比如 w0 就是 x0的低32位!
模擬器是X86架構(gòu),所以用真機(jī)測(cè)才能看到ARM62的寄存器

- 通常,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首先會(huì)將紅色內(nèi)存空間的值放到X0寄存器中:mov X0,紅色內(nèi)存空間
- 然后讓X0寄存器與1相加:add X0,1
- 最后將值賦值給內(nèi)存空間:mov 藍(lán)色內(nèi)存空間,X0
注:為什么是64位寄存器,因?yàn)镃PU是64位的,總線是64位的,一次通電可以傳遞64位的數(shù)據(jù)給CPU,也就是8個(gè)字節(jié),這個(gè)數(shù)據(jù)CPU存在寄存器中,所以寄存器是64位的。
問(wèn): 每次計(jì)算完又開(kāi)辟內(nèi)存空間存放結(jié)果?
答:匯編里面不存在開(kāi)辟空間,銷毀空間,直接通過(guò)內(nèi)存地址訪問(wèn),和高級(jí)語(yǔ)言不一樣。
pc寄存器(program counter)
- 為指令指針寄存器,它指示了CPU當(dāng)前要讀取指令的地址
- 在內(nèi)存或者磁盤上,指令和數(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
0x102aaa928 <+0>: sub sp, sp, #0x10左邊是指令地址,右邊是指令。
Debug -> Debug Workflow -> View Memory 或者通過(guò)快捷鍵:shift+command + m 來(lái)調(diào)用內(nèi)存查看界面

0x102aaa92c - 0x102aaa928 = 4,所以每個(gè)指令戰(zhàn)4個(gè)字節(jié)。
FF 43 00 D1就是指令sub sp, sp, #0x10的二進(jìn)制表現(xiàn)形式。
可以在LLDB輸入ni單步往下走,發(fā)現(xiàn)依然斷點(diǎn)地址依然和pc寄存器一樣的。

輸入register write pc 0x102aaa92c改寫pc寄存器,可以看到跳轉(zhuǎn)到改寫后地址的下一個(gè)寄存器位置。

- CPU根據(jù)什么將內(nèi)存中的信息看做指令?
- CPU將pc指向的內(nèi)存單元的內(nèi)容看做指令
- 如果內(nèi)存中的某段內(nèi)容曾被CPU執(zhí)行過(guò),那么它所在的內(nèi)存單元必然被pc指向過(guò)
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指令
注:#后面跟個(gè)數(shù)字,叫立即數(shù),
bl指令 -- 練習(xí)
現(xiàn)在有兩段代碼!假設(shè)程序先執(zhí)行A,請(qǐng)寫出指令執(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
我們來(lái)寫試試看,在xcode中創(chuàng)建文件,格式選擇Assembly File
.text告訴編譯器在text段,也就是代碼段,.global表示是全局的。
在.m文件中需要加上方法聲明int A();,這樣編譯才能通過(guò),因?yàn)閍sm.s是源文件,編譯的會(huì)鏈接到全局函數(shù)_A。


在A()打斷點(diǎn)

輸入s進(jìn)入函數(shù)A

我們可以看到x0就是a0,此時(shí)x1是50輸入ni單步往下走,x1變成0

add x1, x0, #0x14是把x0加上14然后賦值給x1,這樣x1就變成b4。

mov x0, x1是把x1的值賦值給x0,這樣x0和x1都是b4。

接下來(lái)bl 0x102df2c00跳轉(zhuǎn)到B函數(shù)。

然后一直輸入ni,會(huì)發(fā)現(xiàn)死循環(huán)了,至于為什么之后會(huì)解釋。
關(guān)于CPU&寄存器的補(bǔ)充
寄存器
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ú)立存在的。
注:如果你改了x0寄存器,w0寄存器也會(huì)改,因?yàn)?2位的寄存器是64位寄存器的低32位部分并不是獨(dú)立存在的。
高速緩存
iPhoneX上搭載的ARM處理器A11它的1級(jí)緩存的容量是64KB,2級(jí)緩存的容量8M.
CPU每執(zhí)行一條指令前都需要從內(nèi)存中將指令讀取到CPU內(nèi)并執(zhí)行。而寄存器的運(yùn)行速度相比內(nèi)存讀寫要快很多,為了性能,CPU還集成了一個(gè)高速緩存存儲(chǔ)區(qū)域.當(dāng)程序在運(yùn)行時(shí),先將要執(zhí)行的指令代碼以及數(shù)據(jù)復(fù)制到高速緩存中去(由操作系統(tǒng)完成).CPU直接從高速緩存依次讀取指令來(lái)執(zhí)行.
數(shù)據(jù)地址寄存器
數(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(零寄存器)
注意:
有一種特殊的寄存器段寄存器:CS,DS,SS,ES四個(gè)寄存器來(lái)保存這些段的基地址,這個(gè)屬于Intel架構(gòu)CPU中.在ARM中并沒(méi)有
注:以前內(nèi)存使用段劃分的,現(xiàn)在是平滑狀態(tài),從0到最后,只是文件里面分段,內(nèi)存中不再有段了。
浮點(diǎn)和向量寄存器
因?yàn)楦↑c(diǎn)數(shù)的存儲(chǔ)以及其運(yùn)算的特殊性,CPU中專門提供浮點(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
以上講的都是ARM64寄存器,附上8086的寄存器
- 都是16位的
- 可以存放2個(gè)字節(jié)
