生成匯編代碼
比如,一個(gè)簡(jiǎn)單的函數(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
- 順便看一個(gè)Sun Studio 11: C 5.8 compiler,SPARC架構(gòu)(服務(wù)器來(lái)自u(píng)nix-center)
.global func
.type func,#function
func:
save %sp,-96,%sp
jmp %i7+8
restore
...
- 以及GCC 4.0.1,SPARC架構(gòu)(服務(wù)器來(lái)自u(píng)nix-center)
.global func
func:
retl ! Result =
nop
.type func,2
.size func,(.-func)
...
這些東西太復(fù)雜了,關(guān)注點(diǎn)只能限制到X86架構(gòu)了。先看一下X86下常用的兩種匯編有哪些不同。
X86匯編語(yǔ)言 差異
X86 下常用的匯編有 AT&T 與 Intel 兩種(fix me?),二者在語(yǔ)法上有一定的差異:
前綴/后綴
區(qū)別:
|
Intel語(yǔ)法
|
AT&T語(yǔ)法
|
寄存器
|
|
加前綴 %
|
立即數(shù)
|
|
|
加前綴 $
|
十六進(jìn)制
|
加后綴h
|
數(shù)字前加 0x
|
二進(jìn)制
|
加后綴b
|
|
例子:
Intel語(yǔ)法
|
AT&T語(yǔ)法
|
mov eax,8
|
movl $8,%eax
|
mov ebx,0ffffh
|
movl $0xffff,%ebx
|
int 80h
|
int $0x80
|
操作數(shù)的方向
例子:
Intel語(yǔ)法(<==)
|
AT&T語(yǔ)法(==>)
|
mov eax,[ecx]
|
movl (%ecx),%eax
|
內(nèi)存單元操作數(shù)
- 在Intel的語(yǔ)法中,基寄存器用“[]”括起來(lái)
-
而在AT&T中,用“()”括起來(lái)。
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語(yǔ)法
|
AT&T語(yǔ)法
|
指令 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語(yǔ)法
|
AT&T語(yǔ)法
|
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
|
找個(gè)例子看看
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é),用來(lái)保存局部變量
|
movl $255, (%esp)
|
將立即數(shù)255放入棧頂所指位置
|
call func
|
調(diào)用函數(shù)func,(此時(shí)將下條指令地址IP壓入棧中)
|
movl %eax, -4(%ebp)
|
將func的返回值放入局部變量中(-4(%ebp)就是變量s的位置)
|
movl $0, %eax
|
0送入eax,準(zhǔn)備返回值
|
leave
|
leave等價(jià)于 movl %ebp,%esp 和 popl %ebp
|
ret
|
|
參考
-
http:///kernel-book/ch02/2.6.1.htm
-
http://bbs./thread-106533-1-1.html
==================================================================================================
X86 匯編語(yǔ)言中CPU上的通用寄存器簡(jiǎn)要說(shuō)明
eax, ebx, ecx, edx, esi, edi, ebp, esp等都是X86 匯編語(yǔ)言中CPU上的通用寄存器的名稱(chēng),是32位的寄存器。如果用C語(yǔ)言來(lái)解釋?zhuān)梢园堰@些寄存器當(dāng)作變量看待。
比方說(shuō):add eax,-2 ; //可以認(rèn)為是給變量eax加上-2這樣的一個(gè)值。
這些32位寄存器有多種用途,但每一個(gè)都有“專(zhuān)長(zhǎng)”,有各自的特別之處。
EAX 是"累加器"(accumulator), 它是很多加法乘法指令的缺省寄存器。
EBX 是"基地址"(base)寄存器, 在內(nèi)存尋址時(shí)存放基地址。
ECX 是計(jì)數(shù)器(counter), 是重復(fù)(REP)前綴指令和LOOP指令的內(nèi)定計(jì)數(shù)器。
EDX 則總是被用來(lái)放整數(shù)除法產(chǎn)生的余數(shù)。
ESI/EDI 分別叫做"源/目標(biāo)索引寄存器"(source/destination index),因?yàn)樵诤芏嘧址僮髦噶钪? DS:ESI指向源串,而ES:EDI指向目標(biāo)串.
EBP 是"基址指針"(BASE POINTER), 它最經(jīng)常被用作高級(jí)語(yǔ)言函數(shù)調(diào)用的"框架指針"(frame pointer). 在破解的時(shí)候,經(jīng)??梢钥匆?jiàn)一個(gè)標(biāo)準(zhǔn)的函數(shù)起始代碼:
push ebp ; 保存當(dāng)前ebp
mov ebp,esp ; EBP設(shè)為當(dāng)前堆棧指針
sub esp, xxx ; 預(yù)留xxx字節(jié)給函數(shù)臨時(shí)變量.
...
這樣一來(lái),EBP 構(gòu)成了該函數(shù)的一個(gè)框架, 在EBP上方分別是原來(lái)的EBP, 返回地址和參數(shù). EBP下方則是臨時(shí)變量. 函數(shù)返回時(shí)作 mov esp,ebp/pop ebp/ret 即可.
ESP 專(zhuān)門(mén)用作堆棧指針,被形象地稱(chēng)為棧頂指針,堆棧的頂部是地址小的區(qū)域,壓入堆棧的數(shù)據(jù)越多,ESP也就越來(lái)越小。 在32位平臺(tái)上,ESP每次減少4字節(jié)。
esp:寄存器存放當(dāng)前線程的棧頂指針
ebp:寄存器存放當(dāng)前線程的棧底指針
eip:寄存器存放下一個(gè)CPU指令存放的內(nèi)存地址,當(dāng)CPU執(zhí)行完當(dāng)前的指令后,從EIP寄存器中讀取下一條指令的內(nèi)存地址,然后繼續(xù)執(zhí)行。
一般寄存器:AX、BX、CX、DX
AX:累積暫存器,BX:基底暫存器,CX:計(jì)數(shù)暫存器,DX:資料暫存器
索引暫存器:SI、DI
SI:來(lái)源索引暫存器,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指向此時(shí)的棧頂。
|
臨時(shí)變量1
|
|
臨時(shí)變量2
|
|
臨時(shí)變量3
|
|
臨時(shí)變量…
|
|
臨時(shí)變量5
|
↓低地址
|
- ===========================================================================
-
80x86指令系統(tǒng)
80x86指令系統(tǒng),指令按功能可分為以下七個(gè)部分。
(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)志寄存器傳送指令、符號(hào)擴(kuò)展指令、擴(kuò)展傳送指令等。
一、通用數(shù)據(jù)傳送指令
1傳送指令
傳送指令是使用最頻繁的指令,格式:MOV DEST,SRC
功能:把一個(gè)字節(jié),字或雙字從源操作數(shù)SRC傳送至目的操作數(shù)DEST。
傳送指令允許的數(shù)據(jù)流方向見(jiàn)圖311。

圖 3.11 傳送指令數(shù)據(jù)流
由上圖可知,數(shù)據(jù)允許流動(dòng)方向?yàn)椋和ㄓ眉拇嫫髦g、通用寄存器和存儲(chǔ)器之間、通用寄存器和段寄存器之間、段寄存器和存儲(chǔ)器之間,另外還允許立即數(shù)傳送至通用寄存器或存儲(chǔ)器。但在上述傳送過(guò)程中,段寄存器CS的值不能用傳送指令改變。
例 3.12CPU內(nèi)部寄存器之間的數(shù)據(jù)傳送。
MOV AL,DH ;AL←DH (8位)
MOV DS,AX ??;DS←AX (16位)
MOV EAX,ESI ?。籈AX←ESI (32位)
例 3.13CPU內(nèi)部寄存器和存儲(chǔ)器之間的數(shù)據(jù)傳送。
MOV [BX],AX ;間接尋址 (16位)
MOV EAX,[EBX+ESI] ??;基址變址尋址 (32位)
MOV AL,BLOCK ;BLOCK為變量名,直接尋址(8位)
例 3.14立即數(shù)送通用寄存器、存儲(chǔ)器。
MOV EAX,12345678H ??;EAX←12345678H (32位)
MOV [BX],12H ;間接尋址 (8位)
MOV AX,1234H;AX←1234H(16位)
使用該指令應(yīng)注意以下問(wèn)題:
·源和目的操作數(shù)不允許同時(shí)為存儲(chǔ)器操作數(shù);
·源和目的操作數(shù)數(shù)據(jù)類(lèi)型必須一致;
·源和目的操作數(shù)不允許同時(shí)為段寄存器;
·目的操作數(shù)不允許為CS和立即數(shù);
·當(dāng)源操作數(shù)為立即數(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是按有符號(hào)數(shù)擴(kuò)展,MOVZX是按無(wú)符號(hào)數(shù)擴(kuò)展。無(wú)符號(hào)數(shù)或正數(shù)高位擴(kuò)展為0,負(fù)數(shù)高位擴(kuò)展為全“1”。
例 3.15帶符號(hào)數(shù)擴(kuò)展
MOV BL,80H ??; -128
MOVSX AX,BL ??; 將80H擴(kuò)展為FF80H后送AX中。
例 3.16無(wú)符號(hào)數(shù)擴(kuò)展
MOV BL,80H ; 128
MOVZX AX,BL ?。弧?0H擴(kuò)展為0080H后送AX中。
使用該指令應(yīng)注意以下問(wèn)題:
·目的操作數(shù)應(yīng)為16位或32位通用寄存器;
·源操作數(shù)長(zhǎng)度須小于目的操作數(shù)長(zhǎng)度,為8位或16位通用寄存器或存儲(chǔ)器操作數(shù);
·擴(kuò)展傳送操作不影響標(biāo)志位。
3交換指令
(1) 格式:XCHG OPR1,OPR2
功能:交換操作數(shù)OPR1和OPR2的值,操作數(shù)數(shù)據(jù)類(lèi)型為字節(jié)、字或雙字。允許通用寄存器之間,通用寄存器和存儲(chǔ)器之間交換數(shù)據(jù)。
例 3.17
XCHG AX,BX;通用寄存器之間交換數(shù)據(jù)(16位)
XCHG ESI,EDI;通用寄存器之間交換數(shù)據(jù)(32位)
XCHG BX,/[SI/];通用寄存器和存儲(chǔ)器之間交換數(shù)據(jù)(16位)
XCHG AL,/[BX/];通用寄存器和存儲(chǔ)器之間交換數(shù)據(jù)(8位)
使用該指令應(yīng)注意以下問(wèn)題:
·操作數(shù)OPR1和OPR2不允許同為存儲(chǔ)器操作數(shù);
·操作數(shù)數(shù)據(jù)類(lèi)型必須一致;
·交換指令不影響標(biāo)志位。
如要實(shí)現(xiàn)存儲(chǔ)器操作數(shù)交換,可用如下指令實(shí)現(xiàn):
MOV AL,BLOCK1
XCHG AL,BLOCK2
MOV BLOCK1,AL
(2) 格式:BSWAP REG
功能:將32位通用寄存器中,第1個(gè)字節(jié)和第4個(gè)字節(jié)交換,第2個(gè)字節(jié)和第3個(gè)字節(jié)交換。
例 3.18
MOV EAX,44332211H
BSWAP EAX;EAX=11223344H
使用該指令應(yīng)注意以下問(wèn)題:
·操作數(shù)為32位通用寄存器;
·交換指令不影響標(biāo)志位。
二、堆棧操作指令
1壓棧指令
(1) 格式:PUSH SRC
功能:將源操作數(shù)壓下堆棧,源操作數(shù)允許為16位或32位通用寄存器、存儲(chǔ)器和立即數(shù)以及16位段寄存器。當(dāng)操作數(shù)數(shù)據(jù)類(lèi)型為字類(lèi)型,壓棧操作使SP值減2;當(dāng)數(shù)據(jù)類(lèi)型為雙字類(lèi)型,壓棧操作使SP值減4。
例 3.19
PUSH AX ;通用寄存器操作數(shù)入棧(16位)
PUSH EBX ;通用寄存器操作數(shù)入棧(32位)
PUSH [SI] ;存儲(chǔ)器操作數(shù)入棧(16位)
PUSH DWORD PTR [DI] ?。淮鎯?chǔ)器操作數(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位通用寄存器、存儲(chǔ)器和16位段寄存器。當(dāng)操作數(shù)數(shù)據(jù)類(lèi)型為字類(lèi)型,出棧操作使SP加2;當(dāng)操作數(shù)數(shù)據(jù)類(lèi)型為雙字類(lèi)型,出棧操作使SP加4。
例 3.20
POP AX ;操作數(shù)出棧送寄存器(16位)
POP ECX ;操作數(shù)出棧送寄存器(32位)
POP [BX] ??;操作數(shù)出棧送存儲(chǔ)器(16位)
POP DWORD PTR [SI] ;操作數(shù)出棧送存儲(chǔ)器(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)注意以下問(wèn)題。
(1) 目的操作數(shù)不允許為CS以及立即數(shù)。
(2) 堆棧操作指令不影響標(biāo)志位。
三、地址傳送指令
(1) 格式:LEA REG,MEM
功能:將源操作數(shù)的有效地址傳送到通用寄存器,操作數(shù)REG為16位或32位通用寄存器,源操作數(shù)為16位或32位存儲(chǔ)器操作數(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] ;將32位地址指針?lè)謩e送ES和BX
LSS EAX,[EDI] ?。粚?8位地址指針?lè)謩e送SS和EAX

例 3.23
DATA1 DD buff

LDS BX,DATA1;將buff的32位地址指針?lè)謩e送DS和BX

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

· 兩個(gè)正數(shù)比較,使用SF標(biāo)志位判斷。
SF=0,則AX≥BX,若ZF=1,則AX=BX
SF=1,則AX<BX
· 兩個(gè)無(wú)符號(hào)數(shù)比較,使用CF標(biāo)志位判斷。
CF=0,則AX≥BX,若ZF=1,則AX=BX
CF=1,則AX<BX
· 兩個(gè)負(fù)數(shù)比較,使用SF標(biāo)志位判斷。
SF=0,則AX≥BX,若ZF=1,則AX=BX
SF=1,則AX<BX
· 兩個(gè)異符號(hào)數(shù)比較。
如果OF=0,仍可用SF標(biāo)志判斷大小。
如果OF=1,說(shuō)明結(jié)果的符號(hào)位發(fā)生錯(cuò)誤,所以
SF=0,則AX<BX
SF=1,則AX>BX
綜上所述:兩個(gè)異號(hào)數(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ù)可以為通用寄存器,存儲(chǔ)器操作數(shù)。
CMPXCHG影響標(biāo)志位為OF,SF,ZF,AF,PF,CF。
(3) 格式:CMPXCHG8BMEM
功能:EDX:EAX中值減存儲(chǔ)器操作數(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ù)允許為通用寄存器、存儲(chǔ)器操作數(shù)。
XADD指令影響標(biāo)志位為OF,SF,ZF,AF,PF,CF。
六、求補(bǔ)指令
格式:NEGDEST
功能:對(duì)目的操作數(shù)求補(bǔ),用零減去目的操作數(shù),結(jié)果送目的操作數(shù)。目的操作數(shù)為通用寄存器、存儲(chǔ)器操作數(shù)。
NEG指令影響標(biāo)志位為OF,SF,ZF,AF,PF,CF。
七、乘法指令
(1) 格式:MULSRC
IMULSRC
功能:MUL為無(wú)符號(hào)數(shù)乘法指令,IMUL為帶符號(hào)數(shù)乘法指令。源操作數(shù)為通用寄存器或存儲(chǔ)器操作數(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,表示乘積高位無(wú)有效數(shù)據(jù);CF=OF=1表示乘積高位含有效數(shù)據(jù),對(duì)其它標(biāo)志位無(wú)定義。
例 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位通用寄存器或存儲(chǔ)器操作數(shù)。源操作數(shù)為16位或32位通用寄存器、存儲(chǔ)器或立即數(shù)。
源操作數(shù)和目的操作數(shù)數(shù)據(jù)類(lèi)型要求一致。乘積僅取和目的操作數(shù)相同的位數(shù),高位部分將被舍去,并且CF=OF=1。其它標(biāo)志位無(wú)定義。
(3) 格式:IMUL DEST,SRC1,SRC2
功能:將源操作數(shù)SRC1與源操作數(shù)SRC2相乘,結(jié)果送目的操作數(shù)。目的操作數(shù)DEST為16位或32位,允許為通用寄存器。源操作數(shù)SRC1為16位或32位通用寄存器或存儲(chǔ)器操作數(shù)。源操作數(shù)SRC2允許為立即數(shù)。
例 3.32 IMULEAX,[EBX],12H
要求目的操作數(shù)和源操作數(shù)SRC1類(lèi)型相同,當(dāng)乘積超出目的操作數(shù)部分,將被舍去,并且使CF=OF=1,在使用這類(lèi)指令時(shí),需在IMUL指令后加一條判斷溢出的指令,溢出時(shí)轉(zhuǎn)錯(cuò)誤處理執(zhí)行程序。
八、除法指令
格式:DIV SRC
IDIV SRC
功能:DIV為無(wú)符號(hào)數(shù)除法,IDIV為帶符號(hào)數(shù)除法。源操作數(shù)作為除數(shù),為通用寄存器或存儲(chǔ)器操作數(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ù)的雙倍字長(zhǎng),一般應(yīng)使用擴(kuò)展指令進(jìn)行高位擴(kuò)展。當(dāng)進(jìn)行無(wú)符號(hào)數(shù)除法時(shí),被除數(shù)高位按0擴(kuò)展為雙倍除數(shù)字長(zhǎng)。當(dāng)進(jìn)行有符號(hào)數(shù)除法時(shí),被除數(shù)以補(bǔ)碼表示??墒褂脭U(kuò)展指令CBW,CWD,CWDE,CDQ進(jìn)行高位擴(kuò)展。例如:
MOV AX,BLOCK
CWD;被除數(shù)高位擴(kuò)展
MOV BX,1000H
IDIV BX
對(duì)于帶符號(hào)除法,其商和余數(shù)均采用補(bǔ)碼形式表示,余數(shù)與被除數(shù)同符號(hào)。當(dāng)除數(shù)為零或商超過(guò)了規(guī)定數(shù)據(jù)類(lèi)型所能表示的范圍時(shí),將會(huì)出現(xiàn)溢出現(xiàn)象,產(chǎn)生一個(gè)中斷類(lèi)型碼為“0”的中斷。執(zhí)行除法指令后標(biāo)志位無(wú)定義。
九、BCD算術(shù)運(yùn)算
十進(jìn)制數(shù)在機(jī)器中采用BCD碼表示,以壓縮格式存放,即一個(gè)字節(jié)存儲(chǔ)2位BCD碼,BCD加減法是在二進(jìn)制加減運(yùn)算的基礎(chǔ)上,對(duì)其二進(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無(wú)定義。
例 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無(wú)定義。
例 3.34
SUB AL,BL
DAS
十、ASCII算術(shù)運(yùn)算
數(shù)字0~9的ASCII碼為30H~39H,機(jī)器采用一個(gè)字節(jié)存放一位ASCII碼,對(duì)于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)志位無(wú)定義。
例 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)志位無(wú)定義。
例 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)志位無(wú)定義。
例 3.37
MOV AL,07H
MOV BL,09H
MUL BL;AX=003FH
AAM;AX=0603H
(4) 格式:AAD
功能:將AX中兩位非壓縮BCD碼(一個(gè)字節(jié)存放一位BCD碼),轉(zhuǎn)換為二進(jìn)制數(shù)的表示形式。
調(diào)整方法:AH10+AL→AL0→AH
AAD指令用于二進(jìn)制除法DIV操作之前,影響的標(biāo)志位為SF,ZF,PF。其它標(biāo)志位無(wú)定義。
例 3.38
MOV AX,0605H
MOV BL,09H
AAD;AX=0041H
DIV BL;AX=0207H
使用該類(lèi)指令應(yīng)注意,加法、減法和乘法調(diào)整指令都是緊跟在算術(shù)運(yùn)算指令之后,將二進(jìn)制的運(yùn)算結(jié)果調(diào)整為非壓縮BCD碼表示形式,而除法調(diào)整指令必須放在除法指令之前進(jìn)行,以避免除法出現(xiàn)錯(cuò)誤的結(jié)果。
使用算術(shù)運(yùn)算類(lèi)指令應(yīng)注意:
·如果沒(méi)有特別規(guī)定,參與運(yùn)算的兩個(gè)操作數(shù)數(shù)據(jù)類(lèi)型必須一致,且只允許一個(gè)為存儲(chǔ)器操作數(shù);
·如果參與運(yùn)算的操作數(shù)只有一個(gè),且為存儲(chǔ)器操作數(shù),必須使用PTR偽指令說(shuō)明數(shù)據(jù)類(lèi)型;
·操作數(shù)不允許為段寄存器。
·目的操作數(shù)不允許為立即數(shù);
·如果是存儲(chǔ)器尋址,則存儲(chǔ)器各種尋址方式均可使用。
3.3.3邏輯運(yùn)算指令
一、邏輯指令
1邏輯與指令
格式:AND DEST,SRC
功能:目的操作數(shù)和源操作數(shù)按位進(jìn)行邏輯與運(yùn)算,結(jié)果存目的操作數(shù)中。源操作數(shù)可以是通用寄存器、存儲(chǔ)器或立即數(shù)。目的操作數(shù)可以是通用寄存器或存儲(chǔ)器操作數(shù)。
例 3.39
AND AL,BL
AND EBX,ECX
AND [DI],1101H
AND指令常用于將操作數(shù)中某位清0(稱(chēng)屏蔽),只須將要清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ù)可以是通用寄存器、存儲(chǔ)器或立即數(shù)。目的操作數(shù)可以是通用寄存器或存儲(chǔ)器操作數(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ù)可以是通用寄存器、存儲(chǔ)器或立即數(shù)。目的操作數(shù)可以是通用寄存器或存儲(chǔ)器操作數(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
功能:對(duì)目的操作數(shù)按位取反,結(jié)果回送目的操作數(shù)。目的操作數(shù)可以為通用寄存器或存儲(chǔ)器。
例 3.45
NOT EAX
NOT BYTE PTR [BX]
NOT指令對(duì)標(biāo)志位無(wú)影響。
5測(cè)試指令
格式:TEST DEST,SRC
功能:目的操作數(shù)和源操作數(shù)按位進(jìn)行邏輯與操作,結(jié)果不回送目的操作數(shù)。源操作數(shù)可以為通用寄存器、存儲(chǔ)器或立即數(shù)。目的操作數(shù)可以為通用寄存器或存儲(chǔ)器操作數(shù)。
例 3.46
TEST DWORD PTR [BX],80000000H
TEST AL,CL
TEST指令常用于測(cè)試操作數(shù)中某位是否為1,而且不會(huì)影響目的操作數(shù)。如果測(cè)試某位的狀態(tài),對(duì)某位進(jìn)行邏輯與1的運(yùn)算,其它位邏輯與0,然后判斷標(biāo)志位。運(yùn)算結(jié)果為0,ZF=1,表示被測(cè)試位為0;否則ZF=0,表示被測(cè)試位為1。
例 3.47 TEST AL,80H;測(cè)試AL中最高位
JNZ NEXT;如果最高位為1,轉(zhuǎn)到標(biāo)志NEXT處。
TEST指令影響標(biāo)志位為SF,ZF,PF,并且使OF=CF=0。
二、移位指令
移位指令對(duì)操作數(shù)按某種方式左移或右移,移位位數(shù)可以由立即數(shù)直接給出,或由CL間接給出。移位指令分一般移位指令和循環(huán)移位指令。
1一般移位指令
(1) 算術(shù)/邏輯左移指令。
格式:SAL DEST,OPRD
SHL DEST,OPRD
功能:按照操作數(shù)OPRD規(guī)定的移位位數(shù),對(duì)目的操作數(shù)進(jìn)行左移操作,最高位移入CF中。每移動(dòng)一位,右邊補(bǔ)一位0。如圖312(a)所示。目的操作數(shù)可以為通用寄存器或存儲(chǔ)器操作數(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ù),對(duì)目的操作數(shù)進(jìn)行右移操作,最低位移至CF中,最高位(即符號(hào)位)保持不變。如圖312(b)所示。目的操作數(shù)可以為通用寄存器或存儲(chǔ)器操作數(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ù),對(duì)目的操作數(shù)進(jìn)行右移操作,最低位移至CF中。每移動(dòng)一位,左邊補(bǔ)一位0。如圖312(c)所示,目的操作數(shù)可以為通用寄存器或存儲(chǔ)器操作數(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ù)右移只要無(wú)溢出,每右移一次相當(dāng)于原數(shù)除以2。
2循環(huán)移位指令
格式:ROL DEST,OPRD
ROR DEST,OPRD
RCL DEST,OPRD
RCR DEST,OPRD
功能:循環(huán)左移指令ROL,見(jiàn)圖313(a)所示,目的操作數(shù)左移,每移位一次,其最高位移入最低位,同時(shí)最高位也移入進(jìn)位標(biāo)志CF。循環(huán)右移指令 ROR見(jiàn)圖313(b)所示,目的操作數(shù)右移,每移位一次,其最低位移入最高位,同時(shí)最低位也移入進(jìn)位標(biāo)志CF。
帶進(jìn)位循環(huán)左移指令RCL,見(jiàn)圖313(c)所示,目的操作數(shù)左移,每移動(dòng)一次,其最高位移入進(jìn)位標(biāo)志CF,CF移入最低位。帶進(jìn)位循環(huán)右移指令RCR,見(jiàn)圖313(d)所示,目的操作數(shù)右移,每移動(dòng)一次,其最低位移入進(jìn)位標(biāo)志CF,CF移入最高位。
圖 3.13 循環(huán)移位指令
目的操作數(shù)可以為通用寄存器或存儲(chǔ)器操作數(shù)。循環(huán)移位指令影響標(biāo)志位CF,OF。其它標(biāo)志位無(wú)定義。
例 3.51
ROL AL,CL
ROR BX,5
RCL ECX,3
RCR BYTE PTR [SI],CL
例 3.52 將一個(gè)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
功能:對(duì)于由目的操作數(shù)DEST和源操作數(shù)SRC構(gòu)成的雙精度數(shù),按照操作數(shù)OPRD給出的移位位數(shù),進(jìn)行移位。SHLD是對(duì)目的操作數(shù)進(jìn)行左移,如 圖314(a)所示,SHRD是對(duì)目的操作數(shù)進(jìn)行右移,如圖314(b)所示。先移出位送標(biāo)志位CF,另一端空出位由SRC移入DEST中,而SRC 內(nèi)容保持不變。目的操作數(shù)可以是16位或32位通用寄存器或存儲(chǔ)器操作數(shù)。源操作數(shù)SRC允許為16位或32位通用寄存器。操作數(shù)OPRD可以為立即數(shù)或 CL。目的操作數(shù)和源操作數(shù)SRC數(shù)據(jù)類(lèi)型必須一致。

圖 3.14 雙精度移位指令
SHLD,SHRD指令常用于位串的快速移位、嵌入和刪除等操作,影響標(biāo)志位為SF,ZF,PF,CF,其它標(biāo)志位無(wú)定義。
三、位操作指令
位操作指令包括位測(cè)試和位掃描指令,可以直接對(duì)一個(gè)二進(jìn)制位進(jìn)行測(cè)試,設(shè)置和掃描。
1位測(cè)試和設(shè)置指令
格式:BT DEST,SRC
BTC DEST,SRC
BTR DEST,SRC
BTS DEST,SRC
功能:按照源操作指定的位號(hào),測(cè)試目的操作數(shù),當(dāng)指令執(zhí)行時(shí),被測(cè)試位的狀態(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位通用寄存器或存儲(chǔ)器,源操作數(shù)為16位或32位通用寄存器,以及8位立即數(shù),當(dāng)源操作數(shù)為通用寄存器時(shí),必須同目的操作數(shù)類(lèi)型一致。源操作數(shù)SRC以?xún)煞N方式給出目的操作數(shù)的位號(hào),即
· SRC為8位立即數(shù),以二進(jìn)制形式直接給出要操作的位號(hào);
· SRC為通用寄存器,如果DEST為通用寄存器,則SRC中二進(jìn)制值直接給出要操作的位號(hào)。如果DEST為存儲(chǔ)器操作數(shù),通用寄存器SRC為帶符號(hào)整數(shù), SRC的值除以DEST的長(zhǎng)度所得到的商作為DEST的相對(duì)偏移量,余數(shù)直接作為要操作的位號(hào)。DEST的有效地址為DEST給出的偏移地址和DEST相 對(duì)偏移量之和。
BT,BTC,BTR,BTS指令影響CF標(biāo)志位,其它標(biāo)志位無(wú)定義。
例 3.53
MOV AX,1234H
MOV ECX,5
BT AX,CX ?。籆F=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從低位開(kāi)始掃描源操作數(shù),若所有位都是0,則ZF=0,否則ZF=1。并且將第一個(gè)出現(xiàn)1的位號(hào)存入目的操作數(shù)。BSR從高位開(kāi)始掃描源操作數(shù),若所有位都是0,則ZF=0,否則ZF=1。并且將第一個(gè)出現(xiàn)1的位號(hào)存入目的操作數(shù)。
源操作數(shù)可以為16位32位通用寄存器或存儲(chǔ)器。目的操作數(shù)為16位或32位通用寄存器。源操作數(shù)和目的操作數(shù)類(lèi)型必須一致。
BSF,BSR指令影響ZF標(biāo)志位,其它標(biāo)志位無(wú)定義。
例 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é),見(jiàn)表33。
格式:SETcondDEST
功能:測(cè)試條件(cond)若為真,則將目的操作數(shù)置01H,否則置00H。目的操作數(shù)允許為8位通用寄存器或8位存儲(chǔ)器操作數(shù)。
條件cond與條件轉(zhuǎn)移指令中的條件相同,共分三類(lèi)。
(1) 以標(biāo)志位狀態(tài)為條件可以測(cè)試的標(biāo)志位為ZF,SF,OF,CF,PF。
(2) 以?xún)蓚€(gè)無(wú)符號(hào)數(shù)比較為條件條件為高于、高于等于、低于、低于等于。
(3) 以?xún)蓚€(gè)帶符號(hào)數(shù)比較為條件條件為大于、大于等于、小于、小于等于。
SET指令不影響標(biāo)志位。
使用邏輯運(yùn)算類(lèi)指令應(yīng)注意:
· 如果沒(méi)有特別規(guī)定,參與運(yùn)算的兩個(gè)操作數(shù)類(lèi)型必須一致,且只允許一個(gè)為存儲(chǔ)器操作數(shù);
· 如果參與運(yùn)算的操作數(shù)只有一個(gè),且為存儲(chǔ)器操作數(shù),必須使用PTR偽指令說(shuō)明其數(shù)據(jù)類(lèi)型;
· 操作數(shù)不允許為段寄存器;
· 目的操作數(shù)不允許為立即數(shù);
· 如果是存儲(chǔ)器尋址,則前面介紹的各種存儲(chǔ)器尋址方式均可使用。
表 3.3 條件設(shè)置字節(jié)指令

3.3.4控制轉(zhuǎn)移類(lèi)指令
計(jì)算機(jī)執(zhí)行程序一般是順序地逐條執(zhí)行指令。但經(jīng)常須要根據(jù)不同條件做不同的處理,有時(shí)需要跳過(guò)幾條指令,有時(shí)需要重復(fù)執(zhí)行某段程序,或者轉(zhuǎn)移到另一個(gè)程序段去執(zhí)行。用于控制程序流程的指令包括轉(zhuǎn)移、循環(huán)、過(guò)程調(diào)用和中斷調(diào)用。
一、轉(zhuǎn)移指令
1無(wú)條件轉(zhuǎn)移指令
格式:JMP TARGET
功能:使程序無(wú)條件地轉(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)移
功能:采用相對(duì)尋址將當(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
本例為無(wú)條件轉(zhuǎn)移到本段內(nèi),標(biāo)號(hà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]指令地址在存儲(chǔ)器中,默認(rèn)段寄存器根據(jù)參與尋址的通用寄存器來(lái)確定,將指定存儲(chǔ)單元的字取出直接送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單元存放的一個(gè)字送IP
JMP NEAR PTR [EBX] ?。粚⒍芜x擇符為1000H,偏移地址為00002000H單元存放的雙字送EIP。
(3) 段間直接轉(zhuǎn)移:
格式:JMP FAR PTR TARGET
功能:段間直接轉(zhuǎn)移,F(xiàn)AR PTR說(shuō)明標(biāo)號(hà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]指定的存儲(chǔ)器操作數(shù)作為轉(zhuǎn)移地址。
在16位指令模式下,存儲(chǔ)器操作數(shù)為32位,包括16位段基址和16位偏移地址。
例 3.59
JMP FAR PTR [BX] ;數(shù)據(jù)段雙字存儲(chǔ)單元低字內(nèi)容送IP
??;數(shù)據(jù)段雙字存儲(chǔ)單元高字內(nèi)容送CS
在32位指令模式下,存儲(chǔ)器操作數(shù)包括16位選擇符。
例 3.60 JMP FAR PTR [EAX]
指令中包含指向目標(biāo)地址指針的門(mén)描述符或TSS描述符的指針,其所指的存儲(chǔ)器操作數(shù)中僅選擇符部分有效,指示調(diào)用門(mén)、任務(wù)門(mén)或TSS描述符起作用,而偏移部分不起作用。
2條件轉(zhuǎn)移指令
該類(lèi)指令是根據(jù)上一條指令對(duì)標(biāo)志寄存器中標(biāo)志位的影響來(lái)決定程序執(zhí)行的流程,若滿(mǎn)足指令規(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)移指令包括四類(lèi):?jiǎn)螛?biāo)志位條件轉(zhuǎn)移;無(wú)符號(hào)數(shù)比較條件轉(zhuǎn)移;帶符號(hào)數(shù)比較條件轉(zhuǎn)移;測(cè)試CX條件轉(zhuǎn)移。
格式:Jcc TARGET
功能:若測(cè)試條件‘CC’為真,則轉(zhuǎn)移到目標(biāo)地址TARGET處執(zhí)行程序。否則順序執(zhí)行。
(1) 單標(biāo)志位條件轉(zhuǎn)移指令,見(jiàn)表34。
例 3.61 JZ NEXT;若標(biāo)志ZF=1則轉(zhuǎn)移到標(biāo)號(hào)NEXT處執(zhí)行。
(2) 無(wú)符號(hào)數(shù)比較條件轉(zhuǎn)移,見(jiàn)表35。
例 3.62 JA NEXT;無(wú)符號(hào)數(shù)A與B比較,若A>B則轉(zhuǎn)移到標(biāo)號(hào)NEXT處執(zhí)行程序
表 3.4 單標(biāo)志位條件轉(zhuǎn)移指令

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

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

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

例 3.64 JCXZ TARGET;CX=0轉(zhuǎn)移到標(biāo)號(hào)TARGET處。
JECXZ TARGET;ECX=0轉(zhuǎn)移到標(biāo)號(hào)TARGET處。
條件轉(zhuǎn)移指令一般緊跟在CMP或TEST指令之后,判斷執(zhí)行CMP或TEST指令對(duì)標(biāo)志位的影響來(lái)決定是否轉(zhuǎn)移。
例 3.65 符號(hào)函數(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ù)的形式在屏幕上顯示出來(lái)。
·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)控制指令
這類(lèi)指令用(E)CX計(jì)數(shù)器中的內(nèi)容控制循環(huán)次數(shù),先將循環(huán)計(jì)數(shù)值存放在(E)CX中,每循環(huán)一次(E)CX內(nèi)容減1,直到(E)CX為0時(shí)循環(huán)結(jié)束。
格式:LOOPcc TARGET
功能:將(E)CX內(nèi)容減1,不影響標(biāo)志位,若(E)CX不等于0,且測(cè)試條件‘CC’成立,則轉(zhuǎn)移到目標(biāo)地址TARGET處執(zhí)行程序。轉(zhuǎn)移范圍為-128~+127。如表38所示。
表3.8 循環(huán)控制指令

例 3.67 計(jì)算
·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個(gè)字?jǐn)?shù)組中的第一個(gè)非0項(xiàng),送AX寄存器中。
·MODELSMALL
·DATA
ARRAYDW 0,0,0,0,1010H,…;(100個(gè)字)
·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)于過(guò)程調(diào)用和返回指令將在子程序一節(jié)中介紹。
3.3.5串操作指令
80x86提供處理字符串的操作。串指連續(xù)存放在存儲(chǔ)器中的一些數(shù)據(jù)字節(jié)、字或雙字。串操作允許程序?qū)B續(xù)存放大的數(shù)據(jù)塊進(jìn)行操作。
串操作通常以DS:(E)SI來(lái)尋址源串,以ES:(E)DI來(lái)尋址目的串,對(duì)于源串允許段超越。(E)SI或(E)DI這兩個(gè)地址指針在每次串操作 后,都自動(dòng)進(jìn)行修改,以指向串中下一個(gè)串元素。地址指針修改是增量還是減量由方向標(biāo)志來(lái)規(guī)定。當(dāng)DF=0,(E)SI及(E)DI的修改為增量;當(dāng)DF= 1,(E)SI及(E)DI的修改為減量。根據(jù)串元素類(lèi)型不同,地址指針增減量也不同,在串操作時(shí),字節(jié)類(lèi)型SI,DI加、減1;字類(lèi)型SI,DI加、減 2;雙字類(lèi)型ESI,EDI加、減4。如果需要連續(xù)進(jìn)行串操作,通常加重復(fù)前綴。重復(fù)前綴可以和任何串操作指令組合,形成復(fù)合指令,見(jiàn)表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ī)定的目的串單元中,見(jiàn)表310。
表 3.10 MOVS指令

該指令對(duì)標(biāo)志位無(wú)影響。
如果加重復(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個(gè)字節(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個(gè)字節(jié)內(nèi)容傳送到起始地址為DEST的存儲(chǔ)單元。
四、串比較指令
基本格式:[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)源 串元素與目的串元素值相同時(shí),ZF=1;否則ZF=0。每執(zhí)行一次串比較指令,根據(jù)DF的值和串元素?cái)?shù)據(jù)類(lèi)型自動(dòng)修改(E)SI和(E)DI。
在串比較指令前加重復(fù)前綴REPE/Z,則表示重復(fù)比較兩個(gè)字符串,若兩個(gè)字符串的元素相同則比較到(E)CX=0為止,否則結(jié)束比較。在串比較指令 前加重復(fù)前綴REPNE/NZ,則表示若兩個(gè)字符串元素不相同時(shí),重復(fù)比較直到(E)CX=0為止,否則結(jié)束比較。
例 3.70 編程實(shí)現(xiàn)兩個(gè)串元素比較,如相同則將全“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的值與目的串元素值相同時(shí),ZF=1;否則ZF=0。每執(zhí)行一次串掃描指令,根據(jù)DF的值和串元素?cái)?shù)據(jù)類(lèi)型自動(dòng)修改(E)DI。
在串掃描指令前加重復(fù)前綴REPE/Z,則表示目的串元素值和累加器值相同時(shí)重復(fù)掃描,直到CX/ECX=0為止,否則結(jié)束掃描。若加重復(fù)前綴 REPNE/NZ,則表示當(dāng)目的串元素值與累加器值不相等時(shí),重復(fù)掃描直到CX/ECX=0時(shí)為止,否則結(jié)束掃描。
該指令影響標(biāo)志位為CF,AF,PF,SF,OF,ZF。
例 3.71 在內(nèi)存DEST開(kāi)始的6個(gè)單元尋找字符‘C’,如找到將字符‘C’的地址送ADDR單元,否則0送ADDR單元。
·MODEL SMALL
·DATA
DEST DB ‘A B C D E F’
ADDR DW?;存“C”的地址,所以設(shè)置為字類(lèi)型
·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值以及串元素類(lèi)型自動(dòng)修改地址指針SI/ESI,該指令一般不須加重復(fù)前綴,并且不影響標(biāo)志位。
七、 串存儲(chǔ)指令
格式:[REP] STOS DESTS
[REP] STOSB/STOSW/STOSD
功能:將累加器/[AL,AX,EAX/]中值存入ES:DI/EDI所指的目的串存儲(chǔ)單元中,每傳遞一次,都按DF值以及串元素類(lèi)型自動(dòng)修改地址指 針DI/EDI。若加重復(fù)前綴REP,則表示將累加器的值連續(xù)送目的串存儲(chǔ)單元,直到CX/ECX=0時(shí)為止。
該指令不影響標(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個(gè)端口地址;
· 間接尋址方式,只能用DX作為地址寄存器,尋址范圍為64K字節(jié);
· 每個(gè)I/O地址對(duì)應(yīng)的端口的數(shù)據(jù)長(zhǎng)度為8位,傳送8位數(shù)據(jù)占用一個(gè)端口地址,傳送16位數(shù)據(jù)占用2個(gè)端口地址,傳送32位數(shù)據(jù)占用4個(gè)端口地址。
三、 串輸入指令
格式:[REP] INS DESTS, DX
[REP] INSB/INSW/INSD
功能:根據(jù)DX給出的端口地址,從外設(shè)讀入數(shù)據(jù)送入以ES:DI/EDI為地址的目的串存儲(chǔ)單元中,每輸入一次,均根據(jù)DF的值和串元素類(lèi)型自動(dòng)修改 DI/EDI的值。若加重復(fù)前綴REP,則表示連續(xù)從外設(shè)輸入串元素存入目的串存儲(chǔ)單元中,直到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的值和串元素類(lèi)型自動(dòng)修改SI/ESI的值,若加重復(fù)前綴REP,則表示連續(xù)向外設(shè)輸出串元素,直到CX/ECX=0時(shí)為止。
例 3.74 將內(nèi)存BLOCK為首地址的100個(gè)字符送往端口地址為2000H的外設(shè)。
·MODEL SMALL
·DATA
BLOCKDB ‘A,B,…’(100個(gè)字符)
·CODE
·STARTUP
CLD
LEA SI,BLOCK
MOV CX,100
MOV DX,2000H
REP OUTSB
·EXIT
END
在使用帶重復(fù)前綴的串輸入輸出指令時(shí),必須考慮端口的數(shù)據(jù)準(zhǔn)備或接收狀態(tài)。
所有輸入輸出指令均不影響標(biāo)志位。
3.3.7處理器控制
一、 總線封鎖前綴
格式:LOCK指令
功能:LOCK為指令前綴,可以使LOCK引腳變成邏輯0,在LOCK引腳有效期間,禁止外部總線上的其它處理器存取帶有LOCK前綴指令的存儲(chǔ)器操作數(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為存儲(chǔ)器操作數(shù),Reg為通用寄存器,imm為立即數(shù)。
二、空操作
格式:NOP
功能:空操作,除使IP/EIP增1外,不做任何工作。該指令不影響標(biāo)志位。
三、處理器等待指令
格式:WAIT
功能:檢查BUSY引腳狀態(tài),等待協(xié)處理器完成當(dāng)前工作。
四、處理器暫停指令
格式:HLT
功能:暫停程序的執(zhí)行。當(dāng)產(chǎn)生一個(gè)外部中斷或非屏蔽中斷時(shí),才繼續(xù)執(zhí)行下一條指令。
3.3.8中斷指令與DOS功能調(diào)用
一、中斷指令
在實(shí)模式下,中斷矢量以4個(gè)字節(jié)存放在中斷矢量表中,中斷矢量表為1k字節(jié)(00000H~003FFH),中斷矢量表允許存放256個(gè)中斷矢量,每 個(gè)中斷矢量包含一個(gè)中斷服務(wù)程序地址(段值和16位偏移地址),中斷矢量地址指針由中斷類(lèi)型碼乘以4得到。
在保護(hù)模式下,用中斷描述符表代替中斷矢量表,每個(gè)中斷由8個(gè)字節(jié)的中斷描述符來(lái)說(shuō)明,中斷描述符表允許256個(gè)中斷描述符,每個(gè)中斷描述符包含一個(gè)中斷服務(wù)地址(段選擇符、32位偏移地址、訪問(wèn)權(quán)限等)。中斷描述符地址指針由中斷類(lèi)型碼乘以8得到。
中斷指令格式:INT n
功能:產(chǎn)生中斷類(lèi)型碼為n的軟中斷,該指令包含中斷操作碼和中斷類(lèi)型碼兩部分,中斷類(lèi)型碼n為8位,取值范圍為0~255(00H~FFH)。
軟中斷執(zhí)行過(guò)程:
· 將標(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í)行過(guò)程:
· IRET指令彈出堆棧中數(shù)據(jù)送IP,CS,F(xiàn)LAGS;
· IRETD指令彈出堆棧中數(shù)據(jù)送EIP,CS,EFLAGS。
其它中斷類(lèi)指令如表311所示。
表 3.11 中斷類(lèi)指令

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