汇编语言 复习 第十一章 标志寄存器

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

具有以下3种作用:

(用来存储相关指令的某些执行结果)

(用来为cpu执行相关指令提供行为依据)

(用来控制CPU的相关控制方式)

在8086CPU中,叫做标志寄存器:

下面自己话个图吧

OF(ov/nv):Over 溢出 标志位  
DF(dn/up):Direction 方向 标志位
IF(ei/di):Enable 允许中断 标志位
SF(ng/pl):Symbol 符号 标志位
ZF(zr/nz):Zero 零 标志位
AF(ac/na):Auxiliary 辅助进位 标志位
PF(pe/po):Parity 奇偶 标志位
CF(cy/nc):Carry 进位 标志位
各标志位名称、英文全称、标志值符号及含义一览:
 
标志位
标志位名称/英文
=1
=0
CF
进位标志/Carry Flag
CY/Carry/进位
NC/No Carry/无进位
PF
奇偶标志/Parity Flag
PE/Parity Even/偶
PO/Parity Odd/奇
AF
辅助进位标志/Auxiliary Carry Flag
AC/Auxiliary Carry/进位
NA/No Auxiliary Carry/无进位
ZF
零标志/Zero Flag
ZR/Zero/等于零
NZ/Not Zero/不等于零
SF
符号标志/Sign Flag
NG/Negative/负
PL/Plus/正
TF
陷阱标志/Trap Flag
   
IF
中断标志/Interrupt Flag
EI/Enable Interrupt/允许
DI/Disable Interrupt/禁止
DF
方向标志/Direction Flag
DN/Down/减少
UP/增加
OF
溢出标志/Overflow Flag
OV/Overflow/溢出
NV/Not Overflow/未溢出

检测点11.2

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

                  al                          CF    OF    SF    ZF    PF

sub al,al     0h/0000 0000b         0     0     0     1     1

mov al,10h    10h/0010 0000b     0     0     0     1     1

add al,90h    a0h/1010 0000b     0     0     1     0     1

mov al,80h    80h/1000 0000b     0     0     1     0     1

add al,80h    0h/0000 0000b      1     1     0     1     1

mov al,0fch   0fch/1111 1100b    1     1     0     1     1

add al,05h    1h/0000 0001b      1     0     0     0     0

mov al,7dh    7dh/1111 1101b     1     0     0     0     0

add al,0bh    88h/1000 1000b     0     1     1     0     1

检测点涉及的相关内容:

ZF是flag的第6位,零标志位,记录指令执行后结果是否为0,结果为0时,ZF=1 

PF是flag的第2位,奇偶标志位,记录指令执行后结果二进制数中1的个数是否为偶数,结果为偶数时,PF=1 

SF是flag的第7位,符号标志位,记录有符号运算结果是否为负数,结果为负数时,SF=1 

CF是flag的第0位,进位标志位,记录无符号运算结果是否有进/借位,结果有进/借位时,SF=1

OF是flag的第11位,溢出标志位,记录有符号运算结果是否溢出,结果溢出时,OF=1

add、sub、mul、div 、or、and等运算指令影响flag(inc 不改变cf的值)

mov、push、pop等传送指令对flag没影响

六、             adc指令
1.         adc是带进位加法指令,它利用了CF位上记录的进位值。
2.         指令格式:adc操作对象1,操作对象2
功能:操作对象1=操作对象1+操作对象2+CF
比如指令 adc ax,bx 实现的功能是:(ax)=(ax)+(bx)+CF
3.         在执行adc指令的时候加上的CF的值的含义,是由adc指令前面的指令决定的,也就是说,关键在于所加上的CF值是被什么指令设置的。显然,如果CF的值是被sub指令设置的,那么它的含义就是借位值;如果是被add指令设置的,那么它的含义就是进位值。
4.         CPU提供adc指令的目的,就是来进行加法的第二步运算的。adc指令和add指令相配合就可以对更大的数据进行加法运算。
5.         adc指令执行后,也可能产生进位值,所以也会对CF位进行设置。由于有这样的功能,我们就可以对任意大的数据进行加法运算。
6.         将CF设置为0:sub ax,ax
7.         inc和loop指令不影响CF位。
七、             sbb指令
1.         sbb是带借位减法指令,它利用了CF位上记录的借位值。
指令格式:sbb 操作对象1,操作对象2
功能:操作对象1=操作对象1-操作对象2-CF
比如指令 sbb ax,bx 实现的功能是:(ax)=(ax)-(bx)-CF
sbb指令执行后,将对CF进行设置。利用sbb指令可以对任意大的数据进行减法运算。
2.         sbb和adc是基于同样的思想设计的两条指令,在应用思路上和adc类似。
八、             cmp指令
1.         cmp是比较指令,cmp的功能相当于减法指令,只是不保存结果。cmp指令执行后,将对标志寄存器产生影响。其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果。
2.         cmp指令格式:cmp 操作对象1,操作对象2
功能:计算操作对象1-操作对象2 但并不保存结果,仅仅根据计算结果对标志寄存器进行设置。
3.         通过cmp指令执行后,相关标志位的值就可以看出比较的结果。
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。
4.         比较指令的设计思路:通过做减法运算,影响标志寄存器,标志寄存器的相关位记录了比较的结果。
5.         同add、sub指令一样,CPU在执行cmp指令的时候,也包含两种含义:进行无符号数运算和进行有符号数运算。所以利用cmp指令可以对无符号数进行比较,也可以对有符号数进行比较。用cmp进行无符号数比较时,相关标志位对比较结果的记录。
6.         由于cmp比较时可能会产生溢出,所以不能仅从sf的结果来判断大小,而不要结合of来判断大小:
1)        sf=1,of=0 A<B
2)        sf=1,of=1 A>B
3)        sf=0,of=1 A<B
4)        sf=0,of=0 A>=B
 
 
九、             检测比较结果的条件转移指令
十、             DF标志和串传送指令
 
 
 
;实验11(letterc子程序)小写改成大写

;编写一个子程序,将包含任意字符,以0结尾的字符串的小写字母转变成大;写字母。
;这个代码得出的是正确的结果,但是在调用函数的同时,,,SI最后改变
;了。。。。。。。。所以这个实际上是有问题的

assume cs:code,ds:data

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

code segment

begin:    mov ax,data
        mov ds,ax
        mov si,0
        call letterc
        
        mov ax,4C00H
        int 21H

;名称:letterc
;功能:将以0结尾的字符串中的小写字母转变成大写字母
;参数:ds:si指向的字符串首地址

letterc:mov bl,[si]
        mov bh,0
        cmp bl,0
        je s0
        cmp bl,61H
        jb s1
        cmp bl,87H    ;这边也错了,,不是87H,是86H,,,,,,61H-86H才是26个英文字母
        ja s1
        and bl,11011111B
        mov [si],bl
        jmp s1
        
s1:        inc si
        jmp letterc
        
s0:        ret
        
code ends
end begin
;程序二:参考书中P143页内容,有更好的办法,无需用到寄存器。

;可以用and直接修改内存,将ASCII码的第5位置为0,变为大写字母。
;这个代母没有用到 我在上个代码用的BX寄存器。。。。。更优化?
 

assume cs:codesg

datasg segment

     db "Seginner's All-purpose Symbolic Instruction Code.",'0'

datasg ends

codesg segment

begin:   mov ax,datasg

     mov ds,ax

     mov si,0 ;ds:si指向第一个字节

     call letterc

 

     mov ax,4c00h

     int 21h

 

;名称:letterc

;功能:将以0结尾的字符中的小写字母转变成大写字母

;参数:ds:si指向字符串首地址

letterc:push si        ;压入栈

let: cmp byte ptr [si],0    ;和0进行比较

     je let0                ;如果等于0则转到let0,结束

     cmp byte ptr [si],61h  ;和61h进行比较

     jb let1                ;如果低于60h则转到let1,继续循环

     cmp byte ptr [si],86h  ;和86h进行比较

     ja let1                ;如果高于86h则转到let1,继续循环

     and byte ptr [si],11011111b ;ASCII码的第5位置为0,转为大写

let1:

     inc si

     jmp let

let0:

     pop si    ;出栈

     ret

codesg ends

end begin
            
原文地址:https://www.cnblogs.com/Lee-geeker/p/3165650.html