8086汇编学习笔记15

标志寄存器(下)

系列文章

CMP指令

CMP 是比较指令, CMP 的功能相当于减法指令,只是不保存结果。CMP指令执行后,将对标志寄存器产生影响,其它相关指令通过识别这些被影响的标志寄存器位来得知比较的结果。
CMP指令(比较指令)
格式:
CMP operand1 , operand2
用途:
计算 operand1-operand2 ,但不保存结果,仅仅根据计算结果对标志寄存器进行设置。

例如,指令:

mov ax, 8
mov bx, 3
cmp ax, bx

执行后:

(AX)=8ZF=0PF=1SF=0CF=0OF=0

通过 CMP 指令执行后,标志寄存器的值变化,便记录了相应的比较结果。指令“ CMP AX, BX ”的逻辑含义是比较 AXBX 中的值 ,执行后:

标志寄存器的值 结论
ZF=1 (AX)=(BX)
ZF=0 (AX)≠(BX)
CF=1 (AX)<(BX)
CF=0 (AX)≥(BX)
CF=0 并且 ZF=0 (AX)>(BX)
CF=1ZF=1 (AX)≤(BX)
以上结论是对无符号数据而言的,以下是对有符号数据使用“ CMP AH, BH ”指令进行比较的一些结论:

OF=0 表示没有溢出,逻辑上真正的结果正负=实际结果的正负;
由于 SF=1 ,实际结果为负,故逻辑上的结果为负,即 (AH)<(BH)

OF=1 表示发生溢出,SF=1 表示结果为负;
因此溢出导致了实际结果为负,逻辑上真正的结果必然为正,故 (AH)>(BH)

OF=1 表示发生溢出,SF=0 表示结果为正;
因此溢出导致了实际结果为正,逻辑上真正的结果必然为负,故 (AH)<(BH)

OF=0 ,表示没有发生溢出,而 SF=0 ,实际结果非负; 因此逻辑上真正的结果非负,即 (AH)≥(BH)

比较结果的条件转移指令

除了 JCXZ ,8086CPU还提供了其它转移指令,大多数条件转移指令都检测标志寄存器的相关标志位,根据检测结果来决定是否修改 IP

下面列出了常用的根据无符号数的比较结果进行转移的条件转移指令,这些条件转移指令通常配合 CMP 指令使用,通过检测 flag 标志位来进行转移:

指令 表示 含义 检测的相关标志位
JE equal 等于则转移 ZF=1
JNE not equal 不等于则转移 ZF=0
JB below 低于则转移 CF=1
JNB not below 不低于则转移 CF=0
JA above 高于则转移 CF=0ZF=0
JNA not above 不高于则转移 CF=1ZF=1

以下程序实现了“如果 (AH)>(BH) ,则 (AH)=(AH)-(BH) ,否则 (BH)=(BH)-(AH) ”:

    cmp ah, bh
    ja _true
    sub bh, ah
    jmp short _finally
_true:
    sub ah, bh
_finally:
    ; ...

DF标志和串传送指令

flag的第10位是DF,方向标志位在串处理指令中,控制每次操作后 SIDI 的增减

MOVSB指令(串传送指令)
格式:
MOVSB
用途:
执行 MOVSB 指令相当于进行下面几步操作:
  1. ES:DI 指向内存的值被修改为 DS:SI 指向内存的值
  2. 如果 DF=0 ,则 SIDI 都自增1
  3. 如果 DF=1 ,则 SIDI 都自减1

可以看出,MOVSB 的功能是将 DS:SI 指向的内存单元中的字节送入 ES:DI 中,然后根据标志寄存器 DF 位的值,将 SIDI 递增或递减。

当然,也可以传送一个字,指令如下:

MOVSW指令(串传送指令)
格式:
MOVSW
用途:
执行 MOVSW 指令类似于 MOVSW ,只是一次送入一个字的数据。同时将 SIDI 递增2或递减2:
MOVSBMOVSW 进行的是串传送指令操作的一个步骤,一般来说,MOVSBMOVSW 都和 REP 指令配合使用,格式如下:
REP MOVSB / REP MOVSW

用汇编语法描述“ REP MOVSB ”的功能就是:

s: movsb
    loop s

因此,REP 的作用是根据 CX 的值,重复执行后面的串传送指令。由于每执行一次 WOVSB 指令都会使 SIDI 递增或递减后指向后一个或前一个字节单元,则 REP MOVSB 就可以循环实现 (CX) 个字符的传送。

类似也可以应用:REP MOVSW

8086CPU提供下面两条指令对DF位进行设置:

以下程序利用串传送指令将 datas 段中的第一个字符串复制到它后面的空间中:

assume cs: codes, ds: datas
datas segment
    db 'hello, world    '
    db 16 dup (0)
datas ends
codes segment
start:
    mov ax, datas
    mov ds, ax
    mov si, 0   ; source position = DS:SI
    mov es, ax
    mov di, 16  ; destination position = ES:DI
    mov cx, 16  ; length = 16
    cld         ; positive
    rep movsb
    mov ax, 4c00h
    int 21h

汇编指令PUSHF和POPF

PUSHF指令(标志入栈指令)
格式:
PUSHF
用途:
将标志寄存器的值入栈
POPF指令(标志入栈指令)
格式:
POPF
用途:
将标志寄存器的值出栈

PUSHFPOPF 指令,为直接访问标志寄存器提供了一种方法。