二、显卡驱动--CGA设置

2023-10-20 08:40
文章标签 设置 驱动 显卡 cga

本文主要是介绍二、显卡驱动--CGA设置,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在之前的博客上说过地址空间并不是全部映射到内存上,还有一些外部设备,IA手册上的1MB以下地址空间分布如下图所示。

我们都知道CPU访问外设有两种方式:IO与内存统一编址 和IO与内存独立编址,一般来说,外设中控制读写的端口都是独立编址,即用in/out指令控制,而外设中的存储器一般和内存进行统一编址,即CPU访问这些地址时和访问内存是一样的,也可以理解成这部分存储器映射到了内存中,比如上图中的各种地址段均被映射到了一些外设上。

回归正题,要在PC上要显示文字,通常需要显示器和显卡这两个硬件设备。一般来说显卡负责提供显示内容,并控制具体的显示模块和状态。显示器的职责是负责将显卡呈递的内容可视化的显示出来。既然显卡需要控制显示的数据,自然就需要存储这些待显示的内容,所以显卡就有自己的存储区域。这个存储区域叫做显示存储器(Video RAM,VRAM),简称显存。当然,访问显存就需要地址。CGA/EGA+ Chroma text video buffer 这个区域映射的就是工作在文本模式的显存。同时显卡还有另外一个工作模式叫做图形模式,这个模式是目前最常用的模式。

通常显卡内置一套关于基本英文字符的显示,很容易做到英文字符的显示。本文只使用显卡的文本模式,对于OS开发只需关注以下几点:

1、所有在PC上工作的显卡,在加电初始化之后都会自动初始化到80*25的文本模式。在这个模式下,屏幕被划分为25行,每行可以显示80个字符,所以一屏可以显示2000个字符。上图中的0xB8000~0xBFFFF这个地址段便是映射到文本模式的显存的。当访问这些地址的时候,实际上读写的是显存区域,而显卡会周期性的读取这里的数据,并且把它们按顺序显示在屏幕上。当然一些低版本显卡不支持彩色字符,只支持单色字符,其显存映射范围为0xb0000-0xb7fff。

2、那么,按照什么规则显示呢?这就要谈到内码了。内码定义了字符在内存中存储的形式,而英文编码就是大家所熟知的ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)码了。对应的关系很简单,从0xB8000这个地址开始,每2个字节表示屏幕上显示的一个字符。从屏幕的第一行开始对应,一行接着一行的对应下去。而这两个字节的前一个是显示字符的ASCII码,后一个是控制这个字符颜色和属性的控制信息,这个字节的8个bit位表示不同的含义。每一位的含义如图所示:

3、理解了显卡文本模式的原理之后接下来就是对屏幕显示控制编码了。不过显卡除了显示内容的存储单元之外,还有部分的显示控制单元需要了解。这些显示控制单元被编制在了独立的I/O空间里,需要用特殊的in/out指令去读写。这里相关的控制寄存器多达300多个,显然无法一一映射到I/O端口的地址空间。对此工程师们解决方案是,将一个端口作为内部寄存器的索引:0x3D4,再通过0x3D5端口来设置相应寄存器的值。

4、之前介绍了访问VGA显存的方法,现在我们要在屏幕上设置光标了。光标和显存不一样。它必须通过显卡的I/O端口开控制。VGA显卡内部有一系列寄存器可以用来控制显卡的状态。在标准的PC机上。 0x3d4和0x3d5两个端口可以用来读写显卡的内部寄存器。方法是先向0x3d4端口写入要访问的寄存器编号,再通过0x3d5端口来读写寄存器数据。存放光标位置的寄存器编号为14和15。两个寄存器合起来组成一个16位整数,这个整数就是光标的位置。比如0表示光标在第0行第0列,81表示第1行第1列(屏幕总共80列)。在实际使用中要注意光标位置的计算,比如需要在第x行、第y列设置光标,那么首先需要计算其相对于第0行、第0列的相对值,pos=x*80+y,然后将相对值pos的高8位输入到14号寄存器中,将低8位输入到15号寄存器中,即可将光标显示在第x行、第y列。如下图所示

 

光标的设置大概就这些,接下来继续看字符的显示,按照前面的说明,就是将字符和其属性输入到对应位置的显存中,但这里要注意一点,字符在第一个字节,其属性在第二个字节,但由于X86是小端方式,低地址高字节,所以字符需要放在地址低8位,其属性放在地址高8位。

上面QEMU模拟器输入显存的字符看上去有点难受,所以我们需要先把整个显示屏的字符全部清空后,再显示字符,清空操作相对而言比较简单,只需要用黑底白字的空格充满整个显存即可(25*80=2000个字符),如下所示。

在清空屏幕以及打印字符完成后,字符串的显示也就迎刃而解,只需要显示字符串中的每个字符,如下所示:

 

 

OK.在上述步骤完成后,我们可以显示常见的英文字符,但是数字的显示用这一套就没用了,因为数字大小和ASCII值并不匹配,因此需要进行转换。

 

 

结合之前的打印内存,可得下面的结果

 

 

 

 

 

 

 

 

 

 

遇到的坑:

编译器出错

没问题

没问题

上面三种情况的理解:只能除2的整数倍?相当于右移。经过一番搜索,应该是编译器在除2的整数倍时,可以用右移的指令取代,而我们的程序是32位的,由于32位机器没有64位的除法指令,所以编译器会出现”__udivdi3”或者”__umoddi3”错误,那解决办法就是人工输入除法指令,之前用了很多unsigned long long 指令,主要为了打印内存用,所以需要能解决64位除法的指令,通过嵌入汇编实现。

参考资料:

  1. http://wiki.0xffffff.org/posts/hurlex-4.html
  2. https://blog.csdn.net/gemini_star/article/details/4438280

这篇关于二、显卡驱动--CGA设置的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/245999

相关文章

如何设置vim永久显示行号

《如何设置vim永久显示行号》在Linux环境下,vim默认不显示行号,这在程序编译出错时定位错误语句非常不便,通过修改vim配置文件vimrc,可以在每次打开vim时永久显示行号... 目录设置vim永久显示行号1.临时显示行号2.永www.chinasem.cn久显示行号总结设置vim永久显示行号在li

Linux:alias如何设置永久生效

《Linux:alias如何设置永久生效》在Linux中设置别名永久生效的步骤包括:在/root/.bashrc文件中配置别名,保存并退出,然后使用source命令(或点命令)使配置立即生效,这样,别... 目录linux:alias设置永久生效步骤保存退出后功能总结Linux:alias设置永久生效步骤

Spring MVC如何设置响应

《SpringMVC如何设置响应》本文介绍了如何在Spring框架中设置响应,并通过不同的注解返回静态页面、HTML片段和JSON数据,此外,还讲解了如何设置响应的状态码和Header... 目录1. 返回静态页面1.1 Spring 默认扫描路径1.2 @RestController2. 返回 html2

四种简单方法 轻松进入电脑主板 BIOS 或 UEFI 固件设置

《四种简单方法轻松进入电脑主板BIOS或UEFI固件设置》设置BIOS/UEFI是计算机维护和管理中的一项重要任务,它允许用户配置计算机的启动选项、硬件设置和其他关键参数,该怎么进入呢?下面... 随着计算机技术的发展,大多数主流 PC 和笔记本已经从传统 BIOS 转向了 UEFI 固件。很多时候,我们也

Linux中chmod权限设置方式

《Linux中chmod权限设置方式》本文介绍了Linux系统中文件和目录权限的设置方法,包括chmod、chown和chgrp命令的使用,以及权限模式和符号模式的详细说明,通过这些命令,用户可以灵活... 目录设置基本权限命令:chmod1、权限介绍2、chmod命令常见用法和示例3、文件权限详解4、ch

SpringBoot项目引入token设置方式

《SpringBoot项目引入token设置方式》本文详细介绍了JWT(JSONWebToken)的基本概念、结构、应用场景以及工作原理,通过动手实践,展示了如何在SpringBoot项目中实现JWT... 目录一. 先了解熟悉JWT(jsON Web Token)1. JSON Web Token是什么鬼

使用Spring Cache时设置缓存键的注意事项详解

《使用SpringCache时设置缓存键的注意事项详解》在现代的Web应用中,缓存是提高系统性能和响应速度的重要手段之一,Spring框架提供了强大的缓存支持,通过​​@Cacheable​​、​​... 目录引言1. 缓存键的基本概念2. 默认缓存键生成器3. 自定义缓存键3.1 使用​​@Cacheab

java如何调用kettle设置变量和参数

《java如何调用kettle设置变量和参数》文章简要介绍了如何在Java中调用Kettle,并重点讨论了变量和参数的区别,以及在Java代码中如何正确设置和使用这些变量,避免覆盖Kettle中已设置... 目录Java调用kettle设置变量和参数java代码中变量会覆盖kettle里面设置的变量总结ja

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta