20192409潘則宇組合語言程式設計前四章學習總結
組合語言程式設計
概念
計算機程式設計語言可以分為機器語言、高階語言和組合語言三類。
機器語言:機器語言就是把控制計算機的命令和各種資料直接用二進位制數碼錶示的一種程式設計語言。(優點:執行速度快,程式長度短;缺點:不便於記憶,難於閱讀)
高階語言:高階語言將計算機內部的操作細節遮蔽起來,使用者不需要知道計算機內部資料的傳送和處理的細節,使用類似於自然語言的一些語句來編制程式,完成指定的任務。(優點:程式設計簡單;缺點:程式效率較機器語言低)
組合語言:為了方便記憶和閱讀,使用字母和符號來被表示機器語言的命令,用十進位制數和十六進位制數來表示資料,這樣的計算機程式設計語言就稱為組合語言。
組合語言程式與機器語言程式的關係:一條組合語言的語句與一條機器語言的指令對應,組合語言程式與機器語言程式效率相同。
進位計數制及其相互轉換
進位計數制: 使用一定個數的數碼的組合來表示數字,這種表示方式稱為進位計數制。根據所使用的數碼的個數,就產生了不同的進位計數制。
- 將各個位置上所表示的基本數值稱為位權,簡稱權
- 每個數位上所能使用的不同數碼的個數稱為基數
常用進位計數制:
B(Binary)——二進位制數
O(Octal或Q)——八進位制數
D(Decimal)——十進位制數
H(Hexadecimal)——十六進位制數
各種數值之間的相互轉換:
1.十進位制整數轉換為二進位制數
(1)減權定位法
(2)除基取餘法
2.十進位制小數轉換為二進位制數
(1)減權定位法
(2)乘積取整法
3.二進位制整數轉換為十進位制數
(1)按權相加法
(2)逐次乘積相加法
4.二進位制小數轉換為十進位制數
(1)按權相加法
(2)逐次除基相加法
5.二進位制與八進位制和十六進位制之間的轉換
帶符號數的表示
- 用“+”或“-”表示正負的數叫真值
- 用“0”或“1”表示正負的數叫機器數
帶符號的機器數可以用原碼、補碼、反碼三種不同碼制來表示。
原碼錶示:二進位制數的最高位表示符號,0表示正,1表示負。數值部分用二進位制數絕對值表示。
補碼錶示:帶符號數X的補碼錶示定義為:
[X]補=M+X(Mod M)
其中模數M根據機器數位數而定,如位數為8則M=28。
用補碼錶示的機器數,符號位仍然表示數的符號:0為正,1為負。對於正數,補碼與原碼相同,對於負數需要進行變換(符號位不變,各位取反,末位加1)。
補碼的加減運算:規則為:
[X+Y]補=[X]補+[Y]補
[X-Y]補=[X]補-[Y]補=[X]補+[-Y]補
字元的表示
在計算機內部,各種字元(字母、符號、數字碼)都是按照一定方式編寫成二進位制資訊。不同的計算機以及不同的場合所採用的編碼方式不同。目前最廣泛採用的是ASCII碼。
非列印ASCII碼(33個):用於控制操作,如BEL(響鈴,07H),DEL(刪除,7FH),CR(回車,0DH),LF(換行,0AH)
可列印ASCII碼(95個):如數字符0~9,大小寫字母等
基本邏輯運算
“與”運算(AND):“與”運算也叫邏輯乘,常用∧或·表示,即F=A∧B或F=A·B。
“與”運算是指僅當邏輯變數A和B都是1時,運算結果F才為1;其他情況F為0。
“或”運算(OR):“或”運算也叫邏輯加,常用∨或+表示,即F=A∨B或F=A+B。
“或”運算是指當邏輯變數A和B中,至少有一個為1時,結果F為1;其他情況F為0。
“非”運算:對邏輯變數取相反的一個邏輯值。
“異或”運算(XOR):通常用⨁表示,即F=A⨁B。
“異或”運算是指當A和B相同時(同時為1或者同時為0),運算結果F為0,而不同時,F為1。
IBM-PC微機基本結構
微機結構
一般計算機應包含五大部件:運算器、控制器、儲存器、輸入裝置和輸出裝置。
由於微機的主要特點是其體積很小,因此在系統設計上就有一些特殊考慮。
- 將運算器和控制器兩大部件整合在一個積體電路晶片上,稱為中央處理器,簡稱CPU,也叫微處理器。
- 系統採用匯流排結構,具有較大的靈活性和擴充套件性。
1.中央處理器CPU
微型計算機中的中央處理器也叫微處理器。它包括運算器和控制器。
功能:分析從主儲存器取來的各條指令的功能,控制計算機各部件完成指定功能的各項操作。
2.主儲存器
主儲存器是用來存放程式和資料的部件,它由若干個儲存單元構成。
儲存單元的多少表示儲存器的容量。每個儲存單元使用一個唯一的編號來標識,稱為儲存單元的地址。
對每個儲存單元內容的存和取是按照地址進行訪問的。
3.輸入輸出裝置及介面
輸入裝置將外部資訊(程式、資料和命令)送入計算機。包括鍵盤、滑鼠等。
輸出裝置將計算機處理後的結果轉換為人或其它系統能識別的資訊形式向外輸出。如顯示器、印表機等。
有的裝置既具有輸入功能又具有輸出功能。如磁碟、磁帶、觸控顯示屏等。
4.系統匯流排
系統匯流排將CPU、儲存器和I/O裝置連線起來,實現各大部件之間的各種資訊傳送。
系統匯流排包括地址匯流排、資料匯流排和控制匯流排三組。它們分別用於傳送不同的資訊。
Intel8086/8088 CPU的功能結構
組合語言程式是由一系列的指令(指令序列)構成。
指令是構成組合語言程式的最基本單位,就像高階語言中的語句。
CPU執行指令序列就是重複執行以下兩個步驟:
- 從儲存器中取指令
- 執行指令規定的操作
這兩個步驟的執行又分為序列方式和指令流水線方式。
1.序列方式
特點:
(1)當CPU不在指令執行階段,不需要佔用系統匯流排,但此時匯流排也不工作,因此係統匯流排的空閒時間比較多。
(2)在從儲存器取指令、取資料或存資料的時候,匯流排處於忙狀態,其所佔用的時間也較長。而CPU卻只需要花很短的時間去處理,因此大部分時間處於閒置狀態。
2.指令流水線方式
採用指令流水線方式的計算機具有較高的工作效率。CPU內部採用了一種先進的指令流水線結構,這種結構可以有效而充分地利用各主要硬體資源。
(1)執行單元EU
EU的主要任務是分析與執行指令,包括:
- 從指令佇列中取出指令程式碼,由控制器譯碼後產生相應的控制訊號,控制各部件完成指令規定的操作。
- 對運算元執行各種指定的算數或邏輯運算。
- 向匯流排介面單元BIU傳送訪問主存或I/O的命令,並提供相應的地址和傳送的資料。
(2)匯流排介面單元BIU
BIU負責CPU與儲存器、I/O的資訊傳送。具體包括:
- 取指令——根據CS暫存器和指令指標IP形成20位的實體地址,從相應的儲存器單元中取出指令,暫存到指令佇列中,等待EU取走並執行。
- 存取資料——在EU執行指令的過程中,需要與儲存器或I/O埠傳送資料時,由EU提供的資料和地址,結合段暫存器,通過外部匯流排與儲存器或I/O進行資料的存取。
Intel086/8088 CPU暫存器結構及其用途
通用暫存器:累加器、基址暫存器、計數暫存器、資料暫存器、堆疊暫存器、基址指標、源變址暫存器、目的變址暫存器;
控制暫存器:指令指標、標誌暫存器;
段暫存器:程式碼段暫存器、資料段暫存器、附加段暫存器、堆疊段暫存器。
1.通用暫存器
(1)資料暫存器
它包括AX、BX、CX、DX四個暫存器。它們中的每一個既可以是16位暫存器,也可以分成兩個8位暫存器使用。即可以當作8個獨立的8位暫存器使用。
資料暫存器既可以用來存放參加運算的運算元,也可以存放運算的結果。
(2)指標暫存器
指標暫存器有堆疊指標SP和基址指標BP。
它們一般用來存放16位地址,在形成20位的實體地址時常被作為偏移量使用。
- SP指標——在進行堆疊操作時,被隱含使用,被用來指向堆疊頂部單元。
- BP指標——被用來指向堆疊段內某一儲存單元。
(3)變址暫存器
有兩個16位的變址暫存器SI和DI,一般被用來作地址指標。
- SI——源變址暫存器
- DI——目的變址暫存器
2.段暫存器
8086/8088 CPU在使用暫存器的時候,將它劃分成若干段。
每個段用來存放不同的內容,如程式程式碼、資料等等。
每個儲存段用一個段儲存器來指明該段的起始位置(也叫段基址)。
CPU在訪問儲存器時必須指明兩個內容:
(1)所訪問的儲存單元屬於哪個段,即指明使用的段暫存器。
(2)該儲存單元與段起始地址(段基址)的相距多少,即偏移量。
3.指令指標IP
CPU在從儲存器取指令時,以段暫存器CS作為程式碼段的基址指標,以IP的內容作為偏移量,共同形成一條指令的存放地址。
當CPU從記憶體中取出一條指令後,IP內容自動修改為指向下一條指令。
注意:IP的內容不能被直接訪問,既不能用指令去讀IP的值,也不能用指令給它賦值。但是可以通過某些指令的執行自動修改IP的內容。
- 轉移指令將指令中的目的地址的偏移量送入IP
- 子程式呼叫指令CALL,將IP原有內容自動壓入堆疊,而將子程式的入口地址偏移量自動送入IP,而返回指令RET,又自動從堆疊中彈回原有IP的內容。
4.標誌暫存器
標誌暫存器是用來反映CPU在程式執行時的某些狀態,如是否有進位、奇偶性、結果的符號、結果是否為零等等。
8086/8088 CPU中的標誌暫存器的長度為16位,但只定義了其中的9位。
標誌位分為:
- 狀態標誌:CF、PF、AF、ZF、SF、OF
- 控制標誌:TF、DF、IF
(1)進位標誌位CF
在進行算數運算時,若最高位(對字操作是第15位,位元組操作是第7位)產生進位或借位時CF被自動置“1”,否則置“0”。
在移位類指令中,CF也被用來存放從最高位(左移時)或最低位(右移時)移出的數值(0或1)。
(2)奇偶標誌位PF
當指令操作結果的低8位中含有1的個數為偶數時,則PF被置“1”,否則PF被置“0”。
注意:PF只反映操作結果的低8位的奇偶性,與指令運算元的長度無關。
(3)輔助進位標誌位AF
在進行算術運算時,若低位元組的低四位向高四位產生進位或錯位,即第3位產生進位或借位時,AF位被置“1”,否則置“0”。AF標誌位用於十進位制運算的調整。
注意:AF只反映運算結果低八位,與運算元長度無關。
(4)零值標誌位ZF
若運算結果各位全為0,則ZF被置“1”,否則置“0”。
(5)符號標誌位SF
將運算結果視為帶符號數,當運算結果為負數的時候SF被置“1”,為正數時,則置“0”。
(6)溢位標誌位OF
當運算結果超過機器補碼所能表示數的範圍時,則OF置“1”,否則置“0”。
注意:溢位和進位是兩個完全不同的概念,不能相互混淆。
(7)單步標誌位TF
單步標誌也叫跟蹤位,該標誌為控制標誌位。單步標誌位供除錯程式使用。
當TF位被置“1”時,沒執行一條指令後,CPU暫停執行,即產生單步中斷。
(8)中斷允許標誌位IF
該標誌位為控制標誌位。當IF被置“1”時,CPU可以響應可遮蔽中斷,否則不允許響應可遮蔽中斷。
(9)方向標誌位DF
DF也是控制標誌位。它被用來規定串操作指令的增減方向。
當DF=0時,串操作指令自動使變址暫存器(SI和DI)的內容遞增。當DF=1時,串操作指令自動使變址暫存器內容遞減。
儲存器組織結構
1.暫存器的組成
(1)暫存器是由若干個儲存單元構成
儲存單元的多少就表示了儲存器的容量。
(2)每個儲存單元存放相同長度的二進位制數
一個儲存單元的長度一般為8位二進位制數,即一個位元組。
(3)每個儲存單元有一個唯一的地址編號——地址
8086/8088 CPu有20根地址線,即它可以產生20位的地址碼,它的儲存器定址能力為22,即1兆位元組空間
(4)任何兩個相鄰位元組單元就構成一個字單元
一個字儲存單元(WORD)的長度為16位二進位制數,即兩個位元組。字單元的地址為兩個位元組單元中較小地址位元組單元的地址。
16位長資料的存放規則是低8位放在較低地址位元組單元中,高8位放在較高地址位元組單元中。
(5)在定義一個地址時必須指出是位元組或字型別屬性
2.儲存器的段結構
由於8086/8088可定址的儲存空間為1MB,需要提供20位長的地址碼,而CPU內部的暫存器長度只有16位,能夠直接訪問的最大地址空間是64KB。
特點:
(1)8086/8088 CPU將1MB的儲存空間劃分成若干段,每個段最大長度為64K(65536)個位元組單元組成。
(2)每個段的基址(段基址)必須是一個小節的首址。
(3)邏輯段在物理儲存器中可以是鄰接的、間隔的、部分重疊的和完全重疊的等4種情況。
(4)在任一時刻,一個程式只能訪問4個當前段中的內容。
4個段分別是程式碼段、資料段、堆疊段和附加段,稱為當前段。4個段暫存器CS、DS、SS、ES分別儲存了它們段基址的高16位地址,稱為段基值。段基址的最低4位為0。(小節首址的低4位為全0)
3.邏輯地址與實體地址及對應關係
(1)實體地址
在1MB的儲存空間中,每個儲存單元的實體地址是唯一的,它就是該儲存單元的20位地址。
(2)邏輯地址
一個邏輯地址包括兩個部分:段基值和偏移量
- 段基值:存放在某一個段暫存器中,是一個邏輯段的起始單元地址(段基址)的高16位。
- 偏移量:表示某個儲存單元與它所在段的段基址之間的位元組距離。
(3)邏輯地址轉換為實體地址
當CPU要範圍跟儲存器時,需要由匯流排介面單元BIU將邏輯地址轉換為實體地址。
轉換方法:將邏輯地址的段基值左移4位,形成20位的段基址(低位為0)然後與16位的偏移量相加,,結果即為20位的實體地址。
(4)邏輯地址的來源
在程式的執行過程中,CPU根據不同操作型別訪問儲存器,其邏輯地址中段基值和偏移量的來源是不一樣的。
- 取指令——段基值隱含來源CS——偏移量IP
- 堆疊操作——段基值隱含來源SS——偏移量SP
- 取源串——段基值隱含來源DS允許替代來源CS、SS、ES——偏移量SI
- 存目的串——段基值隱含來源ES——偏移量DI
- 以BP作基址——段基值隱含來源SS允許替代來源CS、DS、ES——偏移量有效地址EA
- 存取一般變數——段基值隱含來源DS允許替代來源CS、SS、ES——偏移量有效地址EA
說明:允許替代來源也叫做段超越,它表示了段基值除使用隱含的段暫存器外是否可以指定其它段暫存器來提供;有效地址EA,它表示根據指令所採用的定址方式計算出來的段內偏移量。
堆疊及其操作方法
堆疊是一個特定的儲存區,訪問該儲存區一般需要按照專門的規則進行操作。
堆疊的用途:主要用於暫存資料以及在過程呼叫或處理中斷時儲存斷點資訊。
1.堆疊的構造
堆疊一般分為專用堆疊儲存器和軟體堆疊
- 專用堆疊儲存器:按堆疊的工作方式專門設計的儲存器
- 軟體堆疊:由程式設計人員用軟體在記憶體中劃出的一塊儲存區域作為堆疊來使用
堆疊的一端是固定的,稱為棧底。棧底是堆疊儲存區最大的地址單元。
另一端是浮動的,稱為棧頂。棧頂是最後存入資訊的儲存單元,隨著堆疊中存放資訊的多少而改變。
為了指示現在堆疊中存放資料位置,通常設定一個暫存器來指示棧頂位置。其內容就像一個指標一樣,因此被稱為堆疊指標SP。
在堆疊中存取資料的規則是“後進先出FILO”。
2.8086/8088堆疊的組織
在8086/8088微機中堆疊是由堆疊段暫存器SS指示的一段儲存區。
(1)頂由堆疊指標SP指示。當SP內容為最大(初始)值時,表示堆疊為空,而當SP=0時,表示堆疊全滿;
(2)當SP被初始化時,指向棧底+2單元,其值就是堆疊的長度。由於SP是16位暫存器,因此堆疊長度小於等於64K位元組;
(3)資料在堆疊中的存放格式是:以字為單位存放,資料的低8位放在較低地址單元,高8位放在較高地址單元。
3.堆疊操作
(1)設定堆疊
設定堆疊主要是對堆疊暫存器SS和堆疊指標SP賦值。
(2)進棧PUSH
進棧就是把資料存入堆疊。由指令PUSH或者由機器自動實現,可以將通用暫存器、段暫存器或字儲存單元的內容壓入堆疊頂部。
(3)出棧POP
出棧操作由POP指令或機器自動實現,它從堆疊頂部彈出一個字到通用暫存器、段暫存器或字儲存單元。
定址方式與指令系統
定址方式
一條指令通常由操作碼和運算元構成。
- 操作碼:表示該指令完成的具體操作,如加法、減法、乘法、移位等等。在組合語言中使用一定的符號來表示,稱為助記符。如ADD、PUSH、POP、MOV等。
- 運算元:表示該指令的操作物件。如移位操作的被移位數,加法操作的加數等等。
定址方式:尋找指令中所需運算元的各種方法,也就是提供指令中運算元的存放資訊的方式。
各指令中提供運算元的方法有以下四種:
- 立即數運算元——運算元在指令程式碼中提供
- 暫存器運算元——運算元在CPU的通用暫存器或段暫存器中
- 儲存器運算元——運算元在記憶體的儲存單元中
- I/O埠運算元——運算元在輸入/輸出介面的暫存器中
(1)立即數定址
立即數定址方式的指令中,所需運算元直接包含在指令程式碼中,這種運算元稱為立即數。
注意:立即數只能作為源運算元,而不能作為目的運算元。
(2)暫存器定址
暫存器定址方式是指指令中所需的運算元在CPU的某個暫存器中。暫存器可以是8位或16位通用暫存器,或者是段暫存器。如:AH、AL、AX、CX、DS、ES等。
(3)直接定址
在直接定址方式的指令中,運算元的有效地址EA只有位移量地址分量。
在組合語言源程式中,直接定址方式用符號或常數來表示。
注意:用常數表示時,必須用方括號括起來。段暫存器不能省略。
(4)暫存器間接定址
運算元有效地址EA直接從基址暫存器(BX或BP)或變址暫存器(SI或DI)中獲得。
暫存器間接定址就是事先將偏移量存放在某個暫存器(BX、BP、SI或DI)中,這些暫存器就如同一個地址指標。
在程式執行期間,只要對暫存器內容進行修改,就可以實現用同一條指令實現對不同儲存單元進行操作。
指示儲存器所在段的段暫存器可以省略,當指令中使用的是BP暫存器,則隱含表示使用SS段暫存器,其餘情況則隱含使用DS段暫存器。
(5)基址定址和變址定址
運算元的有效地址EA等於基地址分量或變址分量加上指令中給出的位移量。
指令中使用BX或BP時為基址定址。指令中使用SI或DI時為變址定址。
注意:當位移量為常數時,不能加方括號。
(6)基址變址定址
運算元的有效地址是三個地址分量之和,即:EA=基址+變址+位移量。
當基址選用BX時隱含使用段暫存器DS,而選用BP時則隱含使用段暫存器SS。
(7)串操作定址方式
- 在尋找源運算元時,隱含使用SI作為地址指標。
- 在尋找目的串時,隱含使用DI作為地址指標。
- 在串操作完成之後,自動對SI和DI進行修改,使它們指向下一個運算元。
(8)I/O埠定址
在計算機系統,對I/O埠的定址方式有以下兩種方法。
- 直接埠定址:在指令中直接給出埠地址,埠地址一般採用2位十六進位制數,也可以用符號表示。
- 暫存器間接埠定址:暫存器間接埠定址:把I/O埠的地址先送到DX中,用DX作間接定址暫存器。
指令系統
一種計算機所能執行的各種型別的指令的集合稱為該計算機的指令系統。
Intel8086/8088CPU指令系統的指令可以分為六大類:
- 傳送類指令
- 算術運算類指令
- 位操作類指令
- 串操作類指令
- 程式轉移類指令
- 處理器控制類指令
從指令的格式劃分,一般可以分為三種:
- 雙運算元指令:OPR DEST SRC
- 單運算元指令:OPR DEST
- 無運算元指令:OPR
對於無運算元指令,包含兩種情況:
- 指令不需要運算元,如暫停指令HLT。
- 在指令格式中,沒有顯式地指明運算元,但是它隱含指明瞭運算元的存放地方,如指令PUSHF。
1.傳送類指令
傳送類指令的作用是將資料資訊或地址資訊傳送到一個暫存器或儲存單元中,可以分為以下四種情況。
通用資料傳送指令:
指令格式:MOV DEST,SRC
作用:將源運算元指定的內容傳送到目的運算元,即DEST<=(SRC)。
MOV指令可以分為以下幾種情況:
- 立即數傳送到通用暫存器或儲存單元
- 暫存器之間的傳送
- 暫存器與儲存單元之間傳送
綜合起來,MOV指令在使用時需注意以下幾個問題:
- 立即數只能作源運算元,且它不能傳送給段暫存器。
- 段暫存器CS只能作源運算元,段暫存器之間不能直接傳送。
- 儲存單元之間不能直接傳送資料。
- MOV指令不影響標誌位。
交換指令
指令格式:XCHG DEST,SRC
作用:源運算元和目的運算元兩者內容相互交換,即:(DEST)<=>(SRC)。
標誌傳送指令
對標誌暫存器進行存取的指令有4條,它們都是無運算元指令,即指令隱含指定標誌暫存器、AH暫存器或堆疊為運算元。
- 取標誌暫存器指令
指令格式:LAHF
作用:將標誌暫存器的低8位送入AH暫存器,即將標誌SF、ZF、AF、PF和CF分別送入AH的第7、6、4、2、0位,而AH的第5、3、1位不確定。
- 儲存標誌暫存器指令
指令格式:SAHF
作用:將暫存器AH中的第7、6、4、2、0位分別送入標誌暫存器的SF、ZF、AF、PF和CF各標誌位。而標誌暫存器高8位中的各標誌位不受影響。
- 標誌進棧指令
指令格式:PUSHF
作用:先將堆疊指標SP減2,使其指向堆疊頂部的空字單元,然後將16位標誌暫存器的內容送SP指向的字單元。
- 標誌出棧指令
指令格式:POPF
作用:將由SP指向的堆疊頂部的一個字單元的內容送入標誌暫存器,然後SP的內容加2。
地址傳送指令
- 裝入有效地址
格式:LEA DEST,SRC
作用:將SRC儲存單元地址中的偏移量,即有效地址EA傳送到一個16位通用暫存器中。
- 裝入地址指標指令
格式:LDS DEST,SRC
LES DEST,SRC
作用:把SRC儲存單元開始的4個位元組單元的內容(32位地址指標)送入DEST通用暫存器和段暫存器DS(LDS指令)或ES(LES指令),其中低字單元內容為偏移量送通用暫存器,高字單元內容為段基值送DS或ES。
2.算術運算類指令
8086/8088指令系統中有加、減、乘、除指令,這些指令可以對位元組資料或字資料進行運算。
參加運算的數可以是無符號數,也可以是帶符號數。帶符號數用補碼錶示。
參加運算的數可以是二進位制數,也可以是十進位制數(以BCD碼錶示)。
加法指令
指令格式:ADD DEST,SRC
功能:目的運算元和源運算元相加,其和存放到目的運算元中,而源運算元內容保持不變,即DEST<=(DEST)+(SRC)。
帶進位加法指令
指令格式:ADC DEST,SRC
功能:該指令的功能與ADD基本相同,所不同的是其結果還要加上進位標誌CF的值,即:DEST<=(DEST)+(SRC)+CF。
加1指令
指令格式:INC DEST
功能:該指令為單運算元指令,其功能是將目的運算元加1,並送回到目的運算元,即:DEST<=(DEST)+1。
減法指令
指令格式:SUB DEST,SRC
功能:目的運算元的內容減去源運算元的內容,結果送入目的運算元,源運算元中內容保持不變。即:DEST<=(DEST)-(SRC)。
帶借位減法
指令格式:SBB DEST,SRC
功能:該指令的功能與SUB指令基本相同,不同的是在兩個運算元相減後再減去進位標誌CF的值。即:DEST<=(DEST)-(SRC)-CF。
減1指令
指令格式:DEC DEST
功能:該指令為單運算元指令,將目的運算元的內容減1後,送回到目的運算元。即:DEST<=(DEST)-1。
求負數指令
指令格式:NEG DEST
功能:用零減去目的運算元的內容,並送回目的運算元,即:DEST<=0-(DEST)。
3.位操作指令
邏輯運算指令
邏輯運算指令共有4條,它們的指令格式分別是:
邏輯“與”指令 AND DEST,SRC
邏輯“或”指令 OR DEST,SRC
邏輯“異或”指令 XOR DEST,SRC
邏輯“非”指令 NOT DEST
測試指令
指令格式:TEST DEST,SRC
功能:該指令的功能與AND指令相似,實現源運算元與目的運算元進行按位“邏輯與”運算,對標誌位的影響與AND指令相同,但運算的結果不送入目的運算元,即目的運算元內容也將保持不變。TEST指令主要用於測試某一運算元的一位或幾位的狀態。
移位/迴圈移位指令
- 算術移位:
算術左移 SAL DEST,COUNT
算術右移 SAR DEST,COUNT
- 邏輯移位:
邏輯左移 SHL DEST,COUNT
邏輯右移 SHR DEST,COUNT
- 迴圈移位:
迴圈左移 ROL DEST,COUNT
迴圈右移 ROR DEST,COUNT
帶進位迴圈左移 RCL DEST,COUNT
帶進位迴圈右移 RCR DEST,COUNT
這8條指令具有以下幾個共同點:
- DEST為操作物件,它可以是位元組或字運算元,可以是通用暫存器或儲存器運算元。
- COUNT用來決定移位/迴圈的位數,即確定移位的次數。
- 在執行移位時,根據指令不同,每移位一次,最高位(左移)或最低位(右移)都要送到進位標誌CF。
- 前4條移位指令根據移位結束後修改標誌位CF、PF、ZF、SF和OF,而AF不確定。而後4條迴圈移位指令根據移位結束後的結果僅修改CF和OF。
4.處理器控制類指令
標誌位操作指令
它們都是無運算元指令,運算元隱含為標誌暫存器的某個標誌位。能直接操作的標誌位有CF、IF和DF。
- 清除進位標誌:CLC;置CF為0
- 置1進位標誌:STC;置CF為1
- 進位標誌取反:CMC;CF的值取反
- 清除方向標誌:CLD;置DF為0
- 置1方向標誌:STD;置DF為1
- 清除中斷標誌:CLI;置IF為0
- 置1中斷標誌:STI;置IF為1
與外部事件同步的指令
- HLT;暫停指令
- WAIT;等待指令
- ESC;外部協處理器指令字首
- LOCK;匯流排鎖定指令
空操作指令 NOP
執行一次NOP佔用CPU三個時鐘週期,它不改變任何暫存器或儲存單元內容,主要用於延時。
指令編碼
Intel8086/8088彙編指令的編碼格式有四種基本格式:
- 雙運算元指令編碼格式
- 單運算元指令編碼格式
- 與AX或AL有關的指令編碼格式
- 其它指令編碼格式
(1)雙運算元指令編碼格式
對於像MOV、ADD、AND等雙運算元指令,運算元可以是以下兩種情形:
- 一個運算元在暫存器中,另一運算元在暫存器或儲存器中。
- 目的運算元在暫存器或儲存器中,源運算元是立即數。
操作特徵部分:
這部分為指令編碼的首位元組,它又分為以下三個段:
- OPCODE:操作碼欄位——該欄位長度為6bit。它表示了該指令所執行的功能和兩個運算元的來源。
- 方向欄位d——該欄位與第2部分定址特徵一起來決定源運算元和目的運算元的來源。
- 字/位元組欄位W——當W=1時,表示兩運算元長度為字;當W=0時,表示兩運算元長度為位元組。
定址特徵部分:
它與操作特徵部分的方向欄位d結合,指定兩個運算元分別使用什麼定址方式,及使用哪個暫存器。
它包括MOD、REG和R/M三個欄位,REG欄位確定一個運算元,而MOD和R/M欄位確定另一個運算元。
- 當d=1時,則目的運算元由REG欄位確定,而源運算元由MOD和R/M欄位確定。
- 當d=0時,則目的運算元由MOD和R/M 欄位確定,而源運算元由REG欄位確定。
REG欄位:
由REG欄位確定的一個運算元是某一通用暫存器的內容,即使用的是暫存器定址方式。
定址方式欄位MOD和暫存器/儲存器欄位R/M:
這兩個欄位共同確定一個運算元。該運算元可以在暫存器中,也可以在儲存器中。
位移量部分:
根據定址特徵中MOD和R/M欄位確定的有效地址計算方法,位移量可以是以下三種情況之一:
- 沒有位移量
- 1位元組位移量disp8
- 2位元組位移量disp16
立即數部分:
如果指令的源運算元為立即數,則指令編碼中包含有該部分。它總是位於指令編碼的最後1~2位元組。
(2)單運算元指令編碼格式
這種編碼格式適用於只有一個運算元的指令,如INC、DEC、移位/迴圈等指令。指令編碼為2~3位元組。
操作特徵部分:
包括OPCODE 、V和W三個欄位,其中V欄位只有移位/迴圈指令中才有該欄位,其它指令中沒有該欄位。
(3)與AX或AL有關的指令編碼格式
這種編碼格式用於隱含指定AX/AL作為一個運算元的雙運算元指令,其編碼格式為:
採用這種編碼格式的指令,除一個運算元隱含指定為AX/AL外,另一個運算元可以是立即數或儲存單元。
立即數:則編碼中應有1~2位元組的立即數
儲存單元:只能使用直接定址方式,位移量由disp欄位給出
(4)其它指令編碼格式
除上述三種編碼格式外,還有一些指令的編碼格式更簡單。如標誌位操作指令、堆疊操作指令等。這些指令的編碼格式一般只有一個位元組。
組合語言語句種類及其格式
組合語言的語句可以分為指令語句和偽指令語句。
1.指令語句
每一條指令語句在彙編時都要產生一個可供CPU執 行的機器目的碼,它又叫可執行語句。
指令語句的一般格式為:
(1)標號欄位
標號是可選欄位,它後面必須有“:”。標號是一 條指令的符號地址,代表了該指令的第一個位元組存放地址。
標號一般放在一個程式段或子程式的入口處,控制程式的執行轉到該程式位置。
在轉移指令或子程式呼叫指令中,可直接引用這個標號。
(2)指令助記符欄位
該欄位是一條指令的必選項,它表示這條語句要求CPU完成什麼具體操作,如MOV、ADD、SHL等。
有些指令還可以在指令助記符的前面加上字首,實 現一定的附加操作。如串操作指令前所加的重複前 綴REP等。
(3)運算元欄位
一條指令可以有一個運算元、兩個運算元或者無運算元。
如ADD、MOV指令需要兩個運算元,INC、NOT 指令只需一個運算元,而CLC指令不需要運算元。
(4)註釋欄位
註釋欄位為可選項,該欄位以分號“;”開始。它的作用是為閱讀程式的人加上一些說明性內容。
註釋欄位不會產生機器目的碼,它不會影響程 序和指令的功能。
註釋欄位可以是一條指令的後面部分,也可以是整個語句行。
2.偽指令語句
偽指令語句又叫命令語句。偽指令本身並不產生對應的機器目的碼。它僅僅是告訴彙編程式對其後面的指令語句和偽指令語句的運算元應該如何處理。
一條偽指令語句可以包含四個欄位。如下所示:
(1)符號名欄位
該欄位為可選項。根據偽指令的不同,符號名可以是常量名、變數名、過程名、結構名和記錄名 等等。
一條偽指令語句的符號名可以作其它偽指令語句或指令語句的運算元,這時它表示一個常 量或 儲存器地址。
(2)偽指令符欄位
該欄位是偽指令語句的必選項,它規定了彙編程式所要完成的具體操作。本章後面的章節將對各種偽指令作詳細介紹。
(3)運算元欄位
該欄位是否需要,以及需要幾個是由偽指令符欄位來決定。
運算元可以是一個常數(二進位制、十進位制、十六進位制等)、字串、常量名、變數名、標號和一些專用符號(如BYTE、FAR、PARA等)。
(4)註釋欄位
註釋欄位為可選項,該欄位必須以分號開始。其作用與指令語句的註釋欄位相同。
3.識別符號
指令語句中的標號和偽指令語句中符號名統稱為識別符號。識別符號是由若干個字元構成的。
識別符號構成規則:
- 字元的個數為1~31個;
- 第一個字元必須是字母、問號、@或下劃線“_”這4種字元之一;
- 從第二個字元開始,可以是字母、數字、@、“_”或問號“?”;
- 不能使用屬於系統專用的保留字。
保留字: CPU中各暫存器名(如AX、CS等),指令助記符(如MOV、ADD),偽指令符(如SEGMENT、DB)、表示式中的運算子(如GE、 EQ)以及屬性操作符(如PTR、OFFSET等)
組合語言資料
資料是指令和偽指令語句中運算元的基本組成部分。一個數據由數值和屬性兩部分構成。
在說明資料時不僅要指定其數值,還需說明它的屬性,比如是位元組資料還是字資料。
在組合語言中常用的資料形式有:常數、變數和標號。
1.常數
常數在彙編期間其值已完全確定,並且在程式執行過程中,其值不會發生變化。
常數有以下幾種形式:
- 二進位制數:以字母B結尾,如01001001B
- 八進位制數:以字母O或Q結尾,如631Q 254O
- 十進位制數:以字母D結尾,或者沒有結尾字母。如2007D、2007
- 十六進位制數:以字母H結尾,如3FEH,如果常數的第一個數字為字母,為了與識別符號加以區別,必須在其前面冠以數字“0”
- 實數。一般格式為:±整數部分.小數部分E±指數部分
- 字串常數:用引號(單引號或雙引號)括起來的一個或多個字元,這些字元以它的ASCII碼值儲存在記憶體
常數在程式中可以用在以下幾種情況:
- 作指令語句的源運算元
- 在指令語句的直接定址方式、變址(基址)定址方式或基址變址定址方式中作位移量
- 在資料定義偽指令中使用
2.變數
變數用來表示存放資料的儲存單元,這些資料在程式執行期間可以被改變 。
程式中以變數名的形式來訪問變數,因此,可以認為變數名就是存放資料的儲存單元地址。
(1)變數的定義與預置
定義變數就是給變數在記憶體中分配一定的儲存單元。也就是給這個儲存單元賦與一個符號名,即變數名,同時還要將這些儲存單元預置初值。
當變數被定義後,就具有了以下三個屬性:
- 段屬性——它表示變數存放在哪一個邏輯段中。
- 偏移量屬性(OFFSET)——它表示變數所在位置與段起始點之間的位元組數。
- 型別屬性——它表示變數佔用儲存單元的位元組數。其中DB偽指令 定義的變數為位元組,DW定義的變數為字,DD定義的為雙字(4位元組),DQ定義的為4字,DT定義的為5字。
在變數的定義語句中,給變數賦初值的表示式可以使用下面4種形式:
- 數值表示式
- ?表示式——不帶引號的問號“?”表示可以預置任意內容。
- 字串表示式——對於DB偽指令,字串為用引號括起來的不超過255 個字元。給每一個字元分配一個位元組單元。字串按從左 到右,將字元的ASCII編碼值以地址遞增的排列順序依次 存放。
- DUP表示式——DUP稱為重複資料操作符。
(2) 變數的使用
- 在指令語句中引用——在指令語句中直接引用變數名就是對其儲存單元的內容進行存取
- 在偽指令語句中引用——後面三條偽指令的運算元中都包含了前面定義的兩個變數
(3)標號
標號寫在一條指令的前面,它就是該指令在記憶體的存放地址的符號表示,也就是指令地址的別名。
標號主要用在程式中需要改變程式的執行順序時,用來標記轉移的目的地,即作轉移指令的運算元。
每個標號具有三屬性:
- 段屬性(SEG)——它表示該標號所代表的地址在哪個邏輯段中,即段基值。
- 偏移量屬性(OFFSET)——它表示該標號所代表的地址在段內與段起點間的位元組 數,即地址的偏移量。
- 距離屬性(也叫型別屬性)——它表示該標號可以被段內還是段間的指令呼叫。
NEAR(近):該標號只能作段內轉移,也就是說只能是與該標號所指指令同在一個邏輯段的轉移指令和呼叫指令才能使用它。
FAR(遠):該標號可以被非本段的轉移和呼叫指令使用。
標號的距離屬性可以有兩種方法來指定:
- 隱含方式
- 用LABEL偽指令給標號指定距離屬性
符號定義語句
在源程式設計中,使用符號定義語句可以將常數或表 達式等內容用某個指定的符號來表示。在8086/8088彙編語 言中有兩種符號定義語句。
(1)等值語句
語句格式:符號名 EQU 表示式
功能:用符號名來表示EQU右邊的表示式。後面的程式中一旦出現該符號名,彙編程式將把它替換成該表示式。
表示式可以是任何形式,常見的有以下幾種情況:
- 常數或數值表示式
- 地址表示式
- 變數、暫存器名或指令助記符
(2)等號語句
格式:符號名=表示式
等號語句與等值語句具有相同的作用。但等號語句可以對一個符號進行多次定義。
表示式與運算子
表示式是指令或偽指令語句運算元的常見形式。它由常數、變數、標號等通過操作運算子連線而成。
注意:任何表示式的值在程式被彙編的過程中進行計算確 定,而不是到程式執行時才計算。
8086/8088巨集組合語言中的操作運算子非常豐富,可以 分為以下五類:
- 算術運算子
包括:+、—、*、 / 、MOD、SHL、SHR、[ ]
運算子“+”和“-”也可作單目運算子,表示數的正負。
使用“+”、“-”、“*”、和“/”運算子時,參加運算的數和運算結果都是整數。
“/”運算為取商的整數部分,而“MOD”運算取除法運算的餘數。
“SHR ”和“SHL ”為邏輯移位運算子。
下標運算子“[ ]”具有相加的作用。
- 邏輯運算子
包括:NOT、AND、OR和XOR
- 關係運算符
包括:EQ(等於)、NE(不等於)、LT(小
於)、 LE(小於等於)、GT(大於)、 GE(大於等於)
關係運算符用來比較兩個表示式的大小。關係運算符如果是常量的比較,則按無符號數進行比較;如果是變數的比較,則比較它們的偏移量的大小。比較的兩個表示式必須同為常數或同一邏輯段中的變數。
關係運算的結果只能是“真”(全1)或“假”(全0)。
- 數值返回運算子
該類運算子有5個,它們將變數或標號的某些特徵值或儲存單元地址的一部分提取出來。
SEG運算子
作用:取變數或標號所在段的段基值。
OFFSET運算子
作用:取變數或標號在段內的偏移量。
TYPE運算子
作用:取變數或標號的型別屬性,並用數字形式表示。對變數來說就是取它的位元組長度。
LENGTH運算子
作用:取變數的長度。
SIZE運算子
作用:作用於變數,SIZE取值等於LENGTH和TYPE兩個運算子返回值的乘積。
- 屬性修改運算子
這一類運算子用來對變數、標號或儲存器運算元的型別屬性進行修改或指定。
PTR運算子
使用格式:型別 PTR 地址表示式
作用:將地址表示式所指定的標號、變數或用其它形式表 示的儲存器地址的型別屬性修改為“型別”所指的值。
HIGH/LOW運算子
使用格式:HIGH 表示式/LOW 表示式
作用:將表示式的值分離出高位元組和低位元組。
THIS運算子
THIS運算子一般與等值運算子EQU連用,用來定義一個變數或標號的型別屬性。所定義的變數或標號的段基值和偏移量與緊跟其後的變數或標號相同。
運算子的優先順序
在一個表示式中如果存在多個運算子時,在計算時就有先後順序問題。不同的運算子具有不同的運算優先級別。
優先級別 | 運算子 |
---|---|
(最高)1 | LENGTH,SIZE ,圓括號 |
2 | PTR,OFFSET,SEG,TYPE,THIS |
3 | HIGH,LOW |
4 | *,/,MOD,SHR,SHL |
5 | +,- |
6 | EQ,NE,LT,LE,GT,GE |
7 | NOT |
8 | AND |
(最低)9 | OR,XOR |
彙編程式在計算表示式時,按以下規則進行運算:
- 先執行優先級別高的運算,再算較低級別運算;
- 相同優先級別的操作,按照在表示式中的順序,從左到右進行;
- 可以用圓括號改變運算的順序。
程式的段結構
8086/8088在管理記憶體時,按照邏輯段進行劃分, 不同的邏輯段可以用來存放不同目的的資料。在程式中使用四個段暫存器CS,DS,ES和SS來訪問它們。
在源程式設計時,使用偽指令來定義和使用這些邏輯段。
1.段定義偽指令
偽指令SEGMENT和ENDS用於定義一個邏輯段。使
用時必須配對,分別表示定義的開始與結束。
段定義偽指令語句各部分的作用如下:
(1)段名
段名是由使用者自己任意選定的,符合識別符號定義規則的一個名稱。
最好選用與該邏輯段用途相關的名稱。如第一個資料段為DATA1,第二個資料為DATA2等。
一個段的開始與結尾用的段名必須一致。
(2)定位型別
定位型別用於決定段的起始邊界,即第一個可存放資料 的位置(不是段基址)。它可以有4種取值。
- PAGE: 表示該段從一個頁面的邊界開始
- PARA:表示該段從一個小節的邊界開始
- WORD:表示該段從一個偶數字節地址開始,即段起始單元地址的最後一位二進位制數一定是0。
- BYTE:表示該段起始單元地址可以是任一地址值。
注意:定位型別為PAGE和PARA時,段起始地址與段基址相同。定位型別為WORD和BYTE時,段起始地址與段基址 可能不同。
(3)組合型別
組合型別說明符用來指定段與段之間的連線關係和定位。 它有六種取值選擇。
- 若未指定組合型別,表示本段與其它段無連線關係。在裝入記憶體時,本段有自己的物理段,因此有自己的段基址。
- PUBLIC:在滿足定位型別的前提下,將與該段同名的段鄰接在一起,形成一個新的邏輯段,共用一個段基址。段內的所有偏移量調整為相對於新邏輯段的段基址。
- COMMON: 產生一個覆蓋段。在多個模組連線時,把該段與其它也用COMMON說明的同名段置成相同的段基址,這樣可達到共享同一儲存區。共享儲存區的長度由同名段中最大的段確定。
- STACK:把所有同名段連線成一個連續段,且系統自動對SS段暫存器初始化為該連續段的段基址。並初始化堆疊指標SP。
- AT表示式:表示本段可定位在表示式所指示的小節邊界上。表示式的值也就是段基值。
- MEMORY:表示本段在儲存器中應定位在所有其它段之後的最高地址上。如果有多個用MEMORY說明的段,則只處理第一個用MEMORY說明的段。其餘的被視為COMMON。
(4)類別名
類別名為某一個段或幾個相同型別段設定的型別名稱。系 統在進行連線處理時,把類別名相同的段存放在相鄰的儲存 區,但段的劃分與使用仍按原來的設定。
類別名必須用單引號引起來。所用字串可任意選定,但它不能使用程式中的標號、變數名或其它定義的符號。
在定義一個段時,段名是必須有的項,而定位型別、組合型別和類別名三個引數是可選項。各個引數之間用空格分隔。各引數之間的順序不能改變。
2.段定址偽指令
段定址偽指令ASSUME的作用是告訴彙編程式,在處理源程式時,定義的段與哪個暫存器關聯。
ASSUME並不設定各個段暫存器的具體內容,段暫存器的值是在程式執行時設定的。
一般格式 :ASSUME 段暫存器名:段名,段暫存器名:段名,......
其中段暫存器名為CS,DS,ES和SS四個之一,段名是用SEGMENT/ENDS偽指令定義的段名。
- 在一個程式碼段中可以有幾條ASSUME偽指令,對於前面的設定,可以用ASSUME改變原來的設定。
- 一條ASSUME語句不一定設定全部段暫存器,可以選擇其中一個或幾個段暫存器。
- 可以使用關鍵字NOTHING將前面的設定刪除。
3.段暫存器的裝入
段暫存器的初值(段基值)裝入需要用程式的方法來實現。四個段暫存器的裝入方法略有不同。
(1)DS和ES的裝入
在程式中,使用資料傳送語句來實現對DS和ES的裝入。
(2)SS的裝入
SS的裝入有兩種方法:
- 在段定義偽指令的組合型別項中,使用STACK引數,並在段定址偽指令ASSUME語句中把該段與SS段暫存器關聯。
- 如果在段定義偽指令的組合型別中,未使用STACK引數,或者是在程式中要調換到另一個堆疊,這時,可以使用類似於DS和ES的裝入方法。
(3)CS的裝入
CPU在執行指令之前根據CS和IP的內容來從記憶體中提取指令,即必須在程式執行之前裝入CS和IP的值。因此,CS和IP的初始值就不能用可執行語句來裝入。
裝入CS和IP一般有下面兩種情況:
- 由系統軟體按照結束偽指令指定的地址裝入初始的CS和IP。
- 在程式執行期間,當執行某些指令時,CPU自動修改CS和IP,使它們指向新的程式碼段。
過程定義偽指令(PROC/ENDP)
在程式設計過程中,常常將具有一定功能的程式段設計成一個子程式。在MASM巨集彙編程式中,用過程(PROCEDURE)來構造子程式。
過程名是子程式的名稱,它被用作過程呼叫指令CALL的目的運算元。它類同一個標號的作用。具有段、偏移量和距離三個屬性。而距離屬性使用NEAR和FAR來指定,若沒有指定,則隱含為NEAR。
NEAR過程只能被本段指令呼叫,而FAR過程可以供其它段的指令呼叫。
每一個過程中必須包含有返回指令RET,其作用是控制CPU從子程式中返回到呼叫該過程的主程式。
當前位置計數器$與定位偽指令ORG(Origin)
彙編程式在彙編源程式時,每遇到一個邏輯段,就要為其設定一個位置計數器,它用來記錄該邏輯段中定義的每一個數據或每一條指令在邏輯段中的相對位置。
在源程式中,使用符號$來表示位置計數器的當前值。因此,$被稱為當前計數器。它位於不同的位置具有不同的值。
定位偽指令ORG:用來改變位置計數器的值。
格式: ORG 數值表示式
作用:將數值表示式的值賦給當前位置計數器$。ORG語句為其後的資料或指令設定起始偏移量。
標題偽指令TITLE
語句格式:TITLE 標題名
作用:給所在程式指定一個標題。以便在列表檔案的每一頁的第一行都顯示這個標題。其中標題是使用者任意選用的字串,字元個數不能超過60。
從程式返回作業系統的方法
為了使程式執行結束後,能夠正確地返回到作業系統,需要在程式中加上一些必要的語句。一般有以下兩種方法。
(1)使用程式段字首PSP(Program Segment Prefix)實現返回
DOS系統將一個.EXE檔案(可執行檔案)裝入記憶體時,在該檔案的前面生成一個程式段字首PSP,其長度為100H位元組。同時讓DS和ES都指向PSP的開始,而CS指向該程式的程式碼段,即第一條可執行指令。
為了使程式執行完後,正確返回DOS,需要做以下三個操作:
- 將使用者程式編製成一個過程,型別為FAR;
- 將PSP的起始邏輯地址壓棧,即將INT 20H指令的地址壓棧;
- 在使用者程式結尾處,使用一條RET指令。執行該指令將使儲存在堆疊中的PSP的起始地址彈出到CS和IP中。
(2)使用DOS系統功能呼叫實現返回
執行DOS功能呼叫4CH,也可以控制使用者程式結束,並返回DOS作業系統。
在程式結束時,使用兩條指令:MOV AH,4CH
INT 21H