第十一章:标志寄存器05
让编程改变世界
Change the world by program
编程训练
编程实现如下功能:如果(ah)=(bh)则(ah)=(ah)+(ah),否则(ah)=(ah)+(bh)。
cmp ah,bh
je s
add ah,bh
jmp short ok
s: add ah,ah
ok: ret
检测比较结果的条件转移指令
虽然 je 的逻辑含义是“相等则转移”,但它进行的操作是,ZF=1时则转移。 “相等则转移”这种逻辑含义,是通过和 cmp 指令配合使用来体现的,因为是cmp 指令为“ZF=1”赋予了“两数相等”的含义。 至于究竟在je之前使不使用cmp指令,在于我们的安排。 je检测的是ZF位置,不管je 前面是什么指令,只要CPU执行je指令时,ZF=1,那么就会发生转移。 比如:
mov ax,0
add ax,0
je s
inc ax
s: inc ax 执行后,(ax)=1。add ax,0 使得ZF=1,所以je指令将进行转移。 可在这个时候发生的转移确不带有“相等则转移”的含义。因为此处的je指令检测到的ZF=1 ,不是由cmp等比较指令设置的,而是由add指令设置的,并不具有“两数相等”的含义。 但无论“ZF=1” 的含义如何,是什么指令设置的,只要是ZF=1,就可以使得je指令发生转移。 CPU提供了cmp指令,也提供了 je 等条件转移指令,如果将它们配合使用,可以实现根据比较结果进行转移的功能。 但这只是“如果”,只是一种合理的建议,和事实上常用的方法。 但究竟是否配合使用它们,完全是你自己的事情。这就好像,call和ret指令的关系一样。 对于jne、jb、jnb、ja、jna等指令和cmp指令配合使用的思想和je相同,可以自己分析一下。
课堂练习
我们来看一组程序:
data段中的8个字节如下:
data segment
db 8,11,8,1,8,5,63,38
data ends
(一)编程:统计data段中数值为8的字节的个数,用ax保存统计结果。
编程思路:初始设置(ax)=0,然后用循环依次比较每个字节的值,找到一个和8相等的数就将ax的值加1。
源码分析:相关代码下载
第二种方案:相关代码下载
比起第一个程序,它直接的遵循了“等于8则计数值加1”的原则,用je指令检测等于8的情况,但是没有第一个程序精简。 第一个程序用 jne 检测不等于 8 的情况 ,从而间接地检测等于 8 的情况。 要注意在使用 cmp 和条件转移指令时的这种编程思想。
(二)编程:统计data段中数值大于8的字节的个数,用ax保存统计结果。
编程思路:初始设置(ax)=0,然后用循环依次比较每个字节的值,找到一个大于8的数就将ax的值加1。
源码分析:相关代码下载
(三)编程:统计data段中数值小于8的字节的个数,用ax保存统计结果。
编程思路:初始设置(ax)=0,然后用循环依次比较每个字节的值,找到一个小于8的数就将ax的值加1。
源码分析:相关代码下载 上面讲解了根据无符号数的比较结果进行转移的条件转移指令。 根据有符号数的比较结果进行转移的条件转移指令的工作原理和无符号的相同,只是检测了不同的标志位。 我们在这里主要探讨的是cmp、标志寄存器的相关位、条件转移指令三者配合应用的原理,这个原理具有普遍性,而不是逐条讲解条件转移指令。
DF标志和串传送指令
flag的第10位是DF,方向标志位。
在串处理指令中,控制每次操作后si,di的增减。
DF = 0:每次操作后si,di递增
DF = 1:每次操作后si,di递减
格式1: 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 的功能是将 ds:si 指向的内存单元中的字节送入 es:di中,然后根据标志寄存器DF位的值,将 si和di递增或递减。 当然,也可以传送一个字:
movsw
格式2:movsw
功能:(以字为单位传送)将 ds:si 指向的内存字单元中 word 送入 es:di 中,然后根据标志寄存器DF位的值,将si和di递增2或递减2。 movsb和movsw进行的是串传送操作中的一个步骤,一般来说,movsb 和 movsw 都和rep配合使用。 格式如下:
rep movsb rep的作用是根据cx的值,重复执行后面的串传送指令。 由于每执行一次movsb指令si和di都会递增或递减指向后一个单元或前个单元,则rep movsb就可以循环实现(cx)个字符的传送。 由于flag的DF位决定着串传送指令执行后,si和di改变的方向,所以CPU应该提供相应的指令来对DF位进行设置,从而使程序员能够决定传送的方向。
8086CPU提供下而两条指令对DF位进行设置:
cld指令:将标志寄存器的DF位置0
std指令:将标志寄存器的DF位置1
[buy]
获得所有教学视频、课件、源代码等资源打包 [/buy] [Downlink href='http://kuai.xunlei.com/d/LQNBMAOSRKAF']视频下载[/Downlink]