概述
文章目录
- 11.8 cmp指令
- 11.9 检测比较结果的条件转移指令
- 检测点11.3
- 11.10 DF标志和串传送指令
- 11.11 pushf和popf
- 检测点11.4
- 11.12 标志寄存器在Debug中的表示
11.8 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
其实,我们通过cmp指令执行后,相关标志位的值就可以看出比较的结果。
cmp ax,bx
sf的值不能判断大小的关键原因在于发生了溢出。如果没有溢出发生的话,那么,实际结果的正负和逻辑上真正结果的正负就一致了。
所以,我们应该再考查sf(得知实际结果的正负)的同时考查of(得知有没有溢出),就可以得知逻辑上真正结果的正负,同时就可以知道比较的结果。
以cmp ah,bh为例讲解:
11.9 检测比较结果的条件转移指令
“转移”指的是它能够修改IP,而“条件”指的是它可以根据某种条件,决定是否修改IP。
编程实现如下功能:
如果(ah)=(bh)则(ah)=(ah)+(ah),否则(ah)=(ah)+(bh)。
cmp ah,bh
je s
add ah,bh
jmp short ok
s:add ah,ah
ok:...
我们来看下面的一组程序。
data段中的8个字节如下:
data segment
db 8,11,8,1,8,5,63,38
data ends
(1)编程,统计data段中数值为8的字节的个数,用ax保存统计结果。
编程,统计data段中数值大于8的字节的个数,用ax保存统计结果。
编程,统计data段中数值小于8的字节的个数,用ax保存统计结果。
检测点11.3
(1)补全下面的程序,统计F000:0处32个字节中,大小在[32,128]的数据的个数。
分析: 此处用dx保存大小在[32,128]的数据的个数。低于32跳转到s0处进行下一次循环,高于128也跳转到s0处进行下一次循环。
(2)补全下面的程序,统计F000:0处32个字节中,大小在(32,128)的数据的个数。
注:
cmp ah,bh
跳转指令(以ja s0举例)
"ja s0"表示:ah的值高于bh的值,则跳转!
注意是前者比后者高(或低,或不高于,或不低于)
11.10 DF标志和串传送指令
flag的第10位是DF,方向标志位。在串处理指令中,控制每次操作后的si、di的增减。
df=0 每次操作后si、di递增;
df=1 每次操作后si、di递减。
我们来看下面的一个串传送指令。
格式: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"表示传送一个byte型的数据。
movsb和movsw进行的是串传送操作中的一个步骤,一般来说,movsb和movsw都和rep配合使用,格式如下:
rep movsb
用汇编语法来描述 rep movsb 的功能就是:
s:movsb
loop s
可见,rep的作用是根据cx的值,重复执行后面的串传送指令。
由于每执行一次movsb指令si和di都会递增或递减指向后一个单元或前一个单元,则rep movsb就可以循环实现(cx)个字符的传送。
rep movsw
相当于:
s:movsw
loop s
(1)编程,用串传送指令,将data段中的第一个字符串复制到它后面的空间中。
mov ax,data
mov ds,ax
mov si,0 ;ds:si指向data:0
mov es,ax
mov di,16 ;es:di指向data:0010
mov cx,16; ;(cx)=16,rep循环16次
cld
rep movsb
(2)编程,用串传送指令,将F000H段中最后的16个字符复制到data段中。
11.11 pushf和popf
pushf的功能是将标志寄存器的值压栈,而popf是从栈中弹出数据,送入标志寄存器中。
pushf和popf,为直接访问标志寄存器提供了一种方法。
检测点11.4
下面的程序执行后:(ax)=?
mov ax,0 ;ax=0000
push ax ;ax=0000
popf ;ax=0000,把标志寄存器的各位置为0
mov ax,0fff0h ;ax=0fff0h
add ax,0010h ;ax=0fff0h+0010h=(0000)h
pushf
pop ax
and al,11000101B
and ah,00001000B
这个要翻一下本章最开始的flag寄存器示意图。
0fff0h+0010h=10000h;因为产生了进位,1是进位值,ax中只能保存0000h
假设进行无符号数运算:
0fff0h+0010h=10000h,产生了进位。
假设进行有符号数运算:
-10h+10h=0,没有产生溢出。
flag各位结果如下:
CF=1,无符号数运算产生了进位;
PF=1,奇偶标志位ax=0000 0000h,偶数个1;
AF=1;辅助进位标志位。运算过程中看最后四位,不论长度为多少。最后四位向前有进位或者借位,AF=1,否则AF=0;后面4位产生了进位,AF=1;
ZF=1,ax=0000,结果为0;
SF=0,符号标志位,ax结果非负;
TF=0;调试标志位。当TF=1时,处理器每次只执行一条指令,即单步执行;TF在popf的时候被置为0;
IF=0;中断允许标志位。它用来控制8086是否允许接收外部中断请求。若IF=1,8086能响应外部中断,反之则屏蔽外部中断;IF在popf的时候被置为0;
DF=0;方向标志位。在串处理指令中,每次操作后,如果DF=0,si、di递增,如果DF=1,si、di递减;注意此处DF的值是由程序员进行设定的 cld命令是将DF设置为0,std命令是将DF设置为1;DF在popf的时候被置为0;
OF=0;溢出标志位,没有溢出;
标志寄存器的其他位在popf的时候被置为0;
flag各位如下:
pop ax之后
ah=0000 0000;al=0101 0101
and al,11000101B的结果为 (al)=0100 0101B
and ah,00001000B的结果为(ah)=0000 0000B
ax=0000 0000 0100 0101=69=45h
故程序执行之后,(ax)=45h.
11.12 标志寄存器在Debug中的表示
最后
以上就是拉长路灯为你收集整理的汇编语言(王爽版)学习笔记 第十一章 标志寄存器(2)的全部内容,希望文章能够帮你解决汇编语言(王爽版)学习笔记 第十一章 标志寄存器(2)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复