利用匯編詳解棧結構


前言

轉載請聲明作者!

對於二進制安全  棧結構是最基本要了解的東西

關於棧  這里用匯編語言來 “調戲” 棧 玩玩。

希望通過這篇文章能夠初步認識棧的原理及其工作機理

這里用三本書來形象概括

《窮,不搞黑產》、《富,不搞PC》、《黑客從入門到入獄》

當我們存數據的時候  先把《窮,不搞黑產》壓入棧

再把《富,不搞PC》、《黑客從入門到入獄》依次壓入

從上述圖中可以大概理解了棧的數據存儲和讀取的原理

就是先進的數據只能最后出來,而后進的數據卻是最先出來

棧的這個規則叫做:先進后出(Last In First Out)。

利用匯編代碼了解棧

從上述可以知道棧的存儲和取出原理

這里我再用匯編代碼深入講解

mov ax,1000
mov ss,ax
mov sp,0010
mov ax,15
mov bx,17
mov cx,8
push ax
push bx
push cx
pop ax
pop bx
pop cx

 

給出匯編代碼 ,下面我們將用到DeBug工具來調試分析

首先用-a命令寫入我們的匯編代碼

稍微講解下匯編指令

mov是傳值 例:mov ax,1000 就是把1000傳給ax寄存器中

push是壓棧 例:push ax將當前寄存器內的值壓入棧中

pop是出棧 例:pop ax將棧中的數據彈出賦值給ax寄存器

現在已經寫完了匯編代碼 那么我們就按t單步執行下去

並注意觀察每一步走完后寄存器內的值

調試:

mov ax,1000

這時候ax寄存器已經被賦值為1000了

mov ss,ax

將ax的值賦值給ss寄存器

關於SS:SP在后面會講

這里賦值我就不繼續了 直接走到push ax那

前面的mov賦值完后  相應的寄存器值都如下AX=0015 BX=0017 AX=0008

接着執行完push

可以看到0015 0017 0008已經依次壓入棧中了 

因為我們的寄存器里存儲的是16位的數值,例如AX分為AH和AL

其中AH是高8位  AH是低8位

比如AX寄存器里的值存儲着0123H

那么AH=01H AL=23H

然后在內存中  又是以一個字單元寫入的  

簡單的說 要占用兩個單元空間 這樣的單元被稱為一個字單元

所以 高8位被存放在下面 而低位被存放在上面

所以push ax(ax的值這時候等於0015)

然后棧頂指針依次-2

最后變成這樣

再出棧 

由於這里出棧是

pop ax

pop bx

pop cx

所以最先吧0008的彈出給了ax

0017給bx  0015給了cx

debug中跟蹤查看

此時AX、BX、CX寄存器中的值就與之前相反了~~

后續:

棧在哪里?

知己知彼,方能百戰不殆。

那么,現在已經知道棧的存儲和讀取原理了,可是,棧  在哪呢???

也許大部分人都聽到過寄存器、內存

可是、、、棧???

其實棧就是內存中分配的一段空間

這段空間我們可以用來當棧使用

如下圖就是在內存10000H~1000FH處分配了16個單元的棧空間

但由於是在內存中,系統不會認為他是棧。(並不會把他當做棧使用)

這時候就需要用到我們的寄存器SS:SP了

當寄存器SS:SP所指向的地址就會被當做棧使用

SS:SP尋址原理

SS:SP要尋到我們在內存空間里定義的一塊棧空間

問題是  怎么尋址的呢?

8086CPU中提供兩個16位的地址,一個稱為段地址,用來指向一個段空間(最大空間為64KB)

另一個就是偏移地址了  

所以物理地址=段地址x16+偏移地址 (相關問題請留言評論)

通常我們用1000:0001來表示段地址和偏移地址

其中1000是段地址

:是分割符

0001是偏移地址

 

也許很多人對這個段地址x16怎么算不知道

其實乘16就相當於左移一位

最后找到1000:0001的位置為

然后在內存地址中指向了10001H處 

SS:SP是棧頂指針

因為內存中的高位在下面

所以

每次push sp-2

每次pop sp+2

 未完待續~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM