關(guān)于我們
書單推薦
新書推薦
|
匯編語言程序設(shè)計教程
本書以IBM PC機型和80x86指令系統(tǒng)為對象,全面而系統(tǒng)地介紹微型計算機系統(tǒng)的結(jié)構(gòu)及匯編語言程序設(shè)計的方法。全書由10章組成。第1章和第2章介紹匯編語言基礎(chǔ)知識和微型計算機的體系結(jié)構(gòu);第3章詳細介紹IBM PC的尋址方式和指令系統(tǒng);第4章介紹偽指令、匯編語言程序格式等知識;第5章講述典型匯編語言程序結(jié)構(gòu)的設(shè)計方法;第6章詳細介紹子程序設(shè)計及參數(shù)傳遞的方法;第7章介紹輸入/輸出程序設(shè)計技術(shù)和方法;第8章介紹宏匯編、重復(fù)匯編和條件匯編等高級匯編技術(shù);第9章講述DOS功能調(diào)用和BIOS功能調(diào)用知識;第10章是匯編語言上機環(huán)境及程序設(shè)計實例分析。
充分考慮微型機技術(shù)的發(fā)展、教學(xué)方法的完善以及教學(xué)手段的改進等因素,系統(tǒng)地介紹微機原理的基礎(chǔ)知識及匯編語言程序設(shè)計的方法和技術(shù)。
提供大量的例程分析,幫助學(xué)生掌握匯編語言程序設(shè)計的步驟和方法。 提供匯編語言程序設(shè)計上機實驗指導(dǎo)、實例分析及學(xué)生上機練習(xí)作業(yè)的要求。 每章均有思考與練習(xí)題,可以作為鞏固相關(guān)知識的課后作業(yè)。
前言
計算機技術(shù)及電子技術(shù)的迅猛發(fā)展,使得人們的學(xué)習(xí)、工作、生活越來越離不開計算機,計算機知識及其應(yīng)用技能已經(jīng)成為人類知識結(jié)構(gòu)的重要組成部分。微型計算機技術(shù)的發(fā)展,不斷涌現(xiàn)新技術(shù)、新產(chǎn)品。本書以IBM PC作為背景,系統(tǒng)地介紹微機原理的基礎(chǔ)知識及匯編語言程序設(shè)計的方法和技術(shù)。本次再版在前三版《匯編語言程序設(shè)計教程》的基礎(chǔ)上,修改并增加了部分內(nèi)容。在教材編寫過程中,參照了國內(nèi)多所高校本科“匯編語言程序設(shè)計”課程的教學(xué)大綱,兼顧相關(guān)專業(yè)的教學(xué)要求和特點,并充分考慮到了微型機技術(shù)的發(fā)展、教學(xué)方法的完善以及教學(xué)手段的改進等因素。全書共分10章。第1章和第2章介紹匯編語言基礎(chǔ)知識和微型計算機的體系結(jié)構(gòu); 第3章詳細介紹IBM PC的尋址方式和指令系統(tǒng); 第4章介紹偽指令、匯編語言程序格式等知識; 第5章講述典型匯編語言程序結(jié)構(gòu)的設(shè)計方法; 第6章詳細介紹子程序設(shè)計及參數(shù)傳遞的方法。第7章介紹輸入/輸出程序設(shè)計技術(shù)和方法; 第8章介紹宏匯編、重復(fù)匯編和條件匯編等高級匯編技術(shù); 第9章講述DOS功能調(diào)用和BIOS功能調(diào)用知識,通過大量程序設(shè)計實例分析系統(tǒng)功能調(diào)用的實現(xiàn); 第10章是匯編語言上機環(huán)境及程序設(shè)計實例分析,給出學(xué)生上機練習(xí)的要求。本書每章后均有思考與練習(xí),可以作為鞏固相關(guān)知識的課后作業(yè)。第5~10章有大量的例程分析,以幫助學(xué)生掌握匯編語言程序設(shè)計的步驟和方法。在附錄部分提供了DOS功能調(diào)用、BIOS功能調(diào)用和80x86指令系統(tǒng)的匯總,供讀者學(xué)習(xí)過程中查閱。本書由上海交通大學(xué)卜艷萍老師和華東理工大學(xué)周偉老師共同編著。周偉編寫第5~8章、第10章和附錄A。卜艷萍編寫第1~4章、第9章、附錄B和附錄C,并負責(zé)全書的統(tǒng)稿工作。由于編者水平有限及時間倉促,書中不妥之處,敬請讀者批評指正。作者聯(lián)系郵箱: ypbu@sjtu.edu.cn。 作者2016年5月
目錄
第1章匯編語言基礎(chǔ)知識 1.1計算機基礎(chǔ)知識 1.1.1計算機的發(fā)展史 1.1.2計算機的特性 1.1.3計算機的分類與應(yīng)用 1.1.4計算機的主要技術(shù)指標(biāo) 1.2計算機的基本結(jié)構(gòu)與組成 1.2.1計算機的硬件 1.2.2計算機的軟件 1.2.3計算機的程序設(shè)計語言 1.2.4計算機系統(tǒng)的層次結(jié)構(gòu) 1.3計算機中的數(shù)制與碼制 1.3.1數(shù)制及數(shù)制轉(zhuǎn)換 1.3.2機器數(shù)的編碼 1.3.3定點數(shù)與浮點數(shù) 1.3.4碼制 思考與練習(xí) 第2章微型計算機體系結(jié)構(gòu) 2.180x86微處理器 2.1.18086/8088的功能結(jié)構(gòu) 2.1.28086/8088的寄存器組織 2.1.38086/8088的存儲器組織 2.1.480x86微處理器的發(fā)展 2.2IA32 CPU 2.2.1IA32 CPU功能結(jié)構(gòu) 2.2.2IA32 CPU寄存器組 2.2.3IA32 CPU存儲器管理 2.3先進的微處理器 2.3.1高檔Pentium微處理器 2.3.2迅馳技術(shù) 2.3.3多核技術(shù) 2.3.4專用微處理器 2.3.5微處理器領(lǐng)域的架構(gòu)革命 思考與練習(xí) 第3章微型計算機的指令系統(tǒng) 3.1尋址方式 3.1.1操作數(shù)的種類 3.1.28086/8088的機器代碼格式 3.1.3與數(shù)據(jù)有關(guān)的尋址方式 3.1.4與轉(zhuǎn)移地址有關(guān)的尋址方式 3.28086/8088指令系統(tǒng) 3.2.1數(shù)據(jù)傳送類指令 3.2.2算術(shù)運算類指令 3.2.3邏輯操作類指令 3.2.4程序控制類指令 3.2.5串操作類指令 3.2.6處理器控制類指令 3.2.7輸入/輸出類指令 3.380x86指令系統(tǒng)介紹 3.3.180x86尋址方式 3.3.280286指令系統(tǒng)新增指令 3.3.380386指令系統(tǒng)新增指令 3.3.480486指令系統(tǒng)新增指令 3.3.5Pentium指令系統(tǒng)新增指令 思考與練習(xí) 第4章偽指令與匯編語言程序結(jié)構(gòu)設(shè)計 4.1匯編語言語句類型和格式 4.2偽指令 4.2.1表達式賦值偽指令 4.2.2數(shù)據(jù)定義偽指令 4.2.3LABEL偽指令 4.2.4段定義偽指令 4.2.5簡化段定義偽指令 4.2.6過程定義偽指令 4.2.7模塊命名、通信等偽指令 4.3匯編語言源程序結(jié)構(gòu) 4.3.1完整段定義結(jié)構(gòu) 4.3.2簡化段定義結(jié)構(gòu) 4.3.3程序段前綴結(jié)構(gòu) 4.3.4可執(zhí)行程序結(jié)構(gòu) 思考與練習(xí) 第5章匯編語言程序設(shè)計 5.1匯編語言程序設(shè)計概述 5.2順序程序設(shè)計 5.3分支程序設(shè)計 5.3.1雙分支結(jié)構(gòu)程序設(shè)計 5.3.2多分支結(jié)構(gòu)程序設(shè)計 5.4循環(huán)程序設(shè)計 5.4.1簡單循環(huán)程序設(shè)計 5.4.2多重循環(huán)程序設(shè)計 思考與練習(xí) 第6章子程序設(shè)計 6.1子程序的定義與調(diào)用 6.1.1子程序的定義 6.1.2子程序的調(diào)用 6.2子程序的參數(shù)傳遞方法 6.2.1通過寄存器傳遞參數(shù) 6.2.2通過堆棧傳遞參數(shù) 6.2.3通過內(nèi)存單元傳遞參數(shù) 6.3子程序的嵌套與遞歸 6.3.1子程序的嵌套調(diào)用 6.3.2子程序的遞歸調(diào)用 思考與練習(xí) 第7章輸入/輸出程序設(shè)計 7.1微機接口技術(shù)概述 7.2輸入/輸出的控制方式 7.2.1程序查詢傳送方式 7.2.2中斷傳送方式 7.2.3DMA傳送方式 7.3輸入/輸出綜合應(yīng)用程序舉例 思考與練習(xí) 第8章高級匯編技術(shù) 8.1宏匯編 8.1.1宏定義與宏調(diào)用 8.1.2宏匯編實例分析 8.1.3宏嵌套 8.2重復(fù)匯編與條件匯編 8.2.1重復(fù)匯編 8.2.2條件匯編 8.3復(fù)雜數(shù)據(jù)結(jié)構(gòu) 8.3.1結(jié)構(gòu) 8.3.2記錄 8.4模塊化程序設(shè)計 8.4.1宏庫的使用 8.4.2源程序的包含文件 8.4.3目標(biāo)代碼文件的連接 思考與練習(xí) 第9章DOS/BIOS功能調(diào)用 9.1概述 9.2DOS功能調(diào)用 9.2.1DOS功能調(diào)用概述 9.2.2DOS功能調(diào)用程序?qū)嵗?br /> 9.3BIOS功能調(diào)用 9.3.1BIOS功能調(diào)用概述 9.3.2BIOS功能調(diào)用程序?qū)嵗?br /> 9.3.3顯示器BIOS中斷服務(wù) 9.4綜合應(yīng)用程序設(shè)計舉例 思考與練習(xí) 第10章匯編語言上機環(huán)境及程序設(shè)計實例 10.1匯編語言程序設(shè)計上機實驗相關(guān)知識 10.1.1匯編程序 10.1.2DEBUG命令的使用 10.1.3匯編錯誤信息 10.2微型計算機操作系統(tǒng)介紹 10.2.1微型機操作系統(tǒng)MSDOS 10.2.2微型機操作系統(tǒng)Windows 10.3程序設(shè)計實例分析及實驗任務(wù) 10.3.1順序程序設(shè)計 10.3.2分支程序設(shè)計 10.3.3循環(huán)程序設(shè)計 10.3.4子程序設(shè)計 10.3.5系統(tǒng)功能調(diào)用 10.4調(diào)試程序CodeView的使用 10.5匯編語言與C/C 的混合編程 10.6軟件逆向工程與反匯編 思考與練習(xí) 附錄ADOS功能調(diào)用(INT 21H) 附錄BBIOS功能調(diào)用 附錄C80x86指令系統(tǒng)一覽表 參考文獻
第3章微型計算機的指令系統(tǒng)
計算機是通過執(zhí)行指令序列來解決問題的,每種計算機都有一套指令集合供用戶使用。在微型計算機中,微處理器能執(zhí)行的各種指令的集合稱為指令系統(tǒng)。微處理器的主要功能是由它的指令系統(tǒng)來體現(xiàn)的。在其他條件相同的情況下,指令系統(tǒng)越強,機器的功能也就越強。不同的微處理器有不同的指令系統(tǒng),其中每一條指令對應(yīng)著處理器的一種基本操作。計算機只能識別由二進制編碼表示的指令,稱為機器指令。一條機器指令應(yīng)包含兩部分內(nèi)容,其一般格式為: 操作碼操作數(shù) 操作碼部分指出此指令要完成何種操作; 操作數(shù)部分則指出參與操作的對象是什么。在指令中可以直接給出操作數(shù)的值或者操作數(shù)存放在何處,操作的結(jié)果應(yīng)送往何處等信息。處理器可根據(jù)指令字中給出的地址信息求出存放操作數(shù)的地址,稱為有效地址(Effective Address,EA),然后對存放在有效地址中的操作數(shù)進行存取操作。3.1尋 址 方 式根據(jù)操作數(shù)的種類,8086/8088指令系統(tǒng)的尋址方式分為兩大類: 數(shù)據(jù)尋址方式和轉(zhuǎn)移地址尋址方式。3.1.1操作數(shù)的種類在8086/8088指令系統(tǒng)中,操作數(shù)可分為數(shù)據(jù)操作數(shù)和轉(zhuǎn)移地址操作數(shù)兩大類。1. 數(shù)據(jù)操作數(shù)數(shù)據(jù)操作數(shù)是指指令中操作的對象是數(shù)據(jù)。數(shù)據(jù)操作數(shù)的類型有以下幾種。(1) 立即數(shù)操作數(shù): 指令中要操作的數(shù)據(jù)在指令中。(2) 寄存器操作數(shù): 指令中要操作的數(shù)據(jù)存放在指定的寄存器中。(3) 存儲器操作數(shù): 指令中要操作的數(shù)據(jù)存放在指定的存儲單元中。(4) I/O操作數(shù): 指令中要操作的數(shù)據(jù)來自或送到I/O端口。對于數(shù)據(jù)操作數(shù),有的指令只有一個操作數(shù)或沒有操作數(shù)。而有的指令有兩個操作數(shù),一個稱為源操作數(shù),在操作過程中保持原值不變; 另一個稱為目標(biāo)操作數(shù),操作后一般被操作結(jié)果所替代。另外,還有一種隱含操作數(shù)。這種操作數(shù)從指令格式上看,好像是沒有操作數(shù),或只有一個操作數(shù),實際上隱含了一個或兩個操作數(shù)。2. 地址操作數(shù)地址操作數(shù)是指指令中操作的對象是地址。其指令只有一個目標(biāo)操作數(shù),該操作數(shù)不是普通數(shù)據(jù),而是要轉(zhuǎn)移的目標(biāo)地址。它也可以分為立即數(shù)操作數(shù)、寄存器操作數(shù)和存儲器操作數(shù),即要轉(zhuǎn)移的目標(biāo)地址包含在指令中,或存放在寄存器中,或存放在存儲單元之中。3.1.28086/8088的機器代碼格式8086/8088 CPU的機器代碼格式如圖3.1所示。 1/2字節(jié)0/1字節(jié)0/1/2字節(jié)0/1/2字節(jié) 操作碼mod reg r/m位移量立即數(shù) 圖3.18086/8088的機器代碼格式 操作碼占1或2字節(jié),后面的各字節(jié)指明操作數(shù)。其中,“mod reg r/m”字節(jié)表明尋找操作數(shù)的方式(即采用的尋址方式),“位移量”字節(jié)給出某些尋址方式需要的相對基地址的偏移量,“立即數(shù)”字節(jié)給出立即尋址方式需要的數(shù)值本身。由于設(shè)計有多種尋址方式,操作數(shù)的各個字段有多種組合,表3.1給出了各種組合情況。 表3.18086/8088指令的尋址方式字節(jié)編碼 r/m mod 000110 11 w=0w=1reg 000[BX SI][BX SI D8][BX SI D16]ALAX000001[BX DI][BX DI D8][BX DI D16]CLCX001010[BP SI][BP SI D8][BP SI D16]DLDX010011[BP DI][BP DI D8][BP DI D16]BLBX011100[SI][SI D8][SI D16]AHSP100101[DI][DI D8][DI D16]CHBP101110[D16][BP D8][BP D16]DHSI110111[BX][BX D8][BX D16]BHDI111 8086/8088指令最多可以有兩個操作數(shù)。在“mod reg r/m”字節(jié)中,reg字段表示一個采用寄存器尋址的操作數(shù),reg占用3位,不同編碼指示8個8位(w=0)或16位(w=1)通用寄存器之一; mod和r/m字段表示另一個操作數(shù)的尋址方式,分別占用2位或3位。(1) mod =00時為無位移量的存儲器尋址方式。但其中,當(dāng)r/m =110時為直接尋址方式,此時該字節(jié)后跟16位有效地址D16。(2) mod =01時為帶有8位位移量的存儲器尋址方式。此時該字節(jié)后跟一個字節(jié),表示8位位移量D8,它是一個有符號數(shù)。(3) mod =10時為帶有16位位移量的存儲器尋址方式。此時該字節(jié)后跟兩個字節(jié),表示16位位移量D16,它也是一個有符號數(shù)。(4) mod =11時為寄存器尋址方式,由r/m指定寄存器,此時的編碼與reg相同。3.1.3與數(shù)據(jù)有關(guān)的尋址方式指令中關(guān)于如何求出存放操作數(shù)有效地址的方法稱為操作數(shù)的尋址方式。計算機按照指令給出的尋址方式求出操作數(shù)有效地址和存取操作數(shù)的過程,稱為尋址操作。在微機中,尋址方式可能有如下3種情況。(1) 操作數(shù)包含在指令中,稱為立即尋址。(2) 操作數(shù)包含在CPU的內(nèi)部寄存器中,稱為寄存器尋址。(3) 操作數(shù)在內(nèi)存的數(shù)據(jù)區(qū)中,這時指令中的操作數(shù)字段包含著此操作數(shù)的地址,稱為存儲器尋址。為了更清楚地掌握尋址方式,下面以最常用的MOV指令來舉例說明各種尋址方式的功能。MOV指令是一個數(shù)據(jù)傳送指令,相當(dāng)于高級語言的賦值語句,其格式為: MOVOPRD1,OPRD2 MOV指令的功能是將源操作數(shù)OPRD2傳送至目的操作數(shù)OPRD1。在講述中,假設(shè)目的操作數(shù)采用寄存器尋址方式,用源操作數(shù)來反映各種尋址方式的功能和彼此的區(qū)別。1. 立即數(shù)尋址方式立即數(shù)尋址方式所提供的操作數(shù)緊跟在操作碼的后面,與操作碼一起放在指令代碼段中。立即數(shù)可以是8位數(shù)或16位數(shù)。如果是16位數(shù),則低位字節(jié)存放在低地址中,高位字節(jié)存放在高地址中。立即數(shù)尋址方式只能用于源操作數(shù)字段,不能用于目的操作數(shù)字段,經(jīng)常用于給寄存器賦初值!纠3.1】將8位立即數(shù)18存入寄存器AL中。 MOVAL,18 指令執(zhí)行后,(AL)= 12H 圖3.2立即數(shù)尋址方式示意圖 【例3.2】將16位立即數(shù)8090H存入寄存器AX中。 MOVAX,8090H 圖3.2給出了立即數(shù)尋址方式示意圖。指令執(zhí)行后的結(jié)果為: (AX)= 8090H。2. 寄存器尋址方式在寄存器尋址方式中,操作數(shù)包含于CPU的內(nèi)部寄存器之中。這種尋址方式大都用于寄存器之間的數(shù)據(jù)傳輸。對于16位操作數(shù),寄存器可以是AX、BX、CX、DX、SI、DI、SP和BP等; 對于8位操作數(shù),寄存器可以是AL、AH、BL、BH、CL、CH、DL和DH。這種尋址方式可以取得較高的運算速度。下列指令都屬于寄存器尋址方式: MOVDS,AX MOVAL,CL MOVSI,AX MOVBL,AH 【例3.3】寄存器尋址方式的指令操作過程如下。 MOVAX,BX 如果指令執(zhí)行前(AX)= 6688H,(BX)= 1020H; 則指令執(zhí)行后,(AX)= 1020H,(BX)保持不變,圖3.3給出了寄存器尋址方式示意圖。3. 存儲器尋址方式 圖3.3寄存器尋址方式示意圖 寄存器尋址雖然速度較快,但CPU中寄存器數(shù)目有限,不可能把所有參與運算的數(shù)據(jù)都存放在寄存器中。多數(shù)情況下,操作數(shù)還是要存儲在主存中。如何尋址主存中存儲的操作數(shù)稱為存儲器尋址方式,也稱為主存尋址方式。在這種尋址方式下,指令中給出的是有關(guān)操作數(shù)的主存地址信息。由于8086/8088的存儲器是分段管理的,因此這里給出的地址只是偏移地址(即有效地址EA),而段地址在默認的或用段超越前綴指定的段寄存器中。為了方便各種數(shù)據(jù)結(jié)構(gòu)的存取,8086/8088設(shè)計了多種主存尋址方式。1) 直接尋址方式直接尋址方式是操作數(shù)地址的16位偏移量直接包含在指令中,和指令操作碼一起放在代碼段,而操作數(shù)則在數(shù)據(jù)段中。操作數(shù)的地址是數(shù)據(jù)段寄存器DS中的內(nèi)容左移4位后,加上指令給定的16位地址偏移量。把操作數(shù)的偏移地址稱為有效地址EA,則物理地址=16D×(DS) EA。如果數(shù)據(jù)存放在數(shù)據(jù)段以外的其他段中,則在計算物理地址時應(yīng)使用指定的段寄存器。直接尋址方式適合于處理單個數(shù)據(jù)變量!纠3.4】直接尋址方式示例如下。 MOVAX,[400H] 如果(DS)= 1000H,則物理地址的計算式為: 圖3.4直接尋址方式示意圖 10000H(段基地址) 400H(偏移地址)= 10400H(物理地址)圖3.4給出了直接尋址方式示意圖。指令執(zhí)行后的結(jié)果為: (AX)= 1A2BH。也可以用符號地址代替數(shù)值地址,例如: MOVAX,BUFFER 此時BUFFER為存放數(shù)據(jù)單元的符號地址。它等效于如下形式: MOVAX,[BUFFER] 2) 寄存器間接尋址方式在寄存器間接尋址方式中,操作數(shù)在存儲器中。操作數(shù)的有效地址由變址寄存器SI、DI或基址寄存器BX、BP提供。這又分成兩種情況: 如果指令中指定的寄存器是BX、SI、DI,則用DS寄存器的內(nèi)容作為段地址,即操作數(shù)的物理地址為: 物理地址 = 10H ×(DS) (BX、SI或DI) 如指令中用BP寄存器,則操作數(shù)的段地址在SS中,即堆棧段,所以操作數(shù)的物理地址為: 物理地址 = 10H ×(SS) (BP) 【例3.5】寄存器間接尋址方式示例如下。 MOVAX,[SI] 圖3.5寄存器間接尋址方式示意圖 如果(DS)=2000H,(SI)=1500H,則物理地址的計算式為: 20000H(段基地址) 1500H(偏移地址) =21500H(物理地址) 圖3.5給出了寄存器間接尋址方式示意圖。指令執(zhí)行后的結(jié)果為: (AX)= C5D6H。3) 寄存器相對尋址方式該尋址方式是以指定的寄存器內(nèi)容,加上指令中給出的位移量(8位或16位),并以一個段寄存器為基準(zhǔn),作為操作數(shù)的地址。指定的寄存器一般是一個基址寄存器或變址寄存器。即: EA= (BX)(BP)(SI)(DI) 8位 16位位移量與寄存器間接尋址方式類似,對于寄存器為BX、SI、DI的情況,段寄存器用DS,則物理地址為: 物理地址 = 10H ×(DS) (BX、SI或DI) 8位(或16位)位移量 當(dāng)寄存器為BP時,則使用SS段寄存器的內(nèi)容作為段地址,此時物理地址為: 物理地址 = 10H ×(SS) (BP) 8位(或16位)位移量 【例3.6】寄存器相對尋址方式示例如下。 MOVAX,DISP[DI] 也可表示為 MOVAX,[DISP DI] 其中DISP為16位位移量的符號地址。如果(DS)= 3000H,(DI)= 2000H,DISP = 600H,則物理地址的計算式為: 30000H(段基地址) 2000H(變址) 600H(位移量) =32600H(物理地址) 圖3.6給出了寄存器相對尋址方式示意圖,指令執(zhí)行后的結(jié)果是: (AX)= 005AH。 圖3.6寄存器相對尋址方式示意圖 4) 基址加變址尋址方式在基址加變址尋址方式中,通常把BX和BP看作是基址寄存器,把SI和DI看作變址寄存器,可把兩種方式組合起來形成一種新的尋址方式;芳幼冎返膶ぶ贩绞绞前岩粋基址寄存器BX或BP的內(nèi)容,加上變址寄存器SI或DI的內(nèi)容,并以一個段寄存器作為地址基準(zhǔn),作為操作數(shù)的地址。兩個寄存器均由指令指定。當(dāng)基址寄存器為BX時,段寄存器使用DS,則物理地址為: 物理地址 = 10H ×(DS) (BX) (SI或DI) 當(dāng)基址寄存器為BP時,段寄存器用SS,此時物理地址為: 物理地址 = 10H ×(SS) (BP) (SI或DI) 【例3.7】基址加變址尋址方式示例如下。 MOVAX,[BX][DI] 或?qū)憺椋?nbsp; MOVAX,[BX DI] 如果(DS)= 1000H,(BX)= 2000H,(DI)= 3000H,則物理地址的計算式為: 10000H(段基地址) 2000H(基址) 3000H(變址) = 15000H(物理地址) 圖3.7給出了基址加變址尋址方式示意圖。指令執(zhí)行后的結(jié)果為: (AX)= 1288H。 圖3.7基址加變址尋址方式示意圖 5) 相對基址變址尋址方式在相對基址變址尋址方式中,通常把BX和BP看作是基址寄存器,把SI和DI看作變址寄存器。它是把一個基址寄存器BX或BP的內(nèi)容,加上變址寄存器SI或DI的內(nèi)容,再加上指令中給定的8位或16位位移量,并以一個段寄存器為地址基準(zhǔn),作為操作數(shù)的地址。同樣,當(dāng)基址寄存器為BX時,段寄存器使用DS,則物理地址為: 物理地址 = 10H ×(DS) (BX) (SI或DI) 8位(或16位)位移量 當(dāng)基址寄存器為BP時,段寄存器則用SS。此時物理地址為: 物理地址 = 10H ×(SS) (BP) (SI或DI) 8位(或16位)位移量 【例3.8】相對基址變址尋址方式示例如下。 MOVAX,DISP[BX][SI] 如果(DS)= 4000H,(BX)= 2000H,(SI)= 1000H,DISP = 800H,則物理地址的計算式為: EA =2000H(基址) 1000H(變址) 800H(位移量)=3800H 40000H(段基地址) 3800H(EA)= 43800H(物理地址) 圖3.8相對基址變址尋址方式示意圖 圖3.8給出了相對基址變址尋址方式示意圖。指令執(zhí)行后的結(jié)果為: (AX)= EEFFH。3.1.4與轉(zhuǎn)移地址有關(guān)的尋址方式微機指令系統(tǒng)中有轉(zhuǎn)移指令及子程序調(diào)用等非順序執(zhí)行指令。這類指令所指出的地址是程序轉(zhuǎn)移到的指定的轉(zhuǎn)移地址,然后再依次順序執(zhí)行程序。這種提供轉(zhuǎn)移地址的方法稱為程序轉(zhuǎn)移地址的尋址方式。它分為段內(nèi)直接尋址、段內(nèi)間接尋址、段間直接尋址和段間間接尋址4種情況。在8086/8088指令系統(tǒng)中,條件轉(zhuǎn)移指令只能使用段內(nèi)直接尋址方式,且位移量為8位; 而非條件轉(zhuǎn)移指令和子程序調(diào)用指令則可用4種尋址方式中的任何一種。1. 段內(nèi)直接尋址這種尋址方式是將當(dāng)前IP寄存器的內(nèi)容和指令中指定的8位或16位位移量之和作為轉(zhuǎn)向的有效地址。一般用相對于當(dāng)前IP值的位移量來表示轉(zhuǎn)向有效地址,所以它是一種相對尋址方式。當(dāng)這一程序段在內(nèi)存中的不同區(qū)域運行時,轉(zhuǎn)移指令本身不會發(fā)生變化,這是符合程序的再定位要求的。這種尋址方式適用于條件轉(zhuǎn)移及無條件轉(zhuǎn)移指令,但是當(dāng)它用于條件轉(zhuǎn)移指令時,位移量只允許8位。指令格式: JMPNEAR PTR ADDR1 JMPSHORT ADDR2 其中,ADDR1和ADDR2都是轉(zhuǎn)向的符號地址,在機器指令中,用位移量來表示。2. 段內(nèi)間接尋址段內(nèi)間接尋址的轉(zhuǎn)向有效地址是一個寄存器或一個存儲單元的內(nèi)容,并且可以用數(shù)據(jù)尋址方式中除立即數(shù)以外的任何一種尋址方式取得轉(zhuǎn)向的有效地址。指令格式: JMPBX JMPWORD PTR [BP DISP] 其中,WORD PTR為操作符,用以指出其后的尋址方式所取得的轉(zhuǎn)向地址是一個字的有效地址,也就是說它是一種段內(nèi)轉(zhuǎn)移。對于段內(nèi)轉(zhuǎn)移尋址方式,直接把求得的轉(zhuǎn)移的有效地址送到IP寄存器就可以了。如果需要計算轉(zhuǎn)移的物理地址,則應(yīng)是: 物理地址 = 10H ×(CS) EA 其中,EA為轉(zhuǎn)移的有效地址。下面的兩個例子說明了在段內(nèi)間接尋址方式的轉(zhuǎn)移指令中有效地址的計算方法。假設(shè): (DS)= 2000H,(BX)= 2000H,(SI)=3000H,(25000H)=3200H!纠3.9】指令如下。 JMPBX 則執(zhí)行指令后 (IP)=2000H 【例3.10】指令如下。 JMP[BX][SI] 則執(zhí)行指令后 (IP)=(10H×(DS) (BX) (SI)) =(20000H 2000H 3000H) =(25000H) = 3200H 3. 段間直接尋址這種尋址方式直接提供轉(zhuǎn)向的段地址(16位)和偏移地址(16位),所以需要32位的地址信息。只要用指令中指定的偏移地址取代IP寄存器的內(nèi)容,用指定的段地址取代CS寄存器的內(nèi)容就完成了從一個段到另一個段的轉(zhuǎn)移操作。指令格式可表示為: JMPFAR PTR ANOSEG 其中,ANOSEG為轉(zhuǎn)向的符號地址,F(xiàn)AR PTR則是表示段間轉(zhuǎn)移的操作符。4. 段間間接尋址為了達到段間轉(zhuǎn)移,這種尋址方式是用存儲器中的兩個相繼字的內(nèi)容來取代IP和CS。內(nèi)存單元的地址是由指令指定的除立即尋址和寄存器尋址方式以外的任何一種數(shù)據(jù)尋址方式取得。指令格式可表示為: JMPDWORD PTR [DISP BX] 其中,[DISP BX]說明數(shù)據(jù)尋址方式為寄存器間接尋址方式,DWORD PTR為雙字操作符,以滿足段間轉(zhuǎn)移地址的要求。3.28086/8088指令系統(tǒng)計算機的指令系統(tǒng)就是指該計算機能夠執(zhí)行的全部指令的集合。8086/8088指令系統(tǒng)的指令分為7類,即數(shù)據(jù)傳送類、算術(shù)運算類、邏輯操作類、程序控制類、數(shù)據(jù)串操作類、處理器控制類以及輸入/輸出類指令。在學(xué)習(xí)指令系統(tǒng)過程中,以下幾個方面是需要注意的。(1) 掌握指令的功能: 該指令能夠?qū)崿F(xiàn)何種操作,通常指令助記符就是指令功能的英文單詞或其縮寫形式。(2) 分析指令支持的尋址方式: 該指令中的操作數(shù)可以采用何種尋址方式。(3) 清楚指令對標(biāo)志位的影響: 該指令執(zhí)行后是否對各個標(biāo)志位有影響,以及如何影響。(4) 其他特征: 如指令執(zhí)行時的約定設(shè)置、必須預(yù)置的參數(shù)、隱含使用的寄存器等。3.2.1數(shù)據(jù)傳送類指令數(shù)據(jù)傳送是計算機中最基本、最重要的一種操作。傳送指令也是最常使用的一類指令,可以實現(xiàn)數(shù)據(jù)從一個位置到另一個位置的移動,如執(zhí)行寄存器與寄存器之間、寄存器與主存單元之間的字或字節(jié)的多種傳送操作。1. 數(shù)據(jù)傳送指令指令格式: MOVOPRD1,OPRD2 OPRD1為目的操作數(shù),可以是寄存器、存儲器、累加器。OPRD2為源操作數(shù),可以是寄存器、存儲器、累加器和立即數(shù)。本指令的功能是將一個8位或16位的源操作數(shù)(字或字節(jié))送到目的操作數(shù)中,即OPRD1←OPRD2,本指令不影響狀態(tài)標(biāo)志位。MOV指令可以分為以下4種情況。1) 寄存器與寄存器之間的數(shù)據(jù)傳送指令例如: MOVAX,BX MOVCL,AL MOVDX,ES MOVDS,AX MOVBP,SI 代碼段寄存器CS及指令指針I(yè)P不參加數(shù)的傳送,其中CS可以作為源操作數(shù)參加傳送,但不能作為目的操作數(shù)參加傳送。2) 立即數(shù)到通用寄存器的數(shù)據(jù)傳送指令立即數(shù)只能作為源操作數(shù)使用,不能作目的操作數(shù)使用。例如: MOVAL,25H MOVBX,20A0H MOVCH,5 MOVSP,2F00H 注意: 由于傳送的數(shù)據(jù)可能是字節(jié),也可能是字,源操作數(shù)與目的操作數(shù)的類型應(yīng)一致,8位寄存器不能和16位寄存器之間傳送數(shù)據(jù)。例如,25H送AL是允許的,2000H送AL是不允許的。在立即數(shù)參加傳送的情況下,數(shù)據(jù)類型由寄存器確定。當(dāng)立即數(shù)送至存儲器時,不僅其類型應(yīng)該一致,而且還應(yīng)當(dāng)用匯編語言的指示性語句或匯編運算符加以說明。3) 寄存器與存儲器之間的數(shù)據(jù)傳送指令例如: MOVAL,BUF MOVAX,[SI] MOVDISP[BX DI],DL MOVSI,ES: [BP] MOVDS,DATA[BX SI] MOVDISP[BX DI],ES 第一條指令是將存儲器變量BUF的值送至AL寄存器。BUF可以看成是存儲數(shù)據(jù)的單元的符號名,實際上是符號地址,因為該地址單元中的數(shù)據(jù)是可變的,用BUF作為變量名是很合適的。如果是對字進行操作,應(yīng)將指令改寫成如下的形式: MOVAX,BUF 這時匯編語言中在定義BUF變量時,要用DW偽指令將其定義為字類型變量,即在數(shù)據(jù)段中,用如下形式定義: BUFDW1234H 這樣,就可以使用“MOVAX,BUF”指令進行數(shù)據(jù)字的傳送操作。該指令將從地址BUF開始的兩個存儲單元的數(shù)據(jù)送至AX中,即(AX)= 1234H。在數(shù)據(jù)段中,如果用偽指令DB將BUF變量定義為字節(jié)類型,但仍要對從BUF開始的單元進行數(shù)據(jù)字的傳送,則應(yīng)將指令寫成如下形式: MOVAX,WORD PTR BUF 其中PTR稱為指針操作符。其作用是將BUF定義為新的變量類型。這個變量的起始地址沒有改變,但已將BUF變量定義為字類型,因而指令能將一個數(shù)據(jù)字送至AX中,F(xiàn)在再來看第二條指令“MOVAX,[SI]”,其中[SI]屬于寄存器間接尋址,即由段寄存器DS與SI一起確定源操作數(shù)的物理地址。因為是數(shù)據(jù)字傳送,所以該操作數(shù)與求出的物理地址指向的兩個連續(xù)存儲單元有關(guān)。 在指令“MOVDISP[BX DI],DL”中,目的操作數(shù)是存儲器操作數(shù),尋址方式是相對基址變址尋址,也可把它寫作DISP[BX][DI]。匯編語言將對它們進行相同的處理,即有效地址EA = (BX) (DI) DISP。指令“MOVSI,ES: [BP]”有些特殊,源操作數(shù)是存儲器操作數(shù),其尋址方式是寄存器間接尋址。但沒有按照事先的約定,BP與SS段寄存器結(jié)合,找到實際的物理地址。而用“ES: [BP]”告訴匯編程序: BP將與段寄存器ES結(jié)合,即EA =(BP)。與上述指令類似,指令“MOVDS,DATA[BX SI]”中的源操作數(shù)是存儲器操作數(shù),采用相對基址變址方式尋址,有效地址EA =(BX) (SI) DATA!癕OVDISP[BX DI],ES”中的目的操作數(shù)是存儲器操作數(shù),也是相對基址變址尋址,其有效地址為EA =(BX) (DI) DISP。由此可見,只有深刻理解指令中各操作數(shù)的尋址方式,才能正確理解指令的真正含義。同樣要注意,寄存器IP不能參加數(shù)據(jù)傳送,CS寄存器不能作為目的操作數(shù)參與數(shù)據(jù)傳送。4) 立即數(shù)到存儲器的數(shù)據(jù)傳送立即數(shù)只能作為源操作數(shù),且一定要使立即數(shù)與存儲器變量類型一致。存儲器變量的類型可以在數(shù)據(jù)定義時指定,也可以在指令中另行指定,應(yīng)保證其與立即數(shù)的類型一致。否則,匯編程序在匯編時,將指出類型不一致的錯誤。例如: MOVBUF,25 MOVDS: DISP[BP],1234H MOVBYTE PTR [SI],40 以上指令如能正確執(zhí)行,則BUF變量應(yīng)定義為字節(jié)類型,DISP[BP]所指的存儲單元應(yīng)定義為字類型。第三條指令中,用指針操作符PTR重新把[SI]所指的單元定義為字節(jié)類型。在編寫匯編語言程序時,用BYTR PTR[SI]能告訴匯編程序,此處按字節(jié)類型處理,生成相應(yīng)的指令代碼。使用MOV指令傳送數(shù)據(jù),必須注意以下幾點。(1) 立即數(shù)只能作為源操作數(shù),不允許作目的操作數(shù),立即數(shù)也不能送至段寄存器。(2) 通用寄存器可以與段寄存器、存儲器互相傳送數(shù)據(jù),寄存器之間也可以互相傳送數(shù)據(jù)。但是CS不能作為目的操作數(shù)。(3) 存儲器與存儲器之間不能進行數(shù)據(jù)直接傳送。若要實現(xiàn)存儲單元之間的數(shù)據(jù)傳送,可以借助于通用寄存器作為中介來進行。【例3.11】要把DATA1單元的內(nèi)容送至DATA2單元中,并假定這兩個單元在同一個數(shù)據(jù)段中,可以通過以下兩條指令實現(xiàn): MOVAL,DATA1 MOVDATA2,AL 2. 數(shù)據(jù)交換指令數(shù)據(jù)傳送指令單方向地將源操作數(shù)送至目的操作數(shù)存儲單元,而數(shù)據(jù)交換指令則將兩個操作數(shù)相互交換位置,例如: XCHGOPRD1,OPRD2 指令中的OPRD1為目的操作數(shù),OPRD2為源操作數(shù),該指令把源操作數(shù)OPRD2與目的操作數(shù)OPRD1交換。OPRD1及OPRD2可為通用寄存器或存儲器。 圖3.9XCHG指令操作示意圖 XCHG指令不支持兩個存儲器單元之間的數(shù)據(jù)交換,但通過中間寄存器,可以很容易地實現(xiàn)兩個存儲器操作數(shù)的交換。交換操作的示意圖如圖3.9所示。本指令不影響狀態(tài)標(biāo)志位,段寄存器內(nèi)容不能用XCHG指令來交換。以下指令是合法的。 XCHGAX,BX XCHGSI,AX XCHGDL,DH XCHGDX,BUF XCHGWBUF,CX 3. 換碼指令指令格式: XLATTABLE XLAT 以上兩種格式是完全等效的。本指令的功能是把待查表格的一個字節(jié)內(nèi)容送到AL累加器中。其中TABLE為一待查表格的首地址,在執(zhí)行該指令前,應(yīng)將TABLE先送至BX寄存器中,然后將待查字節(jié)與在表格中距表首地址位移量送AL,即: (AL)←((BX) (AL)) 換碼指令常用于將一種代碼轉(zhuǎn)換為另一種代碼,如掃描碼轉(zhuǎn)換為ASCII碼,數(shù)字0~9轉(zhuǎn)換為七段顯示碼等。使用前首先在主存中建立一個字節(jié)表格,表格的內(nèi)容是要轉(zhuǎn)換成的目標(biāo)代碼。由于AL的內(nèi)容實際上是距離表格首地址的位移量,只有8位,所以表格的最大長度為256。超過256的表格需要采用修改BX和AL的方法才能轉(zhuǎn)換。本指令不影響狀態(tài)標(biāo)志位。XLAT指令中沒有顯式指明操作數(shù),而是默認使用BX和AL寄存器。這種采用默認操作數(shù)的方法稱為隱含尋址方式,指令系統(tǒng)中有許多指令采用隱含尋址方式!纠3.12】將首地址為200H的表格緩沖區(qū)中的4號數(shù)據(jù)取出。 MOVBX,200H MOVAL,4 XLAT 4. 堆棧操作指令堆棧被定義為一種先進后出的數(shù)據(jù)結(jié)構(gòu),即最后進棧的元素將被最先彈出來。堆棧從一個稱為棧底的位置開始,數(shù)據(jù)進入堆棧的操作稱為入棧(或壓棧),數(shù)據(jù)退出堆棧的操作稱為出棧,每進行一次出棧操作,堆棧就減少一個元素,最后一次入棧的元素,稱為棧頂元素,入棧操作和出棧操作都是對棧頂元素進行的基本操作。在計算機中,堆棧設(shè)置在一個存儲區(qū)域中。8086/8088的堆棧段的開始位置由(SS)×10H 0000H決定,堆棧段最大為64KB。SP稱為堆棧指針,確切地講是指向棧頂元素的地址指針,由SP的值就可以知道棧頂元素的位置。1) 入棧操作指令實現(xiàn)入棧操作的指令是PUSH指令,其格式為: PUSHOPRD 其中,OPRD為16位(字)操作數(shù),可以是寄存器或存儲器操作數(shù)。PUSH的操作過程是: (SP)←(SP)-2,((SP))←OPRD 即先修改堆棧指針SP(入棧時為自動減2),然后,將指定的操作數(shù)送入新的棧頂位置。此處的((SP))←OPRD,也可以理解為: [(SS)×10H (SP)]←OPRD 或 [SS: SP]←OPRD 例如: PUSHAX PUSHBX 每條指令的操作過程分兩步,首先將SP-1→SP,把AH的內(nèi)容送至由SP所指的單元。接下來再使SP-1→SP,把AL的內(nèi)容送到SP所指的單元。隨著入棧內(nèi)容的增加,堆棧就擴展,SP值減少,但每次操作完,SP總是指向堆棧的頂部。圖3.10(a)給出了入棧操作的情況。以下入棧操作指令都是有效的。 PUSHDX PUSHSI PUSHBP PUSHCS PUSHBUFFER PUSHDAT[BX][SI] 注意: 每進行一次入棧操作,都壓入一個字(16位),例中的BUFFER,DAT[BX][SI]所指的存儲器操作數(shù)應(yīng)該被指定為字類型。2) 出棧操作指令實現(xiàn)出棧操作的指令是POP指令,其格式為: POPOPRD 其中,OPRD為16位(字)操作數(shù),可以是寄存器或存儲器操作數(shù)。POP指令的操作過程是: OPRD←((SP)),(SP)←(SP) 2 它與入棧操作相反,是先彈出棧頂?shù)臄?shù)據(jù),然后再修改指針SP的內(nèi)容(自動加2)。例如: POPBX POPAX 圖3.10(b)給出了出棧操作的情況。 圖3.10入棧和出棧操作 以下出棧操作指令都是有效的。 POPAX POPDS POPBUFFER POPDAT[BX][DI] 其中的BUFFER及DAT[BX][DI]所指的存儲器操作數(shù)也應(yīng)被指定為字類型。PUSH及POP指令對標(biāo)志位沒有影響。 【例3.13】用堆棧操作指令實現(xiàn)兩個存儲器操作數(shù)BUF1及BUF2的交換。 PUSHBUF1 PUSHBUF2 POPBUF1 POPBUF2 5. 標(biāo)志傳送指令1) 取FLAGS標(biāo)志寄存器低8位至AH指令指令格式: LAHF 指令含義為: (AH)←(FLAGS)7~0 該指令不影響FLAGS的原來內(nèi)容,AH只是復(fù)制了原FLAGS的低8位內(nèi)容。2) 將AH存至FLAGS低8位指令指令格式: SAHF 指令含義為: (FLAGS)7~0←(AH) 本指令將用AH的內(nèi)容改寫FLAGS中的SF、ZF、AF、PF和CF標(biāo)志,從而改變原來的標(biāo)志位。3) 將FLAGS內(nèi)容入棧指令指令格式: PUSHF 本指令可以把FLAGS的內(nèi)容保存到堆棧中去。4) 從堆棧中彈出一個數(shù)據(jù)字送至FLAGS中的指令指令格式: POPF 本指令的功能與PUSHF相反,在子程序調(diào)用和中斷服務(wù)程序中,往往用PUSHF指令保護FLAGS的內(nèi)容,用POPF指令將保護的FLAGS內(nèi)容恢復(fù)。6. 地址傳送指令地址傳送指令將存儲器的邏輯地址送至指定的寄存器。1) 有效地址傳送指令指令格式: LEAOPRD1,OPRD2 指令中的OPRD1為目的操作數(shù),可為任意一個16位的通用寄存器。OPRD2為源操作數(shù),可為變量名、標(biāo)號或地址表達式。本指令的功能是將源操作數(shù)給出的有效地址傳送到指定的寄存器中。本指令對標(biāo)志位無影響。例如: LEABX,DATA1 LEADX,BETA[BX SI] LEABX,[BP][DI] 顯然,LEA BX,DATA1的功能是將變量DATA1的地址送至BX,而不是將變量DATA1的值送BX。如果要將一個存儲器變量的地址取至某一個寄存器中,也可以用OFFSET DATA1表達式實現(xiàn)。例如MOV SI,OFFSET DATA1指令,其功能是將存儲器變量DATA1的段內(nèi)偏移地址取至SI寄存器中,OFFSET DATA1表達式的值就是取DATA1的段內(nèi)偏移地址值。因此,LEA BX,DATA1指令與MOV BX,OFFSET DATA1指令的功能是等價的。 圖3.11LDS指令操作示意圖 2) 從存儲器取出32位地址的指令指令格式: LDSOPRD1,OPRD2 LESOPRD1,OPRD2 其中,OPRD1為任意一個16位的寄存器,OPRD2指定了主存的連續(xù)4字節(jié)作為邏輯地址,即32位的地址指針。例如: LDSDI,[BX] 該指令的功能是把BX所指的32位地址指針的段地址送入DS,偏移地址送入DI。指令操作示意圖如圖3.11所示。“LES DI,[BX]”指令除將地址指針的段地址送入ES外,其他與LDS類似。因此圖3.11不僅適用于LDS指令,也適用于LES指令。以下指令是合法的。 LDSSI,ABCD LDSBX,F(xiàn)AST[SI] LESSI,ABCD LESBX,F(xiàn)AST[SI] 注意: 以上指令不影響標(biāo)志位。3.2.2算術(shù)運算類指令算術(shù)運算類指令用來執(zhí)行二進制及十進制的算術(shù)運算,主要包括加、減、乘、除指令。二進制數(shù)運算分為帶符號數(shù)運算和不帶符號數(shù)運算。帶符號數(shù)的最高位是符號位,不帶符號數(shù)所有位都是有效位。十進制數(shù)用BCD碼表示,又分為非壓縮的BCD碼和壓縮的BCD碼兩種形式。算術(shù)運算指令會根據(jù)運算結(jié)果影響狀態(tài)標(biāo)志,有時要利用某些標(biāo)志才能得到正確的結(jié)果。該類指令主要影響6個標(biāo)志位,即CF、AF、SF、ZF、PF和OF。1. 加法指令加法指令能實現(xiàn)字或字節(jié)的加法運算。1) 基本加法指令指令格式: ADDOPRD1,OPRD2 指令含義為: OPRD1 ← OPRD1 OPRD2 OPRD1為目的操作數(shù),可以是任意一個通用寄存器,也可以是任意一個存儲器操作數(shù)。在ADD指令執(zhí)行前,OPRD1的內(nèi)容為一個加數(shù),待ADD指令執(zhí)行后,OPRD1中為加法運算的結(jié)果,即和。這給程序的編寫帶來了很大的方便。OPRD2為源操作數(shù),它可以是立即數(shù),也可以是任意一個通用寄存器或存儲器操作數(shù)。立即數(shù)只能用于源操作數(shù)。OPRD1和OPRD2均為寄存器是允許的,一個為寄存器而另一個為存儲器也是允許的,但不允許兩個都是存儲器操作數(shù)。加法指令運算的結(jié)果對CF、SF、OF、PF、ZF、AF都會有影響。以上標(biāo)志也稱為結(jié)果標(biāo)志。加法指令適用于無符號數(shù)或有符號數(shù)的加法運算。操作數(shù)可以是8位,也可以是16位。例如: ADDAL,38H ADDBX,0A0AH ADDDX,DATA[BX] ADDDI,CX ADDBETA[BX],AX ADDBYTE PTR[BX],55 上述第一條指令及第六條指令為字節(jié)相加指令,其他四條均為字(雙字節(jié))相加指令。第三條指令中,存儲器操作數(shù)是源操作數(shù),采用寄存器相對尋址方式; 第五條指令中,存儲器操作數(shù)是目的操作數(shù),采用寄存器相對尋址方式; 第六條指令中,存儲器操作數(shù)也是目的操作數(shù),采用寄存器間接尋址方式,當(dāng)立即數(shù)與存儲器操作數(shù)做加法時,類型必須一致,故此處用BYTE PTR[BX],將存儲器操作數(shù)的類型重新指定為字節(jié)類型,以保證兩個操作數(shù)類型一致。2) 帶進位加法指令指令格式: ADCOPRD1,OPRD2 指令含義為: OPRD1 ← OPRD1 OPRD2 CF 其中,OPRD1、OPRD2與指令A(yù)DD中的含義一樣。該指令對標(biāo)志位的影響同ADD指令。例如: ADCAL,CL ADCAX,SI ADCDX,MEMA ADCCL,15 ADCWORD PTR[BX][SI],25 本指令適用無符號數(shù)及帶符號數(shù)的8位或16位運算!纠3.14】如果兩個32位的數(shù)據(jù)已分別放在ADNUM1和ADNUM2開始的存儲區(qū)中,存放時低字在前,高字在后,將兩個數(shù)相加,且將和存放在ADNUM3開始的存儲區(qū)中。實現(xiàn)兩個32位數(shù)相加的程序為: MOVAX,ADNUM1 ADDAX,ADNUM2 MOVADNUM3,AX MOVAX,ADNUM1 2 ADCAX,ADNUM2 2 MOVADNUM3 2,AX 由于兩個存儲器操作數(shù)不能直接相加,因而不能通過“ADDADNUM1,ADNUM2”指令進行。3) 加1指令指令格式: INCOPRD 指令含義為: OPRD ← OPRD 1 OPRD為寄存器或存儲器操作數(shù)。這條指令的功能是對給定的除段寄存器以外的任何寄存器或存儲單元內(nèi)容加1后,再送回該操作數(shù),可以實現(xiàn)字節(jié)加1或字加1。本指令執(zhí)行結(jié)果影響AF、OF、PF、SF、ZF標(biāo)志位,但不影響CF標(biāo)志位。例如: INCSI INCWORD PTR[BX] INCBYTE PTR[BX DI] INCCL 上述第二條、第三條這兩條指令,是對存儲字及存儲字節(jié)的內(nèi)容加1以替代原來的內(nèi)容。在循環(huán)程序中,常用該指令對地址指針和循環(huán)計數(shù)值進行修改。2. 減法指令1) 基本減法指令指令格式: SUBOPRD1,OPRD2 本指令的功能是進行兩個操作數(shù)的相減,即: OPRD1 ← OPRD1 - OPRD2 本指令的類型及對標(biāo)志位的影響與ADD指令相同,注意立即數(shù)不能用于目的操作數(shù),兩個存儲器操作數(shù)之間不能直接相減。操作數(shù)可為8位或16位的無符號數(shù)或帶符號數(shù)。例如: SUBDX,CX SUB[BX 25],AL SUBDI,ALFA[SI] SUBCL,20 2) 帶借位減法指令指令格式: SBBOPRD1,OPRD2 其中,OPRD1、OPRD2的含義及指令對標(biāo)志位的影響等均與SUB指令相同。完成的操作為: OPRD1←OPRD1-OPRD2-CF。例如: SBBDX,CX SBBBX,2000H SBBAX,DATA1 SBBALFA[BX SI],SI 3) 減1指令指令格式: DECOPRD 其中,OPRD的含義與INC指令相同,本指令的功能是OPRD ←OPRD -1。對標(biāo)志位影響同INC指令。例如: DECAX DECCL DECWORD PTR[DI] DECALFA[DI BX] 4) 取補指令指令格式: NEGOPRD OPRD為任意通用寄存器或存儲器操作數(shù)。NEG指令也是一個單操作數(shù)指令,它對操作數(shù)執(zhí)行求補運算,即用0減去操作數(shù),然后將結(jié)果返回操作數(shù)。求補運算也可以表達成: 將操作數(shù)按位取反后加1。NEG指令對標(biāo)志位的影響與用0做減法的SUB指令一樣。例如: (AL)=44H,取補后,(AL)=0BCH(-44H)。5) 比較指令指令格式: CMPOPRD1,OPRD2 其中,OPRD1和OPRD2可為任意通用寄存器或存儲器操作數(shù),但兩者不同時為存儲器操作數(shù),立即數(shù)可用做源操作數(shù)OPRD2。本指令對標(biāo)志位的影響同SUB指令,完成的操作與SUB指令類似,唯一的區(qū)別是不將OPRD1-OPRD2的結(jié)果送回OPRD1,而只是比較。因而不改變OPRD1和OPRD2的內(nèi)容,該指令用于改變標(biāo)志位。例如: CMPAL,56H CMPDX,CX CMPAX,DATA1[BX] CMPBATE[DI],BX 以CMPDX,CX為例,對標(biāo)志位的影響如下: (1) (DX)=(CX)時,則ZF=1。(2) 兩個無符號數(shù)比較: 若(DX)>(CX),則CF=0,即無借位; 若(DX)<(CX),則CF=1,即有借位。(3) 兩個帶符號數(shù)比較: 可以通過溢出標(biāo)志OF及符號標(biāo)志SF共同來判斷兩個數(shù)的大小。當(dāng)OF=0,即無溢出時,若SF=0,則(DX)>(CX); 若SF=1,則(DX)<(CX)。當(dāng)OF=1,即有溢出時,若SF=1,則(DX)>(CX); 若SF=0,則(DX)<(CX)。3. 乘法指令1) 無符號數(shù)乘法指令指令格式: MULOPRD 其中,OPRD為源操作數(shù),即乘數(shù)。OPRD為通用寄存器或存儲器操作數(shù)。目的操作數(shù)是隱含的,即被乘數(shù)總是指定為累加器AX或AL的內(nèi)容。16位乘法時,AX中為被乘數(shù); 8位乘法時,AL為被乘數(shù)。16位乘法的32位乘積存于DX及AX中; 8位乘法的16位乘積存于AX中。操作過程如下。(1) 字節(jié)相乘: (AX)←(AL)×OPRD,當(dāng)結(jié)果的高位字節(jié)(AH)≠0時,則CF=1,OF=1。(2) 字相乘: (DX)(AX)←(AX)×OPRD,當(dāng)(DX)≠0時,則CF=1,OF=1。例如: MULBETA[BX] MULDI MULBYTE PTR ALFA 【例3.15】設(shè)在DAT1和DAT2字單元中各有一個16位數(shù),若求其乘積并存于DAT3開始的字單元中,可用以下指令組實現(xiàn): MOVAX,DAT1 MULDAT2 MOVDAT3,AX MOVDAT3 2,DX 2) 帶符號數(shù)乘法指令指令格式: IMULOPRD 其中,OPRD為任一通用寄存器或存儲器操作數(shù)。隱含操作數(shù)的定義與MUL指令相同。本指令的功能是完成兩個帶符號數(shù)的相乘。MUL和IMUL指令影響標(biāo)志位CF及OF。計算二進制數(shù)乘法: B4H×11H。如果把它當(dāng)作無符號數(shù),用MUL指令,則乘的結(jié)果為0BF4H; 如果看作有符號數(shù),用IMUL指令,則乘的結(jié)果為FAF4H。由此可見,同樣的二進制數(shù)看作無符號數(shù)與有符號數(shù)相乘,即采用MUL與IMUL指令,其運算結(jié)果是不相同的。4. 除法指令1) 無符號數(shù)除法指令指令格式: DIVOPRD 其中,OPRD為任一通用寄存器或存儲器操作數(shù)。本指令的功能是實現(xiàn)兩個無符號二進制除法運算。字節(jié)相除,被除數(shù)在AX中; 字相除,被除數(shù)在DX、AX中,除數(shù)在OPRD中。操作過程如下。(1) 字節(jié)除法: (AL)←(AX)/OPRD,(AH)←(AX) MOD OPRD。(2) 字除法: (AX)←(DX)(AX)/OPRD,(DX)←(DX)(AX) MOD OPRD。例如: DIVBETA[BX] DIVCX DIVBL 2) 帶符號數(shù)除法指令指令格式: IDIVOPRD 其中,OPRD為任一通用寄存器或存儲器操作數(shù)。隱含操作數(shù)的定義與DIV指令相同。本指令的功能是實現(xiàn)兩個帶符號數(shù)的二進制除法運算,余數(shù)的符號與被除數(shù)符號相同。除法指令DIV和IDIV不產(chǎn)生有效的標(biāo)志位,但是卻可能產(chǎn)生溢出。當(dāng)被除數(shù)遠大于除數(shù)時,所得的商就有可能超出它所能表達的范圍。對DIV指令,除數(shù)為0,或者在字節(jié)除法時商大于255,字除法時商大于65535,則發(fā)生除法溢出。對IDIV指令,除數(shù)為0,或者在字節(jié)除法時商不在-128~127范圍內(nèi),或者在字除法時商不在-32768~32767范圍內(nèi),則發(fā)生除法溢出。3) 字節(jié)擴展指令符號擴展是指用一個操作數(shù)的符號位(即最高位)形成另一個操作數(shù),后一個操作數(shù)的各位是全0(正數(shù))或全1(負數(shù))。符號擴展指令可用來將字節(jié)轉(zhuǎn)換為字,字轉(zhuǎn)換為雙字。有符號數(shù)通過符號擴展加長了位數(shù),但數(shù)據(jù)大小并沒有改變。符號擴展指令不影響標(biāo)志位。指令格式: CBW 本指令的功能是將字節(jié)擴展為字,即把AL寄存器的符號位擴展到AH中。即兩個字節(jié)相除時,先使用本指令形成一個雙字節(jié)長的被除數(shù)。例如: MOVAL,34 CBW IDIVBYTE PTR DATA1 4) 字?jǐn)U展指令指令格式: CWD 本指令的功能是將字?jǐn)U展為雙字長,即把AX寄存器的符號位擴展到DX中。即兩個字相除時,先使用本指令形成一個雙字長的被除數(shù)。符號擴展指令常用來獲得除法指令所需要的被除數(shù)。例如AX=FF00H,它表示有符號數(shù)-256; 執(zhí)行CWD指令后,則DX=FFFFH,DX、AX仍表示有符號數(shù)-256。對無符號數(shù)除法應(yīng)該采用直接使用高8位或高16位清0的方法,獲得倍長的被除數(shù)。這就是0位擴展!纠3.16】在DAT1、DAT2、DAT3字節(jié)類型變量中,分別存有8位帶符號數(shù)a、b、c,用程序?qū)崿F(xiàn) (a*b c)/a運算。程序如下: MOVAL,DAT1 IMULDAT2 MOVCX,AX MOVAL,DAT3 CBW ADDAX,CX IDIVDAT1 5. 十進制調(diào)整指令為了方便進行十進制的運算,8086/8088提供了一組十進制數(shù)調(diào)整指令。這組指令對二進制運算的結(jié)果進行十進制調(diào)整,以得到十進制的運算結(jié)果。十進制數(shù)在計算機中也要用二進制編碼表示,這就是二進制編碼的十進制數(shù): BCD碼。8086/8088支持壓縮BCD碼和非壓縮BCD碼,相應(yīng)地十進制調(diào)整指令分為壓縮BCD碼的調(diào)整指令和非壓縮BCD碼的調(diào)整指令。壓縮BCD碼是通常的8421碼,它用4個二進制位表示一個十進制位,一個字節(jié)可以表示兩個十進制位,即00~99。壓縮BCD碼調(diào)整指令包括加法和減法的十進制調(diào)整指令DAA和DAS,它們用來對二進制加、減法指令的執(zhí)行結(jié)果進行調(diào)整,得到十進制結(jié)果。非壓縮BCD碼用8個二進制位表示一個十進制位,實際上只是用低4個二進制位表示一個十進制位0~9,高4位通常默認為0。ASCII碼中0~9的編碼是30H~39H,所以0~9的ASCII碼(高4位變?yōu)?)就可以認為是非壓縮的BCD碼。非壓縮BCD碼調(diào)整指令包括AAA、AAS、AAM和AAD四條指令,分別用于對二進制加、減、乘、除指令的結(jié)果進行調(diào)整,以得到非壓縮BCD碼表示的十進制數(shù)結(jié)果。由于只要在調(diào)整后的結(jié)果中加上30H就成為十進制數(shù)位的ASCII碼,因此這組指令實際上也是針對ASCII碼的調(diào)整指令。在進行十進制數(shù)算術(shù)運算時,應(yīng)分兩步進行: 先按二進制數(shù)運算規(guī)則進行運算,得到中間結(jié)果; 再用十進制調(diào)整指令對中間結(jié)果進行修正,得到正確的結(jié)果。下面通過幾個例子說明BCD碼運算為什么要調(diào)整以及怎樣調(diào)整!纠3.17】24 33=57。24的BCD碼為00100100B,33的BCD碼為00110011B,57的BCD碼為01010111B。24 33的二進制算式如下: 00100100 00110011 01010111結(jié)論: 結(jié)果正確,不需要調(diào)整!纠3.18】27 54=81。27的BCD碼為00100111B,54的BCD碼為01010100B,81的BCD碼為10000001B。27 54的二進制算式如下: 00100111 01010100 01111011結(jié)果不正確,因為在進行二進制加法運算時,低4位向高4位有一個進位,這個進位是按十六進制進行的,即低4位逢十六才進一,而十進制數(shù)應(yīng)是逢十進一。因此,比正確結(jié)果少6,這時應(yīng)在低4位上進行加6處理,調(diào)整的算式如下: 00100111 01010100 01111011 00000110 10000001調(diào)整后的結(jié)果正確。結(jié)論: 加法運算后,低4位若向高4位有進位(即AF=1)時,應(yīng)對低4位做加06H處理!纠3.19】97 81=178。97的BCD碼為10010111B,81的BCD碼為10000001B,178的BCD碼為000101111000B。97 81的二進制算式如下: 10010111 10000001 CF←100011000結(jié)果不正確,因為高4位向CF的進位是按十六進制進行的,應(yīng)加60H進行調(diào)整。調(diào)整的算式如下: 10010111 10000001 CF←100011000 01100000 01111000調(diào)整后的結(jié)果正確。結(jié)論: 加法運算后,當(dāng)CF=1(有進位產(chǎn)生)時,應(yīng)做加60H處理。【例3.20】64 48=112。64的BCD碼為01100100B,48的BCD碼為01001000B,112的BCD碼為000100010010B。64 48的二進制算式如下: 01100100 01001000 10101100結(jié)果不正確,因為低4位大于9,且高4位也大于9。先加06H調(diào)整低4位,再加60H調(diào)整高4位。調(diào)整的算式如下: 01100100 01001000 10101100 00000110 10110010 01100000 CF←100010010調(diào)整后的結(jié)果正確。結(jié)論: 加法運算后,低4位大于9時,需做加06H處理; 高4位大于9時,需做加60H處理。下面介紹十進制數(shù)的調(diào)整指令。1) DAA指令指令格式: DAA DAA指令為無操作數(shù)指令。用以完成對壓縮的BCD碼加法運算進行校正。一般在ADD指令之后,緊接著用一條DAA指令加以校正,在AL中可以得到正確的結(jié)果。DAA指令的校正操作如下。(1) 若(AL∧0FH)>9或標(biāo)志位AF=1,則 AL←(AL) 6 AF←1 (2) 若AL>9FH或標(biāo)志CF=1,則 CF←AF AL←AL∧0FH AL←(AL) 60H CF←1 DAA指令影響標(biāo)志位AF、CF、PF、SF、ZF,而對OF未定義。2) DAS指令指令格式: DAS DAS指令為無操作數(shù)指令。用以完成對壓縮的BCD碼相減的結(jié)果進行校正,得到正確的壓縮的十進制差。一般在SUB指令之后,緊接著用一條DAS指令加以校正,在AL中可以得到正確的結(jié)果。DAS指令校正的操作如下。(1) 若(AL∧0FH)>9或標(biāo)志位AF=1,則 AL←(AL)-6 AF←1 (2) 若AL>9FH或標(biāo)志CF=1,則 AL←(AL)-60H CF←1 DAS指令執(zhí)行時,影響標(biāo)志位AF、CF、PF、SF、ZF,而對OF未定義。3) AAA指令指令格式: AAA AAA指令為無操作數(shù)指令。AAA指令對在AL中的兩個非壓縮的十進制數(shù)相加后的結(jié)果進行校正。兩個非壓縮的十進制數(shù)可以直接用ADD指令相加,但要得到正確的非壓縮的十進制結(jié)果,必須在ADD指令之后,用一條AAA指令加以校正,在AX中可以得到正確的結(jié)果。AAA指令進行校正的操作如下。若(AL∧0FH)>9或標(biāo)志位AF=1,則 AL←(AL) 6 AH←(AH) 1 AF←1 CF←AF AL←AL∧0FH AAA指令對標(biāo)志位AF和CF有影響,而對OF、PF、SF、ZF未定義。4) AAS指令指令格式: AAS AAS指令為無操作數(shù)指令。AAS指令把AL中兩個非壓縮的十進制數(shù)相減后的結(jié)果進行校正,產(chǎn)生一個正確的非壓縮的十進制數(shù)差。AAS指令進行校正的操作如下。若(AL∧0FH)>9或標(biāo)志位AF=1,則 AL←(AL)-6 AH←(AH)-1 AF←1 CF←AF AL←AL∧0FH AAS指令影響標(biāo)志位AF和CF,而對OF、PF、SF、ZF位未定義。5) AAM指令指令格式: AAM AAM指令執(zhí)行的操作為: 把AL中的積調(diào)整到非壓縮的BCD格式后送給AX寄存器。這條指令之前必須執(zhí)行MUL指令把兩個非壓縮的BCD碼相乘(此時要求其高4位為0),結(jié)果放在AL寄存器中。本指令的調(diào)整方法是: 把AL寄存器的內(nèi)容除以0AH,商放在AH寄存器中,余數(shù)保存在AL寄存器中。本指令根據(jù)AL寄存器的內(nèi)容設(shè)置標(biāo)志位SF、ZF和PF,但對OF、CF和AF標(biāo)志位無影響。6) AAD指令指令格式: AAD 前面所述的對非壓縮BCD碼的調(diào)整指令都是在完成相應(yīng)的加法、減法及乘法運算后,再使用AAA、AAS及AAM指令來對運算結(jié)果進行十進制調(diào)整的。除法的情況卻不同,它針對的情況如下所述。如果被除數(shù)是存放在AX寄存器中的兩位非壓縮BCD數(shù),AH中存放十位數(shù),AL中存放個位數(shù),而且要求AH和AL中的高4位均為0。除數(shù)是一位非壓縮的BCD數(shù),同樣要求高4位為0。在把這兩個數(shù)用DIV指令相除以前,必須先用AAD指令把AX中的被除數(shù)調(diào)整成二進制數(shù),并存放在AL寄存器中。因此,AAD指令執(zhí)行的操作是: 10×AH AL→AL 0→AH 這條指令根據(jù)AL寄存器的內(nèi)容設(shè)置標(biāo)志位SF、ZF和PF,但對OF、CF和AF標(biāo)志位無影響。3.2.3邏輯操作類指令邏輯操作類指令是按位操作指令,可以對8位或16位的寄存器或存儲單元的內(nèi)容按位操作。該類指令包括邏輯運算指令、移位指令和循環(huán)移位指令。1. 邏輯運算指令邏輯運算指令用來對字或字節(jié)按位進行邏輯運算,包括邏輯與AND、邏輯或OR、邏輯非NOT、邏輯異或XOR和測試TEST五條指令。1) 邏輯與運算指令指令格式: ANDOPRD1,OPRD2 其中,目的操作數(shù)OPRD1為任一通用寄存器或存儲器操作數(shù),源操作數(shù)OPRD2為立即數(shù)、任一通用寄存器或存儲器操作數(shù)。也就是在這兩個操作數(shù)中,源操作數(shù)可以是任意的尋址方式,而目的操作數(shù)只能是立即數(shù)之外的其他尋址方式,并且兩個操作數(shù)不能同時為存儲器尋址方式。AND指令實現(xiàn)對兩個操作數(shù)按位進行邏輯與的運算,結(jié)果送至目的操作數(shù)。本指令可以進行字節(jié)或字的“與”運算。AND指令影響標(biāo)志位PF、SF、ZF,使CF=0,OF=0。例如,在同一個通用寄存器自身相與時,操作數(shù)雖不變,但使CF置0。本指令主要用于修改操作數(shù)或置某些位為0。例如: ANDAL,0FH ANDAX,BX ANDDX,BUF1[DI BX] ANDBYTE[BX],00FFH 上例中的第一條指令,將使AL寄存器的高4位置成零保持AL低4位值不變。2) 邏輯或運算指令指令格式: OROPRD1,OPRD2 其中,OPRD1、OPRD2的含義與AND指令相同,對標(biāo)志位的影響也與AND指令相同。唯一不同的地方是,OR指令完成對兩個操作數(shù)按位“或”的運算,結(jié)果送至目的操作數(shù)中。本指令可以進行字節(jié)或字的“或”運算。OR指令可用于置位某些位,而不影響其他位。這時只需將要置1的位同“1”相或,維持不變的位同“0”相或即可。3) 邏輯非運算指令指令格式: NOTOPRD 其中,OPRD可為任一通用寄存器或存儲器操作數(shù)。本指令的功能是完成對操作數(shù)的按位求反運算,結(jié)果送回給原操作數(shù),本指令可以進行字節(jié)或字的“非”運算,不影響標(biāo)志位。4) 邏輯異或運算指令指令格式: XOROPRD1,OPRD2 其中,OPRD1、OPRD2的含義與AND指令相同,對標(biāo)志位的影響也與AND指令相同。本指令的功能是實現(xiàn)兩個操作數(shù)按位“異或”的運算,即相“異或”的兩位不相同時,結(jié)果是1; 否則,“異或”的結(jié)果為0,結(jié)果送至目的操作數(shù)中。XOR指令可以實現(xiàn)字節(jié)或字的“異或”運算。XOR可以用于求反某些位,而不影響其他位。要求求反的位同“1”異或,維持不變的位同“0”異或。例如,XORBL,00010001B指令的功能是將BL中D0和D4求反,其余位不變; XORAX,AX可以實現(xiàn)對AX寄存器內(nèi)容清0。5) 測試指令指令格式: TESTOPRD1,OPRD2 其中,OPRD1、OPRD2的含義同AND指令,對標(biāo)志位的影響也與AND指令相同。該指令與AND指令一樣,也是對兩個操作數(shù)進行按位的“與”運算,唯一不同之處是不將相“與”的結(jié)果送目的操作數(shù),即本指令對兩個操作數(shù)的內(nèi)容均不進行修改,僅是在邏輯“與”操作后,對標(biāo)志位重新置位。TEST指令通常用于檢測一些條件是否滿足,但又不希望改變原操作數(shù)的情況。這條指令之后,一般都是條件轉(zhuǎn)移指令,目的是利用測試條件轉(zhuǎn)向不同的程序段!纠3.21】寫出判斷寄存器AX中D3和D9位是否為0的指令。 TESTAX,0008H TESTAX,0200H 2. 邏輯移位指令8086/8088指令系統(tǒng)的移位指令包括邏輯左移SHL、算術(shù)左移SAL、邏輯右移SHR、算術(shù)右移SAR等指令,其中SHL和SAL指令的操作完全相同。移位指令的操作對象可以是一個8位或16位的寄存器或存儲單元。移位操作可以是向左或向右移一位,也可以移多位。當(dāng)要求移多位時,指令規(guī)定移位位數(shù)(次數(shù))必須放在CL寄存器中,即指令中規(guī)定的移位次數(shù)不允許是1以外的常數(shù)或CL以外的寄存器。移位指令都影響狀態(tài)標(biāo)志位,但影響的方式各條指令不盡相同。1) 邏輯左移指令指令格式: SHLOPRD1,COUNT 其中,OPRD1為目的操作數(shù),可以是通用寄存器或存儲器操作數(shù)。COUNT代表移位的次數(shù)(或位數(shù))。移位一次,COUNT=1,移位多于一次時,COUNT=(CL),(CL)中為移位的次數(shù)。本指令的功能是對給定的目的操作數(shù)(8位或16位)左移COUNT次,每次移位時最高位移入標(biāo)志位CF中,最低位補0。本指令對標(biāo)志位OF、PF、SF、ZF、CF有影響。2) 邏輯右移指令指令格式: SHROPRD1,COUNT 其中,OPRD1、COUNT與指令SHL中意義相同。與SHL一樣,SHR指令也影響標(biāo)志位OF、PF、SF、ZF和CF。所不同的是,本指令實現(xiàn)由COUNT決定次數(shù)的邏輯右移操作,每次移位時,最高位補零,最低位移至標(biāo)志位CF中。例如: SHLBL,1 SHLCX,1 SHLALFA[DI],1 或者: MOVCL,3 SHRDX,CL SHRDAT[DI],CL 上例中前三條指令完成目的操作數(shù)邏輯左移1位的運算; 而后兩條移位指令,則實現(xiàn)由CL內(nèi)容指定的次數(shù)的右移運算,由于(CL)=3,故分別對目的操作數(shù)邏輯右移3位。3) 算術(shù)左移指令指令格式: SALOPRD1,COUNT 其中,OPRD1、COUNT與指令SHL中意義相同。本指令與SHL的功能也完全相同,這是因為邏輯左移指令與算術(shù)左移指令所要完成的操作是一樣的。如果SAL將OPRD1的最高位移至CF,改變了原來的CF值,則溢出標(biāo)志位OF=1,表示移位前后的操作數(shù)不再具有倍增的關(guān)系。因而SAL可用于帶符號數(shù)的倍增運算,SHL只能用于無符號數(shù)的倍增運算。4) 算術(shù)右移指令指令格式: SAROPRD1,COUNT 其中,OPRD1、COUNT與指令SHL中意義相同。本指令通常用于對帶符號數(shù)減半的運算中,因而在每次右移時,保持最高位(符號位)不變,最低位右移至CF中。圖3.12給出了上述四條移位指令的操作示意圖。 圖3.12移位指令操作示意圖 3. 循環(huán)移位指令能實現(xiàn)操作數(shù)首尾相連的移位操作是循環(huán)移位指令。循環(huán)移位指令類似于移位指令,但要從一端移出的位返回到另一端形成循環(huán)。按進位標(biāo)志CF是否參加循環(huán)移位,又可分為不帶CF的循環(huán)移位指令和帶CF的循環(huán)移位指令兩類,每一類都可進行左移或右移,循環(huán)移位的次數(shù)由COUNT操作數(shù)給出。1) 不帶進位循環(huán)左移指令指令格式: ROLOPRD1,COUNT 2) 不帶進位循環(huán)右移指令指令格式: ROROPRD1,COUNT 3) 帶進位循環(huán)左移指令指令格式: RCLOPRD1,COUNT 4) 帶進位循環(huán)右移指令指令格式: RCROPRD1,COUNT 循環(huán)移位指令的操作數(shù)形式與移位指令相同,如果僅移動一次,可以用1表示; 如果需要移動多次,則需用CL寄存器表示移位次數(shù)。這組指令只對標(biāo)志位CF和OF有影響。CF由移入CF的內(nèi)容決定,OF取決于移位一次后符號位是否改變,如改變,則OF=1。由于是循環(huán)移位,因此對字節(jié)移位8次,對字移位16次,就可恢復(fù)為原操作數(shù)。由于帶CF的循環(huán)移位,可以將CF的內(nèi)容移入,因此可以利用它實現(xiàn)多字節(jié)的循環(huán)。循環(huán)移位指令的操作示意圖如圖3.13所示。 圖3.13循環(huán)移位指令操作示意圖 【例3.22】有兩位BCD數(shù)存放在BUFFER單元,要求將其轉(zhuǎn)換為ASCII碼,存于RESULT開始的兩個地址單元,并測試是否有字節(jié)為'0'的ASCII碼,如有,則CF=1,結(jié)束操作。程序如下: MOVAL,BUFFER ANDAL,0F0H MOVCL,4 SHRAL,CL ORAL,30H CMPAL,30H JZZERO MOVRESULT,AL MOVAL,BUFFER ANDAL,0FH ORAL,30H CMPAL,30H JZZERO MOVRESULT 1,AL JMPEXX ZERO: STC EXX: HLT 本程序?qū)UF單元中的兩位BCD數(shù)分離后,用ORAL,30H將AL中的BCD數(shù)轉(zhuǎn)換為ASCII碼,這是因為'0'到'9'的ASCII碼為30H至39H。同理,用比較指令CMPAL,30H 可判斷AL中內(nèi)容是否為30H,若是,則ZF=1; 否則,ZF=0。程序針對這兩種情況,作兩種不同的處理。3.2.4程序控制類指令在8086/8088指令系統(tǒng)中,程序的執(zhí)行序列是由代碼段寄存器CS和指令指針I(yè)P確定的。CS包含當(dāng)前指令所在代碼段的段地址,IP則是要執(zhí)行的下一條指令的偏移地址。程序的執(zhí)行一般依指令序列順序執(zhí)行,但有時需用改變程序的流程?刂妻D(zhuǎn)移類指令通過修改CS和IP寄存器的值來改變程序的執(zhí)行順序,包括五組指令: 無條件轉(zhuǎn)移指令、有條件轉(zhuǎn)移指令、循環(huán)指令、過程調(diào)用和返回指令以及中斷指令。利用程序控制類指令,可以實現(xiàn)分支、循環(huán)、子程序等程序結(jié)構(gòu)。1. 無條件轉(zhuǎn)移指令指令格式: JMPOPRD 其中,OPRD為轉(zhuǎn)移的目的地址。程序轉(zhuǎn)移到目的地址所指向的指令后繼續(xù)向下執(zhí)行。無條件轉(zhuǎn)移,就是無任何先決條件就能使程序改變執(zhí)行順序。處理器只要執(zhí)行無條件轉(zhuǎn)移指令JMP,就能使程序轉(zhuǎn)移到指定的目標(biāo)地址處。目標(biāo)地址操作數(shù)的尋址方法可以是相對尋址、直接尋址或間接尋址。相對尋址方式以當(dāng)前IP為基礎(chǔ),加上位移量構(gòu)成目標(biāo)地址。目標(biāo)地址像立即數(shù)一樣,直接在指令的機器代碼中就是直接尋址方式。目標(biāo)地址如果在寄存器或主存單元中,就是通過寄存器或存儲器的間接尋址方式。相對尋址方式根據(jù)位移量進行轉(zhuǎn)移,方便了程序段在內(nèi)存中的動態(tài)加載,是最常用的目標(biāo)地址尋址方式。例如,同樣的一段程序,如果改變了內(nèi)存地址,轉(zhuǎn)移的目的地址也就改變了,但是轉(zhuǎn)移指令與目的指令之間的位移并沒有因此改變。JMP指令可以將程序轉(zhuǎn)移到1MB存儲空間的任何位置。根據(jù)跳轉(zhuǎn)的距離,JMP指令分成了段內(nèi)轉(zhuǎn)移和段間轉(zhuǎn)移。段內(nèi)轉(zhuǎn)移是指在當(dāng)前代碼段64KB范圍內(nèi)轉(zhuǎn)移,因此不需要更改CS段地址,只要改變IP偏移地址。如果轉(zhuǎn)移范圍用1字節(jié)(-128~127)表達,則可以形成所謂的“短轉(zhuǎn)移short jump”; 如果地址位移用一個16位數(shù)表達,則形成“近轉(zhuǎn)移near jump”,它是在±32KB范圍內(nèi)。段間轉(zhuǎn)移是指從當(dāng)前代碼段跳轉(zhuǎn)到另一個代碼段,此時需要更改CS段地址和IP偏移地址,這種轉(zhuǎn)移也稱為“遠轉(zhuǎn)移far jump”。轉(zhuǎn)移的目標(biāo)地址必須用一個32位數(shù)表達,叫作32位遠指針,它就是邏輯地址。由此可見,JMP指令根據(jù)目標(biāo)地址不同的提供方法和內(nèi)容,可以分為以下4種格式。(1) 段內(nèi)轉(zhuǎn)移,相對尋址。(2) 段內(nèi)轉(zhuǎn)移,間接尋址。(3) 段間轉(zhuǎn)移,直接尋址。(4) 段間轉(zhuǎn)移,間接尋址。以下指令為合法的無條件轉(zhuǎn)移指令: JMPSHORT TARGET JMPTARGET JMPAX JMPTABLE[BX] JMPWORD PTR [BP][DI] JMPFAR PTR LABLE JMPVAR_DOUBLEWORD JMPDWORD PTR [BP][DI] 2. 條件轉(zhuǎn)移指令指令格式: JCCOPRD 條件轉(zhuǎn)移指令只有一個操作數(shù)OPRD,用以指明轉(zhuǎn)移的目的地址。指令助記符中的“CC”表示條件。這種指令的執(zhí)行包括兩個過程: 第一步,測試規(guī)定的條件; 第二步,如果條件滿足,則轉(zhuǎn)移到目標(biāo)地址; 否則,繼續(xù)順序執(zhí)行。條件轉(zhuǎn)移指令的操作數(shù)必須是一個短標(biāo)號,也就是說,所有的條件轉(zhuǎn)移指令都是兩字節(jié)指令,轉(zhuǎn)移指令的下一條指令到目標(biāo)地址之間的距離必須為-128~127。如果指令規(guī)定的條件滿足,則將這個位移量加到IP寄存器上,以實現(xiàn)程序的轉(zhuǎn)移。絕大多數(shù)條件轉(zhuǎn)移指令(除JCXZ指令外)將狀態(tài)標(biāo)志位的狀態(tài)作為測試的條件。因此,首先應(yīng)該執(zhí)行影響有關(guān)的狀態(tài)標(biāo)志位的指令,然后才能用條件轉(zhuǎn)移指令測試這些標(biāo)志,以確定程序是否轉(zhuǎn)移。CMP和TEST指令常常與條件轉(zhuǎn)移指令配合使用,因為這兩條指令不改變目的操作數(shù)的內(nèi)容,但可以影響狀態(tài)標(biāo)志位。8086/8088的條件轉(zhuǎn)移指令非常豐富,不僅可以測試一個狀態(tài)標(biāo)志位的狀態(tài),而且可以綜合測試幾個狀態(tài)標(biāo)志位; 不僅可以測試無符號數(shù)的高低,而且可以測試帶符號數(shù)的大小等,編程時使用十分靈活、方便。所有的條件轉(zhuǎn)移指令的名稱、助記符及轉(zhuǎn)移條件等列在表3.2中。其中同一行內(nèi)用斜杠隔開的幾個助記符,實質(zhì)上代表同一條指令的幾種不同的表示方法。 表3.2條件轉(zhuǎn)移指令 指 令 名 稱助記符轉(zhuǎn) 移 條 件說明 等于/零轉(zhuǎn)移JE/JZZF=1不等于/非零轉(zhuǎn)移JNE/JNZZF=0負轉(zhuǎn)移JSSF=1正轉(zhuǎn)移JNSSF=0“1”的個數(shù)為偶轉(zhuǎn)移JP/JPEPF=1“1”的個數(shù)為奇轉(zhuǎn)移JNP/JPOPF=0溢出轉(zhuǎn)移JOOF=1不溢出轉(zhuǎn)移JNOOF=0進位轉(zhuǎn)移JCCF=1不進位轉(zhuǎn)移JNCCF=0判斷單個標(biāo)志位狀態(tài)續(xù)表 指 令 名 稱助記符轉(zhuǎn) 移 條 件說明 低于/不高于或等于轉(zhuǎn)移JB/JANECF=1高于或等于/不低于轉(zhuǎn)移JAE/JNBCF=0高于/不低于或等于轉(zhuǎn)移JA/JNBECF=1且ZF=0低于或等于/不高于轉(zhuǎn)移JBE/JNACF=0或ZF=1用于無符號數(shù)的比較 大于/不小于或等于轉(zhuǎn)移JG/JNLESF=OF且ZF=0大于或等于/不小于轉(zhuǎn)移JGE/JNLSF=OF小于/不大于或等于轉(zhuǎn)移JL/JNGESF≠OF且ZF=0小于或等于/不大于轉(zhuǎn)移JLE/JNGSF≠OF或ZF=1用于帶符號數(shù)的比較 CX等于零轉(zhuǎn)移JCXZ(CX)=0不用判斷標(biāo)志位狀態(tài) 比較兩個無符號數(shù)大小的指令,通常是根據(jù)一個標(biāo)志位或兩個標(biāo)志位以確定兩個數(shù)的大小。為了與帶符號數(shù)的大小相區(qū)別,無符號數(shù)比較常用高于、低于來表示。帶符號數(shù)比較常用大于、小于來表示。以上兩種表示方法一定要能正確地區(qū)分開,否則就不能正確理解和使用這些指令。【例3.23】設(shè)計一段程序?qū)崿F(xiàn)以下功能: 如果AL最高位為0,則設(shè)置AH=0; 如果AL最高位為1,則設(shè)置AH=FFH。程序段如下: TESTAL,80H JZNEXT0 MOVAH,0FFH JMPDONE NEXT0: MOVAH,0 DONE: … 【例3.24】設(shè)X和Y為存放于X單元和Y單元的16位操作數(shù),計算|X-Y|,并將結(jié)果存入RESULT單元中。程序段如下: MOVAX,X SUBAX,Y JNSNONNEG NEGAX NONNEG: MOVRESULT,AX 【例3.25】完成下式的判定運算。Y=1X≥0 0X<0實現(xiàn)的程序如下: MOVAL,X CMPAL,0 JGEA1 MOVAL,0 JMPA2 A1: MOVAL,1 A2: MOVY,AL … 以上程序段中的X、Y是兩個存儲器變量,把X當(dāng)成帶符號數(shù)與0比較。 3. 循環(huán)控制指令循環(huán)是一種特殊的轉(zhuǎn)移流程,當(dāng)滿足(不滿足)某條件時,反復(fù)執(zhí)行一系列操作,直到不滿足(滿足)條件為止。循環(huán)流程的條件一般是循環(huán)計數(shù),指令約定用CX寄存器作為計數(shù)器。在程序中用循環(huán)計數(shù)來控制循環(huán)次數(shù)。這類指令屬于段內(nèi)SHORT短類型轉(zhuǎn)移,目的地址必須距本指令在-127~128個字節(jié)的范圍內(nèi)。循環(huán)指令不影響標(biāo)志位。1) 循環(huán)指令指令的一般格式為: LOOP標(biāo)號 功能: (CX)←(CX)-1,(CX)≠0,則轉(zhuǎn)移至標(biāo)號處循環(huán)執(zhí)行,直至(CX)=0,繼續(xù)執(zhí)行后續(xù)程序。LOOP指令的操作是先將CX的內(nèi)容減1,如結(jié)果不等于0,則轉(zhuǎn)到指令中指定的短標(biāo)號處; 否則,順序執(zhí)行下一條指令。因此,在循環(huán)程序開始前,應(yīng)將循環(huán)次數(shù)送CX寄存器。2) 條件循環(huán)指令指令的一般格式為: LOOPZ/LOOPE標(biāo)號 功能: (CX)←(CX)-1,(CX)≠0,且ZF=1時,轉(zhuǎn)移至標(biāo)號處循環(huán)。LOOPZ和LOOPE實際上代表同一條指令。本指令的操作也是先將CX寄存器的內(nèi)容減1,如結(jié)果不為零,且零標(biāo)志ZF=1,則轉(zhuǎn)移到指定的短標(biāo)號處。3) 條件循環(huán)指令指令的一般格式為: LOOPNZ/LOOPNE標(biāo)號 功能: (CX)←(CX)-1,(CX)≠0,且ZF=0時,轉(zhuǎn)移至標(biāo)號處循環(huán)。本指令也同樣有兩種表示形式。指令的操作是將CX寄存器的內(nèi)容減1,如結(jié)果不為0,且零標(biāo)志ZF=0(表示“不相等”或“不等于0”),則轉(zhuǎn)移到指定的短標(biāo)號處。4. 過程調(diào)用和返回指令如果有一些程序段需要在不同的地方多次反復(fù)地出現(xiàn),則可以將這些程序段設(shè)計成為過程(相當(dāng)于子程序),每次需要時進行調(diào)用。過程結(jié)束后,再返回到原來調(diào)用的地方。采用這種方法不僅可以使源程序的總長度大大縮短,而且有利于實現(xiàn)模塊化的程序設(shè)計,使程序的編制、閱讀和修改都比較方便。 1) 過程調(diào)用指令指令格式: CALLOPRD 其中,OPRD為過程的目的地址。過程調(diào)用可以分為段內(nèi)調(diào)用和段間調(diào)用兩種。尋址方式也可以分為直接尋址和間接尋址兩種。本指令不影響標(biāo)志位。(1) 段內(nèi)直接調(diào)用。指令格式: CALLNEAR類型的過程名 每一個過程在定義時,應(yīng)指定它是近類型(NEAR),還是遠類型(FAR)。本指令是段內(nèi)直接調(diào)用,因而過程與調(diào)用指令同處在一個代碼段內(nèi)。在執(zhí)行該調(diào)用指令時,首先將IP的內(nèi)容入棧保護,然后將指令代碼給出的目的地址的段內(nèi)偏移量送入IP中,從而實現(xiàn)過程調(diào)用,將程序轉(zhuǎn)至過程入口。(2) 段內(nèi)間接調(diào)用。指令格式: CALLOPRD 其中,OPRD為16位通用寄存器或存儲器數(shù)。本指令執(zhí)行時,首先將IP的內(nèi)容入棧保護,然后將目的地址在段內(nèi)偏移量由指定的16位寄存器或存儲器字中取至IP中,從而實現(xiàn)過程調(diào)用。(3) 段間直接調(diào)用。指令格式: CALLFAR類型的過程名 由于是段間調(diào)用,在指令執(zhí)行時,應(yīng)同時將當(dāng)前的CS及IP的值入棧保護,然后將FAR類型的過程名所在的段基址和段內(nèi)偏移值送CS及IP,從而實現(xiàn)過程調(diào)用。(4) 段間間接調(diào)用。指令格式: CALLDWORD 其中,DWORD為存儲器操作數(shù)。段間間接調(diào)用只能通過存儲器雙字進行。本指令執(zhí)行時,首先將當(dāng)前的CS及IP的值入棧保護,然后將存儲器雙字操作數(shù)的第一個字的內(nèi)容送IP,將第二個字的內(nèi)容送CS,以實現(xiàn)段間調(diào)用。2) 返回指令指令格式: RET 本指令的作用是: 當(dāng)調(diào)用的過程結(jié)束后實現(xiàn)從過程返回至原調(diào)用程序的下一條指令。本指令不影響標(biāo)志位。由于在過程定義時,已指明其近(NEAR)或遠(FAR)的屬性,因此RET指令將根據(jù)段內(nèi)調(diào)用與段間調(diào)用,執(zhí)行不同的操作。對段內(nèi)調(diào)用,返回時,由堆棧彈出一個字的返回地址的段內(nèi)偏移量至IP。對段間調(diào)用,返回時,由堆棧彈出的第一個字為返回地址的段內(nèi)偏移量,將其送入IP中,由堆棧彈出的第二個字為返回地址的段基址,將其送入CS中。5. 中斷指令在程序運行時,遇到某些緊急情況或一些嚴(yán)重的錯誤(如溢出),當(dāng)前程序應(yīng)能夠暫停,處理器中止當(dāng)前程序運行,轉(zhuǎn)去執(zhí)行處理這些緊急情況的程序段。這種情況稱為“中斷”。轉(zhuǎn)去執(zhí)行的處理中斷的子程序稱為“中斷服務(wù)程序”或“中斷處理程序”。當(dāng)前程序被中斷的地方稱為“斷點”。中斷服務(wù)程序執(zhí)行完后應(yīng)返回原來程序的斷點,繼續(xù)執(zhí)行被中斷的程序。中斷提供了又一種改變程序執(zhí)行順序的方法。8086/8088具有很強的中斷系統(tǒng),可以處理256個不同方式的中斷。每一個中斷賦予一個中斷向量碼,CPU根據(jù)向量碼的不同來識別不同的中斷源。8086/8088內(nèi)部中斷源有除法錯中斷、單步中斷、斷點中斷、溢出中斷、用戶自定義的軟中斷5種類型。外部中斷是指來自CPU之外的原因引起的程序中斷,分為可屏蔽中斷和非屏蔽中斷兩種類型。1) 溢出中斷指令指令格式: INTO 功能: 本指令檢測OF標(biāo)志位,當(dāng)OF=1時,說明已發(fā)生溢出,立即產(chǎn)生一個中斷類型4的中斷,當(dāng)OF=0時,本指令不起作用。2) 軟中斷指令指令格式: INTn 其中,n為軟中斷的類型號。功能: 本指令將產(chǎn)生一個軟中斷,把控制轉(zhuǎn)向一個類型號為n的軟中斷,該中斷處理程序入口地址在中斷向量表的n×4地址處的兩個存儲字(4個單元)中。3) 中斷返回指令指令格式: IRET 功能: 用于中斷處理程序中,從中斷程序的斷點處返回,繼續(xù)執(zhí)行原程序。本指令將影響所有標(biāo)志位。無論是軟中斷,還是硬中斷,本指令均可使其返回到中斷程序的斷點處繼續(xù)執(zhí)行原程序。3.2.5串操作類指令串操作類指令是一組具有修改數(shù)據(jù)串操作指針功能的指令。數(shù)據(jù)串可以是字節(jié)串,也可以是字串,即每一個數(shù)據(jù)占用兩個存儲單元。數(shù)據(jù)串只能放在存儲器中,對數(shù)據(jù)串的數(shù)據(jù)進行處理時,可以只對一個數(shù)據(jù)串進行,也可以對兩個數(shù)據(jù)串進行,根據(jù)數(shù)據(jù)串中數(shù)據(jù)的流動方向,可以分源數(shù)據(jù)串和目的數(shù)據(jù)串。8086/8088指令系統(tǒng)還為串操作類指令提供重復(fù)前綴,以便重復(fù)進行相同的操作。在串操作指令中,源操作數(shù)用寄存器SI尋址,默認在數(shù)據(jù)段DS中,但允許段超越; 目的操作數(shù)用寄存器DI尋址,默認在附加段ES中,不允許段超越。每執(zhí)行一次串操作指令,作為源地址指針的SI和作為目的地址指針的DI將自動修改: ±1(對于字節(jié)串)或±2(對于字串)。地址指針是增加還是減少則取決于方向標(biāo)志DF。在系統(tǒng)初始化后或執(zhí)行指令CLD后,DF=0,此時地址指針是增1或2; 在執(zhí)行指令STD后,DF=1,此時地址指針減1或2。1. 串傳送指令指令格式: MOVSOPRD1,OPRD2 MOVSB MOVSW 其中,OPRD1為目的串符號地址,OPRD2為源串符號地址。功能: OPRD1←OPRD2。串傳送指令MOVS將數(shù)據(jù)段主存單元的1字節(jié)或字,傳送到附加段的主存單元中。定義數(shù)據(jù)串時,要求源串和目的串類型一致,并以其類型區(qū)別是字節(jié)或字操作。在指令中不出現(xiàn)操作數(shù)時,字節(jié)串傳送格式為MOVSB,字串傳送格式為MOVSW。MOVS指令不影響標(biāo)志位。(1) 對字節(jié)串操作時,若DF=0,則做加,即: [ES: DI] ← [DS: SI],(SI)←(SI) 1,(DI)←(DI) 1 若DF=1,則做減,即: (SI)←(SI)-1,(DI)←(DI)-1 (2) 對字串操作時,若DF=0,則做加,即: (SI)←(SI) 2,(DI)←(DI) 2 若DF=1,則做減,即: (SI)←(SI)-2,(DI)←(DI)-2 【例3.26】將存儲器中變量BUFA開始的160個數(shù)據(jù)串傳送至BUFB開始的存儲區(qū),可用以下程序段實現(xiàn)。 MOVSI,OFFSET BUFA MOVDI,OFFSET BUFB MOVCX,160 CLD AGAIN: MOVSBUFB,BUFA DECCX JNZAGAIN 2. 串比較指令指令格式: CMPSOPRD1,OPRD2 CMPSB CMPSW 其中,OPRD1為目的串符號地址,OPRD2為源串符號地址。串比較指令CMPS將由SI尋址的源串中的數(shù)據(jù)與DI尋址的目的串中的數(shù)據(jù)(字或字節(jié))進行比較,比較結(jié)果送標(biāo)志位,而不改變操作數(shù)本身。同時,SI、DI將自動調(diào)整。CMPS指令影響標(biāo)志位AF、CF、OF、SF、PF、ZF。CMPS指令可用來檢查兩個字符串是否相同,可以使用循環(huán)控制方法對整串進行比較。 【例3.27】如對兩個字節(jié)串進行比較,若一致,則AL內(nèi)容置為0; 若不一致,則AL內(nèi)容置為0FFH。程序段如下: MOVSI,OFFSET DAT1; DAT1中是內(nèi)存中定義的字節(jié)串1 MOVDI,OFFSET DAT2; DAT2中是內(nèi)存中定義的字節(jié)串2 MOVCX,N CLD NEXT: CMPSB JNZFIN DECCX JNZNEXT MOVAL,0 JMPEXX FIN: MOVAL,0FFH EXX: MOVDAT3,AL; DAT3是內(nèi)存中存放結(jié)果的單元 3. 串掃描指令指令格式: SCASOPRD SCASB SCASW 其中,OPRD為目的串符號地址。串掃描指令SCAS將AL或AX的內(nèi)容與附加段中由DI寄存器尋址的目的串中的數(shù)據(jù)進行比較,根據(jù)比較結(jié)果設(shè)置標(biāo)志位,但不改變操作數(shù)本身。每次比較后修改DI寄存器的值,使之指向下一個元素。SCAS指令影響標(biāo)志位AF、CF、OF、SF、PF、ZF。SCAS指令可查找字符串中的一個關(guān)鍵字,只需在本指令執(zhí)行前,把關(guān)鍵字放在AL或AX中,用重復(fù)前綴可在整串中查找!纠3.28】在附加段定義了一個字符串,首地址由STRING指示,共有100個字符。在字符串中查找“空格”(ASCII碼為20H)字符。 MOVDI,OFFSET STRING MOVAL,20H MOVCX,100 CLD AGAIN: SCASB JZFOUND; ZF=1,發(fā)現(xiàn)空格,轉(zhuǎn)移到FOUND DECCX ; 不是空格 JNZAGAIN; 搜索下一個字符 …; 不含空格,則繼續(xù)執(zhí)行 FOUND: … 4. 串讀取指令指令格式: LODSOPRD LODSB LODSW 其中,OPRD為源串符號地址。串讀取指令LODS的功能是把SI尋址的源串的數(shù)據(jù)字節(jié)送AL或數(shù)據(jù)字送AX中,并根據(jù)DF的值,地址指針SI進行自動調(diào)整。LODS指令不影響標(biāo)志位。5. 字符串存儲指令指令格式: STOSOPRD STOSB STOSW 其中,OPRD為目的串符號地址。本指令的功能是把AL或AX中的數(shù)據(jù)存儲到DI為目的串地址指針?biāo)鶎ぶ返拇鎯ζ鲉卧。地址指針DI將根據(jù)DF的值進行自動調(diào)整。STOS指令與LODS指令功能互逆。STOS指令不影響標(biāo)志位!纠3.29】將附加段64KB主存區(qū)全部設(shè)置為0。 MOVAX,0 MOVDI,0 MOVCX,8000H; CX←傳送次數(shù)(32×1024) CLD ; 設(shè)置DF=0,實現(xiàn)地址增加 AGAIN: STOSW; 傳送一個字 DECCX JNZAGAIN ; 判斷傳送次數(shù)CX是否為0 在此例中,將CLD指令改為STD指令就能反向傳送,實現(xiàn)同樣功能。另外,此例中實際上只要保證DI為偶數(shù)即可!纠3.30】數(shù)據(jù)段DS中有一個數(shù)據(jù)塊,具有100個字節(jié),起始地址為BBUF。現(xiàn)在要把其中的正數(shù)、負數(shù)分開,分別存入同一個段的兩個緩沖區(qū)。存放正數(shù)的起始地址為DATAA,存放負數(shù)的起始地址為DATAB。 MOVSI,OFFSET BBUF MOVDI,OFFSET DATAA MOVBX,OFFSET DATAB MOVAX,DS MOVEX,AX ; 所有數(shù)據(jù)都在一個段中,所以設(shè)置ES=DS MOVCX,100 CLD GOON: LODSB ; 從BBUF中取出一個數(shù)據(jù) TESTAL,80H ; 檢測符號位,判斷是正是負 JNZMINUS; 符號位為1,是負數(shù),轉(zhuǎn)向MINIS STOSB; 符號位為0,是正數(shù),存入DATAA JMPAGAIN MINUS: XCHGBX,DI STOSB ; 將負數(shù)存入DATAB XCHGBX,DI AGAIN: DECCX JNZGOON 6. 重復(fù)前綴的說明在串操作指令前加上重復(fù)前綴,可以對數(shù)據(jù)串進行重復(fù)處理。由于加上重復(fù)前綴后,對應(yīng)的指令代碼是不同的,因此指令的功能便具有重復(fù)處理的功能,重復(fù)的次數(shù)存放在CX寄存器中。重復(fù)前綴形式有: REP; CX≠0,重復(fù)執(zhí)行字符串指令 REPZ/REPE ; CX≠0且ZF=1,重復(fù)執(zhí)行字符串指令 REPNZ/REPNE; CX≠0且ZF=0,重復(fù)執(zhí)行字符串指令 REP與MOVS或STOS串操作指令結(jié)合使用,完成一組數(shù)據(jù)的傳送或建立一組相同數(shù)據(jù)的數(shù)據(jù)串。REPZ/REPE與CMPS串操作指令結(jié)合使用,可以完成兩組數(shù)據(jù)串的比較。當(dāng)串未結(jié)束時,繼續(xù)重復(fù)執(zhí)行數(shù)據(jù)串指令。它可用來判定兩數(shù)據(jù)串是否相同。REPZ/REPE與SCAS串操作指令結(jié)合使用,可以完成在一個數(shù)據(jù)串中搜索一個關(guān)鍵字。只要當(dāng)數(shù)據(jù)串未結(jié)束且當(dāng)關(guān)鍵字與元素相同時,繼續(xù)重復(fù)執(zhí)行串搜索指令,用于在數(shù)據(jù)串中查找與關(guān)鍵字不相同的數(shù)據(jù)的位置。REPNZ/REPNE與CMPS指令結(jié)合使用,表示當(dāng)串未結(jié)束且當(dāng)對應(yīng)串元素不相同時,繼續(xù)重復(fù)執(zhí)行串比較指令。它可在兩數(shù)據(jù)串中查找相同數(shù)據(jù)的位置。REPNZ/REPNE與SCAS指令結(jié)合使用,表示串未結(jié)束且當(dāng)關(guān)鍵字與元素不相同時,繼續(xù)重復(fù)執(zhí)行串搜索指令,用于在數(shù)據(jù)串中查找與關(guān)鍵字相同的數(shù)據(jù)的位置!纠3.31】對兩個字符串STR1與STR2進行比較。 MOVSI,OFFSET STR1 MOVDI,OFFSET STR2 MOVCX,COUNT CLD REPZCMPSB JNZNEQU MOVAL,0 JMPOVR NEQU: MOVAL,0FFH OVR: MOVRESULT,AL HLT 【例3.32】在字符串中搜索關(guān)鍵字,記下搜索的次數(shù)和關(guān)鍵字在串中的位置。 CLD MOVDI,OFFSET BUF MOVCX,COUNT MOVAL,CHAR REPNESCASB JZFOUND MOVDI,0 JMPDONE FOUND: DECDI MOVBUFF,DI MOVBX,OFFSET BUF SUBDI,BX MOVBUFF 2,DI DONE: HLT 在本程序中,由于DI是自增的,若找到關(guān)鍵字,這時DI已指向關(guān)鍵字的下一個字符,故DI減1才是真正的關(guān)鍵字在字符串中的位置。用當(dāng)前關(guān)鍵字的位置減去串首地址,即能得到搜索的次數(shù)。3.2.6處理器控制類指令處理器控制指令用于控制CPU的動作,修改標(biāo)志寄存器的狀態(tài)等,實現(xiàn)對CPU的管理。1. 標(biāo)志位操作指令標(biāo)志位操作指令有7條,可以直接設(shè)置或清除CF、DF和IF標(biāo)志位。例如,串操作中的程序,經(jīng)常用CLD指令清方向標(biāo)志使DF=0,在串操作指令執(zhí)行時,按增量的方式修改串指針。標(biāo)志位操作指令的格式、功能等信息列于表3.3中。 表3.3標(biāo)志位操作指令 指 令 格 式功 能 說 明 CLCCF=0,進位標(biāo)志位置0STCCF=1,進位標(biāo)志位置1CMC進位標(biāo)志位求反CLDDF=0,方向標(biāo)志位置0STDDF=1,方向標(biāo)志位置1CLIIF=0,中斷標(biāo)志位置0,使CPU禁止響應(yīng)外部中斷STIIF=1,中斷標(biāo)志位置1,使CPU允許響應(yīng)外部中斷 這些指令僅對有關(guān)狀態(tài)標(biāo)志位執(zhí)行操作,而對其他狀態(tài)標(biāo)志位則沒有影響。2. CPU控制指令1) 處理器暫停指令指令格式: HLT HLT指令使CPU進入暫停狀態(tài),這時CPU不進行任何操作。當(dāng)CPU發(fā)生復(fù)位(RESET)或來自外部的中斷(NMI或 INTR)時,CPU脫離暫停狀態(tài)。HLT指令不影響標(biāo)志位。HLT指令可用于程序中等待中斷。當(dāng)程序中必須等待中斷時,可用HLT,而不必用軟件死循環(huán)。然后,中斷使CPU脫離暫停狀態(tài),返回執(zhí)行HLT的下一條指令。注意: 該指令在PC中將引起所謂的“死機”,一般的應(yīng)用程序不要使用。2) 處理器等待指令指令格式: WAIT WAIT指令在8086/8088的測試輸入引腳為高電平無效時,使CPU進入等待狀態(tài),這時,CPU并不做任何操作; 測試為低電平有效時,CPU脫離等待狀態(tài),繼續(xù)執(zhí)行WAIT指令后面的指令。WAIT指令不影響標(biāo)志位。浮點指令經(jīng)由8086/8088 CPU處理發(fā)往8087,并與8086/8088本身的整數(shù)指令在同一個指令序列; 而8087執(zhí)行浮點指令較慢,所以8086/8088必須與8087保持同步。8086/8088就是利用WAIT指令和測試引腳實現(xiàn)與8087同步運行的。3) 處理器交權(quán)指令指令格式: ESCEXTOPRD,OPRD 其中,EXTOPRD為外部操作碼(浮點指令的操作碼),是一個6位立即數(shù); OPRD為源操作數(shù),可以是寄存器或內(nèi)存單元。當(dāng)OPRD為寄存器時,它的編碼也作為操作碼; 如果為存儲器操作數(shù),CPU讀出這個操作數(shù)送給協(xié)處理器。交權(quán)指令ESC把浮點指令交給浮點處理器執(zhí)行。為了提高系統(tǒng)的浮點運算能力,8086/8088系統(tǒng)中可加入浮點運算協(xié)處理器8087。但是,8087的浮點指令是和8086/8088的整數(shù)指令組合在一起的,8086/8088主存中存儲8087的操作碼及其所需的操作數(shù)。當(dāng)8086/8088發(fā)現(xiàn)是一條浮點指令時,就利用ESC指令將浮點指令交給8087執(zhí)行。ESC指令不影響標(biāo)志位。4) 空操作指令指令格式: NOP NOP指令不執(zhí)行任何有意義的操作,但占用1字節(jié)存儲單元,空耗一個指令執(zhí)行周期。該指令常用于程序調(diào)試。例如,在需要預(yù)留指令空間時用NOP填充,代碼空間多余時也可用NOP填充,還可以用NOP指令實現(xiàn)軟件延時。事實上,NOP指令就是XCHGAX,AX指令,它們的代碼一樣。NOP指令不影響標(biāo)志位。5) 封鎖總線指令LOCK是一個指令前綴,可放在指令的前面。這個前綴使得在當(dāng)前指令執(zhí)行時間內(nèi),8086/8088 處理器的封鎖輸出引腳有效,即把總線封鎖,使別的控制器不能控制總線,直到該指令執(zhí)行完后,總線封鎖解除。當(dāng)CPU與其他處理器協(xié)同工作時,LOCK指令可避免破壞有用信息。6) 段超越前綴指令 SEG: ; 即CS: ,SS: ,DS: ,ES: ,取代默認段寄存器 在允許段超越的存儲器操作數(shù)之前,使用段超越前綴指令,將不采用默認的段寄存器,而是采用指定的段寄存器尋址操作數(shù)。3.2.7輸入/輸出類指令輸入/輸出指令共有兩條。輸入指令I(lǐng)N用于從外設(shè)端口接收數(shù)據(jù),輸出指令OUT則向端口發(fā)送數(shù)據(jù)。無論是接收到的數(shù)據(jù)或是準(zhǔn)備發(fā)送的數(shù)據(jù)都必須在累加器AL(字節(jié))或AX(字)中,所以這是兩條累加器專用指令。輸入/輸出指令可以分為兩大類: 一類是端口直接尋址的輸入/輸出指令; 另一類是端口通過DX寄存器間接尋址的輸入/輸出指令。在直接尋址的指令中只能尋址256個端口(0~255),而間接尋址的指令中可尋址64K個端口(0~65535)。1. 輸入指令指令格式: INAL,n(AL)←(n) INAX,n (AX)←(n 1),(n) INAL,DX (AL)← [(DX)] INAX,DX (AX)← [(DX 1)],[(DX)] 其中,n為8位的端口地址,當(dāng)字節(jié)輸入時,將端口地址n的內(nèi)容送至AL中; 當(dāng)字輸入時,將端口地址n 1的內(nèi)容送至AH中,端口地址n的內(nèi)容送至AL中。端口地址也可以是16位的,但必須將16位的端口地址送入DX中。當(dāng)字節(jié)尋址時,由DX內(nèi)容作端口地址的內(nèi)容送至AL中; 當(dāng)輸入數(shù)據(jù)字時,[(DX 1)]送AH,[(DX)]送AL中,用符號(AX)← [(DX 1)],[(DX)]表示。指令舉例: INAL,20H 或: MOVDX,0400H INAL,DX 2. 輸出指令指令格式: OUTn,AL(n)←(AL) OUTn,AX(n 1),(n)←(AX) OUTDX,AL[(DX)]←(AL) OUTDX,AX[(DX 1)],[(DX)]←(AX) OUT指令中各個操作數(shù)的定義與IN指令相同。指令舉例: MOVAL,0FH OUT20H,AL 或: MOVDX,0400H MOVAL,86H OUTDX,AL 輸入/輸出指令對標(biāo)志位不產(chǎn)生影響。3.380x86指令系統(tǒng)介紹80x86系列微處理器指令系統(tǒng)保持向上兼容,如80486微處理器可兼容執(zhí)行8086、80286和80386的指令。在介紹了8086/8088指令系統(tǒng)的基礎(chǔ)上,本節(jié)講述80286、80386、80486和Pentium的新增指令以及在8086/8088基礎(chǔ)上擴充的新的功能的一些指令。3.3.180x86尋址方式由于80x86系列CPU對8086/8088的指令是向上兼容的,因此此前所介紹的8086/8088的尋址方式也適用于80x86。下面介紹的尋址方式都是針對存儲器操作數(shù)的尋址方式,它們均與比例因子有關(guān),這些尋址方式只能用在80386及其后繼機型中,8086/8088/80286不支持這幾種尋址方式。在80386及其后續(xù)機型中,8個32位的通用寄存器EAX、EBX、ECX、EDX、ESP、EBP、ESI、EDI既可以存放數(shù)據(jù),也可以存放地址,也就是說,這些寄存器都可以用來提供操作數(shù)在段內(nèi)的偏移地址。1. 比例變址尋址方式操作數(shù)的有效地址是變址寄存器的內(nèi)容乘以指令中指定的比例因子再加上位移量之和,所以有效地址由3種成分組成。這種尋址方式與寄存器相對尋址相比,增加了比例因子,其優(yōu)點在于: 對于元素大小為2、4、8字節(jié)的數(shù)組,可以在變址寄存器中給出數(shù)組元素下標(biāo),而由尋址方式控制直接用比例因子把下標(biāo)轉(zhuǎn)換為變址值。例如: MOVEAX,COUNT[ESI×4] 假設(shè)(DS)=4000H,位移量為500H。如果要求把雙字?jǐn)?shù)組中的元素3送到EAX(EAX為32位累加器)中,用這種尋址方式可以直接在ESI中放入3,選擇比例因子4(數(shù)組元素為4字節(jié)長)就可以方便地達到目的,不必像在寄存器相對尋址方式中要把變址值直接裝入寄存器中。物理地址的計算如圖3.14所示。 圖3.14比例變址尋址方式 2. 基址比例變址尋址方式操作數(shù)的有效地址是變址寄存器的內(nèi)容乘以比例因子再加上基址寄存器的內(nèi)容,所以有效地址由3種成分組成。這種尋址方式與基址變址尋址方式相比,增加了比例因子,其優(yōu)點是很明顯的。例如: MOVECX,[EAX][EDX×8] 此例中,EAX作為基址,EDX作變址,比例因子為8。3. 相對基址比例變址尋址方式操作數(shù)的有效地址是變址寄存器的內(nèi)容乘以比例因子,加上基址寄存器的內(nèi)容,再加上位移量之和,所以有效地址由4種成分組成。這種尋址方式比相對基址變址尋址方式增加了比例因子,便于對元素為2、4、8字節(jié)的二維數(shù)組的處理。例如: MOVEAX,TABLE[EBP][EDI×4] 在此例中,EBP作為基址,EDI作變址,比例因子為4,位移量為TABLE。3.3.280286指令系統(tǒng)新增指令80286指令系統(tǒng)除了包括所有的8086/8088指令外,新增指令以及增強了功能的指令列于表3.4中。其中,控制保護態(tài)指令是80286工作在保護模式下的一些特權(quán)方式指令,常用于操作系統(tǒng)及其他控制軟件中。保護模式是集實地址模式的能力、存儲器管理、對虛擬存儲器的支持和對地址空間的保護為一體而建立起來的一種特殊工作方式。 表3.480286增強與增加的指令 類別增強的指令增加的指令 數(shù)據(jù)傳送類PUSH 立即數(shù)PUSHA POPA算術(shù)運算類IMUL 寄存器,寄存器 IMUL 寄存器,存儲器 IMUL 寄存器,立即數(shù) IMUL 寄存器,寄存器,立即數(shù) IMUL 寄存器,存儲器,立即數(shù)續(xù)表 類別增強的指令增加的指令 邏輯運算與移位類SHL 目的操作數(shù),立即數(shù)(1~31) 其余SAL、SAR、SHR、ROL、ROR、RCL、RCR 7條移位指令同SHL 串操作類[REP]INS 目的串,DX [REP]OUTS DX,源串 [REP]INSB/OUTB [REP]INSW/OUTW高級語言BOUND 寄存器,存儲器 ENTER 立即數(shù)16,立即數(shù) LEAVE 保護模式的系統(tǒng)控制指令類LAR(裝入訪問權(quán)限)、LSL(裝入段界限)、LGDT(裝入全局描述符表)、SGDT(存儲全局描述符表)、LIDT(裝入8字節(jié)中斷描述符表)、SIDT(存儲8字節(jié)中斷描述符表)、LLDT(裝入局部描述符表)、SLDT(存儲局部描述符表)、LTR(裝入任務(wù)寄存器)、STR(存儲任務(wù)寄存器)、LMSW(裝入機器狀態(tài)字)、SMSW(存儲機器狀態(tài)字)、VERR(存儲器或寄存器讀校驗)、VERW(存儲器或寄存器寫校驗)、ARPL(調(diào)整已請求特權(quán)級別)、CLTS(清除任務(wù)轉(zhuǎn)移標(biāo)志) 下面介紹80286指令系統(tǒng)中主要的新增及擴展指令。1. 堆棧操作指令指令格式: PUSH16位立即數(shù) PUSH指令將16位立即數(shù)壓入堆棧,如果給出的數(shù)不夠16位,則自動擴展為16位后壓入堆棧。該指令不影響狀態(tài)標(biāo)志位。在8086/8088指令系統(tǒng)中,PUSH指令允許的操作數(shù)只能是兩字節(jié)的寄存器操作數(shù)或存儲器操作數(shù)。2. 通用寄存器入棧操作指令指令格式: PUSHA PUSHA指令將所有通用寄存器AX、CX、DX、BX、SP、BP、SI和DI的內(nèi)容按順序壓入堆棧,入棧的SP值是執(zhí)行該指令之前的SP值,在執(zhí)行完本指令后,SP值減16。3. 通用寄存器內(nèi)容出棧操作指令指令格式: POPA POPA指令將棧頂?shù)膬?nèi)容順序彈至DI、SI、BP、SP、BX、DX、CX和AX。SP中的值是堆棧中所有通用寄存器彈出后,堆棧指針實際指向的值(不是棧中保存的SP值),也即該指令執(zhí)行后SP的值,可以通過加16來恢復(fù)。4. 有符號整數(shù)乘法指令(兩個操作數(shù))指令格式: IMUL16位寄存器,立即數(shù) 有符號整數(shù)乘法指令I(lǐng)MUL將16位通用寄存器中的有符號數(shù)作為被乘數(shù),與有符號立即數(shù)相乘,乘積送回通用寄存器。若乘積超出有符號數(shù)的表示范圍(-32768~ 32767),除丟失溢出部分外,并將OF及CF置為1; 否則,將OF及CF置為0。5. 有符號整數(shù)乘法指令(3個操作數(shù))指令格式: IMUL16位寄存器,16位存儲器,立即數(shù) 該指令與上一條指令功能類似,區(qū)別僅在于,將16位存儲器操作數(shù)作為被乘數(shù)與立即數(shù)相乘,結(jié)果送16位寄存器。6. 移位指令8086/8088中有8條移位指令,移位計數(shù)使用CL或1表示,且規(guī)定當(dāng)移位次數(shù)大于1時,必須使用CL。在80286中,將上述限制修改為當(dāng)移位次數(shù)為1~31次時,允許使用立即數(shù)。7. 串輸入/輸出指令I(lǐng)NS/OUTS指令格式: [REP]INS目的串,DX [REP]OUTSDX,源串 [REP]INSB [REP]OUTB [REP]INSW [REP]OUTW 串輸入/輸出指令可以帶兩個操作數(shù),也可以采用默認操作數(shù)形式,指令中不指出操作數(shù),但要在指令助記符中用B或W指明輸入/輸出的數(shù)據(jù)串是字節(jié)還是字。該類指令可以實現(xiàn)DX指定的端口與由指定的內(nèi)存地址之間的數(shù)據(jù)塊傳送,其類型可以是字節(jié)或字。如果加重復(fù)前綴REP,完成整個串的輸入/輸出操作,這時CX寄存器中為重復(fù)前綴操作的次數(shù)。8. 內(nèi)存范圍檢查指令指令格式: BOUND16位寄存器,32位存儲器 BOUND指令以32位存儲器低兩字節(jié)的內(nèi)容為下界,高兩字節(jié)的內(nèi)容為上界。若16位寄存器的內(nèi)容在此上、下界表示的地址范圍內(nèi),程序正常執(zhí)行; 否則產(chǎn)生INT 5中斷。當(dāng)出現(xiàn)這種中斷時,返回地址指向BOUND指令,而不是BOUND后面的指令,這與返回地址指向程序中下一條指令的正常中斷是有區(qū)別的。9. 設(shè)置堆?臻g指令格式: ENTER16位立即數(shù),8位立即數(shù) 在ENTER指令中,兩個操作數(shù)中的16位立即數(shù)表示堆?臻g的大小,也即表示給當(dāng)前過程分配多少字節(jié)的堆?臻g,8位立即數(shù)指出在高級語言內(nèi)調(diào)用自身的次數(shù),也即嵌套層數(shù)。值得注意的是該指令使用BP寄存器而非SP作為;怠10. 撤銷堆?臻g指令指令格式: LEAVE LEAVE指令撤銷由ENTER指令建立的堆?臻g。例如: TASKPROC NEAR ENTER400,8; 建立堆棧空間為400字節(jié),允許過程嵌套8層 … LEAVE ; 釋放堆?臻g RET TASKENDP 3.3.380386指令系統(tǒng)新增指令80386指令系統(tǒng)包括了所有80286指令,并對80286的部分指令進行了功能擴充,還新增了一些指令,特別指出的是,80386提供了32位尋址方式,可對32位數(shù)據(jù)直接操作。所有16位指令均可擴充為32位指令。表3.5列出了80386增強及增加的指令。 表3.580386增強與增加的指令 類別增強的指令增加的指令 數(shù)據(jù)傳送類PUSH 立即數(shù) PUSHAD/POPAD PUSHFD/POPFDMOVSX 寄存器,寄存器/存儲器 MOVZX 寄存器,寄存器/存儲器 算術(shù)運算類IMUL 寄存器,寄存器/存儲器 IMUL 寄存器,寄存器/存儲器,立即數(shù) CWDE CDQ邏輯運算與移位類SHLD/SHRD 寄存器/存儲器,寄存器,CL/立即數(shù)串操作類所有串操作指令后面擴展D,如MOVSD、OUTD等位操作類BT/BTC/BTS/BTR 寄存器/存儲器,寄存器/立即數(shù) BSF/BSR 寄存器,寄存器/存儲器條件設(shè)置類SET條件 寄存器/存儲器 下面介紹80386指令系統(tǒng)中主要的新增及擴展指令。1. 數(shù)據(jù)傳送與擴展指令1) MOVSX指令格式: MOVSX寄存器,寄存器/存儲器 MOVSX指令將源操作數(shù)傳送到目的操作數(shù)中。目的操作數(shù)可以是16位或32位寄存器; 源操作數(shù)可以是寄存器或存儲器操作數(shù),其位數(shù)應(yīng)小于或等于目的操作數(shù)的位數(shù)。當(dāng)源操作數(shù)的位數(shù)少于目的操作數(shù)時,目的操作數(shù)的高位用源操作數(shù)的符號位填補。此指令適用于有符號數(shù)的傳送與擴展。2) MOVZX指令格式: MOVZX寄存器,寄存器/存儲器 MOVZX指令與MOVSX功能基本相同,唯一區(qū)別的是當(dāng)源操作數(shù)的位數(shù)少于目的操作數(shù)位數(shù)時,目的操作數(shù)的高位補“0”。該指令適用于無符號數(shù)的傳送與擴展。2. 堆棧操作指令1) PUSH指令格式: PUSH32位立即數(shù) 該指令將32位立即數(shù)壓入堆棧。該指令執(zhí)行后SP的值將減4。2) PUSHAD指令格式: PUSHAD 該指令將所有通用寄存器EAX、ECX、EDX、EBX、ESP、EBP、ESI和EDI的內(nèi)容順序壓入堆棧,其中壓入堆棧的ESP是該指令執(zhí)行前ESP的值。執(zhí)行該指令后,ESP的值減32。3) POPAD指令格式: POPAD 該指令將當(dāng)前棧頂內(nèi)容順序彈至EDI、ESI、EBP、ESP、EBX、EDX、ECX和EAX,但是最終ESP的值為彈出操作對堆棧指針調(diào)整后的值(而不是堆棧中保存的ESP的值)。即執(zhí)行該指令后ESP的值,可以通過增加32來恢復(fù)。4) PUSHFD指令格式: PUSHFD 該指令將32位標(biāo)志寄存器EFLAGS的內(nèi)容壓入堆棧。5) POPFD指令格式: POPFD 該指令將當(dāng)前棧頂?shù)?字節(jié)內(nèi)容彈至EFLAGS寄存器。3. 有符號數(shù)乘法指令1) 兩操作數(shù)乘法指令指令格式: IMUL寄存器,寄存器/存儲器 該指令將16位或32位通用寄存器中的有符號數(shù)作為被乘數(shù),相同位數(shù)通用寄存器或存儲單元中的有符號數(shù)作為乘數(shù),乘積送目的操作數(shù)。若乘積溢出,溢出位部分將丟失,且將OF及CF置1; 否則將OF及CF清0。2) 三操作數(shù)乘法指令指令格式: IMUL寄存器,寄存器/存儲器,立即數(shù) 該指令與前一個指令功能基本相同,唯一區(qū)別在于,寄存器/存儲器為被乘數(shù),立即數(shù)為乘數(shù),乘積存放在第一個操作數(shù)中。3) 符號擴展指令該指令將AX中16位有符號數(shù)的符號位擴展到EAX的高16位中,即把AX的16位有符號數(shù)擴展為32位后,送EAX。4) 符號擴展指令該指令將EAX中32位有符號數(shù)擴展到EDX: EAX寄存器中,使之成為64位有符號數(shù),即將EAX中的符號位擴展到EDX中。4. 移位指令80386中新增加了一組移動多位的指令。它們可以把指定的一組位左移或右移到一個操作數(shù)中。1) SHLD指令格式: SHLD寄存器/存儲器,寄存器,CL/立即數(shù) 該指令將第一操作數(shù)(16位或32位)左移若干位(由8位立即數(shù)或CL指定),空出位用第二操作數(shù)(與第一操作數(shù)等位寬)高位部分填補,但第二操作數(shù)的內(nèi)容不變,CF標(biāo)志位中保留第一操作數(shù)最后的移出位。若僅移一位,當(dāng)CF值與移位后的第一操作數(shù)的符號位不一致時,OF置1; 否則OF清0。SHLD指令操作示意圖如圖3.15所示。2) SHRD指令格式: SHRD寄存器/存儲器,寄存器,CL/立即數(shù) 該指令將第一操作數(shù)(16位或32位)右移若干位(由8位立即數(shù)或CL指定),空出位用第二操作數(shù)(與第一操作數(shù)等位寬)低位部分填補,指令執(zhí)行后,第二操作數(shù)的內(nèi)容不變,CF標(biāo)志位中保留第一操作數(shù)最后的移出位。SHRD指令操作示意圖如圖3.16所示。 圖3.15SHLD指令功能示意圖 圖3.16SHRD指令功能示意圖 5. 位操作指令1) 位測試及設(shè)置指令測試指令可用來對指定位進行測試,因而可根據(jù)該位的值來控制程序流的執(zhí)行方向,而置位指令可對指定的位進行設(shè)置。指令格式及功能如表3.6所示。 表3.6位測試與設(shè)置指令 指 令 格 式功能 BT 寄存器/存儲器,寄存器/立即數(shù)第一操作數(shù)指定要測試的內(nèi)容(16位或32位),第二操作數(shù)(與第一操作數(shù)同長度的通用寄存器或8位立即數(shù))指定要測試的位,將被測內(nèi)容的指定測試位的值送CF BTC 寄存器/存儲器,寄存器/立即數(shù)在BT指令功能的基礎(chǔ)上,將被測試位取反BTR 寄存器/存儲器,寄存器/立即數(shù)在BT指令功能的基礎(chǔ)上,將被測試位清0BTS 寄存器/存儲器,寄存器/立即數(shù)在BT指令功能的基礎(chǔ)上,將被測試位置1 2) 位掃描指令位掃描指令用于找出寄存器或存儲器地址中所存數(shù)據(jù)的第一個或最后一個是1的位。該指令可用于檢查寄存器或存儲單元是否為0。BSF和BSR指令格式及功能如表3.7所示。 表3.7位掃描指令 指 令 格 式功能 BSF 寄存器,寄存器/存儲器對第二操作數(shù)(16位或32位通用寄存器或存儲器)從最低位到最高位進行掃描,將首先掃描到“1”的位號送第一操作數(shù),且使ZF=0。若第二操作數(shù)的各位均為0,則第一操作數(shù)的值不確定,且使ZF=1BSR 寄存器,寄存器/存儲器與BSF指令功能基本相同,唯一區(qū)別的是該指令從最高位到最低位進行掃描 6. 條件設(shè)置指令指令格式: SET條件寄存器/存儲器 這是80386特有的指令,用于測試指定的標(biāo)志位所處的狀態(tài),并根據(jù)測試結(jié)果,將指定的一個8位寄存器或內(nèi)存單元置1或清0。它們類似于條件轉(zhuǎn)移指令中的標(biāo)志位測試,但前者根據(jù)測試結(jié)果將操作數(shù)置1或清0,而后者根據(jù)測試結(jié)果決定轉(zhuǎn)移還是不轉(zhuǎn)移。指令中的條件是指令助記符的一部分,用于指定要測試的標(biāo)志位,如SETZ或SETNZ等。3.3.480486指令系統(tǒng)新增指令在80486微處理器中既包含有Cache存儲器,又包含有浮點運算器,因此,新增了用于比較和對Cache、TLB進行操作的指令以及比較完整的浮點操作指令。全部指令可分為13類,共計200多條。表3.8列出了80486新增加的指令。 表3.880486增加的指令 類別指 令 格 式功能 數(shù)據(jù)傳送類BSWAP reg32字節(jié)交換 算術(shù)運算類 XADD 寄存器/存儲器,寄存器交換與相加CMPXCHG 寄存器/存儲器,寄存器比較與交換 Cache管理類INVD WBINVD INVLPG這類指令用于80486管理CPU內(nèi)部的8KB Cache 下面介紹80486指令系統(tǒng)中新增的指令。1. 字節(jié)交換指令指令格式: BSWAPreg32 該指令可以實現(xiàn)雙字交換。使32位寄存器中的操作數(shù)按字節(jié)首尾交換,即D31~D24與D7~D0交換,D23~D16與D15~D8交換。【例3.33】[EAX]=01234567H,執(zhí)行以下指令,并分析結(jié)果。 BSWAPEAX 結(jié)果: [EAX]= 67452301H。2. 算術(shù)運算指令指令格式: XADD寄存器/存儲器,寄存器 該指令將源操作數(shù)與目的操作數(shù)交換并相加,其中源操作數(shù)必須為寄存器,而目的操作數(shù)可以是寄存器也可以是內(nèi)存單元,然后相加,其結(jié)果存放在目的操作數(shù)中!纠3.34】設(shè)[EAX]= 12000001H,[EBX]= 30000002H,執(zhí)行以下指令,并分析結(jié)果。 XADD EAX,EBX 結(jié)果: [EAX]= 42000003H,[EBX]=12000001H。3. 比較與交換指令指令格式: CMPXCHG寄存器/存儲器,寄存器 該指令使用3個操作數(shù): 一個寄存器中的源操作數(shù)、一個寄存器或內(nèi)存儲器單元的目的操作數(shù)和一個隱含(不出現(xiàn)在用戶所書寫的指令中)的累加器(AL/AX/EAX)。如果目的操作數(shù)與累加器的值相等,源操作數(shù)送目的單元,否則將目的操作數(shù)送累加器。【例3.35】設(shè)[EAX]=01010101H,[EBX]=02020202H,[ECX]=03030303H,執(zhí)行以下指令,并分析結(jié)果。 CMPXCHG ECX,EBX 結(jié)果: CF=0,[EAX]=03030303H,[EBX]=02020202H,[ECX]=03030303H。4. 作廢Cache指令指令格式: INVD INVD指令用于將Cache的內(nèi)容作廢。其具體操作是: 刷新內(nèi)部Cache,并分配一個專用總線周期刷新外部Cache。執(zhí)行該指令不會將外部Cache中的數(shù)據(jù)寫回主存儲器。5. 寫回和作廢Cache指令指令格式: WBINVD WBINVD指令先刷新內(nèi)部Cache,并分配一個專用總線周期將外部Cache的內(nèi)容寫回主存儲器,并在此后的一個總線周期將外部Cache刷新。6. 作廢TLB項指令指令格式: INVLPG INVLPG指令用于使TLB中的某一項作廢。如果TLB中含有一個存儲器操作數(shù)映像的有效項,則該TLB項被標(biāo)記為無效。3.3.5Pentium指令系統(tǒng)新增指令與80486相比,Pentium新增加了3條處理器專用指令和5條系統(tǒng)控制指令,但某些新增的指令是否有效與Pentium的型號有關(guān),可利用處理器特征識別指令CPUID判別處理器是否支持某些新增指令。表3.9列出了Pentium增加的指令。由于Pentium系列處理器的指令集是向上兼容的,因此所有早期的軟件可直接在Pentium機器上運行。 表3.9Pentium增加的指令 類別指 令 格 式含義操作 專 用 指 令 CMPXCHG8B 存儲器8字節(jié)比較與交換IF(EDX: EAX=D) ZF=1,D←ECX: EBX ELSE ZF=0,EDX: EAX←D CPUIDCPU標(biāo)識IF(EAX=0H) EAX,EBX,ECX,EDX←廠商信息 IF(EAX=1H) EAX,EBX,ECX,EDX←CPU信息 RDTSC讀時間標(biāo)記計數(shù)器EDX; EAX←時間標(biāo)記計數(shù)器 系 統(tǒng) 控 制 指 令 RDMSR讀模式專用寄存器EDX; EAX←MSR ECX=0H,MSR選擇MCA ECX=1H,MSR選擇MCT WRMSR寫模式專用寄存器MSR←EDX; EAX ECX=0H,MSR選擇MCA ECX=1H,MSR選擇MCT RSM恢復(fù)系統(tǒng)管理模式 MOV CR4,寄存器 MOV 寄存器,CR4與CR4傳輸CR4←reg32 reg32←CR4 下面介紹Pentium指令系統(tǒng)中新增指令的功能。1. 處理器標(biāo)識指令指令格式: CPUID 使用該指令可以辨別微機中Pentium處理器的類型和特點。在執(zhí)行CPUID指令前,EAX寄存器必須設(shè)置為0或1,根據(jù)EAX中設(shè)置值的不同,軟件會得到不同的標(biāo)志信息。2. 8字節(jié)比較交換指令指令格式: CMPXCHG8B存儲器 該指令帶有一個內(nèi)存儲器單元操作數(shù)。它能實現(xiàn)將EDX: EAX中的8字節(jié)值與指定的8字節(jié)存儲器操作數(shù)相比較,若相等,則使ZF=1,且將ECX: EBX中的值送指定的8字節(jié)存儲單元替換原有的存儲器操作數(shù); 否則使ZF=0,且將指定的8字節(jié)存儲器操作數(shù)送EDX: EAX。【例3.36】設(shè)[EAX]=01010101H,[EBX]=02020202H,[ECX]=03030303H,[EDX]=04040404H,而DS: 2000H所指的內(nèi)存單元開始的8個連續(xù)單元的內(nèi)容為0404040401010101H。執(zhí)行以下指令,并分析結(jié)果。 CMPXCHG8B[2000H] 結(jié)果是將DS: 2000H所指單元開始的8個字節(jié)和EDX: EAX中的8個字節(jié)比較,由于[EDX: EAX]中為0404040401010101H,而存儲器DS: [2000H]中開始的8個字節(jié)也是0404040401010101H,因此ZF=1,并將ECX: EBX中的數(shù)送給DS: 2000H開始的8個單元,使得DS: [2000H]開始的8個字節(jié)為0303030302020202H。3. 讀時間標(biāo)記計數(shù)器指令指令格式: RDTSC Pentium處理器有一個片內(nèi)64位計數(shù)器,稱為時間標(biāo)記計數(shù)器。計數(shù)器的值在每個時鐘周期都遞增,在RESET后該計數(shù)器被置0。執(zhí)行RDTSC指令可以將Pentium中的64位時間標(biāo)記計數(shù)器的高32位送EDX,低32位送EAX。一些應(yīng)用軟件需要確定某個事件已經(jīng)執(zhí)行了多少個時鐘周期,在執(zhí)行該事件之前和之后分別讀出時鐘標(biāo)志計數(shù)器的值,計算兩次值的差就可得出時鐘周期數(shù)。4. 讀模式專用寄存器指令指令格式: RDMSR 該指令使軟件可訪問模式專用寄存器的內(nèi)容,這兩種模式專用寄存器是機器地址檢查寄存器(MCA)和機器類型檢查寄存器(MCT)。若要訪問MCA,指令執(zhí)行前需將ECX置為0; 而為了訪問MCT,需要將ECX置為1。執(zhí)行指令時在訪問的模式專用寄存器與寄存器組EDX: EAX之間進行64位的操作。具體來說,是將ECX所指定的模式專用寄存器的內(nèi)容送EDX: EAX,高32位送EDX,低32位送EAX。5. 寫模式專用寄存器指令指令格式: WRMSR 該指令將EDX: EAX的內(nèi)容送到由ECX指定的模式專用寄存器。具體來說,EDX和EAX的內(nèi)容分別作為高32位和低32位。若指定的模式寄存器有未定義或保留的位,則這些位的內(nèi)容不變。6. 恢復(fù)系統(tǒng)管理模式指令指令格式: RSM Pentium處理器有一種稱為系統(tǒng)管理模式(SMM)的操作模式,這種模式主要用于執(zhí)行系統(tǒng)電源管理功能。外部硬件的中斷請求使系統(tǒng)進入SMM模式,執(zhí)行RSM指令后返回原來的實模式或保護模式。7. 32位寄存器與CR4之間的傳輸指令指令格式: MOVCR4,reg32 MOVreg32,CR4 該指令實現(xiàn)將32位寄存器的內(nèi)容傳送至控制寄存器CR4或?qū)⒖刂萍拇嫫鰿R4的內(nèi)容送到32位寄存器中。思考與練習(xí)1. 什么叫尋址方式?8086/8088系統(tǒng)中關(guān)于存儲器操作數(shù)的尋址方式有哪幾類?80386及后繼處理器支持的新增的存儲器尋址方式有哪幾種?2. 指令中數(shù)據(jù)操作數(shù)的種類有哪些?3. 指出段地址、偏移地址與物理地址之間的關(guān)系。有效地址EA又是指什么?4. 在8086/8088系統(tǒng)中,能用于寄存器間接尋址及相對尋址的寄存器有哪些?它們通常與哪個段寄存器配合形成物理地址?5. 80x86指令系統(tǒng)中新增加的數(shù)據(jù)傳送類指令有哪些?分析它們的功能。6. 什么是堆棧操作?以下關(guān)于堆棧操作的指令執(zhí)行后,SP的值是多少? PUSHAX PUSHCX PUSHDX POPAX PUSHBX POPCX POPDX 7. 用匯編語言指令實現(xiàn)以下操作。(1) 將寄存器AX、BX和DX的內(nèi)容相加,和放在寄存器DX中。(2) 用基址變址尋址方式(BX和SI)實現(xiàn)AL寄存器的內(nèi)容和存儲器單元BUF中的一個字節(jié)相加的操作,和放到AL中。(3) 用寄存器BX實現(xiàn)寄存器相對尋址方式(位移量為100H),將DX的內(nèi)容和存儲單元中的一個字相加,和放到存儲單元中。(4) 用直接尋址方式(地址為0500H)實現(xiàn)將存儲器中的一個字與立即數(shù)3ABCH相加,和放回該存儲單元中。(5) 用串操作指令實現(xiàn)將內(nèi)存定義好的兩個字節(jié)串BUF1和BUF2相加后,存放到另一個串BUF3中的功能。8. 指出下列指令中,源操作數(shù)及目的操作數(shù)的尋址方式。(1) SUBBX,[BP 35](2) MOVAX,2030H(3) SCASB(4) INAL,40H(5) MOV[DI BX],AX(6) ADDAX,50H[DI](7) MOVAL,[1300H](8) MULBL9. 已知(DS)=1000H,(SI)=0200H,(BX)=0100H,(10100H)=11H,(10101H)=22H,(10600H)=33H,(10601H)=44H,(10300H)=55H,(10301H)=66H,(10302H)=77H,(10303H)=88H,試分析下列各條指令執(zhí)行完后AX寄存器的內(nèi)容。(1) MOVAX,2500H(2) MOVAX,500H[BX] (3) MOVAX,[300H](4) MOVAX,[BX](5) MOVAX,[BX][SI](6) MOVAX,[BX SI 2]10. 判斷下列指令是否有錯,如果有錯,說明理由。(1) SUBBL,BX(2) MOVBYTE PTR[BX],3456H(3) SHLAX,CH(4) MOVAH,[SI][DI](5) SHRAX,4(6) MOVCS,BX(7) MOV125,CL(8) MOVAX,BYTE PTR[SI](9) MOV[DI],[SI]11. 設(shè)(DS)=1000H,(ES)=2000H,(SS)=3000H,(SI)=0080H,(BX)=02D0H,(BP)=0060H,試指出下列指令的源操作數(shù)字段是什么尋址方式?它的物理地址是多少?(1) MOVAX,0CBH(2) MOVAX,[100H](3) MOVAX,[BX](4) MOVAX,[BP](5) MOVAX,[BP 50](6) MOVAX,[BX][SI] 12. 分別說明下列每組指令中的兩條指令的區(qū)別。(1) ANDCL,0FHORCL,0FH(2) MOVAX,BXMOVAX,[BX](3) SUBBX,CXCMPBX,CX(4) ANDAL,01HTESTAL,01H(5) JMPNEAR PTR NEXTJMPSHORT NEXT(6) ROLAX,CLRCLAX,CL(7) PUSHAXPOPAX13. 試分析以下程序段執(zhí)行完后BX的內(nèi)容為何? MOVBX,1030H MOVCL,3 SHLBX,CL DECBX 14. 寫出下列指令序列中每條指令的執(zhí)行結(jié)果,并在DEBUG環(huán)境下驗證,注意各標(biāo)志位的變化情況。 MOVBX,126BH ADDBL,02AH MOVAX,2EA5H ADDBH,AL SBBBX,AX ADCAX,26H SUBBH,-8 15. 編寫能實現(xiàn)以下功能的程序段。根據(jù)CL中的內(nèi)容決定程序的走向,設(shè)所有的轉(zhuǎn)移都是短程轉(zhuǎn)移。若D0位等于1,其他位為0,轉(zhuǎn)向LAB1; 若D1位等于1,其他位為0,轉(zhuǎn)向LAB2; 若D2位等于1,其他位為0,轉(zhuǎn)向LAB3; 若D0、D1、D2位都是1,則順序執(zhí)行。
你還可能感興趣
我要評論
|