8086彙編指令全集
學習組合語言,最關鍵的就在於彙編指令集的掌握以及計算機工作方式的理解,以下是80X86彙編過程中經常用到的一些彙編指令。
從功能分類上來說,一共可分為
一、 資料傳送指令:MOV、XCHG、LEA、LDS、LES、PUSH、POP、PUSHF、POPF、CBW、CWD、CWDE。
二、 算術指令:ADD、ADC、INC、SUB、SBB、DEC、CMP、MUL、DIV、DAA、DAS、AAA、AAS。
三、 邏輯指令:AND、OR、XOR、NOT、TEST、SHL、SAL、SHR、SAR、RCL、RCR、ROL、ROR。
四、 控制轉移指令:JMP、Jcc、JCXZ、LOOP、LOOPZ、LOOPNZ
五、 串操作指令:MOVS、LODS、STOS、CMPS、SCAS。
六、 標誌處理指令:CLC、STC、CLD、STD。
七、 32位CPU新增指令(後續補充並完善)
除上述的一些指令外,還有許多32位80X86CPU新增指令,這些指令有時會簡化程式設計,不過由於我也是剛剛學習彙編,這些都是從書上看到的,所以很多還不是十分了解,我寫這些的目的僅僅是想讓自己能更好的去記住這些指令的作用和用法,同事也希望和我一樣剛入門的朋友能夠多瞭解一些,並沒有其他目的,所有的示例也並沒有經過實際的程式碼測試,所以希望各位朋友,不管你喜歡不喜歡,反對不反對,請文明發言,謝謝!
------------------------------------------------資料傳送指令開始-------------------------------------------------------
1、 MOV(傳送)
指令寫法:MOV target,source
功能描述:將源運算元source的值複製到target中去,source值不變
注意事項:1)target不能是CS(程式碼段暫存器),我的理解是程式碼段不可寫,只可讀,所以相應這地方也不能對CS執行復制操作。2)target和source不能同時為記憶體數、段暫存器(CS\DS\ES\SS\FS\GS
寫法示例:MOV dl,01H;MOV eax,[bp]; eax=ss:[bp] 雙字傳送。
2、 XCHG(交換)
指令寫法:XCHGobject1,object2
功能描述:交換object1與object2的值
注意事項:1)不能直接交換兩個記憶體數的值2)型別必須匹配3)兩個運算元任何一個都不能是段暫存器【看來段暫存器的寫入的限制非常的嚴格,MOV指令也不能對段暫存器進行寫入】,4)必須是通用暫存器(ax、bx、cx、dx、si、di)或記憶體數
寫法示例:XCHG ax,[bx][si]; XCHGax,bx;
3、 LEA(裝入有效地址)
指令寫法:LEZreg16,mem
功能描述:將有效地址MEM的值裝入到16位的通用暫存器中。
寫法示例:假定bx=5678H,EAX=1,EDX=2
Leasi,2[bx] ;si=567AH
Leadi,2[eax][edx] ;di=5
注意,這裡裝入的是有效地址,並不是實際的記憶體中的數值,如果要想取記憶體中該地址對應的數值,還需要加上段地址才行,而段地址有可能儲存在DS中,也有可能儲存在SS或者CS中哦:>不知道我的理解可正確。。。。
4、 LDS\LES\LGS\LSS(注意,與LEA不同的是,這裡是裝入的值,而不是有效地址)
這幾個指令,名稱不同,作用差不多。
寫法:LDSreg16,mem32
功能描述:reg16等於mem32的低字,而DS對應於mem32的高字(當為LES時,這裡就是ES對應於mem32的高字)
用來給一個段暫存器和一個16位通用暫存器同時複製。
注意事項:第一個運算元必須是16位通用暫存器
在接著往下說之前,先熟悉下堆疊的概念。堆疊,位於記憶體的堆疊段中,是記憶體的一部分,具有“先進後出”的特點,堆疊只有一個入口,即當前棧頂,當堆疊為空時,棧頂和棧底指向同一記憶體地址,在WINDOWS中,可以把堆疊理解成一個倒著的啤酒瓶,上面的地址大,下面的地址小,當從瓶口往啤酒瓶塞啤酒時(進棧),棧頂就會往瓶口下移動,也就是往低地址方向移動,同理,出棧時,正好相反,把啤酒給倒出來,棧頂向高地址方向移動。這就是所謂的堆疊,哼哼,很Easy吧。
在組合語言中,堆疊操作的最小單位是字,也就是說,只能以字或雙字為單位,同時,SS:SP指向棧頂(SS為堆疊段暫存器,SP為堆疊指標,二者一相加,就構成了堆疊棧頂的記憶體地址)。
5、 PUSH(進棧)
寫法:PUSH reg16(32)/seg/mem16(32)/imm
功能描述:將通用暫存器/段暫存器/記憶體數/立即數的值壓入棧中,即:
SP=SP-2SS:[SP]=16位數值(當將32位數值壓入棧中時,SP=SP-4,SS:[SP]=32為數值)
6、 POP(出棧)
寫法:POP reg16(32)/seg/mem16(32)【不能出棧到CS中】
功能描述:將堆疊口的16(32)位資料推出到通用暫存器/段暫存器/記憶體中,即:
暫存器/段暫存器/記憶體= SS:[SP] SP=SP+2(當將32位數值出棧時,SP=SP+4)(注意,不能出棧給立即數哦,常量不可變嘛)
7、 PUSHA、PUSHAD、POPA、POPAD
作用:將所有16/32位通用暫存器進棧/出棧
如:PUSHA ;將AX、CX、DX、BX、原SP、BP、SI、DI依次進棧。POPA出棧順序正好相反,但要注意的是,彈出到SP的值被丟棄,SP通過增加16位來恢復(當然嘛,不然棧頂地址就被修改了,就會出息不對齊的情況,就有可能亂套了)
POPAD PUSHAD一樣,只不過是32位的罷了。
8、 PUSHF、PUSHFD、POPF、POPFD
功能描述:標誌暫存器FLAGS(EFLAGS)進棧或出棧
如:PUSHF ;FLAGS進棧 POPF;棧頂字出棧到FLAGS
總結下,POP 和PUSH通常可以用來交換兩個暫存器的值,也可以用來保護暫存器的值,如下:
交換ax與cx的值:push ax;push cx;pop ax;popcx;
保護暫存器:push ax;push 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(符號擴充套件指令的一般形式)
寫法:MOVSXreg16\32,reg8\reg16\mem8\mem16
作用:用來將8位符號擴充套件到16位,或者16位符號擴充套件到32位
MOVZX(零擴充套件指令)
寫法:MOVZXreg16\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,如01100100 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;或 ROLREG/MEM,IMM8;(型別可不匹配)
作用:將DEST的各二進位制位向左移動,並將最高位移出到CF,並同時移入最低位。
ROR(迴圈右移)
寫法:ROR REG\MEM, 1\CL;或 RORREG/MEM,IMM8;(型別可不匹配)
作用:將DEST的各二進位制位向右移動,並將最低位移出到CF,並同時移入最高位。
RCL(帶進位迴圈左移)
寫法:RCL REG\MEM, 1\CL;或 RCLREG/MEM,IMM8;(型別可不匹配)
作用:將DEST的各二進位制位向左移動,並將最高位移出到CF,原CF移入最低位。
RCR(帶進位迴圈右移)
寫法:RCR REG\MEM, 1\CL;或 RCRREG/MEM,IMM8;(型別可不匹配)
作用:將DEST的各二進位制位向右移動,並將最低位移出到CF,原CF移入最高位。
28、位測試指令
BT(位測試)
寫法:BT REG16/MEM16,REG16/IMM8;或BTREG32/MEM32,REG32/IMM8;
作用:CF=DEST的第index位,dest不變。
BTS(位測試並置位)
寫法:BTS REG16/MEM16,REG16/IMM8;或BTSREG32/MEM32,REG32/IMM8;
作用:CF=DEST的第index位,dest的第index位=1;
BTR(位測試並復位)
寫法:BTR REG16/MEM16,REG16/IMM8;或BTRREG32/MEM32,REG32/IMM8;
作用:CF=DEST的第index位,dest的第index位=0;
BTC(位測試並復位)
寫法:BTC REG16/MEM16,REG16/IMM8;或BTCREG32/MEM32,REG32/IMM8;
作用:CF=DEST的第index位,dest的第index位取反;
說明:若dest為暫存器,則以index除以16(dest為reg16)或32(dest為reg32)的餘數作為測試位。當然,index最好不要超出運算元的位數。
若dest為記憶體運算元,則無論其型別為字或雙字,測試位為相對於起始地址的位移,例如,設BX=50,X為字型別的變數,則執行指令BTX,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、JMPlabel;若label與該指令位於同一程式碼段內,IP=label的偏移地址,否則CS:IP=label的分段地址,簡單的說,就是跳到label的地址去。
2、JMPreg16/mem16;段內轉移,偏移地址=reg16/[mem16]
3、JMPmem32;段間間接轉移,段地址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/RETFimm16:在返回後,CPU立即將imm16加到堆疊指標SP。這種機制用來在返回前將引數從棧中移除。
說明:CALL 與 RET必須配合使用,並且確保返回時棧頂正好是返回地址,不然就會出錯。
36、IN T(中斷指令)
寫法:INT n;(n為中斷號,取值為0~255)
通常,程式內部的跳轉,用JMP或CALL,並且JMP和CALL得引數是要跳轉的過程的入口指令地址,而INT則是呼叫系統提供的中斷服務程式,並且引數是中斷號,然後由CPU根據中斷號去計算中斷服務程式的入口地址,MSDOS使用中斷號21H作為系統呼叫,一般INT中斷的步驟如下:
(1)由AH給出中斷號
(2)根據相應功能的要求,設定入口引數
(3)INT 21H
(4)分析和使用出口引數
比如如下程式碼實現程式的退出並返回DOS:
Mov ah,4ch;-----給出中斷號
Int 21h; -----開始中斷
說明:除了直接以AL或AX返回出口引數外,INT21H還是用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控制指令結束--------------------------------------------------
到這裡為止,一些基本的彙編指令都已經學習完了,但是還得好好的去應用,不然還真的記不住這些指令的功能。
總結一下,一般情況下,通用暫存器可以較隨便使用,段暫存器和指標暫存器用來指示位置,一般不能隨便更改,另外一個就是標誌暫存器的各個標誌位的意義也非常的重要,很多指令都是根據標誌位來執行操作的。
接下來準備學習彙編的程式設計格式,然後就可以寫一些簡單的程式並自己進行除錯了 ,哈哈哈哈哈。偶非常的期待。