一、棧的基本概念棧有兩個(gè)基本的操作:入棧和出棧。 8086CPU提供的棧機(jī)制8086CPU提供入棧和出棧指令: (最基本的) push和pop指令也可以在內(nèi)存和寄存器傳輸數(shù)據(jù)(以棧的形式) 示例:
那么問題來了,在執(zhí)行push和pop的時(shí)候,如何知道哪個(gè)單元是棧頂單元? 8086CPU中,有兩個(gè)寄存器:
任意時(shí)刻,SS:SP指向棧頂元素。 二、push和pop指令push 指令的執(zhí)行過程在執(zhí)行push ax指令時(shí),主要做了一下2件事
pop 指令的執(zhí)行過程在執(zhí)行pop ax指令時(shí),主要做了一下2件事
當(dāng)棧為空的時(shí)候,SS:SP指向最高地址空間的下一位
任意時(shí)刻,SS:SP 指向棧頂元素,當(dāng)棧為空的時(shí)候,棧中沒有元素,也就不存在棧頂元素,所以SS:SP 只能指向棧的最底部單元下面的單元,該單元的偏移地址為棧最底部的字單元的偏移地址+2,棧最底部字單元的地址為1000:000E,所以??諘r(shí),SP=0010H。 棧頂超界的問題(簡(jiǎn)單了解就好,我們又不做黑客)原因:SS和SP只記錄了棧頂?shù)牡刂罚?strong>依靠SS和SP可以保證在入棧和出棧時(shí)找到棧頂。 上面我說了,CPU并不知道這段是代碼段,數(shù)據(jù)段還是棧段,都是人為設(shè)定的所以加入這個(gè)??樟?,我們繼續(xù)pop,它就會(huì)把其它段的數(shù)據(jù)pop出。所以非常危險(xiǎn) 解決辦法:一個(gè)很NC的辦法,就是我們?cè)诰幊痰臅r(shí)候要自己操心棧頂超界的問題 ,要根據(jù)可能用到的最大??臻g,來安排棧的大小,防止入棧的數(shù)據(jù)太多而導(dǎo)致的超界;執(zhí)行出棧操作的時(shí)候也要注意,以防??盏臅r(shí)候繼續(xù)出棧而導(dǎo)致的超界。 push和pop指令具體可以操作
示例: 1、將10000H~1000FH 這段空間當(dāng)作棧,初始狀態(tài)是空的,將 AX、BX、DS中的數(shù)據(jù)入棧。
2、編程 (1)將10000H~1000FH 這段空間當(dāng)作棧,初始狀態(tài)是空的;
3、編程: (1)將10000H~1000FH 這段空間當(dāng)作棧,初始狀態(tài)是空的; 4、補(bǔ)全下面的代碼,完成同樣的功能:在10000H處寫入字型數(shù)據(jù)2266H。 __________
棧段上面說過我們可以定義一段內(nèi)存單元為代碼段,數(shù)據(jù)段或棧段。 我們可以將一個(gè)段空間當(dāng)做一個(gè)棧段,一個(gè)棧段最大64K,因?yàn)?6位CPU的偏移地址最大為2^16B,如果超出FFFF它會(huì)重新變成0(FFFF+1=0000,1被拋棄了)。 CPU是如何判斷哪塊是什么段的? 我們可以將一段內(nèi)存定義為一個(gè)段,用一個(gè)段地址指示段,用偏移地址訪問段內(nèi)的單元。這完全是我們自己的安排。 對(duì)于代碼段,將它的段地址放在 CS中,將段中第一條指令的偏移地址放在IP中,這樣CPU就將執(zhí)行我們定義的代碼段中的指令; 對(duì)于棧段,將它的段地址放在SS中,將棧頂單元的偏移地置放在 SP 中,這樣CPU在需要進(jìn)行棧操作的時(shí)候,比如執(zhí)行 push、pop 指令等,就將我們定義的棧段當(dāng)作??臻g來用。 可見,不管我們?nèi)绾伟才?,CPU 將內(nèi)存中的某段內(nèi)存當(dāng)作代碼 ,是因?yàn)镃S:IP指向了那里;CPU將某段內(nèi)存當(dāng)作棧 ,是因?yàn)?SS:IP 指向了那里。
|
|
|