汇编语言-标志寄存器

汇编语言-标志寄存器

CPU内部的寄存器中,有一个特殊的寄存器,叫标志寄存器,它具有以下三种作用:

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

flag和其他寄存器不一样,其他寄存器是用来存放数据的,都是整个寄存器具有一个含义。
而flag寄存器是按位起作用的,也就是说,它的每一位都有专门的含义,记录特定的信息。

标记寄存器内部结构及其功能简介


ZF标志

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

代码示范

mov ax,1

sub ax,1

执行后,结果为0,则ZF=1,表示“结果是0”。

注意,在8086CPU的指令集中,有的指令的执行是影响标志寄存器的,比如:add、sub、mul、div、inc、or、and等,它们大都是运算指令(进行逻辑或自述运算);有的指令的执行对标志寄存器没有影响,比如:mov、push、pop等,它们大都是传送指令。


PF标志

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

代码示范

mov al,1

add al,10

执行后,结果为00001011B,其中有3(奇数)个1,则PF=0


SF标志

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

代码示范

mov al,10000001B

add al,1

执行后,结果为10000010B,符号位为1,则SF=1


CF标志

flag的第0位是CF,进位标志位。一般情况下,在进行了无符号运算的时候,它记录了运算结果的最高有效位向更高位的进位值,或从更高位的借位值。

代码示范

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


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


OF标志

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

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

mov al,98
add al,99
add指令执行后:CF=0,OF=1


adc指令

adc 操作对象1,操作对象2

功能:

操作对象1=操作对象1+操作对象2+CF

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

代码示范

mov ax,2

mov bx,1

sub bx,ax

adc ax,1

执行后,(ax) = 4adc执行时,相当于计算:(ax) + 1 + CF=2+1+1=4


sbb指令

使用方法和adc指令相似


cmp指令

cmp是比较指令,cmp的功能相当于减法指令,只是不保存结果。

cmp指令执行后,将对标志寄存器产生影响。其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果。

cmp指令格式:cmp 操作对象1,操作对象2

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

代码示范

比如,指令cmp ax,ax,做(ax)-(ax)的运算,结果为0,但并不在ax中保存,仅影响flag的相关各位。指令执行后,ZF=1,PF=1,SF=0,CF=0,OF=0。

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

执行后标记寄存器标记位产生影响:(ax)=8,ZF=0,PF=1,SF=0,CF=0,OF=0


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

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

比如:jcxz就是一个条件转移指令,它可以检测cx中的数值,如果(cx)=0,就修改IP,否则什么也不做。

所有条件转移指令的转移位移都是[-128~127]。

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

它们检测的是哪些标志位呢?就是被cmp指令影响的那些,表示比较结果的标志位。这些条件转移指令通常都和cmp相配合使用,就好像call和ret指令通常相配合使用一样。

因为cmp指令可以同时进行两种比较,无符号数比较和有符号数比较,所以根据cmp指令的比较结果进行转移的指令也分为两种,即:

  • 根据无符号数的比较结果进行转移的条件转移指令,它们检测ZF、CF的值;
  • 和根据有符号数的比较结果进行了转移的条件转移指令,它们检测SF、OF和ZF的值。

指令介绍:

这里写图片描述

代码示范

如果(ah)=(bh)则(ah)=(ah)+(ah),否则(ah)=(ah)+(bh)。

cmp ah,bh

je s

    add ah,bh
    jmp short ok

s:add ah,ah

ok:

上面的程序执行时,如果(ah)=(bh),则cmp ah,bh 使ZF=1,而je检测ZF是否为1,如果为1,将转移到标号s处执行指令 add ah,ah。这也可以说,cmp比较ah、bh后所得到的相等的结果使得je指令进行转移。从而很好地体现了je指令的逻辑含义,相等则转移。

虽然je的逻辑含义是“相等则转移”,但它实际进行的操作是,ZF=1时则转移。

“相等则转移”这种逻辑含义,是通过和cmp指令配合使用来体现的,因为cmp指令为“ZF=1”赋予了“两数相等”的含义。

至于究竟在je之前使不使用cmp指令,在于我们在安排je检测的是ZF位置,不管je前面是什么指令,只要CPU执行je指令时,ZF=1,那么就会发生转移。

实例介绍

程序功能:将包含任意字符,以0结尾的字符串中的小写字母转变成大写字母

assume cs:code

data segment
    db 'sfsd;++dfasd"fdsafsd_fdfdfdIIIIss',0
data ends

code segment

start:  mov ax,data
    mov ds,ax
    mov si,0
    call letterc

    mov ax,4c00H
    int 21

letterc:
    push ax
    push ds
    push si

s:  
    mov al,ds:[si]
    mov ah,'a'
    cmp al,ah
    jb next
    mov ah,'z'
    cmp al,ah
    ja next

change:     
    and al,11011111B
    mov ds:[si],al

next:
    inc si
loop s

    pop si
    pop ds
    pop ax

code ends
end start

效果图:


DF标志和串传送指令

DF标记

flag的第10位是DF,Direction Flag,方向标志位。

在串处理指令中,控制每操作后si,di的增减。

DF=0,每次操作后si,di递增;DF=1,每次操作后si,di递减。

DF相关指令

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

cld指令:将标志寄存器的DF位置0std指令:将标志寄存器的DF位置1


串传送指令

格式:movsb

功能介绍

功能:执行movsb 指令相当于进行下面几步操作:


1. ((es)*16+(di)) = ((ds)*16+(si))

2. DF=0则:(si)=(si)+1

                             (di)=(di)+1

   如果DF=1则:(si)=(si)-1

                             (di)=(di)-1

用汇编语法描述movsb的功能如下:

mov es:[di],byte ptr ds:[si]           ;8086CPU并不支持这样的指令,这里只是个描述。

如果DF=0inc si
    inc di

如果DF=1dec si
    dec di

rep指令

rep的作用是根据cx的值,重复执行后面的串传送指令

movsb和movsw都和rep配合使用,格式如下:

mov cx,100
rep movsb

用汇编语法来描述rep movsb的功能就是:

mov cx,100
s:movsb
loop s


pushf和popf

pushf的功能是将标志寄存器的值压栈,而popf是从栈中弹出数据,送入标志寄存器中。

pushf和popf,为直接访问标志寄存器提供了一种方法。

posted @ 2015-11-08 17:46  AbeDay  阅读(753)  评论(0编辑  收藏  举报