彙編指令全集
轉自:http://blog.sina.com.cn/s/blog_542a1e4a01011nyx.html
學習組合語言,最關鍵的就在於彙編指令集的掌握以及計算機工作方式的理解,以下是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、LOOPNE、CALL、RET、INT。
五、串操作指令:MOVS、LODS、STOS、CMPS、SCAS。
六、標誌處理指令:CLC、STC、CLD、STD。
七、32位CPU新增指令(後續補充並完善)
除上述的一些指令外,還有許多32位80X86CPU新增指令,這些指令有時會簡化程式設計,不過由於我也是剛剛學習彙編,這些都是從書上看到的,所以很多還不是十分了解,我寫這些的目的僅僅是想讓自己能更好的去記住這些指令的作用和用法,同事也希望和我一樣剛入門的朋友能夠多瞭解一些,並沒有其他目的,所有的示例也並沒有經過實際的程式碼測試,所以希望各位朋友,不管你喜歡不喜歡,反對不反對,請文明發言,謝謝!
------------------------------------------------資料傳送指令開始-------------------------------------------------------
1、MOV(傳送)
指令寫法:MOVtarget,source
功能描述:將源運算元source的值複製到target中去,source值不變
注意事項:1)target不能是CS(程式碼段暫存器),我的理解是程式碼段不可寫,只可讀,所以相應這地方也不能對CS執行復制操作。2)target和source不能同時為記憶體數、段暫存器(CS\DS\ES\SS\FS\GS)3)不能將立即數傳送給段暫存器
寫法示例:MOVdl,01H;MOVeax,[bp];eax =ss:[bp]雙字傳送。
2、XCHG(交換)
指令寫法:XCHGobject1,object2
功能描述:交換object1與object2的值
注意事項:1)不能直接交換兩個記憶體數的值2)型別必須匹配3)兩個運算元任何一個都不能是段暫存器【看來段暫存器的寫入的限制非常的嚴格,MOV指令也不能對段暫存器進行寫入】,4)必須是通用暫存器(ax、bx、cx、dx、si、di)或記憶體數
寫法示例:XCHGax,[bx][si];XCHG ax,bx;
3、LEA(裝入有效地址)
指令寫法:LEZreg16,mem
功能描述:將有效地址MEM的值裝入到16位的通用暫存器中。
寫法示例:假定bx=5678H,EAX=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不同的是,這裡是裝入的值,而不是有效地址)
這幾個指令,名稱不同,作用差不多。
寫法: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;pop cx;
保護暫存器: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(符號擴充套件指令的一般形式)
寫法: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/memreg/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碼相減的借位。