美文网首页
1.【VGA图形系统初探】

1.【VGA图形系统初探】

作者: 月下蓑衣江湖夜雨 | 来源:发表于2021-01-03 02:28 被阅读0次

    提示:可以将virtualbox虚拟机界面大小设置大一些。https://jingyan.baidu.com/article/6525d4b13b7d0fac7d2e94ef.html

    1、设置背景色为白色

    设置背景色为白色
    前提条件:需要要将VGA显卡设置为图形模式,在boot中写,代码如下:
      ;;;;;;;;;;;;;;;;;;;;;;;;;;;设置VGA图形格式
      mov al, 0x13
      mov ah, 0x00
      int 0x10
      ;;;;;;;;;;;;;;;;;;;;;;;;;;;
    

    AH=0x00;
    AL=模式:(省略了一些不重要的画面模式)
    0x03:16位字符模式,80x25
    0x12:VGA图形模式,640x480x4位彩色模式,独特的4面存储模式
    0x13:VGA图形模式,320x200x8位彩色模式,调色板模式
    0x6a:扩展VGA图形模式,800x600x4位彩色模式,独特的4面存储模式(有的显卡不支持这种模式)
    返回值:无
    我们暂且选择0x13模式,因为8位彩色模式可以使用256种颜色,这一点看来不错。
    写显卡

    ; 导出函数
    global  write_mem8
    
    [SECTION .text]
    ; ========================================================================
    ;                  void write_mem8(int addr, int data);
    ; ========================================================================
    write_mem8:
        mov ecx, [esp + 4]      ; [esp + 4]中存放的是地址,将其读入ecx
        mov al, [esp + 8]       ; [esp + 8]中存放的是数据,将其读入al
        mov [ecx], al
        ret
    

    c语言设置背景色位白色

    void set_background_white(){    
        for(int i = 0xa0000; i<=0xaffff; i++){
            write_mem8(i, 15);
        }
    }
    

    2、设置背景为条纹图案

    条纹背景
    void set_background_stripe(){   
        for(int i = 0xa0000; i<=0xaffff; i++){
            write_mem8(i, i & 0x0f);
        }
    }
    

    c语言可以直接使用指针操作内存,不用借助于汇编!
    char *p; // 用于BYTE类地址
    short *p // 用于WORD类地址
    int *p // 用于DWORD类地址

    void set_background_stripe(){   
        char *p;
        for(int i = 0xa0000; i<=0xaffff; i++){
            p = (char *) i;
            *p = i & 0x0f;
        }
    }
    

    3、设置调色板,色号
    这次使用的是320x200的8位颜色模式,色号使用8位(二进制)数,也就是只能使用0~255的数。
    RGB使用6位16进制数,也就是24位(二进制)来指定颜色。
    这个8位彩色模式,是由程序随意指定0~255的数字所对应的颜色的。
    例如25号颜色对应#ffffff,26号颜色对应对应#123456,等,这种方式叫叫做调色板。(palette)
    如果程序员不做任何设定,0号颜色就是#000000,15号颜色就是#ffffff。
    c:初始化调色板

    // 初始化调色板
    void init_palette(){
        // 我们只设置如下16种颜色就可以了
        static unsigned char table_rgb[16*3] = {
            0x00, 0x00, 0x00, //  0:黑
            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:暗紫
            0x00, 0x84, 0x84, // 14:浅暗蓝
            0x84, 0x84, 0x84, // 15:暗灰
        };
        
        set_palette(0, 15, table_rgb);
    }
    
    // 设置调色板
    void set_palette(int start, int end, unsigned char *rgb){
        int eflags = io_load_eflags();    // 记录中断许可标志的值
        io_cli();                         // 将中断许可标志置为0,禁止中断
        
        io_out8(0x03c8, start);
        for(int i = start; i <= end; i++){
            io_out8(0x03c9, rgb[0] / 4);
            io_out8(0x03c9, rgb[1] / 4);
            io_out8(0x03c9, rgb[2] / 4);
            rgb += 3;
        }
        
        io_store_eflags(eflags);
    }
    

    asm:依赖函数

    ; ========================================================================
    ;                  void io_out8(int port, int data);
    ; ========================================================================
    io_out8:
        mov edx, [esp + 4]      ; port
        mov al,  [esp + 8]      ; data
        mov dx, al
        ret
        
    ; ========================================================================
    ;                  int io_load_eflags();
    ; ========================================================================
    io_load_eflags:
        pushfd         ; 指push eflags
        pop eax        ; 函数执行完毕后,如果返回值小于等于4字节,则会将值保存在寄存器eax中
        ret
    
    ; ========================================================================
    ;                  void io_store_eflags(int eflags);
    ; ========================================================================
    io_load_eflags:
        mov eax, [esp + 4]
        push eax
        popfd          ; 指pop eflags
        ret     
        
    ; ========================================================================
    ;                  void io_cli();
    ; ========================================================================
    io_cli:
        cli
        ret 
    

    c语言函数返回值问题https://blog.csdn.net/wanna_wsl/article/details/70550825

    4、绘制矩形

    画面上由320x200=64000个像素。
    假设左上点的坐标是(0, 0),右下点的坐标是(319, 199),那么像素坐标(x,y)对应的VRAM地址为:
    0xa0000 + x + y*320

    效果
    绘制函数
    // 绘制矩形
    void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1){
        for(int y = y0; y <= y1; y++){
            for(int x = x0; x <= x1; x++){
                vram[y * xsize + x] = c;
            }
        }
    }
    

    调用

        // 绘制矩形
        char *p = (char *) 0xa0000;
        boxfill8(p, 320, COL8_FF0000,  20, 20, 120, 120);
        boxfill8(p, 320, COL8_00FF00,  70, 50, 170, 150);
        boxfill8(p, 320, COL8_0000FF, 120, 80, 220, 180);
    

    5、绘制界面

    效果
    // 绘制ui
    void draw_ui(){
        init_palette();
        
        char *vram = (char *) 0xa0000;
        const int xsize = 320;
        const int ysize = 200;
        
        boxfill8(vram, xsize, COL8_008484, 0,        0, xsize - 1, ysize - 29);
        boxfill8(vram, xsize, COL8_C6C6C6, 0, ysize-28, xsize - 1, ysize - 28);
        boxfill8(vram, xsize, COL8_FFFFFF, 0, ysize-27, xsize - 1, ysize - 27);
        boxfill8(vram, xsize, COL8_C6C6C6, 0, ysize-26, xsize - 1, ysize -  1);
        
        boxfill8(vram, xsize, COL8_FFFFFF,  3, ysize-24, 59, ysize -24);
        boxfill8(vram, xsize, COL8_FFFFFF,  2, ysize-24,  2, ysize - 4);
        boxfill8(vram, xsize, COL8_848484,  3, ysize- 4, 59, ysize - 4);
        boxfill8(vram, xsize, COL8_848484, 59, ysize-23, 59, ysize - 5);
        boxfill8(vram, xsize, COL8_000000,  2, ysize- 3, 59, ysize - 3);
        boxfill8(vram, xsize, COL8_000000, 60, ysize-24, 60, ysize - 3);
        
        boxfill8(vram, xsize, COL8_848484,  xsize - 47, ysize- 24, xsize - 4, ysize - 24);
        boxfill8(vram, xsize, COL8_848484,  xsize - 47, ysize- 23, xsize -47, ysize -  4);
        boxfill8(vram, xsize, COL8_FFFFFF,  xsize - 47, ysize-  3, xsize - 4, ysize -  3);
        boxfill8(vram, xsize, COL8_FFFFFF,  xsize -  3, ysize- 24, xsize - 3, ysize -  3);
    }
    

    相关文章

      网友评论

          本文标题:1.【VGA图形系统初探】

          本文链接:https://www.haomeiwen.com/subject/ntmeoktx.html