x86 操作系统:理解显卡 256 色下调色板的设置!

起因

在网上查找相关的信息时我发现似乎有一点点不对,尤其是《30天自制操作系统》这本书带偏了好多人!
在《30天自制操作系统》中,对调色板的设置中使用了这张图这样的数据《30天自制操作系统》中有关调色板数据的部分
根据这张图,要设置白色应该使用这样的代码(错误的!!!!虽然可以用但是不要抄!!!):

;这世界上不存在汇编高亮这种东西咧
    mov al,0			;al=当前设置的调色板号
    mov dx,3c8h			;DAC命令寄存器
    out dx,al			;表示要设置al指定的调色板
    
    mov dx,3c9h			;DAC数据寄存器
    mov al,0ffh			;红色值为FF(最高)
    out dx,al
    xor al,al			;al=0

 	out dx,al			;绿色值(由于寄存器和颜色一样就不用修改寄存器了)
	
	out dx,al			;蓝色值(同绿色值)

它确实可以设置00号调色板为白色,但是存在一些问题,试想一下,如果您要一个没那么白的白色(也就是灰色啦),比如四分之一的白配四分之三的黑,那是不是:

;汇编是最好的语言,php也是,所以汇编=php,所以我可以用php高亮
    mov al,0			;al=当前设置的调色板号
    mov dx,3c8h			;DAC命令寄存器
    out dx,al			;表示要设置al指定的调色板
    
    mov dx,3c9h			;DAC数据寄存器
    mov al,3fh			;红色值为3F
    out dx,al
	xor al,al			;al=0
	
 	out dx,al			;绿色值(由于寄存器和颜色一样就不用修改寄存器了)
	
	out dx,al			;蓝色值(同绿色值)

但是简单运行一下,怎么会和上面的一样咧?
找找原因吧(我在这卡了好久好久)
根本原因:生产力的发展决定了生产关系(串台了,但是作为文科生,找原因时这是必答的一点:D)
确实是生产力的问题咧!
生产力落后制约了显卡256色模式下的颜色范围(叉腰)

256色下显卡的颜色范围

由于落后的生产力,显卡256色各颜色范围只有0-63,即0-3Fh!超过这个数则会溢出!
也就是说,当您啊,把某颜色的范围设置为64(40h)时,他就会溢出为0,换句话说,FFh也会溢出为3Fh!所以你说它有问题嘛,它运行又没问题,你说它没问题嘛,有些颜色也弄不了,比如(80,00,00)这个颜色(16进制),它理应是红色,但是它是黑色!原因就是80溢出了两次后(请允许我这么说),等于0!故所有的颜色的RGB值应该除以4!
简单写了一个小程序用来将PS的调色板(ACT文件)转为汇编语言的格式

//我知道我写的像史一样,不要嘲讽我
#include <stdio.h>
#include <stdlib.h>

int main() {
    FILE *file;
    unsigned char buffer[768]; // 256 colors * 3 bytes per color
    int i;
	int temp1;
	int temp2;
	int temp3;
    // 打开ACT文件
    file = fopen("palette.act", "rb");
    if (file == NULL) {
        perror("请将文件命名为palette.act放置在同路径下");
        return 1;
    }

    // 读取颜色数据
    size_t bytesRead = fread(buffer, sizeof(unsigned char), 768, file);
    if (bytesRead < 768) {
        perror("文件读取错误");
        fclose(file);
        return 1;
    }

    // 关闭文件
    fclose(file);
	printf("section .text\npalette_data:\n");
    // 以十六进制格式打印颜色值
    for (i = 0; i < 256; i++) {
    	temp1=buffer[i * 3];
    	temp2=buffer[i * 3 + 1];
    	temp3=buffer[i * 3 + 2];
    	if(temp1==255){
    		temp1=63;
		}
		else{
			temp1=temp1/4;
		}
    	if(temp2==255){
    		temp2=63;
		}
		else{
			temp2=temp2/4;
		}
		if(temp3==255){
    		temp3=63;
		}
		else{
			temp3=temp3/4;
		}
        printf("	;颜色 %02Xh: \n	db %03Xh, %03Xh, %03Xh \n",
               i,
               temp1,
               temp2,
               temp3);
    }

    return 0;
}

好了,就差给您编译好了呈上哩!

配套的汇编过程源代码:

section .text
colorful_palette:       ;想打世界计划了🤤🤤🤤
                        ;奏宝🤤🤤🤤,我的奏宝🤤🤤🤤
    mov esi,palette_data;此标号由上面的程序生成
    xor ax,ax           ;ah=当前设置的调色板,al作为输出IO端口的缓存
    mov dx,3c8h     ;dac寄存器
    out dx,al       ;从零号开始
        
    set_palette_loop:

        mov dx,3c9h     ;dac数据寄存器
        mov al,[esi]    ;设置红色值
        out dx,al
        
        inc esi
        mov al,[esi]    ;设置绿色值
        out dx,al       ;表达了绿色值的思乡之情
        
        inc esi
        mov al,[esi]    ;设置蓝色值
        out dx,al
        cmp ah,255d
        jae finish_set_palette   ;如果ah>=255,则设置完了(其实je就行,但是jae保险一点~~似乎ah没法大于255?~~ )
        inc esi
        inc ah          ;下一个调色板
 
    jmp set_palette_loop
finish_set_palette:

简单说一下吧:
设置调色板之前要给3C8h端口送出当前要设置的调色板编号,然后依次按红绿蓝送出作为各颜色分量的三个值(0~63)到3C9h端口
然后如果是连续设置(如设置完了0号,立刻要设置1号),则不需再送出调色板编号到3C8h端口,直接送出分量值即可。

结语

其实目前自制操作系统有些冷门(似乎一直都很冷门),但是希望在这条路上,抱有相同理想的各位互相扶持,共同努力!

青年一代有理想,有本领,有担当,国家才有前途,民族才有希望。广大青年要坚定理想信念,志存高远,脚踏实地,勇做时代弄潮儿,在中华民族伟大复兴的生动实践中放飞青春梦想,在为人民利益的不懈奋斗中书写人生华章!

写完啦!打世界计划去啦!(或许我应该先写历史作业?)XD

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值