二、显卡驱动--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

相关文章

python设置环境变量路径实现过程

《python设置环境变量路径实现过程》本文介绍设置Python路径的多种方法:临时设置(Windows用`set`,Linux/macOS用`export`)、永久设置(系统属性或shell配置文件... 目录设置python路径的方法临时设置环境变量(适用于当前会话)永久设置环境变量(Windows系统

Go语言编译环境设置教程

《Go语言编译环境设置教程》Go语言支持高并发(goroutine)、自动垃圾回收,编译为跨平台二进制文件,云原生兼容且社区活跃,开发便捷,内置测试与vet工具辅助检测错误,依赖模块化管理,提升开发效... 目录Go语言优势下载 Go  配置编译环境配置 GOPROXYIDE 设置(VS Code)一些基本

小白也能轻松上手! 路由器设置优化指南

《小白也能轻松上手!路由器设置优化指南》在日常生活中,我们常常会遇到WiFi网速慢的问题,这主要受到三个方面的影响,首要原因是WiFi产品的配置优化不合理,其次是硬件性能的不足,以及宽带线路本身的质... 在数字化时代,网络已成为生活必需品,追剧、游戏、办公、学习都离不开稳定高速的网络。但很多人面对新路由器

Linux之platform平台设备驱动详解

《Linux之platform平台设备驱动详解》Linux设备驱动模型中,Platform总线作为虚拟总线统一管理无物理总线依赖的嵌入式设备,通过platform_driver和platform_de... 目录platform驱动注册platform设备注册设备树Platform驱动和设备的关系总结在 l

Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式

《Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式》本文详细介绍如何使用Java通过JDBC连接MySQL数据库,包括下载驱动、配置Eclipse环境、检测数据库连接等关键步骤,... 目录一、下载驱动包二、放jar包三、检测数据库连接JavaJava 如何使用 JDBC 连接 mys

linux hostname设置全过程

《linuxhostname设置全过程》:本文主要介绍linuxhostname设置全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录查询hostname设置步骤其它相关点hostid/etc/hostsEDChina编程A工具license破解注意事项总结以RHE

Python设置Cookie永不超时的详细指南

《Python设置Cookie永不超时的详细指南》Cookie是一种存储在用户浏览器中的小型数据片段,用于记录用户的登录状态、偏好设置等信息,下面小编就来和大家详细讲讲Python如何设置Cookie... 目录一、Cookie的作用与重要性二、Cookie过期的原因三、实现Cookie永不超时的方法(一)

Qt 设置软件版本信息的实现

《Qt设置软件版本信息的实现》本文介绍了Qt项目中设置版本信息的三种常用方法,包括.pro文件和version.rc配置、CMakeLists.txt与version.h.in结合,具有一定的参考... 目录在运行程序期间设置版本信息可以参考VS在 QT 中设置软件版本信息的几种方法方法一:通过 .pro

PostgreSQL 默认隔离级别的设置

《PostgreSQL默认隔离级别的设置》PostgreSQL的默认事务隔离级别是读已提交,这是其事务处理系统的基础行为模式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一 默认隔离级别概述1.1 默认设置1.2 各版本一致性二 读已提交的特性2.1 行为特征2.2

一文详解MySQL如何设置自动备份任务

《一文详解MySQL如何设置自动备份任务》设置自动备份任务可以确保你的数据库定期备份,防止数据丢失,下面我们就来详细介绍一下如何使用Bash脚本和Cron任务在Linux系统上设置MySQL数据库的自... 目录1. 编写备份脚本1.1 创建并编辑备份脚本1.2 给予脚本执行权限2. 设置 Cron 任务2