用C语言程序对显存进行操作

我们之前研究过变量、数组、函数和指针,他们都可以看作是内存中存储的一段数据,当程序需要用到它们时,会通过它们的地址找到它们并进行调用,只是调用的用途不同而已:变量和数组元素是作为常量来处理,对它们进行赋值、运算、取址等操作,而程序是从首地址开始执行直到返回,指针是用来对地址进行操作,或者对指向的内容进行操作。但是我们要知道,它们在内存中都是以一个字节一个字节的数据形式存储的,我们可将他们的存储空间都看作是一个char型数组。

现在定义了一个有200个元素的char型数组a,要我们向a中加入数组元素,使程序可以在屏幕中间打印一个字符“c”。在执行程序main里只有一句语句:((void (far *)())(long)a)();分析语句:a是数组的首地址,将它强制转换成long型使它的数据包含段地址和偏移地址的数据,但此时它还不是一个地址而是一个long型变量,那么我们将它再强制类型转换成一个voidfar *)()型的函数指针,它是一个远指针,指向一个void型的函数,所以这个函数的入口地址就是数组a的首地址。即程序是要执行以数组a里的元素构成的语句所组成的函数。那么我们要向数组a里填充的是一段内存空间的数据,这些数据连起来能被翻译成一段语句,这段语句的功能是在屏幕中间打印一个字符“c”。

那么我们先考虑怎么在屏幕中间打印一个字符“c”。我们知道输出函数都是在当前光标的位置输出,而我们要在屏幕中间打印是在固定位置输出,即在段地址为b800的数据段的某一个位置存放要输出的数据,我们知道dos窗口的大小是80*25的,一共占4000个字节,那么屏幕中间是,即偏移地址为:13*80+40-1*2=2158=0x86e,那么要打印的地址为0xb800086e。我们怎么把字符c放到内存中地址0xb800086e处呢?要对地址操作首先想到的就是指针,因为要存放段地址加偏移地址,所以要定义一个far指针。我们先写一个输出的程序如下:

用C语言程序对显存进行操作

输出结果为:

用C语言程序对显存进行操作

可见结果是正确的。现在我们要找到这个程序在内存中存储的数据,我们用debug加载程序:

用C语言程序对显存进行操作

可以看到,程序从01fa开始,到0215结束,我们查看这一段的内存:

用C语言程序对显存进行操作

可见这一段的内存里的数据为55 8b ec 83 ec 04 c7 46 fe 00 b8 c7 46 fc 6e 08 c4 5e fc 26 c6 07 63 8b e5 5d c3,我们将这些数据存到数组a中,看能否打印出c,结果发现虽然输出了c,但是还在屏幕上输出了两个字符,还有程序输出了之后没有正确返回:

用C语言程序对显存进行操作

但是查看内存,我们向数组a里补充的数据完全正确,用u命令查看也发现和我们之前写的输出语句的汇编语句一样,那是为什么呢?我们之前写的输出语句是在main函数里输出的,但是这里数组a是在数据段里的,不是在一个段里,需要返回值,所以我们在输出函数里把输出语句写在一个far型的子函数里,程序如下:

用C语言程序对显存进行操作

查看函数f的汇编语句为:

用C语言程序对显存进行操作

可以发现最后的返回语句变成了retf,再查看内存空间:

用C语言程序对显存进行操作

只有21e处的c3变成了cb,修改之后发现能够正常显示:

用C语言程序对显存进行操作

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/a57fa485d3090932eab8348830f1da25.html