匯編語言之寄存器(內(nèi)存訪問)

1、內(nèi)存中字的存儲(chǔ)

2、ds和【address】

CPU要讀寫一個(gè)內(nèi)存單元的時(shí)候,必須先給出這個(gè)內(nèi)存單元的地址,在8086CPU中,內(nèi)存地址由段地址和偏移地址組成,

其中,段地址存放在段寄存器DS中,DS稱作數(shù)據(jù)段寄存器。

如果我們要將內(nèi)存地址為14A70的內(nèi)存單元中的數(shù)據(jù)送入AL中,可以用如下的程序段進(jìn)行:

Mov bx,1000H    ;把段地址1000H送入bx中。

mov ds,bx        ;把bx中的數(shù)值送入ds中。

Mov al,[4a70]     ;把段地址為1000H,偏移地址位4a70H的內(nèi)存單元中的數(shù)據(jù)送入al中。

[address]表示一個(gè)內(nèi)存單元,內(nèi)存單元中的address表示偏移地址,它的中文翻譯就是地址的意思。

內(nèi)存單元[address],我們可以知道它的地址是多少,但它的數(shù)值是多少,我們并不知道。
3、mov指令

傳送指令mov可以完成以下4種傳送:

1:將數(shù)據(jù)直接送入寄存器。    如:mov ax,1230H。

2:將一個(gè)寄存器中的數(shù)據(jù)送入另一個(gè)寄存器。    如:mov ax,bx

3:將一個(gè)內(nèi)存單元中的數(shù)據(jù)送入一個(gè)寄存器。    如:mov ax,[27b0]

4:將一個(gè)寄存器中的數(shù)據(jù)送入內(nèi)存單元中。    如:mov [607c],bx

注意:不能直接用數(shù)據(jù)送給段寄存器,如:mov ds,1230H 是錯(cuò)誤的,必須要用一個(gè)寄存器來進(jìn)行中轉(zhuǎn)。比如:

Mov bx,1230H

Mov ds,bx

這樣就行了。為什么8086CPU不支持將數(shù)據(jù)直接送入段寄存器呢?這屬于8086CPU硬件設(shè)計(jì)的問題,我們只要知道這一

點(diǎn)就行了。
4、add和sub指令

Mov指令有兩個(gè)操作對(duì)象,add和sub同樣有兩個(gè)操作對(duì)象。

Add為加法指令,格式:add 操作對(duì)象1,操作對(duì)象2。功能:兩數(shù)相加,并把結(jié)果保存到操作對(duì)象1中。

Add有以下幾種形式:

Add 寄存器,數(shù)據(jù)    如:add ax, 8

Add 寄存器,寄存器    如:add ax, bx

Add 寄存器,內(nèi)存單元    如:add ax, [27a0]

Add 內(nèi)存單元,寄存器    如:add [46e9], bx

 

Sub為減法指令,格式:sub 操作對(duì)象1,操作對(duì)象2。功能:兩數(shù)相減,即從操作對(duì)象1減去操作對(duì)象2,其結(jié)果保存到

操作對(duì)象1中。

Sub 也有以下幾種形式:

Sub 寄存器,數(shù)據(jù)    如:sub ax, 9

Sub 寄存器,寄存器    如:sub ax, bx

Sub 寄存器,內(nèi)存單元    如:sub ax, [b027]

Sub 內(nèi)存單元,寄存器    如:sub [8601], bx
5、數(shù)據(jù)段

前面講過(參見2.7節(jié)),對(duì)于8086PC機(jī),在編程時(shí),可以根據(jù)需要,將一組內(nèi)存單元定義為一個(gè)段。我們可以將一組長(zhǎng)度

為N(N≤64KB)、地址連續(xù)、起始地址為16的倍數(shù)的內(nèi)存單元當(dāng)作專門存儲(chǔ)數(shù)據(jù)的內(nèi)存空間,從而定義了一個(gè)數(shù)據(jù)段。

比如:用123B0H~123B9H這段內(nèi)存空間來存放數(shù)據(jù),我們就可以認(rèn)為123B0H~123B9H這段內(nèi)存是一個(gè)數(shù)據(jù)段,長(zhǎng)度

為10個(gè)字節(jié)。

如何訪問數(shù)據(jù)段中的數(shù)據(jù)呢?首先用DS存放數(shù)據(jù)段的段地址,然后用相關(guān)的指令訪問數(shù)據(jù)段中的內(nèi)存單元。

比如,將123B0H~123B9H的內(nèi)存單元定義為數(shù)據(jù)段,現(xiàn)在要累加這個(gè)數(shù)據(jù)段中的前3個(gè)單元中的數(shù)據(jù),代碼如下:

Mov ax, 123BH

Mov ds, ax    ;將123BH送入ds中,作為數(shù)據(jù)段的段地址。

Mov al, 0      ;用al存放累加結(jié)果,先把a(bǔ)l中的數(shù)據(jù)清零。

Add al, [0]     ;將數(shù)據(jù)段第一個(gè)單元(偏移地址為0)中的數(shù)值加到al中。

Add al, [1]     ;將數(shù)據(jù)段第二個(gè)單元(偏移地址為1)中的數(shù)據(jù)加到al中。

Add al, [2]     ;將數(shù)據(jù)段第三個(gè)單元(偏移地址為2)中的數(shù)據(jù)加到al中。

 

在1.5節(jié)中,我們說過,在內(nèi)存中指令和數(shù)據(jù)沒有任何區(qū)別,都是二進(jìn)制信息,CPU在工作的時(shí)候,把有的信息看作指令,

把有的信息看作數(shù)據(jù),那么CPU在什么時(shí)候把它看作指令?在什么時(shí)候把它看作數(shù)據(jù)呢?在2.5節(jié)中我們回答了第一個(gè)問題,現(xiàn)

在可以回答第二個(gè)問題了。

答:只要把這一段內(nèi)存單元的段地址放到DS中,在用mov、add、sub等訪問內(nèi)存單元的指令時(shí),CPU就會(huì)將這些內(nèi)存單

元看作數(shù)據(jù)來訪問。
6、棧

棧是一種具有特殊的訪問方式的存儲(chǔ)空間,它的特殊性就在于:最后進(jìn)入這個(gè)空間的數(shù)據(jù)最先出去??梢杂靡粋€(gè)盒子和3本書

來描述棧的這種操作方式。

入棧:把A放入棧中,再把B放入棧中,然后再把C放入棧中。就形成了A、B、C

出棧:先出棧頂C,然后是B,然后A,

特點(diǎn):先進(jìn)后出

入棧和出棧。入棧就是將一個(gè)新的元素放到棧頂,出棧就是從棧

頂取出一個(gè)元素。棧頂?shù)脑乜偸亲詈笕霔?,需要出棧時(shí)又最先被從棧中取出,棧的這種操作規(guī)則被稱為L(zhǎng)IFO(last in first out,

后進(jìn)先出)

 
7、cpu提供的棧機(jī)制

現(xiàn)今的CPU中都有棧的設(shè)計(jì)。8086CPU提供的入棧和出棧指令,最基本的兩個(gè)是push(入棧)和pop(出棧)。比如:

Push ax 表示將寄存器ax中的數(shù)據(jù)送入棧中,pop ax 表示從棧頂取出數(shù)據(jù)送入ax。8086CPU的入棧和出棧操作都是以字為

單位進(jìn)行的。

下面兩張圖描述了push和pop指令的執(zhí)行過程。

上面兩張圖指令的執(zhí)行過程,寫成代碼如下:

Mov ax, 123H

Push ax

Mov bx, 2266H

Push bx

Mov cx, 1122H

Push cx

Pop ax

Pop bx

Pop cx

注意:字型數(shù)據(jù)用兩個(gè)內(nèi)存單元存放,高地址單元存放高8位,低地址單元存放低8位。

看了上面兩張圖后,現(xiàn)在提出兩個(gè)問題。問題1:我們將10000H~1000FH這段內(nèi)存當(dāng)作棧來使用,CPU是如何知道這段空

間是棧?關(guān)于這個(gè)問題將在3.10節(jié)解答。

問題2:push ax等入棧指令執(zhí)行時(shí),要將寄存器中的數(shù)據(jù)放入當(dāng)前棧頂單元的上方,成為新的棧頂元素;pop ax等指令執(zhí)

行時(shí),要從棧頂單元取出數(shù)據(jù)送入寄存器中。顯然,push、pop在執(zhí)行的時(shí)候,CPU必須要知道哪個(gè)單元是棧頂單元,可是,如

何知道?

答:8086CPU中,有兩個(gè)寄存器,堆棧段寄存器SS,堆棧指針寄存器SP,棧頂?shù)亩蔚刂反娣旁赟S中,偏移地址存放在

SP中,任意時(shí)刻,SS:SP指向棧頂元素,push和pop指令在執(zhí)行時(shí),CPU從SS和SP中得到棧頂單元的地址。

現(xiàn)在,我們可以完整地描述push和pop指令的功能了,例如:push ax。push ax的執(zhí)行,由以下兩步完成:

1. SP=SP-2,SS:SP指向當(dāng)前棧頂前面的單元,以當(dāng)前棧頂前面的單元為新的棧頂。

2. 將ax中的數(shù)據(jù)送入SS:SP指向的內(nèi)存單元處,SS:SP此時(shí)指向新棧頂。

下圖描述了push ax的執(zhí)行過程。

將10000H~1000FH這段空間當(dāng)作棧段,SS=1000H,??臻g大小為16字節(jié),棧最底部的字單元地址為1000:000E,任

意時(shí)刻,SS:SP指向棧頂,當(dāng)棧中只有一個(gè)元素的時(shí)候,SS=1000H,SP=000EH,棧為空,就相當(dāng)于棧中唯一的元素出棧后,

SP=SP+2,原來為000EH,加2后SP=0010H,所以,當(dāng)棧為空的時(shí)候,SS=1000H,SP=0010H。

換一個(gè)角度看,任意時(shí)刻,SS:SP指向棧頂元素,當(dāng)棧為空的時(shí)候棧中沒有元素,也就不存在棧頂元素,所以SS:SP只能指

向棧的最底部單元下面的單元,該單元的偏移地址為棧最底部的字單元的偏移地址+2,棧最底部字單元的地址為1000:000E,

所以,棧空時(shí),SP=0010H。

接下來,我們描述pop指令的功能,例如:pop ax。Pop ax的執(zhí)行過程和push ax剛好相反,由以下兩步完成:

1. 將SS:SP指向的內(nèi)存單元處的數(shù)據(jù)送入ax中。

2. SP=SP+2,SS:SP指向當(dāng)前棧頂下面的單元,以當(dāng)前棧頂下面的單元為新的棧頂。

下圖描述了pop ax的執(zhí)行過程。

注意:上圖中,出棧后,SS:SP指向新的棧頂1000EH,pop操作前的棧頂元素,1000CH處的數(shù)據(jù)2266H依然存在,但

是,它已不在棧中,當(dāng)再次執(zhí)行push等入棧指令后,SS:SP移至1000CH,并在里面寫入新的數(shù)據(jù),將它覆蓋。
8、push指令 pop指令

Push和pop指令的格式有如下兩種形式:

第一種形式:push 寄存器    ;將一個(gè)寄存器中的數(shù)據(jù)入棧。

            Pop 寄存器    ;出棧,用一個(gè)寄存器接收出棧的數(shù)據(jù)。

這一種形式,它們可以在棧和寄存器之間傳送數(shù)據(jù)。

注意:上面的寄存器可以是段寄存器,比如,可以是:push ds、pop ds。

第二種形式:push 內(nèi)存單元    ;將一個(gè)內(nèi)存單元中的字型數(shù)據(jù)入棧(注意,棧操作都是以字為單位)。

            Pop 內(nèi)存單元    ;出棧,用一個(gè)內(nèi)存字單元接收出棧的數(shù)據(jù)。

比如:mov ax, 1000H

      Mov ds, ax    ;將內(nèi)存單元的段地址放在DS中。

      Push [2a38]    ;將內(nèi)存單元[2a38]中的字型數(shù)據(jù)入棧。

      Pop [2a3a]    ;出棧,出棧的數(shù)據(jù)送入內(nèi)存單元[2a3a]。

這一種形式,它們可以在棧和內(nèi)存單元之間傳送數(shù)據(jù)。

指令執(zhí)行時(shí),CPU要知道內(nèi)存單元的地址,可以在push、pop指令中給出內(nèi)存單元的偏移地址,段地址在指令執(zhí)行時(shí),CPU

從DS中取得。

Push和pop實(shí)質(zhì)上是一種內(nèi)存?zhèn)魉椭噶?,與mov指令不同的是,push和pop指令訪問的??臻g的地址不是在指令中給出

的,而是由SS:SP指出的。同時(shí),push和pop指令還要改變SP中數(shù)值。Mov指令只需一步操作,就是傳送,而執(zhí)行push、

Pop指令需要兩步操作,執(zhí)行push時(shí),先改變SP,后向SS:SP處傳送;執(zhí)行pop時(shí),先讀取SS:SP處的數(shù)據(jù),后改變SP。
9 、 棧段

前面講過(參見2.7節(jié)),對(duì)于8086PC機(jī),在編程時(shí),可以根據(jù)需要,將一組內(nèi)存單元定義為一個(gè)段。我們可以將長(zhǎng)度為N

(N≤64KB)的一組地址連續(xù)、起始地址為16的倍數(shù)的內(nèi)存單元,當(dāng)作??臻g來用,從而定義了一個(gè)棧段。

比如,我們將10010H~1001FH這段內(nèi)存空間當(dāng)作棧來用,以棧的方式進(jìn)行訪問,這段空間就可以認(rèn)為是一個(gè)棧段,大小為

16個(gè)字節(jié)。

如何使得如push、pop等棧操作指令訪問我們定義的棧段呢?那就是要將SS:SP指向我們定義的棧段。

現(xiàn)在我們來回答3.8節(jié)中的第一個(gè)問題。答:只要這段內(nèi)存單元被SS:SP指向,那么,CPU就會(huì)把這段空間當(dāng)作棧來使用。

 

 

 






作者:chen.yu
深信服三年半工作經(jīng)驗(yàn),目前就職游戲廠商,希望能和大家交流和學(xué)習(xí),
微信公眾號(hào):編程入門到禿頭 或掃描下面二維碼
零基礎(chǔ)入門進(jìn)階人工智能(鏈接)