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没影响
;实验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