购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

6.8 数位的显示

一旦各个数位都分解出来了,下面的工作就是在屏幕上显示它们。源程序第40 行,将保存有各个数位的数据区首地址传送到基址寄存器BX。

一共有5 个数字要显示,它们在当前数据段内的起始偏移地址就是number 的汇编地址,且已传送到寄存器BX 中。为了依次得到这5 个数字,程序中使用的指令是

在这里,我们的意图是,寄存器BX 中的内容是基地址,保持不变,当寄存器SI 的内容从0逐次增加到4,或者反过来,从4 递减到0 时,就可以通过BX+SI 来连续访问这5 个数字。在这里,SI 的作用相当于索引,因此它被称为索引寄存器(Index Register),或者叫变址寄存器。另一个常用的变址寄存器是DI。

注意,INTEL8086 处理器只允许以下几种基址寄存器和变址寄存器的组合:

这些组合可以用于任何带有内存操作数的指令中。其他任何组合,比如[bx+ax]、[cx+dx]、[ax+cx]等等,都是非法的。

因此,源程序第41 行,把初始的索引值4 传送到SI 寄存器,这是由于要先显示万位上的数字。

源程序第43 行,从指定的内存单元取出一个字节,传送到AL 寄存器,偏移地址是BX+SI。但是,它们之间的运算并非是在编译阶段进行的,而是在指令实际执行的时候,由处理器完成的。

源程序第44 行,将AL 中的数字加上0x30,以得到它对应的ASCII 码。

源程序第45 行,将数字0x04 传送到寄存器AH。0x04 是显示属性,即前面讲过的黑底红字,无加亮,无闪烁。到此,AX 中是一个完整的字,前8 位是显示属性值,后8 位是字符的ASCII 码。

源程序第46 行,将AX 中的内容传送到由段寄存器ES 所指向的显示缓冲区中,偏移地址由DI 指定。还记得吗,在前面使用movsw 传送字符串“Label offset:”到显示缓冲区时,也使用了DI,当时DI 是指向显示缓冲区首地址的(0),而且每传送一次就自动加2。传送结束后,DI 正好指向字符“:”的下一个存储单元。之后,DI 一直没用过,还保持着原先的内容。

注意,如图6-5 所示,数据的传送是按低端字节序的,寄存器的低字节传送到显示缓冲区的低地址部分(字节),寄存器的高字节传送到显示缓冲区的高地址部分(字节)。

源程序第47 行,将DI 的内容加上2,以指向显示缓冲区的下一个单元。

源程序第48 行,将SI 的内容减1,使得下一次的BX+SI 指向千位数字。dec 是减一指令,和inc 指令一样,后面跟一个操作数,可以是8 位或者16 位的通用寄存器或者内存单元。

源程序第49 行,指令jns show 的意思是,如果未设置符号位,则转移到标号“show”所在的位置处执行。如图6-2 所示,Intel 处理器的标志寄存器里有符号位SF(Sign Flag),很多算术逻辑运算都会影响到该位,比如这里的dec 指令。如果计算结果的最高位是比特“0”,处理器把SF 位置“0”,否则SF 位置“1”。

处理器的任务是忠实地执行指令,多数时候,它不会知道你的意图,也不会知道你进行的是有符号数运算,还是无符号数运算。如果运算结果的最高位是“1”,它唯一所能做的,就是将SF标志置“1”,以示提醒,剩下的事,你自己看着办,它已经尽力了。

图6-5 低端字节序的字传送示意图

由于SI 的初始值为4,故第一次执行dec si 后,si 的内容为3,即二进制数0000000000000011,符号位是比特“0”,处理器将标志寄存器的SF 位清“0”。于是,当执行jns show 时,符合条件,于是转移到标号“show”所在的位置处执行,等于是开始显示下一个数位。

当显示完最后一个数位后,SI 的内容是零。执行dec si 指令后,由于产生了借位,实际的运算结果是0xffff(SI 只能容纳16 个比特),因其最高位是“1”,故处理器将标志位SF 置“1”,表明当前SI 中的结果可以理解为一个负数(-1)。于是,执行jns show 时,条件不满足,接着执行后面第51 行的指令。

jns 是条件转移指令,处理器在执行它的时候要参考标志寄存器的SF 位。除了只是在符合条件的时候才转移之外,它和jmp 指令很相似,它也是相对转移指令,编译后的机器指令操作数也是一个相对偏移量,是用标号处的汇编地址减去当前指令的汇编地址,再减去当前指令的长度得到的。 Ip0xAgz8nlDQrcqoOOuczNQfyRCmU7CjOO2gXgGam903u/7tJMFvotKN8aR2uqOJ

点击中间区域
呼出菜单
上一章
目录
下一章
×