标记寄存器---汇编学习笔记

标记寄存器

CPU内部的寄存器中,有一种特殊的寄存器(对于不同的处理机,个数和结构都可能不同)具有以下3种作用

(1)用来存储相关指令的某些执行结果。
(2)用来为CPU执行相关指令提供行为依据。
(3)用来控制CPU的相关工作方式。

这种特殊的寄存器在8086CPU中,被称为标志寄存器(flag)。如图:
这里写图片描述


11.1 ZF标志

flag的第6位是ZF,零标志位。它记录相关指令执行后,其结果是否为0。如果结果为0那么zf=1;如果不为0,那么zf=0。

运算指令的执行对标志寄存器会产生影响,而传送指令对标志寄存器不会产生影响

比如:

mov ax,1    ;不对标志寄存器产生影响
sub ab,1    ;对标志寄存器产生影响,并且zf=1

11.2 PF标志

flag的第2位是PF,奇偶标志位。它记录相关指令执行后,其结果的所有bit位中1的个数是否为偶数。如果1的个数为偶数,pf=1,如果为奇数,那么pf=0。

比如:

mov al,1     ;不影响标志寄存器
add al,10    ;影响标志寄存器,并且1的个数为奇数,pf=0

11.3 SF标志

flag的第7位是SF,符号标志位。它记录相关指令执行后,其结果是否为负。如果结果为负,sf=1;如果非负,sf=0。

检测点 11.1
写出下面指令执行后,ZF、PF、SF等标志位的值。

指令ZFPFSF
sub al,al110
mov al,1000
push ax——————
pop bx——————
add al,bl000
add al,10010
mul al011


11.4 CF标志

flag的第0位是CF,进位标志位。一般情况下,在进行无符号数运算的时候,它记录了运算结果的最高有效位向更高位的进位值,或从更高位的借位值。如图(加法器的Ci进位,i=7):
这里写图片描述

加法减法都会产生借位:
(1)加法比如:

mov al,98H
add al,al     ;执行后:(al)=30H,CF=1,CF记录了从更高有效位向更高的进位值

(2)减法比如:

mov al,97H
sub al,98H    ;执行后:(al)=FFH,CF=1,CF记录了向更高位进行借位值

11.5 OF标志

flag的第11位是OF,溢出标志位。一般情况下,OF记录了有符号数运算的结果是否发生了溢出。如果发生溢出,OF=1;如果没有,OF=0。

注意CF和OF的区别:CF是对无符号位数运算有意义的标志位,而OF是对有符号数运算有意义的标志位

比如:

mov al,0f0h    ;有符号为-10,无符号为240
add al,78h     ;有无符号都为120
;进行无符号运算则发生溢出,进行有符号运算将不溢出
;则cf=1,of=0

检测点 11.2
写出下面每条指令执行后,ZF、PF、SF、CF、OF等标志位的值。

指令CFOFSFZFPF
sub al,al00011
mov al,10h——————————
add al,90h00101
mov al,80h——————————
add al,80h11011
mov al,0fch——————————
add al,05h10000
mov al,7dh——————————
add al,0bh11000


11.6 adc指令

adc是带进位加法指令,它利用了CF位上记录的进位值

指令格式:adc 操作对象1,操作对象2
功能:操作对象1=操作对象1+操作对象2+CF

例子:
编程,计算1EF000H+201000H,结果放在ax(高16位)和bx(低16位)中。

mov ax,001eh
mov bx,0f000h
add bx,1000h     ;标志寄存器cf置1
adc ax,0020h     ;(ax)=(ax)+0020h+cf

编写一个子程序,对两个128位数据进行相加。
名称: add128
功能:两个128位数据进行相加。
参数:
*参数1:*ds:si指向存储第一个数的内存空间,因数据为128位,所以需要8个字单元,由低地址单元到高地址单元一次存放128位数据由低到高的各个字。运算结果存储在第一个数的存储空间中。
*参数2:*ds:di指向存储的第二个数的内存空间。

程序如下:

add128:
    push ax
    push cx
    push si
    push di

    sub ax,ax   ;将cf置0

    mov cx,8
s:
    mov ax,[si]
    adc ax,[di]
    mov [si],ax
    add si,2
    add di,2
    loop s

    pop di
    pop si
    pop cx
    pop ax
    ret

11.7 sbb指令

sbb是带借位减法指令,它利用了CF位上记录的借位值

指令格式:sbb 操作对象1,操作对象2
功能:操作对象1 = 操作对象1-操作对象2-CF

与adc具有相同的思想设计


11.8 cmp指令

cmp是比较指令,cmp的功能相当于减法指令,只是不保存结果。cmp指令执行后,将对标志寄存器产生影响

cmp指令格式:cmp 操作对象1,操作对象2
功能:计算操作对象1-操作对象2但并不保存结果,仅仅根据计算结果对标志寄存器进行设置

比如:cmp ax,ax指令执行后:zf=1,pf=1,sf=0,cf=0,of=0。

执行cmp ax,bx后:

  1. 如果(ax)=(bx) 则(ax)-(bx)=0,所以:zf=1
  2. 如果(ax)!=(bx) 则(ax)-(bx)!=0,所以:zf=0
  3. 如果(ax)<(bx) 则(ax)-(bx)将产生借位,所以:cf=1
  4. 如果(ax)>=(bx) 则(ax)-(bx)不必借位,所以:cf=0
  5. 如果(ax)>(bx) 则(ax)-(bx)即不必借位,结果又不为0,所以:cf=0并且zf=0
  6. 如果(ax)<=(bx) 则(ax)-(bx)既可能借位,结果可能为0,所以:cf=1或zf=1

显然,除了上面那样还不够!

还需要sf和of一起作用(记住,of=1溢出导致实际结果与逻辑结果相反):
这里写图片描述


11.9 检测比较结果的条件转移指令

“转移”指的是它能够修改IP,而“条件”指的是它可以根据某种条件,决定是否修改IP

指令含义检测的相关标志位
je等于则转移zf=1
jne不等于则转移zf=0
jb低于则转移cf=1
jnb不低于则转移cf=0
ja高于则转移cf=0且zf=0
jna不高于则转移cf=1或zf=1

e:表示equal
ne:表示not equal
b:表示below
nb:表示not below
a:表示above
na:表示not above

检测点 11.3
(1)补全下面的程序,统计F000:0处32个字节中,大小在[32,128]的数据的个数。

assume cs:code

code segment
    start:
        mov ax,0f000h
        mov ds,ax
        mov bx,0
        mov dx,0
        mov cx,32
    s:  
        mov al,[bx]
        cmp al,32
        ;低于32
        jb s0
        cmp al,128
        ;高于128
        ja s0
        ;如果在范围内,则+1
        inc dx
    s0:
        ;如果不在范围内,则+1
        inc bx
        loop s
code ends
end start

(2)补全下面的程序,统计F000:0处32个字节中,大小在(32,128)的数据个数。

assume cs:code

code segment
    start:
        mov ax,0f000h
        mov ds,ax
        mov bx,0
        mov dx,0
        mov cx,32
    s:  
        mov al,[bx]
        cmp al,32
        ;不高于是<=
        jna s0
        cmp al,128
        ;不低于是>=
        jnb s0
        ;如果在范围内,则+1
        inc dx
    s0:
        ;如果不在范围内,则+1
        inc bx
        loop s
code ends
end start

11.10 DF标志和串传送指令

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

格式:movsb
功能:执行movsb指令相当于进行下面几步操作。
(1) ((es)16+(di))=((ds)16+(si)) ( ( e s ) ∗ 16 + ( d i ) ) = ( ( d s ) ∗ 16 + ( s i ) )
(2)如果df=0则: (si)=(si)+1,(di)=(di)+1 ( s i ) = ( s i ) + 1 , ( d i ) = ( d i ) + 1
(3)如果df=1则: (si)=(si)1,(di)=(di)1 ( s i ) = ( s i ) − 1 , ( d i ) = ( d i ) − 1

格式:movsw
功能:将ds:si指向的内存单元中的字送入es:di中,然后根据标志寄存器df位的值,将si和di递增2或递减2。
(1)如果df=0则:add si,2 and add di,2
(2)如果df=1则:sub si,2 and sub si,2

格式:rep movsb
功能:根据cx来决定循环次数,n次就是复制n个字节的内容

s:  movsb
    loop s

同理:拥有格式rep movsw
功能:根据cx来决定循环次数,n次就是复制n个字的内容

改变方向的2个指令:
(1)cld指令:将标志寄存器的df置0
(2)std指令:将标志寄存器的df置1

例子:
编程,用串传送指令,将data段中的第一个字符复制到它后面的空间中。
这里写图片描述

mov ax,data
mov ds,ax
mov si,0
mov es,ax
mov di,16
mov cx,16
cld
rep movsb

11.11 pushf和popf

pushf的功能是将标志寄存器的值压入栈中,而popf是从栈中弹出数据,送入标志寄存器中。pushf和popf,为直接访问标志寄存器提供了一种方法。

检测点 11.4
下面的程序执行后: (ax)=? ( a x ) = ?

mov ax,0        ;ax=0
push ax         ;ax=0,stack=[top>0>bottom]
popf            ;ax=0,stack=[top>bottom]
mov ax,0fff0h   ;ax=fff0h
add ax,0010h    ;ax=0h
pushf           ;ax=0,stack=[top>1000111B>bottom]
pop ax          ;ax=47h(0100 0111B),stack=[top>bottom]
and al,11000101B;ax=45h(0100 0101B)
and ah,00001000B;ax=45h

11.12 标志寄存器在Debug中的表示

在Debug中,标志寄存器是按照有意义的各个标志位单独表示的。在Debug中,我们可以看到下面的信息。
这里写图片描述

实验11 编写子程序

这里写图片描述
应用举例:

assume cs:codesg

datasg segment
    db "Beginner's All-purpose Symbolic Instruction Code.",0
datasg ends

codesg segment
    begin:
        mov ax,datasg
        mov ds,ax
        mov si,0
        call letterc
        mov ax,4c00h
        int 21h

    letterc:
        ;比较是'a'<=ds:[si]<='z'
        ;如果是,则变为大写
        ;否则,啥也不干
        ;循环到0位置
        push ax

    change:
        mov al,ds:[si]
        ;ax<'a'则什么也不做
        cmp al,97
        jb next
        ;ax>'z'则什么也不做
        cmp al,122
        ja next
        ;ax=0,则返回
        cmp al,0
        je return
        and al,11011111B
        mov ds:[si],al

    next:
        inc si
        loop change

    return:
        pop ax
        ret

codesg ends
end begin
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值