一步步学习汇编系列(7)
從訪問內(nèi)存的角度繼續(xù)學(xué)習(xí)幾個寄存器<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
首先理解幾個要點:
1.內(nèi)存中字的存儲
n??????? 在0地址處開始存放20000:
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace prefix = w ns = "urn:schemas-microsoft-com:office:word" />
?
n??????? 0號單元是低地址單元,1號單元是高地址單元。
備注:任何兩個地址連續(xù)的內(nèi)存單元,N號單元和 N+1號單元,可以將它們看成兩個內(nèi)存單元 ,也可以看成一個地址為N的字單元中的高位字節(jié)單元和低位字節(jié)單元。
?
2. DS和[address]
n??????? CPU要讀取一個內(nèi)存單元的時候,必須先給出這個內(nèi)存單元的地址;
n??????? 在8086PC中,內(nèi)存地址由段地址和偏移地址組成。
n??????? 8086CPU中有一個 DS寄存器,通常用來存放要訪問的數(shù)據(jù)的段地址。
n??????? ???例如:我們要讀取10000H單元的內(nèi)容可以用如下程序段進(jìn)行:
????????? mov bx,1000H
????????? mov ds,bx
????????? mov al,[0]
n??????? 上面三條指令將10000H(1000:0)中的數(shù)據(jù)讀到al中。
mov指令的格式:
????? mov 寄存器名,內(nèi)存單元地址
“[…]”表示一個內(nèi)存單元, “[…]”中的0表示內(nèi)存單元的偏移地址。
那么內(nèi)存單元的段地址是多少呢?就是上面的ds
?
備注:8086CPU不支持將數(shù)據(jù)直接送入段寄存器的操作,ds是一個段寄存器。
?(硬件設(shè)計的問題)
mov ds,1000H 是非法的。
數(shù)據(jù)-一般的寄存器-段寄存器
?
明白了以上原理,我們具體來看看字的傳送
3.字的傳送
因為8086CPU是16位結(jié)構(gòu),有16根數(shù)據(jù)線,所以,可以一次性傳送16位的數(shù)據(jù),也就是一次性傳送一個字。
看下面的圖清晰的描述了這個過程:
?
內(nèi)存中的情況如右圖,寫出下面指令執(zhí)行后寄存器ax,bx,cx中的值。
分析后就可以知道
Ax=1000h
Ds=1000h
Ax=1123h
Bx=6622h
Cx=2211h
Bx=6622h+2211h=8833hh
Cx=8833hh
?
現(xiàn)在您可以練習(xí)一下,看圖寫出每行運(yùn)行后寄存器的結(jié)果,如下:
參考答案提供上來:
?
通過上面的分析,實際上我們已經(jīng)接觸到了以下幾種指令:
mov 寄存器,數(shù)據(jù)
? mov 寄存器,寄存器
? mov 寄存器,內(nèi)存單元
? mov 內(nèi)存單元,寄存器
? mov 段寄存器,寄存器
?? mov 內(nèi)存單元,段寄存器
? ?mov 段寄存器,內(nèi)存單元
?
add和sub指令同mov一樣,都有兩個操作對象。
?
4. 數(shù)據(jù)段
前面講過,對于8086PC機(jī),我們可以根據(jù)需要將一組內(nèi)存單元定義為一個段。
我們可以將一組長度為N(N≤64K)、地址連續(xù)、起始地址為16的倍數(shù)的內(nèi)存單元當(dāng)作專門存儲數(shù)據(jù)的內(nèi)存空間,從而定義了一個數(shù)據(jù)段。
比如我們用123B0H~123B9H這段空間來存放數(shù)據(jù):
段地址:123BH
長度:10字節(jié)
?? 如何訪問數(shù)據(jù)段中的數(shù)據(jù)呢?
將一段內(nèi)存當(dāng)作數(shù)據(jù)段,是我們在編程時的一種安排,我們可以在具體操作的時候 ,用 ds 存放數(shù)據(jù)段的段地址,再根據(jù)需要,用相關(guān)指令訪問數(shù)據(jù)段中的具體單元。
?
例子:
我們將123B0H~123BAH的內(nèi)存單元定義為數(shù)據(jù)段,我們現(xiàn)在要累加這個數(shù)據(jù)段中的前3個單元中的數(shù)據(jù),代碼如下:
5.棧的操作(先進(jìn)后出)
push 指令的執(zhí)行過程
先來看入棧的操作,用圖來分析:
?
解釋如下:
n??????? 我們將10000H~1000FH 這段空間當(dāng)作棧段,SS=1000H,棧空間大小為16 字節(jié) ,棧最底部的字單元地址為1000:000E。
???? 任意時刻,SS:SP指向棧頂,當(dāng)棧中只有一個元素的時候,SS = 1000H,SP=000EH。
n??????? 棧為空,就相當(dāng)于棧中唯一的元素出棧,出棧后,SP=SP+2 ,SP 原來為 000EH,加 2 后SP=10H,所以,當(dāng)棧為空的時候,SS=1000H,SP=10H。
?
再來看看出棧的操作:
解釋如下:
n??????? 出棧后,SS:SP指向新的棧頂 1000EH,pop操作前的棧頂元素,1000CH 處的2266H 依然存在 ,但是,它已不在棧中。
n??????? 當(dāng)再次執(zhí)行push等入棧指令后,SS:SP移至1000CH,并在里面寫入新的數(shù)據(jù),它將被覆蓋。
?
SS和SP只記錄了棧頂?shù)牡刂?#xff0c;依靠SS和SP可以保證在入棧和出棧時找到棧頂。
?
可是,如何能夠保證在入棧、出棧時,棧頂不會超出棧空間。
棧頂超界的問題
看下面的圖:
下面來解釋一下:
n??????? 8086CPU不保證對棧的操作不會超界。
?? 這就是說, 8086CPU 只知道棧頂在何處(由SS:SP指示),而不知道讀者安排的棧空間有多大。這點就好像 ,CPU 只知道當(dāng)前要執(zhí)行的指令在何處(由CS:SP指示)而不知道讀者要執(zhí)行的指令有多少。
?? 我們在編程的時候要自己操心棧頂超界的問題 ,要根據(jù)可能用到的最大棧空間,來安排棧的大小,防止入棧的數(shù)據(jù)太多而導(dǎo)致的超界;執(zhí)行出棧操作的時候也要注意,以防棧空的時候繼續(xù)出棧而導(dǎo)致的超界。
看下面棧頂超出棧空間的情況:
?
解釋如下:
? 1/當(dāng)棧空時,此時ss=1000h,sp=0020h;
當(dāng)執(zhí)行了八次壓棧后,棧滿了,此時ss=1000h,sp=0010h;
如果再執(zhí)行一次,那么此時ss=1000h,sp=sp-2=000e,這樣就把其它內(nèi)存地址給復(fù)蓋了,這對程序來講是致命 的。
?
出棧的原理和入棧原理類似,在此就不用圖描述了。讀者可自己去體會。
總結(jié)如下:
?
n??????? 我們可以將一段內(nèi)存定義為一個段,用一個段地址指示段,用偏移地址訪問段內(nèi)的單元。這完全是我們自己的安排。
n??????? 我們可以用一個段存放數(shù)據(jù),將它定義為“數(shù)據(jù)段”;
n??????? 我們可以用一個段存放代碼,將它定義為“代碼段”;
n??????? 我們可以用一個段當(dāng)作棧,將它定義為“棧段”;
?
n??????? 我們可以這樣安排,但若要讓CPU按照我們的安排來訪問這些段,就要:
n??????? 對于數(shù)據(jù)段,將它的段地址放在 DS中,用mov、add、sub等訪問內(nèi)存單元的指令時,CPU就將我們定義的數(shù)據(jù)段中的內(nèi)容當(dāng)作數(shù)據(jù)段來訪問;
n??????? 對于代碼段,將它的段地址放在 CS中,將段中第一條指令的偏移地址放在IP中,這樣CPU就將執(zhí)行我們定義的代碼段中的指令;
n??????? 對于棧段,將它的段地址放在SS中,將棧頂單元的偏移地置放在 SP 中,這樣CPU在需要進(jìn)行棧操作的時候,比如執(zhí)行 push、pop 指令等,就將我們定義的棧段當(dāng)作棧空間來用
?????
可見,不管我們?nèi)绾伟才?/span> ,CPU 將內(nèi)存中的某段內(nèi)存當(dāng)作代碼 ,是因為CS:IP指向了那里;CPU將某段內(nèi)存當(dāng)作棧 ,是因為 SS:IP 指向了那里。
?
?
?
?
?
?
?
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/mfm11111/archive/2009/03/26/1422648.html
總結(jié)
以上是生活随笔為你收集整理的一步步学习汇编系列(7)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 创建RGB、CMYK颜色分量圆代码
- 下一篇: 删除临时表并且插入数据