生成匯編代碼
比如,一個簡單的函數(shù):
// hello.c
void func(){}
如何得到相應(yīng)的匯編代碼呢?
gcc -S hello.c
|
hello.s
|
clang -S hello.c
|
hello.s
|
gcc -S -masm=intel hello.c
|
hello.s
|
cl /FAs /C hello.c
|
hello.asm
|
看些結(jié)果:
- gcc 4.5.2, Ubuntu11.04 X86 默認(rèn)的匯編
.globl func
.type func, @function
func:
pushl %ebp
movl %esp, %ebp
popl %ebp
ret
- clang 2.8, Ubuntu11.04 X86
.globl func
.align 16, 0x90
.type func,@function
func:
pushl %ebp
movl %esp, %ebp
popl %ebp
ret
.Ltmp0:
.size func, .Ltmp0-func
- gcc 4.5.2, Ubuntu11.04 X86 Intel格式的匯編
.globl func
.type func, @function
func:
push ebp
mov ebp, esp
pop ebp
ret
- cl 16 (即VC10), Windows Xp
_func PROC
; 1 : void func(){}
push ebp
mov ebp, esp
pop ebp
ret 0
_func ENDP
- 順便看一個Sun Studio 11: C 5.8 compiler,SPARC架構(gòu)(服務(wù)器來自unix-center)
.global func
.type func,#function
func:
save %sp,-96,%sp
jmp %i7+8
restore
...
- 以及GCC 4.0.1,SPARC架構(gòu)(服務(wù)器來自unix-center)
.global func
func:
retl ! Result =
nop
.type func,2
.size func,(.-func)
...
這些東西太復(fù)雜了,關(guān)注點(diǎn)只能限制到X86架構(gòu)了。先看一下X86下常用的兩種匯編有哪些不同。
X86匯編語言 差異
X86 下常用的匯編有 AT&T 與 Intel 兩種(fix me?),二者在語法上有一定的差異:
前綴/后綴
區(qū)別:
|
Intel語法
|
AT&T語法
|
寄存器
|
|
加前綴 %
|
立即數(shù)
|
|
|
加前綴 $
|
十六進(jìn)制
|
加后綴h
|
數(shù)字前加 0x
|
二進(jìn)制
|
加后綴b
|
|
例子:
Intel語法
|
AT&T語法
|
mov eax,8
|
movl $8,%eax
|
mov ebx,0ffffh
|
movl $0xffff,%ebx
|
int 80h
|
int $0x80
|
操作數(shù)的方向
例子:
Intel語法(<==)
|
AT&T語法(==>)
|
mov eax,[ecx]
|
movl (%ecx),%eax
|
內(nèi)存單元操作數(shù)
- 在Intel的語法中,基寄存器用“[]”括起來
-
而在AT&T中,用“()”括起來。
Intel
|
AT&T
|
mov eax,[ebx+5]
|
movl 5(%ebx),%eax
|
間接尋址方式
-
Intel的指令格式是segreg:[base+index*scale+disp]
-
AT&T的格式是%segreg:disp(base,index,scale)
Intel語法
|
AT&T語法
|
指令 foo,segreg:[base+index*scale+disp]
|
指令 %segreg:disp(base,index,scale),foo
|
mov eax,[ebx+20h]
|
Movl 0x20(%ebx),%eax
|
add eax,[ebx+ecx*2h]
|
Addl (%ebx,%ecx,0x2),%eax
|
lea eax,[ebx+ecx]
|
Leal (%ebx,%ecx),%eax
|
sub eax,[ebx+ecx*4h-20h]
|
Subl -0x20(%ebx,%ecx,0x4),%eax
|
操作碼的后綴
例子:
Intel語法
|
AT&T語法
|
Mov al,bl
|
movb %bl,%al
|
Mov ax,bx
|
movw %bx,%ax
|
Mov eax,ebx
|
movl %ebx,%eax
|
Mov eax, dword ptr [ebx]
|
movl (%ebx),%eax
|
找個例子看看
int func(int i)
{
return 2 * i;
}
int main()
{
int s = func(255);
return 0;
}
- hello.s (gcc4.5.2, x86/ubuntu11.04)
func:
|
|
pushl %ebp
|
將ebp內(nèi)容壓棧保存
|
movl %esp, %ebp
|
|
movl 8(%ebp), %eax
|
注意到立即數(shù)255在main中壓棧后,先后有IP和本函數(shù)內(nèi)的ebp壓棧,故,棧頂+8指向立即數(shù)255
|
addl %eax, %eax
|
乘法操作變成了加法,eax存放返回值
|
popl %ebp
|
ebp出棧
|
ret
|
函數(shù)返回,(IP出棧)
|
main:
|
|
pushl %ebp
|
將ebp內(nèi)容壓棧保存,
|
movl %esp, %ebp
|
將棧頂保存到ebp中
|
subl $20, %esp
|
棧頂下移20字節(jié),用來保存局部變量
|
movl $255, (%esp)
|
將立即數(shù)255放入棧頂所指位置
|
call func
|
調(diào)用函數(shù)func,(此時將下條指令地址IP壓入棧中)
|
movl %eax, -4(%ebp)
|
將func的返回值放入局部變量中(-4(%ebp)就是變量s的位置)
|
movl $0, %eax
|
0送入eax,準(zhǔn)備返回值
|
leave
|
leave等價于 movl %ebp,%esp 和 popl %ebp
|
ret
|
|
參考
-
http:///kernel-book/ch02/2.6.1.htm
-
http://bbs./thread-106533-1-1.html
==================================================================================================
X86 匯編語言中CPU上的通用寄存器簡要說明
eax, ebx, ecx, edx, esi, edi, ebp, esp等都是X86 匯編語言中CPU上的通用寄存器的名稱,是32位的寄存器。如果用C語言來解釋,可以把這些寄存器當(dāng)作變量看待。
比方說:add eax,-2 ; //可以認(rèn)為是給變量eax加上-2這樣的一個值。
這些32位寄存器有多種用途,但每一個都有“專長”,有各自的特別之處。
EAX 是"累加器"(accumulator), 它是很多加法乘法指令的缺省寄存器。
EBX 是"基地址"(base)寄存器, 在內(nèi)存尋址時存放基地址。
ECX 是計數(shù)器(counter), 是重復(fù)(REP)前綴指令和LOOP指令的內(nèi)定計數(shù)器。
EDX 則總是被用來放整數(shù)除法產(chǎn)生的余數(shù)。
ESI/EDI 分別叫做"源/目標(biāo)索引寄存器"(source/destination index),因?yàn)樵诤芏嘧址僮髦噶钪? DS:ESI指向源串,而ES:EDI指向目標(biāo)串.
EBP 是"基址指針"(BASE POINTER), 它最經(jīng)常被用作高級語言函數(shù)調(diào)用的"框架指針"(frame pointer). 在破解的時候,經(jīng)常可以看見一個標(biāo)準(zhǔn)的函數(shù)起始代碼:
push ebp ; 保存當(dāng)前ebp
mov ebp,esp ; EBP設(shè)為當(dāng)前堆棧指針
sub esp, xxx ; 預(yù)留xxx字節(jié)給函數(shù)臨時變量.
...
這樣一來,EBP 構(gòu)成了該函數(shù)的一個框架, 在EBP上方分別是原來的EBP, 返回地址和參數(shù). EBP下方則是臨時變量. 函數(shù)返回時作 mov esp,ebp/pop ebp/ret 即可.
ESP 專門用作堆棧指針,被形象地稱為棧頂指針,堆棧的頂部是地址小的區(qū)域,壓入堆棧的數(shù)據(jù)越多,ESP也就越來越小。 在32位平臺上,ESP每次減少4字節(jié)。
esp:寄存器存放當(dāng)前線程的棧頂指針
ebp:寄存器存放當(dāng)前線程的棧底指針
eip:寄存器存放下一個CPU指令存放的內(nèi)存地址,當(dāng)CPU執(zhí)行完當(dāng)前的指令后,從EIP寄存器中讀取下一條指令的內(nèi)存地址,然后繼續(xù)執(zhí)行。
一般寄存器:AX、BX、CX、DX
AX:累積暫存器,BX:基底暫存器,CX:計數(shù)暫存器,DX:資料暫存器
索引暫存器:SI、DI
SI:來源索引暫存器,DI:目的索引暫存器
堆疊、基底暫存器:SP、BP
SP:堆疊指標(biāo)暫存器,BP:基底指標(biāo)暫存器
EAX、ECX、EDX、EBX:為ax,bx,cx,dx的延伸,各為32位元
ESI、EDI、ESP、EBP:為si,di,sp,bp的延伸,32位元
棧的基本模型
參數(shù)N
|
↓高地址
|
參數(shù)…
|
函數(shù)參數(shù)入棧的順序與具體的調(diào)用方式有關(guān)
|
參數(shù) 3
|
參數(shù) 2
|
參數(shù) 1
|
EIP
|
返回本次調(diào)用后,下一條指令的地址
|
EBP
|
保存調(diào)用者的EBP,然后EBP指向此時的棧頂。
|
臨時變量1
|
|
臨時變量2
|
|
臨時變量3
|
|
臨時變量…
|
|
臨時變量5
|
↓低地址
|
- ===========================================================================
-
80x86指令系統(tǒng)
80x86指令系統(tǒng),指令按功能可分為以下七個部分。
(1) 數(shù)據(jù)傳送指令。
(2) 算術(shù)運(yùn)算指令。
(3) 邏輯運(yùn)算指令。
(4) 串操作指令。
(5) 控制轉(zhuǎn)移指令。
(6) 處理器控制指令。
(7) 保護(hù)方式指令。
3.3.1數(shù)據(jù)傳送指令
數(shù)據(jù)傳送指令包括:通用數(shù)據(jù)傳送指令、地址傳送指令、標(biāo)志寄存器傳送指令、符號擴(kuò)展指令、擴(kuò)展傳送指令等。
一、通用數(shù)據(jù)傳送指令
1傳送指令
傳送指令是使用最頻繁的指令,格式:MOV DEST,SRC
功能:把一個字節(jié),字或雙字從源操作數(shù)SRC傳送至目的操作數(shù)DEST。
傳送指令允許的數(shù)據(jù)流方向見圖311。

圖 3.11 傳送指令數(shù)據(jù)流
由上圖可知,數(shù)據(jù)允許流動方向?yàn)椋和ㄓ眉拇嫫髦g、通用寄存器和存儲器之間、通用寄存器和段寄存器之間、段寄存器和存儲器之間,另外還允許立即數(shù)傳送至通用寄存器或存儲器。但在上述傳送過程中,段寄存器CS的值不能用傳送指令改變。
例 3.12CPU內(nèi)部寄存器之間的數(shù)據(jù)傳送。
MOV AL,DH ;AL←DH (8位)
MOV DS,AX ??;DS←AX (16位)
MOV EAX,ESI ??;EAX←ESI (32位)
例 3.13CPU內(nèi)部寄存器和存儲器之間的數(shù)據(jù)傳送。
MOV [BX],AX ;間接尋址 (16位)
MOV EAX,[EBX+ESI] ??;基址變址尋址 (32位)
MOV AL,BLOCK ;BLOCK為變量名,直接尋址(8位)
例 3.14立即數(shù)送通用寄存器、存儲器。
MOV EAX,12345678H ?。籈AX←12345678H (32位)
MOV [BX],12H ;間接尋址 (8位)
MOV AX,1234H;AX←1234H(16位)
使用該指令應(yīng)注意以下問題:
·源和目的操作數(shù)不允許同時為存儲器操作數(shù);
·源和目的操作數(shù)數(shù)據(jù)類型必須一致;
·源和目的操作數(shù)不允許同時為段寄存器;
·目的操作數(shù)不允許為CS和立即數(shù);
·當(dāng)源操作數(shù)為立即數(shù)時,目的操作數(shù)不允許為段寄存器;
·傳送操作不影響標(biāo)志位。
2擴(kuò)展傳送指令
格式:MOV SX DEST,SRC
MOV ZX DEST,SRC
功能:將源操作數(shù)由8位擴(kuò)展到16位送目的操作數(shù),或由16位擴(kuò)展到32位送目的操作數(shù)。其中MOVSX是按有符號數(shù)擴(kuò)展,MOVZX是按無符號數(shù)擴(kuò)展。無符號數(shù)或正數(shù)高位擴(kuò)展為0,負(fù)數(shù)高位擴(kuò)展為全“1”。
例 3.15帶符號數(shù)擴(kuò)展
MOV BL,80H ??; -128
MOVSX AX,BL ?。弧?0H擴(kuò)展為FF80H后送AX中。
例 3.16無符號數(shù)擴(kuò)展
MOV BL,80H ?。弧?28
MOVZX AX,BL ; 將80H擴(kuò)展為0080H后送AX中。
使用該指令應(yīng)注意以下問題:
·目的操作數(shù)應(yīng)為16位或32位通用寄存器;
·源操作數(shù)長度須小于目的操作數(shù)長度,為8位或16位通用寄存器或存儲器操作數(shù);
·擴(kuò)展傳送操作不影響標(biāo)志位。
3交換指令
(1) 格式:XCHG OPR1,OPR2
功能:交換操作數(shù)OPR1和OPR2的值,操作數(shù)數(shù)據(jù)類型為字節(jié)、字或雙字。允許通用寄存器之間,通用寄存器和存儲器之間交換數(shù)據(jù)。
例 3.17
XCHG AX,BX;通用寄存器之間交換數(shù)據(jù)(16位)
XCHG ESI,EDI;通用寄存器之間交換數(shù)據(jù)(32位)
XCHG BX,/[SI/];通用寄存器和存儲器之間交換數(shù)據(jù)(16位)
XCHG AL,/[BX/];通用寄存器和存儲器之間交換數(shù)據(jù)(8位)
使用該指令應(yīng)注意以下問題:
·操作數(shù)OPR1和OPR2不允許同為存儲器操作數(shù);
·操作數(shù)數(shù)據(jù)類型必須一致;
·交換指令不影響標(biāo)志位。
如要實(shí)現(xiàn)存儲器操作數(shù)交換,可用如下指令實(shí)現(xiàn):
MOV AL,BLOCK1
XCHG AL,BLOCK2
MOV BLOCK1,AL
(2) 格式:BSWAP REG
功能:將32位通用寄存器中,第1個字節(jié)和第4個字節(jié)交換,第2個字節(jié)和第3個字節(jié)交換。
例 3.18
MOV EAX,44332211H
BSWAP EAX;EAX=11223344H
使用該指令應(yīng)注意以下問題:
·操作數(shù)為32位通用寄存器;
·交換指令不影響標(biāo)志位。
二、堆棧操作指令
1壓棧指令
(1) 格式:PUSH SRC
功能:將源操作數(shù)壓下堆棧,源操作數(shù)允許為16位或32位通用寄存器、存儲器和立即數(shù)以及16位段寄存器。當(dāng)操作數(shù)數(shù)據(jù)類型為字類型,壓棧操作使SP值減2;當(dāng)數(shù)據(jù)類型為雙字類型,壓棧操作使SP值減4。
例 3.19
PUSH AX ??;通用寄存器操作數(shù)入棧(16位)
PUSH EBX ;通用寄存器操作數(shù)入棧(32位)
PUSH [SI] ?。淮鎯ζ鞑僮鲾?shù)入棧(16位)
PUSH DWORD PTR [DI] ??;存儲器操作數(shù)入棧(32位)
PUSHW 0A123H ;立即數(shù)入棧(16位)
PUSHD 20H ;立即數(shù)入棧(32位)
(2) 格式:PUSHA
PUSHAD
功能:PUSHA將16位通用寄存器壓入堆棧,壓棧順序?yàn)锳X,CX,DX,BX,SP,BP,SI,DI。
PUSHAD將32位通用寄存器壓入堆棧,壓棧順序?yàn)镋AX,ECX,EDX,EBX,ESP,EBP,ESI,EDI。
2出棧指令
(1) 格式:POP DEST
功能:從棧頂彈出操作數(shù)送入目的操作數(shù)。目的操作數(shù)允許為16或32位通用寄存器、存儲器和16位段寄存器。當(dāng)操作數(shù)數(shù)據(jù)類型為字類型,出棧操作使SP加2;當(dāng)操作數(shù)數(shù)據(jù)類型為雙字類型,出棧操作使SP加4。
例 3.20
POP AX ;操作數(shù)出棧送寄存器(16位)
POP ECX ;操作數(shù)出棧送寄存器(32位)
POP [BX] ?。徊僮鲾?shù)出棧送存儲器(16位)
POP DWORD PTR [SI] ?。徊僮鲾?shù)出棧送存儲器(32位)
(2) 格式:POPA
POPAD
功能:POPA從堆棧移出16字節(jié)數(shù)據(jù),并且按順序存入寄存器DI,SI,BP,SP,BX,DX,CX,AX中。
POPAD從堆棧移出32字節(jié)數(shù)據(jù),并且按順序存入寄存器EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX中。
使用堆棧操作指令應(yīng)注意以下問題。
(1) 目的操作數(shù)不允許為CS以及立即數(shù)。
(2) 堆棧操作指令不影響標(biāo)志位。
三、地址傳送指令
(1) 格式:LEA REG,MEM
功能:將源操作數(shù)的有效地址傳送到通用寄存器,操作數(shù)REG為16位或32位通用寄存器,源操作數(shù)為16位或32位存儲器操作數(shù)。
例 3.21
LEA BX,BLOCK;將BLOCK的有效地址傳送到BX中(16位)
LEA EAX,/[EBX/];將EBX內(nèi)容(有效地址)傳送到EAX中(32位)
(2) 格式LDS(ES,F(xiàn)S,GS,SS)REG,MEM
功能:根據(jù)源操作數(shù)指定的偏移地址,在數(shù)據(jù)段中取出段地址和偏移地址分別送指定的段寄存器和指定的通用寄存器。
例 3.22
LES BX,[SI] ?。粚?2位地址指針分別送ES和BX
LSS EAX,[EDI] ??;將48位地址指針分別送SS和EAX

例 3.23
DATA1 DD buff

LDS BX,DATA1;將buff的32位地址指針分別送DS和BX

地址傳送指令對標(biāo)志位無影響。
四、標(biāo)志寄存器傳送指令
(1) 格式:LAHF
SAHF
功能:LAHF將標(biāo)志寄存器中低8位送AH中。SAHF將AH中內(nèi)容送標(biāo)志寄存器中低8位。
(2) 格式:PUSHF
POPF
功能:PUSHF將標(biāo)志寄存器低16位內(nèi)容壓入堆棧,SP←SP-2。POPF將當(dāng)前棧頂一個字傳送到標(biāo)志寄存器低16位中,SP←SP+2。
(3) 格式:PUSHFD
POPFD
功能:PUSHFD將標(biāo)志寄存器32位內(nèi)容壓入堆棧SP←SP-4。POPFD將當(dāng)前棧頂一個雙字傳送到32位標(biāo)志寄存器中,SP←SP+4。
上述SAHF,POPF,POPFD均影響相應(yīng)的標(biāo)志寄存器內(nèi)容。
五、查表指令
格式:XLAT
功能:將寄存器AL中的內(nèi)容轉(zhuǎn)換成存儲器表格中的對應(yīng)值。實(shí)現(xiàn)直接查表功能。
XLAT指令規(guī)定:BX寄存器存放表的首地址,AL寄存器中存放表內(nèi)偏移量,執(zhí)行XLAT指令,以段寄存器DS的內(nèi)容為段基址,有效地址為BX和AL內(nèi)容之和,取出表中一個字節(jié)內(nèi)容送AL中。
例 3.24內(nèi)存中有一起始地址為TABLE的編碼表,試編程將表中順序號為4的存儲單元內(nèi)容送寄存器AL。
·MODEL SMALL
·DATA
TABLE DB 11H,22H,33H,44H,55H 某編碼表
·CODE
·STARTUP
MOV AL,4 ;AL←4
MOV BX,OFFSET TABLE ??;BX←TABLE表首地址
XLAT ?。唤Y(jié)果在AL中,AL=55H
·EXIT
END
查表指令不影響標(biāo)志位。
六、符號擴(kuò)展指令
(1) 格式:CBW
功能:將AL中8位帶符號數(shù),進(jìn)行帶符號擴(kuò)展為16位,送AX中。帶符號擴(kuò)展是指對正數(shù)高位擴(kuò)展為全“0”,對負(fù)數(shù)高位擴(kuò)展為全“1”。
例 3.25AL=55H 經(jīng)CBW擴(kuò)展后 AX=0055H
AL=A5H 經(jīng)CBW擴(kuò)展后 AX=FFA5H
(2) 格式:CWD
功能:將AX中16位帶符號數(shù),進(jìn)行帶符號擴(kuò)展為32位,送DX和AX中。高16位送DX中,低16位送AX中。
(3) 格式:CWDE
功能:將AX中16位帶符號數(shù),進(jìn)行帶符號擴(kuò)展為32位,送EAX中。
(4) 格式:CDQ
功能:將EAX中32位帶符號數(shù),進(jìn)行帶符號擴(kuò)展為64位,送EDX和EAX中。低32位送EAX中,高32位送EDX中。
符號擴(kuò)展指令對標(biāo)志位無影響。
3.3.2 算術(shù)運(yùn)算指令
80x86指令包括加、減、乘、除四種基本算術(shù)運(yùn)算操作及十進(jìn)制算術(shù)運(yùn)算調(diào)整指令。二進(jìn)制加、減法指令,帶符號操作數(shù)采用補(bǔ)碼表示時,無符號數(shù)和帶符號數(shù)據(jù)運(yùn)算可以使用相同的指令。二進(jìn)制乘、除法指令分帶符號數(shù)和無符號數(shù)運(yùn)算指令。
一、加法指令
格式:ADDDEST,SRC
ADCDEST,SRC
功能:ADD是將源操作數(shù)與目的操作數(shù)相加,結(jié)果傳送到目的操作數(shù)。ADC是將源操作數(shù)與目的操作數(shù)以及CF(低位進(jìn)位)值相加,結(jié)果傳送到目的操作數(shù)。
源操作數(shù)可以是通用寄存器、存儲器或立即數(shù)。目的操作數(shù)可以是通用寄存器或存儲器操作數(shù)。
ADD,ADC指令影響標(biāo)志位為OF,SF,ZF,AF,PF,CF。
例 3.26
MOV AX,9876H
ADD AH,AL;AX=0E76H CF=1 SF=0O F=0 ZF=0 AF=0 PF=0
ADC AH,AL;AX=8576H CF=0 SF=1O F=1 ZF=0 AF=1 PF=0
二、減法指令
格式:SUB DEST,SRC
SBB DEST,SRC
功能:SUB將目的操作數(shù)減源操作數(shù),結(jié)果送目的操作數(shù)。SBB將目的操作數(shù)減源操作數(shù),還要減CF(低位借位)值,結(jié)果送目的操作數(shù)。
源操作數(shù)可以是通用寄存器、存儲器或立即數(shù)。目的操作數(shù)可以是通用寄存器或存儲器操作數(shù)。
SUB,SBB指令影響標(biāo)志位為OF,SF,ZF,AF,PF,CF。
例 3.27
MOV AX, 9966H;AX=9966H
SUB AL, 80H;AL=E6HCF=1SF=1OF=1ZF=0AF=0PF=0
SBB AH, 80H;AH=18HCF=0SF=0OF=0ZF=0AF=0PF=1
三、加1減1指令
格式:INC DEST
DEC DEST
功能:INC指令將目的操作數(shù)加1,結(jié)果送目的操作數(shù)。DEC指令將目的操作數(shù)減1,結(jié)果送目的操作數(shù)。目的操作數(shù)為通用寄存器或存儲器操作數(shù)。
INC,DEC指令影響標(biāo)志位為OF,SF,ZF,AF,PF。
例 3.28
INC BL;BL←BL+1
INC AX;AX←AX+1
INC WORDPTR [BX];存儲器操作數(shù)加1
DEC BYTE PTR [SI];存儲器操作數(shù)減1
DEC EAX;EAX←EAX-1
四、比較指令
(1) 格式:CMP DEST,SRC =============這個是intel格式
功能:目的操作數(shù)減源操作數(shù),結(jié)果不回送。源操作數(shù)為通用寄存器、存儲器和立即數(shù)。目的操作數(shù)為通用寄存器、存儲器操作數(shù)。
CMP指令影響標(biāo)志位為OF,SF,ZF,AF,PF,CF。
例 3.29
CMP CX,3
CMP WORD PTR [SI],3
CMP AX,BLOCK
執(zhí)行比較指令后,對狀態(tài)標(biāo)志位影響見表3.2。對于兩個數(shù)的比較(AX-BX)有以下3種情況。
表 3.2 CMP指令對標(biāo)志位的影響

· 兩個正數(shù)比較,使用SF標(biāo)志位判斷。
SF=0,則AX≥BX,若ZF=1,則AX=BX
SF=1,則AX<BX
· 兩個無符號數(shù)比較,使用CF標(biāo)志位判斷。
CF=0,則AX≥BX,若ZF=1,則AX=BX
CF=1,則AX<BX
· 兩個負(fù)數(shù)比較,使用SF標(biāo)志位判斷。
SF=0,則AX≥BX,若ZF=1,則AX=BX
SF=1,則AX<BX
· 兩個異符號數(shù)比較。
如果OF=0,仍可用SF標(biāo)志判斷大小。
如果OF=1,說明結(jié)果的符號位發(fā)生錯誤,所以
SF=0,則AX<BX
SF=1,則AX>BX
綜上所述:兩個異號數(shù)比較
當(dāng)OF=0,SF=0,則AX>BX
SF=1,則AX<BX
當(dāng)OF=1,SF=0,則AX<BX
SF=1,則AX>BX
用邏輯表達(dá)式表示為:
若OF∨-SF=0,則AX>BX
若OF∨-SF=1,則AX<BX
(2) 格式:CMPXCHGDEST,REG
功能:目的操作數(shù)減源操作數(shù),
如果DEST=SRC,則SRC→DEST。
如果DEST≠SRC,則DEST→ACC(AL,AX,EAX)。
源操作數(shù)允許為通用寄存器。目的操作數(shù)可以為通用寄存器,存儲器操作數(shù)。
CMPXCHG影響標(biāo)志位為OF,SF,ZF,AF,PF,CF。
(3) 格式:CMPXCHG8BMEM
功能:EDX:EAX中值減存儲器操作數(shù)。
如果EDX:EAX=MEM64,則ECX:EBX→MEM64。
如果EDX:EAX≠M(fèi)EM64,則MEM64→EDX:EAX。
該指令為64位比較交換指令,影響ZF標(biāo)志位。
例 3.30 CMPXCHG8BQWORDPTR[EBX]
五、交換相加指令
格式:XADDDEST,REG
功能:目的操作數(shù)加源操作數(shù),結(jié)果送目的操作數(shù)。原目的操作數(shù)內(nèi)容送源操作數(shù)。源操作數(shù)允許為通用寄存器。目的操作數(shù)允許為通用寄存器、存儲器操作數(shù)。
XADD指令影響標(biāo)志位為OF,SF,ZF,AF,PF,CF。
六、求補(bǔ)指令
格式:NEGDEST
功能:對目的操作數(shù)求補(bǔ),用零減去目的操作數(shù),結(jié)果送目的操作數(shù)。目的操作數(shù)為通用寄存器、存儲器操作數(shù)。
NEG指令影響標(biāo)志位為OF,SF,ZF,AF,PF,CF。
七、乘法指令
(1) 格式:MULSRC
IMULSRC
功能:MUL為無符號數(shù)乘法指令,IMUL為帶符號數(shù)乘法指令。源操作數(shù)為通用寄存器或存儲器操作數(shù)。目的操作數(shù)缺省存放在ACC(AL,AX,EAX)中,乘積存AX,DX:AX,EDX:EAX中。
字節(jié)乘:ALSRC→AX
字乘:AXSRC→DX∶AX
雙字乘:EAXSRC→EDX∶EAX
MUL,IMUL指令執(zhí)行后,CF=OF=0,表示乘積高位無有效數(shù)據(jù);CF=OF=1表示乘積高位含有效數(shù)據(jù),對其它標(biāo)志位無定義。
例 3.31
MUL BL;字節(jié)乘
MUL WORD PTR [SI];字乘
IMUL BYTE PTR [DI];字節(jié)乘
IMUL DWORD PTR [ECX];雙字乘
如果使用IMUL指令,積采用補(bǔ)碼形式表示。
(2) 格式:IMULDEST,SRC
功能:將目的操作數(shù)乘以源操作數(shù),結(jié)果送目的操作數(shù)。目的操作數(shù)為16位或32位通用寄存器或存儲器操作數(shù)。源操作數(shù)為16位或32位通用寄存器、存儲器或立即數(shù)。
源操作數(shù)和目的操作數(shù)數(shù)據(jù)類型要求一致。乘積僅取和目的操作數(shù)相同的位數(shù),高位部分將被舍去,并且CF=OF=1。其它標(biāo)志位無定義。
(3) 格式:IMUL DEST,SRC1,SRC2
功能:將源操作數(shù)SRC1與源操作數(shù)SRC2相乘,結(jié)果送目的操作數(shù)。目的操作數(shù)DEST為16位或32位,允許為通用寄存器。源操作數(shù)SRC1為16位或32位通用寄存器或存儲器操作數(shù)。源操作數(shù)SRC2允許為立即數(shù)。
例 3.32 IMULEAX,[EBX],12H
要求目的操作數(shù)和源操作數(shù)SRC1類型相同,當(dāng)乘積超出目的操作數(shù)部分,將被舍去,并且使CF=OF=1,在使用這類指令時,需在IMUL指令后加一條判斷溢出的指令,溢出時轉(zhuǎn)錯誤處理執(zhí)行程序。
八、除法指令
格式:DIV SRC
IDIV SRC
功能:DIV為無符號數(shù)除法,IDIV為帶符號數(shù)除法。源操作數(shù)作為除數(shù),為通用寄存器或存儲器操作數(shù)。被除數(shù)缺省在目的操作數(shù)AX,DX:AX,EDX:EAX中。
字節(jié)除法:AX/SRC商→AL,余數(shù)→AH
字除法:DX·AX/SRC商→AX,余數(shù)→DX
雙字除法:EDX·EAX/SRC商→EAX,余數(shù)→EDX
由于被除數(shù)必須是除數(shù)的雙倍字長,一般應(yīng)使用擴(kuò)展指令進(jìn)行高位擴(kuò)展。當(dāng)進(jìn)行無符號數(shù)除法時,被除數(shù)高位按0擴(kuò)展為雙倍除數(shù)字長。當(dāng)進(jìn)行有符號數(shù)除法時,被除數(shù)以補(bǔ)碼表示??墒褂脭U(kuò)展指令CBW,CWD,CWDE,CDQ進(jìn)行高位擴(kuò)展。例如:
MOV AX,BLOCK
CWD;被除數(shù)高位擴(kuò)展
MOV BX,1000H
IDIV BX
對于帶符號除法,其商和余數(shù)均采用補(bǔ)碼形式表示,余數(shù)與被除數(shù)同符號。當(dāng)除數(shù)為零或商超過了規(guī)定數(shù)據(jù)類型所能表示的范圍時,將會出現(xiàn)溢出現(xiàn)象,產(chǎn)生一個中斷類型碼為“0”的中斷。執(zhí)行除法指令后標(biāo)志位無定義。
九、BCD算術(shù)運(yùn)算
十進(jìn)制數(shù)在機(jī)器中采用BCD碼表示,以壓縮格式存放,即一個字節(jié)存儲2位BCD碼,BCD加減法是在二進(jìn)制加減運(yùn)算的基礎(chǔ)上,對其二進(jìn)制結(jié)果進(jìn)行調(diào)整,將結(jié)果調(diào)整成BCD碼表示形式。
(1) 格式:DAA
功能:將存放在AL中的二進(jìn)制和數(shù),調(diào)整為壓縮格式的BCD碼表示形式。
調(diào)整方法:若AL中低4位大于9或標(biāo)志AF=1(表示低4位向高4位有進(jìn)位),則
AL+6→AL,1→AF,
若AL中高4位大于9,或標(biāo)志CF=1,(表示高4位有進(jìn)位),則
AL+60H→AL,1→CF,
DAA指令一般緊跟在ADD或ADC指令之后使用,影響標(biāo)志位為SF,ZF,AF,PF,CF。OF無定義。
例 3.33
ADD AL,BL
DAA
(2) 格式:DAS
功能:將存放在AL中的二進(jìn)制差數(shù),調(diào)整為壓縮的BCD碼表示形式。
調(diào)整方法:若AL中低4位大于9或標(biāo)志AF=1(表示低4位向高位借位),則
AL-6→AL,1→AF
若AL中高4位大于9或標(biāo)志CF=1(表示高4位向高位借位),則
AL-60H→AL,1→CF
DAS指令一般緊跟在SUB或SBB指令之后使用,影響標(biāo)志位為SF,ZF,AF,PF,CF。OF無定義。
例 3.34
SUB AL,BL
DAS
十、ASCII算術(shù)運(yùn)算
數(shù)字0~9的ASCII碼為30H~39H,機(jī)器采用一個字節(jié)存放一位ASCII碼,對于ASCII碼的算術(shù)運(yùn)算是在二進(jìn)制運(yùn)算基礎(chǔ)上進(jìn)行調(diào)整。調(diào)整指令有加、減、乘、除四種調(diào)整指令。
(1) 格式:AAA
功能:將存放在AL中的二進(jìn)制和數(shù),調(diào)整為ASCII碼表示的結(jié)果。
調(diào)整方法:若AL中低4位小于或等于9,僅AL中高4位清0,AF→CF。若AL中低4位大于9或標(biāo)志AF=1(進(jìn)位),則AL+6→AL,AH+1→AH,1→AF,AF→CF,AL中高4位清0。
AAA指令一般緊跟在ADD或ADC指令之后使用,影響標(biāo)志位為AF,CF。其它標(biāo)志位無定義。
例 3.35
MOV AX,0036H
ADD,AL,35H
AAA;AX=0101H
(2) 格式:AAS
功能:將存放在AL中的二進(jìn)制差數(shù),調(diào)整為ASCII碼表示形式
調(diào)整方法:若AL中低4位小于等于9,僅AL中高4位清0,AF→CF。若AL中低4位大于9或標(biāo)志AF=1,則AL-6→AL,AH-1→AH,1→AF,AF→CF,AL中高4位清0。
AAS指令一般緊跟在SUB,SBB指令之后使用,影響標(biāo)志位為AF,CF。其它標(biāo)志位無定義。
例 3.36
MOV AX,0132H
SUB AL,35H
AAS;AX=0007H
(3) 格式:AAM
功能:將存放在AL中的二進(jìn)制積數(shù),調(diào)整為ASCII碼表示形式。
調(diào)整方法:AL/10商→AH,余數(shù)→AL
AAM指令一般緊跟在MUL指令之后使用,影響標(biāo)志位為SF,ZF,PF。其它標(biāo)志位無定義。
例 3.37
MOV AL,07H
MOV BL,09H
MUL BL;AX=003FH
AAM;AX=0603H
(4) 格式:AAD
功能:將AX中兩位非壓縮BCD碼(一個字節(jié)存放一位BCD碼),轉(zhuǎn)換為二進(jìn)制數(shù)的表示形式。
調(diào)整方法:AH10+AL→AL0→AH
AAD指令用于二進(jìn)制除法DIV操作之前,影響的標(biāo)志位為SF,ZF,PF。其它標(biāo)志位無定義。
例 3.38
MOV AX,0605H
MOV BL,09H
AAD;AX=0041H
DIV BL;AX=0207H
使用該類指令應(yīng)注意,加法、減法和乘法調(diào)整指令都是緊跟在算術(shù)運(yùn)算指令之后,將二進(jìn)制的運(yùn)算結(jié)果調(diào)整為非壓縮BCD碼表示形式,而除法調(diào)整指令必須放在除法指令之前進(jìn)行,以避免除法出現(xiàn)錯誤的結(jié)果。
使用算術(shù)運(yùn)算類指令應(yīng)注意:
·如果沒有特別規(guī)定,參與運(yùn)算的兩個操作數(shù)數(shù)據(jù)類型必須一致,且只允許一個為存儲器操作數(shù);
·如果參與運(yùn)算的操作數(shù)只有一個,且為存儲器操作數(shù),必須使用PTR偽指令說明數(shù)據(jù)類型;
·操作數(shù)不允許為段寄存器。
·目的操作數(shù)不允許為立即數(shù);
·如果是存儲器尋址,則存儲器各種尋址方式均可使用。
3.3.3邏輯運(yùn)算指令
一、邏輯指令
1邏輯與指令
格式:AND DEST,SRC
功能:目的操作數(shù)和源操作數(shù)按位進(jìn)行邏輯與運(yùn)算,結(jié)果存目的操作數(shù)中。源操作數(shù)可以是通用寄存器、存儲器或立即數(shù)。目的操作數(shù)可以是通用寄存器或存儲器操作數(shù)。
例 3.39
AND AL,BL
AND EBX,ECX
AND [DI],1101H
AND指令常用于將操作數(shù)中某位清0(稱屏蔽),只須將要清0的位與0,其它不變的位與1即可。
例 3.40 AND AL,0FH;將AL中高4位清0,低4位保持不變。
AND指令影響標(biāo)志位為SF,ZF,PF,并且使OF=CF=0。
2邏輯或指令
格式:OR DEST,SRC
功能:目的操作數(shù)和源操作數(shù)按位進(jìn)行邏輯或運(yùn)算,結(jié)果存目的操作數(shù)中。源操作數(shù)可以是通用寄存器、存儲器或立即數(shù)。目的操作數(shù)可以是通用寄存器或存儲器操作數(shù)。
例 3.41
OR AX,BX
OR ECX,[EAX]
OR指令常用于將操作數(shù)中某位置1,只須將要置1的位或1,其它不改變的位或0即可。
例 3.42 OR AL,80H;將AL中最高位置1。
OR指令影響標(biāo)志位為SF,ZF,PF。并且使OF=CF=0。
3邏輯異或指令
格式:XOR DEST,SRC
功能:目的操作數(shù)和源操作數(shù)按位進(jìn)行邏輯異或運(yùn)算,結(jié)果送目的操作數(shù)。源操作數(shù)可以是通用寄存器、存儲器或立即數(shù)。目的操作數(shù)可以是通用寄存器或存儲器操作數(shù)。
例 3.43
XOR AX,BX
XOR [BX],1010H
XOR指令常用于將操作數(shù)中某些位取反,只須將要取反的位異或1,其它不改變的位異或0即可。
例 3.44 XOR AL,OFH;將AL中低4位取反,高4位保持不變。
XOR指令影響標(biāo)志位為SF,ZF,PF,并且使OF=CF=0。
4邏輯非指令
格式:NOT DEST
功能:對目的操作數(shù)按位取反,結(jié)果回送目的操作數(shù)。目的操作數(shù)可以為通用寄存器或存儲器。
例 3.45
NOT EAX
NOT BYTE PTR [BX]
NOT指令對標(biāo)志位無影響。
5測試指令
格式:TEST DEST,SRC
功能:目的操作數(shù)和源操作數(shù)按位進(jìn)行邏輯與操作,結(jié)果不回送目的操作數(shù)。源操作數(shù)可以為通用寄存器、存儲器或立即數(shù)。目的操作數(shù)可以為通用寄存器或存儲器操作數(shù)。
例 3.46
TEST DWORD PTR [BX],80000000H
TEST AL,CL
TEST指令常用于測試操作數(shù)中某位是否為1,而且不會影響目的操作數(shù)。如果測試某位的狀態(tài),對某位進(jìn)行邏輯與1的運(yùn)算,其它位邏輯與0,然后判斷標(biāo)志位。運(yùn)算結(jié)果為0,ZF=1,表示被測試位為0;否則ZF=0,表示被測試位為1。
例 3.47 TEST AL,80H;測試AL中最高位
JNZ NEXT;如果最高位為1,轉(zhuǎn)到標(biāo)志NEXT處。
TEST指令影響標(biāo)志位為SF,ZF,PF,并且使OF=CF=0。
二、移位指令
移位指令對操作數(shù)按某種方式左移或右移,移位位數(shù)可以由立即數(shù)直接給出,或由CL間接給出。移位指令分一般移位指令和循環(huán)移位指令。
1一般移位指令
(1) 算術(shù)/邏輯左移指令。
格式:SAL DEST,OPRD
SHL DEST,OPRD
功能:按照操作數(shù)OPRD規(guī)定的移位位數(shù),對目的操作數(shù)進(jìn)行左移操作,最高位移入CF中。每移動一位,右邊補(bǔ)一位0。如圖312(a)所示。目的操作數(shù)可以為通用寄存器或存儲器操作數(shù)。
SAL,SHL指令影響標(biāo)志位OF,SF,ZF,PF,CF。

圖 3.12 移位指令示意圖
例 3.48
SHL BYTE PTR [DI],2
SAL BX,CL
(2) 算術(shù)右移指令。
格式:SAR DEST,OPRD
功能:按照操作數(shù)OPRD規(guī)定的移位次數(shù),對目的操作數(shù)進(jìn)行右移操作,最低位移至CF中,最高位(即符號位)保持不變。如圖312(b)所示。目的操作數(shù)可以為通用寄存器或存儲器操作數(shù)。
SAR指令影響標(biāo)志位OF,SF,ZF,PF,CF。
例 3.49
SAR AL,5
SAR WORD PTR /[ECX/],CL
(3) 邏輯右移指令。
格式:SHR DEST,SRC
功能:按照操作數(shù)OPRD規(guī)定的移位位數(shù),對目的操作數(shù)進(jìn)行右移操作,最低位移至CF中。每移動一位,左邊補(bǔ)一位0。如圖312(c)所示,目的操作數(shù)可以為通用寄存器或存儲器操作數(shù)。
SHR指令影響標(biāo)志位OF,SF,ZF,PF,CF。
例 3.50
SHR BYTE PTR [SI],3
SHR EDX,CL
算術(shù)/邏輯左移,只要結(jié)果未超出目的操作數(shù)所能表達(dá)的范圍,每左移一次相當(dāng)于原數(shù)乘2。算術(shù)右移只要無溢出,每右移一次相當(dāng)于原數(shù)除以2。
2循環(huán)移位指令
格式:ROL DEST,OPRD
ROR DEST,OPRD
RCL DEST,OPRD
RCR DEST,OPRD
功能:循環(huán)左移指令ROL,見圖313(a)所示,目的操作數(shù)左移,每移位一次,其最高位移入最低位,同時最高位也移入進(jìn)位標(biāo)志CF。循環(huán)右移指令 ROR見圖313(b)所示,目的操作數(shù)右移,每移位一次,其最低位移入最高位,同時最低位也移入進(jìn)位標(biāo)志CF。
帶進(jìn)位循環(huán)左移指令RCL,見圖313(c)所示,目的操作數(shù)左移,每移動一次,其最高位移入進(jìn)位標(biāo)志CF,CF移入最低位。帶進(jìn)位循環(huán)右移指令RCR,見圖313(d)所示,目的操作數(shù)右移,每移動一次,其最低位移入進(jìn)位標(biāo)志CF,CF移入最高位。
圖 3.13 循環(huán)移位指令
目的操作數(shù)可以為通用寄存器或存儲器操作數(shù)。循環(huán)移位指令影響標(biāo)志位CF,OF。其它標(biāo)志位無定義。
例 3.51
ROL AL,CL
ROR BX,5
RCL ECX,3
RCR BYTE PTR [SI],CL
例 3.52 將一個2位數(shù)壓縮的BCD碼轉(zhuǎn)換成二進(jìn)制數(shù)。
·MODEL SMALL
·DATA
BCD DB 01011001B
BIN DB?
CODE
·START UP
MOV AL,BCD
MOV BL,AL
AND BL,0FH
AND AL,0F0H
MOV CL,4
ROR AL,CL
MOV BH,0AH
MUL BH
ADD AL,BL
MOV BIN,AL
·EXIT
END
3雙精度移位指令
格式:SHLD DEST,SRC,OPRD
SHRD DEST,SRC,OPRD
功能:對于由目的操作數(shù)DEST和源操作數(shù)SRC構(gòu)成的雙精度數(shù),按照操作數(shù)OPRD給出的移位位數(shù),進(jìn)行移位。SHLD是對目的操作數(shù)進(jìn)行左移,如 圖314(a)所示,SHRD是對目的操作數(shù)進(jìn)行右移,如圖314(b)所示。先移出位送標(biāo)志位CF,另一端空出位由SRC移入DEST中,而SRC 內(nèi)容保持不變。目的操作數(shù)可以是16位或32位通用寄存器或存儲器操作數(shù)。源操作數(shù)SRC允許為16位或32位通用寄存器。操作數(shù)OPRD可以為立即數(shù)或 CL。目的操作數(shù)和源操作數(shù)SRC數(shù)據(jù)類型必須一致。

圖 3.14 雙精度移位指令
SHLD,SHRD指令常用于位串的快速移位、嵌入和刪除等操作,影響標(biāo)志位為SF,ZF,PF,CF,其它標(biāo)志位無定義。
三、位操作指令
位操作指令包括位測試和位掃描指令,可以直接對一個二進(jìn)制位進(jìn)行測試,設(shè)置和掃描。
1位測試和設(shè)置指令
格式:BT DEST,SRC
BTC DEST,SRC
BTR DEST,SRC
BTS DEST,SRC
功能:按照源操作指定的位號,測試目的操作數(shù),當(dāng)指令執(zhí)行時,被測試位的狀態(tài)被復(fù)制到進(jìn)位標(biāo)志CF。
BT將SRC指定的DEST中一位的數(shù)值復(fù)制到CF。BTC將SRC指定的DEST中一位的數(shù)值復(fù)制到CF,且將DEST中該位取反。BTR將SRC 指定的DEST中一位的數(shù)值復(fù)制到CF,且將DEST中該位復(fù)位。BTS將SRC指定的DEST中一位的數(shù)值復(fù)制到CF,且將DEST中該位置位。
目的操作數(shù)為16位或32位通用寄存器或存儲器,源操作數(shù)為16位或32位通用寄存器,以及8位立即數(shù),當(dāng)源操作數(shù)為通用寄存器時,必須同目的操作數(shù)類型一致。源操作數(shù)SRC以兩種方式給出目的操作數(shù)的位號,即
· SRC為8位立即數(shù),以二進(jìn)制形式直接給出要操作的位號;
· SRC為通用寄存器,如果DEST為通用寄存器,則SRC中二進(jìn)制值直接給出要操作的位號。如果DEST為存儲器操作數(shù),通用寄存器SRC為帶符號整數(shù), SRC的值除以DEST的長度所得到的商作為DEST的相對偏移量,余數(shù)直接作為要操作的位號。DEST的有效地址為DEST給出的偏移地址和DEST相 對偏移量之和。
BT,BTC,BTR,BTS指令影響CF標(biāo)志位,其它標(biāo)志位無定義。
例 3.53
MOV AX,1234H
MOV ECX,5
BT AX,CX ??;CF=1AX=1234H
BTC AX,5 ;CF=1;AX=1214H
BTS AX,CX; ;CF=0AX=1234H
BTR EAX,ECX ;CF=1EAX=00001214H
例 3.54
·MODEL SMALL
·586
·DATA
DATA1 DW 1234H,5678H
·CODE
·START UP
BTC DATA1,3;CF=0(DATA1)=123CH
MOV CX,20
BTR DATA1,CX;CF=1[DATA+2]=5668H
·EXIT
END
2位掃描指令
格式:BSFDEST,SRC
BSRDEST,SRC
功能:BSF從低位開始掃描源操作數(shù),若所有位都是0,則ZF=0,否則ZF=1。并且將第一個出現(xiàn)1的位號存入目的操作數(shù)。BSR從高位開始掃描源操作數(shù),若所有位都是0,則ZF=0,否則ZF=1。并且將第一個出現(xiàn)1的位號存入目的操作數(shù)。
源操作數(shù)可以為16位32位通用寄存器或存儲器。目的操作數(shù)為16位或32位通用寄存器。源操作數(shù)和目的操作數(shù)類型必須一致。
BSF,BSR指令影響ZF標(biāo)志位,其它標(biāo)志位無定義。
例 3.55
MOV EBX,0F333EE00H
BSR EAX,EBX;ZF=1EAX=0000001FH=31
BSF EDX,EBX;ZF=1EDX=00000009H
3進(jìn)位標(biāo)志指令
(1) 格式:CLC。功能:清除進(jìn)位標(biāo)志。
(2) 格式:STC。功能:設(shè)置進(jìn)位標(biāo)志。
(3) 格式:CMC。功能:進(jìn)位標(biāo)志取反。
4條件設(shè)置字節(jié)指令
條件設(shè)置指令用于根據(jù)條件設(shè)置某一狀態(tài)字節(jié)或標(biāo)志字節(jié),見表33。
格式:SETcondDEST
功能:測試條件(cond)若為真,則將目的操作數(shù)置01H,否則置00H。目的操作數(shù)允許為8位通用寄存器或8位存儲器操作數(shù)。
條件cond與條件轉(zhuǎn)移指令中的條件相同,共分三類。
(1) 以標(biāo)志位狀態(tài)為條件可以測試的標(biāo)志位為ZF,SF,OF,CF,PF。
(2) 以兩個無符號數(shù)比較為條件條件為高于、高于等于、低于、低于等于。
(3) 以兩個帶符號數(shù)比較為條件條件為大于、大于等于、小于、小于等于。
SET指令不影響標(biāo)志位。
使用邏輯運(yùn)算類指令應(yīng)注意:
· 如果沒有特別規(guī)定,參與運(yùn)算的兩個操作數(shù)類型必須一致,且只允許一個為存儲器操作數(shù);
· 如果參與運(yùn)算的操作數(shù)只有一個,且為存儲器操作數(shù),必須使用PTR偽指令說明其數(shù)據(jù)類型;
· 操作數(shù)不允許為段寄存器;
· 目的操作數(shù)不允許為立即數(shù);
· 如果是存儲器尋址,則前面介紹的各種存儲器尋址方式均可使用。
表 3.3 條件設(shè)置字節(jié)指令

3.3.4控制轉(zhuǎn)移類指令
計算機(jī)執(zhí)行程序一般是順序地逐條執(zhí)行指令。但經(jīng)常須要根據(jù)不同條件做不同的處理,有時需要跳過幾條指令,有時需要重復(fù)執(zhí)行某段程序,或者轉(zhuǎn)移到另一個程序段去執(zhí)行。用于控制程序流程的指令包括轉(zhuǎn)移、循環(huán)、過程調(diào)用和中斷調(diào)用。
一、轉(zhuǎn)移指令
1無條件轉(zhuǎn)移指令
格式:JMP TARGET
功能:使程序無條件地轉(zhuǎn)移到指令規(guī)定的目的地址TARGET去執(zhí)行指令。轉(zhuǎn)移分為短轉(zhuǎn)移、段內(nèi)轉(zhuǎn)移(近程轉(zhuǎn)移)和段間轉(zhuǎn)移(遠(yuǎn)程轉(zhuǎn)移)。
(1) 段內(nèi)直接轉(zhuǎn)移:
格式:JMP SHORT TARGET;短轉(zhuǎn)移
JMP NEAR PTR TARGET;近程轉(zhuǎn)移
功能:采用相對尋址將當(dāng)前IP值(即JMP指令下一條指令的地址)與JMP指令中給出的偏移量之和送IP中。段內(nèi)短轉(zhuǎn)移(SHORT)指令偏移量為8 位,允許轉(zhuǎn)移偏移值的范圍為-128~+127。段內(nèi)近程轉(zhuǎn)移(NEAR)指令在16位指令模式下,偏移量為16位,允許轉(zhuǎn)移偏移值范圍為-215~+ 215-1。在32位指令模式下,偏移值范圍為-231~+231-1。
例 3.56
JMP NEXT

NEXT:MOV AL,BL
本例為無條件轉(zhuǎn)移到本段內(nèi),標(biāo)號為NEXT的地址去執(zhí)行指令,匯編程序可以確定目的地址與JMP指令的距離。
(2) 段內(nèi)間接轉(zhuǎn)移:
格式:JMP REG
JMP NEAR PTR [REG]
功能:段內(nèi)間接轉(zhuǎn)移,其中JMP REG指令地址在通用寄存器中,將其內(nèi)容直接送IP實(shí)現(xiàn)程序轉(zhuǎn)移。JMP NEAR PTR [REG]指令地址在存儲器中,默認(rèn)段寄存器根據(jù)參與尋址的通用寄存器來確定,將指定存儲單元的字取出直接送IP實(shí)現(xiàn)程序轉(zhuǎn)移。在16位指令模式,轉(zhuǎn)移偏 移值范圍為 。在32位指令模式,轉(zhuǎn)移偏移值范圍為 。
例 3.57 設(shè)DS=1000HEBX=00002000H。
JMP BX ?。粚?000H送IP
JMP NEAR PTR [BX] ;將地址1000∶2000單元存放的一個字送IP
JMP NEAR PTR [EBX] ;將段選擇符為1000H,偏移地址為00002000H單元存放的雙字送EIP。
(3) 段間直接轉(zhuǎn)移:
格式:JMP FAR PTR TARGET
功能:段間直接轉(zhuǎn)移,F(xiàn)AR PTR說明標(biāo)號TARGET具有遠(yuǎn)程屬性。將指令中由TARGET指定的段值送CS,偏移地址送IP。
例 3.58 JMP FAR PTR NEXT。
在16位指令模式下,段基地送CS,偏移地址為16位,轉(zhuǎn)移偏移值范圍 ;在32位指令模式下,代碼段選擇符送CS,偏移地址為32位,轉(zhuǎn)移偏移值范圍為 。
(4) 段間間接轉(zhuǎn)移:
格式:JMP FAR PTR [Reg]
功能:段間間接轉(zhuǎn)移,由FAR PTR [Reg]指定的存儲器操作數(shù)作為轉(zhuǎn)移地址。
在16位指令模式下,存儲器操作數(shù)為32位,包括16位段基址和16位偏移地址。
例 3.59
JMP FAR PTR [BX] ?。粩?shù)據(jù)段雙字存儲單元低字內(nèi)容送IP
??;數(shù)據(jù)段雙字存儲單元高字內(nèi)容送CS
在32位指令模式下,存儲器操作數(shù)包括16位選擇符。
例 3.60 JMP FAR PTR [EAX]
指令中包含指向目標(biāo)地址指針的門描述符或TSS描述符的指針,其所指的存儲器操作數(shù)中僅選擇符部分有效,指示調(diào)用門、任務(wù)門或TSS描述符起作用,而偏移部分不起作用。
2條件轉(zhuǎn)移指令
該類指令是根據(jù)上一條指令對標(biāo)志寄存器中標(biāo)志位的影響來決定程序執(zhí)行的流程,若滿足指令規(guī)定的條件,則程序轉(zhuǎn)移;否則程序順序執(zhí)行。
條件轉(zhuǎn)移指令的轉(zhuǎn)移范圍為段內(nèi)短轉(zhuǎn)移或段內(nèi)近程轉(zhuǎn)移,不允許段間轉(zhuǎn)移。段內(nèi)短轉(zhuǎn)移(short)的轉(zhuǎn)移偏移值范圍為-128~+127。段內(nèi)近程轉(zhuǎn)移,在16位指令模式下轉(zhuǎn)移偏移值范圍為 ,在32位指令模式下轉(zhuǎn)移偏移值范圍為 。
條件轉(zhuǎn)移指令包括四類:單標(biāo)志位條件轉(zhuǎn)移;無符號數(shù)比較條件轉(zhuǎn)移;帶符號數(shù)比較條件轉(zhuǎn)移;測試CX條件轉(zhuǎn)移。
格式:Jcc TARGET
功能:若測試條件‘CC’為真,則轉(zhuǎn)移到目標(biāo)地址TARGET處執(zhí)行程序。否則順序執(zhí)行。
(1) 單標(biāo)志位條件轉(zhuǎn)移指令,見表34。
例 3.61 JZ NEXT;若標(biāo)志ZF=1則轉(zhuǎn)移到標(biāo)號NEXT處執(zhí)行。
(2) 無符號數(shù)比較條件轉(zhuǎn)移,見表35。
例 3.62 JA NEXT;無符號數(shù)A與B比較,若A>B則轉(zhuǎn)移到標(biāo)號NEXT處執(zhí)行程序
表 3.4 單標(biāo)志位條件轉(zhuǎn)移指令

表 3.5 無符號數(shù)比較條件轉(zhuǎn)移指令

表 3.6 帶符號數(shù)比較條件轉(zhuǎn)移指令

例 3.63 JG NEXT;帶符號數(shù)A與B比較,若A>B則轉(zhuǎn)移到標(biāo)號NEXT。
(4) 測試CX條件轉(zhuǎn)移,見表37。
表 3.7 測試CX條件轉(zhuǎn)移指令

例 3.64 JCXZ TARGET;CX=0轉(zhuǎn)移到標(biāo)號TARGET處。
JECXZ TARGET;ECX=0轉(zhuǎn)移到標(biāo)號TARGET處。
條件轉(zhuǎn)移指令一般緊跟在CMP或TEST指令之后,判斷執(zhí)行CMP或TEST指令對標(biāo)志位的影響來決定是否轉(zhuǎn)移。
例 3.65 符號函數(shù)

假設(shè)x為某值且存放在寄存器AL中,試編程將求出的函數(shù)值f(x)存放在AH中。
·MODEL TINY
·CODE
·STARTUP
CMPAL,0
JGE BIG
MOV AL,0FFH
JMP DONE
BIG: JE DONE
MOV AL,1
DONE:MOV AH,AL
·EXIT
END
例 3.66 編程實(shí)現(xiàn)把BX寄存器內(nèi)的二進(jìn)制數(shù)用十六進(jìn)制數(shù)的形式在屏幕上顯示出來。
·MODEL TINY
·CODE
·STARTUP
MOV CH,4
AGAIN: MOV CL,4
ROL BX,CL
MOV AL,BL
ANDAL,0FH
OR AL,30H
CMP AL,3AH
JB NEXT
ADD AL,07H
NEXT: MOV DL,AL;DL←要顯示的ASCII碼
MOV AH,2;顯示
INT 21H
DECCH
JNZ AGAIN
·EXIT
END
二、循環(huán)控制指令
這類指令用(E)CX計數(shù)器中的內(nèi)容控制循環(huán)次數(shù),先將循環(huán)計數(shù)值存放在(E)CX中,每循環(huán)一次(E)CX內(nèi)容減1,直到(E)CX為0時循環(huán)結(jié)束。
格式:LOOPcc TARGET
功能:將(E)CX內(nèi)容減1,不影響標(biāo)志位,若(E)CX不等于0,且測試條件‘CC’成立,則轉(zhuǎn)移到目標(biāo)地址TARGET處執(zhí)行程序。轉(zhuǎn)移范圍為-128~+127。如表38所示。
表3.8 循環(huán)控制指令

例 3.67 計算
·MODEL TINY
·CODE
·STARTUP
XOR EAX,EAX
MOV EDX,1
MOV ECX,1000
SUM: ADD EAX,EDX
INC EDX
LOOPD SUM
·EXIT
END
例 3.68 找出以ARRAY為首地址的100個字?jǐn)?shù)組中的第一個非0項,送AX寄存器中。
·MODELSMALL
·DATA
ARRAYDW 0,0,0,0,1010H,…;(100個字)
·CODE
·STARTUP
MOV CX,64H
LEA BX,ARRAY
MOV SI,0FFFEH
ZERO: INC SI
INC SI
CMP WORD PTR [BX+SI],0
LOOPZ ZERO
MOV AX,[BX+SI]
·EXIT
END
關(guān)于過程調(diào)用和返回指令將在子程序一節(jié)中介紹。
3.3.5串操作指令
80x86提供處理字符串的操作。串指連續(xù)存放在存儲器中的一些數(shù)據(jù)字節(jié)、字或雙字。串操作允許程序?qū)B續(xù)存放大的數(shù)據(jù)塊進(jìn)行操作。
串操作通常以DS:(E)SI來尋址源串,以ES:(E)DI來尋址目的串,對于源串允許段超越。(E)SI或(E)DI這兩個地址指針在每次串操作 后,都自動進(jìn)行修改,以指向串中下一個串元素。地址指針修改是增量還是減量由方向標(biāo)志來規(guī)定。當(dāng)DF=0,(E)SI及(E)DI的修改為增量;當(dāng)DF= 1,(E)SI及(E)DI的修改為減量。根據(jù)串元素類型不同,地址指針增減量也不同,在串操作時,字節(jié)類型SI,DI加、減1;字類型SI,DI加、減 2;雙字類型ESI,EDI加、減4。如果需要連續(xù)進(jìn)行串操作,通常加重復(fù)前綴。重復(fù)前綴可以和任何串操作指令組合,形成復(fù)合指令,見表39。
一、重復(fù)前綴指令
表 3.9 重復(fù)前綴指令

二、方向標(biāo)志指令
格式:CLD/STD
功能:CLD為清除方向標(biāo)志,即將DF置‘0’。STD為設(shè)置方向標(biāo)志,即將DF置‘1’。
三、串傳送指令
基本格式:[REP]MOVS DESTS, SRCS
[REP] MOVSB/MOVSW/MOVSD
功能:將DS:(E)SI規(guī)定的源串元素復(fù)制到ES:(E)DI規(guī)定的目的串單元中,見表310。
表 3.10 MOVS指令

該指令對標(biāo)志位無影響。
如果加重復(fù)前綴REP,則可以實(shí)現(xiàn)連續(xù)存放的數(shù)據(jù)塊的傳送,直到(E)CX=0為止。
在16位指令模式下,使用SI,DI,CX寄存器;在32位指令模式下,使用ESI,EDI,ECX寄存器。
例 3.69
·MODEL SMALL
·DATA
SRC DB 1,2,3,…(100個字節(jié))
DEST DB 100DUP(?)
·CODE
·STARTUP
MOV AX,@DATA
MOV ES,AX
MOV CX,100
LEA SI,SRC
LEA DI,DEST
CLD
REP MOVSB
·EXIT
END
該程序?qū)⑵鹗嫉刂窞镾RC的100個字節(jié)內(nèi)容傳送到起始地址為DEST的存儲單元。
四、串比較指令
基本格式:[REPE/Z] [REPNZ/NE] CMPS DESTS, SRCS
[REPE/Z] [REPNZ/NE] CMPSB/CMPSW/CMPSD
功能:由DS:(E)SI規(guī)定的源串元素減去ES:(E)DI指出的目的串元素,結(jié)果不回送,僅影響標(biāo)志位CF,AF,PF,OF,ZF,SF。當(dāng)源 串元素與目的串元素值相同時,ZF=1;否則ZF=0。每執(zhí)行一次串比較指令,根據(jù)DF的值和串元素數(shù)據(jù)類型自動修改(E)SI和(E)DI。
在串比較指令前加重復(fù)前綴REPE/Z,則表示重復(fù)比較兩個字符串,若兩個字符串的元素相同則比較到(E)CX=0為止,否則結(jié)束比較。在串比較指令 前加重復(fù)前綴REPNE/NZ,則表示若兩個字符串元素不相同時,重復(fù)比較直到(E)CX=0為止,否則結(jié)束比較。
例 3.70 編程實(shí)現(xiàn)兩個串元素比較,如相同則將全“1”送SUT單元,否則全“0”送SUT單元。
·MODEL SMALL
·DATA
DEST DB ‘A B C D E F G H’
SRC DB ‘A B C E F F F E’
SUT DB?
·CODE
·STARTUP
MOV AX,@DATA
MOV ES,AX
MOV CX,8
LEA SI,DEST
LEA DI,SRC
CLD
REPE CMPSB
JZ EQUL;ZF=1;CX=0
MOV BH,0;CX≠0,ZF=0
JMP DONE
EQUL: MOV BH,0FFH
DONE: MOV SUT,BH
·EXIT
END
五、串掃描指令
格式①: [REPE/Z] [REPNE/NZ] SCAS DESTS
格式②: [REPE/Z] [REPNE/NZ] SCASB/SCASW/SCASD
功能:由AL,AX或EAX的內(nèi)容減去ES:(E)DI規(guī)定的目的串元素,結(jié)果不回送,僅影響標(biāo)志位CF,AF,PF,SF,OF,ZF。當(dāng)AL, AX或EAX的值與目的串元素值相同時,ZF=1;否則ZF=0。每執(zhí)行一次串掃描指令,根據(jù)DF的值和串元素數(shù)據(jù)類型自動修改(E)DI。
在串掃描指令前加重復(fù)前綴REPE/Z,則表示目的串元素值和累加器值相同時重復(fù)掃描,直到CX/ECX=0為止,否則結(jié)束掃描。若加重復(fù)前綴 REPNE/NZ,則表示當(dāng)目的串元素值與累加器值不相等時,重復(fù)掃描直到CX/ECX=0時為止,否則結(jié)束掃描。
該指令影響標(biāo)志位為CF,AF,PF,SF,OF,ZF。
例 3.71 在內(nèi)存DEST開始的6個單元尋找字符‘C’,如找到將字符‘C’的地址送ADDR單元,否則0送ADDR單元。
·MODEL SMALL
·DATA
DEST DB ‘A B C D E F’
ADDR DW?;存“C”的地址,所以設(shè)置為字類型
·CODE
·STARTUP
MOV AX,@DATA
MOV ES,AX
MOV CX,6
LEA DI,DEST
MOV AL,‘C’
CLD
REPNE SCASB
JZ EQUL
MOV DI,0
JMP DONE
EQUL: DEC DI
DONE: MOV ADDR,DI
·EXIT
END
六、 串裝入指令
格式:LODS SRCS
LODSB/LODSW/LODSD
功能:將DS:SI/ESI所指的源串元素裝入累加器(AL,AX,EAX)中,每裝入一次都按照DF值以及串元素類型自動修改地址指針SI/ESI,該指令一般不須加重復(fù)前綴,并且不影響標(biāo)志位。
七、 串存儲指令
格式:[REP] STOS DESTS
[REP] STOSB/STOSW/STOSD
功能:將累加器/[AL,AX,EAX/]中值存入ES:DI/EDI所指的目的串存儲單元中,每傳遞一次,都按DF值以及串元素類型自動修改地址指 針DI/EDI。若加重復(fù)前綴REP,則表示將累加器的值連續(xù)送目的串存儲單元,直到CX/ECX=0時為止。
該指令不影響標(biāo)志位。
3.3.6輸入/輸出指令
一、 輸入指令
格式:IN DEST, SRC
功能:根據(jù)源操作數(shù)SRC給出的端口地址,將操作數(shù)從指定端口傳送到目的操作數(shù)DEST處,其中DEST為AL,AX或EAX,端口地址SRC可以直接形式給出8位端口地址,或由DX寄存器以間接形式給出。
例 3.72
IN AL,10H
IN AX,20H
IN EAX,30H
IN AL,DX
IN AX,DX
IN EAX,DX
二、 輸出指令
格式OUT DEST, SRC
功能:將源操作數(shù)SRC送到目的操作數(shù)DEST所指定的端口。其中源操作數(shù)SRC為AL,AX或EAX,目的操作數(shù)可以8位端口地址方式直接給出或以DX寄存器間接方式給出。
使用輸入、輸出指令應(yīng)注意:
· 直接尋址方式端口地址為8位,共有0~255個端口地址;
· 間接尋址方式,只能用DX作為地址寄存器,尋址范圍為64K字節(jié);
· 每個I/O地址對應(yīng)的端口的數(shù)據(jù)長度為8位,傳送8位數(shù)據(jù)占用一個端口地址,傳送16位數(shù)據(jù)占用2個端口地址,傳送32位數(shù)據(jù)占用4個端口地址。
三、 串輸入指令
格式:[REP] INS DESTS, DX
[REP] INSB/INSW/INSD
功能:根據(jù)DX給出的端口地址,從外設(shè)讀入數(shù)據(jù)送入以ES:DI/EDI為地址的目的串存儲單元中,每輸入一次,均根據(jù)DF的值和串元素類型自動修改 DI/EDI的值。若加重復(fù)前綴REP,則表示連續(xù)從外設(shè)輸入串元素存入目的串存儲單元中,直到CX/ECX=0為止。
例 3.73 從端口地址為1000H處取數(shù)存入內(nèi)存BLOCK單元。
·MODEL SMALL
·DATA
BLOCKDB?
·CODE
·STARTUP
MOV AX,@DATA
MOV ES,AX
CLD
LEA DI,BLOCK
MOV DX,1000H
INS BLOCK,DX
·EXIT
END
四、串輸出指令
格式:[REP] OUTS DX,SRCS
[REP] OUTSB/OUTSW/OUTSD
功能:將DS:SI/ESI所指的源串元素,按照DX寄存器指定的端口地址送往外設(shè),每輸出一次,均根據(jù)DF的值和串元素類型自動修改SI/ESI的值,若加重復(fù)前綴REP,則表示連續(xù)向外設(shè)輸出串元素,直到CX/ECX=0時為止。
例 3.74 將內(nèi)存BLOCK為首地址的100個字符送往端口地址為2000H的外設(shè)。
·MODEL SMALL
·DATA
BLOCKDB ‘A,B,…’(100個字符)
·CODE
·STARTUP
CLD
LEA SI,BLOCK
MOV CX,100
MOV DX,2000H
REP OUTSB
·EXIT
END
在使用帶重復(fù)前綴的串輸入輸出指令時,必須考慮端口的數(shù)據(jù)準(zhǔn)備或接收狀態(tài)。
所有輸入輸出指令均不影響標(biāo)志位。
3.3.7處理器控制
一、 總線封鎖前綴
格式:LOCK指令
功能:LOCK為指令前綴,可以使LOCK引腳變成邏輯0,在LOCK引腳有效期間,禁止外部總線上的其它處理器存取帶有LOCK前綴指令的存儲器操作數(shù)。
可加LOCK前綴的指令:
(1) ADD/SUB/ADC/SBB/OR/XOR/AND Mem, Reg/imm;
(2) NOT/NEG/INC/NEC Mem;
(3) XCHG Reg, Mem或XCHG Mem, Reg;
(4) BT/BTS/BRT/BTC Mem, Reg/imm。
Mem為存儲器操作數(shù),Reg為通用寄存器,imm為立即數(shù)。
二、空操作
格式:NOP
功能:空操作,除使IP/EIP增1外,不做任何工作。該指令不影響標(biāo)志位。
三、處理器等待指令
格式:WAIT
功能:檢查BUSY引腳狀態(tài),等待協(xié)處理器完成當(dāng)前工作。
四、處理器暫停指令
格式:HLT
功能:暫停程序的執(zhí)行。當(dāng)產(chǎn)生一個外部中斷或非屏蔽中斷時,才繼續(xù)執(zhí)行下一條指令。
3.3.8中斷指令與DOS功能調(diào)用
一、中斷指令
在實(shí)模式下,中斷矢量以4個字節(jié)存放在中斷矢量表中,中斷矢量表為1k字節(jié)(00000H~003FFH),中斷矢量表允許存放256個中斷矢量,每 個中斷矢量包含一個中斷服務(wù)程序地址(段值和16位偏移地址),中斷矢量地址指針由中斷類型碼乘以4得到。
在保護(hù)模式下,用中斷描述符表代替中斷矢量表,每個中斷由8個字節(jié)的中斷描述符來說明,中斷描述符表允許256個中斷描述符,每個中斷描述符包含一個中斷服務(wù)地址(段選擇符、32位偏移地址、訪問權(quán)限等)。中斷描述符地址指針由中斷類型碼乘以8得到。
中斷指令格式:INT n
功能:產(chǎn)生中斷類型碼為n的軟中斷,該指令包含中斷操作碼和中斷類型碼兩部分,中斷類型碼n為8位,取值范圍為0~255(00H~FFH)。
軟中斷執(zhí)行過程:
· 將標(biāo)志寄存器FLAGS(或EFLAGS)壓入堆棧;
· 清除TF和IF標(biāo)志位;
· CS,IP/EIP壓入堆棧;
· 實(shí)模式下,n×4獲取中斷矢量表地址指針;保護(hù)模式下,n×8獲取中斷描述符表地址指針;
· 根據(jù)地址指針,從中斷矢量表或中斷描述符表中取出中斷服務(wù)程序地址送IP/EIP和CS中,控制程序轉(zhuǎn)移去執(zhí)行中斷服務(wù)程序。
中斷返回指令格式:IRET/IRETD
功能:該指令實(shí)現(xiàn)在中斷服務(wù)程序結(jié)束后,返回到主程序中斷斷點(diǎn)處,繼續(xù)執(zhí)行主程序。
中斷返回執(zhí)行過程:
· IRET指令彈出堆棧中數(shù)據(jù)送IP,CS,F(xiàn)LAGS;
· IRETD指令彈出堆棧中數(shù)據(jù)送EIP,CS,EFLAGS。
其它中斷類指令如表311所示。
表 3.11 中斷類指令

二、DOS功能調(diào)用
系統(tǒng)功能調(diào)用是MS—DOS為程序員編寫匯編語言源程序提供的一組子程序,包括設(shè)備管理、文件管理和目錄管理等。
DOS規(guī)定使用軟中斷指令I(lǐng)NT 21H作為進(jìn)入各功能子程序的總?cè)肟?,再為每個功能調(diào)用規(guī)定一個功能號,引用功能號即可進(jìn)入相應(yīng)的子程序入口。DOS系統(tǒng)功能調(diào)用的使用方法歸納如下:
(1) 傳送入口參數(shù)到指定的寄存器中;
(2) 把要調(diào)用功能的功能號送入AH寄存器中;
(3) 用INT 21H指令轉(zhuǎn)入子程序入口;
(4) 相應(yīng)的子程序運(yùn)行結(jié)束后,可以按照規(guī)定取得出口參數(shù)。
常用系統(tǒng)功能調(diào)用簡介。
1鍵盤輸入單字符
這是1號系統(tǒng)功能調(diào)用,其調(diào)用格式為
MOV AH,1
INT 21H
該功能調(diào)用無入口參數(shù)。其功能為系統(tǒng)等待鍵盤輸入,如是Ctrol-Break鍵則退出;否則將鍵入字符的ASCII碼送入AL寄存器中,并且通過顯示器顯示該字符。
2鍵盤輸入字符串
這是0AH號系統(tǒng)功能調(diào)用,其功能為將鍵盤輸入的字符串寫入內(nèi)存單元中。因此,首先在內(nèi)存中定義一個緩沖區(qū),緩沖區(qū)第一個字節(jié)存放規(guī)定字符串的最大字 節(jié)數(shù),第二個字節(jié)由系統(tǒng)送入實(shí)際鍵入的字符數(shù),從第三個字節(jié)開始用于存放鍵入的字符串,最后通過鍵入回車鍵來表示字符串的結(jié)束。如果實(shí)際鍵入的字符數(shù)未達(dá) 到最大規(guī)定數(shù),其緩沖區(qū)的空余區(qū)間填0;如果實(shí)際鍵入數(shù)超過緩沖區(qū)的容量,則超出的字符自動丟失,而且響鈴警告。注意,回車鍵值也存于緩沖區(qū)中。
例 3.75 使用格式舉例。
·MODEL SMALL
·DATA
BUF DB 20
DB?
DB 20 DUP(?)
·CODE
·STARTUP
MOV DX,OFFSET BUF
MOV AH,0AH
INT 21H
·EXIT
END
該程序在BUF為首地址的緩沖區(qū)定義了20個字符串字節(jié)的緩沖區(qū),并且將緩沖區(qū)首地址送入DX中,調(diào)用0AH號子程序,系統(tǒng)等待用戶鍵入字符串,每鍵 入一個字符,其相應(yīng)的ASCII碼將被寫入緩沖區(qū)中,直到鍵入回車鍵,由系統(tǒng)輸入實(shí)際鍵入字符數(shù),送入緩沖區(qū)第二個字節(jié)中。
3輸出單字符
這是2號系統(tǒng)功能調(diào)用,其使用格式為:
MOV DL,‘A’
MOV AH,2
INT 21H
執(zhí)行2號系統(tǒng)功能調(diào)用,將置入DL寄存器中的字符(以ASCII碼形式表示)通過顯示器顯示出來(或從打印機(jī)輸出)。
4輸出字符串
這是9號系統(tǒng)功能調(diào)用,其功能是將指定的內(nèi)存緩沖區(qū)中的字符串從顯示器顯示輸出(或從打印機(jī)輸出),緩沖區(qū)中的字符串以字符‘$’作為結(jié)束標(biāo)志。
例 3.76使用格式舉例。
·MODEL SMALL
·DATA
BUF DB ‘Thank you $’
·CODE
·STARTUP
MOV DX,OFFSET BUF
MOV AH,9
INT 21H
·EXIT
END
5返回操作系統(tǒng)
這是4CH號系統(tǒng)功能調(diào)用,使用格式為
MOV AH,4CH
INT 21H
在用戶程序結(jié)束處插入此調(diào)用,則返回到DOS操作系統(tǒng),顯示器顯示系統(tǒng)提示符。
習(xí)題與思考題
1數(shù)據(jù)尋址方式有哪幾種?
216位指令模式下和32位指令模式下的存儲器尋址方式各有哪幾種尋址方式?并比較它們相似與不同之處。
3程序地址尋址方式有哪幾種?
4什么是堆棧地址尋址方式?
5指令編碼格式是由哪幾部分組成的?各部分的含義是什么?
6 80x86的指令格式由哪幾部分組成?
7 80x86指令系統(tǒng)按其功能可分為幾部分?
8數(shù)據(jù)傳送指令包括哪些類型?
9堆棧的含義是什么?80x86所用的堆棧有什么特點(diǎn)?
10堆棧操作指令有哪幾種?
11 XLAT指令在使用時有哪些規(guī)定?
12符號擴(kuò)展指令在什么情況下使用?
13十進(jìn)制算術(shù)運(yùn)算調(diào)整指令在什么情況下使用?它們都是跟在哪些指令的后面?
14哪些指令采用隱含尋址?
15使用算術(shù)運(yùn)算類指令應(yīng)注意哪些問題?
16邏輯運(yùn)算指令有幾種?
17測試指令和比較指令在使用時有什么不同?
18算術(shù)移位指令和邏輯移位指令有什么不同?
19控制轉(zhuǎn)移類指令的作用是什么?有哪幾種?
20什么叫串?串操作指令有哪些?串前綴在什么情況下使用?
21輸入/輸出指令起什么作用?尋址方式有哪些?
22設(shè)DS=2000H,SS=3000H,BP=0200H,SI=4000H,BUF=1000H,EAX=00001000H,EBX= 00002000H,假設(shè)按16位實(shí)模式操作,確定下列每條指令訪問內(nèi)存的物理地址,并且指出源操作數(shù)及目的操作數(shù)的尋址方式。
(1) MOV AL,[1234H](2) MOV EDX,[BX]
(3) MOV CL,[BX+100H](4) MOV [SI],EBX
(5) MOV AH,BUF[BX+SI](6) MOV EAX,[BP+1234H]
(7) MOV [EAX+EBX],DH
23試指出下列指令中的錯誤。
(1) MOV [BX],[SI](2) MOV AH,DX
(3) INC [BX](4) MOV DS,SS
(5) XCHG AX,2000H(6) MOV AX,[BX+DX]
(7) XCHG [SP],ES(8) ADD [AX],BX
(9) MOV AX,DI+SI(10) INAL,BX
24指出下列算術(shù)邏輯指令執(zhí)行后標(biāo)志CF,ZF,SF,PF,OF和AF的狀態(tài)。
MOV AL,80H
DEC AL
ADD AL,10H
SUB AL,10H
MOV AL,3AH
AND AL,0F0H
OR AL,0F0H
XOR AL,0F0H
25使AX寄存器清0有多種方式,試寫出這多條指令。
26寫出把首地址為BUF的字節(jié)緩沖區(qū)中第5個字節(jié)數(shù)送AL寄存器的指令,要求使用以下幾種尋址方式:
(1) 寄存器間接尋址;
(2) 寄存器相對尋址;
(3) 基址變址尋址。
27試分別使用數(shù)據(jù)傳送指令、交換指令和堆棧操作指令,實(shí)現(xiàn)將首地址為BLOCK的內(nèi)存單元中兩個數(shù)據(jù)字交換。BLOCK變量定義如下:
BLOCK DW 10H,20H
28設(shè)一個字節(jié)數(shù)據(jù)X存放在AL寄存器中,試說明下列程序的功能。
XOR AH,AH
SAL AX,1
MOV BX,AX
MOV CL,2
SAL AX,CL
ADD AX,BX
29試編程實(shí)現(xiàn):
(1) AL寄存器的低4位清0;
(2) BL寄存器的低4位置1;
(3) CL寄存器的低4位取反;
(4) 測試DL寄存器的最低2位是否為0,若是將0送入AL寄存器;否則將1送AL寄存器。
30試編程統(tǒng)計在AX寄存器中有多少個1,并將結(jié)果送DL寄存器中。
31試編程統(tǒng)計在內(nèi)存BLOCK單元開始按字節(jié)存放的100個帶符號數(shù)中有多少負(fù)數(shù),并將結(jié)果存放在DL寄存器中。
================================================================
32位CPU所含有的寄存器有:
4個數(shù)據(jù)寄存器(EAX、EBX、ECX和EDX)
2個變址和指針寄存器(ESI和EDI) 2個指針寄存器(ESP和EBP)
6個段寄存器(ES、CS、SS、DS、FS和GS)
1個指令指針寄存器(EIP) 1個標(biāo)志寄存器(EFlags)
1、數(shù)據(jù)寄存器
數(shù)據(jù)寄存器主要用來保存操作數(shù)和運(yùn)算結(jié)果等信息,從而節(jié)省讀取操作數(shù)所需占用總線和訪問存儲器的時間。
32位CPU有4個32位的通用寄存器EAX、EBX、ECX和EDX。對低16位數(shù)據(jù)的存取,不會影響高16位的數(shù)據(jù)。這些
低16位寄存器分別命名為:AX、BX、CX和DX,它和先前的CPU中的寄存器相一致。
4個16位寄存器又可分割成8個獨(dú)立的8位寄存器(AX:AH-AL、BX:BH-BL、CX:CH-CL、DX:DH-DL),每個寄
存器都有自己的名稱,可獨(dú)立存取。程序員可利用數(shù)據(jù)寄存器的這種“可分可合”的特性,靈活地處理字/字
節(jié)的信息。
AX和AL通常稱為累加器(Accumulator):可用于乘、除、輸入/輸出等操作(在乘除指令中指定用來存放操作數(shù))
BX稱為基地址寄存器(Base Register):在計算存儲器地址時,可作為基址寄存器使用。
CX稱為計數(shù)寄存器(Count Register):用來保存計數(shù)值,如在移位指令、循環(huán)指令和串處理指令中用作隱含的計數(shù)器(當(dāng)移多位時,要用CL來指明移位的位數(shù))。DX在作雙字長運(yùn)算時,可把DX和AX組合在一起存放一個雙字長數(shù),DX用來存放高16位數(shù)據(jù)。此外,對某些I/O操作,DX可用來存放I/O的端口地址。
DX稱為數(shù)據(jù)寄存器(Data Register)。在進(jìn)行乘、除運(yùn)算時,它可作為默認(rèn)的操作數(shù)參與運(yùn)算,也可用于存放I/O的端口地址。
在16位CPU中,AX、BX、CX和DX不能作為基址和變址寄存器來存放存儲單元的地址,但在32位CPU中,其32位
寄存器EAX、EBX、ECX和EDX不僅可傳送數(shù)據(jù)、暫存數(shù)據(jù)保存算術(shù)邏輯運(yùn)算結(jié)果,而且也可作為指針寄存器,
所以,這些32位寄存器更具有通用性。
2、變址寄存器
32位CPU有2個32位通用寄存器ESI和EDI。其低16位對應(yīng)先前CPU中的SI和DI,對低16位數(shù)據(jù)的存取,不影響
高16位的數(shù)據(jù)。
寄存器ESI、EDI、SI和DI稱為變址寄存器(Index Register),它們主要用于存放存儲單元在段內(nèi)的偏移量,
用它們可實(shí)現(xiàn)多種存儲器操作數(shù)的尋址方式,為以不同的地址形式訪問存儲單元提供方便。
變址寄存器不可分割成8位寄存器。作為通用寄存器,也可存儲算術(shù)邏輯運(yùn)算的操作數(shù)和運(yùn)算結(jié)果。
它們可作一般的存儲器指針使用。在字符串操作指令的執(zhí)行過程中,對它們有特定的要求,而且還具有特
殊的功能。
3、指針寄存器
32位CPU有2個32位通用寄存器EBP和ESP。其低16位對應(yīng)先前CPU中的SBP和SP,對低16位數(shù)據(jù)的存取,不影
響高16位的數(shù)據(jù)。
寄存器EBP、ESP、BP和SP稱為指針寄存器(Pointer Register),主要用于存放堆棧內(nèi)存儲單元的偏移量,
用它們可實(shí)現(xiàn)多種存儲器操作數(shù)的尋址方式,為以不同的地址形式訪問存儲單元提供方便。
指針寄存器不可分割成8位寄存器。作為通用寄存器,也可存儲算術(shù)邏輯運(yùn)算的操作數(shù)和運(yùn)算結(jié)果。
它們主要用于訪問堆棧內(nèi)的存儲單元,并且規(guī)定:
BP為基指針(Base Pointer)寄存器,用它可直接存取堆棧中的數(shù)據(jù);
SP為堆棧指針(Stack Pointer)寄存器,用它只可訪問棧頂。
4、段寄存器
段寄存器是根據(jù)內(nèi)存分段的管理模式而設(shè)置的。內(nèi)存單元的物理地址由段寄存器的值和一個偏移量組合而成
的,這樣可用兩個較少位數(shù)的值組合成一個可訪問較大物理空間的內(nèi)存地址。
CPU內(nèi)部的段寄存器:
CS——代碼段寄存器(Code Segment Register),其值為代碼段的段值;
DS——數(shù)據(jù)段寄存器(Data Segment Register),其值為數(shù)據(jù)段的段值;
ES——附加段寄存器(Extra Segment Register),其值為附加數(shù)據(jù)段的段值;
SS——堆棧段寄存器(Stack Segment Register),其值為堆棧段的段值;
FS——附加段寄存器(Extra Segment Register),其值為附加數(shù)據(jù)段的段值;
GS——附加段寄存器(Extra Segment Register),其值為附加數(shù)據(jù)段的段值。
在16位CPU系統(tǒng)中,它只有4個段寄存器,所以,程序在任何時刻至多有4個正在使用的段可直接訪問;在32位
微機(jī)系統(tǒng)中,它有6個段寄存器,所以,在此環(huán)境下開發(fā)的程序最多可同時訪問6個段。
32位CPU有兩個不同的工作方式:實(shí)方式和保護(hù)方式。在每種方式下,段寄存器的作用是不同的。有關(guān)規(guī)定簡
單描述如下:
實(shí)方式: 前4個段寄存器CS、DS、ES和SS與先前CPU中的所對應(yīng)的段寄存器的含義完全一致,內(nèi)存單元的邏輯
地址仍為“段值:偏移量”的形式。為訪問某內(nèi)存段內(nèi)的數(shù)據(jù),必須使用該段寄存器和存儲單元的偏移量。
保護(hù)方式: 在此方式下,情況要復(fù)雜得多,裝入段寄存器的不再是段值,而是稱為“選擇子”(Selector)的某個值。。
5、指令指針寄存器
32位CPU把指令指針擴(kuò)展到32位,并記作EIP,EIP的低16位與先前CPU中的IP作用相同。
指令指針EIP、IP(Instruction Pointer)是存放下次將要執(zhí)行的指令在代碼段的偏移量。在具有預(yù)取指令功
能的系統(tǒng)中,下次要執(zhí)行的指令通常已被預(yù)取到指令隊列中,除非發(fā)生轉(zhuǎn)移情況。所以,在理解它們的功能
時,不考慮存在指令隊列的情況。
在實(shí)方式下,由于每個段的最大范圍為64K,所以,EIP中的高16位肯定都為0,此時,相當(dāng)于只用其低16位
的IP來反映程序中指令的執(zhí)行次序。
6、標(biāo)志寄存器
一、運(yùn)算結(jié)果標(biāo)志位
1、進(jìn)位標(biāo)志CF(Carry Flag)
進(jìn)位標(biāo)志CF主要用來反映運(yùn)算是否產(chǎn)生進(jìn)位或借位。如果運(yùn)算結(jié)果的最高位產(chǎn)生了一個進(jìn)位或借位,那么,其值為1,否則其值為0。
使用該標(biāo)志位的情況有:多字(字節(jié))數(shù)的加減運(yùn)算,無符號數(shù)的大小比較運(yùn)算,移位操作,字(字節(jié))之間移位,專門改變CF值的指令等。
2、奇偶標(biāo)志PF(Parity Flag)
奇偶標(biāo)志PF用于反映運(yùn)算結(jié)果中“1”的個數(shù)的奇偶性。如果“1”的個數(shù)為偶數(shù),則PF的值為1,否則其值為0。
利用PF可進(jìn)行奇偶校驗(yàn)檢查,或產(chǎn)生奇偶校驗(yàn)位。在數(shù)據(jù)傳送過程中,為了提供傳送的可靠性,如果采用奇偶校驗(yàn)的方法,就可使用該標(biāo)志位。
3、輔助進(jìn)位標(biāo)志AF(Auxiliary Carry Flag)
在發(fā)生下列情況時,輔助進(jìn)位標(biāo)志AF的值被置為1,否則其值為0:
(1)、在字操作時,發(fā)生低字節(jié)向高字節(jié)進(jìn)位或借位時;
(2)、在字節(jié)操作時,發(fā)生低4位向高4位進(jìn)位或借位時。
對以上6個運(yùn)算結(jié)果標(biāo)志位,在一般編程情況下,標(biāo)志位CF、ZF、SF和OF的使用頻率較高,而標(biāo)志位PF和AF的使用頻率較低。
4、零標(biāo)志ZF(Zero Flag)
零標(biāo)志ZF用來反映運(yùn)算結(jié)果是否為0。如果運(yùn)算結(jié)果為0,則其值為1,否則其值為0。在判斷運(yùn)算結(jié)果是否為0時,可使用此標(biāo)志位。
5、符號標(biāo)志SF(Sign Flag)
符號標(biāo)志SF用來反映運(yùn)算結(jié)果的符號位,它與運(yùn)算結(jié)果的最高位相同。在微機(jī)系統(tǒng)中,有符號數(shù)采用補(bǔ)碼表示法,所以,SF也就反映運(yùn)算結(jié)果的正負(fù)號。運(yùn)算結(jié)果為正數(shù)時,SF的值為0,否則其值為1。
6、溢出標(biāo)志OF(Overflow Flag)
溢出標(biāo)志OF用于反映有符號數(shù)加減運(yùn)算所得結(jié)果是否溢出。如果運(yùn)算結(jié)果超過當(dāng)前運(yùn)算位數(shù)所能表示的范圍,則稱為溢出,OF的值被置為1,否則,OF的值被清為0。
“溢出”和“進(jìn)位”是兩個不同含義的概念,不要混淆。如果不太清楚的話,請查閱《計算機(jī)組成原理》課程中的有關(guān)章節(jié)。
二、狀態(tài)控制標(biāo)志位
狀態(tài)控制標(biāo)志位是用來控制CPU操作的,它們要通過專門的指令才能使之發(fā)生改變。
1、追蹤標(biāo)志TF(Trap Flag)
當(dāng)追蹤標(biāo)志TF被置為1時,CPU進(jìn)入單步執(zhí)行方式,即每執(zhí)行一條指令,產(chǎn)生一個單步中斷請求。這種方式主要用于程序的調(diào)試。
指令系統(tǒng)中沒有專門的指令來改變標(biāo)志位TF的值,但程序員可用其它辦法來改變其值。
2、中斷允許標(biāo)志IF(Interrupt-enable Flag)
中斷允許標(biāo)志IF是用來決定CPU是否響應(yīng)CPU外部的可屏蔽中斷發(fā)出的中斷請求。但不管該標(biāo)志為何值,CPU都必須響應(yīng)CPU外部的不可屏蔽中斷所發(fā)出的中斷請求,以及CPU內(nèi)部產(chǎn)生的中斷請求。具體規(guī)定如下:
(1)、當(dāng)IF=1時,CPU可以響應(yīng)CPU外部的可屏蔽中斷發(fā)出的中斷請求;
(2)、當(dāng)IF=0時,CPU不響應(yīng)CPU外部的可屏蔽中斷發(fā)出的中斷請求。
CPU的指令系統(tǒng)中也有專門的指令來改變標(biāo)志位IF的值。
3、方向標(biāo)志DF(Direction Flag)
方向標(biāo)志DF用來決定在串操作指令執(zhí)行時有關(guān)指針寄存器發(fā)生調(diào)整的方向。具體規(guī)定在第5.2.11節(jié)——字符串操作指令——中給出。在微機(jī)的指令系統(tǒng)中,還提供了專門的指令來改變標(biāo)志位DF的值。
三、32位標(biāo)志寄存器增加的標(biāo)志位
1、I/O特權(quán)標(biāo)志IOPL(I/O Privilege Level)
I/O特權(quán)標(biāo)志用兩位二進(jìn)制位來表示,也稱為I/O特權(quán)級字段。該字段指定了要求執(zhí)行I/O指令的特權(quán)級。如果當(dāng)前的特權(quán)級別在數(shù)值上小于等于IOPL的值,那么,該I/O指令可執(zhí)行,否則將發(fā)生一個保護(hù)異常。
2、嵌套任務(wù)標(biāo)志NT(Nested Task)
嵌套任務(wù)標(biāo)志NT用來控制中斷返回指令I(lǐng)RET的執(zhí)行。具體規(guī)定如下:
(1)、當(dāng)NT=0,用堆棧中保存的值恢復(fù)EFLAGS、CS和EIP,執(zhí)行常規(guī)的中斷返回操作;
(2)、當(dāng)NT=1,通過任務(wù)轉(zhuǎn)換實(shí)現(xiàn)中斷返回。
3、重啟動標(biāo)志RF(Restart Flag)
重啟動標(biāo)志RF用來控制是否接受調(diào)試故障。規(guī)定:RF=0時,表示“接受”調(diào)試故障,否則拒絕之。在成功執(zhí)行完一條指令后,處理機(jī)把RF置為0,當(dāng)接受到一個非調(diào)試故障時,處理機(jī)就把它置為1,中國自學(xué)編程網(wǎng)整理發(fā)布!。
4、虛擬8086方式標(biāo)志VM(Virtual 8086 Mode)
如果該標(biāo)志的值為1,則表示處理機(jī)處于虛擬的8086方式下的工作狀態(tài),否則,處理機(jī)處于一般保護(hù)方式下的工作狀態(tài)。
===================================================
雖然jmp指令提供了控制轉(zhuǎn)移,但是它不允許進(jìn)行任何復(fù)雜的判斷。80x86條件跳轉(zhuǎn)指令提供了這種判斷。條件跳轉(zhuǎn)指令是創(chuàng)建循環(huán)和實(shí)現(xiàn)其他條件執(zhí)行語句,如if…endif的基本要素。
條件跳轉(zhuǎn)指令檢查一個或多個標(biāo)志位,判斷它們是否匹配某個特殊條件(就像setcc指令):如果標(biāo)志匹配成功,該指令就將控制轉(zhuǎn)移到目標(biāo)位置;如果匹配失敗,CPU忽略該條件跳轉(zhuǎn)指令而繼續(xù)執(zhí)行下一條指令。一些條件跳轉(zhuǎn)指令只是簡單測試符號位(sign)、進(jìn)位位(carry)、溢出位(overflow)、零標(biāo)志(zero)位的設(shè)置。例如,在執(zhí)行一條sh1指令后,您需要測試進(jìn)位標(biāo)志,來判斷sh1是否從操作數(shù)的高地址位移出一位。類似地,也可以在一條test指令后測試零標(biāo)志位,來判斷指定的位是否為1。大多數(shù)情況,在cmp指令之后執(zhí)行條件跳轉(zhuǎn)指令。cmp指令設(shè)置標(biāo)志位,以便判斷小于、大于、等于等情況。
條件跳轉(zhuǎn)指令形式如下:
Jcc label;
其中,Jcc中的“cc”,必須用表示測試條件類型的字符序列替換。這些字符和setcc指令使用的一樣。例如,“js”表示根據(jù)符號(sign)標(biāo)志是否被置位來決定是否跳轉(zhuǎn)。一個典型的js指令如下:
js ValueIsNegative ;
在這個示例中,如果符號(sign)標(biāo)志被置位,則js指令將控制轉(zhuǎn)移到ValueIsNegative語句標(biāo)號處;如果符號標(biāo)志清零,則將控制直接轉(zhuǎn)移給js指令后的指令。
與無條件jmp指令不同,條件跳轉(zhuǎn)指令不提供間接跳轉(zhuǎn)的形式。惟一允許的形式是跳轉(zhuǎn)到程序中某一標(biāo)號處。條件跳轉(zhuǎn)指令有一個限制:目標(biāo)標(biāo)號的位置必須在跳轉(zhuǎn)指令本身附近32768字節(jié)范圍內(nèi),這通常對應(yīng)著8000~32000條機(jī)器指令。一般情況下不會超過這種限制。
注意:Intel文檔為許多條件跳轉(zhuǎn)指令定義了多種替代名或指令別名。表7-1、7-2和7-3列出了每個指令所有的別名。這些表格也列出了表示相反分支的指令。很快您將明白這些相反分支指令的作用。
表7-1 測試標(biāo)志位的JCC指令
指 令
|
描 述
|
條 件
|
別 名
|
相 反 指 令
|
JC
|
如果進(jìn)位位被置位則跳轉(zhuǎn)
|
進(jìn)位標(biāo)志=1
|
JB,JNAE
|
JNC
|
JNC
|
如果進(jìn)位位沒有置位則跳轉(zhuǎn)
|
進(jìn)位標(biāo)志=0
|
JNB,JAE
|
JC
|
JZ
|
如果0標(biāo)志被置位則跳轉(zhuǎn)
|
0標(biāo)志=1
|
JE
|
JNZ
|
JNZ
|
如果0標(biāo)志沒有置位則跳轉(zhuǎn)
|
0標(biāo)志=0
|
JNE
|
JZ
|
(續(xù)表)
指 令
|
描 述
|
條 件
|
別 名
|
相反指令
|
JS
|
如果符號位被置位則跳轉(zhuǎn)
|
符號標(biāo)志=1
|
|
JNS
|
JNS
|
如果符號位沒有被置位則跳轉(zhuǎn)
|
符號標(biāo)志=0
|
|
JS
|
JO
|
如果溢出標(biāo)志置位則跳轉(zhuǎn)
|
溢出標(biāo)志=1
|
|
JNO
|
JNO
|
如果溢出標(biāo)志沒有置位則跳轉(zhuǎn)
|
溢出標(biāo)志=0
|
JO
|
|
JP
|
如果奇偶校驗(yàn)位被置位則跳轉(zhuǎn)
|
奇偶校驗(yàn)標(biāo)志=1
|
JPE
|
JNP
|
JPE
|
如果奇偶校驗(yàn)位為偶校驗(yàn)則跳轉(zhuǎn)
|
奇偶校驗(yàn)標(biāo)志=1
|
JP
|
JPO
|
JNP
|
如果奇偶校驗(yàn)位沒有被置位則跳轉(zhuǎn)
|
奇偶校驗(yàn)標(biāo)志=0
|
JPO
|
JP
|
JPO
|
如果奇偶校驗(yàn)位為奇校驗(yàn)則跳轉(zhuǎn)
|
奇偶校驗(yàn)標(biāo)志=0
|
JNP
|
JPE
|
表7-2 使用無符號數(shù)比較的JCC指令
指 令
|
描 述
|
條 件
|
別 名
|
相反指令
|
JA
|
如果超過(>)則跳轉(zhuǎn)
|
進(jìn)位標(biāo)志=0,0標(biāo)志=0
|
JNBE
|
JNA
|
JNBE
|
如果不低于或等于(不 <=)則跳轉(zhuǎn)
|
進(jìn)位標(biāo)志=0,0標(biāo)志=0
|
JA
|
JBE
|
JAE
|
如果超過或等于(>=)則跳轉(zhuǎn)
|
進(jìn)位標(biāo)志=0
|
JNC,JNB
|
JNAE
|
JNB
|
如果不低于則跳轉(zhuǎn)(不 <)
|
進(jìn)位標(biāo)志=0
|
JNC,JAE
|
JB
|
JB
|
如果低于(<)則跳轉(zhuǎn)
|
進(jìn)位標(biāo)志=1
|
JC,JNAE
|
JNB
|
JNAE
|
如果不超過或等于(不>=)則跳轉(zhuǎn)
|
進(jìn)位標(biāo)志=1
|
JC,JB
|
JAE
|
JBE
|
如果低于或等于(<=)則跳轉(zhuǎn)
|
進(jìn)位標(biāo)志=1或0標(biāo)志=1
|
JNA
|
JNBE
|
JNA
|
如果不超過(不>)則跳轉(zhuǎn)
|
進(jìn)位標(biāo)志=1或0標(biāo)志=1
|
JBE
|
JA
|
JE
|
如果相等(=)則跳轉(zhuǎn)
|
0標(biāo)志=1
|
JZ
|
JNE
|
JNE
|
如果不相等(<>)則跳轉(zhuǎn)
|
0標(biāo)志=0
|
JNZ
|
JE
|
表7-3 使用有符號數(shù)比較的JCC指令
指 令
|
描 述
|
條 件
|
別 名
|
相反指令
|
JG
|
如果大于(>)則跳轉(zhuǎn)
|
符號標(biāo)志=溢出標(biāo)志或0標(biāo)志=0
|
JNLE
|
JNG
|
JNLE
|
如果小于或等于(<=)則跳轉(zhuǎn)
|
符號標(biāo)志=溢出標(biāo)志或0標(biāo)志=0
|
JG
|
JLE
|
JGE
|
如果大于或等于(>=)則跳轉(zhuǎn)
|
符號標(biāo)志=溢出標(biāo)志
|
JNL
|
JGE
|
JNL
|
如果不小于(不<)則跳轉(zhuǎn)
|
符號標(biāo)志=溢出標(biāo)志
|
JGE
|
JL
|
JL
|
如果小于(<)則跳轉(zhuǎn)
|
符號標(biāo)志<>溢出標(biāo)志
|
JNGE
|
JNL
|
JNGE
|
如果大于或等于(>=)跳轉(zhuǎn)
|
符號標(biāo)志<>溢出標(biāo)志
|
JL
|
JGE
|
JLE
|
如果小于或等于(<=)跳轉(zhuǎn)
|
符號標(biāo)志<>溢出標(biāo)志或0標(biāo)志=1
|
JNG
|
JNLE
|
JNG
|
如果不大于(不>)則跳轉(zhuǎn)
|
符號標(biāo)志<>溢出標(biāo)志或0標(biāo)志=1
|
JLE
|
JG
|
JE
|
如果等于(=)則跳轉(zhuǎn)
|
0標(biāo)志=1
|
JZ
|
JNE
|
JNE
|
如果不等于(<>)則跳轉(zhuǎn)
|
0標(biāo)志=0
|
JNZ
|
JE
|
接下來將對“相反指令”一列進(jìn)行簡單的說明。在許多情況下,需要產(chǎn)生與某條分支指令條件相反的分支(在本章后面會給出示例),即相反分支。除了兩個例外,都可以按下面的簡單規(guī)則(后面統(tǒng)稱為N/No N規(guī)則)產(chǎn)生相反分支:
● 如果Jcc的第二個字母不是“n”,則在“j”后面插入一個“n”。例如:je對應(yīng)為jne,jl對應(yīng)為jnl。
● 如果Jcc的第二個字母是“n”,則去掉指令中的“n”。例如:jng對應(yīng)為jg,jne對應(yīng)為je。
不遵循這兩條規(guī)則的兩個例外是jpe(奇偶位為偶跳轉(zhuǎn))和jpo(奇偶位為奇跳轉(zhuǎn))。這兩個例外并不會導(dǎo)致什么問題,因?yàn)椋?a)很少需要測試奇偶標(biāo)志;(b)可以使用別名jp和jnp替代jpe和jpo。而“N/No N”規(guī)則對jp和jnp是適用的。
雖然jge是jl的相反指令,但是建議使用jnl作為jl的相反指令。因?yàn)楹苋菀渍`認(rèn)為“大于是小于的相反”,從而把jg當(dāng)作jl的相反指令。您可以堅持使用“N/No N”規(guī)則以避免這種混淆。
80x86條件跳轉(zhuǎn)指令提供了這樣的能力:根據(jù)判斷條件將程序流分支到兩條路徑中的某一條。例如,要實(shí)現(xiàn):如果BX等于CX,則寄存器AX的值加1??梢允褂孟旅娴拇a來完成該功能:
cmp(bx,cx );
jne SkipStmts;
inc(ax );
SkipStmts:
其中的訣竅是使用相反分支指令來跳過在條件滿足的情況下需要執(zhí)行的指令。請堅持使用前面介紹的“N/no N”規(guī)則來選擇相反分支指令。
使用條件跳轉(zhuǎn)指令還可以實(shí)現(xiàn)循環(huán)。例如,下面的代碼序列實(shí)現(xiàn)了從用戶輸入讀入一串字符,并將字符存儲到一組連續(xù)的單元中,直到用戶輸入回車鍵。
mov(0,edi );
RdLnLoop:
stdin.getc(); //Read a character into the AL register.
mov(al,Input [edi])); //Store away the character.
inc(edi ); //Move on to the next character.
cmp(al,stdio.cr ); //See if the user pressed Enter.
jne RdLnLoop;
與setcc指令類似,條件跳轉(zhuǎn)指令分為兩類—— 測試特殊處理器標(biāo)志位的條件跳轉(zhuǎn)指令(例如jz、jc、jno)和測試某些條件(小于、大于等)的條件跳轉(zhuǎn)指令。當(dāng)測試某個條件時,條件跳轉(zhuǎn)指令通常緊跟在一個cmp指令之后。cmp指令設(shè)置標(biāo)志位后,如果是無符號數(shù)比較,使用ja、jae、jb、jbe、je或jne等指令測試這些標(biāo)志來判斷是否小于、小于等于、等于、不等于、大于或大于等于;如果是有符號數(shù)比較,則使用jl、jle、je、jne、jg、jge指令。
條件跳轉(zhuǎn)指令測試標(biāo)志位,但不影響標(biāo)志位。
=========================
jnz(jump if not zero flag set) 和 jne(jump if not equal) 有相同的功效。
|