彙編語言學習知識點1


  • 寄存器(cpu)
彙編語言由以下3類組成:
1、彙編指令(機器碼的助記符)
2、僞指令  (由編譯器執行)
3、其它符號(由編譯器識別)

8086CPU有14個寄存器 它們的名稱爲:AX、BX、CX、DX、SI、DI、SP、BP、 IP、CS、SS、DS、ES、PSW

8086CPU所有的寄存器都是16位的,可以存放兩個字節。AX、BX、CX、DX 通常用來存放一般性數據被稱爲通用寄存器

AX可以分爲AH和AL;BX可以分爲BH和BL;CX可以分爲CH和CL;DX可以分爲DH和DL

地址加法器合成物理地址的方法:物理地址=段地址×16+偏移地址

需要注意的兩點:
(1)段地址×16 必然是 16的倍數,所以一個段的起始地址也一定是16的倍數;
(2)偏移地址爲16位,16 位地址的尋址能力爲 64K,所以一個段的長度最大爲64K。

段寄存器就是提供段地址的。8086CPU有4個段寄存器:CS、DS、SS、ES

CS和IP是8086CPU中最關鍵的寄存器,它們指示了CPU當前要讀取指令的地址。CS爲代碼段寄存器;IP爲指令指針寄存器

同時修改CS、IP的內容:

  jmp 段地址:偏移地址

  jmp 2AE3:3

  功能:用指令中給出的段地址修改CS,偏移地址修改IP。


僅修改IP的內容:

  jmp 某一合法寄存器

  jmp ax  (類似於 mov IP,ax)

  功能:用寄存器中的值修改IP。

  • 寄存器(內存訪問)
將10000H(1000:0)中的數據讀到al中
mov bx,1000H
mov ds,bx
mov al,[0]

mov 寄存器名,內存單元地址

“[…]”表示一個內存單元, “[…]”中的0表示內存單元的偏移地址。執行指令時,8086cpu自動取DS中的數據爲內存單元的段地址。

將al中的數據送入內存單元10000H
mov bx,1000H
mov ds,bx
mov [0],al     
  • cpu提供的棧機制
8086cpu提供入棧和出棧的指令:

push ax: 將寄存器ax中的數據送入棧中;

pop ax: 從棧頂取出數據送入ax。

8086cpu的入棧和出棧操作都是以字爲單位進行的。

8086CPU中,有兩個寄存器:
段寄存器SS   存放棧頂的段地址
寄存器SP      存放棧頂的偏移地址
 任意時刻,SS:SP指向棧頂元素。

push ax
(1)SP=SP–2;
(2)將ax中的內容送入SS:SP指向的內存單元處,SS:SP此時指向新棧頂。
pop ax
(1)將SS:SP指向的內存單元處的數據送入ax中;
(2)SP = SP+2,SS:SP指向當前棧頂下面的單元,以當前棧頂下面的單元爲新的棧頂。
注意:
出棧後,SS:SP指向新的棧頂 ,pop操作前的棧頂元素依然存在,但是已經不在棧中,當再次執行push等入棧指令後,會寫入新的數據。

  • 棧頂超界問題
8086CPU不保證對棧的操作不會超界。這就是說, 8086CPU 只知道棧頂在何處(由SS:SP指示),而不知道讀者安排的棧空間有多大。這點就好像 ,CPU 只知道當前要執行的指令在何處(由CS:SP指示)而不知道讀者要執行的指令有多少。
所以在編程的時候要自己操心棧頂超界的問題 ,要根據可能用到的最大棧空間,來安排棧的大小,防止入棧的數據太多而導致的超界;執行出棧操作的時候也要注意,以防棧空的時候繼續出棧而導致的超界。
練習:
(1)將10000H~1000FH 這段空間當作棧,初始狀態是空的;
(2)設置AX=001AH,BX=001BH;
(3)將AX、BX中的數據入棧;
(4)然後將AX、BX清零;
(5)從棧中恢復AX、BX原來的內容。
mov ax,1000H
mov ss,ax
mov sp,0010H
mov ax,001AH
mov bx,001BH
push ax
push bx
sub ax,ax
sub bx,bx
pop bx
pop ax
  • 棧的綜述
(1)8086CPU提供了棧操作機制,方案如下:
    在SS,SP中存放棧頂的段地址和偏移地址;
  提供入棧和出棧指令,他們根據SS:SP指示的地址,按照棧的方式訪問內存單元。
(2)push指令的執行步驟:
  SP=SP-2;
  向SS:SP指向的字單元中送入數據。
(3)pop指令的執行步驟:
從SS:SP指向的字單元中讀取數據; 
SP=SP-2。
(4)任意時刻,SS:SP指向棧頂元素。
(5)8086CPU只記錄棧頂,棧空間的大小我們要自己管理。
(6)用棧來暫存以後需要恢復的寄存器的內容時 ,寄存器出棧的順序要和 入棧的順序相反。
(7)push、pop實質上是一種內存傳送指令。
  • 段的綜述
我們可以將一段內存定義爲一個段,用一個段地址指示段,用偏移地址訪問段內的單元。這完全是我們自己的安排。
我們可以用一個段存放數據,將它定義爲“數據段”;
我們可以用一個段存放代碼,將它定義爲“代碼段”;
我們可以用一個段當作棧,將它定義爲“棧段”;
我們可以這樣安排,但若要讓CPU按照我們的安排來訪問這些段,就要:
對於數據段,將它的段地址放在 DS中,用mov、add、sub等訪問內存單元的指令時,CPU就將我們定義的數據段中的內容當作數據段來訪問;
對於代碼段,將它的段地址放在 CS中,將段中第一條指令的偏移地址放在IP中,這樣CPU就將執行我們定義的代碼段中的指令;
對於棧段,將它的段地址放在SS中,將棧頂單元的偏移地置放在 SP 中,這樣CPU在需要進行棧操作的時候,比如執行 push、pop 指令等,就將我們定義的棧段當作棧空間來用。

可見,不管我們如何安排 ,CPU 將內存中的某段內存當作代碼 ,是因爲CS:IP指向了那裏;CPU將某段內存當作棧 ,是因爲 SS:IP 指向了那裏
  • 第一個彙編程序
編程運算2^3
assume cs:abc
abc segment
mov ax,2
add ax,ax
add ax,ax
abc ends
end 
關於段結束、程序結束、程序返回



EXE文件中的程序的加載過程









發佈了24 篇原創文章 · 獲贊 2 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章