彙編語言筆記

最近將彙編粗略的複習了下,作個簡單記錄:


1,基礎知識
2,寄存器
3,寄存器(內存訪問)
4,第一個程序
5,[BX]和loop指令
6,包含多個段的程序
。。。


第一章 基礎知識
1,用彙編語言編寫程序的過程如下圖所示:


2,彙編語言發展至今,有以下3類指令組成:
彙編指令:機器碼的助記符,有對應的機器碼。
僞指令:沒有對應的機器碼,由編譯器執行,計算機並不執行。
其它符號:如+、-、*、/等,由編譯器識別,沒有對應的機器碼。
彙編語言的核心是彙編指令,它決定了彙編語言的特性。

3,每一種CPU都有自己的彙編指令集。CPU可以直接使用的信息在存儲器中存放。

4,在存儲器中指令和數據沒有任何區別,都是二進制信息。存儲單元從零開始順序編號。一個存儲單元可以存儲8個bit,即8位二進制數。

5, 1Byte=8bit  1KB=1024B  1MB = 1024KB  1GB = 1024MB

6,每一個CPU芯片都有許多管腳,這些管腳和總線相連。也可以說,這些管腳引出總線。一個CPU可以引出3種總線的寬度標誌了這個CPU的不同方面的性能:

地址總線的寬度決定了CPU的尋址能力;
數據總線的寬度決定了CPU與其它器件進行數據傳送時的一次數據傳輸量;
控制總線的寬度決定了CPU對系統中其它器件的控制能力。

7,CPU系統中各類存儲器看作一個邏輯存儲器,如下圖所示。

8,不同的計算機系統的內存地址空間的分配情況各不相同。8086PC機內存地址空間分配情況如下圖所示:


2.第二章 寄存器

1,一個典型的CPU由運算器、控制器、寄存器等器件構成。運算器進行信息處理;寄存器進行信息存儲;控制器控制各種器件進行工作;內部總線連接各種器件,在它們之間進行數據的傳送。

2,8086 CPU有14個寄存器,每個寄存器都有一個名字:AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DS、ES、PSW

3,通用寄存器:AX、BX、CX、DX,用於存儲一般性的16位數據。這4個寄存器又可以各自分爲兩個獨立的8位寄存器來用:AH和AL;BH和BL、CH和CL、DH和DL。數據存儲情況如下所示:


4,字節:記爲byte,一個字節由8個bit組成,可以存儲在8位寄存器中。字:記爲word,一個字由兩個字節組成,這兩個字節分別稱爲這個字的高位字節和低位字節。

5,幾條彙編指令舉例:


6,16位結構的CPU可以按照如下描述:
運算器一次最多可以處理16位的數據;
寄存器的最大寬度爲16位;
寄存器和運算器之間的通路爲16位。

7,8086CPU有20位地址總線,可以傳送20位地址,達到1MB尋址能力。而8086CPU又是16位結構,所以,8086CPU採用一種在內部用兩個16位地址合成的辦法來形成一個20位的物理地址,相關部件的邏輯結構如下圖說所示:


1)CPU中的相關部件(CS和IP)提供兩個16位的地址,一個稱爲段地址,另一個稱爲偏移地址;
2)段地址和偏移地址通過內部總線送入一個稱爲地址加法器的部件;
3)地址加法器將兩個16位地址合成爲一個20位的物理地址:物理地址 = 段地址x 16 + 偏移地址 
4)地址加法器通過內部總線將20位物理地址送入輸入輸出控制電路;
5)輸入輸出控制電路將20位物理地址送上地址總線;
6)20位物理地址被地址總線傳送到存儲器。

8,CS和IP是8086CPU中兩個最關鍵的寄存器,它們指示了CPU當前讀取指令的地址。CS爲代碼段寄存器,IP爲指令指針寄存器。在8086CPU機中,任意時刻,設CS中的內容爲M,IP中的內容爲N,8086CPU將從內存Mx16+N單元開始,讀取一條指令並執行。

9,8086CPU的工作過程簡述如下:
Step1: 從CS:IP指向的內存單元讀取指令,讀取的指令進入指令緩衝器;
Step2:IP=IP+所讀取指令的長度,從而指向下一條指令;
Step3:指令執行。轉至step1,重複這個過程。

10,修改CS、IP的指令
a)jmp 段地址:偏移地址  -> 用指令中給出的段地址修改CS,偏移地址修改IP。
b)Jmp 某一合法寄存器    -> 僅修改IP的內容

第三章 寄存器(內存訪問)
1,子單元,即存放一個字型數據(16位)的內存單元,由兩個地址連續的內存單元組成。高地址內存單元中存放字型數的高位字節,低地址內存單元中存放字型數據的低位字節。起始地址爲N的字單元簡稱爲N地址字單元。

2,DS和[address]。8086CPU有一個DS寄存器,通常用來存放要訪問數據的段地址。用mov指令訪問內存單元,可以再mov指令中只給出單元的偏移地址,此時,段地址默認在DS寄存器中。示例代碼如下:將1000H(1000:0)中的數據讀入到al中。至於爲何不直接將1000H送入ds,即mov ds,1000H,這是8086CPU硬件設計的問題。

mov bx,1000H
mov ds,bx
mov al,[0]

3,mov指令
mov:寄存器,數據
mov:寄存器,寄存器
mov:寄存器,內存單元
mov:段寄存器,內存單元
mov:內存單元,寄存器
mov:內存單元,段寄存器
mov:段寄存器,寄存器
mov:寄存器,段寄存器

4,add指令
add:寄存器,數據
add:寄存器,寄存器
add:內存單元,寄存器
add:寄存器,內存單元

4,sub指令
sub:寄存器,數據
sub:寄存器,寄存器
sub:內存單元,寄存器
sub:寄存器,內存單元

 
5,jmp指令
jmp:段地址:偏移地址  用段地址修改CS 用偏移地址修改IP
jmp:寄存器,只用寄存器的內容修改IP

6,在內存和寄存器之間傳送字型數據時,高地址單元和高8位寄存器、低地址單元和低8位寄存器相對應。

7,mov、add、jmp是具有兩個操作對象的指令。jmp是具有一個操作對象的指令。

8,棧:LIFO(Last In First Out,後進先出)。

9,8086CPU出棧入棧都是以字爲單位進行的;在SS、SP中存放棧頂的段地址和偏移地址;任意時刻,SS:SP指向棧頂元素;push指令(入棧)和pop指令(出棧)執行時,CPU從SS和SP中得到棧頂的地址;8086CPU只記錄棧頂,棧空間的大小我們要自己管理;push、pop實質上是一種內存傳送指令。

10,push ax 由一下兩步完成
1)SP=SP-2
2)將ax中的內容送入SS:SP指向的內存單元

11,pop ax 
1)將SS:SP指向的內存單元中的內容送入ax
2)SP=SP+2

12,push/pop其它
push 寄存器
pop 寄存器
push 段寄存器 
pop 段寄存器
push 內存單元
pop 內存單元
只給出內存單元的偏移地址,段地址在指令執行時從ds中獲得。

13,段的綜述
++++++++++++++++++++++++
爲了編程的方便,人爲的將一段內存定義爲一個段:用一個段地址指示段,用偏移地址訪問段內的單元。
比如,用一個段存放數據,將它定義爲“數據段”;用一個段存放代碼,將它定義爲“代碼段”;用一個段當作棧,將它定義爲“棧段”。

對於數據段,將它的段地址放在DS中,用mov、add、sub等訪問內存單元的指令時,CPU就將我們定義的數據段中的內容當作數據來訪問;
對於代碼段,將它的段地址放在CS中,將段中第一條指令的偏移地址放在IP中,這樣CPU就將執行我們定義的代碼段中的指令;
對於棧段,將它的段地址放在SS中,將棧頂單元的偏移地址放在SP中,這樣CPU在需要進行棧操作的時候,比如執行push、pop指令等,就將我們定義的棧段當作棧空間來用。

可見,不管我們如何安排,CPU將內存中的某段內容當作代碼,是因CS:IP指向了那裏;CPU將某段內存當作棧,是因爲SS:SP指向了那裏。我們要清楚,什麼是我們的安排,以及如何讓CPU按我們的安排行事。

一段代碼,可以既是代碼的存儲空間,又是數據的存儲空間,還可以是棧空間,也可以什麼也不是。關鍵在於寄存器的設置,即CS、IP,SS、SP,DS的指向。
++++++++++++++++++++++++

第四章 第一個程序
1,segment 和ends是一對成對使用的僞指令,用於定義一個段。segment說明一個段開始,ends說明一個段結束。如下的Xxx爲段的名稱。

Xxx segment
...
Xxx ends

2,僞指令end是一個彙編程序的結束標記。注意區別ends(與segment是成對使用的)。

3,僞指令assume含義爲“假設”,即假設某一段寄存器和程序中的某一個用segment...ends定義的段相關聯。

4,與結束相關的概念


5,彙編程序從寫出到執行的全部過程如下:


 

第五章 [BX]和loop指令

1,mov ax, [bx]  功能:bx中存放的數據作爲一個偏移地址EA,段地址SA默認在ds中,將SA:EA處的數據送入ax中。即:(ax)=((ds)*16+(bx))。

2,mov [bx], ax 功能:bx中存放的數據作爲一個偏移地址EA,段地址SA默認在ds中,將ax中的數據送入內存SA:EA處。即:((ds)*16+(bx))=(ax)。

3,用cx和loop指令相配合實現循環功能的程序框架如下:

  mov cx, 循環次數
s: 
  循壞執行的程序段
  loop s

4,loop指令的格式是:loop標號,CPU執行loop指令的時候,要進行兩個操作:
Step1:(cx)=(cx)-1;
Step2:判斷cx中的值,不爲零則轉至標號處執行程序,如果爲零則向下執行。

第六章 包含多個段的程序

1,段名相當於一個標號,它代表了段地址。所以,“mov ax,data”就是將名爲data的段的段地址送入ax.

assume cs:code,ds:data,ss:stack
data segment
    dw    0123H,0456H,0789H,0abcH,0defH,0fedH,0cbaH,0987H
data ends
stack segment
    dw    0,0,0,0,0,0,0,0
stack ends
code segment    
start:    mov ax,stack
        mov ss,ax
        mov sp,16    ;將設置棧頂ss:sp指向stack:16
        
        mov ax,data
        mov ds,ax    ;ds指向data 
        
        mov bx,0    ;ds:bx指向data段中第一個單元
        mov cx,8
    s:    push [bx]
        add bx,2
        loop s        ;將以上代碼段0-16單元中的8個字符型數據依次入棧
        
        mov bx,0
        mov cx,8
    s0:    pop [bx]
        add bx,2
        loop s0        ;以上依次出棧8個字符型數據到代碼段0-16單元中
        
        mov ax,4c00H
        int 21h
code ends
end start            ;指名程序的入口在start處

。。。。。。

參考:
1,《彙編語言》-王爽,清華大學出版社
2,  彙編網

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章