堆疊算是非常重要的結構了,今晚講講它是怎麼設計的,最後講幾個跟堆疊相關的彙編指令。
之前學過那些通用暫存器,讀取方便,而且快速,但是有乙個問題:就是暫存器有大小限制,資料量大的時候,暫存器就不夠用了。為了實現訪問大量的資料,並且能快速讀取資料,前人發明了堆疊的結構。
堆疊的結構是這樣的,分配一段連續的記憶體,定義兩個變數base(棧底)、
top(棧頂)。
base(棧底)裡面儲存乙個位址,記錄該連續記憶體(堆疊)的起始位址。
top(棧頂)裡面儲存乙個位址,記錄該連續記憶體(堆疊)的結束位址。
這兩個變數儲存棧底、棧頂的記憶體位址,這兩個變數的值(記憶體位址)分別儲存通用暫存器ebp和
esp中。
說那個多,來點實在的,看看od中的堆疊長什麼樣的吧。
可以看到堆疊就是一塊連續的記憶體,只不過這段連續的記憶體的開始位址儲存在ebp暫存器中,結束位址儲存在
esp中。這麼看,其實堆疊也沒想的那麼複雜。大家可能也注意到
od的堆疊中棧頂的位址的背景色是深黑色的。
向棧中放入乙個數(假設4個位元組)時,
top(棧頂)的值減
4。可以看下面的示意圖。
向棧中放入乙個數的過程,叫入棧
。在windows系統中,棧是向低位擴充套件的,所以入棧的時候位址是減去乙個數。
在od中執行了一條入棧的命令,可以看到這樣的結果。
從棧中取出乙個數(假設4個節字)時,
base
(棧底)的值加
4。可以看下面的示意圖。
從棧中取出乙個數的過程,叫出棧。
可以看到出棧時,只是把棧頂的位址改變,並沒有去刪除原來棧頂的值。
在od中執行一條出棧的命令,可以看到原來棧頂的值還是存在記憶體中的。
如果要讀取棧中間的某個值,可以通過棧頂或棧底加上乙個偏移量的方式去讀取。
可以看到用這種方式讀取記憶體的資料非常快,直接加偏移量就能讀取記憶體中的值。
入棧時,在od中可以發現,
esp中的值減了
4,棧頂上移,並且把值放入到棧頂中。我們可以用已經學過的指令實現這一過程。
mov dword ptr ds:[esp-4],0xa
sub esp,0x4
當然還有其他的方式實現。
其實彙編中還有乙個更好用的指令實現入棧的過程:push指令。
push指令
格式:push r32/r16/m16/m32/imm8/imm16/imm32
例子:push eax :把
eax暫存器中的值壓入棧中。
執行前棧的情況
執行後棧的變化情況
出棧時,也可以用已經學過的指令來實現。
mov eax, dword ptr ds:[esp]
add esp,0x4
當然彙編中也有一條命令實現出棧的過程:pop指令
pop指令
格式:pop r16/r32/m16/32注意pop後面不能是立即數,因為pop後面要有乙個容器接收從棧中取出的數。
例子:pop ecx :把棧頂的值取出放入到
ecx暫存器中。
執行前棧的情況
執行後棧的情況
這篇文章就寫這麼多吧,本來還想寫lea、
call
、ret
等指令的,留到下次吧。
寫於2020.6.12 22:55
Go語言第十八課 CGO
可借助cgo實現go語言對c的呼叫,下面展示幾種呼叫方式。c 內容如下 include include include char test hello const char name int main 執行結果 yuyong hello go 如下 package main include incl...
日本語 第十八課
第十八課 攜帯電話 小 手機便的很小了 音 大 電視的聲音便大了 息子 醫者 兒子成為了醫生 部屋 綺麗 請把屋子收拾乾淨 風邪 感冒怎麼樣了啊?昨夜 薬 飲 昨天吃藥了,但是還沒有好轉 旅行 荷物 軽 旅行箱還是輕點好.軽 是啊,盡可能的變輕了.嬢 你的女兒多大了?今年 七歳 今年,已經7歲了.啊...
孫鑫 第十八課ActiveX控制項
說明 activex控制項有三個要素 屬性,方法,事件 屬性比如button控制項的顯示文字,名字等。屬性值包括stock屬性和custom屬性,其中stock屬性為控制項固有屬性,即mfc封裝的屬性,例如前景色 背景色等。而custom屬性則為使用者自己定製的屬性,在新增custom屬性時要指定外...