二、显卡驱动--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设置的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/cy295957410/article/details/108436730
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/245999

相关文章

如何在Ubuntu上安装NVIDIA显卡驱动? Ubuntu安装英伟达显卡驱动教程

《如何在Ubuntu上安装NVIDIA显卡驱动?Ubuntu安装英伟达显卡驱动教程》Windows系统不同,Linux系统通常不会自动安装专有显卡驱动,今天我们就来看看Ubuntu系统安装英伟达显卡... 对于使用NVIDIA显卡的Ubuntu用户来说,正确安装显卡驱动是获得最佳图形性能的关键。与Windo

嵌入式Linux之使用设备树驱动GPIO的实现方式

《嵌入式Linux之使用设备树驱动GPIO的实现方式》:本文主要介绍嵌入式Linux之使用设备树驱动GPIO的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、设备树配置1.1 添加 pinctrl 节点1.2 添加 LED 设备节点二、编写驱动程序2.1

嵌入式Linux驱动中的异步通知机制详解

《嵌入式Linux驱动中的异步通知机制详解》:本文主要介绍嵌入式Linux驱动中的异步通知机制,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、异步通知的核心概念1. 什么是异步通知2. 异步通知的关键组件二、异步通知的实现原理三、代码示例分析1. 设备结构

CentOS和Ubuntu系统使用shell脚本创建用户和设置密码

《CentOS和Ubuntu系统使用shell脚本创建用户和设置密码》在Linux系统中,你可以使用useradd命令来创建新用户,使用echo和chpasswd命令来设置密码,本文写了一个shell... 在linux系统中,你可以使用useradd命令来创建新用户,使用echo和chpasswd命令来设

usb接口驱动异常问题常用解决方案

《usb接口驱动异常问题常用解决方案》当遇到USB接口驱动异常时,可以通过多种方法来解决,其中主要就包括重装USB控制器、禁用USB选择性暂停设置、更新或安装新的主板驱动等... usb接口驱动异常怎么办,USB接口驱动异常是常见问题,通常由驱动损坏、系统更新冲突、硬件故障或电源管理设置导致。以下是常用解决

C#TextBox设置提示文本方式(SetHintText)

《C#TextBox设置提示文本方式(SetHintText)》:本文主要介绍C#TextBox设置提示文本方式(SetHintText),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录C#TextBox设置提示文本效果展示核心代码总结C#TextBox设置提示文本效果展示核心代

Pyserial设置缓冲区大小失败的问题解决

《Pyserial设置缓冲区大小失败的问题解决》本文主要介绍了Pyserial设置缓冲区大小失败的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录问题描述原因分析解决方案问题描述使用set_buffer_size()设置缓冲区大小后,buf

Feign Client超时时间设置不生效的解决方法

《FeignClient超时时间设置不生效的解决方法》这篇文章主要为大家详细介绍了FeignClient超时时间设置不生效的原因与解决方法,具有一定的的参考价值,希望对大家有一定的帮助... 在使用Feign Client时,可以通过两种方式来设置超时时间:1.针对整个Feign Client设置超时时间

PyCharm如何设置新建文件默认为LF换行符

《PyCharm如何设置新建文件默认为LF换行符》:本文主要介绍PyCharm如何设置新建文件默认为LF换行符问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录PyCharm设置新建文件默认为LF换行符设置换行符修改换行符总结PyCharm设置新建文件默认为LF

Linux上设置Ollama服务配置(常用环境变量)

《Linux上设置Ollama服务配置(常用环境变量)》本文主要介绍了Linux上设置Ollama服务配置(常用环境变量),Ollama提供了多种环境变量供配置,如调试模式、模型目录等,下面就来介绍一... 目录在 linux 上设置环境变量配置 OllamPOgxSRJfa手动安装安装特定版本查看日志在