組合語言(三) 暫存器

2021-10-02 21:40:43 字數 4528 閱讀 2749

任何兩個位址連續的記憶體單元,n號單元和 n+1號單元,可以將它們看成兩個記憶體單元 ,也可以看成乙個位址為n的字單元中的高位位元組單元和低位位元組單元。

cpu要讀取乙個記憶體單元時,必須先給出這個記憶體單元的位址

在8086pc中,記憶體位址由段位址和偏移位址組成

8086cpu中有乙個ds暫存器,通常用來存放要訪問的資料的段位址

mov al,[0]

已知的mov指令可完成的兩種傳送功能:

將資料直接送入暫存器;

將乙個暫存器中的內容送入另乙個暫存器中。

mov 指令 還可以將乙個記憶體單元中的內容送入乙個暫存器。

mov指令的格式

mov 暫存器名,記憶體單元位址

【……】表示乙個記憶體單元,「【……】」中的0表示記憶體單元的偏移位址

那麼記憶體單元的段位址是多少呢?

執行指令時,8086cpu自動取ds中的資料為記憶體單元的段位址。

如何用mov指令從10000h中讀取資料?

將段位址1000h放入ds

用mov al,[0]完成傳送(mov指令中的說明操作物件是乙個記憶體單元,中的0說明這個記憶體單元的偏移位址是0,它的段位址預設放在ds中)

如何把1000h送入ds?

首先,類似於mov ds,1000h是非法的,8086cpu不支援將資料之間送入段暫存器的操作

一般是資料⟶

\longrightarrow

⟶一般的暫存器⟶

\longrightarrow

⟶段暫存器

怎樣將資料從暫存器送入記憶體單元?

mov bx,1000h

mov ds,bx

mov ,al

因為8086cpu是16位結構,有16根資料線,所以可以一次性傳16位的資料,也就是一次性傳送乙個字

已學mov指令的幾種形式:

mov 暫存器,資料

mov 暫存器,暫存器

mov 暫存器,記憶體單元

mov 記憶體單元,暫存器

mov 段暫存器,暫存器

根據已知指令進行推測:(未驗證)

mov 段暫存器,暫存器⟶

\longrightarrow

⟶mov 暫存器,段暫存器

mov 記憶體單元,暫存器⟶

\longrightarrow

⟶mov 記憶體單元,段暫存器、mov 段暫存器,記憶體單元

add與sub指令

add 暫存器,資料

add 暫存器,暫存器

add 暫存器,記憶體單元

add 記憶體單元,暫存器

sub 暫存器,資料

sub 暫存器,暫存器

sub 暫存器,記憶體單元

sub 記憶體單元,暫存器

我們可以將一組長度為n(n≤64k)、位址連續、起始位址為16的倍數的記憶體單元當作專門儲存資料的記憶體空間,從而定義了乙個資料段。

如何訪問資料段中的資料呢?

我們研究棧的角度:

棧是一種具有特殊的訪問方式的儲存空間。它的特殊性就在於,最後進入這個空間的資料,最先出去。

棧的基本操作

出棧,入棧

又稱為lifo(last in first out)

cpu有棧的設計,這意味著我們在使用8086cpu程式設計時可以將一段記憶體當做棧來使用

棧指令

push(入棧)

out(出棧)

cpu如何知道當前要執行的指令所在的位置?

段暫存器ss  存放棧頂的段位址

暫存器sp  存放棧頂的偏移位址

任意時刻,ss:sp指向棧頂元素。

如果我們將10000h~1000fh 這段空間當作棧,初始狀態棧是空的,此時,ss=1000h,sp=0010h

執行push ax後:ss:sp指向棧中的第乙個元素

pop指令的執行過程

pop ax

將ss:sp指向的記憶體單元處的資料送入ax中

sp=sp+2,ss:sp指向當前棧頂下面的單元,以當前棧頂下面的單元為新的棧頂

注意:

出棧後,ss:sp指向新的棧頂 1000eh,pop操作前的棧頂元素,1000ch 處的2266h 依然存在 ,但是,它已不在棧中。

當再次執行push等入棧指令後,ss:sp移至1000ch,並在裡面寫入新的資料,它將被覆蓋。

棧頂超界是危險的

因為我們既然將一段空間安排為棧 ,那麼在棧空間之外的空間裡很可能存放了具有其他用途的資料、**等,這些資料、**可能是我們自己的程式中的,也可能是別的程式中的。

8086cpu不保證對棧的操作不會超界

因為根據8086cpu工作機理,只考慮當前情況

當前棧頂在何處

當前要執行的指令是哪一條

push暫存器:將乙個暫存器中的資料入棧

pop暫存器:出棧,用乙個暫存器接收出棧的資料

push ax

pop bx

push段暫存器:將乙個段暫存器中的資料入棧

pop段暫存器:出棧,用乙個段暫存器接收出棧的資料

push ds

pop es

push記憶體單元:將乙個記憶體單元處中的字入棧

pop記憶體單元:出棧,用乙個記憶體字單元接收出棧的資料

push

pop

指令執行時 ,cpu 要知道記憶體單元的位址,可以在 push、pop 指令中給出記憶體單元的偏移位址,段位址在指令執行時,cpu從ds中取得。

結論:

push、pop 實質上就是一種記憶體傳送指令,可以在暫存器和記憶體之間傳送資料,與mov指令不同的是,push和pop指令訪問的記憶體單元的位址不是在指令中給出的,而是由ss:sp指出的。

同時,push和pop指令還要改變 sp 中的內容。

另外

push和pop指令同mov指令不同,cpu執行mov指令只需一步操作,就是傳送,而執行push、pop指令卻需要兩步操作。

執行push時:先改變sp,後向ss:sp處傳送。

執行pop時:先讀取ss:sp處的資料,後改變sp。

我們可以將長度為 n(n ≤64k )的一組位址連續、起始位址為16的倍數的記憶體單元,當作棧來用,從而定義了乙個棧段。

比如

比如我們將10010h~1001fh 這段長度為 16 位元組的記憶體空間當作棧來用,以棧的方式進行訪問。

這段空間就可以成為棧段,段位址為1000h,大小為16位元組。

如何使的如push、pop 等棧操作指令訪問我們定義的棧段呢?

將ss:sp指向我們定義的棧段。

乙個棧段最大可以設為多少?

所以乙個棧段的容量最大為64kb

我們可以將一段記憶體定義為乙個段,用乙個段位址指示段,用偏移位址訪問段內的單元。這完全是我們自己的安排。

我們可以用乙個段存放資料,將它定義為「資料段」;

我們可以用乙個段存放**,將它定義為「**段」;

我們可以用乙個段當作棧,將它定義為「棧段」;

對於cpu來說

對於資料段,將它的段位址放在 ds中,用mov、add、sub等訪問記憶體單元的指令時,cpu就將我們定義的資料段中的內容當作資料段來訪問;

對於**段,將它的段位址放在 cs中,將段中第一條指令的偏移位址放在ip中,這樣cpu就將執行我們定義的**段中的指令;

對於棧段,將它的段位址放在ss中,將棧頂單元的偏移地置放在 sp 中,這樣cpu在需要進行棧操作的時候,比如執行 push、pop 指令等,就將我們定義的棧段當作棧空間來用。

可見,不管我們如何安排 ,cpu 將記憶體中的某段記憶體當作** ,是因為cs:ip指向了那裡;cpu將某段記憶體當作棧 ,是因為ss:ip指向了那裡。

一段記憶體,可以既是**的儲存空間,又是資料的儲存空間,還可以是棧空間,也可以什麼也不是。

關鍵在於cpu中暫存器的設定,即:cs、ip、ss、sp、ds的指向

組合語言 暫存器

乙個典型的cpu由運算器 控制器 暫存器等器件組成,這些器件靠內部匯流排相連。通用暫存器 ax bx cx dx 段位址暫存器 cs ds es ss 專用暫存器 bp sp si di 指令指標暫存器 ip 標誌暫存器 psw ah al ax accumulator 累加暫存器 bh bl bx...

組合語言 暫存器

乙個cpu由暫存器,運算器,控制器組成,暫存器負責儲存資料。通用暫存器 ax,bx,cx,dx。8086cpu的暫存器都是16位的,能存放兩個位元組。乙個暫存器又能分為兩個部分,乙個高位位元組如ah,還有乙個地位位元組如al。這兩個部分可以單獨看成乙個八位暫存器來用。當暫存器當整體來看時,它可以進行...

組合語言 暫存器

ax,bx,cx,dx 這4個暫存器通常用來存放一般性的資料,被稱為通用暫存器。8086cpu這5個暫存器都可以分為兩個可以獨立使用的8位暫存器來用 ax的低8位 0 7 構成al暫存器,高8位 8 15 構成了ah暫存器。ah和al暫存器是可以獨立使用的8位暫存器。考慮相容性8086cpu可以一次...