2020国产成人精品视频,性做久久久久久久久,亚洲国产成人久久综合一区,亚洲影院天堂中文av色

分享

X86匯編學(xué)習(xí)小結(jié)

 herowuking 2015-09-26

生成匯編代碼


比如,一個簡單的函數(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?),二者在語法上有一定的差異:

  • 注:本節(jié)內(nèi)容來自http://,文字和格式進(jìn)行了重新整理。

前綴/后綴

區(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語法,第一個是目的操作數(shù),第二個是源操作數(shù)。
  • AT&T中,第一個數(shù)是源操作數(shù),第二個數(shù)是目的操作數(shù)。(更符合閱讀習(xí)慣哈)

例子:

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

操作碼的后綴

  • 在AT&T的操作碼后加后綴,“l(fā)”(long,32位),“w”(word,16位),“b”(byte,8位)

  • 在Intel的語法中,在操作數(shù)的前加byte ptr、 word ptr 或 dword ptr

例子:

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

找個例子看看

  • hello.c

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ù)流方向見圖311。

    圖 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é)乘:ALSRC→AX
      字乘:AXSRC→DX∶AX
      雙字乘:EAXSRC→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)整方法:AH10+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。如圖312(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中,最高位(即符號位)保持不變。如圖312(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。如圖312(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,見圖313(a)所示,目的操作數(shù)左移,每移位一次,其最高位移入最低位,同時最高位也移入進(jìn)位標(biāo)志CF。循環(huán)右移指令 ROR見圖313(b)所示,目的操作數(shù)右移,每移位一次,其最低位移入最高位,同時最低位也移入進(jìn)位標(biāo)志CF。
      帶進(jìn)位循環(huán)左移指令RCL,見圖313(c)所示,目的操作數(shù)左移,每移動一次,其最高位移入進(jìn)位標(biāo)志CF,CF移入最低位。帶進(jìn)位循環(huán)右移指令RCR,見圖313(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)行左移,如 圖314(a)所示,SHRD是對目的操作數(shù)進(jìn)行右移,如圖314(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é),見表33。
      格式: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)移指令,見表34。
      例 3.61 JZ NEXT;若標(biāo)志ZF=1則轉(zhuǎn)移到標(biāo)號NEXT處執(zhí)行。
      (2) 無符號數(shù)比較條件轉(zhuǎn)移,見表35。
      例 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)移,見表37。


    表 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。如表38所示。

    表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ù)合指令,見表39。
      一、重復(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ī)定的目的串單元中,見表310。

    表 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。
      其它中斷類指令如表311所示。

    表 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ù)尋址方式有哪幾種?
    216位指令模式下和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) 有相同的功效。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多