逆向學習筆記3——暫存器與彙編指令
CPU包括控制器、運算器、暫存器。其中暫存器的作用就是進行資料的臨時儲存。
CPU的運算速度是非常快的,為了效能CPU在內部開闢一小塊臨時儲存區域,並在進行運算時先將資料從記憶體複製到這一小塊臨時儲存區域中,運算時就在這一小快臨時儲存區域內進行。我們稱這一小塊臨時儲存區域為暫存器。
對於arm64系的CPU來說, 如果暫存器以x開頭則表明的是一個64位的暫存器,如果以w開頭則表明是一個32位的暫存器,在系統中沒有提供16位和8位的暫存器供訪問和使用。其中32位的暫存器是64位暫存器的低32位部分並不是獨立存在的。
快取記憶體
iPhoneX上搭載的ARM處理器A11它的1級快取的容量是64KB,2級快取的容量8M.
CPU每執行一條指令前都需要從記憶體中將指令讀取到CPU內並執行。而暫存器的執行速度相比記憶體讀寫要快很多,為了效能,CPU還整合了一個快取記憶體儲存區域.當程式在執行時,先將要執行的指令程式碼以及資料複製到快取記憶體中去(由作業系統完成).CPU直接從快取記憶體依次讀取指令來執行.
暫存器
內部部件之間由匯流排連線
- 對程式設計師來說,CPU中最主要部件是暫存器,可以通過改變暫存器的內容來實現對CPU的控制
- 不同的CPU,暫存器的個數、結構是不相同的
通用暫存器
-
ARM64擁有有31個64位的通用暫存器 x0 到 x30,這些暫存器通常用來存放一般性的資料,稱為通用暫存器(有時也有特定用途)
- 那麼w0 到 w28 這些是32位的. 因為64位CPU可以相容32位.所以可以只使用64位暫存器的低32位.
- 比如 w0 就是 x0的低32位!
- 通常,CPU會先將記憶體中的資料儲存到通用暫存器中,然後再對通用暫存器中的資料進行運算
-
假設記憶體中有塊紅色記憶體空間的值是3,現在想把它的值加1,並將結果儲存到藍色記憶體空間
- CPU首先會將紅色記憶體空間的值放到X0暫存器中:mov X0,紅色記憶體空間
- 然後讓X0暫存器與1相加:add X0,1
- 最後將值賦值給記憶體空間:mov 藍色記憶體空間,X0
pc暫存器(program counter)
-
為指令指標暫存器,它指示了CPU當前要讀取指令的地址
- 在記憶體或者磁碟上,指令和資料沒有任何區別,都是二進位制資訊
- CPU在工作的時候把有的資訊看做指令,有的資訊看做資料,為同樣的資訊賦予了不同的意義
- 比如 1110 0000 0000 0011 0000 1000 1010 1010
- 可以當做資料 0xE003008AA
- 也可以當做指令 mov x0, x8
- CPU根據什麼將記憶體中的資訊看做指令?
- CPU將pc指向的記憶體單元的內容看做指令
- 如果記憶體中的某段內容曾被CPU執行過,那麼它所在的記憶體單元必然被pc指向過
棧
-
棧:是一種具有特殊的訪問方式的儲存空間(後進先出, Last In Out Firt,LIFO)
SP和FP暫存器
- sp暫存器在任意時刻會儲存我們棧頂的地址.
- fp暫存器也稱為x29暫存器屬於通用暫存器,但是在某些時刻我們利用它儲存棧底的地址!()
注意:ARM64開始,取消32位的 LDM,STM,PUSH,POP指令! 取而代之的是ldr\ldp str\stp
ARM64裡面 對棧的操作是16位元組對齊的!!
狀態暫存器
CPU內部的暫存器中,有一種特殊的暫存器(對於不同的處理器,個數和結構都可能不同).這種暫存器在ARM中,被稱為狀態暫存器就是CPSR(current program status register)暫存器
CPSR和其他暫存器不一樣,其他暫存器是用來存放資料的,都是整個暫存器具有一個含義.而CPSR暫存器是按位起作用的,也就是說,它的每一位都有專門的含義,記錄特定的資訊.
注:CPSR暫存器是32位的
- CPSR的低8位(包括I、F、T和M[4:0])稱為控制位,程式無法修改,除非CPU執行於特權模式下,程式才能修改控制位!
- N、Z、C、V均為條件碼標誌位。它們的內容可被算術或邏輯運算的結果所改變,並且可以決定某條指令是否被執行!意義重大!
N(Negative)標誌
CPSR的第31位是 N,符號標誌位。它記錄相關指令執行後,其結果是否為負.如果為負 N = 1,如果是非負數 N = 0.
注意,在ARM64的指令集中,有的指令的執行時影響狀態暫存器的,比如add\sub\or等,他們大都是運算指令(進行邏輯或算數運算);
Z(Zero)標誌
CPSR的第30位是Z,0標誌位。它記錄相關指令執行後,其結果是否為0.如果結果為0.那麼Z = 1.如果結果不為0,那麼Z = 0.
對於Z的值,我們可以這樣來看,Z標記相關指令的計算結果是否為0,如果為0,則N要記錄下"是0"這樣的肯定資訊.在計算機中1表示邏輯真,表示肯定.所以當結果為0的時候Z = 1,表示"結果是0".如果結果不為0,則Z要記錄下"不是0"這樣的否定資訊.在計算機中0表示邏輯假,表示否定,所以當結果不為0的時候Z = 0,表示"結果不為0"。
C(Carry)標誌
CPSR的第29位是C,進位標誌位。一般情況下,進行無符號數的運算。
加法運算:當運算結果產生了進位時(無符號數溢位),C=1,否則C=0。
減法運算(包括CMP):當運算時產生了借位時(無符號數溢位),C=0,否則C=1。
對於位數為N的無符號數來說,其對應的二進位制資訊的最高位,即第N - 1位,就是它的最高有效位,而假想存在的第N位,就是相對於最高有效位的更高位。如下圖所示:
進位
我們知道,當兩個資料相加的時候,有可能產生從最高有效位向更高位的進位。比如兩個32位資料:0xaaaaaaaa + 0xaaaaaaaa,將產生進位。由於這個進位值在32位中無法儲存,我們就只是簡單的說這個進位值丟失了。其實CPU在運算的時候,並不丟棄這個進位制,而是記錄在一個特殊的暫存器的某一位上。ARM下就用C位來記錄這個進位值。比如,下面的指令
mov w0,#0xaaaaaaaa;0xa 的二進位制是 1010
adds w0,w0,w0; 執行後 相當於 1010 << 1 進位1(無符號溢位) 所以C標記 為 1
adds w0,w0,w0; 執行後 相當於 0101 << 1 進位0(無符號沒溢位) 所以C標記 為 0
adds w0,w0,w0; 重複上面操作
adds w0,w0,w0
借位
當兩個資料做減法的時候,有可能向更高位借位。再比如,兩個32位資料:0x00000000 - 0x000000ff,將產生借位,借位後,相當於計算0x100000000 - 0x000000ff。得到0xffffff01 這個值。由於借了一位,所以C位 用來標記借位。C = 0.比如下面指令:
"mov w0,#0x7fffffff\n" //暫存器 cpsr = 0x60000000 0110
"adds w0,w0,#0x2\n" //暫存器 cpsr = 0x90000000 1001
"mov w0,#0x80000000\n" //暫存器 cpsr =0x90000000 1001
"subs w0,w0,#0x2\n" //暫存器 cpsr = 0x30000000 0011
V(Overflow)溢位標誌
CPSR的第28位是V,溢位標誌位。在進行有符號數運算的時候,如果超過了機器所能標識的範圍,稱為溢位。
- 正數 + 正數 為負數 溢位
- 負數 + 負數 為正數 溢位
- 正數 + 負數 不可能溢位
關於記憶體讀寫指令
注意:讀/寫 資料是都是往高地址讀/寫
str(store register)指令
將資料從暫存器中讀出來,存到記憶體中.
ldr(load register)指令
將資料從記憶體中讀出來,存到暫存器中
此ldr 和 str 的變種ldp 和 stp 還可以操作2個暫存器.
堆疊操作練習
使用32個位元組空間作為這段程式的棧空間,然後利用棧將x0和x1的值進行交換.
sub sp, sp, #0x20 ;拉伸棧空間32個位元組
stp x0, x1, [sp, #0x10] ;sp往上加16個位元組,存放x0 和 x1
ldp x1, x0, [sp, #0x10] ;將sp偏移16個位元組的值取出來,放入x1 和 x0
bl和ret指令
bl標號
- 將下一條指令的地址放入lr(x30)暫存器
-
轉到標號處執行指令
ret
- 預設使用lr(x30)暫存器的值,通過底層指令提示CPU此處作為下條指令地址!
ARM64平臺的特色指令,它面向硬體做了優化處理的
x30暫存器
x30暫存器存放的是函式的返回地址.當ret指令執行時刻,會尋找x30暫存器儲存的地址值!
注意:在函式巢狀呼叫的時候.需要講x30入棧!
adrp
是計算指定的資料地址到當前PC值的相對偏移。
/*1.先將1的值左移12位二進位制位則為 1 0000 0000 0000 ==> 0x1000
*2.將 PC 暫存器的低12位清零,也就是0x100c1e6c4 ==> 0x100c1f000
*/
0x100c1e6c4 <+36>: adrp x0, 1
//0x100c1f000 + 0x65c ==> 0x100c1f65c也就是說這個常量所對應的值得地址是0x100c1f65c
0x100c1e6c8 <+40>: add x0, x0, #0x65c ; =0x65c
memory read X //簡寫memory read 簡寫x
0x100400e48: d9 55 2b a5 01 00 00 00 c1 eb 3f 00 01 00 00 00
0x100400e58: ac c7 a0 8c 01 00 00 00 f8 0e 40 00 01 00 00 00
//iOS是從右邊向左讀10位 0x 01 a5 2b 55 d9
p (char *)0x01a52b55d9 //實際是什麼型別,就強轉成什麼型別
bl指令
CPU從何處執行指令是由pc中的內容決定的,我們可以通過改變pc的內容來控制CPU執行目標指令
-
ARM64提供了一個mov指令(傳送指令),可以用來修改大部分暫存器的值,比如
- mov x0,#10、mov x1,#20
但是,mov指令不能用於設定pc的值,ARM64沒有提供這樣的功能
ARM64提供了另外的指令來修改PC的值,這些指令統稱為轉移指令,最簡單的是bl指令
bl指令 -- 練習
現在有兩段程式碼!假設程式先執行A,請寫出指令執行順序.最終暫存器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
相關文章
- iOS逆向學習筆記 - 彙編(一) - 初識彙編iOS筆記
- iOS逆向學習筆記 - 彙編(四) - 迴圈&選擇[cmp 比較指令]iOS筆記
- 彙編學習筆記之轉移指令筆記
- 學習筆記分享之彙編---2.彙編指令/語法筆記
- 逆向之彙編筆記筆記
- 彙編學習筆記筆記
- 彙編學習筆記07——BCD碼及調整指令筆記
- iOS彙編基礎(二)暫存器iOS
- 逆向與安全學習筆記筆記
- 彙編基礎學習筆記筆記
- 組合語言學習筆記03——暫存器(CPU工作原理)組合語言筆記
- 重新整理彙編—————暫存器的基本概念[二]
- Solidity語言學習筆記————38、Solidity彙編Solid筆記
- 除錯時檢視彙編和暫存器資料等除錯
- 8086 彙編學習 Part 3
- Solidity語言學習筆記————39、獨立彙編Solid筆記
- Git 的工作區、暫存區、版本庫—— Git 學習筆記 15Git筆記
- 【Redis學習筆記】2018-07-10 Redis指令學習3Redis筆記
- 【自用】彙編初學筆記 #1筆記
- Angularjs學習筆記指令AngularJS筆記
- Vue 學習筆記——指令Vue筆記
- 6.常見暫存器和指令
- 滴水逆向筆記系列 - 4.記憶體地址_堆疊-5.標誌暫存器-6.JCC命令筆記記憶體
- 彙編學習小記(三)-查表
- 3. 暫存器(記憶體) | 問題 3.7 - 3.10記憶體
- Python3學習筆記-字串和編碼Python筆記字串
- CS 暫存器 和 IP 暫存器
- 滴水逆向筆記系列-1.進位制-2.資料寬度_邏輯運算-3.通用暫存器_記憶體讀寫筆記記憶體
- deepin linux 學習筆記(二)——文字編輯器Linux筆記
- shell指令碼學習筆記-1指令碼筆記
- Linux學習筆記(2)——ls指令Linux筆記
- 吳恩達機器學習筆記(3)吳恩達機器學習筆記
- CPU中跟蹤後繼指令地址的暫存器
- spark學習筆記--資料讀取與儲存Spark筆記
- [PyTorch 學習筆記] 7.1 模型儲存與載入PyTorch筆記模型
- iOS彙編教程(六)CPU 指令重排與記憶體屏障iOS記憶體
- 暫存器
- 20.10.29【EndNote學習彙總筆記01】筆記