1. 程式人生 > 其它 >20192430謝志琛組合語言程式設計1~4章學習筆記

20192430謝志琛組合語言程式設計1~4章學習筆記

組合語言程式設計

第一章 基礎知識

1.組合語言的一般概念

1.1 組合語言的一般概念

計算機程式設計語言可分為機器語言、高階
語言和組合語言三類

(1). 機器語言

機器語言就是把控制計算機的命令和各種資料直接用二進位制數碼錶示的一種程式設計語言。

機器指令中既包含了指示運算功能的程式碼,又給出了參加運算的操作資料

優點:機器語言最直接地表示了計算機內部的基本操作,用它編制的程式在計算機中執行的效率最高。即執行速度最快,程式長度最短。

缺點:用二進位制數表示的內容既不便於記憶又難於閱讀。

(2). 高階語言

高階語言將計算機內部的操作細節遮蔽起來,使用者不需要知道計算機內部資料的傳送和處理的細節,使用類似於自然語言的一些語句來編制程式,完成指定的任務。

特點:程式設計簡單,但程式效率較機器語言低。

(3). 組合語言

為了便於記憶和閱讀,使用字母和符號來表示機器語言的命令,用十進位制數或十六進位制數來表示資料,這樣的計算機程式設計語言就稱為組合語言。

一條組合語言的語句與一條機器語言指令對應,組合語言程式與機器語言程式效率相同。

為了學習和使用某種計算機的組合語言,必須熟悉計算機的內部組成結構。但並非要掌握計算機系統的全部硬體組成,只需掌握用匯編語言編制程式時所涉及到的那些硬體的結構和功能。

對一臺計算機來說,機器語言的執行主要取決於該計算機的中央處理器CPU。


1.2 學習和使用匯編語言的目的

通過用匯編語言編制程式可以更清楚地瞭解計算機是如何完成各種複雜的工作。在此基礎上,程式設計人員能更充分地利用機器硬體的全部功能,發揮機器的長處。

在計算機系統中,某些功能必須用匯編語言程式來實現。

組合語言程式的效率高於高階語言程式。實時過程控制、智慧儀器儀表等,常常用匯編語言來編制程式。


1.3 進位計數制及其相互轉換

一. 進位計數制

如十進位制數,用0、1~9十個數碼的組合來表示數字。每個數碼排在不同位置,所表示的數值大小不相同。

各個位置上所表示的基本數值稱為位權, 簡稱權。

每個數位上能使用不同數碼的個數稱為基數。

例如十進位制有十個數碼0~9,基數為10,二進位制基數為2。

每個數位能取的最大數碼值=基數-1。

在計算機中資料表示一般採用二進位制數,因為它在計算機中最容易表示和儲存,且適合於邏輯值的表達與運算。

對人來說二進位制不便於書寫和閱讀,因此書寫時常使用8進位制和16進位制。

3位二進位制數與一位8進位制數對應,4位二進位制數與一位16進位制數對應。

B(Binary)--二進位制數
O (Octal)或Q--八進位制數
D (Decimal)--十進位制數
H (Hexadecimal)--十六進位制數。
如未使用任何字母,則預設表示是十進位制數。

二. 各種數制間的相互轉換

1.十進位制整數轉換為二進位制數
(1)減權定位法
  1. 從二進位制數高位起,依次用待轉換的十進位制數與各位權值進行比較;
  2. 如夠減,則該數位係數Ki=1,同時減去該位權值,餘數作為下一次比較的值;
  3. 如不夠減,則Ki=0 。
(2) 除基取餘法
  1. 將十進位制數除以基數2,其餘數為二進位制數的最低位,再用其商除2,其餘數為次低位,反覆做下去,直到商0.
2.十進位制小數轉換為二進位制數
(1) 減權定位法
(2) 乘基取整法
3. 二進位制整數轉換為十進位制數
(1) 按權相加法
(2) 逐次乘基相加法
4. 二進位制小數轉換為十進位制數
(1) 按權相加法
(2) 逐次除基相加法
5. 二進位制與八進位制和十六進位制間的轉換

三位二進位制數對應一位八進位制數,四位二進位制數對應一位十六進位制數。


1.4 帶符號數的表示

在一般算術表示中使用”“+”和“-”來表示正數與負數,而在計算機中使用“0”和“1”來表示正數和負數。

一、原碼錶示

二進位制數的最高位表示符號,0表示正,1表示負。數值 部分用二進位制數絕對值表示。

二、補碼的表示

1.補碼的定義
[X]補=M+X (Mod M)

用補碼錶示的機器數,符號位仍然表示數的符號:0為正,1為負。對於正數,補碼與原碼相同,對於負數需要進行變換。

2.由真值、原碼變換為補碼

負數的真值變換為補碼的方法:將各位變反(0變1,1變0)然後在最低位加1.

負數的原碼變換為補碼:保持符號位不變,其餘各位變反,最低位加1。

3.補碼數的表示範圍

當位數為8時
最大補碼為

01111111=[+127]補

最小補碼為

10000000=[-128]補

0的補碼只有一個

[0]補=00000000
10000000=[-128]補
11111111=[-1]補
4. 補碼的加減運算
[X+Y]補=[X]補+[Y]補
[X-Y]補=[X]補-[Y]補=[X]補+[-Y]補
  • 其中[-Y]補是對[Y]補執行一次求補運算。

1.5 字元的表示

目前最廣泛採用的是ASCII碼

標準ASCII碼為一位元組,其中用低七位表示字元編碼,用最高位表示奇偶數驗位。

標準ASCII碼共有128個,可分為兩類:

  • 非列印ASCII碼,共33個,用於控制操作, 如BEL(響鈴07H),DEL(刪除7FH),CR(回車,0DH), LF(換行,0AH).

  • 可列印ASCII碼共有95個,如數字符0~9,大小寫字母等。


1.6 基本邏輯運算

1. “與”運算(AND)

F=A ∧ B 或 F=A · B
0 ∧ 0 =0 
0 ∧ 1 = 0
1 ∧ 0 = 0
1 ∧ 1 =1

2. “或”運算(OR)

F=A ∨B 或F=A +B
0 ∨0=0
0 ∨1=1
1 ∨0=1 
1 ∨1=1

3. “非”運算

邏輯“非”運算通常是在邏輯變數上方加一橫線表示。

4. “異或”運算(XOR)

1 ⊕ 1=0
1 ⊕ 0=1
0 ⊕ 1=1
0⊕ 0=0


第二章 IBM-PC微機的功能結構

2.1 IBM-PC微機基本結構

一. 微機的一般構成

一般計算機應包括五大部件:運算器、控制器、儲存器、輸入裝置和輸出裝置。

微機的主要特點是其體積很小。

將運算器和控制器兩大部件整合在一個積體電路晶片上,稱為中央處理器,簡稱CPU,也叫微處理器。

系統採用匯流排結構,具有較大的靈活性和擴充套件性。
(https://qr.maitube.com/img/GDBHDB)

1、中央處理器CPU

分析從主儲存器取來的各條指令的功能,控制計算機各部件完成指定功能的各項操作。

2、主儲存器

主儲存器是用來存放程式和資料的部件。它由若干個儲存單元構成。儲存單元的多少表示儲存器的容量。每個儲存單元使用一個唯一的編號來標識,稱為儲存單元的地址。對每個儲存單元內容的存和取是按照地址進行訪問的。由於它的位置是在主機之外,因此也叫做外存。

3、輸入輸出裝置及介面

輸入裝置將外部資訊(程式、資料和命令)送入計算機。包括鍵盤、滑鼠等。

輸出裝置將計算機處理後的結果轉換為人或其它系統能識別的資訊形式向外輸出。如顯示器、印表機等。

由於I/O裝置的工作速度、工作原理以及所處理的資訊格式等與主機相差很大,因此I/O裝置要通過I/O接口才能與系統匯流排連線。

I/O介面是主機與I/O裝置之間設定的邏輯控制部件。通過它實現主機與I/O裝置間的資訊傳送。

4、系統匯流排

系統匯流排包括地址匯流排、資料匯流排和控制匯流排三組。它們分別用於傳送不同的資訊。

二、 Intel 8086/8088 CPU的功能結構

指令是構成組合語言程式的最基本單位,就象高階語言中的語句。

CPU執行指令序列就是重複執行從儲存器中取指令和執行指令規定的操作。

這兩個步驟的執行又分為序列方式和指令流水線方式。

1. 序列方式

當CPU在指令執行階段,不需要佔用系統匯流排,但此時匯流排也不工作,因此係統匯流排的空閒時間比較多。

在從儲存器取指令、取資料或存資料時,匯流排處於忙狀態,其所佔用的時間也較長。而CPU卻只需要花很短的時間去處理,因此大部分時間處於閒置狀態。

2.指令流水線方式

採用指令流水線工作方式的計算機具有較高的工作效率。CPU內部採用了一種先進的指令流水線結構,這種結構可以有效而充分地利用各主要硬體資源。

要實現指令流水線方式,從CPU組成結構上要劃分成多個單元。8086/8088CPU被劃分成兩個單元。
(https://qr.maitube.com/img/GDBHDD)

(1)執行單元EU

EU的主要任務是分析與執行指令,具體包括:

  1. 從指令佇列中取出指令程式碼,由控制器譯碼後產生相應的控制訊號,控制各部件完成指令規定的操作。

  2. 對運算元執行各種指定的算術或邏輯運算。

  3. 向匯流排介面單元BIU傳送訪問主存或I/0的命令,並提供相應的地址和傳送的資料。

(2)匯流排介面單元BIU

BIU負責CPU與儲存器、I/O的資訊傳送。具體包括:

  1. 取指令——根據CS暫存器和指令指標IP形成20位的實體地址,從相應的儲存器單元中取出指令,暫存到指令佇列中,等待EU取走並執行。

  2. 存取資料——在EU執行指令的過程中,需要與儲存器或I/O埠傳送資料時,由EU提供的資料和地址,結合段暫存器,通過外部匯流排與儲存器或I/0進行資料的存取。


2. 2 Intel 8086/8088CPU暫存器結構及其用途

一、通用暫存器

Intel 8086/8088有8個16位通用暫存器,它們具有良好的通用性,並且還可以用作某個特定的功能,可以由程式設計人員進行程式設計訪問。

1. 資料暫存器

它包括AX、BX、CX和DX四個暫存器。它們中的每一個既可以是16位暫存器,也可以分成兩個8位暫存器使用。即可以當作8個獨立的8位暫存器使用。

資料暫存器既可以用來存放參加運算的運算元,也可以存放運算的結果。在多數情況下,使用這些暫存器時必須在指令中明確指示。

在有些指令中,不需要明確指出使用的暫存器名,即隱念使用了某暫存器,稱為隱含使用。

個別指令對暫存器有特定的使用,並且又必須在指令中指明它的名字,這類暫存器的使用稱為特定使用。

2. 指標暫存器

SP指標——在進行堆疊操作時,被隱含使用,被用來指向堆疊頂部單元。

BP指標——被用來指向堆疊段內某一儲存單元。BP除用作地址指標外也可以象資料暫存器一 樣,存放參加運算的運算元和運算的結果。

3. 變址暫存器

有兩個16位的變址暫存器SI和DI,一般被用來作地址指標。

  • SI——源變址暫存器
  • DI——目的變址暫存器

二、段暫存器

8086/8088CPU在使用儲存器時,將它劃分成若干個段。

每個段用來存放不同的內容,如程式程式碼、資料等等。

每個儲存段用一個段暫存器來指明該段的起始位置(也叫段基址)。

CPU在訪問儲存器時必須指明兩個內容:
(1)所訪問的儲存單元屬於哪個段,即指明使用的段暫存器。
(2)該儲存單元與段起始地址(段基址)的相距多少,即偏移量。

三、指令指標IP

CPU在從儲存器取指令時,以段暫存器CS作為程式碼段的基址指標,以IP的內容作為偏移量,共同形成一條指令的存放地址。

當CPU從記憶體中取出一條指令後,IP內容自動修改為指向下一條指令。

IP的內容不能被直接訪問,既不能用指令去讀IP的值,也不能用指令給它賦值。但是可以通過某些指令的執行而自動修改IP的內容。

四、標誌暫存器

標誌暫存器是用來反映CPU在程式執行時的某些狀態,如是否有進位、奇偶性、結果的符號、結果是否為零等等。

1. 進位標誌位CF

在進行算術運算時,若最高位(對字操作是第15位,位元組操作是第7位)產生進位或借位時CF被自動置“1”,否則置“0”

在移位類指令中,CF也被用來存放從最高位(左移時)或最低位(右移時)移出的數值(0或1)。

2. 奇偶標誌位PF

當指令操作結果的低8位中含有1的個數為偶數時,則PF被置1,否則PF被置0。

注意:PF只反映操作結果的低8位的奇偶性,與指令運算元的長度無關。

3. 輔助進位標誌位AF

在進行算術運算時,若低位元組的低四位向高4位產生進位或借位,即第3位產生進位或借位時,AF位被置1,否則置0。AF標誌位用於十進位制運算的調整。

4. 零值標誌位ZF

若運算結果各位全為0,則ZF被置1,否則置0。

5. 符號標誌位SF

將運算結果視為帶符號數,當運算結果為負數時SF被置1,為正數時,則置0。

由於第7位是位元組運算元的符號位,而第15位是字運算元的符號位,因此,SF位與運算結果的最高位(第7位或第15位)相同。

6. 溢位標誌位OF

當運算結果超過機器用補碼所能表示數的範圍時,則OF置1,否則置0.

位元組資料,機器用補碼所能表示的數範圍為-128~+127。字資料的表示範圍為:-32768~+32767

注意:溢位與進位是兩個完全不同的概念,不能相互混淆。

7. 單步標誌位TF(Trace Flag)

單步標誌也叫跟蹤位,該標誌為控制標誌位。單步標誌位供除錯程式使用。

當TF位被設定為1時,每執行一條指令後,CPU暫停執行,即產生單步中斷。

8. 中斷允許標誌位IF

該標誌位為控制標誌位。當IF被設定為1時,CPU可以響應可遮蔽中斷,否則不允許響應可遮蔽中斷。

9. 方向標誌位DF

DF也是控制標誌位。它被用來規定串操作指令的增減方向。

當DF=0時,串操作指令自動使變址暫存器(SI和DI)的內容遞增。當DF=1時,串操作指令自動使變址暫存器的內容遞減。


2.3 儲存器組織結構

一、儲存器的組成

1. 儲存器是由若干個儲存單元構成

儲存單元的多少就表示了儲存器的容量。

2. 每個儲存單元存放相同長度的二進位制數

一個儲存單元的長度一般為8位二進位制數,即一個位元組。

3. 每個儲存單元有一個唯一的地址編號——地址

8086/8088CPU有20根地址線,即它可以產生20位的地址碼,它的儲存器定址能力為1兆位元組空間。

4. 任何兩個相鄰位元組單元就構成一個字單元

一個字儲存單元(WORD)的長度為16位二進
制數,即兩個位元組。字單元的地址為兩個位元組單元中較小地址位元組單元的地址。

16位長資料的存放規則是低8位放在較低地址位元組單元中,高8位放在較高地址位元組單元中。

5. 在定義一個地址時必須指出是位元組或字型別屬性

由於儲存單元可分為字單元和位元組單元,因此8086/8088CPU訪問記憶體的指令中,分為位元組訪問和字訪問兩種指令。

二、儲存器的段結構

由於8086/8088可定址的儲存空間為1MB,需要提供20位長的地址碼。而CPU內部的暫存器長度只有16位。能夠直接訪問的最大地址空間是64KB。

8086/8088系統的儲存器段結構具有以下幾個特點:

1. 8086/8088CPU將1MB的儲存空間劃分成若干個段,每個段最大長度為64K(65536)個位元組單元組成。

在8086/8088的組合語言源程式中,使用者可以根據自己需要來設定段的個數、各個段長度和每個段的用途。並且程式碼或資料可以存放在段內任意單元中。

2. 每個段的基址(段基址)必須是一個小節的首址。

段基址——一個段的起始地址。

在儲存器中規定從0地址開始,每16個位元組單元稱為一個小節(Paragraph)。因此,1MB記憶體就可劃分為64K個小節。

3. 邏輯段在物理儲存器中可以是鄰接的、間隔的、部分重疊的和完全重疊的等4種情況。

邏輯段是指在組合語言源程式中設定的段
記憶體中的一個物理儲存單元可以映象到一個或多個邏輯段中

4. 在任一時刻,一個程式只能訪問4個當前段中的內容。

4個段分別是程式碼段、資料段、堆疊段和附加段,稱為當前段。

4個段暫存器CS、DS、SS和ES分別儲存了它們段基址的高16位地址,稱為段基值。段基址的最低4位為0。(小節首址的低4位為全0 )。

三、 邏輯地址與實體地址及對應關係

1. 實體地址

在1MB的儲存空間中,每個儲存單元的實體地址是唯一的,它就是該儲存單元的20位地址。

8086/8088的實體地址範圍:00000H~0FFFFFH

CPU與儲存器之間的任何資訊交換都使用實體地址。

2. 邏輯地址

在程式設計中,為了便於程式的開發和對儲存器進行動態管理,使用了邏輯地址。

一個邏輯地址包括兩個部分:段基值和偏移量

段基值:存放在某一個段暫存器中,是一個邏輯段的起始單元地址(段基址)的高16位。

偏移量:表示某個儲存單元與它所在段的段基址之間的位元組距離。

邏輯地址的表示方法

段基值:偏移量

3. 邏輯地址轉換為實體地址

當CPU要訪問儲存器時,需要由匯流排介面單元BIU將邏輯地址轉換成實體地址。

轉換方法:將邏輯地址的段基值左移4位,形成20位的段基址(低位為0)然後與16位的偏移量相加,結果即為20位的實體地址。

4. 邏輯地址的來源

在程式的執行過程中,CPU根據不同操作型別訪問儲存器,其邏輯地址中段基值和偏移量的來源是不一樣的。下表是各種操作型別所對應的邏輯地址的來源。
https://qr.maitube.com/img/GDBHEB

(1)允許替代來源也叫做段超越,它表示了段基值除使用隱含的段暫存器外是否可以指定其它段暫存器來提供。

(2)有效地址EA,它表示根據指令所採用的定址方式計算出來的段內偏移量。


2.4 堆疊及其操作方法

堆疊的用途:主要用於暫存資料以及在過程呼叫或處理中斷時儲存斷點資訊。

一、堆疊的構造

專用堆疊儲存器:
按堆疊的工作方式專門設計的儲存器

軟體堆疊:
由程式設計人員用軟體在記憶體中劃出的一塊儲存區作為堆疊來使用。8086/8088採用這種方式。

堆疊的一端是固定的,稱為棧底。棧底是堆疊儲存區的最大地址單元。

另一端是浮動的,稱為棧頂。在任何時刻,棧頂是最後存入資訊的儲存單元。棧頂是隨著堆疊中存放資訊的多少而改變。

為了指示現在堆疊中存放資料位置,通常設定一個暫存器來指示棧頂位置。其內容就象一個指標一樣,因此被稱為堆疊指標SP(Stack Pointer)。

SP的內容始終指向棧頂單元
堆疊中資料進出都由SP來控制

在堆疊中存取資料的規則是:“先進後出FILO”(First-In Last-Out)。即最先送入堆疊的資料要到最後才能取出,而最後送入堆疊的資料,最先取出。

二、8086/8088堆疊的組織

在8086/8088微機中堆疊是由堆疊段暫存器SS指示的一段儲存區。

頂由堆疊指標SP指示。SP中內容始終表示堆疊段基址與棧頂之間的距離(位元組數)。當SP內容為最大(初始)值時,表示堆疊為空。而當(SP)=0時,表示堆疊全滿.

當SP被初始化時,指向棧底+2單元,其值就是堆疊的長度。由於SP是16位暫存器,因此堆疊長度 64K位元組。

資料在堆疊中的存放格式是:以字為單位存放,資料的低8位放在較低地址單元,高8位放在較高地址單元。

當用戶程式中要求的堆疊長度超過一個堆疊段的最大長度64KB時,可以設定幾個堆疊段。

通過改變堆疊段暫存器SS的內容,即可改變到另一個堆疊段,當改變了堆疊段暫存器SS的內容後,必須緊接著賦予SP新值。

三、 堆疊操作

1.設定堆疊

設定堆疊主要是對堆疊段暫存器SS和堆疊指標SP賦值。

當程式經過彙編、連線並裝入記憶體時,系統將自動為其分配一個儲存區作為堆疊段,將這個段的段基址的高16位送入SS中,將程式指定的位元組單元數100賦值給SP。

2.進棧PUSH

進棧就是把資料存入堆疊。由指令PUSH或者由機器自動實現,可以將通用暫存器、段暫存器或字儲存單元的內容壓入堆疊頂部。

進棧的執行過程:
(1)首先將堆疊指標SP減2,即指向一個空的堆疊字單元

SP<=(SP)-2

(2)將要儲存的內容(暫存器或儲存單元的內容)送入SP指向的字單元中。

(SP)<=資料
3.出棧POP

出棧操作由POP指令或機器自動實現,它從堆疊頂部彈出一個字到通用暫存器、段暫存器或字儲存單元。

出棧的操作過程:
(1)將SP指向的字單元(即棧頂字單元)內容送往指定的暫存器或儲存器。

暫存器/儲存器<=((SP))

(2)堆疊指標SP內容加2

SP<=(SP)+2


第三章 定址方式與指令系統

3.1 定址方式

一條指令通常由兩大部分構成:
操作碼:表示該指令應完成的具體操作,如加法、減法、乘法、移位等等。在組合語言中使用一定的符號來表示,稱為助記符。如ADD 、PUSH、POP、MOV等等。

運算元: 表示該指令的操作物件。如移位操作的被移位數,加法操作的加數等等。它可以是一個運算元,也可以是多個運算元。這取決於操作碼部分的具體需要。

定址方式:尋找指令中所需運算元的各種方法,也就是提供指令中運算元的存放資訊的方式。

Intel 8086/8088各指令中提供運算元的方法有以下四種:

(1)立即數運算元——運算元在指令程式碼中提供
(2)暫存器運算元——運算元在CPU的通用暫存器或段暫存器中
(3)儲存器運算元——運算元在記憶體的儲存單元中
(4)I/O埠運算元——運算元在輸入/輸出介面的暫存器中

1.立即數定址

立即數定址方式的指令中,所需運算元直接包含在指令程式碼中,這種運算元稱為立即數。

由於在指令執行過程中,立即數作為指令的一部分直接從BIU的指令佇列中取出,它不需另外佔用匯流排週期,因此這種定址方式執行速度快。

注意:立即數只能作為源運算元,而不能作為目的運算元。

2.暫存器定址

暫存器定址方式是指指令中所需的運算元在CPU的某個暫存器中。暫存器可以是8位或16位通用暫存器,或者是段暫存器。如:AH、AL、AX、CX、DS、ES等。

由於存取暫存器運算元完全在CPU內部進行,不需要匯流排週期,所以執行速度很快。

一個儲存單元邏輯地址表示形式:

段基值:偏移量

段基值由某個段暫存器提供.

偏移量表示了該儲存單元與段起始地址之間的距離,也叫做有效地址EA。

有效地址EA是以下三個地址分量的幾種組合,由CPU的執行單元EU計算出來的。
(1)位移量:位移量是指令中直接給出的一個8位或16位數。一般源程式中以運算元名字(變數名或標號)的形式出現。
(2)基址:由基址暫存器BX或基址指標BP提供的內容。
(3)變址:由源變址暫存器SI或目的變址暫存器DI提供的內容

位移量、基址和變址三個地址分量組合時,若有兩個或兩個以上分量時,將進行以2
的16次方為模的十六位加法運算。

3.直接定址

在直接定址方式的指令中,運算元的有效地址EA只有位移量地址分量。

在組合語言源程式中,直接定址方式用符號或常數來表示。

(1)用符號表示
例:

MOV BX,VAR=>MOV BX,DS:VAR

它表示將資料段中,偏移了VAR個位元組距離的字單元內容送到暫存器BX中。

MOV AL,DATA+2=> MOV AL, DS: DATA+2

它表示將資料段偏移了DATA+2的位元組單元內容送入AL中。

(2)用常數表示

MOV AX,DS:[64H]

它表示從當前資料段開始,偏移100個位元組的字單元內容送到AX中。不能寫為:

MOV AX,64H

注意:用常數表示時,必須用方括號括起來。段寄存
器不能省略。

4.暫存器間接定址

運算元有效地址EA直接從基址暫存器(BX或BP)或變址暫存器(SI或DI)中獲得。

暫存器間接定址就是事先將偏移量存放在某個暫存器(BX、BP、SI或DI)中,這些暫存器就如同一個地址指標。

在程式執行期間,只要對暫存器內容進行修改,就可以實現用同一條指令實現對不同儲存單元進行操作。

指示儲存器所在段的段暫存器可以省略,當指令中使用的是BP暫存器,則隱含表示使用SS段暫存器,其餘情況則隱含使用DS段暫存器。

例如:

MOV AX,[BX]=> MOV AX,DS:[BX]
MOV BH,[BP]=> MOV BH,SS:[BP]
MOV [DI],BX=> MOV DS:[DI],BX

5.基址定址/變址定址

運算元的有效地址EA等於基址分量或變址分量加上指令中給出的位移量。

指令中使用BX或BP時為基址定址。指令中使用SI或DI時為變址定址。

段暫存器的隱含使用規則與暫存器間接定址方式相同

例:

MOV AX,10H [SI]=> MOV AX,DS:10H [SI]
MOV TABLE [DI],AL=>MOV DS:TABLE [DI],AL

注意:當位移量為常數時,不能加方括號。

由於這兩種定址方式中暫存器中的內容是相對於由位移量指定的初始單元。因此也叫暫存器相對定址。

6.基址變址定址

運算元的有效地址是三個地址分量之和,即:

EA=基址+變址+位移量

例如:

MOV CX,100H[BX][DI]
MOV TABLE[BX][DI],AX

在基址變址定址方式中,程式執行期間有兩個地址分量可以修改。因此它是最靈活的一種定址方式,可以方便地對二維陣列進行訪問。

儲存器運算元定址方式中地址形成小結
(https://qr.maitube.com/img/GDBHEH)

7.串操作定址方式

8086/8088設定有專門用於串操作的指令,這些指令的運算元雖然也在儲存器中,但它們不使用前面介紹的各種定址方式,而隱含地使用變址暫存器SI和DI專門指示。

在尋找源運算元時,隱含使用SI作為地址指標。

在尋找目的串時,隱含使用DI作為地址指標。

在串操作完成之後,自動對SI和DI進行修改,使它們指向下一個運算元。

8. I/O埠定址

儲存器編址方法:
將I/O埠視為儲存器的一個單元,對埠的訪問就如同訪問儲存單元一樣。訪問儲存器的指令和各種定址方式同樣適用對I/O埠的訪問。

特點: 程式設計靈活,但需要佔用儲存地址空間。

I/O埠編址方法:
I/O埠的地址與儲存器地址分開,並使用專門的輸入指令和輸出指令。

(1) 直接埠定址

在指令中直接給出埠地址,埠地址一般採用2位十六進位制數,也可以用符號表示。

直接埠定址可訪問的埠數為0~255個。

(2)暫存器間接埠定址

暫存器間接埠定址:把I/O埠的地址先送到DX中,用DX作間接定址暫存器。

如果訪問的埠地址值大於255,則必須用I/O埠的間接定址方式。


3.2 指令系統

一種計算機所能執行的各種型別的指令的集合稱為該計算機的指令系統。
Intel8086/8088CPU指令系統的指令可以分為六大類:
1.傳送類指令
2.算術運算類指令
3.位操作類指令
4.串操作類指令
5.程式轉移類指令
6.處理器控制類指令

從指令的格式劃分,一般可以分為三種:
1.雙運算元指令:OPR DEST SRC
2.單運算元指令:OPR DEST
3.無運算元指令:OPR

對於無運算元指令,包含兩種情況:
(1)指令不需要運算元,如暫停指令HLT。
(2)在指令格式中,沒有顯式地指明運算元,但是它隱含指明瞭運算元的存放地方,如指令PUSHF。

一、傳送類指令

傳送類指令的作用是將資料資訊或地址資訊傳送到一個暫存器或儲存單元中,可以分為以下四種情況。

1.通用資料傳送指令

指令格式:MOV DEST,SRC

作用:將源運算元指定的內容傳送到目的運算元,即DEST<=(SRC)。

當指令執行完後,目的運算元原有的內容被源運算元內容覆蓋,即目的運算元和源運算元具有相同內容。

MOV指令對標誌暫存器的各位無影響

MOV指令可以是位元組資料傳送也可以是字資料傳送,但是源運算元和目的運算元的長度必須一致。

MOV指令可以分為以下幾種情況:
(1)立即數傳送到通用暫存器或儲存單元
注意:立即數只能作為源運算元,立即數不能傳送給段暫存器。

(2)暫存器之間的傳送
注意:段暫存器CS只能作源運算元,不能作目的運算元。

(3)暫存器與儲存單元之間傳送

綜合起來,MOV指令在使用時需注意以下幾個問題:
(1)立即數只能作源運算元,且它不能傳送給段暫存器。
(2)段暫存器CS只能作源運算元,段暫存器之間不能直
接傳送。
(3)儲存單元之間不能直接傳送資料
(4)MOV指令不影響標誌位

2.交換指令

指令格式:XCHG DEST,SRC

作用:源運算元和目的運算元兩者內容相互交換,即:

(DEST)<=>(SRC)

指令對標誌暫存器各位無影響

資料交換可以在暫存器之間或暫存器與儲存器單元之間進行。但是不能在儲存單元之間直接進行資料交換。暫存器只能使用通用暫存器。

為了完成兩個儲存單元(DA_BYTE1和DA_BYTE2)之間的資料交換可以使用以下三條指令來實現。

MOV AL,DA-BYTE1; AL<=(DA_BYTE1)
XCHG AL,DA-BYTE2 ; (AL)<=>(DA-BYTE2)
XCHG AL,DA-BYTE1 ; (AL)<=>(DA-BYTE1)

MOV DA-BYTE1,AL;(DA_BYTE1)<=(AL)
3.標誌傳送指令

對標誌暫存器進行存取的指令有4條,它們都是無運算元指令,即指令隱含指定標誌暫存器、AH暫存器或堆疊為運算元。

(1)取標誌暫存器指令

指令格式:LAHF

作用:將標誌暫存器的低8位送入AH暫存器,即將標誌SF、ZF、AF、PF和CF分別送入AH的第7、6、4、2、0位,而AH的第5、3、1位不確定。

指令執行對標誌暫存器各位無影響,即標誌暫存器各位不變.

(2)儲存標誌暫存器指令

指令格式:SAHF

作用:將暫存器AH中的第7、6、4、2、0位分別送入標誌暫存器的SF、ZF、AF、PF和CF各標誌位。而標誌暫存器高8位中的各標誌位不受影響。

(3)標誌進棧指令

指令格式:PUSHF

作用:先將堆疊指標SP減2,使其指向堆疊頂部的空字單元,然後將16位標誌暫存器的內容送SP指向的字單元。

(4)標誌出棧指令

指令格式:POPF

作用:將由SP指向的堆疊頂部的一個字單元的內容送入標誌暫存器,然後SP的內容加2.

4.地址傳送指令

這類指令有3條,它們的作用是將儲存單元的地址送暫存器。

(1)裝入有效地址

格式:LEA DEST,SRC

其中:源運算元SRC必須是一個位元組或字儲存器運算元(地址),DEST必須是一個16位通用暫存器。

作用:將SRC儲存單元地址中的偏移量,即有效地址EA傳送到一個16位通用暫存器中。

指令執行對標誌暫存器各位無影響。

(2)裝入地址指標指令

其中:DEST是任意一個16位通用暫存器。SRC必須是一個儲存器運算元。

作用:把SRC儲存單元開始的4個位元組單元的內容(32位地址指標)送入DEST通用暫存器和段暫存器DS(LDS指令)或ES(LES指令),其中低字單元內容為偏移量送通用暫存器,高字單元內容為段基值送DS或ES。

二、算術運算類指令

8086/8088指令系統中有加、減、乘、除指令,這些指令可以對位元組資料或字資料進行運算。

參加運算的數可以是無符號數,也可以是帶符號數。帶符號數用補碼錶示。

參加運算的數可以是二進位制數,也可以是十進位制數(以BCD碼錶示)。

1.加法指令

指令格式:ADD DEST,SRC

功能:目的運算元和源運算元相加,其和存放到目的運算元中,而源運算元內容保持不變,即:

DEST<=(DEST)+(SRC)

根據相加的結果將影響到標誌暫存器的CF、PF、AF、ZF、SF和OF。

DEST只能是通用暫存器或儲存器運算元。不能是立即數。

SRC可以是通用暫存器、儲存器或立即數運算元

DEST和SRC不能都為儲存器運算元。

ADD指令可以是位元組運算元相加,也可以是字運算元相加。

2.帶進位加法指令

指令格式:ADC DEST,SRC

該指令的功能與ADD基本相同,所不同的是其結果還要加上進位標誌CF的值,即:

DEST<=(DEST)+(SRC)+CF

根據相加的結果設定標誌暫存器中的CF、PF、AF、ZF、SF和OF

注意:參加運算的進位CF是本條指令執行之前的值。用ADC指令可實現資料長度大於16位的兩數相加。

3.加1指令

指令格式:INC DEST

該指令為單運算元指令,其功能是將目的運算元加1,並送回到目的運算元,即:

DEST<=(DEST)+1

目的運算元可以是任意的8位、16位通用暫存器或儲存器運算元。目的運算元被視為帶符號二進位制數

根據指令執行結果設定PF、AF、ZF、SF和OF標
志,但不影響CF。INC指令主要用於某些計數器的計數和修改地址指標。

4.減法指令

指令格式:SUB DEST,SRC

功能:目的運算元的內容減去源運算元的內容,結果送入目的運算元,源運算元中內容保持不變。即:

E = mc^2DEST<=(DEST)-(SRC)

操作結果將影響標誌位CF、PF、AF、ZF、SF和OF。

目的運算元DEST和源運算元SRC可以是8位或16位的通用暫存器、儲存器運算元,但兩者不能同時為儲存器運算元。立即數只能作源運算元。

注意:減法指令對借位標誌的影響,若採用變減為加的運算方法,則產生的進位與CF標誌結果相反。

5.帶借位減法

指令格式:SBB DEST,SRC

該指令的功能與SUB指令基本相同,不同的是在兩個運算元相減後再減去進位標誌CF的值。即:

DEST<=(DEST)-(SRC)-CF

注意:該CF的值是本條指令執行前的結果。

SBB指令在使用上與ADC類似,主要用於長度大於16位的數相減,即將低16位相減的結果引入高位部分的減法中。

根據指令執行結果設定PF、AF、ZF、SF 、OF和CF。

6.減1指令

指令格式:DEC DEST

該指令為單運算元指令,將目的運算元的內容減1後,送回到目的運算元。即:

DEST<=(DEST)-1

DEST可以是8位或16位的通用暫存器儲存器運算元,該指令將DEST看作是帶符號二進位制數。

根據指令執行結果設定PF、AF、ZF、SF和OF,
但不影響CF。

DEC指令的使用類似INC指令。主要用於計數和修改地址指標,計數方向與INC指令相反。

7.求負數指令

指令格式:NEG DEST

功能:用零減去目的運算元的內容,並送回目的運算元,即:

DEST<=0-(DEST)

DEST可以是任意一個8位或16位的通用暫存器或儲存器運算元,被視為帶符號的運算元。

由於機器中帶符號數用補碼錶示,求運算元的負數就是求補操作。因此,NEG指令也叫取補指令。

NEG指令將影響標誌PF、AF、ZF、SF、CF和OF。

只有當運算元為零時,進位標誌CF被置零,其它情況都被置1.

當位元組運算元為-128,或字運算元為-32768時,執行NEG指令的結果運算元將無變化,但溢位標誌OF被置1.

三、位操作類指令

1.邏輯運算指令

邏輯運算指令共有4條,它們的指令格式分別是:
邏輯“與”指令 AND DEST,SRC
邏輯“或”指令 OR DEST,SRC
邏輯“異或”指令 XOR DEST,SRC
邏輯“非”指令 NOT DEST

DEST和SRC可以是8位或16位的通用暫存器或儲存器運算元,但兩者不能同時為儲存器運算元,SRC可以為立即數。

邏輯指令對標誌位的影響:
NOT指令對標誌無影響。而其餘三條指令將根據結果影響SF、ZF和PF,而CF和OF總 是置0,AF為不確定。

邏輯運算指令除用來實現各種邏輯運算之外,還常用於對位元組或字資料的某些位的組合、分離或位設定。

2.測試指令

指令格式:TEST DEST,SRC

該指令的功能與AND指令相似,實現源運算元與目的運算元進行按位“邏輯與”運算,對標誌位的影響與AND指令相同,但運算的結果不送入目的運算元,即目的運算元內容也將保持不變。

TEST指令主要用於測試某一運算元的一位或幾
位的狀態。

3.移位/迴圈移位指令
(1)算術移位

算術左移 SAL DEST,COUNT
算術右移 SAR DEST,COUNT

(2)邏輯移位

邏輯左移 SHL DEST,COUNT
邏輯右移 SHR DEST,COUNT

邏輯左移SHL與算術左移SAL功能相同。

(3)迴圈移位

小迴圈:
迴圈左移 ROL DEST,COUNT
迴圈右移 ROR DEST,COUNT

大迴圈:
帶進位迴圈左移 RCL DEST,COUNT
帶進位迴圈右移 RCR DEST,COUNT

這8條指令具有以下幾個共同點:
(1)DEST為操作物件,它可以是位元組或字運算元,可以是通用暫存器或儲存器運算元。

(2)COUNT用來決定移位/迴圈的位數,即確定移位的次數。

當移位次數為1時,使用常數1或暫存器CL。
當移位次數大於1時,必須使用暫存器CL。

(3)在執行移位時,根據指令不同,每移位一次,最高位(左移)或最低位(右移)都要送到進位標誌CF。

(4)前4條移位指令根據移位結束後修改標誌位CF、PF、ZF、SF和OF,而AF不確定。而後4條迴圈移位指令根據移位結束後的結果僅修改CF和OF

對溢位標誌位OF的影響:
移位次數為1時,移位前後運算元的符號位發生變化,則OF被置1,否則置0。移位次數大於1時,OF不確定。

指令SAL和SAR當移位次為n時,其作用相當於乘以2的n次方或除以2的n次方,因此被叫做算術移位指令。

為了保持其算術運算結果的正確性,移位後的結果不能發生溢位。

對於多位元組或多字資料的移位,需要使用帶進位迴圈移位指令。

四、處理器控制類指令

處理器控制類指令包括以下三種情況。

1.標誌位操作指令

它們都是無運算元指令,運算元隱含為標誌暫存器的某個標誌位。能直接操作的標誌位有CF、IF和DF。

(1)清除進位標誌

CLC ;置CF為0

(2)置1進位標誌

STC ;置CF為1

(3)進位標誌取反

CMC ;CF的值取反

(4)清除方向標誌

CLD;置DF為0

(5)置1方向標誌

STD;置DF為1

(6)清除中斷標誌

CLI;置IF為0

(7)置1中斷標誌

STI;置IF為1

2、與外部事件同步的指令

HLT ;暫停指令
WAIT ;等待指令
ESC ;外部協處理器指令字首
LOCK ;匯流排鎖定指令

3、空操作指令 NOP

執行一次NOP佔用CPU三個時鐘週期,它不改變任何暫存器或儲存單元內容,主要用於延時。


3.3 指令編碼

彙編:將組合語言程式轉換為機器語言程式的過程

彙編程式:在計算機中實現彙編過程的系統程式

Intel8086/8088彙編指令的編碼格式有四種基本格式。

1.雙運算元指令編碼格式
2.單運算元指令編碼格式
3.與AX或AL有關的指令編碼格式
4.其它指令編碼格式

一、雙運算元指令編碼格式

對於象MOV、ADD、AND等雙運算元指令,運算元可以是以下兩種情形:
一個運算元在暫存器中,另一運算元在暫存器或儲存器中。

目的運算元在暫存器或儲存器中,源運算元是立即數。

這類指令的機器目的碼長度為2~6個位元組

整個指令編碼可以包含4個部分,但其中某些部分在一些指令的編碼中可以沒有。

1.操作特徵部分

這部分為指令編碼的首位元組,它又分為以下三個段

(1)OPCODE:操作碼欄位

該欄位長度為6bit。它表示了該指令所執行的功能和兩個運算元的來源。

如果指令的源運算元是立即數,則需要使用指令編碼的第2位元組中REG欄位作輔助操作碼。

(2)方向欄位d

該欄位與第2部分定址特徵一起來決定源運算元和目的運算元的來源。

注意:當源運算元為立即數Imm時,d欄位無效,它被併入 操作碼欄位。

(3)字/位元組欄位W

當W=1時,表示兩運算元長度為字;當W=0時,表示兩運算元長度為位元組。

2.定址特徵部分

它與操作特徵部分的方向欄位d結合,指定兩個運算元分別使用什麼定址方式,及使用哪個暫存器。

它包括MOD、REG和R/M三個欄位,REG欄位確定一個運算元,而MOD和R/M欄位確定另一個運算元。

當d=1時,則目的運算元由REG欄位確定,而源運算元由MOD和R/M欄位確定。

當d=0時,則目的運算元由MOD和R/M欄位確定,而源運算元由REG欄位確定。

(1)REG欄位

由REG欄位確定的一個運算元是某一通用暫存器的內容,即使用的是暫存器定址方式。

第一部分中的W欄位決定運算元是字或是位元組。

(2)定址方式欄位MOD和暫存器/儲存器欄位R/M

這兩個欄位共同確定一個運算元。該運算元可以在暫存器中,也可以在儲存器中

MOD、R/M和W欄位共同確定運算元的定址方式和所使用的暫存器,如下表所示。
(https://qr.maitube.com/img/GDBHFA)
注意:在表中沒有使用BP作暫存器間接定址方式,如果在指令中使用了[BP],則將其彙編為[BP+0],即基址定址。

3.位移量部分

根據定址特徵中MOD和R/M欄位確定的有效地址計算方法,位移量可以是以下三種情況之一:
沒有位移量
1位元組位移量disp8
2位元組位移量disp16

4.立即數部分

如果指令的源運算元為立即數,則指令編碼中包含有該部分。它總是位於指令編碼的最後1~2位元組。

二、單運算元指令編碼格式

這種編碼格式適用於只有一個運算元的指令,如INC、DEC、移位/迴圈等指令。指令編碼為2~3位元組。

操作特徵部分:
包括OPCODE、V和W三個欄位,其中V欄位只有移位/迴圈指令中才有該欄位。其它指令中沒有該欄位。

V=0時,指令中使用常數1作為移位或迴圈次數。
V=1時,指令中使用暫存器CL作移位次數。

由於單運算元指令中只有一個運算元,因此定址特徵部分就不需要REG欄位,而該欄位被用作輔助操作碼。

三、與AX或AL有關的指令編碼格式

這種編碼格式用於隱含指定AX/AL作為一個運算元的雙運算元指令

採用這種編碼格式的指令,除一個運算元隱含指定為AX/AL外,另一個運算元可以是立即數或儲存單元。

立即數:則編碼中應有1~2位元組的立即數

儲存單元:只能使用直接定址方式,位移量由disp欄位給出.

四、其它指令編碼格式

除上述三種編碼格式外,還有一些指令的編碼格式更簡單。如標誌位操作指令、堆疊操作指令等。這些指令的編碼格式一般只有一個位元組。

例如 CLC清進位標誌,該指令的編碼只有一個位元組的操作碼

在有些單位元組指令的編碼中,將該位元組劃出部分位作為REG欄位。



第四章 組合語言程式格式

4.1 組合語言語句種類及其格式

組合語言的語句可以分為指令語句和偽指令語句

一、指令語句

每一條指令語句在彙編時都要產生一個可供CPU執行的機器目的碼,它又叫可執行語句。

指令語句的一般格式為:

標號:指令助記符-運算元(,);註釋

一條指令語句最多可以包含4個欄位

1.標號欄位

標號是可選欄位,它後面必須有“:”。標號是一條指令的符號地址,代表了該指令的第一個位元組存放地址。

標號一般放在一個程式段或子程式的入口處,控制程式的執行轉到該程式位置。

在轉移指令或子程式呼叫指令中,可直接引用這個標號。

2.指令助記符欄位

該欄位是一條指令的必選項,它表示這條語句要求CPU完成什麼具體操作,如MOV、ADD、SHL等。

有些指令還可以在指令助記符的前面加上字首,實現一定的附加操作。

3.運算元欄位

註釋欄位為可選項,該欄位以分號“;”開始。

它的作用是為閱讀程式的人加上一些說明性內容

註釋欄位不會產生機器目的碼,它不會影響程式和指令的功能。

註釋欄位可以是一條指令的後面部分,也可以是整個語句行。

二、偽指令語句

偽指令語句又叫命令語句。

偽指令本身並不產生對應的機器目的碼。它僅僅是告訴彙編程式對其後面的指令語句和偽指令語句的運算元應該如何處理。

一條偽指令語句可以包含四個欄位。如下所示:

符號名-偽指令符-運算元(,);註釋
1.符號名欄位

該欄位為可選項。根據偽指令的不同,符號名可以是常量名、變數名、過程名、結構名和記錄名等等。

一條偽指令語句的符號名可以作其它偽指令語句或指令語句的運算元,這時它表示一個常量或儲存器地址

注意:符號名後面沒有冒號“:”,這是與指令語句的重要區別。

2.偽指令符欄位

該欄位是偽指令語句的必選項,它規定了彙編程式所要完成的具體操作。

3.運算元欄位

該欄位是否需要,以及需要幾個是由偽指令符欄位來決定。

運算元可以是一個常數(二進位制、十進位制、十六進位制等)、字串、常量名、變數名、標號和一些專用符號(如BYTE、FAR、PARA等)。

4.註釋欄位

註釋欄位為可選項,該欄位必須以分號開始。其作用與指令語句的註釋欄位相同。

三、識別符號

指令語句中的標號和偽指令語句中符號名統稱為識別符號。識別符號是由若干個字元構成的。

識別符號構成規則:
1.字元的個數為1~31個;
2.第一個字元必須是字母、問號、@或下劃線“__”這4種字元之一;
3.從第二個字元開始,可以是字母、數字、@ 、“_”或問號“?”;
4.不能使用屬於系統專用的保留字。

保留字: CPU中各暫存器名(如AX、CS等),指令助記符(如MOV、ADD),偽指令符(如SEGMENT、DB)、表示式中的運算子(如GE、EQ)以及屬性操作符(如PTR、OFFSET等)


4.2 組合語言資料

資料是指令和偽指令語句中運算元的基本組成部分。一個數據由數值和屬性兩部分構成。

在說明資料時不僅要指定其數值,還需說明它的屬性,比如是位元組資料還是字資料。

在組合語言中常用的資料形式有:常數、變數和標號。

一、常數

常數在彙編期間其值已完全確定,並且在程式執行過程中,其值不會發生變化。

常數有以下幾種形式:
1.二進位制數:以字母B結尾,如01001001B
2.八進位制數:以字母O或Q結尾,如631Q 254O
3. 十進位制數:以字母D結尾,或者沒有結尾字母。如2007D、2007。
4. 十六進位制數:以字母H結尾,如3FEH,如果常數的第一個數字為字母,為了與識別符號加以區別,必須在其前面冠以數字“0”。
5. 實數。一般格式為:

±整數部分• 小數部分E ±指數部分(前兩部分合稱尾數)

彙編程式在彙編源程式時,可以把實數轉換為4位元組、8位元組或10位元組的二進位制數形式存放。

6.字串常數:用引號(單引號或雙引號)括起來的一個或多個字元,這些字元以它的ASCII碼值儲存在記憶體。

常數在程式中可以用在以下幾種情況:
(1)作指令語句的源運算元
(2)在指令語句的直接定址方式、變址(基址)定址方式或基址變址定址方式中作位移量。
(3)在資料定義偽指令中使用

二、變數

變數用來表示存放資料的儲存單元,這些資料在程式執行期間可以被改變。

程式中以變數名的形式來訪問變數,因此,可以認為變數名就是存放資料的儲存單元地址。

1.變數的定義與預置

定義變數就是給變數在記憶體中分配一定的儲存單元。也就是給這個儲存單元賦與一個符號名,即變數名,同時還要將這些儲存單元預置初值。

定義變數使用資料定義偽指令 DB、DW、DD、DQ和DT等。

變數定義的一般格式:

變數名(DB/DW/DD/DQ/DT)表示式1,表示式2......;定義位元組變數/定義字變數/定義4位元組變數/定義8位元組變數/定義10位元組變數

其中表達式1、表示式2是給儲存單元賦的初值

當變數被定義後,就具有了以下三個屬性:

(1)段屬性

它表示變數存放在哪一個邏輯段中。

(2)偏移量屬性(OFFSET)

它表示變數所在位置與段起始點之間的位元組數。

段屬性和偏移量屬性就構造了變數的邏輯地址

(3)型別屬性

它表示變數佔用儲存單元的位元組數。其中DB偽指令定義的變數為位元組,DW定義的變數為字,DD定義的為雙字(4位元組),DQ定義的為4字,DT定義的為5字。

在變數的定義語句中,給變數賦初值的表示式可以使用下面4種形式:

(1)數值表示式
(2)?表示式

不帶引號的問號“?”表示可以預置任意內容。

(3)字串表示式

對於DB偽指令,字串為用引號括起來的不超過255個字元。給每一個字元分配一個位元組單元。字串按從左到右,將字元的ASCII編碼值以地址遞增的排列順序依次存放。

對於DW偽指令可以給兩個字元組成的字串分配兩個位元組儲存單元。
注意:兩個字元的存放順序是前一個字元放在高地址,後一字元放低地址單元。

對於DD偽指令,只能給兩個字元組成的字串分配4個位元組單元。
兩個字元存放在較低地址的兩個位元組單元中。存放順序與DW偽指令相同,而較高地址的兩個位元組單元存放0。

注意:DW和DD偽指令不能用兩個以上字元構成的字串賦初值,否則將出錯。

(4)DUP表示式

DUP稱為重複資料操作符。
使用DUP表示式的一般格式為:

變數名(DB/DW/DD) 表示式1 DUP (表示式2)

其中:表示式1是重複的次數,表示式2是重複的內容。

DUP還可以巢狀使用,即表示式2又可以是一個帶DUP的表示式。

2.變數的使用

(1)在指令語句中引

在指令語句中直接引用變數名就是對其儲存單元的內容進行存取

當變量出現在變址(基址)定址或基址變址定址的運算元中時表示取用該變數的偏移量。

(2)在偽指令語句中引用

三、標號

標號寫在一條指令的前面,它就是該指令在記憶體的存放地址的符號表示,也就是指令地址的別名。

標號主要用在程式中需要改變程式的執行順序時,用來標記轉移的目的地,即作轉移指令的運算元

每個標號具有三屬性:

(1)段屬性(SEG)

它表示該標號所代表的地址在哪個邏輯段中,即段基值。

(2)偏移量屬性(OFFSET)

它表示該標號所代表的地址在段內與段起點間的位元組數,即地址的偏移量。

(3)距離屬性(也叫型別屬性)

它表示該標號可以被段內還是段間的指令呼叫。

NEAR(近):該標號只能作段內轉移,也就是說只能是與該標號所指指令同在一個邏輯段的轉移指令和呼叫指令才能使用它。

FAR(遠):該標號可以被非本段的轉移和呼叫指令使用。標號的距離屬性可以有兩種方法來指定:
a.隱含方式
當標號加在指令語句前面時,它隱含為NEAR屬性。

b.用LABEL偽指令給標號指定距離屬性
型別為NEAR或FAR。該語句應與指令語句連用。

SUB1_FAR與SUB1兩個標號具有相同的段屬性和偏移量屬性,即相同的邏輯地址。被轉移指令或呼叫指令訪問時,是指同一個入口地址,但SUB1-FAR可以被其它段的指令呼叫。

LABEL偽指令還可以用來定義變數的屬性,即改變一個變數的屬性,如把字變數的高低位元組作為位元組變數來處理。


4.3 符號定義語句

一、等值語句

語句格式:符號名 EQU 表示式

功能:用符號名來表示EQU右邊的表示式。後面的程式中一旦出現該符號名,彙編程式將把它替換成該表示式。

表示式可以是任何形式,常見的有以下幾種情況。
1.常數或數值表示式

COUNT EQU 5
NUM EQU COUNT+5

2.地址表示式

ADR1 EQU DS:[BP+14]

ADR1被定義為在DS資料段中以BP作基址定址的一個儲存單元。

3.變數、暫存器名或指令助記符

CREG EQU CX;在後面的程式使用CREG就是使用CX
CBD EQU DAA;DAA為十進位制調整指令。

二、等號語句

格式:符號名=表示式

等號語句與等值語句具有相同的作用。但等號語句可以對一個符號進行多次定義。

等號語句不能為助記符定義別名

注意:等值語句與等號語句都不會為符號分配儲存單元。因此所定義的符號沒有段、偏移量和型別等屬性。


4.4 表示式與運算子

表示式是指令或偽指令語句運算元的常見形式。它由常數、變數、標號等通過操作運算子連線而成。

表示式是指令或偽指令語句運算元的常見形式。它由常數、變數、標號等通過操作運算子連線而成。

8086/8088巨集組合語言中的操作運算子非常豐富,可以分為以下五類。

一、算術運算子

+、—、*、 / 、MOD、SHL、SHR、[ ]
1.運算子“+”和“-”也可作單目運算子,表示數的正負。
2.使用“+”、“-”、“*”、和“/”運算子時,參加運算的數和運算結果都是整數。
3.“/”運算為取商的整數部分,而“MOD”運算取除法運算的餘數。
4. “SHR ”和“SHL ”為邏輯移位運算子

“SHR”為右移,左邊移出來的空位用0補入。
“SHL”為左移,右邊移出來的空位用0補入。

注意:移位運算子與移位指令區別。 移位運算子的操作物件是某一具體的數(常數),在彙編時完成移位操作。而移位指令是對一個暫存器或儲存單元內容在程式執行時執行移位操作。

5.下標運算子“[ ]”具有相加的作用

一般使用格式: 表示式1 [表示式2]

作用:將表示式1與表示式2的值相加後形成一個儲存器運算元的地址。

二、邏輯運算子

邏輯運算子有NOT、AND、OR和XOR等四個,它們執行的都是按位邏輯運算。

三、關係運算符

關係運算符包括:EQ(等於)、NE(不等於)、LT(小於)、 LE(小於等於)、GT(大於)、 GE(大於等於)

關係運算符用來比較兩個表示式的大小。關係運算符比較的兩個表示式必須同為常數或同一邏輯段中的變數。

如果是常量的比較,則按無符號數進行比較;如果是變數的比較,則比較它們的偏移量的大小。

關係運算的結果只能是“真”(全1)或“假”(全0)

四、數值返回運算子

該類運算子有5個,它們將變數或標號的某些特徵值或儲存單元地址的一部分提取出來。

1.SEG運算子

作用:取變數或標號所在段的段基值。

2.OFFSET運算子

該運算子的作用是取變數或標號在段內的偏移量。

3.TYPE運算子

作用:取變數或標號的型別屬性,並用數字形式表示。對變數來說就是取它的位元組長度。

4.LENGTH運算子

該運算子用於取變數的長度。

如果變數是用重複資料操作符DUP說明的,則LENGTH運算取外層DUP給定的值。
如果沒有用DUP說明,則LENGTH運算返回值總是1。

5.SIZE運算子

該運算子只能作用於變數,SIZE取值等於LENGTH和TYPE兩個運算子返回值的乘積。

五、屬性修改運算子

1.PTR運算子

使用格式:型別 PTR 地址表示式

作用: 將地址表示式所指定的標號、變數或用其它形式表示的儲存器地址的型別屬性修改為 “型別”所指的值。

型別可以是BYTE、WORD、DWORD、NEAR和FAR。這種修改是臨時的,只在含有該運算子的語句內有效。

2.HIGH/LOW運算子

使用格式:
HIGH 表示式
LOW 表示式
這兩個運算子用來將表示式的值分離出高位元組和低位元組。

如果表示式為一個常量,則將其分離成高8位和低8位;如果表示式是一個地址(段基值或偏移量)時,則分離出它的高位元組和低位元組。

注意:HIGH/LOW運算子不能用來分離一個變數、暫存器或儲存器單元的高位元組與低位元組。

3、THIS運算子

THIS運算子一般與等值運算子EQU連用,用來定義一個變數或標號的型別屬性。所定義的變數或標號的段基值和偏移量與緊跟其後的變數或標號相同。

六、運算子的優先順序

https://qr.maitube.com/img/GDBHFB
先執行優先級別高的運算,再算較低級別運算;
相同優先級別的操作,按照在表示式中的順序,從左到右進行;
可以用圓括號改變運算的順序。


4.5 程式的段結構

8086/8088在管理記憶體時,按照邏輯段進行劃分,不同的邏輯段可以用來存放不同目的的資料。在程式中使用四個段暫存器CS,DS,ES和SS來訪問它們。

在源程式設計時,使用偽指令來定義和使用這些邏輯段。

一、段定義偽指令

一般格式:

段名 SEGMENT [定位型別] [組合型別] [‘類別名']+本段語句序列+段名 ENDS
1、段名

段名是由使用者自己任意選定的,符合識別符號定義規則的一個名稱。

最好選用與該邏輯段用途相關的名稱。如第一個資料段為DATA1,第二個資料為DATA2等。

一個段的開始與結尾用的段名必須一致。

2、定位型別

定位型別用於決定段的起始邊界,即第一個可存放資料的位置(不是段基址)。它可以有4種取值。

(1)PAGE:表示該段從一個頁面的邊界開始

由於一個頁面為256個位元組,並且頁面編號從0開始,因此,PAGE定位型別的段起始地址的最後8位二進位制數一定為0,即以00H結尾的地址。

(2)PARA:表示該段從一個小節的邊界開始

如果使用者未選定位型別,則預設為PARA。

(3)WORD:表示該段從一個偶數字節地址開始,即段起始單元地址的最後一位二進位制數一定是0。
(4)BYTE:表示該段起始單元地址可以是任一地址值。

注意:定位型別為PAGE和PARA時,段起始地址與段基址相同。定位型別為WORD和BYTE時,段起始地址與段基址可能不同。

3、組合型別

組合型別說明符用來指定段與段之間的連線關係和定位。它有六種取值選擇。

(1)若未指定組合型別,表示本段與其它段無連線關係。在裝入記憶體時,本段有自己的物理段,因此有自己的段基址
(2)PUBLIC:在滿足定位型別的前提下,將與該段同名的段鄰接在一起,形成一個新的邏輯段,共用一個段基址。段內的所有偏移量調整為相對於新邏輯段的段基址。
(3)COMMON:產生一個覆蓋段。在多個模組連線時,把該段與其它也用COMMON說明的同名段置成相同的段基址,這樣可達到共享同一儲存區。共享儲存區的長度由同名段中最大的段確定。
(4)STACK:把所有同名段連線成一個連續段,且系統自動對SS段暫存器初始化為該連續段的段基址。並初始化堆疊指標SP。

使用者程式中應至少有一個段用STACK說明,否則需要使用者程式自己初始化SS和SP。

(5)AT表示式:表示本段可定位在表示式所指示的小節邊界上。表示式的值也就是段基值。
(6)MEMORY:表示本段在儲存器中應定位在所有其它段之後的最高地址上。如果有多個用MEMORY說明的段,則只處理第一個用MEMORY說明的段。其餘的被視為COMMON
4.類別名

類別名必須用單引號引起來。所用字串可任意選定,但它不能使用程式中的標號、變數名或其它定義的符號。

類別名必須用單引號引起來。所用字串可任意選定,但它不能使用程式中的標號、變數名或其它定義的符號。
例:
STACK1 SEGMENT PARA STACK 'STACK0'
.....
STACK1 ENDS
DATA1 SEGMENT PARA 'DATA'
......
DATA1 ENDS
STACK2 SEGMENT PARA 'STACK0'
......
STACK2 ENDS
CODE SEGMENT PARA MEMORY
ASSUME CS:CODE,DS:DATA1,SS:STACK1
MAIN: ......
......
CODE ENDS
DATA2 SEGMENT BYTE 'DATA'
......
DATA2 ENDS
END MAIN
在進行程式設計時,如果程式不大,一般只需要定義三個段就可以了。

二、段定址偽指令

段定址偽指令ASSUME的作用是告訴彙編程式,在處理源程式時,定義的段與哪個暫存器關聯。

ASSUME並不設定各個段暫存器的具體內容,段暫存器的值是在程式執行時設定的。

一般格式:
ASSUME並不設定各個段暫存器的具體內容,段暫存器的值是在程式執行時設定的。

其中段暫存器名為CS,DS,ES和SS四個之一,段名是用SEGMENT/ENDS偽指令定義的段名。

在一個程式碼段中可以有幾條ASSUME偽指令,對於前面的設定,可以用ASSUME改變原來的設定。

在一個程式碼段中可以有幾條ASSUME偽指令,對於前面的設定,可以用ASSUME改變原來的設定。

可以使用關鍵字NOTHING將前面的設定刪除。

ASSUME ES:NOTHING;刪除前面對ES與某個定義段的關聯
ASSUME NOTHING;刪除全部4個段暫存器的設定

三、段暫存器的裝入

段暫存器的初值(段基值)裝入需要用程式的方法來實現。四個段暫存器的裝入方法略有不同。

1、DS和ES的裝入

在程式中,使用資料傳送語句來實現對DS和ES的裝入。
為了改正上述程式中的錯誤,可以在變數DBYTE2前加一個段字首說明即可。即:

MOV ES:DBYTE2[2], AL
2、SS的裝入

SS的裝入有兩種方法
(1)在段定義偽指令的組合型別項中,使用STACK引數,並在段定址偽指令ASSUME語句中把該段與SS段暫存器關聯。

(2)如果在段定義偽指令的組合型別中,未使用STACK引數,或者是在程式中要調換到另一個堆疊,這時,可以使用類似於DS和ES的裝入方法。

3、CS的裝入

CPU在執行指令之前根據CS和IP的內容來從記憶體中提取指令,即必須在程式執行之前裝入CS和IP的值。因此,CS和IP的初始值就不能用可執行語句來裝入。

裝入CS和IP一般有下面兩種情況。

(1)由系統軟體按照結束偽指令指定的地址裝入初始的CS和IP

任何一個源程式都必須以END偽指令來結束。

其格式為:END 起始地址

起始地址可以是一個標號或表示式,它與程式中第一條指令語句前所加的標號必須一致。

END偽指令的作用是標識源程式結束和指定程式執行時的起始地址。當程式被裝入記憶體時,系統軟體根據起始地址的段基值和偏移量分別被裝入CS和IP中。

(2)在程式執行期間,當執行某些指令時,CPU自動修改CS和IP,使它們指向新的程式碼段。

4.6 過程定義偽指令(PROC/ENDP)

在程式設計過程中,常常將具有一定功能的程式段設計成一個子程式。在MASM巨集彙編程式中,用過程(PROCEDURE)來構造子程式。

過程名是子程式的名稱,它被用作過程呼叫指令CALL的目的運算元。它類同一個標號的作用。具有段、偏移量和距離三個屬性。而距離屬性使用NEAR和FAR來指定,若沒有指定,則隱含為NEAR。

NEAR過程只能被本段指令呼叫,而FAR過程可以供其它段的指令呼叫。

每一個過程中必須包含有返回指令RET,其作用是控制CPU從子程式中返回到呼叫該過程的主程式。


4.7 當前位置計數器$與定位偽指令ORG(Origin)

彙編程式在彙編源程式時,每遇到一個邏輯段,就要為其設定一個位置計數器,它用來記錄該邏輯段中定義的每一個數據或每一條指令在邏輯段中的相對位置。

在源程式中,使用符號\(來表示位置計數器的當前值。因此,\)被稱為當前計數器。它位於不同的位置具有不同的值。

位置計數器$在使用上完全類似變數的使用

定位偽指令ORG--用來改變位置計數器的值。

格式:ORG 數值表示式

作用:將數值表示式的值賦給當前位置計數器$ 。ORG語句為其後的資料或指令設定起始偏移量。

表示式的值必須為正值。表示式中也可以包含有當前位置計數器的現行值$。


4.8 標題偽指令TITLE

語句格式:TITLE 標題名

作用:給所在程式指定一個標題。以便在列表檔案的每一頁的第一行都顯示這個標題。其中標題是使用者任意選用的字串,字元個數不能超過60。


4.9 從程式返回作業系統的方法

為了使程式執行結束後,能夠正確地返回到作業系統,需要在程式中加上一些必要的語句。一般有以下兩種方法。

一、使用程式段字首PSP(Program Segment Prefix)實現返回

DOS系統將一個.EXE檔案(可執行檔案)裝入記憶體時,在該檔案的前面生成一個程式段字首PSP,其長度為100H位元組。同時讓DS和ES都指向PSP的開始,而CS指向該程式的程式碼段,即第一條可執行指令。

為了使程式執行完後,正確返回DOS,需要做以下三個操作:

  1. 將使用者程式編製成一個過程,型別為FAR;
  2. 將PSP的起始邏輯地址壓棧,即將INT 20H指令的地址壓棧;
  3. 在使用者程式結尾處,使用一條RET指令。執行該指令將使儲存在堆疊中的PSP的起始地址彈出到CS和IP中。

程式結構:
DATA SEGMENT

DATA ENDS
STACK1 SEGMENT STACK

STACK1 ENDS
CODE SEGMENT
BEGIN PROC FAR
ASSUME CS:CODE,DS:DATA,SS:STACK1
PUSH DS
MOV AX,0
PUSH AX
MOV AX,DATA
MOV DS,AX

RET
BEGIN ENDP
CODE ENDS
END BEGIN

二、使用DOS系統功能呼叫實現返回

執行DOS功能呼叫4CH,也可以控制使用者程式結束,並返回DOS作業系統。
在程式結束時,使用兩條指令:

MOV AH,4CH
INT 21H

程式碼段的結構為:
CODE SEGMENT
ASSUME CS:CODE......
BEGIN:MOV AX,DATA
MOV DS,AX

MOV AH,4CH
INT 21H
CODE ENDS
END BEGIN