第十一章 标志寄存器
文章目录
章节内容
概述
主要介绍了标志寄存器和其中的CF,PF,ZF,SF,OF,DF标志位。
标志寄存器的作用:
- 用来储存相关指令的某些执行结果
- 用来为CPU执行相关指令提供行为依据
- 用来控制CPU的相关工作方式
8086CPU 的 flag 寄存器结构:
8086CPU指令集中:add、sub、mul、div、inc、or、and等(大多为运算指令)指令执行会影响标志寄存器。
像 mov、push、pop等(大多是传送指令)指令执行不影响标志寄存器。
本章还介绍了与标志寄存器有关的adc、sbb、cmp、movsb、movsw、pushf、popf等指令。
ZF标志
flag的第6位,零标志位,若相关指令执行后结果为0,则zf=1,否则zf=0;
PF标志
flag的第2位,奇偶标志,若相关指令执行后结果中所有bit位中1的个数为偶数,则pf=1,否则pf=0;
SF标志
flag的第7位,符号标志位,若相关指令执行后结果为负,则sf=1,否则sf=0;
CF标志
flag的第0位,进位标志位,在进行无符号数运算时,记录运算结果的最高有效位向更高位的进位值,或从更高位的借位值,进位/借位了cf=1,否则cf=0;
OF标志
flag的第11位,溢出标志位,在进行有符号数运算时,记录运算结果是否发生了溢出,溢出了of=1,否则of=0;
(如进行8位寄存器或内存单元有符号运算,超过范围-128~127为溢出,16位有符号运算,超过范围-32768~32767为溢出)
CF和OF所表示的进位和溢出,分别是对无符号数和有符号数运算而言的,他们之间没有任何关系。
DF标志
flag的第10位,方向标志位,在串处理指令中,控制每次操作后si、di的增减。
df=0,每次操作后si、di递增。
df=1,每次操作后si、di递减。
cld指令设置df=0
std指令设置df=1
串传送指令会在后文介绍。
adc/sbb指令
带进位加法/带借位减法指令,利用了CF位上记录的进位/借位值。
指令格式: adc 操作对象 1,操作对象 2
功能: 操作对象 1 = 操作对象 1 + 操作对象 2 + CF
指令格式: sbb 操作对象 1,操作对象 2
功能: 操作对象 1 = 操作对象 1 - 操作对象 2 - CF
cmp指令与检测比较结果的条件转移指令
cmp是比较指令,相当于不保存结果的减法,但是会对标志寄存器产生影响,其他若干指令通过识别被影响的寄存器位得知比较结果。
指令格式: cmp 操作对象 1,操作对象 2
功能: 计算操作对象 1 - 操作对象 2 但不保存结果,根据计算结果对标志寄存器进行设置
检测比较结果的条件转移指令:
指令 | 字母表示意义 | 含义 | 检测的相关标志位 |
---|---|---|---|
je | jump equal | 等于则转移 | zf=1 |
jne | jump not equal | 不等于则转移 | zf=0 |
jb | jump below | 低于则转移 | cf=1 |
jnb | jump not below | 不低于则转移 | cf=0 |
ja | jump above | 高于则转移 | cf=0 且 zf=0 |
jna | jump not above | 不高于则转移 | cf=1 或 zf=1 |
这些常与cmp配合使用。
注意,对于有符号数和无符号数,这些指令检测的标志位可能会不同,但这里不做详细探究。(指令的重点不在这)
串传送指令
movsb
执行相当于以下几步骤
( (es)*16+(di) ) = ( (ds)*16+(si) )
根据df标志位的值递增/递减1
movsw
与movsb类似,但每次传送一个字
( (es)*16+(di) ) = ( (ds)*16+(si) )
根据df标志位的值递增/递减2
movsb/movsw常与rep配合使用构成一个串传送操作。
格式为rep movsb
/ rep movsw
rep根据cx的值,重复执行若干次之后的串传送指令。
相当于汇编语言下的
s: movsb
loop s
;以及
s: movsw
loops
从而实现(cx)个字符或字的传送,由df标志位控制方向(递增或递减)
pushf和popf指令
pushf将标志寄存器的值压栈,popf将栈中的值弹出送入标志寄存器中。
标志寄存器在Debug中的表示
Debug中标志寄存器的各个位是单独表示的。
如图:
各标志位的表示:
标志 | 值为1的标记 | 值为0的标记 |
---|---|---|
of | OV | NV |
sf | NG | PL |
zf | ZR | NZ |
pf | PE | PO |
cf | CY | NC |
df | DN | UP |
实验11 编写子程序
编写子程序,将包含任意字符,以0结尾的字符串中的小写字母转变成大写字母。
名称:letterc
功能:将以0结尾的字符串中的小写字母转变成大写字母
参数:ds:si指向字符串首地址。
需要用到本章学习的cmp和条件转移指令判断一个字符是否为小写字母,其他就挺简单了。
代码如下:
assume cs:codesg
datasg segment
db "Beginner's All-purpose Symbolie Instruction Code.",0
datasg ends
stacksg segment
db 16 dup (0)
stacksg ends
codesg segment
begin :
mov ax,datasg
mov ds,ax
mov si,0
mov ax,stacksg
mov ss,ax
mov sp,16
call letterc
mov ax,4c00h
int 21h
letterc:
;寄存器入栈
push si
push cx
mov ch,0
;子程序
letterc_begin:
mov cl,[si]
jcxz betterc_ok
cmp cl,'a'
jb letterc_next
cmp cl,'z'
ja letterc_next
and cl,11011111b
mov [si],cl
letterc_next:
inc si
jmp short letterc_begin
betterc_ok:
;寄存器出栈
pop cx
pop si
ret
codesg ends
end begin
结果: