前言:比起esp定址的方式,ebp需要去理解下其中的含義,所以記錄下!
個人理解:
1、ebp和esp之間的關係
起初-1 相隔 ----> 在沒進call之前,會先將呼叫call的引數先壓入堆疊,堆疊中ebp暫存器中的位址是在esp暫存器中的位址之下, 自己理解為相隔
中間-2 相等 ----> 進入call之後,ebp暫存器會先把儲存的位址先壓入堆疊中儲存,然後再儲存esp暫存器中的位址,這裡就可以理解為esp不變,將ebp進行提公升棧頂的操作
中間-3 相隔 ----> 因為呼叫了call,那麼就會進行一系列的運算,那麼肯定需要堆疊中的空間,那麼esp位址就會上公升
中間-4 相等 ----> 當呼叫完了之後,當前ebp暫存器儲存的就是之前的esp的位址,現在就會返回給esp暫存器,堆疊需要保持平衡
末尾-5 相隔 ----> 堆疊到現在還沒有完全保持平衡,還需要把ebp的位址返回給ebp暫存器,然後出了call之後,還需要指令進行外/內平衡的操作保持真正的堆疊平衡!
彙編體現:
00401000 > 6a 01 push 0x1 ; 壓入堆疊0x1
00401002 6a 02 push 0x2 ; 壓入堆疊0x2
00401004 e8 3c000000 call crackme.00401045 ; 呼叫call 00401045
00401009 83c4 08 add esp,0x8 ; 恢復兩個引數的堆疊數,所以+8
0040100c . 6a 00 push 0x0 ; /
0040100e . 68 f4204000 push crackme.004020f4 ; |
00401013 . e8 a6040000 call ; \
00401018 . 0bc0 or eax,eax
0040101a . 74 01 je short crackme.0040101d
0040101c . c3 retn
0040101d > c705 64204000>mov dword ptr ds:[0x402064],0x4003
00401027 . c705 68204000>mov dword ptr ds:[0x402068],crackme.wndp>; è
00401031 . c705 6c204000>mov dword ptr ds:[0x40206c],0x0
0040103b . c705 70204000>mov dword ptr ds:[0x402070],0x0
00401045 55 push ebp ; 儲存原始ebp位址
00401046 8bec mov ebp,esp ; 再讓當前ebp中儲存esp的位址
00401048 83ec 10 sub esp,0x10 ; 提公升棧頂,用於儲存其他要用到的東西,當前沒有體現用處
0040104b 8b45 08 mov eax,dword ptr ss:[ebp+0x8] ; crackme.0040104e 0345 0c add eax,dword ptr ss:[ebp+0xc]
00401051 8be5 mov esp,ebp ; 把之前儲存的ebp返回給esp
00401053 5d pop ebp ; 再把之前壓入的ebp位址返回給ebp暫存器
00401054 c3 retn ; 跳出
經典資料結構之間接定址
線性表主要有兩中表現方式,一種是連續儲存式,例如陣列,另一種是非連續儲存式,例如鍊錶。相比於鍊錶,陣列最大的好處就在於可以隨機訪問,鍊錶的最大優勢是,能夠有效利用儲存空間,合理的新增,刪除操作只需要o 1 於是誕生了間接定址,即是把陣列與鍊錶的優點結合起來。如下 ifndef indirectlis...
函式幀的esp與ebp操作
每乙個函式都有乙個函式幀 就是以ebp為基位址,esp為頂位址 而函式之間的呼叫會出現幀的切換,這時用到了兩個暫存器,esp與ebp,那麼它們的作用與關心是怎樣的呢 由兩句話可知 esp 棧 頂 指標,始終指向棧頂,當遇到push pop call ret等指令時它會改變,因此,程式設計師使用它來進...
orange s 中的定址
定址是我覺得入門時遇到的最難的最大的問題,因為這是有許多年輕人不知道的歷史典故的,必須有歷史的積澱 看orange s的時候,定址是最先的乙個坎,8086的歷史告訴我們,20位位址線 16位的暫存器 所產生的是無法直接定址的痛苦,這裡的直接是 單用乙個16位的暫存器來提交給cpu 因為畢竟還有4位的...