匯編語(yǔ)言指令
匯編指令英文全稱(chēng)
1.通用數(shù)據(jù)傳送指令
MOV----> move
MOV dest,src ;dest←src
MOV指令把一個(gè)字節(jié)或字的操作數(shù)從源地址src傳送至目的地址dest。
MOVSX---->extended move with sign data
MOVZX---->extended move with zero data
PUSH---->push
POP---->pop
進(jìn)棧出棧指令
PUSHA---->push all
POPA---->pop all
PUSHAD---->push all data
POPAD---->pop all data
BSWAP---->byte swap
XCHG---->exchange
交換指令用來(lái)將源操作數(shù)和目的操作數(shù)內(nèi)容交換,操作數(shù)可以是字、也可以是字節(jié),可以在通用寄存器與通用寄存器或存儲(chǔ)器之間對(duì)換數(shù)據(jù),但不能在存儲(chǔ)器與存儲(chǔ)器之間對(duì)換數(shù)據(jù)。
mov ax,1234h ;ax=1234h
mov bx,5678h ;bx=5678h
xchg ax,bx ;ax=5678h,bx=1234h
xchg ah,al ;ax=7856h
CMPXCHG---->compare and change
XADD---->exchange and add
XLAT---->translate
換碼指令用于將BX指定的緩沖區(qū)中、AL指定的位移處的數(shù)據(jù)取出賦給AL。
2.輸入輸出端口傳送指令
IN---->input
OUT---->output
3.目的地址傳送指令
LEA---->load effective addres
有效地址傳送指令
mov bx,0400h
mov si,3ch
lea bx,[bx+si+0f62h] ;BX=139EH
這里BX得到的是主存單元的有效地址,不是物理地址,也不是該單元的內(nèi)容。
LDS---->load DS
LES---->load ES
LFS---->load FS
LGS---->load GS
LSS---->load SS
4.標(biāo)志傳送指令
LAHF---->load AH from flag
SAHF---->save AH to flag
PUSHF---->push flag
POPF---->pop flag
PUSHD---->push dflag
POPD---->pop dflag
二、算術(shù)運(yùn)算指令
ADD---->add
加法指令 mov al,0fbh ;al=0fbh
add al,07h ;al=02h
ADC---->add with carry
INC---->increase 1
AAA---->ascii add with adjust
DAA---->decimal add with adjust
SUB---->substract
SBB---->substract with borrow
DEC---->decrease 1
NEC---->negative
CMP---->compare
AAS---->ascii adjust on substract
DAS---->decimal adjust on substract
MUL---->multiplication
IMUL---->integer multiplication
AAM---->ascii adjust on multiplication
DIV---->divide
IDIV---->integer divide
AAD---->ascii adjust on divide
CBW---->change byte to word
CWD---->change word to double word
CWDE---->change word to double word with sign to EAX
CDQ---->change double word to quadrate word
三、邏輯運(yùn)算指令
AND---->and
or---->or
XOR---->xor
NOT---->not
TEST---->test
SHL---->shift left
SAL---->arithmatic shift left
SHR---->shift right
SAR---->arithmatic shift right
ROL---->rotate left
ROR---->rotate right
RCL---->rotate left with carry
RCR---->rotate right with carry
四、串指令
MOVS---->move string
CMPS---->compare string
SCAS---->scan string
LODS---->load string
STOS---->store string
REP---->repeat
REPE---->repeat when equal
REPZ---->repeat when zero flag
REPNE---->repeat when not equal
REPNZ---->repeat when zero flag
REPC---->repeat when carry flag
REPNC---->repeat when not carry flag
五、程序轉(zhuǎn)移指令
1>無(wú)條件轉(zhuǎn)移指令(長(zhǎng)轉(zhuǎn)移)
JMP---->jump
CALL---->call
RET---->return
RETF---->return far
2>條件轉(zhuǎn)移指令(短轉(zhuǎn)移,-128到+127的距離內(nèi))
JA--->jump when above
JAE---->jump when above or equal
JNB---->jump when not below
JB---->jump when below
JNAE---->jump when not above or equal
JBE---->jump when below or equal
JNA---->jump when not above
JG---->jump when greater
JNLE---->jump when not less or equal
JGE---->jump when greater or equal
JNL---->jump when not less
JL---->jump when less
JNGE---->jump when not greater or equal
JLE---->jump when less or equal
JNG---->jump when not greater
JE---->jump when equal
JZ---->jump when has zero flag
JNE---->jump when not equal
JNZ---->jump when not has zero flag
JC---->jump when has carry flag
JNC---->jump when not has carry flag
JNO---->jump when not has overflow flag
JNP---->jump when not has parity flag
JPO---->jump when parity flag is odd
JNS---->jump when not has sign flag
JO---->jump when has overflow flag
JP---->jump when has parity flag
JPE---->jump when parity flag is even
JS---->jump when has sign flag
3>循環(huán)控制指令(短轉(zhuǎn)移)
LOOP---->loop
LOOPE---->loop equal
LOOPZ---->loop zero
LOOPNE---->loop not equal
LOOPNZ---->loop not zero
JCXZ---->jump when CX is zero
JECXZ---->jump when ECX is zero
4>中斷指令
INT---->interrupt
INTO---->overflow interrupt
IRET---->interrupt return
5>處理器控制指令
HLT---->halt
WAIT---->wait
ESC---->escape
LOCK---->lock
NOP---->no operation
STC---->set carry
CLC---->clear carry
CMC---->carry make change
STD---->set direction
CLD---->clear direction
STI---->set interrupt
CLI---->clear interrupt
六、偽指令
DW---->definw word
PROC---->procedure
ENDP---->end of procedure
SEGMENT---->segment
ASSUME---->assume
ENDS---->end segment
END---->end
學(xué)習(xí)數(shù)據(jù)傳送指令MOV、XCHG效果
80386的數(shù)據(jù)傳送指令是為了實(shí)現(xiàn)CPU和內(nèi)存、輸入/輸出端口之間的數(shù)據(jù)傳送。
(1)MOV:稱(chēng)為數(shù)值傳送指令,格式是“MOV DST,SRC”。
(2)MOV指令將源操作數(shù)SRC傳送到目的操作數(shù)DST中,
(3)傳送的數(shù)據(jù)格式可以是8字節(jié)、16字節(jié)和32字節(jié)。
?示例代碼:
????MOV EAX,56? //將56H立即數(shù)傳送到EAX寄存器
????MOV ESI,DWROD PTR [EAX*2+1] //將內(nèi)存地址為EAX*2+1處的4字節(jié)數(shù)據(jù)傳送到ESI寄存器。
????MOV AH,BYTE PTR [ESI*2+EAX]? //將內(nèi)存地址為ESI*2+EAX處的8位數(shù)據(jù)傳送到AH寄存器。
????MOV DWORD PTR [ESP+36],EBX? //將EBX寄存器的值以4字節(jié)傳送到堆棧地址為ESP+36所指向的地方。
(4)XCHG:稱(chēng)為交換指令,XCHG實(shí)現(xiàn)寄存器間和內(nèi)存間的數(shù)據(jù)交換。
格式是“XCHG DST,SRC”。XCHG指令交換SRC和DST之間的數(shù)據(jù),
交換的數(shù)據(jù)可以是8字節(jié)、16字節(jié)和32字節(jié),其中SRC和DST必須格式相同。
示例代碼:
????XCHG EAX,EDX? ?//將EDX寄存器的值和EAX寄存器的值交換
????XCHG [ESP-55],EDI //將EDI寄存器的值和堆棧地址為[esp-55]處的值交換。
????XCHG BH,BL? ? ? //將BL寄存器和BH寄存器的值交換。
????
學(xué)習(xí)數(shù)據(jù)傳送指令PUSH、POP效果。
PUSH和POP:稱(chēng)為壓入堆棧指令和彈出堆棧指令,格式是“PUSH SRC(源操作數(shù))”和“POPDST(目的操作數(shù))”。
PUSH指令和POP指令是匹配出現(xiàn)的,上面的代碼有多少個(gè)PUSH下面的代碼就有多少個(gè)POP,否則堆棧就會(huì)不平衡。
PUSH指令將源操作數(shù)SRC壓入堆棧,同時(shí)ESP-4,而POP恰恰相反,POP指令從堆棧的頂部彈出4字節(jié)的數(shù)值然后放入DST。在32位的Windows操作系統(tǒng)上,PUSH和POP指令的操作是以4字節(jié)為單位的。
PUSH和POP指令常用于向函數(shù)傳遞參數(shù)。
示例代碼:
????PUSH EAX //將EAX寄存器的值以4字節(jié)壓入堆棧,同時(shí)ESP-4
????PUSH DWORD PTR [12FF8589] //將內(nèi)存地址為12FF8589所指向的值以4字節(jié)壓入堆棧,同時(shí)ESP-4

????POP DWORD PTR [12FF8589] //將堆棧頂部的4字節(jié)彈出到內(nèi)存地址為12FF8589所指地方,同時(shí)ESP+4
????POP EAX ?//將堆棧頂部的4字節(jié)彈出到EAX寄存器,同時(shí)ESP+4
?
?
學(xué)習(xí)地址傳送指令 LEA效果
80x86有3條地址傳送指令,分別是LEA,LDS和LES。其實(shí)LDS和LES指令和段寄存器有關(guān),在32位的Windows操作系統(tǒng)上,一般的程序員都不需要管理段寄存器,所以相對(duì)而言,LDS和LES寄存器使用得比較少,一般情況下常見(jiàn)的只有LEA指令。
???LEA:稱(chēng)為地址傳送指令,格式是“LEA DST,ADDR”。LEA指令將ADDR地址加載到DST,其中ADDR可以是內(nèi)存,也可以是寄存器,而DST必須是一個(gè)通用寄存器。
???LEA指令相當(dāng)于C語(yǔ)言中的“&”and操作符,需要注意的是LEA和MOV是不同的,前者傳送的是地址,后者傳送的是操作數(shù)。
示例代碼:?
????LEA EAX,[12345678]
????MOV EAX,[12345678]
????//指令執(zhí)行后EAX寄存器的值為12345678H,而MOV EAX,[12345678] 指令執(zhí)行后EAX寄存器的值為內(nèi)存地址12345678指向的那個(gè)數(shù)值。?
還有一點(diǎn)需要注意LEA指令可用于算法運(yùn)算。
示例代碼:
????LEA ECX,[ECX+EAX*4] ?//ECX=ECX+EAX*4
?
學(xué)習(xí)算數(shù)運(yùn)算指令A(yù)DD SUB效果
80x86提供了8條加減法指令:ADD、ADC、SUB、SBB、INC、DEC、CMP和NEG,4條乘除法指令:MUL、IMUL、DIV和IDIV。
(1)常用的加減法指令。
1.ADD:稱(chēng)為加法指令,格式是“add OPER1,OPER2”。(操作數(shù)(operand))
ADD指令將OPER1+OPER2結(jié)果存放在OPER1中。
示例代碼:
????ADD EAX,ESI //將EAX寄存器的值加上ESI寄存器的值,得出的結(jié)果保存在EAX寄存器中。
????ADD EBX,DWORD PTR [12345678] //將EBX寄存器的值加上內(nèi)存地址為12345678所指的4字節(jié)值,得出的結(jié)構(gòu)保存在EBX寄存器中,其中DWORD PTR的意思是顯示說(shuō)明按多少字節(jié)來(lái)操作,DWORD是DOUBLE WORD的縮寫(xiě),也就是兩個(gè)WORD的意思。
????? ?
不同的平臺(tái)和編譯器中,DWORD占用的字節(jié)數(shù)不同,在32位的Windows中一個(gè)WORD占用16字節(jié)空間,DWORD占用32字節(jié)空間,讀者可以在32位的Windows平臺(tái)上使用Visual C++編譯器編寫(xiě)C語(yǔ)言Printf("%d",sizeof(DWORD))來(lái)驗(yàn)證。
在匯編語(yǔ)言中常用的還有WORD PTR和BYTE PTR,表示的意思分別是按WORD來(lái)操作和按BYTE來(lái)操作。
2.SUB:稱(chēng)為減法指令,格式是“SUB OPER1,OPER2”。
SUB 指令將OPER1-OPER2結(jié)果存放在OPER1中。
示例代碼:
????SUB ECX,4H? //將ECX寄存器的值減去4H,得出的結(jié)果保存在EAX寄存器中。
????SUB BYTE PTR[EAX],CH //將內(nèi)存地址為EAX所指向的數(shù)據(jù)按字節(jié)為單位和CH寄存器相減,得出的結(jié)果按字節(jié)為單位保存在EAX所指向的地方。
學(xué)習(xí)算數(shù)運(yùn)算指令I(lǐng)NC DEC效果
INC:稱(chēng)為加1指令,格式是“INC OPER”。
INC指令將操作數(shù)OPER加1,得出的結(jié)果保存在OPER中。
示例代碼:
????INC EAX //將EAX寄存器的值加1,得出的結(jié)果存放在原來(lái)的地方。
????INC WORD PTR [EBX+2] //將內(nèi)存地址為EBX+2的數(shù)據(jù)按WORD為單位加1,得出的結(jié)果存放在原來(lái)的地方。
?
DEC:稱(chēng)為減1指令,格式是“EDC OPER”。
DEC指令將操作數(shù)OPER減1,得出的結(jié)果保存在OPER中。
示例代碼:
????DEC EDX //將EDX寄存器的值減1,得出的結(jié)果存放在原來(lái)的地方
????DEC DWORD PTR [EBP+36] //將堆棧地址為EBP+36的數(shù)據(jù)按DWORD為單位減1,得出的結(jié)果存放在原來(lái)的地方。
?
學(xué)習(xí)算數(shù)運(yùn)算指令CMP NEG效果
CMP:稱(chēng)為比較指令,格式是“CMP OPER1,OPER2”.
CMP指令將OPER1減去OPER2,得出的結(jié)果不保存,只是相應(yīng)地設(shè)置寄存器EFLAGS的CF、PF、ZF、AF、SF和OF。也就是說(shuō)可以通過(guò)測(cè)試寄存器EFLAGS相關(guān)的標(biāo)志的值得知CMP指令執(zhí)行后的結(jié)果。
示例代碼:
????CMP EAX,56H? //將EAX寄存器的值減去56H,得出的結(jié)果不保存,并且設(shè)置寄存器EFLAGS相關(guān)的標(biāo)志位。
????CMP EDX,DWORD PTR [ECX+2] //將EDX寄存器的值以DWORD為單位減去內(nèi)存地址為ECX+2所指向的數(shù)據(jù),得出的結(jié)果不保存,并且設(shè)置寄存器EFLAGS相關(guān)的標(biāo)志位。
NEG:稱(chēng)為取補(bǔ)指令,格式是“NEG OPER”。
NEG指令將OPER操作數(shù)取反,簡(jiǎn)而言之就是將零減去OPER操作數(shù),得出的結(jié)果保存在OPER自身中。
? ?在計(jì)算機(jī)的CPU中沒(méi)有減法的機(jī)制,減法是用加法實(shí)現(xiàn)的,例如:100-55這個(gè)操作,CPU實(shí)際執(zhí)行的是100+(-55),而-55相當(dāng)于是求55的相反數(shù),求相反數(shù)的時(shí)候NEG指令正好派上用場(chǎng)了。
示例代碼:
????NEG EAX //將EAX寄存器的值取反,得出的結(jié)果保存在EAX中
????NEG WORD PTR [12345678] //將內(nèi)存地址為12345678所指向的數(shù)據(jù)以WORD為單位取反,得出的結(jié)果以WORD為單位,保存在內(nèi)存地址為12345678
? ? ? ??
學(xué)習(xí)算數(shù)運(yùn)算指令 MUL IMUL效果
MUL:稱(chēng)為無(wú)符號(hào)乘法指令,格式是“MUL OPER”。
MUL指令隱含了一個(gè)參加運(yùn)算的操作數(shù)EAX寄存器,MUL指令將EAX寄存器的值乘以O(shè)PER,得出的結(jié)果保存在EAX寄存器中。如果結(jié)果超過(guò)32位,則高32位使用EDX寄存器保存,EAX寄存器則保存低32位。
示例代碼:
????MUL EDX //將EAX寄存器的值乘以EDX寄存器的值,得出的結(jié)果保存在EAX寄存器中。
????MUL BYTE PTR [EDI] //將EAX寄存器的值乘以以BYTE為單位內(nèi)存地址為EDI所指向的數(shù)據(jù),得出的結(jié)果保存在EAX寄存器中。
IMUL稱(chēng)為有符號(hào)乘法指令,原理和操作可以參考MUL指令,IMUL和MUL的區(qū)別是IMUL將參與運(yùn)算的操作數(shù)當(dāng)成有符號(hào)數(shù)來(lái)處理。
學(xué)習(xí)算數(shù)運(yùn)算指令 DIV IDIV效果。
DIV:稱(chēng)為除法指令,格式是“DIV OPER”。
DIV 指令將64位(EDX和EAX)或32位(EAX)的值除以O(shè)PER,得出的商保存在EAX寄存器中,而余數(shù)則保存在EDX寄存器中,由OPER操作數(shù)決定按多少字節(jié)操作。
示例代碼:
????DIV ECX //將EAX寄存器的值按4字節(jié)為單位除以ECX寄存器的值,得出的結(jié)果商保存在EAX寄存器中,余數(shù)保存在EDX寄存器中。
????DIV WORD PTR [ESP+36] //將EAX寄存器的值按WORD為單位除以堆棧地址為ESP+36所指向的數(shù)據(jù),得出的結(jié)果商保存在EAX寄存器中,余數(shù)保存在EDX寄存器中。
?????
IDIV:稱(chēng)為有符號(hào)除法指令,原理和操作可以參考DIV指令,IDIV和DIV的區(qū)別是IDIV將參與運(yùn)算的操作數(shù)當(dāng)成有符號(hào)數(shù)來(lái)處理。
mov eax,1000
cwd
div ecx
1000(H)/7= 4096/7 =585.1
CWD是匯編語(yǔ)言中的字?jǐn)U展指令,它的功能是將一個(gè)字型變量擴(kuò)展為雙字型變量,即Change Word to Double word。
??
學(xué)習(xí)邏輯運(yùn)算指令OR AND NOT效果
80x86提供了OR、AND、NOT/XOR和TEST這5條邏輯運(yùn)算指令,邏輯運(yùn)算指令是數(shù)據(jù)加密/解密的基礎(chǔ),所以應(yīng)該熟練掌握它們的用法。
(1)OR:稱(chēng)為或操作指令,格式是“OR OPER1,OPER2”。OR指令將OPER1操作數(shù)和OPER2操作數(shù)進(jìn)行或運(yùn)算,得出的結(jié)果保存在OPER1中。
? OR指令主要用于維持某個(gè)二進(jìn)制的某些位的值不變,而另一些位設(shè)置為1的情況。把不需要改變的位用0進(jìn)行或運(yùn)算,把要設(shè)置為1的位用1進(jìn)行或運(yùn)算即可。
示例代碼:
????OR EAX,80008000H? //將EAX寄存器和立即數(shù)80008000H進(jìn)行或運(yùn)算,實(shí)際上是將EAX寄存器的31位和15位置1
????OR AH,BH? //將AH寄存器或BH寄存器進(jìn)行或運(yùn)算。
EAX= 1C1EA4
OR EAX,80008000H
得到:eax=801C9EA4
AH=1 BH=2
? ? 1 二進(jìn)制 0001
Or? 2 二進(jìn)制 0010?
? ? ? ? ? ? ?0011(也就是10進(jìn)制3)
因?yàn)榈谝晃皇?,第二位是0,而第二個(gè)數(shù)的第一位是0第二位是1
根據(jù) or計(jì)算原理.1 or 0=1,0 or 0=0,0 or 1=1,1 or 1=1
的原理得到的就是0011
(2)AND:稱(chēng)為與操作指令,格式是“AND OPER1,OPER2”。AND指令將OPER1操作數(shù)和OPER2操作數(shù)進(jìn)行與運(yùn)算,得出的結(jié)果保存在OPER1中。?
? ?AND指令主要用于維持某個(gè)二進(jìn)制數(shù)的某些位的值不變,而另一些位設(shè)置為0的情況。把不需要改變的位用1進(jìn)行與運(yùn)算,把要設(shè)置為0的位用0進(jìn)行與運(yùn)算即可。
? 示例代碼:
AND CH,80H //將CH寄存器的值和80H進(jìn)行與運(yùn)算,實(shí)際上是將CH寄存器的第7位保存不變,其余位置0.
AND DWORD PTR [EAX],80008000H //將內(nèi)存地址為EAX所指向的數(shù)據(jù)按DWORD為單位與80008000H進(jìn)行與運(yùn)算,實(shí)際上是將內(nèi)存地址為EAX指向的4字節(jié)數(shù)據(jù)的第31位和15位置保存不變,其余位置0.
AND CH,80H
CH=1? 二進(jìn)制 00000001
80 二進(jìn)制 10000000
And? ? ? ? ? ?00000000
根據(jù) and計(jì)算原理 0 and 1 =0 ,0 and 0=0,1 and 1=1的原理得到的就是00000000
AND DWORD PTR [EAX],80008000H
EAX=001C1EA4
001C1EC8? ?二進(jìn)制_00000000000111000001111011001000
080008000? ?二進(jìn)制10000000000000001000000000000000
? ? ? And? ? ? ? ?00000000000000000000000000000000? (十六進(jìn)制就是00000000)
根據(jù) and計(jì)算原理 0 and 1 =0 ,0 and 0=0,1 and 1=1的原理得到的就是00000000000000000000000000000000?
(3)NOT:稱(chēng)為取反指令,格式是“NOT OPER”。NOT 指令將OPER操作數(shù)取反。注意NOT和NEG不同,NOT指令是按位取反,NEG是求補(bǔ),意即將0減去操作數(shù)。
例如:
? ? ? ?15H的二進(jìn)制為? 0 0 0 1 0 1 0 1 B
?NEG? 15H 的二進(jìn)制為 1 1 1 0 1 0 1 1 B
?NOT? 15H 的二進(jìn)制為 1 1 1 0 1 0 1 0 B
根據(jù) NOT計(jì)算原理 0 not 1, 1 not 0? 得 1 1 1 0 1 0 1 0?
NOT ECX? ? // ECX=1? 執(zhí)行后就是用FFFFFFFF-1=FFFFFFFE
學(xué)習(xí)邏輯運(yùn)算指令XOR TEST效果
(1)XOR:稱(chēng)為異或操作指令,格式是“XOR OPER1,OPER2”。XOR指令將OPER1操作數(shù)和OPER2操作數(shù)進(jìn)行異或運(yùn)算,得出的結(jié)果保存在OPER1中。
?XOR指令主要用于維持某個(gè)二進(jìn)制數(shù)的某些位的值不變,而某些位取反的情況。把不需要改變的位用0進(jìn)行異或運(yùn)算,把需要取反的位用1進(jìn)行異或運(yùn)算即可。
示例代碼:
????XOR EAX,FFFF0000H //將EAX寄存器的值和立即數(shù)FFFF0000H進(jìn)行異或運(yùn)算,實(shí)際上將EAX寄存器的值的高16位取反,低16位保存不變。
????XOR AH,F0H ?//將AH寄存器的值和立即數(shù)F0F0H進(jìn)行異或運(yùn)算,實(shí)際上是將AH寄存器的值的第15位和7位取反,其余位保持不變。
?
EAX=001C1EA4
001C1EA4_0000000000111000001111010100100
FFFF0000 _11111111111111110000000000000000
???Xor ??_11111111111000110001111010100100 (十六進(jìn)制:FFE31EA4)
根據(jù) XOR 計(jì)算原理:0 xor 0 =0, 1 xor 1 =0,1 xor 0 =1 得到:FFE31EA4
?
XOR AH,F0H
AH=50_01010000
????F0_11110000
XOR ??10100000 (A0十六進(jìn)制)
根據(jù) XOR 計(jì)算原理:0 xor 0 =0, 1 xor 1 =0,1 xor 0 =1 得到:A0
(2)TEST:稱(chēng)為測(cè)試指令,格式是“TEST OPER1,OPER2”。TEST指令將OPER1操作數(shù)和OPER2操作數(shù)進(jìn)行與運(yùn)算,不保存結(jié)果,只設(shè)置標(biāo)志寄存器EFLAGS相應(yīng)的標(biāo)志位的值。
?TEST指令常用于測(cè)試一個(gè)二進(jìn)制位的某些位是否為1,但不改變?cè)床僮鲾?shù)的情況。
?
示例代碼:
TEST EAX,F0000000H ?//將EAX寄存器的值和立即數(shù)F00000000H進(jìn)行與運(yùn)算,實(shí)際上是測(cè)試EAX寄存器的第31、30、29、28位是否為1,并且設(shè)置標(biāo)志寄存器EFLAGS相應(yīng)的標(biāo)志位的值。
TEST EAX,F0000000H
EAX=001C1EA4
001C1EA4_ 000000000000000111000001111010100100
F00000000_111100000000000000000000000000000000
???And ???000000000000000000000000000000000000
?
根據(jù) and計(jì)算原理?0 and 1 =0 ,0 and 0=0,1 and 1=1的原理得到的就是?0
學(xué)習(xí)普通移位指令SAL SAR SHL SHR效果
80x86有4條普通移位指令和4條循環(huán)移位指令,它們都隱含地使用CF寄存器參與運(yùn)算。
(1)普通移位指令。
SAL算術(shù)左移指令、SAR算術(shù)右移指令、SHL邏輯左移指令和SHR邏輯右移指令。
這4條普通移位指令的格式都是一樣的:普通移位指令名稱(chēng) OPER1,OPER2,其中OPER1可以是寄存器或內(nèi)存,OPER2代表的是移位的位數(shù)。其中SAL指令和SHL指令指向結(jié)果是一樣的。
對(duì)于有符號(hào)和無(wú)符號(hào)數(shù)而言,SAL算術(shù)左移指令和SHL邏輯左移指令每移動(dòng)一位相當(dāng)于乘以2.而SAR算術(shù)右移指令和SHR邏輯右移指令有點(diǎn)不同。對(duì)于有符號(hào)和無(wú)符號(hào)而言,SAR算術(shù)右移指令每移動(dòng)一位相當(dāng)于除以2,而SHR邏輯右移指令不管操作數(shù)是有符號(hào)數(shù)還是無(wú)符號(hào)數(shù),每向右移動(dòng)一位,左邊都是用0填充,所以當(dāng)操作數(shù)是無(wú)符號(hào)數(shù)的時(shí)候,SHR邏輯右移指令每移動(dòng)一位才等于除以2.
示例代碼:
????SAL EAX,2 //將EAX寄存器的值向左移動(dòng)2位,得出的結(jié)果保存在EAX寄存器中,相當(dāng)于EAX=EAX*4
????SAR DWORD PTR DS:[ESI],4 //將內(nèi)存地址為ESI所指向的數(shù)據(jù)按DWORD為單位右移4位,相當(dāng)于將內(nèi)存地址為ESI所指向的數(shù)據(jù)按DWORD為單位的數(shù)據(jù)除以2*2*2*2=16(十進(jìn)制)?
????SHL DWORD PTR [EBP+2H],2 //將堆棧地址為EBP+2H所指向的數(shù)據(jù)按DWORD為單位左移2位,相當(dāng)于將內(nèi)存地址為EBP+2H所指向的數(shù)據(jù)按DWORD為單位的數(shù)據(jù)乘以4.
????SHR EDI,4? //將EDI寄存器的值邏輯右移ECX位。EDI值除以2*2*2*2=16(十進(jìn)制)
學(xué)習(xí)循環(huán)移位指令ROL ROR RCL RCR效果
循環(huán)移位指令
ROL左循環(huán)移位指令、ROR右循環(huán)移位指令、RCL帶進(jìn)位左循環(huán)移位指令和RCR帶進(jìn)位右循環(huán)移位指令。
這4條循環(huán)移位指令的格式都是一樣的:循環(huán)移位指令名稱(chēng) OPER1,OPER2,其中OPER1可以是寄存器或內(nèi)存,OPER2要么是CL寄存器要么是1,代表移動(dòng)的次數(shù),如果要移的次數(shù)多于1次,則需要把移位次數(shù)存放在CL寄存器中。
ROL、ROR和RCL、RCR的區(qū)別是前者沒(méi)有將標(biāo)志寄存器EFLAGS的CF進(jìn)位標(biāo)志包含參與循環(huán)移位,后者則把CF進(jìn)位標(biāo)志包含參與循環(huán)移位。
示例代碼:
????ROL AL,1? ?//將EAX寄存器的值向左移動(dòng)一位,被移出的位送到CF,同時(shí)將被移出的位放到最低位。
????ROR EAX,CL? //將EAX寄存器的值向右移動(dòng)CL位,被移出的位送到CF,同時(shí)將被移出的位放到最高位。
????RCL EAX,1? //將EAX寄存器的值向左移動(dòng)1位,被移出位送到CF,同時(shí)將CF之前的值放到最低位。
????RCR EAX,CL? //將EAX寄存器的值向右移動(dòng)CL位,被移出位送到CF,同時(shí)將CF之前的值放到最高位。
ROL AL,1
ROR EAX,CL
把82H轉(zhuǎn)成二進(jìn)制數(shù)10000010(B)
循環(huán)左移1位后變成:00000101(B),換算成十六進(jìn)制數(shù)便是05(H)
循環(huán)右移1位后變成:01000001(B),換算成十六進(jìn)制數(shù)便是41(H)
RCL AL,1
RCR AL,CL
首先把82H轉(zhuǎn)換成二進(jìn)制數(shù)10000010B
帶進(jìn)位循環(huán)左移1位后變成:00000100B,CF=1換算成十六進(jìn)制數(shù)便是04H
帶進(jìn)位循環(huán)右移1位后變成:11000001B,CF=0 換算成十六進(jìn)制數(shù)便是C1H
學(xué)習(xí)條件轉(zhuǎn)移指令 JMP JNZ JE 等效果
條件轉(zhuǎn)移指令
???程序的結(jié)構(gòu)可以分為3大部分,分別是順序結(jié)構(gòu)、分支結(jié)構(gòu)、循環(huán)結(jié)構(gòu)。像高級(jí)語(yǔ)言一樣,在高級(jí)語(yǔ)言里有if-else條件分支、do-while循環(huán)、for 循環(huán)和goto語(yǔ)句來(lái)改變程序的執(zhí)行流程。在匯編語(yǔ)言中沒(méi)有高級(jí)語(yǔ)言里的if-else條件分支、do-while循環(huán)和for循環(huán),匯編語(yǔ)言通過(guò)提供條件轉(zhuǎn)移指令來(lái)實(shí)現(xiàn)程序執(zhí)行流程的改變。?
在匯編語(yǔ)言中條件轉(zhuǎn)移指令分為無(wú)條件轉(zhuǎn)移指令和條件轉(zhuǎn)移指令。
(1)無(wú)條件轉(zhuǎn)移指令JMP
JMP指令格式是:JMP OPER,其中OPER是目的地址。
示例代碼:
????JMP EAX //跳轉(zhuǎn)到EAX寄存器指示的4字節(jié)地址。
????JMP DWORD PTR DS:[ESI+2] ?//跳轉(zhuǎn)到內(nèi)存地址為ESI+2指示的2字節(jié)地址。
?
(2)條件轉(zhuǎn)移指令。
匯編的條件轉(zhuǎn)移指令非常多,通??梢苑譃?大部分:無(wú)符號(hào)數(shù)的條件轉(zhuǎn)移指令、有符號(hào)數(shù)的條件轉(zhuǎn)移指令和算術(shù)條件轉(zhuǎn)移指令。
?
條件轉(zhuǎn)移指令格式是:條件轉(zhuǎn)移指令名稱(chēng) OPER,其中OPER是目的地址。
無(wú)符號(hào)數(shù)的條件轉(zhuǎn)移指令名稱(chēng)、轉(zhuǎn)移條件、轉(zhuǎn)移說(shuō)明如表1-2表示。

有符號(hào)數(shù)的條件轉(zhuǎn)移指令名稱(chēng)、轉(zhuǎn)移條件、轉(zhuǎn)移說(shuō)明如表1-3所示。

算術(shù)條件轉(zhuǎn)移指令名稱(chēng)、轉(zhuǎn)移條件、轉(zhuǎn)移說(shuō)明如表1-4所示。

學(xué)習(xí)函數(shù)(子程序)調(diào)用指令 CALL RET效果。
魔恩QQ:8643245
各位親愛(ài)的朋友:
我們又在VIP零基礎(chǔ)匯編語(yǔ)言入門(mén)基礎(chǔ)課程相會(huì)了,那么,這節(jié)課,我將與你一起學(xué)習(xí)函數(shù)(子程序)調(diào)用指令 CALL RET效果。
學(xué)習(xí)理論秘籍:用最有效,最簡(jiǎn)單,最快速的技巧:“記憶或者理解”。
函數(shù)調(diào)用指令CALL
? 在高級(jí)語(yǔ)言中,對(duì)函數(shù)再熟悉不過(guò)了,一個(gè)程序的功能可以認(rèn)為是一組函數(shù)互相調(diào)用的結(jié)果,函數(shù)是計(jì)算并且返回某些值的一段代碼。
? 在匯編語(yǔ)言中,
使用CALL指令和RET指令或者CALL指令和ADD ESP,OPER指令
實(shí)現(xiàn)函數(shù)的調(diào)用與函數(shù)返回。
? CALL指令的格式是:CALL OPER,其中OPER是函數(shù)地址(子程序地址)
CALL指令首先將ESP堆棧指針寄存器的值減4,然后將EIP程序指令計(jì)數(shù)器的值壓入堆棧,最后計(jì)算函數(shù)地址,將當(dāng)前EIP程序指令計(jì)數(shù)器的值設(shè)置為函數(shù)地址。
例如:調(diào)用下面的C語(yǔ)言函數(shù),計(jì)算機(jī)會(huì)執(zhí)行如下操作:
? ? ? ? ? ? ? ? PUSH a[i]
Print("%d",a[i]) :? PUSH OFFSET String "%d"
? ? ? ? ? ? ? ? CALL print
? ? ? ? ? ? ? ? Add esp,8?
在高級(jí)語(yǔ)言中調(diào)用函數(shù)時(shí)不需要編程人員管理堆棧和恢復(fù)函數(shù)調(diào)用前的環(huán)境,因?yàn)楦呒?jí)語(yǔ)言的編譯器在編譯源代碼的時(shí)候已經(jīng)做好了。
? 在匯編語(yǔ)言中,編程人員使用CALL調(diào)用完函數(shù)后需要使用RET指令或ADD ESP指令恢復(fù)函數(shù)調(diào)用前的壞境,以便調(diào)用完函數(shù)后程序能繼續(xù)正常執(zhí)行。
??
RET函數(shù)返回指令的格式是:RET OPER,其中OPER是需要從堆棧中彈出的字節(jié)數(shù)。
? RET指令首先將堆棧中彈出4字節(jié)數(shù)據(jù)到EIP,然后ESP=ESP+2,最后根據(jù)OPER的值修改ESP堆棧指針的值ESP=ESP+OPER。
? 對(duì)于遵從Cdecl調(diào)用約定(后面會(huì)講到)的那些函數(shù)而言,函數(shù)調(diào)用完后不是使用RET指令,而是由調(diào)用者使用ADD ESP,OPER從堆棧中彈出OPER字節(jié)數(shù)據(jù)來(lái)清理堆棧。
如何判斷CALL有多少個(gè)參數(shù)?
? 1.看CALL前面的有幾個(gè)PUSH,假設(shè)有3個(gè),就是有3個(gè)參數(shù)
? 2.進(jìn)入CALL,看CALL尾部retn指令 是幾,假設(shè)是:retn 4 說(shuō)明該CALL有1個(gè)參數(shù),假設(shè)retn 0c? 說(shuō)明有3個(gè)參數(shù),0c(十六進(jìn)制)=12(10進(jìn)制),之所以4為一個(gè)參數(shù),是因?yàn)?個(gè)PUSH 占用4字節(jié)。
如果平衡堆棧?
? 根據(jù)上面的方法可以判斷出CALL有幾個(gè)參數(shù),
? 平衡堆棧就是用add esp,參數(shù)個(gè)數(shù)*4再轉(zhuǎn)換成16進(jìn)制
? 假設(shè):有5個(gè)參數(shù),5*4=20(十進(jìn)制) =轉(zhuǎn)換成十六進(jìn)制(14) 也就是: add esp,14?
Push 1
Push 2
Push 3
Push 4
Push 5
Call 00401000
Add esp,14
用于:CALL調(diào)用后能達(dá)到效果,但是游戲奔潰。
學(xué)習(xí)函數(shù)(子程序)調(diào)用約定-3種常用的調(diào)用約定。
魔恩QQ:8643245
各位親愛(ài)的朋友:
我們又在VIP零基礎(chǔ)匯編語(yǔ)言入門(mén)基礎(chǔ)課程相會(huì)了,那么,這節(jié)課,我將與你一起學(xué)習(xí)函數(shù)(子程序)調(diào)用約定-3種常用的調(diào)用約定。
學(xué)習(xí)理論秘籍:用最有效,最簡(jiǎn)單,最快速的技巧:“記憶或者理解”。
在早期的編程語(yǔ)言中具有代表性的有C語(yǔ)言、Pascal、Basic、不辛的是這些具有代表性的編程語(yǔ)言各自使用不同的函數(shù)參數(shù)傳遞方式和由誰(shuí)負(fù)責(zé)清除傳遞參數(shù)時(shí)使用的堆棧,俗稱(chēng)堆棧平衡方式,從而導(dǎo)致了有幾種調(diào)用約定。
? 調(diào)用約定是規(guī)定函數(shù)參數(shù)傳遞的順序和堆棧平衡的方式。常見(jiàn)的函數(shù)調(diào)用約定有Pascal調(diào)用約定、Cdecl調(diào)用約定和StdCall調(diào)用約定。
? 使用Delphi、編寫(xiě)的程序都遵從Pascal調(diào)用約定,C/C++/JAVA編寫(xiě)的程序都遵從Cdecl調(diào)用約定,Windows的API調(diào)用遵從的是StdCall調(diào)用約定。
? ?調(diào)用約定的參數(shù)傳遞順序
假設(shè)有一高級(jí)語(yǔ)言函數(shù)Message(parameter1,paramerer2,parameter3),按照Pascal調(diào)用約定、Cdecl調(diào)用約定和StdCall調(diào)用約定的參數(shù)傳遞順序如表1-5所示。

