80X86指令集

學習彙編語言,最關鍵的就在於彙編指令集的掌握以及計算機工作方式的理解,以下是80X86彙編過程中經常用到的一些彙編指令。

從功能分類上來說,一共可分爲

一、   數據傳送指令:MOVXCHGLEALDSLESPUSHPOPPUSHFPOPFCBWCWDCWDE

二、   算術指令:ADDADCINCSUBSBBDECCMPMULDIVDAADASAAAAAS

三、   邏輯指令:ANDORXORNOTTESTSHLSALSHRSARRCLRCRROLROR

四、   控制轉移指令:JMPJccJCXZLOOPLOOPZLOOPNZLOOPNECALLRETINT

五、   串操作指令:MOVSLODSSTOSCMPSSCAS

六、   標誌處理指令:CLCSTCCLDSTD

七、   32CPU新增指令(後續補充並完善)

除上述的一些指令外,還有許多3280X86CPU新增指令,這些指令有時會簡化程序設計,不過由於我也是剛剛學習彙編,這些都是從書上看到的,所以很多還不是十分了解,我寫這些的目的僅僅是想讓自己能更好的去記住這些指令的作用和用法,同事也希望和我一樣剛入門的朋友能夠多瞭解一些,並沒有其他目的,所有的示例也並沒有經過實際的代碼測試,所以希望各位朋友,不管你喜歡不喜歡,反對不反對,請文明發言,謝謝!

------------------------------------------------數據傳送指令開始-------------------------------------------------------

1、     MOV(傳送)

指令寫法:MOV  targetsource

功能描述:將源操作數source的值複製到target中去,source值不變

注意事項:1target不能是CS(代碼段寄存器),我的理解是代碼段不可寫,只可讀,所以相應這地方也不能對CS執行復制操作。2targetsource不能同時爲內存數、段寄存器(CS\DS\ES\SS\FS\GS3)不能將立即數傳送給段寄存器4targetsource必須類型匹配,比如,要麼都是字節,要麼都是字或者都是雙字等。4)由於立即數沒有明確的類型,所以將立即數傳送到target時,系統會自動將立即數零擴展到與target數的位數相同,再進行傳送。有時,需要用BYTE PTR WORD PTR DWORD PTR明確指出立即數的位數

寫法示例:MOV  dl,01H;MOV  eax,[bp]; eax =ss:[bp] 雙字傳送。

2、     XCHG(交換)

指令寫法:XCHG object1object2

功能描述:交換object1object2的值

注意事項:1)不能直接交換兩個內存數的值 2)類型必須匹配3)兩個操作數任何一個都不能是段寄存器【看來段寄存器的寫入的限制非常的嚴格,MOV指令也不能對段寄存器進行寫入】,4)必須是通用寄存器(axbxcxdxsidi或內存數

寫法示例:XCHG  ax[bx][si]; XCHG ax,bx;

3、     LEA(裝入有效地址)

指令寫法:LEZ reg16mem

功能描述:將有效地址MEM的值裝入到16位的通用寄存器中。

寫法示例:假定bx=5678HEAX=1,EDX=2

                              Lea si,2[bx]                    ;si=567AH

                              Lea di,2[eax][edx]       ;di=5

注意,這裏裝入的是有效地址,並不是實際的內存中的數值,如果要想取內存中該地址對應的數值,還需要加上段地址才行,而段地址有可能保存在DS中,也有可能保存在SS或者CS中哦:>不知道我的理解可正確。。。。

4、     LDS\LES\LGS\LSS注意,與LEA不同的是,這裏是裝入的值,而不是有效地址

這幾個指令,名稱不同,作用差不多。

寫法:LDS reg16mem32  

功能描述:reg16等於mem32的低字,而DS對應於mem32的高字(當爲LES時,這裏就是ES對應於mem32的高字)

用來給一個段寄存器和一個16位通用寄存器同時複製。

注意事項:第一個操作數必須是16位通用寄存器

 

在接着往下說之前,先熟悉下堆棧的概念。堆棧,位於內存的堆棧段中,是內存的一部分,具有“先進後出”的特點,堆棧只有一個入口,即當前棧頂,當堆棧爲空時,棧頂和棧底指向同一內存地址,在WINDOWS中,可以把堆棧理解成一個倒着的啤酒瓶,上面的地址大,下面的地址小,當從瓶口往啤酒瓶塞啤酒時(進棧),棧頂就會往瓶口下移動,也就是往低地址方向移動,同理,出棧時,正好相反,把啤酒給倒出來,棧頂向高地址方向移動。這就是所謂的堆棧 ,哼哼,很Easy吧。

在彙編語言中,堆棧操作的最小單位是字,也就是說,只能以字或雙字爲單位,同時,SSSP指向棧頂(SS爲堆棧段寄存器,SP爲堆棧指針,二者一相加,就構成了堆棧棧頂的內存地址)

5、     PUSH(進棧)

寫法:PUSH reg1632/seg/mem1632/imm

功能描述:將通用寄存器/段寄存器/內存數/立即數的值壓入棧中,即:

SP=SP-2 SS:[SP]=16位數值(當將32位數值壓入棧中時,SP=SP-4SS:[SP]=32爲數值)

6、     POP(出棧)

寫法:POP reg1632/seg/mem1632【不能出棧到CS中】

功能描述:將堆棧口的1632)位數據推出到通用寄存器/段寄存器/內存中,即:

寄存器/段寄存器/內存= SS:[SP]   SP=SP+2(當將32位數值出棧時,SP=SP+4(注意,不能出棧給立即數哦,常量不可變嘛)

7、     PUSHAPUSHADPOPAPOPAD

作用:將所有16/32位通用寄存器進棧/出棧

如:PUSHA ;AXCXDXBX、原SPBPSIDI依次進棧。POPA出棧順序正好相反,但要注意的是,彈出到SP的值被丟棄,SP通過增加16位來恢復(當然嘛,不然棧頂地址就被修改了,就會出息不對齊的情況,就有可能亂套了)

POPAD PUSHAD一樣,只不過是32位的罷了。

8、     PUSHFPUSHFDPOPFPOPFD

功能描述:標誌寄存器FLAGSEFLAGS)進棧或出棧

如:PUSHF FLAGS進棧  POPF 棧頂字出棧到FLAGS

總結下,POP PUSH通常可以用來交換兩個寄存器的值,也可以用來保護寄存器的值,如下:

交換axcx的值:push axpush cxpop ax pop cx

保護寄存器:push axpush cx….中間有很多執行的代碼…pop cx;pop ax;

9、LAHF\SAHF(標誌寄存器傳送指令)

寫法:lahf;

作用:AH=FLAGS的低8位

寫法:sahf;

作用:FLAGS的低8位=AH

10、符號擴展和零擴展指令

CBW;AL符號擴展爲AX

CWD;AX符號擴展爲32位數DX:AX

CWDE;AX符號擴展爲EAX;

CDQ:EAX符號擴展爲64位數EDX:EAX

MOVSX(符號擴展指令的一般形式)

寫法:MOVSX reg16\32,reg8\reg16\mem8\mem16

作用:用來將8位符號擴展到16位,或者16位符號擴展到32位

MOVZX(零擴展指令)

寫法:MOVZX reg16\32,reg8\reg16\mem8\mem16

零擴展,就是高位補0進行擴展。通常用在將數據複製到一個不同的寄存器中,如AL零擴展爲EBX。相同寄存器的零擴展,可以使用MOV 高位, 0來實現。

11、BSWAP(字節交換)

寫法:bswap reg32

作用:將reg32的第0與第3個字節,第1與第2個字節進行交換。

示例:設EAX=12345678h

執行bswap eax;後,eax=78563412H

12、XLAT(換碼)

寫法:XLAT;

作用:AL=DS:[bx+AL]

將DS:BX所指內存中的由AL指定位移處的一個字節賦值給AL。(貌似這是一個方便偷懶的指令哦。。),原來它的主要用途是查表。注意可以給它提供操作數,用來指定使用哪個段地址,如:

XLAT ES:table;使用ES來作爲段地址,table不起作用。

XLAT table ;使用table所在段對應的段寄存器作爲段地址。

------------------------------------------------數據傳送指令結束-------------------------------------------------------

 

----------------------------------算術指令開始-----------------------------------------------

13、ADD(加法)

寫法:ADD reg/mem reg/mem/imm

作用:將後面的操作數加到前面的操作數中

注意:兩個操作數必須類型匹配,並且不能同時是內存操作數

ADC (帶進位加法)

寫法:ADC reg/mem, reg/mem/imm ;

作用:dest=dest+src+cf

當CF=0時 ADD與ADC的作用是相同的。

示例:實現64位數EDX:EAX與ECX:EBX的加法:

Add EAX,EBX;

ADC EDX,ECX;

14、INC(自加一)

寫法:INC reg/mem;

作用:dest=dest+1;

15、XADD(交換加)

寫法:XADD reg/mem, reg

作用:先將兩個數交換,然將二者之和送給第一個數

16、SUB(減法)

寫法:SUB reg/mem, reg/mem/imm;

作用:dest=dest-src;

SBB(帶借位減法)

寫法:SBB reg/mem, reg/mem/imm

作用:dest=dest-src-cf;

注意:兩個操作數必須類型匹配,且不能同時是內存數

17、DEC(自減1)

寫法:DEC reg/mem;

作用:dest=dest-1;

18、CMP(比較)

寫法:CMP reg/mem, reg/mem/imm

作用:dest-src

注意:這裏並不將結果存入dest中,而僅僅是執行相減的運算,達到依據運算結果去影響EFLAG標誌位的效果

19、NEG(求補)

寫法:NEG reg/mem

作用:求補就是求相反數,即:dest=0-dest;

20、CMPXCHG(比較交換)

寫法:CMPXCHG reg/mem, reg;

作用:AL/AX/EAX-oprd1,如果等於0,則oprd1=oprd2,否則,AL/AX/EAX=oprd1;

即:比較AL/AX/EAX與第一個操作數,如果相等,則置ZF=1,並複製第二個操作數給第一個操作數;否則,置ZF=0,並複製第一個操作數給AL/AX/EAX。

說明:CMPXCHG主要爲實現原子操作提供支持

CMPXCHG8B(8字節比較交換指令)

寫法:CMPXCHG8B MEM64;

功能:將EDX:EAX中的64位數與內存的64位數進行比較,如果相等,則置ZF=1,並存儲ECX:EBX到mem64指定的內存地址;否則,置ZF=0,並設置EDX:EAX爲mem64的8字節內容

21、MUL(無符號乘法)

寫法:MUL reg/mem;

作用:當操作數爲8位時,AX=AL*src;

當操作數爲16位時,DX:AX=AX*src;

當操作數爲32位時,EDX:EAX=EAX*src;

22、IMUL(帶符號位乘法)

寫法:IMUL reg/mem;(作用同上)

IMUL reg16,reg16/mem16,imm16;

IMUL reg32,reg32/mem32,imm32;

IMUL reg16,imm16/reg16/imm16;

IMUL reg32,reg32/mem32/imm32;

注意:沒有兩個操作數均爲8位的多操作數乘法。

對於同一個二進制數,採用MUL和IMUL執行的結果可能不同,設AL=0FF,BL=1,分別執行下面的指令,會得到不同的結果:

Mul bl; AX=0FFH(255);

Imul bl; AX=0FFFFH(-1)(高一半爲低一半的擴展)

23、DIV(無符號除法 )/IDIV(帶符號數除法)

寫法:DIV reg/mem;/IDIC reg/mem

作用:如果操作數是8位,AX%SRC,結果商在AL、餘數在AH中;

如果操作數是16位,DX:AX%SRC,結果商在AX,餘數在DX中;

如果操作數是32位,EDX:EAX%SRC,結果商在EAX,餘數在EDX中;

注意:不能直接實現8位數除8位數、16位數除16位數、32除32,若需要這樣,則必須先把除數符號擴展或零擴展到16、32、64位,然後用除法指令。

對於IDIV,餘數和被除數符號相同,如:-5 IDIV 2 = 商 -2,餘數:-1;

在下列情況下,會使CPU產生中斷:一:除數爲0 ;二:由於商太大,導致EAX\AX或AL不能容納,從而產生了溢出。

-----------------BCD碼調整指令(十進制調整指令)待補充------------------------------------------------

24、關於BCD碼:BCD碼就是一種十進制數的二進制編碼表示,分爲壓縮BCD碼和非壓縮BCD碼,壓縮BCD碼用4個二進制位表示一個十進制位,即用0000B~1001B表示十進制0~9,如0110 0100 0010 1001B表示6429

用8位二進制來表示一個十進制叫非壓縮BCD碼,其中,低四位與壓縮BCD碼相同,高四位無意義。

壓縮BCD碼調整指令包括DAA(加法的壓縮BCD碼調整)和DAS(減法的壓縮BCD碼調整)

寫法:

DAA;

作用:調整AL中的和爲壓縮BCD碼。

功能:使用DAA指令時,通常先執行ADD/ADC指令,將兩個壓縮BCD碼相加,結果存放在AL中,然後使用該指令將AL調整爲壓縮BCD碼格式。

DAA的調整算法:

IF(AL低4位>9 或 AF=1)

THEN

AL=AL+6;

AF=1;

ENDIF

IF( AL高4位>9或CF=1)

THEN

AL=AL+60H;

CF=1;

ENDIF

說明:CF反映壓縮BCD碼相加的進位。

DAS;

作用:調整AL中的差爲壓縮BCD碼。

功能:使用DAS指令時,通常先執行SUB/SBB指令,將兩個壓縮BCD碼相減,結果存放在AL中,然後使用該指令將AL調整爲壓縮BCD碼格式。

DAS的調整算法:

IF(AL低4位>9 或 AF=1)

THEN

AL=AL-6;

AF=1;

ENDIF

IF( AL高4位>9或CF=1)

THEN

AL=AL-60H;

CF=1;

ENDIF

說明:CF反映壓縮BCD碼相減的借位。

特別注意,如果使用DAA或DAS指令,則參加加法或減法運算的操作數應該是壓縮BCD碼,如果將任意兩個二進制數相加或相減,然後調整,則得不到正確的結果。

關鍵是調整的規則,其中AF標誌位就是專門爲BCD碼調整設計的,當低四位有向高四位進位或借位時,值爲1。而CF就是最高位有進位或者借位時,爲1.

非壓縮BCD碼調整指令,包括AAA,AAS,AAM,AAD。

寫法:AAA ;

作用:調整AL中的和爲非壓縮BCD碼;調整後,AL高4位等於0,AH=AH+產生的CF

功能:使用AAA指令時,通常先執行ADD/ADC指令,以AL爲目的操作數,將兩個非壓縮BCD碼(與高位無關)相加,然後使用AAA將AL調整爲非壓縮BCD碼格式,且高4位等於0,同時,將調整產生的進位加到AH中。

AAA調整算法:

IF(AL低4位>9 或者 AF=1)

THEN

AL=AL+6;

AH=AH+1;

AF=1;

CF=1;

ELSE

AF=0;CF=0;

ENDIF

AL=AL AND OFH;;AL高4位清0

寫法:AAS ;

作用:調整AL中的差爲非壓縮BCD碼;調整後,AL高4位等於0,AH=AH-產生的CF

功能:使用AAS指令時,通常先執行SUB/SBB指令,以AL爲目的操作數,將兩個非壓縮BCD碼(與高位無關)相減,然後使用AAS將AL調整爲非壓縮BCD碼格式,且高4位等於0,同時,將調整產生的借位從AH中減去。

AAA調整算法:

IF(AL低4位>9 或者 AF=1)

THEN

AL=AL-6;

AH=AH-1;

AF=1;

CF=1;

ELSE

AF=0;CF=0;

ENDIF

AL=AL AND OFH;;AL高4位清0

寫法:AAM;

作用:AH=AX DIV 10, AL=AX MOD 10;

功能:使用AAM時,通常先執行MUL/IMUL指令,將兩個一字節非壓縮BCD碼(高四位必須爲0)相乘,結果存入AX.然後使用AAM指令將AX(AH=0)調整爲兩字節壓縮BUC碼格式。

寫法:AAD;

作用:AL=AH*10+AL,AH=0;

功能:使用AAD時,通常先執行該指令,將AX中的兩字節非壓縮BCD碼(AH與AL的高4位必須爲0)調整爲相應的二進制表示,然後使用DIV/IDIV指令,除以一個一字節的非壓縮BCD碼(高四位必須爲0),可得到非壓縮BCD碼的除法結果。

特別注意,參加非壓縮BCD碼乘法或除法的操作數高4位必須爲0。

-----------------------------算術指令結束-----------------------------------------------------------------------------

-----------------------------------------位操作指令開始-----------------------------------------------------

25、AND\OR\XOR\NOT\TEST

寫法:

AND reg/mem,reg/mem/imm;

OR reg/mem,reg/mem/imm;

XOR reg/mem,reg/mem/imm;

NOT reg/mem;

TEST reg/mem,reg/mem/imm;

作用:AND\TEST\OR\XOR,兩個操作數必須類型匹配,而且不能同時是內存操作數

XOR通常用來將寄存器清0,如 XOR AX,AX;

TEST與AND的關係類似於CMP與SUB。TEST的典型用法是檢查某位是否爲1,如:

TEST DX,109H;

若 DX的第0,3,8位至少有一位爲1,則 ZF=0,否則ZF=1;

26、移位指令

SHL(邏輯左移)

寫法:SHL REG\mem,1\CL ;

作用:將dest的各個二進制位向左移動1(CL)位,並將DEST的最高位移出到CF,最低位移入0

SAL(算術左移)

寫法:SAL REG\mem,1\CL ;

作用:將dest的各個二進制位向左移動1(CL)位,並將DEST的最高位移出到CF,最低位移入0(同SHL)。

SHR(邏輯右移)

寫法:SHR REG\mem,1\CL ;

作用:將dest的各個二進制位向左移動1(CL)位,並將DEST的最低位移出到CF,最高位移入0

SAR(算術右移)

寫法:SAR REG\mem,1\CL ;

作用:將dest的各個二進制位向左移動1(CL)位,並將DEST的最低位移出到CF,最高位不變

SHLD(雙精度左移)

寫法:SHLD REG16/REG32/MEM16/MEM32, REG16/REG32, IMM8/CL;(類型須匹配)

作用:將OPRD1的各二進制左移,並將oprd1的最高位移到CF,oprd2的最高位移到oprd1的最低位,但是,oprd2的值不變

SHRD(雙精度右移)

寫法與作用與雙精度左移類似。注意移動方向爲右移。

以上位移指令對標誌位的影響:

若移位後符號位發生了變化,則OF=1,否則OF=0;CF爲最後移入位;按一般規則影響ZF與SF。然而,若移位次數爲0,則不影響標誌位;若移位次數大於1,則OF無定義

27、循環移位指令

ROL(循環左移)

寫法:ROL REG\MEM, 1\CL;或 ROL REG/MEM,IMM8;(類型可不匹配)

作用:將DEST的各二進制位向左移動,並將最高位移出到CF,並同時移入最低位

ROR(循環右移)

寫法:ROR REG\MEM, 1\CL;或 ROR REG/MEM,IMM8;(類型可不匹配)

作用:將DEST的各二進制位向右移動,並將最低位移出到CF,並同時移入最高位

RCL(帶進位循環左移)

寫法:RCL REG\MEM, 1\CL;或 RCL REG/MEM,IMM8;(類型可不匹配)

作用:將DEST的各二進制位向左移動,並將最高位移出到CF,原CF移入最低位

RCR(帶進位循環右移)

寫法:RCR REG\MEM, 1\CL;或 RCR REG/MEM,IMM8;(類型可不匹配)

作用:將DEST的各二進制位向右移動,並將最低位移出到CF,原CF移入最高位

28、位測試指令

BT(位測試)

寫法:BT REG16/MEM16,REG16/IMM8;或BT REG32/MEM32,REG32/IMM8;

作用:CF=DEST的第index位,dest不變。

BTS(位測試並置位)

寫法:BTS REG16/MEM16,REG16/IMM8;或BTS REG32/MEM32,REG32/IMM8;

作用:CF=DEST的第index位,dest的第index位=1;

BTR(位測試並復位)

寫法:BTR REG16/MEM16,REG16/IMM8;或BTR REG32/MEM32,REG32/IMM8;

作用:CF=DEST的第index位,dest的第index位=0;

BTC(位測試並復位)

寫法:BTC REG16/MEM16,REG16/IMM8;或BTC REG32/MEM32,REG32/IMM8;

作用:CF=DEST的第index位,dest的第index位取反;

說明:若dest爲寄存器,則以index除以16(dest爲reg16)或32(dest爲reg32)的餘數作爲測試位。當然,index最好不要超出操作數的位數。

若dest爲內存操作數,則無論其類型爲字或雙字,測試位爲相對於起始地址的位移,例如,設BX=50,X爲字類型的變量,則執行指令BT X,BX;後,CF=X+6單元的第2位,因爲50%8=6餘2.

BTS、BTC、BTR指令可用於併發程序設計。

29、位掃描指令

BSF(前向位掃描)

寫法:BSF reg16/reg32, reg16/reg32/mem16/mem32;(類型須匹配)

作用:dest=src中值爲1的最低位編號(從低位向高位搜索)

BSR(後向位掃描)

寫法:BSR reg16/reg32, reg16/reg32/mem16/mem32;(類型須匹配)

作用:dest=src中值爲1的最高位編號(從高位向低位搜索)

說明:BSF和BSR搜索SRC操作數中首次出現1的位置,BSF從低位向高位搜索,BSR反之。若找到一個1,則置ZF=0,並存儲位編號到DEST操作數中。若SRC=0,即沒有1出現,則置ZF=1,且dest的值不確定。

比如,有如下二進制數0111 1111 1010 0100

執行bsf後,位編號爲2,執行bsr後,位編號爲14.

30、條件置位指令

通用寫法:SETcc reg8/mem8

作用:若條件cc成立,則dest=1,否則,dest=0;

SETcc有很多種命令形式,這裏的cc只是一個描述符,具體的參見下面的三個表,其中,E(Equal)表示相等,G(Greatet)表示帶符號大於,L(Less)表示帶符號小於,A(Above)表示無符號大於,B(Below)表示無符號小於。

表一:測試單個標誌位的SETcc指令

SETcc指令

描述

置1條件

SETC,SETB,SETNAE

有進位時置1

CF=1

SETNC,SETNB,SETAE

無進位時置1

CF=0

SETZ,SETE

爲0(相等)時置1

ZF=1

SETNA,SETNE

非0(不等)時置1

ZF=0

SETS

爲負時置1

SF=1

SETNS

爲正時置1

SF=0

SET0

溢出時置1

OF=1

SETNO

不溢出時置1

OF=0

SETP,SETPE

‘1’的個數爲偶數時置1

PF=1

SETNP,SETPO

‘1’的個數爲奇數時置1

PF=0

表二:用於帶符號數比較的SETcc指令,這些指令常用在CMP指令之後,以判斷帶符號數的大小

SETcc指令

描述

置1條件

SETG,SETNLE

大於(不小於等於)時置1

SF=OF且ZF=0

SETGE,SETNL

大於等於(不小於)時置1

SF=OF

SETL,SETNGE

小於(不大於等於)時置1

SF≠OF

SETLE,SETNG

小於等於(不大於)時置1

SF≠OF或ZF=1

表三:用於無符號數比較的SETcc指令,常用在CMP指令之後,用來判斷無符號數的大小

SETcc指令

描述

置1條件

SETA,SETNBE

大於(不小於等於)時置1

CF=0且ZF=0

SETAE,SETNB,SETNC

大於等於(不小於)時置1

CF=0

SETB,SETNAE,SETC

小於(不大於等於)時置1

CF=1

SETBE,SETNA

小於等於(不大於)時置1

CF=1或ZF=1

-----------------------------------------位操作指令結束----------------------------------------------------

----------------------------------------------------

---------------------------控制轉移指令開始--------------------------------------------------

31、JMP(無條件轉移指令)

執行代碼的跳轉,分爲兩種,一:段內轉移,即要跳過去的代碼地址和當前地址在同一段,這時只要修改IP(專用寄存器--指令指針)即可;二:段間轉移:即要跳過去的代碼地址和當前代碼地址不在同一段內,需要同時修改CS和IP的值。

寫法:

1、JMP label;若label與該指令位於同一代碼段內,IP=label的偏移地址,否則CS:IP=label的分段地址,簡單的說,就是跳到label的地址去。

2、JMP reg16/mem16;段內轉移,偏移地址=reg16/[mem16]

3、JMP mem32;段間間接轉移,段地址CS=mem32高字,偏移地址IP=mem32低字。

說明:當操作數是內存操作數時,若內存操作數是雙字類型,則產生段間轉移,若內存操作數是字類型,則產生段內間接轉移。當不能確定類型時,編譯器將報錯

32、Jcc(條件轉移指令)

寫法:Jcc label;

作用:若條件成立,則IP=label的偏移地址,否則,CPU將忽略該條件轉移,繼續執行下一條指令

條件轉移有以下幾種形式:

表一:測試單個標誌位的Jcc指令:

Jcc指令

描述

轉移條件

JC,JB,JNAE

有進位時轉移

CF=1

JNC,JNB,JAE

無進位時轉移

CF=0

JZ,JE

爲零(相等)時轉移

ZF=1

JNZ,JNE

非零(不等)時轉移

ZF=0

JS

爲負時轉移

SF=1

JNS

爲正時轉移

SF=0

JO

溢出時轉移

OF=1

JON

不溢出時轉移

OF=0

JP,JPE

‘1’的個數爲偶數時轉移

PF=1

JNP,JPO

‘1’的個數爲奇數時轉移

PF=0

表二:用於帶符號數比較的Jcc指令(常用在CMP指令之後,以判斷帶符號數的大小)

Jcc指令

描述

轉移條件

JG,JNLE

大於(不小於等於)時轉移

SF=OF且ZF=0

JGE,JNL

大於等於(不小於)時轉移

SF=OF

JL,LNGE

小於(不大於等於)時轉移

SF<>OF

JLE,LNG

小於等於(不大於)時轉移

SF<>OF或ZF=1

表三:用於無符號數比較的Jcc指令(常用在CNO指令之後,以判斷無符號數的大小)

Jcc指令

描述

轉移條件

JA,JNBE

大於(不小於等於)時轉移

CF=0且ZF=0

JAE,JNB,JNC

大於等於(不小於)時轉移

CF=0

JB,LNAE,JC

小於(不大於等於)時轉移

CF=1

JBE,LNA

小於等於(不大於)時轉移

ZF=1或CF=1

33、JCXZ/JECXZ(Jump if CX/ECX is zero)

寫法:JCXZ label;(若CX=0,則轉移到label)

JECXZ label;(若ECX=0,則轉移到label)

說明:label相對位移量必須在-126~127之間

 

34、循環指令

LOOP label;

作用:CX=CX-1;若CX<>0,則轉移到label;

LOOPZ/LOOPE label;

作用:CX=CX-1;若CX<>0且 ZF=1,則轉移到label;

LOOPNZ/LOOPNE label;

作用:CX=CX-1;若CX<>0且ZF=0,則轉移到label;

說明:label相對位移量必須在-128~127之間

35、過程調用和返回指令

CALL(過程調用)

寫法:CALL label;

作用:若label與該指令在同一代碼段,則爲段內直接調用,IP進棧,IP=label的偏移地址,如果是不在同一代碼段,則爲段間間接調用,CS:IP進棧,CS:IP=label的分段地址

寫法:CALL reg16/mem16;

作用:段內間接調用,IP進棧,IP=reg16/【mem16】

寫法:CALL mem32;

作用:段間間接調用,CS:IP進棧,CS等於mem32高字,ip等於mem32低字。

該指令與JMP指令的區別就是保存了CS:IP的值,這樣在調用指令結束後,可以返回回來而已。

RET(過程返回)

寫法:RET; 近返回或遠返回

RETN; 近返回;

RETF; 遠返回

RET imm16; 近返回或遠返回,並調整堆棧,SP=SP+imm16;

RETN imm16;近返回,並調整堆棧,SP=SP+imm16;

RETF imm16;遠返回,並調整堆棧,SP=SP+imm16;

作用:RET/RETN/RETF:返回地址出棧,從而使調用返回,其中,遠返回是POP一個雙字到CS:IP,而近返回是POP一個字到IP

RET/RETN/RETF imm16:在返回後,CPU立即將imm16加到堆棧指針SP。這種機制用來在返回前將參數從棧中移除。

說明:CALL 與 RET必須配合使用,並且確保返回時棧頂正好是返回地址,不然就會出錯。

36、IN T(中斷指令)

寫法:INT n;(n爲中斷號,取值爲0~255)

通常,程序內部的跳轉,用JMP或CALL,並且JMP和CALL得參數是要跳轉的過程的入口指令地址,而INT則是調用系統提供的中斷服務程序,並且參數是中斷號,然後由CPU根據中斷號去計算中斷服務程序的入口地址,MS DOS使用中斷號21H作爲系統調用,一般INT中斷的步驟如下:

(1)由AH給出中斷號

(2)根據相應功能的要求,設置入口參數

(3)INT 21H

(4)分析和使用出口參數

比如如下代碼實現程序的退出並返回DOS:

Mov ah,4ch;-----給出中斷號

Int 21h; -----開始中斷

說明:除了直接以AL或AX返回出口參數外,INT 21H還是用AL或AX作爲返回碼,對於功能號0~2eh,由AL返回0(表示成功)或1(表示失敗);其餘功能號則由CF返回0或者1,並由AX返回錯誤碼。

---------------------------控制轉移指令結束--------------------------------------------------

-----------------------------標誌處理指令開始-----------------------------------------------------------

37、標誌處理指令

CLC ; CF=0

STC ; CF=1

CMC ; CF=NOT CF

CLD ; DF=0

STD ; DF=1

CLI ; IF=0(應慎用)

STI ; IF=1

-----------------------------標誌處理指令結束-----------------------------------------------------------

---------------------------串操作指令開始--------------------------------------------------

到這爲止,所涉及的指令都是處理一個操作數,如果要處理連續內存單元的一批數據,通常需藉助於循環。而串操作指令就可以用來處理內存中的數據串,並在助記符後面加上B、W、D分別表示操作類型爲字節、字或雙字

38、MOVS(串傳送)

寫法:

MOVSB/MOVSW/MOVSD

功能:

ES:[DI]=DS:[SI]

If(DF=0)

Then

SI=SI+size;

DI=DI+size;

Else

SI=SI-size;

DI=DI-size;

Endif

其中,size等於1(B)、2(W)、4(D).

作用:將DS:SI所指源串的一個字節/字/雙字複製到ES:DI所指的內存單元,然後,若DF=0,則SI和DI增加1、2、4,否則減少1、2、4.

現在有點明白爲什麼SI爲源變址寄存器,而DI爲目標變址寄存器了,而DS爲數據段寄存器,ES爲附加段寄存器了

 

39、LODS(串載入)

寫法:LODSB\LODSW\LODSD

功能:

AL/AX/EAX=DS:[SI];

IF (DF=0) THEN

SI=SI+size;

ELSE

SI=SI-size;

Endif

作用:將DS:SI所指源串的值複製到AL/AX/EAX中,然後,根據DF使SI增加或減小1、2、4

40、STOS(串存儲)

寫法:

STOSB\STOSW\STOSD

功能:

ES:[DI]=AL/AX/EAX;

IF (DF=0) THEN

DI=DI+size;

ELSE

DI=DI-size;

ENDIF

作用:將AL/AX/EAX中的值複製到ES:[DI]所指的內存單元中去,並根據DF標誌位的值調整DI

41、CMPS(串比較)

寫法:CMPSB/CMPSW/CMPSD

功能:

DS:[SI]-ES:[DI];

IF (DF=0) THEN

SI=SI+size;DI=DI+size;

ELSE

SI=SI-size;DI=DI-size;

ENDIF

作用:將DS:SI所指內存值與ES:DI所指內存值進行比較,並根據比較結果設置標誌位,然後,對SI和DI做相應的調整。

42、SCAS(串掃描)

寫法:SCASB/SCASW/SCASD

功能:

AL/AX/EAX-ES:[DI];

IF (CF=0) THEN

DI=DI+size;

ELSE

DI=DI-size;

ENDIF

作用:將AL/AX/EAX與ES:DI所指內存值進行比較,根據比較結果設置標誌位,然後根據DF調整相應的DI的值。

說明:以上串操作的共性:

DS:SI指向源串,ES:DI指向目的串

SI和DI自動增加或減少1、2、4,關鍵看DF及操作類型是B\W\D

43、重複前綴

重複前綴用來和以上幾個串操作指令混合使用

REP(重複)

功能:當CX<>0時,重複執行後面的串指令,每執行一次,CX自動-1,該指令只能用在MOVS\LODS\STOS之前

REPZ/REPE(爲零/等於時重複)

功能:當CX<>0且ZF=1時,重複執行後面的指令,每執行一次,CX自動-1,該指令只能用在CMPS\ACAS之前。

REPNZ/REPNE(非零/不等於時重複)

功能:CX<>0且ZF=0時,重複執行後面的指令,每執行一次,CX自動-1,該指令只能用在CMPS\ACAS之前。

說明:REPNE SCAS(B/W/D)適用於在多字節、字、雙字數據結構中搜索特定值。

---------------------------串操作指令結束--------------------------------------------------

---------------------------CPU控制指令開始--------------------------------------------------

44、NOP(無操作)

寫法:NOP;

作用:該指令不做任何事情,只佔用1個字節,耗費一個指令執行週期。

45、HIT(暫停)

寫法:HIT;

作用:HIT使CPU進入暫停狀態,這時CPU不執行任何操作,直到系統復位或發生外部中斷爲止,中斷使CPU繼續執行後面的指令(貌似和屏保或待機的功能類似)

46、LOCK(封鎖前綴)

功能:LOCK指令用於多處理器系統,作爲某些指令的前綴,可以使CPU通過鎖住總線等方式,抱着指令作爲原子性操作,即:指令執行過程不會被打斷操作。

該指令用於以下指令的前綴時,以保證原子性的對內存的“讀-修改-寫”操作:

1) 加法:ADD\ADC\INC\XADD

2) 減法:SUB\SBB\DEC\NEG

3) 交換:XCHG\CMPXCHG\CMPXCHG8B

4) 邏輯:AND\NOT\OR\XOR

5) 位測試:BTS\BTC\BTR

說明:其他類型指令不能加LOCK前綴,另外,XCHG總是原子性操作,無論前面有沒有加LOCK前綴。LOCK前綴典型用於BTS指令,以實現多處理器環境中程序的併發執行,如:

LOCK BTS [EBX],AX

LOCK ADD [SI],AL

---------------------------CPU控制指令結束--------------------------------------------------

到這裏爲止,一些基本的彙編指令都已經學習完了,但是還得好好的去應用,不然還真的記不住這些指令的功能。

總結一下,一般情況下,通用寄存器可以較隨便使用,段寄存器和指針寄存器用來指示位置,一般不能隨便更改,另外一個就是標誌寄存器的各個標誌位的意義也非常的重要,很多指令都是根據標誌位來執行操作的。

接下來準備學習彙編的編程格式,然後就可以寫一些簡單的程序並自己進行調試了 ,哈哈哈哈哈。偶非常的期待。

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