匯編語言-指令集_第1頁
匯編語言-指令集_第2頁
匯編語言-指令集_第3頁
匯編語言-指令集_第4頁
匯編語言-指令集_第5頁
已閱讀5頁,還剩84頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

80x86/8088指令系統(tǒng)

8086/8088的指令系統(tǒng)豐富,而且指令的功能也強。 大多數(shù)指令既能處理字數(shù)據(jù),又能處理字節(jié)數(shù)據(jù)。 指令系統(tǒng)可分為如下6個功能組: (1)數(shù)據(jù)傳送 (2)算術運算 (3)邏輯運算 (4)串操作 (5)程序控制 (6)處理器控制 匯編語言中,指令語句可由四部分組成,一般格式如下:

[標號:]指令助記符

[操作數(shù)1[,操作數(shù)2]][;注釋]

(一)數(shù)據(jù)傳送指令 可以實現(xiàn)數(shù)據(jù)傳送的指令可分為:傳送指令,交換指令,地址傳送指令,堆棧操作指令,標志傳送指令。

1.傳送指令 其格式如下:MOVDST,SRC

源操作數(shù)可以是累加器、寄存器、存儲單元及立即數(shù), 目的操作數(shù)可以是累加器、寄存器和存儲單元。 傳送不改變源操作數(shù)。 傳送指令能實現(xiàn)下列傳送功能:

(1)CPU內(nèi)部寄存器之間的數(shù)據(jù)傳送。例如:

MOVAH,AL MOVDL,DH MOVBP,SP MOVAX,CS

注意:源和目的操作數(shù)不能同時是段寄存器;代碼段寄存器CS不能作為目的數(shù);指令指針I(yè)P不能作為源,也不能作為目的操作數(shù)。

(2)立即數(shù)送至通用寄存器或存儲單元。例如:

MOVAL,3 MOVSI,-5 MOVVARB,-1;VARB是變量名,代表一個存儲單元

MOVVARW,3456H;VARW是一個字變量

MOV[SI],6543H

注意: 立即數(shù)不能直接送到段寄存器, 立即數(shù)永遠不能作為目的操作數(shù)。 (3)寄存器與存儲器間的數(shù)據(jù)傳送。例如:

MOVAX,VARW MOVBH,[DI] MOVDI,ES:[SI+3] MOVVARB,DL MOVDS:[BP],DL MOVVARW,DS MOVES,VARW

注意: 源操作數(shù)和目的操作數(shù)不能一個為字節(jié)另一個為字;

源操作數(shù)和目的操作數(shù)不能同時是存儲器操作數(shù)(串指令除外)

如果要在兩個存儲單元間傳送數(shù)據(jù),怎么辦呢? 那么可利用通用寄存器過渡的方法進行: 例如:把字變量VARW1的內(nèi)容送到字變量VARW2 MOVAX,VARW1 MOVVARW2,AX

這種方法也適用于段寄存器間的數(shù)據(jù)傳送。例如:

MOVAX,CS MOVDS,AX

請熟悉下面語句:

MOVAL,‘D’; 立即數(shù)(字符’D’的ASCII碼)送到AL寄存器

MOVBX,OFFSETTABLE

;把TABLE的偏移地址(不是內(nèi)容)送到BX寄存器,OFFSET為屬性操作符。 2.交換指令 利用交換指令可方便地實現(xiàn)通用寄存器與通用寄存器或存儲單元的數(shù)據(jù)交換。交換指令的格式如下:

XCHGOPRD1,OPRD2

此指令把操作數(shù)OPRD1的內(nèi)容與操作數(shù)OPRD2的內(nèi)容交換。操作數(shù)同時是字節(jié)或字。 例如: XCHGAL,AH XCHAGSI,BX OPRD1和OPRD2可以是通用寄存器或存儲單元。但不能包括段寄存器,也不能同時是存儲單元,還不能有立即數(shù)。 對于要交換的存儲單元,可有多種尋址方式。 例如:XCHGBX,[BP+SI]

如指令執(zhí)行前:(BX)=6F30H,(BP)=0200H,(SI)=0046H, (SS)=2F00H,(2F246)=4154H

指令執(zhí)行后(BX)=4154H,(2F246H)=6F30H 3.地址傳送指令

8086/8088有3條地址傳送指令。 (1)LEA(LoadEffectiveAddress) LEAREG,OPRD

把操作數(shù)OPRD的有效地址傳送到操作數(shù)REG。

操作數(shù)OPRD必須是指存儲器, 操作數(shù)REG必須是一個16位的通用寄存器。 例如:

LEAAX,BUFFER ;BUFFER是變量名

LEASI,[BP+SI+4]

例如:LEABX,[BX+SI+0F62H]

如執(zhí)行指令前(BX)=0400H,(SI)=003CH

執(zhí)行指令后(BX)=0400+003C+0F62=139EH

(2)LDS(LoadpointerintoDS)

段值和段內(nèi)偏移構成32位指針(兩個16位地址)。

LDS用于傳送32位地址指針,格式如下:

LDSREG,OPRD

執(zhí)行的操作: (REG)<-(SRC) (DS)<-(SRC+2)

該指令把操作數(shù)OPRD中所含的一個32位地址指針的段值部分送到數(shù)據(jù)段寄存器,把偏移部分送到指令給出的通用寄存器REG。操作數(shù)OPRD必須是一個32位的存儲器操作數(shù)。

32位地址指針的偏移部分存儲在雙字變量的低地址字中, 段值部分存放在高地址字中 例如:LDSSI,[10H]

如執(zhí)行指令前(DS)=C000H,(C0010H)=0108H, (C0012H)=2000H.

執(zhí)行指令后(SI)=0180H,(DS)=2000H

(3)LES(LoadpointerintoES) LES指令也是用于傳送32位地址指針,格式如下:

LESREG,OPRD

執(zhí)行的操作: (REG)<-(SRC) (ES)<-(SRC+2)

例如:LESDI,[BX]

如執(zhí)行指令前:(DS)=B000H,(BX)=080AH, (B080AH)=05AEH,(B080CH)=4000H

執(zhí)行指令后(DI)=05AEH,(ES)=4000H

例如:如果TABLE為數(shù)據(jù)段中0032單元的符號名,其中存放的內(nèi)容為1234H,試問以下兩條指令有什么區(qū)別?

MOVAX,TABLE LEAAX,TABLE

第2條效果與

MOVAX,OFFSETTABLE

相同。分析其中的數(shù)據(jù)傳送指令 3.堆棧操作指令 在8086/8088系統(tǒng)中,堆棧是一段RAM區(qū)域,是以“后進先出”方式工作的一個存儲區(qū)。 稱為棧底的一端地址較大(高地址), 稱為棧頂?shù)囊欢说刂份^小(低地址)。 堆棧的段值在堆棧段寄存器SS中,堆棧指針SP始終指向棧頂。 堆棧的存取必須以字位單位。 堆棧操作指令分為2種: (1)進棧指令PUSH

格式:PUSHSRC SRC可以是通用寄存器、段寄存器也可以是字存儲單元。 執(zhí)行的操作:把源數(shù)據(jù)壓入堆棧。步驟為:

1.堆棧指針寄存器器SP的值減2;

2.把源操作數(shù)SRC送入由SP所指的棧頂。

例如:PUSHAX

假設(AX)=2107H

(2)出棧指令POP

格式:POPDST

執(zhí)行的操作:從堆棧頂彈出一個字數(shù)據(jù)到目的操作數(shù)DST。

步驟為:

1.把堆棧指針寄存器SP所指的字數(shù)據(jù)送往目的操作數(shù)DST;

2.堆棧指針寄存器器SP的值加2。

DST可以是通用寄存器、段寄存器(CS除外),也可以是字存儲單元 接前面例子:

POPAX

執(zhí)行后: (AX)=2107H

注意:

PUSH和POP只能作字操作。 它們可以使用除立即數(shù)之外的其它尋址方式。 但POP指令不運行訪問CS寄存器。 下面程序說明堆棧的一種用途,請熟悉。

PUSHAX; 保護AX PUSHBX; 保護BX ….. POPBX; 恢復BX POPAX; 恢復AX

例:假設(SS)=2250H,(SP)=0140H

如果在堆棧中存入5個數(shù)據(jù),則棧頂?shù)奈锢淼刂肥嵌嗌伲?未存入數(shù)據(jù)之前物理地址=22500+0140=22640H

存入5個數(shù)據(jù),棧頂?shù)奈锢淼刂窞椋?/p>

22640–0A=22636H

如果又從堆棧中取出3個數(shù)據(jù),則棧頂?shù)奈锢淼刂肥嵌嗌伲?/p>

22636+6=2263CH

通過前面講授的指令,數(shù)據(jù)交換至少有3種方式: 傳送指令、交換指令、堆棧指令 例如:將寄存器AX與SI的內(nèi)容交換。 用MOV指令,利用通用寄存器過渡的方式:

MOVBX,AX MOVAX,SI MOVSI,BX

用交換指令XCHG XCHGAX,SI

用堆棧指令

PUSHAX; PUSHSI; POPAX; POPSI;

其它傳送操作指令 累加器專用傳送指令:

IN OUT XLAT

標志寄存器傳送指令:

LAHF SAHF PUSHF POPF

(二)加減運算指令

1.加法指令ADD

其格式如下:ADDOPRD1,OPRD2

執(zhí)行的操作:(OPRD1)<-(OPRD1)+(OPRD2)

例如:

MOVAX,7896H; AX=7896H,各標志位保持不變

ADDAL,AH; AL=0EH,即AX=780EH ;CF=1,ZF=0,SF=0,OF=0,AF=0,PF=0

又如: 例:ADDDX,0F0F0H

若執(zhí)行前(DX)=4652H,則執(zhí)行后(DX)=3742H,

ZF=0,SF=0,CF=1,OF=0

例:ADDAX,4321

若執(zhí)行前(AX)=62A0,則執(zhí)行后(AX)=A5C1H,

ZF=0,SF=1,CF=0,OF=1,加法操作影響標志位。 2.帶進位加指令ADC(ADdwithCarry) 其格式如下:ADCOPRD1,OPRD2

(OPRD1)<-(OPRD1)+(OPRD2)+CF

例如,執(zhí)行兩個雙精度數(shù)(32位)的加法。設目的操作數(shù)放在DX和AX中,其中DX存放高位字。源操作數(shù)放在BX,CX中,其中BX存放高位字。 如執(zhí)行前 (DX)=0002H, (AX)=0F365H, (BX)=0005H, (CX)=0E024H

指令序列位: ADDAX,CX ADCDX,BX

執(zhí)行第一條指令后,(AX)=D389H,SF=1,ZF=0,CF=1,OF=0

執(zhí)行第二條指令后,(DX)=0008H,SF=0,ZF=0,CF=0,OF=0

運算結果:(DX)=0008H,(AX)=D389H

從上面例子可以看出:為實現(xiàn)雙精度加法,必須用兩條指令分別完成低位字和高位字的加法。在高位字相加時,應該使用ADC指令以便把前一條ADD指令作低位字加法所產(chǎn)生的進位值加入高位字之內(nèi)。帶符號雙精度數(shù)的溢出,應該根據(jù)ADC指令的OF位來判斷,而作低位加法用的ADD指令的溢出標志在雙精度數(shù)相加時,是無意義的。 3.加1指令INC(INCrement) 其格式如下:INCOPRD

(OPRD)<-(OPRD)+1

功能:對操作數(shù)加1. OPRD可以是通用寄存器,也可以是存儲單元。 指令執(zhí)行的結果影響ZF、SF、OF、PF、AF,但不影響CF.

改指令主要用于調(diào)整地址指針和用于計算器。

例:寫出把首地址為BLOCK的字數(shù)組的第6個字送到DX寄存器的指令。 (1)使用寄存器間接尋址

MOVBX,OFFSETBLOCK ADDBX,000AH MOVDX,[BX]

(2)寄存器相對尋址

MOVBX,OFFSETBLOCK MOVDX,[BX+000AH]

其中,MOVBX,OFFSETBLOCK還可以寫成:

LEABX,BLOCK

例:在TABLE數(shù)組中依次存儲了7個字數(shù)據(jù),緊接著是名位ZERO的字單元,表示如下:

TABLEDW23,36,2,100,3200,54,0 ZERODW?

(1)如果BX包含數(shù)據(jù)TABLE的初始地址,請編寫指令將數(shù)據(jù)0傳送給ZERO單元。

MOVAX,[BX+0CH] MOVZERO,AX

(2)如果BX包含數(shù)據(jù)0在數(shù)組中的位移量,請編寫指令將數(shù)據(jù)0傳送給ZERO單元。

MOVAX,[TABLE+BX] MOVZERO,AX

例:試分析下列程序段執(zhí)行后,AX的內(nèi)容是是多少?

Datasegment Adw0 Bdw0 Cdw230,20,54 Dataends Codesegment … MOVBX,OFFSETC MOVAX,[BX] MOVB,AX MOVAX,2[BX] ADDAX,B … Codeends 4.減法指令SUB(SUBtraction) 其格式如下:SUBOPRD1,OPRD2

執(zhí)行的操作:(OPRD1)<-(OPRD1)-(OPRD2)

例:SUB[SI+14H],0136H

若執(zhí)行前(DS)=3000H,(SI)=0040H,(30054H)=4336H

則執(zhí)行后(30054H)=4200H,

ZF=0,SF=0,CF=0,OF=0

例:SUBDH,[BP+4]

若執(zhí)行前(DH)=41H,(SS)=0000H,(BP)=00E4,(000E8)=5AH

則執(zhí)行后(DH)=E7H,

ZF=0,SF=1,CF=1,OF=0,

加法操作影響標志位。

減法的OF位設置方法為:若兩個數(shù)的符號相反,而結果的符號與減數(shù)(減號后那個數(shù))相同,則OF=1,說明結果是錯誤的。 5.帶借位減法指令SBB(SUBtractwithBorrow) 其格式如下:SBBOPRD1,OPRD2

執(zhí)行的操作:(OPRD1)<-(OPRD1)-(OPRD2)-CF

例: SBBAL,DL SBBDX,AX

該指令主要用于多字節(jié)相減的場合。

6.減1指令DEC(DECrement) 格式:DECOPRD

執(zhí)行的操作:(OPRD)<-(OPRD)-1

例如:DECVARB;VARB是字節(jié)變量。

OPRD可以是通用寄存器,也可以是存儲單元。 指令執(zhí)行的結果影響ZF、SF、OF、PF、AF,但不影響CF.

改指令主要用于調(diào)整地址指針和用于計算器。 7.取補指令NEG(NEGate) 其格式如下:NEGOPRD

執(zhí)行的操作:(OPRD)<--(OPRD)

例:

NEGAL

如在字節(jié)操作時,對-128取補,或在字操作時對-32768取補,則操作數(shù)不變,但是OF被置1。其它均為0.

操作數(shù)可以是寄存器,也可是一存儲單元。 此指令的執(zhí)行結果影響CF、ZF、SF、OF、AF和PF。 操作數(shù)位0時,求補運算的結果使CF=0,其它情況則均為1. 8.比較指令CMP(CoMPare) 其格式如下:CMPOPRD1,OPRD2

這條指令將操作數(shù)OPRD1減去OPRD2,但是運算結果不送到OPRD1,但是,要影響到標志位CF、ZF、SF、OF、AF、PF.

例:

CMPSI,DI CMPCL,5 CMPDX,[BP-4]

比較指令主要是用于比較兩個數(shù)的關系,如大小。 根據(jù)ZF是否為0,判斷兩者是否相等; 如果兩者是無符號數(shù),可根據(jù)CF判斷大??; 如兩者為有符號數(shù),則要根據(jù)SF和OF判斷大小。

例:設X,Y,Z均為雙精度數(shù),它們分別存放在地址為X,X+2;Y,Y+2;Z,Z+2的存儲單元中。下列指令序列實現(xiàn)(X+Y+24-Z),并將結果放在W和W+2單元中。

MOVAX,X MOVDX,X+2 ADDAX,Y ADCDX,Y+2 ADDAX,24 ADCDX,0 SUBAX,Z SBBDX,Z+2 MOVW,AX MOVW+2,DX

例:設在當前數(shù)據(jù)段的偏移地址2000H單元內(nèi),含有兩指針,它們是兩個16位變量的偏移地址和段地址,試寫出把該變量裝入AX的指令序列。

MOVBX,[2000H] MOVES,[2002H] MOVAX,ES:[BX]

例:寫出執(zhí)行以下計算的指令指令序列。

Z←W+(Z-X)

其中X,W,Z均為存放16位帶符號數(shù)單元的地址。

方法1:

MOVAX,Z MOVBX,X SUBAX,BX MOVBX,W ADDAX,BX MOVZ,AX

方法2:

MOVAX,Z SUBAX,X ADDAX,W MOVZ,AX

執(zhí)行下列指令序列后,AX寄存器中的內(nèi)容是什么?

TABLEDW10,20,30,40,50 RETURNDW3 … MOVBX,OFFSETTABLE ADDBX,RETURN MOVAX,[BX]

(AX)=1E00H

指出下列指令的錯誤: (1)MOVAH,BX

位數(shù)不匹配 (2)MOVAX,[SI][DI] SI,DI同為變址寄存器 (3)CMP15,BX

目的操作數(shù)不能為立即數(shù) (4)PUSHBL PUSH,POP只能是對字單元進行操作 (5)POPCS

代碼段寄存器不能作為目的操作數(shù) (6)MOV[BX],[SI]

源操作數(shù)和目的操作數(shù)不能同時為存儲器單元內(nèi)容 (7)CMPOP1,OP2(OP1,OP2是字節(jié)變量)

字節(jié)變量相當于存放于存儲器,“源目”不能同時為存儲器

執(zhí)行下列指令序列后,AX=?,BX=? MOVAX,0123H MOVBX,0321H PUSHAX PUSHBX POPAX POPBX

AX=0321H,BX=0123H (三)乘除運算指令 乘除運算指令分為無符號數(shù)運算和有符號數(shù)運算指令,這點與加減法運算指令不同。 乘除運算對標志位的影響有些特別。

1.乘法指令 在乘法指令中,一個操作數(shù)總是隱含在寄存器中(AL或AX),另一個操作數(shù)可以采用除立即數(shù)以外的任一種尋址方式。 (1)無符號數(shù)乘法指令MUL(MULtiply) 格式:MULOPRD

在乘法指令里,目的操作數(shù)必須是累加器。 兩個8位數(shù)相乘得到的是16位乘積,存放于AX中;兩個16位數(shù)相乘得到的是32位乘積,存放于DX(高位字)和AX(低位字)中。 如果乘積結果的高半部分(字節(jié)相乘時為AH,字相乘時為DX)不等于0,則CF=1,OF=1。否則,CF=0,OF=0.

(2)有符號數(shù)乘法指令IMUL(sIgnedMULtiply) 格式:IMULOPRD

這條指令把被乘數(shù)和乘數(shù)均作為有符號數(shù)。 如果乘積結果的高半部分(字節(jié)相乘時為AH,字相乘時為DX)不是低半部分的符號擴展,則標志CF=1,OF=1。否者,CF=0,OF=0。 所以,MUL和IMUL指令運行后,可根據(jù)CF和OF是否等于1來判斷AH或DX中含有的結果是否為有效數(shù)。 例:如(AL)=B4H,(BL)=11H, 求MULBL和IMULBL后的乘積值?

(AL)=B4H,無符號數(shù)為180D,帶符號數(shù)為-76D (BL)=11H,無符號數(shù)位17D,帶符號數(shù)為17D

執(zhí)行MULBL結果:(AX)=3060D=0BF4H,CF=OF=1

執(zhí)行IMULBL結果:(AX)=-1292D=FAF4H,CF=OF=1 2.除法指令 在除法指令中,被除數(shù)總是隱含在寄存器AX(除數(shù)是8位)或者DX和AX(除數(shù)是16位)中,另一個操作數(shù)可以采用除立即數(shù)以外的任一種尋址方式。 (1)無符號數(shù)除法指令DIV(DIVision) 格式:DIVOPRD

字節(jié)操作時:

(AL)<-(AX)/(OPRD)的商,(AH)<-(AX)/(OPRD)的余數(shù); 字操作時:

(AX)<-(DX,AX)/(OPRD)的商,

(DX)<-(DX,AX)/(OPRD)的余數(shù).

如果除數(shù)是0,或者在8位數(shù)除時商超過8位,或者在16位除時超過16位,則認為是溢出,引起0號中斷。 除法指令對標志位的影響無定義。

(2)有符號數(shù)除法指令IDIV(sIgnedDIVision) 格式:IDIVOPRD

這條指令把被除數(shù)和除數(shù)均作為有符號數(shù)。 字節(jié)操作時: 如果除數(shù)是0,或者商太大 (字節(jié)除時超過127,字除時超過32767) 或者商太小 (字節(jié)除時超過-127,字除時超過-32767) 則引起0號中斷。 例如:(AX)=0400H,(BL)=B4H,

執(zhí)行DIVBL的結果是

(AH)=124D=7CH(余數(shù)),(AL)=5D=05H(商) 執(zhí)行IDIVBL的結果是

(AH)=36D=24H(余數(shù)),(AL)=-13D=F3H(商) 3符號擴展指令 由于除法指令隱含使用字被除數(shù)或雙字被除數(shù),所以當被除數(shù)為字節(jié),或者除數(shù)和被除數(shù)均為字時,需要在除操作前擴展被除數(shù)。 (1)字節(jié)轉為字指令CBW(ConvertBytetoWord) 格式:CBW

功能:把寄存器AL中的符號擴展到寄存器AH中。 例如: MOVAX,3487H;AX=3487H,AL=87H CBW ;AX=FF87H

這條指令不影響各標志位。 (2)字轉為位雙字指令CWD(ConvertWordtoDoubleword)

格式:CWD

功能:把AX中的符號位擴展到寄存器DX。 例如: MOVAX,4567H ;AX=4567H CWD ;AX=4567H,DX=0

例如:計算表達式(X*Y+Z-1024)/75之值。 假設其中的X、Y、Z均為16位帶符號數(shù),分別存放在名為XXX、YYY、ZZZ的變量單元中。把最后計算結果的商在AX中,余數(shù)保存在DX中。

MOVAX,XXX IMULYYY ;計算X*Y,結果已擴展至32位

MOVCX,AX MOVBX,DX ;乘積保存到BX、CX中

MOVAX,ZZZ CWD ;把ZZZ也擴展成32位

ADDAX,CX ;再計算和

ADCDX,BX SUBAX,1024 ;再計算差

SBBDX,0 MOVCX,75 IDIVCX ;最后計算商和余數(shù)

(四)邏輯運算和移位指令

1.邏輯運算指令 (1)否操作指令 格式:NOTOPRD

這條指令把操作數(shù)OPRD取反,然后送回OPRD。 操作數(shù)可以是通用寄存器,也可以是存儲器操作數(shù)。 此指令對標志沒有影響。 (2)與操作指令AND

格式:ANDOPRD1,OPRD2

這條指令對兩個操作數(shù)進行按位的邏輯“與”運算,結果送到目的操作數(shù)OPRD1。該指令執(zhí)行后,標志CF=0,OF=0,標志PF、ZF、SF反映運算結果,標志AF未定義。

與操作指令主要用在使一個操作數(shù)中的若干位維持不變,而另外若干位清0的場合。 把要維持不變的這些位與“1”相“與”,而把要清位0的這些位與“0”相“與”就能達到這樣的目的。

(3)或操作指令OR

格式:OROPRD1,OPRD2

這條指令執(zhí)行后,標志CF=0,標志OF=0,標志PF,ZF,SF反映運算結果,標志AF未定義。 某個操作數(shù)與自己相“或”,則值不變,但進位標志CF清0。

或指令主要用在使一個操作數(shù)中的某些位維持不變,而另外若干位設置為1的場合。 (4)異或操作指令XOR

格式:XOROPRD1,OPRD2

這條指令對兩個操作進位按位的邏輯“異或”運算,結果送到目的操作數(shù)OPRD1。該指令執(zhí)行以后,標志CF=0,OF=0,標志PF,ZF,SF反映運算結果,AF未定義。 某個操作數(shù)自己與自己相“異或”,則結果為0,并使CF清0。

異或操作主要用在使一個操作數(shù)中的若干位維持不變,而另外若干位置取反的場合。 把要維持不變的這些位與“0”相“異或”,而把要去反的位與“1”相異或就能實現(xiàn)改功能。

(5)測試指令TEST

格式:TESTOPRD1,OPRD2

這條指令和指令AND類似,也把兩個操作數(shù)進行按位“與”,但結果不送到操作數(shù)OPRD1。 該指令執(zhí)行后,標志ZF、PF和SF反映運算結果,標志CF和OF被清0。 該指令常用于檢測某些位是否為1,但又不希望改變原操作數(shù)的場合。 例如:要檢查AL中的位6或位2是否有一位是1。

TESTAL,01000100B ;符號B表示二進制數(shù) 或

TESTAL,44H

如果位6和位2全為0,那么在執(zhí)行上面的指令后,ZF被置為1,否者ZF被清0。

舉例:

1.要求屏蔽0、1兩位,可用AND指令并設置常數(shù)FCH。

MOVAL,BFH ;將待屏蔽的數(shù)送至AL ANDAL,FCH

執(zhí)行后(AL)=BCH 2.要求第5位置1,可用OR指令

MOVAL,43H ;將待處理的數(shù)送至AL ORAL,20H

執(zhí)行后(AL)=63H 3.要測試操作數(shù)的某位是否為1,則可先把該操作數(shù)求反,然后用TEST指令測試。 如要測試AL寄存器中第2位是否為1,如是則轉移到EXIT:

MOVDL,AL NOTDL TESTDL,00000100B

JEEXIT 2.一般移位指令 (1)算術左移或邏輯左移指令,SAL/SHL (ShiftArithmeticLeft或ShiftLogicLeft)

算術左移和邏輯左移進行相同的操作,盡管為了方便提供了兩個助記符,但只有一條機器指令。具體格式如下:

SALOPRD,m或者

SHLOPRD,m

算術左移SAL/邏輯左移SHL指令把操作數(shù)OPRD左移m位。每移動一位,右邊用0補足一位,移出的最高位進入標致位CF。 例如:

MOVAL,8CH SHLAL,1;AL=18H,CF=1,PF=1,ZF=0,SF=0,OF=1 MOVCL,6 SHLAL,CL;AL=0,CF=0,PF=1,ZF=1,SF=0,OF=0

只要左移以后的結果未超出一個字節(jié)或一個字的表達范圍,那么每左移一次,原相當于乘以2。

例:把寄存器AL中的內(nèi)容(設為無符號數(shù))乘10,結果放在AX中。

XORAH,AH ;(AX)=0 SHLAX,1 ;2X MOVBX,AX ;暫存2X SHLAX,1 ;4X SHLAX,1 ;8X ADDAX,BX ;8X+2X (2)算術右移指令SAR(ShiftArithmeticRight) 格式:SAROPRD,m

該指令是操作數(shù)右移m位,同時每移一位,左邊的符號位保持不變,移入位與符號位一致,移出的最低位進入標致位CF。 例如: MOVCL,5 SAR[DI],CL

如執(zhí)行前:(DS)=F800H,(DI)=180AH,(F980A)=0064H/8064H

執(zhí)行后:(F980A)=0003H/FC03H

(3)邏輯右移指令SHR(ShiftlogicRight) 格式:SHROPRD,m

該指令是操作數(shù)右移m位,同時每移一位,左邊用0補足,移出的最低位進入標致位CF。 對于無符號數(shù)而言,邏輯右移一位相當于除以2。

在匯編語言程序設計中,經(jīng)常需要對以位為單位的數(shù)據(jù)進行合并和分解處理。這種操作一般是通過移位指令和邏輯運算指令執(zhí)行。 例如:假設DATA1和DATA2各長4位,分別存放在AL寄存器的低4位和高4位中,現(xiàn)要把它們分別存放到BL寄存器和BH寄存器的低4位中。

MOVBL,AL ANDBL,0FH ;得DATA1 MOVBH,AL MOVCL,4 SHRBH,CL ;得DATA2 3.循環(huán)移位指令

8086/8088有四條循環(huán)指令,這些指令可以一次只移移位;也可以一位移多位,那么移位次數(shù)存放在CL寄存器中。 這些指令格式如下:

ROLOPRD,m (RotateLeft)

ROROPRD,m RCLOPRD,m (Rotateleftthroughcarry) RCROPRD,m

其中,m是移位次數(shù),或為1或為CL。操作數(shù)OPRD可以是通用寄存器,可以是存儲器操作數(shù)。前兩條循環(huán)指令沒有把進位標志CF包含在循環(huán)的環(huán)中;后兩條循環(huán)指令把進位標志CF包含在循環(huán)的環(huán)中,即作為整個循環(huán)的一部分。 對于不帶進位的循環(huán)移位,如果操作數(shù)是8位,則移位8次后操作數(shù)就能復原;如果操作數(shù)是16位,則移位16次后就能復原。 對于帶進位的循環(huán)指令而言,如果操作數(shù)是8位,那么在移位9次后操作數(shù)就能復原;如果操作數(shù)是16位,則要復原需要移位17次。

MOVCL,9 RCRAL,CL

通過循環(huán)移位指令和其它移位指令的結合,可以實現(xiàn)兩個或多個操作數(shù)的重新結合。 例如:實現(xiàn)把AL的高4位和低4位交換

ROLAL,1 ROLAL,1 ROLAL,1 ROLAL,1

例(AX)=0012H,(BX)=0034H,要求把他們裝配在一起形成(AX)=1234H MOVCL,8 ROLAX,CL ADDAX,BX

例如:試分析下面程序完成什么功能?

MOVCL,4 SHLDX,CL MOVBL,AH SHLAX,CL SHRBL,CL ORDL,BL

(五)串處理指令

回憶一下:同學們學習了C語言,知道了哪些關于串操作的函數(shù)?

(五)串處理指令

1.串拷貝 利用C語言編寫串拷貝函數(shù)

voidcopy_str(char*dst,char*src,intlen) { inti; for(i=0;i<len;i++) {

*dst=*src; dst++; src++; } } src:源串

dst:目標串

len:拷貝長度

++:拷貝方向 關鍵字for:循環(huán)過程

(1)利用匯編指令進行串拷貝

src:源串 ——〉由SI寄存器給出

dst:目標串 ——〉由DI寄存器給出

len:拷貝長度 ——〉由CX寄存器給出

++:拷貝方向 ——〉由PSW的DF給出(CLD,STD設置) 關鍵字for:循環(huán)過程 ——〉由指令REP給出 進一步講,操作對象由MOVS/MOVSB/MOVSW給出 其中MOVS指令的格式為:

MOVSDST,SRC

應在操作數(shù)種明確指明是字還是字節(jié)。 例:MOVSES:BYTEPTR[DI],DS:[SI] MOVSES:WORDPTR[DI],DS:[SI]

而MOVSB和MOVSW無需再專門寫出操作數(shù)。 結合起來:REPMOVSDST,SRC

或REPMOVSB/REPMOVSW

注意:(1)目的操作數(shù)必須放在附加段中; (2)源操作數(shù)原則上應放在數(shù)據(jù)段中,但可通過段前綴改變串拷貝程序。左邊源串位于數(shù)據(jù)段,右邊源串位于附加段:

(2)存入串指令

STOSDST STOSB STOSW

功能:把AL或AX的內(nèi)容存入由DI指定的目標串中。 存入的個數(shù)由CX寄存器決定。

(3)從串取指令

LODSSRC LODB LODW

功能:把由SI指定的源串中取內(nèi)容并送至AL或AX寄存器。 存入的個數(shù)由CX寄存器決定。

2.串比較 (1)利用C語言編寫串比較函數(shù)

intcmp_str(char*s1,char*s2,intlen,int*left) { inti; *left=len; for(i=0;i<len;i++) {

(*left)--; if(*s1==*s2)continue; if(*s1>*s2)return1;//串1比串2大

if(*s1<*s2)return-1; //串1比串2小

}

return0; //串1與串2相等

} ==:循環(huán)條件、len最大比較個數(shù)

0、-1、1:比較結果標志 *left:未比較的個數(shù)

(2)利用匯編指令進行串比較

s1:源串 ——〉由SI寄存器給出

s2:目標串 ——〉由DI寄存器給出

len:比較長度 ——〉由CX寄存器給出

++:拷貝方向 ——〉由PSW的DF給出(CLD,STD設置) 循環(huán)條件 ——〉由指令REPE/REPZ給出 進一步講,對應單元內(nèi)容相同或為0時則重復。

重復什么?CMPS/CMPSB/CMPSW。 其中CMPS需要指出所比較的兩個串

CMPSSRC,DST

而CMPSB/CMPSW則無需顯式地給出這兩個串。 結合起來:REPECMPSSRC,DST

或 REPECMPSB/REPECMPSW

結果:

(SI)、(DI)不相匹配字符的下一個字符地址;

(CX)剩下未比較的字符個數(shù)。

CMPS/CMPSB/CMPSW會改變PSW,即反映串之間的大小關系。比較“hello!”和“helle.”,下列程序輸出 3.串掃描 (1)利用C語言編寫串掃描函數(shù)

intscan_str(char*s,intlen,charc) { inti; for(i=0;i<len;i++) {

if(*s++!=c) continue; else break; }

returni; //串1與串2相等

}

返回值為c在串中的位置

!=

:循環(huán)條件、len最大比較個數(shù)

(3)利用匯編指令進行串掃描

s:串 ——〉由DI寄存器給出

len:比較長度 ——〉由CX寄存器給出

++:拷貝方向 ——〉由PSW的DF給出(CLD,STD設置) 循環(huán)條件 ——〉由指令REPNE/REPNZ給出 進一步講,對應單元內(nèi)容不相同或不為0時則重復。

重復什么?SCAS/SCASB/SCASW。 其中SCAS需要指出所掃描的串

SCASDST

而SCASB/SCASW則無需顯式地給出這個串。 所比較的內(nèi)容是[DI]與(AL), 或[DI]與(AX) 若不相等則繼續(xù)比較。直到相等(即掃描到指定單元)為止。

結果:

(DI)相匹配字符的下一個地址;

(CX)剩下未比較的字符個數(shù)。在“12345abcde”中掃描“b”,下列程序輸出

(六)轉移指令

1.無條件轉移指令

(1)無條件段內(nèi)直接轉移指令 格式:JMP標號 功能:無條件地轉移到標號地址處。 例如:

NEXT:MOVAX,CX …… JMPNEXT

;轉NEXT處

…… JMPOVER

;轉OVER處

……

OVER:MOVAX,1

編譯器根據(jù)標號與IP的相對位置,將指令翻譯位跳轉一定的位移量,即EBXX或EBXXX。 其中EB表示跳轉,而XX或XXXX則表示要跳轉的位移量。 當翻譯成EBXX時,表示跳轉位移為8位數(shù),此時的跳轉稱為短轉移。 短轉移的書寫格式為:

JMPSHORT

標號 執(zhí)行的操作:(IP)<-(IP)+8位位移量 例如: …… JMPSHORTHELLO …… HELLO: MOVAL,3 ……

按同樣的道理,當翻譯成EBXXXX時,表示跳轉位移為16位數(shù),此時的跳轉為近轉移。 短轉移的書寫格式為:

JMPNEARPTR

標號 執(zhí)行的操作:(IP)<-(IP)+16位位移量

對于JMPSHORTOPR和JMPNEARPTROPR,除翻譯后多一個字節(jié)和少一個字節(jié)外并無多少實質的差別,因此對于段內(nèi)直接轉移,編程時可直接寫為:

JMP標號 (2)無條件段內(nèi)間接轉移 格式: JMPWORDPTROPRD

功能:無條件地轉移到由操作數(shù)OPRD的內(nèi)容指定的去處。

OPRD可以是通用寄存器,也可以是字存儲單元。

例:

JMPWORDPTR[1234H]

偏移地址為1234的內(nèi)容送IP

(3)無條件段間直接(遠)轉移指令 格式:JMPFARPTR

標號 功能:無條件地轉移到標號所對應的地址處。 標號前的符號“FARPTR”向匯編程序說明這是段間轉移。

(CS)=標號所在段的段地址;

(IP)=標號在段中的偏移地址。

FARPTR指名了用標號的段地址和偏移地址去修改CS和IP.

例: C1SEGMENT …… JMPFARPTRNEXT_PROG …… C1ENDS C2SEGMENT …… NEXT_PROG: …… C2ENDS

一般不區(qū)分"JMPSHORTNEXT"與"JMPNEARPTRNEXT",因為把"JMPSHORTNEXT"處理為"JMPNEARPTRNEXT"只是增加了機器指令的長度,不會使執(zhí)行結果出現(xiàn)錯誤。因此,程序中只區(qū)分"段間轉移"和"段內(nèi)轉移"。即,出現(xiàn)段間轉移時,使用"JMPFARPTRNEXT",否則,使用"JMPNEXT"。 (4)無條件段間間接轉移指令 格式:JMPDWORDPTROPRD

功能:無條件地轉移到由操作數(shù)OPRD的內(nèi)容指定的去處。

OPRD必須是雙字存儲單元。 例如:

JMPDWORDPTR[1234H]

;雙字存儲單元的低字內(nèi)容送IP

;雙字存儲單元的高字內(nèi)容送CS

注意段內(nèi)間接轉移和段間間接轉移的區(qū)別:字和雙字。 2.條件轉移指令

8086/8088提供了大量的條件轉移指令,它們根據(jù)某標志位或某些標志位的邏輯運算來判別條件是否成立。如果成立,則轉移。否則繼續(xù)順序執(zhí)行。

所有條件轉移都只是段內(nèi)轉移;條件轉移不影響標志。

通常,在條件轉移指令前,總有用于條件判別的有關指令。 例:下面的程序測試AX的低四位是否全為0,如果是,那么使CX=0,否則使CX=-1。

MOVCX,-1

TESTAX,0FH ;全為0是,ZF=1 JNZNZERO ;ZF=0則轉移

MOVCX,0 NZERO:……

記憶技巧:

1.基于單個標志位跳轉指令可直接根據(jù)標志名稱記憶:JZ,JO 2.有符號數(shù)間的次序關系稱為: 大于(G)、等于(E)、小于(L);

3.無符號數(shù)間的次序關系稱為: 高于(A)、等于(E)、低于(B)。

對于有符號數(shù)和無符號數(shù),使用時請注意區(qū)分。 例:實現(xiàn)兩個無符號數(shù)(設在AX和BX中)的比較,把較大的數(shù)放在AX中,把較小的數(shù)放在BX中。

CMPAX,BX JAEOK ;無符號數(shù)比較大小轉移

XCHGAX,BX OK:

……

如果要比較的兩個數(shù)是有符號數(shù),則可用下面程序片段:

CMPAX,BX JGEOK ;有符號數(shù)之間比較

XCHGAX,BX OK:

……

例如:設X、Y均為存放在X單元和Y單元中的16位操作數(shù),先判斷X>50否,如滿足條件則轉移到TOO-HIGH去執(zhí)行,否則做X–Y,如溢出則轉移到OVER去執(zhí)行,否則計算|X-Y|,并把結果存入RESULT中。

MOVAX,X CMPAX,50

JGTOO-HIGH ;大于則跳轉

SUBAX,Y

JOOVER ;溢出則跳轉

JNSNONEG ;結果為正則跳轉

NEGAX ;以上2條計算|X-Y| NONEG: MOVRESULT,AX …… TOO-HIGH: …… OVER: ……

例:假如有100個16位無符號數(shù)存放在從1234:5678H開始的內(nèi)存中,現(xiàn)需要求它們的和。其結果用32位數(shù)存放,高位放在DX中,低位放在AX中。

MOVAX,1234H MOVDS,AX ;置段寄存器

MOVSI,5678H ;置指針初值

MOVAX,0 MOVDX,AX ;清32位累加器和

MOVCX,100 ;設置個數(shù)計數(shù)器

NEXT: ADDAX,[SI] ADCDX,0 ;32位求和

INCSI INCSI ;調(diào)整2次指針(16位,2字節(jié))

DECCX ;調(diào)整計數(shù)器

JNZNEXT ;如不為0,則繼續(xù)累加

例:在存儲器中有一個首地址為ARRAY的N字數(shù)組,要求測試其中正數(shù)、0及負數(shù)的個數(shù)。正數(shù)的個數(shù)放在DI中,0的個數(shù)放在SI中,并根據(jù)N-(DI)-(SI)求得負數(shù)的個數(shù)并放在AX中,如果有負數(shù)則轉移到VAL中去執(zhí)行。

3.循環(huán)指令 利用條件轉移指令和無條件轉移指令可以實現(xiàn)循環(huán)。 但是,為了讓循環(huán)的實現(xiàn)更加方便,8086/8088提供了4條用于實現(xiàn)循環(huán)的指令。 循環(huán)指令類似于條件轉移指令,而且也采用相對轉移的方式,即通過在IP上加一個地址差的方式來實現(xiàn)轉移。 循環(huán)指令中也只有一個字節(jié)表示地址差, 所以,如果以循環(huán)指令的下一條指令作為基準,移動范圍在-128至+127之間.

(1)計數(shù)循環(huán)指令LOOP

格式:LOOP標號 操作:使寄存器CX的值減1,如果結果不等于0,則轉移到標號,否則順序執(zhí)行。 該指令類似于如下兩條指令:DECCX JNZ標號 因此,通常在利用LOOP指令構成循環(huán)時,先要設置好計數(shù)器CX的初值,即循環(huán)次數(shù)。由于先進行CX減1,再判斷結構是否為0,所以最多可循環(huán)65536次。

例: 如下面程序片段實現(xiàn)把從偏移1000H開始的512個字節(jié)的數(shù)據(jù)復制到從偏移3000H開始的緩沖區(qū)中(假設在當前數(shù)據(jù)段中進行移動)。

MOVSI,1000H;置源指針

MOVDI,3000H;置目標指針

MOVCX,512 ;置計數(shù)初值

NEXT: MOVAL,[SI] MOV[DI],AL INCSI INCDI LOOPNEXT ;控制循環(huán)

……

(2)等于/全零循環(huán)指令LOOPE/LOOPZ

等于/全零循環(huán)指令有2個助記符,格式如下:

LOOPE標號 或 LOOPZ標號 操作:使寄存器CX的值減1,當CX不等于0且ZF為1時(相等),進行循環(huán),否則退出循環(huán)并順序執(zhí)行后續(xù)語句。

ZF標志從哪里來?通過CMP、DEC、TEST、ADD、SUB等運算指令設置。 例:在字符串中查找第一個非‘A’字符。設字符串長已保存在CX中,并且DS:DI指向字符串。如果找到,那么使BX指向該非‘A’字符,如果找補到,那么使BX=-1。

(3)不等于/非全零循環(huán)指令LOOPNE/LOOPNZ

不等于/非全零循環(huán)指令有2個助記符,格式如下:

LOOPNE標號 或 LOOPNZ標號 操作:使寄存器CX的值減1,當CX不等于0且ZF為0時(不相等),進行循環(huán),否則退出循環(huán)并順序執(zhí)行后續(xù)語句。

ZF標志從哪里來?通過CMP、DEC、TEST、ADD、SUB等運算指令設置。 (4)跳轉指令JCXZ JCXZ也可以認為是條件跳轉指令。格式如下:

JCXZ標號 該指令實現(xiàn)當CX的值等于0時轉移到標號,否則順序執(zhí)行。

通常該指令用在循環(huán)開始前,以便根據(jù)需要判斷是否跳過循環(huán)體。

例如:有一長度為L的字符串,存儲于首地址為TABLE的存儲器中。要求在字符串中查找“空格”字符,找到則繼續(xù)執(zhí)行,如未找到則轉到NOT-FOUND去執(zhí)行

MOVCX,L MOVSI,-1 MOVAL,20H;空格字符的ASCII碼

NEXT: INCSI

CMPAL,TABLE[SI];若相等,則ZF=1

LOOPNENEXT ;ZF=0且(CX)不等于0則循環(huán)

JNZNOT-FOUND ;ZF=0則轉移。ZF=0,說明循環(huán)

;體不是因為相等而退出,而是因為(CX)為0了。

…… NOT-FOUND:…….

例如:若自BLOCK開始的內(nèi)存緩沖區(qū)有100個字節(jié)帶符號數(shù),要找出其中最大值,把它存放到MAX單元中。

MOVBX,OFFSETBLOCK MOVAX,[BX] INCBX MOVCX,99

AGAIN:

CMPAX,[BX]

JGNEXT MOVAX,[BX] NEXT: INCBX

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論