标志寄存器概述
特殊的寄存器:FLAG
CPU内部的寄存器中,有一种特殊的寄存器(对于不同的处理机,个数和结构都可能不同)具有以下3种作用:
- 用来存储相关指令的某些执行结果。
- 用来为CPU执行相关指令提供行为依据。
- 用来控制CPU的相关工作方式。
这就是标志寄存器,8086CPU的标志寄存器有16位,其中存储的信息通常被称为程序状态字(PSW)。 (可以理解为状态寄存器)
FLAG内部结构:
ZF
1、flag的第六位是ZF,零标志位。
2、它记录相关指令执行后,其结果是否为0。
3、如果结果为0,那么zf=1;如果结果不为0,那么zf=0。
PF
1、flag的第二位是PF,奇偶标志位。
2、记录相关指令执行后,结果的所有bit位中1的个数是否是偶数。
3、如果结果bit位中有偶数个1,则pf=1,奇数个1,pf=0。
SF
1、flag的第七位是SF(symbol flag),符号标志位。
2、它记录相关指令执行后,结果是否为负。
3、如果为负,sf=1;非负,则sf=0。
CF
1、flag的第0位是CF,进位标志位。
2、一般情况下,在进行无符号数运算的时候,它记录了运算结果的最高有效位向更高位的进位值,或从更高位的借位值。
eg. 98H+98H=130H
mov al,98H
add al,al ;执行后,(al)=30H,CF=1,CF记录了从最高有效位向更高位的进位值
add al,al ;执行后,(al)=60H,CF=0,CF记录了从最高有效位向更高位的进位值
97H-98H=FFH
mov al,97H
sub al,98h ;执行后,(al)=FFH,CF=1,CF记录了向更高位的借位值
sub al,al ;执行后,(al)=0,CF=0,CF记录了向更高位的借位值
OF
谈谈溢出:有符号数运算时果超过了机器范围叫溢出。
mov al,98
add al,99
;(al)=(al)+99=98+99=197 >127(对于8位有符号数来讲)
1、flag的第11位是OF,溢出标志位。
2、OF记录了有符号数运算结果是否溢出。
3、如果溢出,OF=1,没有则OF=O。
mov al,98 mov al,0F0H
add al,99 add al,88H
;add指令执行后:CF=0,OF=1 add 指令执行后:CF=1,OF=1
mov al,0F0H
add al,78H
;add指令执行后:CF=1,OF=0
检测
1、补全程序,实现从内存1000:0000处开始执行程序
assume cs:code
stack segment
db 16 dup (0)
stack ends
code segment
start:mov ax,stack
mov ss,ax
mov sp,16 ;初始化栈
mov ax,(1000H) ;cs的值
push ax
mov ax,(0) ;IP的值
push ax
retf
code ends
end start
CPU执行retf指令时,进行四步操作:
- (IP)=((ss)*16+sp)
- (sp)=(sp)+2
- (CS)=((ss)*16+sp)
- (sp)=(sp)+2 也就是相当于进行 pop IP pop CS
2、下面程序执行后,ax中的值是多少?
assume cs:codesg
codesg segment
start:
mov ax,0
call s
inc ax
s:pop ax
codesg ends
end start
1000:0 mov ax,0 ;读取此条指令后IP=3 ,执行完该指令后IP=3
1000:3 call s ;读取此条指令后IP=6 ,所以IP=6入栈,执行完该指令后IP=7,跳转到s处
1000:6 inc ax
1000:7 s:pop ax ;所以POP后,ax=6
ax=6
adc
adc是带进位加法指令,它利用了CF位上的记录的进位值。
格式:adc 操作对象1,对象2
功能:对象1=对象1+对象2+CF
比如:
mov ax,2
mov bx,1
sub bx,ax
adc ax,1 ;执行后,(ax)=4,adc执行时,相当于计算2+1+1=4
sbb
sbb带借位减法指令。
格式:sbb 操作对象1,对象2
功能:对象1=对象1-对象2-CF
cmp
cmp是比较指令,cmp的功能相当于减法指令,但是不保存结果。
格式:cmp o1,o2
功能:o1-o2,但不保存结果,只对标志寄存器进行重置。
cmp ax,ax
做(ax)-(ax)运算,结果为0。
此时的flag相应变化:zf=1,pf=1,sf=0,cf=0,of=O
mov ax,8
mov bx,3
cmp ax,bx
;执行后:(ax)=8,zf=0,pf=1,sf=0,cf=0,of=0
条件转移指令
eg.统计8的个数存于AX
data segment
db 8,11,8,1,8,5,63,38
data ends
assume cs:code,ds:data
data segment
db 8,11,8,1,8,5,63,38
data ends
code segment
mov ax,data
mov ds,ax
mov bx,0
mov ax,0
mov cx,0
s:
cmp byte ptr [bx],8
jne next
inc ax
next:
inc bx
loop s
mov ax,4c00h
int 21h
code ends
DF和串传送指令
第十位是DF(definition flag),控制每次操作后si、di的增减。
df=0,每次操作后si di递增。
df=1,每次操作后si di递减。
串传送指令:movsb
movsb指令相当于相当于进行下面几步:
1、((es)*16+(di))=((ds)*16+(si))
2、如果 df=0 则:inc si
inc di
如果 df=1 则:dec si
dec di
这里的b是byte,所以相对偏移量为1。
除了movsb,还有movsw,显然这货就是按字操作,id和si增减单位为2字节。
mov es:[di],word ptr ds:[si]
如果 df=0:
add si,2
add di,2
如果 df=1
sub si,2
sub di,2
movsb和movsw都是串传送操作的一个步骤,一般配合rep使用。
rep: 重复执行该语句直至寄存器cx为0
rep movsb
相当于:s: movsb
loop s
DF的特权:
- cld:df位清0
- std:df位置1
(1)编程,用串传送指令,将data段中的第一个字符串复制到它后面的空间中。
data segment
db 'Welcome to masm!'
db 16 dup(0)
data ends
code segment
start:
mov ax,data
mov ds,ax
mov si,0 ;ds:si指向data:0
mov es,ax
mov di,16 ;es:di指向data:001h
mov cx,16
cld
rep movsb
mov ax,4c00h
int 21h
code ends
end start
pushf和popf
pushf的功能是将标志寄存器的值压栈,而popf就是将其出栈,扔入flag。
下面的程序执行后:(ax)=?
mov ax,0
push ax
popf
mov ax,0fff0h
add ax,0010h
pushf
pop ax
and al,11000101B
and al,00001000B
执行add ax,0010h
后,flag寄存器中的情况:
ax=45h
debug中的标志位
检测
1、下面程序执行后,ax中的数值为多少?
内存地址 汇编指令
1000:0 mov ax,0
1000:3 call far ptr s ;将1000:0008存入栈中 先cs后IP
1000:8 inc ax
1000:9 s:pop ax ;弹出IP的值8,所以AX=8
add ax,ax ;ax=ax+ax = 16=10H
pop bx ;弹出CS的值1000,所以BX=1000
add ax,bx ;所以ax=10H(即16)+1000H=1010H 即1010H,所以指令执行后,AX=1010
中断
官方的回答就不说了,懂得都懂,不懂自己看去。
中断的意识就是说,CPU不再向下执行,而是去处理这个信息,再回去。
内中断的产生
当CPU内部有什么事发生的时候,将产生需要马上处理的中断信息呢?对于8086来说,当CPU内部有下面的情况发生时,产生相应的中断:
- 除法错误,比如,执行div指令产生的除法溢出;
- 单步执行;
- 执行into指令;
- 执行int指令。
8086用称为中断类型码的数据来识别中断信息的来源。中断类型码位一个字节型数据,可以表示256种中断信息的来源。
上面的四种中断源,在8086中中断类型码如下:
- 除法错误:0
- 单步执行:1
- 执行into指令:4
- 执行int指令,该指令的格式为int n,指令中的n为字节型立即数,是提供给CPU的中断类型码。
中断处理程序
顾名思义,就是对中断信息进行处理的程序。
中断向量表
中断向量表在内存中保存,其中存放着256个中断源所对应的中断处理程序的入口。
对于8086pc机,中断向量表指定放在内存地址0处。从0000:0000到0000:03FF的1024个单元中存放着中断向量表。
一个表项占两个字,高字节放段地址,低字节放偏移地址。
中断过程
中断类型码–>中断向量表–>修改CS:IP–>中断处理程序
这个过程由CPU自动完成,这一过程叫中断过程。另外,中断执行后,一般还要返回原指令处,所以类似CALL,还要将原来的CS和IP保存起来。
简洁描述:
1、取得中断类型码N
2、pushf
3、TF=O,IF=O
4、push CS
5、push IP
6、(IP)=(N*4),(CS)=(N*4+2)
然后,执行程序员编写的中断处理程序。
中断信息可能随时被检测到,所以中断处理程序必须一直存储在内存某段空间之中。中断处理程序入口地址,即中断向量,必须存储在对应表项中。
1、保存用到的寄存器; 2、处理中断 3、恢复用到的寄存器 4、用iret指令返回。
iret就相当于:
pop ip
pop cs
popf