假设我们有一台64位字寻址的计算机,我们想对其进行编程,以将存储为二进制图像位图(例如下面的一个)的5x7字符输出到内存映射的显示器。



由于每个字符有5 x 7 = 35像素,因此我们可以在单个单词中使用35位存储字符。最低有效位从单词的左侧开始,并且图像中的每个像素由第n个位表示,如上所示,上面的数字“ 3”将存储在内存中:011101000100001001100000100011000101110,后跟29个未使用的位设置为0。

这是在旧/现代计算机中存储字符的方式吗?还是每个像素使用单个字节/字呢?

如果以这种方式存储它们,汇编/机器代码中的例程将是什么(仅使用基本指令,例如按位,来自计算机的指令集体系结构的算术和数据传输操作)用于将这些数据转换为显示器上的图像是什么样的?就像这样:


将要更新的当前像素的x和y显示坐标存储在某个寄存器中。
存储两个选定的RGB值(在此在另外两个单独的寄存器中分别为绿色0,255,0和黑色0,0,0)。
还有另外两个寄存器用作初始化为5和7的计数器,以跟踪当前图像的当前行和列
测试列寄存器是否不为0。如果不是,则测试位图的LSB是否设置为1,然后根据x和y坐标将相应的RGB值寄存器与x和y坐标寄存器进行“与”运算。结果,然后将结果MOV到显示输出寄存器。
将行计数器寄存器减1,测试是否为0。如果是,则将其设置回5,并将y坐标增加1,然后将列计数器减1。
将持有位图的寄存器向左移1位。
JMP转到指令4。

有没有更简单或更有效的方法?似乎即使是像渲染单个小文本字符这样的简单操作也需要大量的操作,并且大约需要200个CPU周期。级别的代码,用于显示从头开始显示的图像,因为我无法找到任何图像,因为它们要么掩盖了特定主题,要么代码是使用高级语言编写的,或者是使用宏的汇编程序编写的,所有这些都在“作弊”并且不要解释最低层的基本情况。

评论

图形编程黑皮书无疑是一本值得一读的经典书。很多老式的黑魔法;)

是的,我是迈克尔·阿布拉什(Michael Abrash)的第二本书。这是一个伟大的阅读。本书所写的内容还有很多技巧,但其背后的哲学很重要(即使到今天!)

#1 楼

您必须区分计算机图形卡的文本和图形模式。

过去,大多数情况下都支持文本模式。在这种模式下,开发板负责存储字符的位图定义,并将其显示在当前光标位置。您要做的就是在一个小的文本缓冲区中提供字符的ASCII码(每个字符一个字节)。

如今,提供了一个高分辨率的光栅缓冲区,该缓冲区可以访问像素并且您以某种受支持的格式向其写入颜色信息(在“最高”模式下,每像素3字节(RGB),百万像素或更多)。

最初,简单的(压缩)二进制位图使用了不同的大小,并通过对设备驱动程序的请求将其“钝化”到光栅存储器中,并进行了可能的格式转换。轮廓,并且需要经历一个复杂的渲染过程,其中包括使用抗锯齿来获得平滑的结果。

可以再次通过点按以缓存显示的输出以快速显示。

整个过程很复杂,可以通过硬件加速,并且由操作系统(GUI管理)以透明的方式处理,与其他图形原始绘图操作相结合。

#2 楼

简短的答案是肯定的,如果您的格式需要它,您就不能避免进行很多位操作。它需要这样做。 (引用Obvious上尉的话)

更长的答案是,如果您编写软件光栅化程序,则可以使用一些算法和技巧来节省CPU时间(通过知道不需要绘制的那一部分(透明度)优化),通过使源像素格式与目标像素格式相同(直接或以缓存的形式),优化执行内存复制等操作...基本上考虑光栅化器的绘制循环,并了解如何将其重构为节省CPU时间(例如:您可以在运行时生成一段汇编代码,专门用于打印字母A或在源位图信息中包含meta,以告诉您如何跳过透明区域等。)
每个基于CPU指令集,缓冲区格式,渲染原语的算法(旋转,拉伸位图,什么样的过滤等),CPU寄存器和缓存等,用例可能有不同的解决方案。

所以无论如何,在过去的wei时代,写入单个像素会占用很多CPU周期rd编码和小内存是常态。 :-)
但是它并没有禁止具有8 MHZ CPU的16/32位计算机执行类似的操作:https://www.youtube.com/watch?v=GWwPJU6pp30音乐也使用了CPU)

对于硬件渲染,硬件将执行从源格式到目标格式的转换,虽然它不会使用SW光栅化器可用的许多技巧,它在硬件中的通用实现很可能会击败大多数SW实现。