2

0x04_My-OS实现自定义颜色 - Z_Chan

 1 year ago
source link: https://www.cnblogs.com/Frank-dev-blog/p/17142241.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

0x03我们提到:

把12(红色)用循环写入显存,每个像素点怎么显示都要看对应的显存地址,比如0xa0000到0xaffff就是每一个像素点的显存

你问为什么12就是红色,这些东西在主板出厂的时候就是规定好的,就是有点调用主板api的味道,这是我的猜测,具体为什么还要你们来查

你会发现12是红色,11就是另一种颜色,有没有办法可以自定义颜色呢

自定义颜色的原因是:

  颜色丰富度不够,因此使用调色板功能来增强颜色显示,使用RGB模式,表示一个RGB颜色需要24位数

修改class01名字为class02,把我给出的代码对原来的内容进行替换,当然你也可以找不同,如果你有这个耐心的话

naskfunc.asm

; naskfunc
; TAB=4

[FORMAT "WCOFF"]                ; 制作目标文件的模式    
[INSTRSET "i486p"]                ; 使用到486为止的指令
[BITS 32]                        ; 3制作32位模式用的机器语言
[FILE "naskfunc.asm"]            ; 文件名
    GLOBAL _io_hlt,_write_mem8,_io_cli,_io_sti,_io_get8,_io_set8,_io_stihlt
    GLOBAL _io_load_eflags,_io_store_eflags
        

[SECTION .text]

_io_hlt:    ; void io_hlt(void);
        HLT
        RET

_io_cli:    ; void io_cli(void);
        CLI
        RET

_io_sti:    ; void io_sti(void);
        STI
        RET

_io_get8:    ; int io_get8(int port);
        MOV        EDX,[ESP+4]        ; port
        MOV        EAX,0
        IN        AL,DX
        RET

_io_set8:    ; void io_set8(int port, int data);
        MOV        EDX,[ESP+4]        ; port
        MOV        AL,[ESP+8]        ; data
        OUT        DX,AL
        RET

_io_stihlt:    ; void io_stihlt(void);
        STI
        HLT
        RET

_write_mem8: ; void write_mem8(int addr, int data);
        MOV ECX,[ESP+4] ; taking content of add
        MOV AL,[ESP+8] ; taking content of data
        MOV [ECX],AL ; *ecx=al
        RET
_io_load_eflags:    ; int io_load_eflags(void);
        PUSHFD        ; PUSH EFLAGS 
        POP        EAX
        RET

_io_store_eflags:    ; void io_store_eflags(int eflags);
        MOV        EAX,[ESP+4]
        PUSH    EAX
        POPFD        ; POP EFLAGS 
        RET

这里增加了一些函数,看不懂没关系,我等下调用他们的时候讲一下是干嘛的

新建一个文件graphic.c

#include "include/head.h"


void init_palette(void)
{
    static unsigned char table_rgb[18 * 3] = {
        0x24, 0x86, 0xb9,    /*  0:宝石蓝(#2486b9) */
        0xff, 0x00, 0x00,    /*  1:梁红 */
        0x00, 0xff, 0x00,    /*  2:亮绿 */
        0xff, 0xff, 0x00,    /*  3:亮黄 */
        0x00, 0x00, 0xff,    /*  4:亮蓝 */
        0xff, 0x00, 0xff,    /*  5:亮紫 */
        0x00, 0xff, 0xff,    /*  6:浅亮蓝 */
        0xff, 0xff, 0xff,    /*  7:白 */
        0xc6, 0xc6, 0xc6,    /*  8:亮灰 */
        0x84, 0x00, 0x00,    /*  9:暗红 */
        0x00, 0x84, 0x00,    /* 10:暗绿 */
        0x84, 0x84, 0x00,    /* 11:暗黄 */
        0x00, 0x00, 0x84,    /* 12:暗青 */
        0x84, 0x00, 0x84,    /* 13:暗紫 */
        0x33, 0x33, 0x33,    /* 14:浅暗蓝 */
        0x84, 0x84, 0x84,    /* 15:暗灰 */
        0xD0, 0xD0, 0xD0,
        0x20, 0x20, 0x20
    };
    set_palette(0, 17, table_rgb);
    return;

    /* C语言中的static char语句只能用于数据,相当于汇编中的DB指令 */
}

void set_palette(int start, int end, unsigned char *rgb)
{
    int i, eflags;
    eflags = io_load_eflags();    /* 记录中断许可标志的值 */
    io_cli();                     /* 将中断许可标志置为0,禁止中断 */
    io_set8(0x03c8, start);
    for (i = start; i <= end; i++) {
        io_set8(0x03c9, rgb[0] / 4);
        io_set8(0x03c9, rgb[1] / 4);
        io_set8(0x03c9, rgb[2] / 4);
        rgb += 3;
    }
    io_store_eflags(eflags);    /* 复原中断许可标志 */
    return;
}
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)
{
    int x, y;
    for (y = y0; y <= y1; y++) {
        for (x = x0; x <= x1; x++)
            vram[y * xsize + x] = c;
    }
    return;
}

前两个函数是用来实现调色板的,具体原理我解释不了,Ctrl+CV大佬不需要知道原理,你懂我意思吧,里面调用了很多asm里的函数

第三个函数是绘制方块的参数意思分别是:显存地址,显示宽度,颜色代号,从x0到x1,y0到y1进行绘制一个矩形

head.h

/*naskfunc.asm*/
void io_stihlt();
void io_hlt(void);
void io_cli(void);
void io_sti(void);
int io_get8(int port);
void io_set8(int port, int data);
void write_mem8(int addr, int data);
int io_load_eflags(void);
void io_store_eflags(int eflags);

/* asmhead.nas */
struct BOOTINFO { /* 0x0ff0-0x0fff */
    char cyls; /* 启动区读磁盘读到此为止 */
    char leds; /* 启动时键盘的LED的状态 */
    char vmode; /* 显卡模式为多少位彩色 */
    char reserve;
    short scrnx, scrny; /* 画面分辨率 */
    char *vram;
};
#define ADR_BOOTINFO 0x00000ff0

/*graphic.c*/
void init_palette(void);
void set_palette(int start, int end, unsigned char *rgb);
void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1);

我们主要看第二个asmhead.asm的函数声明,这个BOOTINFO结构体,是涵盖了显示器的信息,信息的位置在0x0ff0-0x0ffff

main.c

#include "include/head.h"

struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;

void Main(void){
    int i;
    init_palette();
    boxfill8(binfo->vram, binfo->scrnx, 0,0,0,binfo->scrnx, binfo->scrny);
    for (;;) {
        io_hlt();
    }
}

第一句是获取这个显示器信息的结构体,调用boxfill8填充整个屏幕,颜色代号是调色板中的0号宝石蓝

最后在make脚本中增加graphic.obj

1455587-20230221195336390-1970908271.png

cd class02
..\z_tools\make.exe run
1455587-20230221200058162-2038040784.png
自制操作系统合集
原文地址:https://www.cnblogs.com/Frank-dev-blog/category/2249116.html
项目github地址rick521/My-OS (github.com)给我点颗star

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK