x86指令集总结

首先回顾下一条完整汇编指令的组成:  [标号]:指令助记符 [操作数1] [, 操作数2] [; 注释] , 其中标号的使用取决于程序需要。指令助记符就是类似 MOV、ADD之类的。对于每一条指令如果要详细分析的话,可以关注以下几点:1. 指令的功能   2. 指令操作数的寻址方式   3. 指令对标志的影响  4. 指令的长度和执行时间。下面对x86的指令集做一个总结,x86的指令总体可以分为 数据传送、算术运算、逻辑运算、串操作、程序控制、处理器控制 六种。

一. 数据传送

1.1 传送指令MOV

> 格式: MOV DST, SRC

> 含义:将数据从SRC传到DST中

> 传送方向: SRC: 可以是寄存器、存储单元、立即数    DST: 可以是寄存器、内存,下图展示了MOV指令的数据传送方向

> 实现功能:

1). CPU内部寄存器之间的数据传递,但源和目的寄存器不能同时是段寄存器,代码段寄存器CS不能作为目的寄存器,指令指针IP既不能作为源也不能作为目的。           

 ; 通用寄存器 -> 通用寄存器
MOV AH, AL   
MOV DL, BH    
MOV BP, SP

; 段寄存器 -> 通用寄存器
MOV AX, CS


; 通用寄存器 -> 段寄存器
MOV DS, BX

; 错误的指令
MOV CS, BX     ; 代码段寄存器CS不能作为目的寄存器
MOV IP, BX     ; 指令寄存器不能作为目的寄存器, 也不能作为源寄存器
MOV AX, IP     
MOV DS, CS     ; 源和目的寄存器不能同时为源 和 目的寄存器

2). 立即数传递至通用寄存器 及 存储单元(各种寻址方式),但立即数不能直接传送到段寄存器,立即数不能作为目的操作数。

; 立即数 -> 通用寄存器
MOV  AL, 3
MOV  SI, -5
; 立即数 -> 存储单元
MOV  VARB, -1                   ; VARB是变量名,代表一个存储单元
MOV  VARW, 3456H                ; VARW是一个字变量
MOV  [SI], 6543H                ; 目的操作数是寄存器间接寻址

3). 寄存器和存储器之间的数据传送

; 寄存器 -> 存储器
MOV VARB,     DL
MOV [BP],      AX
MOV DS:[BP], DL
MOV VARW,    DS

; 存储器 -> 寄存器
MOV AX, VARW
MOV BH, [DI]
MOV DI,  ES: [SI+3]
MOV BP,  [BX+SI+3]
MOV ES,  VARW

> 注意:

1). 源操作数和目的操作数的类型必须是一致的,不能一个是字节,另一个是字

2). 源操作数和目的操作数不能同时是存储器操作数

; 由于不能在两个存储单元之间传送数据,那么可以利用通用寄存器过渡的方式进行
; 把字变量VARW1的内容送到字变量VARW2
MOV    AX,   VARW1
MOV    VAW2, AX 

; 段寄存器间的数据传送
MOV    AX,  CS    ; 把CS的内容送到DS
MOV    DS,  AX

1.2 交换指令

> 格式:XCHG OPRD1, OPRD2

> 含义:把操作数OPRD1和OPRD2的内容进行交换

> 传送方向:OPRD1 和 OPRD2 可以是通用寄存器和存储单元。但不包括段寄存器,不包括立即数,不能同时是存储单元,

> 实现功能:

1). 通用寄存器与通用寄存器的数据交换

XCHG   AL,  AH
XCHG   BX,  AX

2). 通用寄存器与存储单元的数据交换

XCHG    [SI+3],      AH
XCHG    [DI+BP+3],   BX

1.3 地址传送指令

> 格式:

1). LEA  REG, OPRD

2). LDS  REG, OPRD

3). LES   REG, OPRD

> 含义:

1). LEA(Load Effective Address),将操作数的有效地址传送到REG,OPRD必须是一个存储器操作数,操作数REG是一个通用寄存器

2). LDS(Load pointer indo DS),将OPRD中所含的一个32位地址指针的段值部分送到数据段寄存器DS,把偏移部分送到 REG 指示的通用寄存器中

3). LES(Load pointer into ES),将OPRD中所含的32位地址指针的段值部分送到附加段寄存器ES,把偏移部分送到指令给出的通用寄存器REG中

二. 堆栈操作指令

堆栈主要有4个用途:现场和返回地址的保护,寄存器内容的保护,传递参数,存储局部变量

> 格式:

1). PUSH SRC

2). POP   DST

> 含义:

1). PUSH SRC 就是将源操作数SRC压入堆栈。具体流程是,SUB ESP, 4 ;  MOV ESP, SRC, 注意,堆栈是从高地址往低地址方向生长

PUSH  SI             ; 通用寄存器入栈
PUSH  DS             ; 段寄存器入栈
PUSH  VARW           ; 存储单元入栈
PUSH  [SI]

2). POP   DST 就是从栈顶弹出一个数据,放入DST中。 具体流程是, MOV SRC, ESP ;  ADD ESP, 4

POP    [SI]     ; 弹出到存储单元
POP    VARW
POP    ES       ; 弹出到段寄存器 
POP    SI       ; 弹出到通用寄存器

> 方向:

1). PUSH指令的源操作数可以是 通用寄存器 和 段寄存器, 也可以是 存储单元

2). POP指令的目的操作数可以是 通用寄存器 和 段寄存器(CS不行), 也可以是存储单元

三.  标志操作指令

X86指令中有一部分是专门对标志寄存器或标志位进行的,包括4条标志寄存器传送指令 和 7条专门用于设置或清除某些标志位的指令

3.1 标志传送指令

1. LAHF(Load AH With Flags)

格式:LAHF

功能:将标志寄存器的低 8 位传送到寄存器 AH 的相应位中, 这条指令本身不影响标志寄存器本身的值

2. SAHF(Store AH into Flags)

格式:SAHF

功能:与LAHF指令相反,将AH的指定位传送至标志寄存器的低8位

3. PUSHF

格式: PUSHF

功能:将标志寄存器压入堆栈中

4. POPF

格式:POPF

功能:把当前堆栈顶的一个字传送到标志寄存器

3.2 标志位操作指令

1. CLC(CLear Carry flag)

格式: CLC

功能:清除进位标志,CLC使进位标志为0

2. STC(SeT Carry flag)

格式:STC

功能:置进位标志,STC使进位标志为1

3. CMC(CoMplement Carry falg)

格式:CMC

功能:使进位标志取反,如果CF为1,则CMC使得CF为0,反之亦然

4. CLD(Clear Direction flag)

格式:CLD

功能:清除方向标志,使方向标志w为0

5. STD(SeT Direction flag)

格式:STD

功能:置方向标志,使方向标志位1

6. CLI(Clear Interrupt enable flag)

格式:CLI

功能:清中断允许表示,使中断允许标志IF为0

7. STI(SeT Interrupt enable flag)

格式:STI

功能:置中断允许标志,使中断允许标志为1

四. 加减运算指令

4.1 加法指令

1. 普通加法指令ADD(ADDition)

> 格式:ADD OPRD1, OPRD2

> 功能:OPRD1 = OPRD1 + OPRD2

> 举例:

; 列举ADD指令用法及其对标志寄存器的影响
MOV AX, 7896H   ; AX = 7896H,AH = 78H,AL = 96H, 不影响标志位
ADD AL, AH      ; AL = 0EH, CF = 1, AX = 780EH
                ; 无符号角度有进位, 结果不为0,符号位为0,有符号角度未溢出,低字节向高字节产生进位,结果中1的个数为奇数CF = 1, ZF = 0, SF = 0, OF = 0, AF = 0, PF = 0
 
ADD AH, AL      ; AH = 86H, AX = 860EH
                ; 无符号数角度无进位,结果不为0, 符号位为1, 有符号数角度有溢出,低字节向高字节产生了进位,结果中1的个数为奇数 CF = 0, ZF = 0, SF = 1, OF = 1, AF = 1, PF = 0
ADD AL, 0F2H    ; AL = 00H, CF = 1, AX = 8600H
                ; 无符号数角度有进位,结果为0, 符号位为0, 有符号数角度无溢出,低字节向高字节产生了进位,结果中1的个数为偶数  CF = 1, ZF = 1, SF = 0, OF = 0, AF = 1, PF = 1
ADD AX, 1234H   ; AX = 9834H 
                ; CF = 0, ZF = 0, SF = 1, OF = 0, AF = 0, PF = 0

2. 带进位的加法指令ADC(ADd with Carry)

> 格式: ADD OPRD1, OPRD2

> 功能: OPRD1 = OPRD1 + OPRD2 + CF   在完成两个数相加的时候还要将CF的现行值加上去,把结果送至目的操作数OPRD1中

ADC指令主要用于多字节运算中。16位(两字节)运算能表达的整数的范围还是很有限的,为了扩大数的范围,需要进行多字节的运算。例如,有四个字节的数相加,加法要分两次进行,先进行低两字节相加,然后再做高两字节相加。在高两字节相加时,要把低两字节相加以后可能出现的进位考虑进去

> 举例:

MOV  AX, FIRST1        ; FIRST1是存放第一个数低两字节的变量
ADC  AX, SECOND1       ; SECOND1是存放第二个数低两字节的变量
MOV  THIRD1, AX        ; 保存低两字节相加的结果到THIRD1变量中
MOV  AX, FIRST2        ; FIRST2是存放第一个数高两字节的变量
ADC  AX, SECOND2      ; SECOND2是存放第二个数高字节的变量
MOV  THIRD2, AX        ; 保存结果的高两字节到THIRD2变量中 

3. 加1指令INC(INCrement)

> 格式: INC OPRD

> 功能: OPRD = OPRD + 1   这条指令完成对操作数OPRD加1操作,然后把结果送到OPRD中

> 举例:

// INC指令的操作数可以是通用寄存器也可以是存储单元
// 本条指令执行的结果影响标志 ZF, SF, OF,PF, AF, 但不影响CF(因为只加1怎么地也影响不到最高位?)
INC  AL
INC  VARB    ; VARB是字节变量

4.2 减法指令

1. 普通减法指令SUB(SUBtraction)

> 格式: SUB OPRD1, OPRD2

> 功能: OPRD1 = OPRD1 + OPRD2

> 举例:

; 演示SUB指令对标志寄存器的影响
MOV BX, 9048H      ; BH = 90H, BL = 48H
SUB  BH, BL        ; BH = 48H, BX = 4848H
                   ; CF = 0, ZF = 0, SF = 0, OF = 0, AF = 0, PF = 1
SUB  BL, BH        ; BL = 00H, BX = 4800H
                   ; CF = 0, ZF = 1, SF = 0, OF = 0, AF = 0, PF = 1
SUB  BL, 5         ; BL = FBH, BX = 48FBH
                   ; CF = 1, ZF = 0, SF = 1, OF = 0, AF = 1, PF = 0
 
SUB BX, 8F34H      ; BX = B9C7H
                   ; CF = 1, ZF = 0, SF = 1, OF = 1, AF = 0, PF = 0

2. 带进(借)位减指令SBB(SuBtract with Borrow)

>  格式: SBB OPRD1, OPRD2

>  功能: OPRD1 = OPRD1 – OPRD2 – CF, 与SUB指令类似,但是在OPRD1减去OPRD2的同时还要减借位(进位)标志CF的先行值

> 举例:

SBB AL, DL
SBB DX, AX 

3. 减1指令DEC(DECrement)

> 格式:DEC OPRD

> 功能:OPRD = OPRD – 1, 操作数OPRD可以是通用寄存器也可以是存储单元,在相减时是把操作数作为一个无符号数对待的。

> 举例:

DEC  BX
DEC  VARB

4. 取补指令NEG(NEGate)

> 格式: NEG OPRD

> 功能: OPRD = 0 – OPRD, 对操作数取补,也就是用零减去操作数OPRD,再把结果送回OPRD

5. 比较指令CMP(CoMPare)

> 格式:CMP OPRD1, OPRD2

> 功能:将 OPRD1 – OPRD2,运算结果不送到OPRD1,但会影响到 CF, ZF, SF, OF, AF 和 PF 等标志位。 在执行了比较指令后,可根据ZF是否置位,判断两者是否相等;如果是无符号数,可根据CF判断大小;如果是有符号数,则要根据SF和OF判断大小。

> 举例: 现假设有两个64位数按”高高低低”的原则存放在同一个段的的两个缓冲区DATA1和DATA2中,现在需要计算DATA1-DATA2。

......
    MOV    CX, 4            ; 64位数,寄存器是16位,需要分四次计算
    SUB    BX, BX           ; 清指针
NEXT:    MOV  AX, DATA2[BX]              ; 取被减数
         SBB  DATA1[BX], AX              ; 带进位减
         INC  BX           ; 调整指针 + 2,因为每次计算16位
         INC  BX
         SUB  CX           ; 是否已经处理完4个字节
         JNZ  NEXT         ; 没完,继续
......

五. 乘除运算指令

5.1 乘法指令

在乘法指令中,一个操作数总是隐含在寄存器AL(8位数相乘)或者AX(16位数相乘)中,另一个操作数可以采用除了立即数寻址之外的任意一种寻址方式。

1. 无符号数乘法指令MUL(MULtiply)

> 格式: MUL OPRD

> 功能: 如果OPRD是字节操作数,则 AX = AL * OPRD; 如果OPRD是字操作数,则 DX:AX = AX * OPRD,32位运算结果中,高16位存放于DX寄存器中,低16位存放于AX寄存器中

对标志位的影响: 乘积结果的高半部分不等于零,则 CF = 1, OF = 1, 否则 CF = 0, OF = 0 ; 反过来可看出,当 CF = 1, OF = 1 的时候, AH 或者 DX 不为零,包含有效结果。

> 举例:

MUL  BL           ;  AX = AL * BL
MUL  AX           ;  DX:AX = AX * OPRD
MUL  VARW         ;  DX:AX = AX * VARW

2. 有符号数乘法指令IMUL(sIgned MULtiply)

> 格式: IMUL OPRD

> 功能: 这条指令与MUL指令基本相同,唯一的区别是其把 被乘数 和 乘数 均作为有符号数

对标志位的影响:乘积的高半部分不是低半部分的符号扩展,则CF =1, OF =1,否则 CF = 0, OF = 0 ;反过来可看出,当CF=1,OF=1 的时候,AX或者DX中有结果的有效数。

> 举例:

IMUL CL          
IMUL DX
IMUL VARW

5.2 除法指令

在除法指令中,被除数总是隐含在寄存器AX(除数是8位)或者DX和AX中(除数是16位),另一个操作数可以采用除了立即数寻址之外的任意一种寻址方式。

1. 无符号数除法指令DIV(DIVision)

> 格式: DIV   OPRD

> 功能: 如果OPRD是字节操作数,则 AL = AX / OPRD ; 如果OPRD是字操作数,则 AX : DX = DX : AX / OPRD,16位的商送到AX, 16位的余数送到DX中

> 举例:

DIV BL                 ; AL = AX / BL
DIV SI                 ; AX : DX = DX:AX / OPRD
DIV VARW               ; VARW 是字变量   AX : DX = DX : AX / OPRD

注意:如果除数为0,或者在8位数时商超过8位,或者在16位除时商超过16位,则被认为是除溢出,会引起0号中断, 另,除法指令对标志位的影响无定义

2. 有符号数除法指令IDIV(sIgned DIVision)

> 格式: IDIV OPRD

> 功能:除了将被除数和除数都作为有符号数,其他与指令DIV完全类似

> 举例:

IDIV CX
IDIV VARW            ; VARW 是字变量

注意:当除数为0,或者商太大(字节除时超过127,字除时超过32767),后者商太小(字节除时小于-127,字除时小于-32767)时,则引起0号中断。

5.3 符号扩展指令

1. 字节转换为字指令CBW(Convert Byte to Word)

> 格式:CBW

> 功能:将寄存器AL中的符号 扩展 到寄存器 AH 中,若AL的最高位为0,则执行这条指令后AH=0; 若AL的最高有效位为1,则AH=0FFH

> 举例:

MOV  AX, 3487H   ; AH = 34H, AL = 87H
CBW              ; AH = 0FFH, AL = 87H, AH = FF87H

2. 字转换为双字指令CWD(Convert Word to Double word)

> 格式:CWD

> 功能:将寄存器AX中的符号扩展到寄存器DX中,若AX的最高有效位为0,则DX=0; 若AX的最高有效位为1,则DX=0FFFFH

> 举例:

MOV AX, 4567H   ; AX = 4567H
CWD             ; DX = 0H

六. 逻辑运算和移位指令

6.1 逻辑运算指令

1. 否操作指令NOT

> 格式:NOT OPRD

> 功能:把操作数OPRD取反后再送到OPRD中,OPRD可以是通用寄存器或者存储器操作数,该指令对标志位没有影响

2. 与操作指令AND

> 格式:AND OPRD1, OPRD2

> 功能:对两个操作数进行按位的逻辑”与”操作,结果送到OPRD1中。标志ZF、PF和SF反映了运算结果,标志CF和OF被清0,标志AF未定义。如果想要使操作数中的若干位保持不变,则与1进行与操作;需要清零的位,则与0进行与操作

> 举例:

AND  DH, DH
AND  AX,  ES: [SI]

3. 或操作指令OR

> 格式:OR OPRD1, OPRD2

> 功能:对两个操作数进行按位的逻辑”或”操作,结果送到目的操作数OPRD1。标志ZF、PF和SF反映了运算结果,标志CF和OF被清0,标志AF未定义。如果想要使操作数中的若干位保持不变,则与0进行或操作;另外一些位置1,则与1进行或操作

> 举例:

OR AX, 8080H
OR CL, AL
OR [BX-3], AX

4. 异或指令XOR

> 格式:XOR OPRD1, OPRD2

> 功能:将两个操作数进行异或操作(0与0异或是0, 0与1异或是1,1与1异或是0),结果送到操作数OPRD1中。该指令执行后,标志ZF、PF和SF反映了运算结果,标志CF和OF被清0,标志AF未定义。如果想要使得操作数中的某部分保持不不变,则用0与之异或;使某些部分取反,则用1与之异或。自己与自己异或得0,并可使标志位CF清0

> 举例:

; 作用一:清零
XOR DX, DX         ; DX = 0, CF = 0 
; 作用二:某些位取反,某些位保持不变
MOV AX, 1234H      ; AH = 12H, AL = 34H
XOR  AX, FF30H     ; 执行后,有  AX = ED04 

5. 测试指令TEST

> 格式:TEST OPRD1, OPRD2

> 功能:把两个操作数进行按位”与”,但结果不送到操作数OPRD1,仅仅影响标志。该指令执行后,标志ZF、PF和SF反映了运算结果,标志CF和OF被清0,该指令通常用于检测某位是否为1,但又不希望改变操作数的值的情况下。

> 举例:

TEST AL, 0100 0010B   ; 检查AL中的第2位和第7位是否为0,当全为0的时候,ZF = 0;否则,ZF = 1

6.2 一般移位指令

; m表示移位的位数,为1 或者 CL, 当要移动多个位时,移位位数需放在CL寄存器中,操作数OPRD可以是通用寄存器也可以是存储器操作数
; 该指令执行后会影响PF、SF和ZF,OF会受影响,但标志AF未定义
SAL OPRD, m    ; 算术左移指令(同逻辑左移指令)
SHL OPRD, m    ; 逻辑左移指令
SAR OPRD, m    ; 算术右移指令
SHR OPRD, m    ; 逻辑右移指令

首先先看下面的移位指令示意图:

1. 算术左移或逻辑左移指令SAL/SHL(Shift Arithmetic Left 或 SHift logic Left)

> 格式: SAL OPRD, m 或者  SHL OPRD, m

> 功能: 把操作数OPRD左移m位,每移动一位,右边用0补足一位,移出的最高位进入标志位CF。每左移一次,相当于原数乘2

> 举例:

MOV AL, 8CH     ; AL = 8CH
SHL AL, 1      ; AL = 18H, CF = 1, PF = 1, ZF = 0, OF = 1
MOV CL, 6
SHL AL, CL     ; AL = 0, CF = 0, PF = 1, ZF = 1 SF = 0, OF = 0

2. 算术右移指令SAR(Shift Arithmetic Right)

> 格式:SAR OPRD, m

> 功能:把操作数右移m位,同时每移动一位,左边的符号位保持不变,移出的最低位进入标志位CF。对于有符号数和无符号数而言,算术右移相当于除以2

3. 逻辑右移指令SHR(SHift logic Right)

> 格式:SHR OPRD, m

> 功能:把操作数右移m位,同时每移动一位,左边用0补足,移出的最低位进入标志位CF中。对于无符号数而言,逻辑右移相当于除以2

6.3 循环移位指令

; 与一般移位指令类似,m表示移动多少位,可以为1或者是CL寄存器
ROL    OPRD, m    ; 左循环移位指令,ROtate Left
ROR    OPRD, m    ; 右循环移位指令,ROtate Right
RCL    OPRD, m    ; 带进位的左循环移位指令,Rotate Left through CF
RCR    OPRD, m    ; 带进位的右循环移位指令,Rotate Right through CF

根据下面的循环移位指令示意图可以清晰的看出它们的作用:

1. 左循环移位指令,每移位一次,操作数左移,其最高位会移入最低位也会移入进位标志CF中

2. 右循环移位指令,每移位一次,操作数右移,其最低位会移入最高位也会移入进位标志CF中

3. 带进位左循环移位指令,每移位一次,操作数左移,其最高位移入进位标志CF,而CF移入最低位

4. 带进位右循环移位指令,每移位一次,操作数右移,其最低位进入进位标志CF,而CF移入最高位

注意:对于不带进位的循环移位指令而言,如果操作数是8位,那么在移位8次后,操作数就能复原;同理,如果操作数是16位,那么移位16次后,操作数就能复原。

对于带进位的循环移位指令而言,如果操作数是8位,那么在移位9次后,操作数就能复原;如果操作数是16位,那么在移位17次后,操作就能复原。

七. 转移指令

7.1 无条件转移指令

1. 无条件段内直接转移指令

> 格式:JMP 标号

其对应的及其指令格式如下,由操作码和地址差值构成:  指令操作码  地址差,地址差表示的是该无条件转移指令的下一条指令的地址到转移目标地址的差值,由汇编程序在汇编时计算得出。在执行无条件段内转移指令的时候,实际的动作是把指令中的地址差加到指令指针IP上,使IP的内容为目标地址,从而达到转移的目的。

请看下面的示意图,JMP指令转换成机器码的格式为:  OP 1131 ,1131表示的是地址差值,为下一条指令的地址(567B)到转移目标地址的差值(67AC-567B == 1131H),该条指令最后后,IP = 67AC,自然会转到 MOV AX, 1这条指令去执行了

> 功能:控制无条件的转移到标号地址处

> 举例:

NEXT:    MOV    AX, CX
            ......
         JMP     NEXT            ; 转NEXT处
            ......
         JMP     OVER            ; 转OVER处
            ......
OVER:    MOV    AX, 1

2. 无条件段内间接转移指令

> 格式:JMP OPRD

> 功能:使控制无条件地转移到由操作数OPRD的内容给定的目标地址处。操作数OPRD可以是通用寄存器,也可以是字存储单元。

> 举例:

JMP    CX    ; CX寄存器的内容送到IP
JMP    WORD PTR [1234H];    ; 字存储单元[1234H]的内容送IP

上面的示意图描述的就是: JMP WORD PTR[1234H] 这条指令的执行结果,指令 op 1234H 指示转移到1234H指示的 5678地址处,即为后面的MOV AX,1 指令的位置

3. 无条件段间直接转移指令

> 格式: JMP FAR PTR 标号

> 功能: 使控制无条件转移到标号所对应的地址处。标号前的符号”FAR PTR”向汇编程序说明这是段间偏移。无条件段间直接转移指令的机器指令格式是这样的: 指令操作码 目标地址偏移 目标地址段值,由操作码及包含段值和偏移的地址构成,它执行的具体动作就是把指令中包含的目标地址的段值和偏移分别置入CS和IP中,这种方式也被称之为绝对转移。

> 举例:

JMP     FAR PTR EXIT        ; EXIT是定义在另一个代码段中的标号

4. 无条件段间间接转移指令

> 格式:JMP OPRD

> 功能:使控制无条件地转移到由操作数OPRD的内容给定的目标地址处。操作数OPRD必须是双字存储单元。

> 举例:

JMP DWORD PTR [1234H]      ; 双字存储单元的低字内容送IP, 双字存储单元的高字内容送CS

7.2 条件转移指令(段内转移)

条件转移指令是用的最多的转移指令。通常情况下,在条件转移指令钱,总有用于条件判别的有关指令

1. 条件转移是根据某标志位或某些标志位的逻辑运算来判断条件是否成立,如果条件成立,则转移,否则继续顺序执行。

2. 所有的条件转移都是段内转移。

3. 它的实现是采用相对转移的方式,即通过在IP上加上一个地址差的方法来实现转移。

4. 条件转移指令对标志位无影响

5. 无符号数之间大小比较后的条件转移指令和有符号数之间的大小比较后的条件转移指令有很大不同。有符号数间的次序关系称为大于(G)、等于(E)和小于(L);无符号数间的次序关系称为高于(A),等于(E)和低于(B)

指令的格式见下表所示:

指令格式 转移条件 转移说明 其他说明
JZ 标号

JE 标号

ZF = 1

ZF = 1

等于0转移

或者,相等转移

单个标志
JNZ 标号

JNE 标号

ZF = 0

ZF = 0

不等于0转移

或者,不相等转移

单个标志
JS 标号

JNS 标号

SF = 1

SF = 0

为负转移

为正转移

单个标志
JO 标号

JNO 标号

OF = 0

OF = 1

溢出转移

不溢出转移

单个标志
JP 标号

JPE 标号

JNP 标号

JPO 标号

PF = 1

 

PF = 0

偶转移

 

奇转移

单个标志
JB 标号

JNAE 标号

JC 标号

CF = 1

CF = 1

CF = 1

低于转移

或者,不高于等于转移

胡总和,进位标志被置转移

无符号数

单个标志位

JNB 标号

JAE 标号

JNC 标号

CF = 0

CF = 0

CF = 0

不低于转移

或者,高于等于转移

或者,进位标志被清转移

无符号数

单个标志位

JBE 标号

JNA 标号

(CF 或 ZF ) = 1

(CF 或 ZF ) = 1

低于等于转移

或者,不高于转移

两个标志

无符号数

JNBE 标号

JA 标号

(CF 或 ZF ) = 0

(CF 或 ZF ) = 0

不低于等于转移

或者,高于转移

两个标志

无符号数

JL 标号

JNGE 标号

(SF 异或 OF) = 1

(SF 异或 OF) = 1

小于转移

或者,不大于等于转移

两个标志

有符号数

JNL 标号

JGE 标号

(SF 异或 OF) = 0

(SF 异或 OF) = 0

不小于转移

或者,不大于等于转移

两个标志

有符号数

JLE 标号

JNG 标号

((SF 异或 OF)或ZF)=1

((SF 异或 OF)或ZF)=1

小于等于转移

不大于转移

三个标志

有符号数

JNLE 标号

JG 标号

((SF 异或 OF)或ZF)=0

((SF 异或 OF)或ZF)=0

不小于等于转移

大于转移

三个标志

有符号数

举例:

例子一: 测试AX的低四位是否全是0,如果全是0,那么使CX=0,否则使CX=-1

MOV    CX, -1
TEST   AX, 0FH
JNZ    NZERO        ; 不全为0的时候转移
MOV    CX, 0          

NZERO: ......

例子二:比较两个数,把比较大的数放到AX中,把较小的数放到BX中

CMP    AX, BX
JAE     OK            ; 无符号数比较大小转移
XCHG    AX, BX

OK: ......
CMP    AX, BX
JGE     OK            ; 有符号数比较大小转移
XCHG    AX, BX

OK: ......

7.3 循环指令

1. 计数循环指令LOOP

> 格式:LOOP 标号

> 功能:使寄存器CX的值减1,如果结果不等于0,则转移到标号,否则顺序执行LOOP指令后的指令。类似于这两条指令的组合: DEC CX ;  JNZ 标号

> 举例:把从偏移1000H开始的512个字节的数据复制到从偏移3000H开始的缓冲区中

    MOV    SI, 1000H     ; 置源指针   
    MOV    DI, 3000H     ; 置目标指针
    MOV    CX, 512       ; 置计数初值
NEXT:
    MOV    AL, [SI]
    INC     SI
    MOV   [DI], SI
    INC    DI
    LOOP    NEXT         ; 控制循环

2. 等于/全零循环指令LOOP/LOOPZ

> 格式:LOOPE 标号   或者   LOOPZ 标号

> 功能:使寄存器CX的值减1,如果结果不等于0,并且零标志ZF等于1,那么则转移到标号,否则顺序执行,指令本身的使寄存器CX减1的操作不影响标志

> 举例:在字符串中查找第一个非’A’的字符,假设字符串长度已经保存在CX中,并且DS:DI指向字符串,如果找到,那么使BX指向该非’A’字符,如果找不到,那么使BX = 0FFFFH

    MOV AL,    'A'
    DEC    DI
NEXT   :
    INC    DI
    CMP    AL, [DI]
    LOOPE    NEXT
    
    MOV    BX, DI
    JNE     OK
    MOV    BX, -1

OK :
    .....

3. 不等于/非零循环指令LOOPNE/LOOPNZ

> 格式:LOOPNE 标号  或者  LOOPNZ 标号

> 功能:使寄存器CX的值减1,如果结果不等于0,且零标志ZF等于0,那么则转移到标号,否则顺序执行。

4. 跳转指令JCXZ

> 格式:JCXZ 标号

> 功能:当寄存器CX的值等于0时转移到标号,否则顺序执行。

> 举例:通常本条指令用在循环开始之前,以便在循环次数为0的时候,跳过循环体

    ......
    JCXZ    OK        ; 如果循环计数为0,就跳过循环
NEXT:    ......
         ......
    LOOP    NEXT      ; 根据计数控制循环
OK:      ......



发表评论

电子邮件地址不会被公开。 必填项已用*标注