汇编语言之寄存器(内存访问)
1、內存中字的存儲
2、ds和【address】
CPU要讀寫一個內存單元的時候,必須先給出這個內存單元的地址,在8086CPU中,內存地址由段地址和偏移地址組成,
其中,段地址存放在段寄存器DS中,DS稱作數據段寄存器。
如果我們要將內存地址為14A70的內存單元中的數據送入AL中,可以用如下的程序段進行:
Mov bx,1000H??? ;把段地址1000H送入bx中。
mov ds,bx??????? ;把bx中的數值送入ds中。
Mov al,[4a70]???? ;把段地址為1000H,偏移地址位4a70H的內存單元中的數據送入al中。
[address]表示一個內存單元,內存單元中的address表示偏移地址,它的中文翻譯就是地址的意思。
內存單元[address],我們可以知道它的地址是多少,但它的數值是多少,我們并不知道。
3、mov指令
傳送指令mov可以完成以下4種傳送:
1:將數據直接送入寄存器。??? 如:mov ax,1230H。
2:將一個寄存器中的數據送入另一個寄存器。??? 如:mov ax,bx
3:將一個內存單元中的數據送入一個寄存器。??? 如:mov ax,[27b0]
4:將一個寄存器中的數據送入內存單元中。??? 如:mov [607c],bx
注意:不能直接用數據送給段寄存器,如:mov ds,1230H 是錯誤的,必須要用一個寄存器來進行中轉。比如:
Mov bx,1230H
Mov ds,bx
這樣就行了。為什么8086CPU不支持將數據直接送入段寄存器呢?這屬于8086CPU硬件設計的問題,我們只要知道這一
點就行了。
4、add和sub指令
Mov指令有兩個操作對象,add和sub同樣有兩個操作對象。
Add為加法指令,格式:add 操作對象1,操作對象2。功能:兩數相加,并把結果保存到操作對象1中。
Add有以下幾種形式:
Add 寄存器,數據??? 如:add ax, 8
Add 寄存器,寄存器??? 如:add ax, bx
Add 寄存器,內存單元??? 如:add ax, [27a0]
Add 內存單元,寄存器??? 如:add [46e9], bx
?
Sub為減法指令,格式:sub 操作對象1,操作對象2。功能:兩數相減,即從操作對象1減去操作對象2,其結果保存到
操作對象1中。
Sub 也有以下幾種形式:
Sub 寄存器,數據??? 如:sub ax, 9
Sub 寄存器,寄存器??? 如:sub ax, bx
Sub 寄存器,內存單元??? 如:sub ax, [b027]
Sub 內存單元,寄存器??? 如:sub [8601], bx
5、數據段
前面講過(參見2.7節),對于8086PC機,在編程時,可以根據需要,將一組內存單元定義為一個段。我們可以將一組長度
為N(N≤64KB)、地址連續、起始地址為16的倍數的內存單元當作專門存儲數據的內存空間,從而定義了一個數據段。
比如:用123B0H~123B9H這段內存空間來存放數據,我們就可以認為123B0H~123B9H這段內存是一個數據段,長度
為10個字節。
如何訪問數據段中的數據呢?首先用DS存放數據段的段地址,然后用相關的指令訪問數據段中的內存單元。
比如,將123B0H~123B9H的內存單元定義為數據段,現在要累加這個數據段中的前3個單元中的數據,代碼如下:
Mov ax, 123BH
Mov ds, ax??? ;將123BH送入ds中,作為數據段的段地址。
Mov al, 0????? ;用al存放累加結果,先把al中的數據清零。
Add al, [0]???? ;將數據段第一個單元(偏移地址為0)中的數值加到al中。
Add al, [1]???? ;將數據段第二個單元(偏移地址為1)中的數據加到al中。
Add al, [2]???? ;將數據段第三個單元(偏移地址為2)中的數據加到al中。
?
在1.5節中,我們說過,在內存中指令和數據沒有任何區別,都是二進制信息,CPU在工作的時候,把有的信息看作指令,
把有的信息看作數據,那么CPU在什么時候把它看作指令?在什么時候把它看作數據呢?在2.5節中我們回答了第一個問題,現
在可以回答第二個問題了。
答:只要把這一段內存單元的段地址放到DS中,在用mov、add、sub等訪問內存單元的指令時,CPU就會將這些內存單
元看作數據來訪問。
6、棧
棧是一種具有特殊的訪問方式的存儲空間,它的特殊性就在于:最后進入這個空間的數據最先出去。可以用一個盒子和3本書
來描述棧的這種操作方式。
入棧:把A放入棧中,再把B放入棧中,然后再把C放入棧中。就形成了A、B、C
出棧:先出棧頂C,然后是B,然后A,
特點:先進后出
入棧和出棧。入棧就是將一個新的元素放到棧頂,出棧就是從棧
頂取出一個元素。棧頂的元素總是最后入棧,需要出棧時又最先被從棧中取出,棧的這種操作規則被稱為LIFO(last in first out,
后進先出)
?
7、cpu提供的棧機制?
現今的CPU中都有棧的設計。8086CPU提供的入棧和出棧指令,最基本的兩個是push(入棧)和pop(出棧)。比如:
Push ax 表示將寄存器ax中的數據送入棧中,pop ax 表示從棧頂取出數據送入ax。8086CPU的入棧和出棧操作都是以字為
單位進行的。
下面兩張圖描述了push和pop指令的執行過程。
上面兩張圖指令的執行過程,寫成代碼如下:
Mov ax, 123H
Push ax
Mov bx, 2266H
Push bx
Mov cx, 1122H
Push cx
Pop ax
Pop bx
Pop cx
注意:字型數據用兩個內存單元存放,高地址單元存放高8位,低地址單元存放低8位。
看了上面兩張圖后,現在提出兩個問題。問題1:我們將10000H~1000FH這段內存當作棧來使用,CPU是如何知道這段空
間是棧?關于這個問題將在3.10節解答。
問題2:push ax等入棧指令執行時,要將寄存器中的數據放入當前棧頂單元的上方,成為新的棧頂元素;pop ax等指令執
行時,要從棧頂單元取出數據送入寄存器中。顯然,push、pop在執行的時候,CPU必須要知道哪個單元是棧頂單元,可是,如
何知道?
答:8086CPU中,有兩個寄存器,堆棧段寄存器SS,堆棧指針寄存器SP,棧頂的段地址存放在SS中,偏移地址存放在
SP中,任意時刻,SS:SP指向棧頂元素,push和pop指令在執行時,CPU從SS和SP中得到棧頂單元的地址。
現在,我們可以完整地描述push和pop指令的功能了,例如:push ax。push ax的執行,由以下兩步完成:
1. SP=SP-2,SS:SP指向當前棧頂前面的單元,以當前棧頂前面的單元為新的棧頂。
2. 將ax中的數據送入SS:SP指向的內存單元處,SS:SP此時指向新棧頂。
下圖描述了push ax的執行過程。
將10000H~1000FH這段空間當作棧段,SS=1000H,棧空間大小為16字節,棧最底部的字單元地址為1000:000E,任
意時刻,SS:SP指向棧頂,當棧中只有一個元素的時候,SS=1000H,SP=000EH,棧為空,就相當于棧中唯一的元素出棧后,
SP=SP+2,原來為000EH,加2后SP=0010H,所以,當棧為空的時候,SS=1000H,SP=0010H。
換一個角度看,任意時刻,SS:SP指向棧頂元素,當棧為空的時候棧中沒有元素,也就不存在棧頂元素,所以SS:SP只能指
向棧的最底部單元下面的單元,該單元的偏移地址為棧最底部的字單元的偏移地址+2,棧最底部字單元的地址為1000:000E,
所以,棧空時,SP=0010H。
接下來,我們描述pop指令的功能,例如:pop ax。Pop ax的執行過程和push ax剛好相反,由以下兩步完成:
1. 將SS:SP指向的內存單元處的數據送入ax中。
2. SP=SP+2,SS:SP指向當前棧頂下面的單元,以當前棧頂下面的單元為新的棧頂。
下圖描述了pop ax的執行過程。
注意:上圖中,出棧后,SS:SP指向新的棧頂1000EH,pop操作前的棧頂元素,1000CH處的數據2266H依然存在,但
是,它已不在棧中,當再次執行push等入棧指令后,SS:SP移至1000CH,并在里面寫入新的數據,將它覆蓋。
8、push指令 pop指令
Push和pop指令的格式有如下兩種形式:
第一種形式:push 寄存器??? ;將一個寄存器中的數據入棧。
??????????? Pop 寄存器??? ;出棧,用一個寄存器接收出棧的數據。
這一種形式,它們可以在棧和寄存器之間傳送數據。
注意:上面的寄存器可以是段寄存器,比如,可以是:push ds、pop ds。
第二種形式:push 內存單元??? ;將一個內存單元中的字型數據入棧(注意,棧操作都是以字為單位)。
??????????? Pop 內存單元??? ;出棧,用一個內存字單元接收出棧的數據。
比如:mov ax, 1000H
????? Mov ds, ax??? ;將內存單元的段地址放在DS中。
????? Push [2a38]??? ;將內存單元[2a38]中的字型數據入棧。
????? Pop [2a3a]??? ;出棧,出棧的數據送入內存單元[2a3a]。
這一種形式,它們可以在棧和內存單元之間傳送數據。
指令執行時,CPU要知道內存單元的地址,可以在push、pop指令中給出內存單元的偏移地址,段地址在指令執行時,CPU
從DS中取得。
Push和pop實質上是一種內存傳送指令,與mov指令不同的是,push和pop指令訪問的棧空間的地址不是在指令中給出
的,而是由SS:SP指出的。同時,push和pop指令還要改變SP中數值。Mov指令只需一步操作,就是傳送,而執行push、
Pop指令需要兩步操作,執行push時,先改變SP,后向SS:SP處傳送;執行pop時,先讀取SS:SP處的數據,后改變SP。
9 、 棧段
前面講過(參見2.7節),對于8086PC機,在編程時,可以根據需要,將一組內存單元定義為一個段。我們可以將長度為N
(N≤64KB)的一組地址連續、起始地址為16的倍數的內存單元,當作棧空間來用,從而定義了一個棧段。
比如,我們將10010H~1001FH這段內存空間當作棧來用,以棧的方式進行訪問,這段空間就可以認為是一個棧段,大小為
16個字節。
如何使得如push、pop等棧操作指令訪問我們定義的棧段呢?那就是要將SS:SP指向我們定義的棧段。
現在我們來回答3.8節中的第一個問題。答:只要這段內存單元被SS:SP指向,那么,CPU就會把這段空間當作棧來使用。
總結
以上是生活随笔為你收集整理的汇编语言之寄存器(内存访问)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 汇编语言之寄存器(CPU工作原理)
- 下一篇: 汇编语言之数据处理的2个基本问题