汇编学习教程:第一个实验

引言

在上篇博文中,我们学习了Debug工具的使用,相信小伙伴们都还记得Debug的操作方法。Debug中,我们使用D命令可以查看制定内存范围的内容,可以使用E命令去修改指定内存地址下的内容,那么接下来,我们将讲一下课本中给出的第一个实验:实验1。课本中给出了4道实验题目,这里我们讲述第3道和第四道。

说明一下,汇编不像C语言C++那样流行,很难找到合适的汇编题目来做练习,所以课本中给出的例题和实验都是很好的练习例子,希望小伙伴们要珍惜不多的例题,把课本中例题和实验完全掌握和吃透。

题目1

查看内存中的内容。

PC机主板上的ROM中写有一个生产日期,在内存FFF00H~FFFFFH的某几个单元中,请找到这个生产日期并改变它。

下面我们就来做下这个实验题目。实验要求我们查看内存,首先进入Debug,使用D命令查看内存范围FFF00H~FFFFFH的内容。因为寻址是基地址✖16+偏移地址,所以我们先对起始目的地址 FFF00H 进行寻址,确定:FFF0:0;结束目的地址 FFFFFH进行寻址,确定:FFF0:FF。

Debug下输入命令:

d FFF0:0 FF

显示出范围 FFF00H~FFFFFH 的全部内容,在最右边的ASCALL码输出显示区,我们看到了生产日期:01/01/92。对应中间的字节,则日期范围是 FFFF5H~FFFFCH 。那么接下来修改日期的话,我们就需要修改 FFFF5H~FFFFCH 内存范围的内容即可。

我们将前面的 “01” 改成 “10”。字符1对应的ASCALL码是31H,字符0对应的ASCALL码是30H,所以我们输入的数据应该为:31,30。Debug下输入命令:

e FFF0:F5 31 30

 我们再次使用D命令查看是否修改成功,Debug下输入命令:

d FFF0:F0 FF

 结果发现实际上并没有修改,数据还是之前的“01”。可是我们之前E命令执行没有报错,应该是修改成功了呀,怎么还是“01”呢?

8086PC内存地址空间分布

要解释该问题,我们需要首先看张图:

这张图展示的是在8086CPU的总线上,范围0H~FFFFFH,各类存储器在内存上的分布情况,从上到下分别是:主存储器地址空间,显存地址空间,显卡BISO ROM 地址空间,网卡BISO ROM 地址空间,系统BISO ROM 地址空间。

具体范围如下:

 也就是说,我们向00000H~10000H地址范围的内存单元写入数据,数据会写入主随机存储器中;我们向A0000H~BFFFFH地址范围的内存地址单元写入数据,这个数据就会写入显存中,然后显存传输到显示屏上;向C0000H~FFFFFH地址范围的内存地址单元写入数据,则操作无效,对应内存单元数据不会改变,因为该范围是ROM地址空间,对外只读,而不能写。

我们回过头来看主板的ROM所在地址:FFF00H~FFFFFH,在ROM地址空间范围内,所以数据只读,而不能写。这也就是说为什么我们可以使用D命令查看,使用E命令修改却无效果的原因。

题目2

向内存从B8100H开始的单元中填写数据,如:

e B810:0000 01 01 02 02 03 03 04 04

请读者先填写不同的数据,观察产生的现象;再改变填写的地址,观察填写的现象。

现在我们做下这个实验,Debug下输入命令:

e B810:0000 01 01 02 02 03 03 04 04

执行如图所示:

 注意到右上角的显示出的字符了么?只是修改了内存内容怎么该变了屏幕显示呢?

还是要回到上面题目1中,在题目1中实际上我们已经有所提及:A0000H~BFFFFH这段内存地址空间为显存地址空间,也就是说,我们向A0000H~BFFFFH地址范围的内存地址单元写入数据,这个数据就会写入显存中,然后显存传输到显示屏上。我们刚才修改的起始地址为 B8100H ,位于显存地址空间内,所以我们修改内存内容后,就立马显示到了显示屏上。

我们再改变一下修改的数据,Debug下输入命令:

e B810:0000 30 01 31 02 32 03 33 04

执行如图所示:

我们发现右上角出现了“0123”的字符,但是,我们上条显示的居然还在?!我们修改的是同一个内存地址, 按道理新字符“0123”会把之前的字符给覆盖掉啊,怎么没有覆盖?这是为什么?

在搞鬼的人

我们先解释这个问题,之所以没有覆盖掉上条字符显示,完全是因为Debug的界面显示在搞鬼。我们已经说到,A0000H~BFFFFH这段内存地址空间为显存地址空间,如果想要在屏幕上显示字符,必然要修改此内存地址范围下的内存单元内容。

Debug的界面显示也是需要屏幕输出,也就是说,Debug程序也需要操作显存地址空间去显示它的界面内容。而此时,我们也正在Debug界面中通过E命令修改显存地址空间内容,所以我们的操作和Debug的操作产生了一个冲突,导致了上述问题出现。

Debug在执行上述E命令的步骤如下:

  1. 当我们输入完命令后,按下“Enter”键去执行,此时Debug并未去立即执行E命令,而是转而先处理它的界面显示。
  2. 处理界面显示的操作很简单,就是将屏幕中每一行数据显示整体向上滚动一行。此步骤中,上一条E命令显示出的字符也向上滚动了一行。
  3. 界面显示处理完成后,才开始执行E命令,修改了命令指定的内存单元内容。
  4. 由于修改的是显存地址空间,所以屏幕显示出本次E命令修改的字符。

我们通过上述步骤可以解释两个问题:

1、为什么没有覆盖上条E命令显示出的字符?是因为上条E命令显示的字符被Debug程序向上滚动了一行,所以它的地址就发生了变化,不再是B8100H。我们修改的还是B8100H起始的内存单元,所以无法覆盖。

2、为什么上条E命令显示出的字符在新显示出的字符上面?因为是先向上滚动,再执行的修改内存内容。

这里,其实也就是本书作者王爽老师想让大家明白的地方。上面的解释估计大家还是有些疑问,比如屏幕中每一行数据显示整体向上滚动,怎么就会改变了之前显示字符的地址呢?

屏幕显示画面的背后

解释这个问题之前,我们需要先了解下屏幕。我们都知道屏幕能够显示出各种画面,文字,视频等,屏幕是如何做到显示不同颜色画面呢?基本的原理估计我们都学过,也就是三原色。首先,屏幕实际上是由一个个发光单元组成,每个发光单元包含三个微小发光结构,分别能发出红、绿蓝三种颜色光。

 

每个发光单元实际上对应我们显存地址空间里面的两个连续内存单元内容,为什么是两个连续内存单元?因为一个内存单元存放需要显示的字符,另外一个存放的内容则是显示效果。显示效果就是字符颜色、背景色、高亮闪烁这些显示效果。

以上述E命令:e B810:0000 30 01 31 02 32 03 33 04 为例。D810:0 内存单元内容为30,在ASCALL码中对应字符“0”,所以屏幕显示出“0”,接下来的地址 D810:1 内存单元内容为01,这个01则是对应字符“0”的显示效果,这里01效果是蓝色,所以屏幕上显示出蓝色的字符“0”。我们可以说,地址D810:0 和地址 D810:1 这两个连续的内存单元组成了一个发光单元,第一个单元决定显示内容,第二个单元决定显示效果。

这也就是为什么说,我们实际上使用E命令修改了八个内存单元内容,屏幕上却只显示出四个字符的原因。

滚动的实现

了解完屏幕,现在我们说一下是如何实现屏幕滚动的。

我们想象一下,将屏幕上的发光单元看成两个内存单元为一组的内存空间,那么从屏幕上左上角开始的第一个发光单元,一直到右下角最后一个发光单元,这些发光单元对应的也是一个连续的内存地址空间。现在为了方便理解和增强认知,这里我们先假设屏幕上每一行的发光单元有4个,共有4行,那么我们可以说屏幕的显存地址空间为 0~31。第一行为0~7,第二行为8~15,第三行为16~23,第四行为24~31。

现在我们需要将屏幕中每一行的数据整体向上滚动一行,该怎么实现呢?很明显,我们需要将第一行的内容设置为原第二行的内容,第二行的内容设置为原第三行的内容,第三行的内容设置为原第四行的内容,最后一行第四行清空显示内容,这样就实现了整体向上滚动一行。

这时我们发现,滚动实际改变了原显示字符对应的内存地址。比如我第二行的内容显示字符为“0123”,第二行的起始地址为:8,现在向上滚动一行,那么字符“0123”就变成了第一行的显示内容,而第一行的起始地址为:0。这样,字符“0123”对应的地址发生了改变。

回到我们的实验中,把假设的4×4屏幕变成8086PC机对应的实际屏幕大小80×25,道理还是一样的。由于Debug程序将屏幕中每一行都整体向上滚动一行,这个行为也就导致了上一个E命令显示的字符的地址发生了变化,我们再次修改相同地址的内存单元内容,就不会对上次显示出的字符造成覆盖,因为地址已经不同了。

实验后的领悟

王爽老师为什么要设置两个题目,而且要我们观察变化理解,这里他的目的就是告诉读者,也就是我们学习者,在汇编中,一定要从CPU的角度,从内存地址空间的角度,来看待硬件与软件的联系和关系。比如屏幕显示,如果只是单纯从硬件上考虑你可能很难理解屏幕如何做到画面输出显示,但是我们结合显存地址空间来看待,通过Debug程序对界面显示的控制以及我们亲自动手改变内存内容,明白了屏幕显示出画面背后的数据运算和基本逻辑。我们扩展一下,不管是显存,包括其他的硬件,声卡、网卡等,其实背后的逻辑基本都是一致的。它们都对应有地址空间范围,在各自的地址空间内,做到与CPU进行数据的交互和处理。

本篇结束语

本篇博文中主要讲述了课本实验1的最后两道题目,通过亲自动手实验观察现象,我们学习到了硬件背后运转的逻辑,深入了解了8086PC机内存地址空间分配,领会了作者王爽老师的良苦用心。

下篇博文我们将正式学习访问内存相关知识,学习了解DS段寄存器和SS段寄存器它们两个的作用和使用。

感谢围观,转发分享请标明出处,谢谢!

  • 20
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值