• 0x04_自制操作系统My-OS实现自定义颜色


    前言:

    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

     运行:

    cd class02
    ..\z_tools\make.exe run

    自制操作系统合集
    原文地址:https://www.cnblogs.com/Frank-dev-blog/category/2249116.html
    项目github地址rick521/My-OS (github.com)给我点颗star

     

  • 相关阅读:
    int(*(*v)[ ])();怎么理解
    Tlsr8258开发-读写内部flash
    【付费推广】常见问题合集,焦点展台与任务管理
    查询&会议签字
    云安全系列4:解析云安全工具集
    文件的常用操作(读取压缩文件、解压、删除)
    不重复数字
    Python入门 函数 基础入门篇
    时间、时间戳互转、日期格式化、获取各种天数
    (二)正点原子STM32MP135移植——TF-A移植
  • 原文地址:https://www.cnblogs.com/Frank-dev-blog/p/17142241.html