操作系统开发日记-day5

书中关于C语言编译的过程和中间的文件可以参考这张图
在这里插入图片描述
今天的其中一个小任务就是把我们写出来的命令行窗口填上颜色,这就要说明一下VRAM是什么东西了,VRAM是 video RAM的缩写,在电脑中指的是显卡内存,也就是用来显示画面的一段内存地址。

我们在bootpack.c中用一个for循环来向地址0xa0000~0xaffff地址的位置写入0x15,意思是全部像素的颜色都是第15种颜色。

void io_hlt(void);
void write_mem8(int addr, int data);

void HariMain(void)
{
    
    
	int i; /*?量声明。?量i是32位整数*/

	for (i = 0xa0000; i <= 0xaffff; i++) {
    
    
		write_mem8(i, 15); /* MOV BYTE [i],15 */
	}

	for (;;) {
    
    
		io_hlt();
	}
}

在这里插入图片描述
接下来换一种方式,通过逻辑运算的方式,将地址与0x0f进行按位与运算,这个时候,低四位保留,高四位全部变为0;

void io_hlt(void);
void write_mem8(int addr, int data);


void HariMain(void)
{
    
    
	int i; /*变量声明。变量i是32位整数*/

	for (i = 0xa0000; i <= 0xaffff; i++) {
    
    
		write_mem8(i, i & 0x0f);
	}

	for (;;) {
    
    
		io_hlt();
	}
}

补充说明一下其余运算方式的结果
在这里插入图片描述
通过上面的运算方式,我们写入的值就是00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 00 01 02 03 04 05 06…每16个像素,色号就反复一次。

在这里插入图片描述
改成与0xFF相与就变成这样了…
在这里插入图片描述
都是学过C的人了,指针用起来!!!

void io_hlt(void);

void HariMain(void)
{
    
    
	int i; /*变量声明。变量i是32位整数*/
	char *p; /* p这个变量是BYTE[…]地址*/

	p = (char *) 0xa0000; /*代入*号*/

	for (i = 0; i <= 0xffff; i++) {
    
    
		p[i] = i & 0x0f;
	}

	for (;;) {
    
    
		io_hlt();
	}
}

这样就把上面的那个write函数给替代了,这就是C语言里面指针的功能,用来向指定的内存地址处写入数据。这里用p[i]的方式,实际上p[i]和*(p+i)是等价的。
在这里插入图片描述
颜色设置
我们之前用的颜色是采用8为二进制数来显示的,而实际上现在的操作系统图形界面采用的都是RGB的方式来显示色彩的,比如#ffffff。由于制作一个简易的操作系统只需要一些颜色就足够了,所以在bootpack.c中设置如下颜色
在这里插入图片描述
bootpack.c完整代码

//bootpack.c  完整代码
#include <stdio.h>

void io_hlt(void);
void io_cli(void);
void io_out8(int port, int data);
int io_load_eflags(void);
void io_store_eflags(int eflags);

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);
void init_screen8(char *vram, int x, int y);
void putfont8(char *vram, int xsize, int x, int y, char c, char *font);
void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s);
void init_mouse_cursor8(char *mouse, char bc);
void putblock8_8(char *vram, int vxsize, int pxsize,
    int pysize, int px0, int py0, char *buf, int bxsize);

#define COL8_000000        0
#define COL8_FF0000        1
#define COL8_00FF00        2
#define COL8_FFFF00        3
#define COL8_0000FF        4
#define COL8_FF00FF        5
#define COL8_00FFFF        6
#define COL8_FFFFFF        7
#define COL8_C6C6C6        8
#define COL8_840000        9
#define COL8_008400        10
#define COL8_848400        11
#define COL8_000084        12
#define COL8_840084        13
#define COL8_008484        14
#define COL8_848484        15

//接受启动信息写成结构体的形式  P89.接着从asmhead.nas中读取启动信息数据(启动地址和内容)
//注意在第一天中,我们已经把asmhead.nas中的信息写到了镜像中。每次系统启动时,首先载入镜像,然后读到asmhead.nas中的内容启动
struct BOOTINFO {
    
      
    char cyls, leds, vmode, reserve;
    short scrnx, scrny;
    char *vram;
};

struct SEGMENT_DESCRIPTOR {
    
      //GDT的内容;8字节
    short limit_low, base_low;
    char base_mid, access_right;
    char limit_high, base_high;
};

struct GATE_DESCRIPTOR {
    
        //IDT的内容,8字节
    short offset_low, selector;
    char dw_count, access_right;
    short offset_high;
};

void init_gdtidt(void);
void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar);
void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar);
void load_gdtr(int limit, int addr);
void load_idtr(int limit, int addr);

void HariMain(void)
{
    
    
    struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0;
    char s[40], mcursor[256];
    int mx, my;

    init_gdtidt();
    init_palette();
    init_screen8(binfo->vram, binfo->scrnx, binfo->scrny);  //所谓的使用箭头记号->
    mx = (binfo->scrnx - 16) / 2;   /* 启动信息结构体BOOTINFO 从asmhead.nas中读取启动信息数据*/
    my = (binfo->scrny - 28 - 16) / 2;

    init_mouse_cursor8(mcursor, COL8_008484); //初始化并显示鼠标指针
    putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16);

    sprintf(s, "(%d, %d)", mx, my);  //显示变量,先把内容放到字符串s中
    putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, s); //接着把字符串s显示出来

    for (;;) {
    
    
        io_hlt();
    }
}

void init_palette(void)
{
    
    
    static unsigned char table_rgb[16 * 3] = {
    
    
        0x00, 0x00, 0x00,    
        0xff, 0x00, 0x00,    
        0x00, 0xff, 0x00,    
        0xff, 0xff, 0x00,    
        0x00, 0x00, 0xff,    
        0xff, 0x00, 0xff,    
        0x00, 0xff, 0xff,    
        0xff, 0xff, 0xff,    
        0xc6, 0xc6, 0xc6,    
        0x84, 0x00, 0x00,    
        0x00, 0x84, 0x00,    
        0x84, 0x84, 0x00,    
        0x00, 0x00, 0x84,    
        0x84, 0x00, 0x84,    
        0x00, 0x84, 0x84,    
        0x84, 0x84, 0x84    
    };
    set_palette(0, 15, table_rgb);
    return;
}

void set_palette(int start, int end, unsigned char *rgb)
{
    
    
    int i, eflags;
    eflags = io_load_eflags();
    io_cli();                     
    io_out8(0x03c8, start);		//往指定装置中传递数据
    for (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);
    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;
}

void init_screen8(char *vram, int x, int y)
{
    
    
    boxfill8(vram, x, COL8_008484,  0,     0,      x -  1, y - 29);
    boxfill8(vram, x, COL8_C6C6C6,  0,     y - 28, x -  1, y - 28);
    boxfill8(vram, x, COL8_FFFFFF,  0,     y - 27, x -  1, y - 27);
    boxfill8(vram, x, COL8_C6C6C6,  0,     y - 26, x -  1, y -  1);

    boxfill8(vram, x, COL8_FFFFFF,  3,     y - 24, 59,     y - 24);
    boxfill8(vram, x, COL8_FFFFFF,  2,     y - 24,  2,     y -  4);
    boxfill8(vram, x, COL8_848484,  3,     y -  4, 59,     y -  4);
    boxfill8(vram, x, COL8_848484, 59,     y - 23, 59,     y -  5);
    boxfill8(vram, x, COL8_000000,  2,     y -  3, 59,     y -  3);
    boxfill8(vram, x, COL8_000000, 60,     y - 24, 60,     y -  3);

    boxfill8(vram, x, COL8_848484, x - 47, y - 24, x -  4, y - 24);
    boxfill8(vram, x, COL8_848484, x - 47, y - 23, x - 47, y -  4);
    boxfill8(vram, x, COL8_FFFFFF, x - 47, y -  3, x -  4, y -  3);
    boxfill8(vram, x, COL8_FFFFFF, x -  3, y - 24, x -  3, y -  3);
    return;
}

//输出,显示字符
void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
{
    
    
    int i;
    char *p, d /* data */;
    for (i = 0; i < 16; i++) {
    
    
        p = vram + (y + i) * xsize + x;
        d = font[i];
        if ((d & 0x80) != 0) {
    
     p[0] = c; }
        if ((d & 0x40) != 0) {
    
     p[1] = c; }
        if ((d & 0x20) != 0) {
    
     p[2] = c; }
        if ((d & 0x10) != 0) {
    
     p[3] = c; }
        if ((d & 0x08) != 0) {
    
     p[4] = c; }
        if ((d & 0x04) != 0) {
    
     p[5] = c; }
        if ((d & 0x02) != 0) {
    
     p[6] = c; }
        if ((d & 0x01) != 0) {
    
     p[7] = c; }
    }
    return;
}

//输出,显示字符串
void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s)
{
    
    
    extern char hankaku[4096];
    for (; *s != 0x00; s++) {
    
    
        putfont8(vram, xsize, x, y, c, hankaku + *s * 16);
        x += 8;
    }
    return;
}

void init_mouse_cursor8(char *mouse, char bc)
/* 准备,初始化鼠标指针 16*16=512字符(字节)*/
{
    
    
    static char cursor[16][16] = {
    
    
        "**************..",
        "*OOOOOOOOOOO*...",
        "*OOOOOOOOOO*....",
        "*OOOOOOOOO*.....",
        "*OOOOOOOO*......",
        "*OOOOOOO*.......",
        "*OOOOOOO*.......",
        "*OOOOOOOO*......",
        "*OOOO**OOO*.....",
        "*OOO*..*OOO*....",
        "*OO*....*OOO*...",
        "*O*......*OOO*..",
        "**........*OOO*.",
        "*..........*OOO*",
        "............*OO*",
        ".............***"
    };
    int x, y;

    for (y = 0; y < 16; y++) {
    
    
        for (x = 0; x < 16; x++) {
    
    
            if (cursor[y][x] == '*') {
    
    
                mouse[y * 16 + x] = COL8_000000;
            }
            if (cursor[y][x] == 'O') {
    
    
                mouse[y * 16 + x] = COL8_FFFFFF;
            }
            if (cursor[y][x] == '.') {
    
    
                mouse[y * 16 + x] = bc;
            }
        }
    }
    return;
}
//这里显示鼠标指针;
void putblock8_8(char *vram, int vxsize, int pxsize,
    int pysize, int px0, int py0, char *buf, int bxsize)
{
    
    
    int x, y;
    for (y = 0; y < pysize; y++) {
    
    
        for (x = 0; x < pxsize; x++) {
    
    
            vram[(py0 + y) * vxsize + (px0 + x)] = buf[y * bxsize + x];
        }
    }
    return;
}

void init_gdtidt(void)   //GDT和IDT的初始化
{
    
    
    struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) 0x00270000;
    struct GATE_DESCRIPTOR    *idt = (struct GATE_DESCRIPTOR    *) 0x0026f800;
    int i;

    /* GDT初始化 */
    for (i = 0; i < 8192; i++) {
    
        //i每次加一;但是gdt指向8字节的结构体;结果地址增加了8
        set_segmdesc(gdt + i, 0, 0, 0);    //gdt*(地址)每次+8
    }
    set_segmdesc(gdt + 1, 0xffffffff, 0x00000000, 0x4092);  //段号为1;大小4G 表示CPU管理的全部内存
    set_segmdesc(gdt + 2, 0x0007ffff, 0x00280000, 0x409a);  //段号位2; 大小512K  为bootpack.hrb准备
    load_gdtr(0xffff, 0x00270000);  //GDT    0x270000-0x27ffff  借助汇编语言的力量给寄存器GDTR赋值

    /* IDT初始化  */
    for (i = 0; i < 256; i++) {
    
        //和上面一样
        set_gatedesc(idt + i, 0, 0, 0);
    }                               //IDT    0x26f800-0x26ffff
    load_idtr(0x7ff, 0x0026f800);    //向寄存器IDTR赋值

    return;
}

void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar)
{
    
    
    if (limit > 0xfffff) {
    
    
        ar |= 0x8000; /* G_bit = 1 */
        limit /= 0x1000;
    }
    sd->limit_low    = limit & 0xffff;
    sd->base_low     = base & 0xffff;
    sd->base_mid     = (base >> 16) & 0xff;
    sd->access_right = ar & 0xff;
    sd->limit_high   = ((limit >> 16) & 0x0f) | ((ar >> 8) & 0xf0);
    sd->base_high    = (base >> 24) & 0xff;
    return;
}

void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar)
{
    
    
    gd->offset_low   = offset & 0xffff;
    gd->selector     = selector;
    gd->dw_count     = (ar >> 8) & 0xff;
    gd->access_right = ar & 0xff;
    gd->offset_high  = (offset >> 16) & 0xffff;
    return;
}
bootpack.c 完整代码day_05
harib02a:

  P89 这里做的就是数值写入asmhead.nas中,然后取值;
  而不是将这些数值直接写入程序bootpack.c中

//bootpack.c节选
void HariMain(void)
{
    
    
    char *vram;
    int xsize, ysize;
    short *binfo_scrnx, *binfo_scrny;
    int *binfo_vram;

    init_palette();
    binfo_scrnx = (short *) 0x0ff4;
    binfo_scrny = (short *) 0x0ff6;
    binfo_vram = (int *) 0x0ff8;
    xsize = *binfo_scrnx;
    ysize = *binfo_scrny;
    vram = (char *) *binfo_vram;

    init_screen(vram, xsize, ysize);
    for (;;) {
    
    
        io_hlt();
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_45394002/article/details/113836957
今日推荐