第10天 叠加处理

提高叠加处理速度(2)

harib07d

准备材料(windows环境)
  • VMware Workstation
  • Visual Studio Code
  • 程序和源代码:https://pan.baidu.com/s/1bFGAYgnA0m9KB7tzFrMD5g
    提取码:d210
  • Makefile
  • windows 批处理
开始实验
  1. 在tolset文件夹下创建子文件侠harib07d。

  2. 打开记事本,输入以下代码并另存为 !cons_nt.bat文件(windows 批处理),存放在harib07d文件夹中。

cmd.exe

ps:当然也可以直接使用 win + r 快捷键也可以,不过最好还是创建一个比较好。因为以后打开时不需要再麻烦了。
3. 打开vc code,输入以下代码并保存为 naskfunc.nas,存放在harib07d文件夹中。

; naskfunc
; TAB=4[FORMAT "WCOFF"]              ; 制作目标文件的模式
[INSTRSET "i486p"]                ; 要使用486指令的语句
[BITS 32]                       ; 制作32位模式用的机器语言
[FILE "naskfunc.nas"]         ; 原文件名信息GLOBAL  _io_hlt, _io_cli, _io_sti, _io_stihltGLOBAL _io_in8,  _io_in16,  _io_in32GLOBAL _io_out8, _io_out16, _io_out32GLOBAL    _io_load_eflags, _io_store_eflagsGLOBAL _load_gdtr, _load_idtrGLOBAL    _load_cr0, _store_cr0GLOBAL _asm_inthandler21, _asm_inthandler27, _asm_inthandler2cGLOBAL   _memtest_subEXTERN  _inthandler21, _inthandler27, _inthandler2c[SECTION .text]  _io_hlt:    ; void io_hlt(void);HLTRET_io_cli:  ; void io_cli(void);CLIRET_io_sti:  ; void io_sti(void);STIRET_io_stihlt:   ; void io_stihlt(void);STIHLTRET_io_in8:    ; int io_in8(int port);MOV      EDX,[ESP+4]        ; portMOV       EAX,0IN     AL,DXRET_io_in16:   ; int io_in16(int port);MOV     EDX,[ESP+4]        ; portMOV       EAX,0IN     AX,DXRET_io_in32:   ; int io_in32(int port);MOV     EDX,[ESP+4]        ; portIN        EAX,DXRET_io_out8:  ; void io_out8(int port, int data);MOV      EDX,[ESP+4]        ; portMOV       AL,[ESP+8]     ; dataOUT       DX,ALRET_io_out16:  ; void io_out16(int port, int data);MOV     EDX,[ESP+4]        ; portMOV       EAX,[ESP+8]        ; dataOUT       DX,AXRET_io_out32:  ; void io_out32(int port, int data);MOV     EDX,[ESP+4]        ; portMOV       EAX,[ESP+8]        ; dataOUT       DX,EAXRET_io_load_eflags:   ; int io_load_eflags(void);PUSHFD       ; 指 PUSH EFLAGSPOP      EAXRET_io_store_eflags: ; void io_store_eflags(int eflags);MOV      EAX,[ESP+4]PUSH    EAXPOPFD        ; 指 POP EFLAGSRET_load_gdtr:        ; void load_gdtr(int limit, int addr);MOV       AX,[ESP+4]     ; limitMOV      [ESP+6],AXLGDT [ESP+6]RET_load_idtr:      ; void load_idtr(int limit, int addr);MOV       AX,[ESP+4]     ; limitMOV      [ESP+6],AXLIDT [ESP+6]RET_load_cr0:       ; int load_cr0(void);MOV        EAX,CR0RET_store_cr0:       ; void store_cr0(int cr0);MOV       EAX,[ESP+4]MOV     CR0,EAXRET_asm_inthandler21:PUSH    ESPUSH  DSPUSHADMOV     EAX,ESPPUSH EAXMOV      AX,SSMOV        DS,AXMOV        ES,AXCALL   _inthandler21POP        EAXPOPADPOP     DSPOP       ESIRETD_asm_inthandler27:PUSH   ESPUSH  DSPUSHADMOV     EAX,ESPPUSH EAXMOV      AX,SSMOV        DS,AXMOV        ES,AXCALL   _inthandler27POP        EAXPOPADPOP     DSPOP       ESIRETD_asm_inthandler2c:PUSH   ESPUSH  DSPUSHADMOV     EAX,ESPPUSH EAXMOV      AX,SSMOV        DS,AXMOV        ES,AXCALL   _inthandler2cPOP        EAXPOPADPOP     DSPOP       ESIRETD_memtest_sub:    ; unsigned int memtest_sub(unsigned int start, unsigned int end)PUSH    EDI                     ; (由于还要使用EBX, ESI, EDI)PUSH  ESIPUSH EBXMOV      ESI,0xaa55aa55          ; pat0 = 0xaa55aa55;MOV        EDI,0x55aa55aa          ; pat1 = 0x55aa55aa;MOV        EAX,[ESP+12+4]            ; i = start;
mts_loop:MOV        EBX,EAXADD      EBX,0xffc               ; p = i + 0xffc;MOV       EDX,[EBX]               ; old = *p;MOV     [EBX],ESI               ; *p = pat0;XOR        DWORD [EBX],0xffffffff  ; *p ^= 0xffffffff;CMP     EDI,[EBX]               ; if (*p != pat1) goto fin;JNE     mts_finXOR      DWORD [EBX],0xffffffff  ; *p ^= 0xffffffff;CMP     ESI,[EBX]               ; if (*p != pat0) goto fin;JNE     mts_finMOV      [EBX],EDX               ; *p = old;ADD     EAX,0x1000              ; i += 0x1000;CMP     EAX,[ESP+12+8]            ; if (i <= end) goto mts_loop;JBE       mts_loopPOP     EBXPOP      ESIPOP      EDIRET
mts_fin:MOV     [EBX],EDX               ; *p = old;POP     EBXPOP      ESIPOP      EDIRET
  1. 打开vc code,输入以下代码并保存为 bootpack.c 存放在harib07d文件夹中。
/* bootpack 其他处理 */#include "bootpack.h"
#include <stdio.h>void HariMain(void)
{struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;char s[40], keybuf[32], mousebuf[128];int mx, my, i;unsigned int memtotal;struct MOUSE_DEC mdec;struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;struct SHTCTL *shtctl;struct SHEET *sht_back, *sht_mouse;unsigned char *buf_back, buf_mouse[256];    init_gdtidt();init_pic();io_sti(); /* 由于IDT / PIC的初始化已完成,因此请禁用CPU的中断。 */fifo8_init(&keyfifo, 32, keybuf);fifo8_init(&mousefifo, 128, mousebuf);io_out8(PIC0_IMR, 0xf9); /* 允许PIC1和键盘(11111001) */io_out8(PIC1_IMR, 0xef); /* 允许鼠标(11101111) */init_keyboard();enable_mouse(&mdec);memtotal = memtest(0x00400000, 0xbfffffff);memman_init(memman);memman_free(memman, 0x00001000, 0x0009e000); /* 0x00001000 - 0x0009efff */memman_free(memman, 0x00400000, memtotal - 0x00400000);init_palette();shtctl = shtctl_init(memman, binfo->vram, binfo->scrnx, binfo->scrny);sht_back  = sheet_alloc(shtctl);sht_mouse = sheet_alloc(shtctl);buf_back  = (unsigned char *) memman_alloc_4k(memman, binfo->scrnx * binfo->scrny);sheet_setbuf(sht_back, buf_back, binfo->scrnx, binfo->scrny, -1); /* 没有透明色 */sheet_setbuf(sht_mouse, buf_mouse, 16, 16, 99); /* 透明色号99 */init_screen8(buf_back, binfo->scrnx, binfo->scrny);init_mouse_cursor8(buf_mouse, 99); /* 背景色号99 */sheet_slide(shtctl, sht_back, 0, 0);    mx = (binfo->scrnx - 16) / 2; /* 按显示在画面中央来计算坐标 */my = (binfo->scrny - 28 - 16) / 2;sheet_slide(shtctl, sht_mouse, mx, my);sheet_updown(shtctl, sht_back,  0);sheet_updown(shtctl, sht_mouse, 1);sprintf(s, "(%3d, %3d)", mx, my);putfonts8_asc(buf_back, binfo->scrnx, 0, 0, COL8_FFFFFF, s);sprintf(s, "memory %dMB   free : %dKB",memtotal / (1024 * 1024), memman_total(memman) / 1024);putfonts8_asc(buf_back, binfo->scrnx, 0, 32, COL8_FFFFFF, s);sheet_refresh(shtctl, sht_back, 0, 0, binfo->scrnx, 48); /* 这里! */for (;;) {io_cli();if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) {io_stihlt();} else {if (fifo8_status(&keyfifo) != 0) {i = fifo8_get(&keyfifo);io_sti();sprintf(s, "%02X", i);boxfill8(buf_back, binfo->scrnx, COL8_008484,  0, 16, 15, 31);putfonts8_asc(buf_back, binfo->scrnx, 0, 16, COL8_FFFFFF, s);sheet_refresh(shtctl, sht_back, 0, 16, 16, 32);} else if (fifo8_status(&mousefifo) != 0) {i = fifo8_get(&mousefifo);io_sti();if (mouse_decode(&mdec, i) != 0) {/* 因为已得到3字节的数据所以显示 */sprintf(s, "[lcr %4d %4d]", mdec.x, mdec.y);if ((mdec.btn & 0x01) != 0) {s[1] = 'L';}if ((mdec.btn & 0x02) != 0) {s[3] = 'R';}if ((mdec.btn & 0x04) != 0) {s[2] = 'C';}boxfill8(buf_back, binfo->scrnx, COL8_008484, 32, 16, 32 + 15 * 8 - 1, 31);putfonts8_asc(buf_back, binfo->scrnx, 32, 16, COL8_FFFFFF, s);sheet_refresh(shtctl, sht_back, 32, 16, 32 + 15 * 8, 32); /* 这里! *//* 移动光标 */mx += mdec.x;my += mdec.y;if (mx < 0) {mx = 0;}if (my < 0) {my = 0;}if (mx > binfo->scrnx - 16) {mx = binfo->scrnx - 16;}if (my > binfo->scrny - 16) {my = binfo->scrny - 16;}sprintf(s, "(%3d, %3d)", mx, my);boxfill8(buf_back, binfo->scrnx, COL8_008484, 0, 0, 79, 15); /* 消去坐标 */putfonts8_asc(buf_back, binfo->scrnx, 0, 0, COL8_FFFFFF, s); /* 写出坐标 */sheet_refresh(shtctl, sht_back, 0, 0, 80, 16); /* 这里! */sheet_slide(shtctl, sht_mouse, mx, my);}}}}
}
  1. 打开vc code,输入以下代码并保存为 bootpack.h 存放在harib07d文件夹中。
/* asmhead.nas */
struct BOOTINFO { /* 0xff0-0x0fff */char cyls; /* 启动区读硬盘读到何处为止 */char leds; /* 启动时键盘LED的状态 */char vmode; /* 显卡模式为多少位彩色 */char reserve;short scrnx, scrny; /* 画面分辨率 */char *vram;
};
#define ADR_BOOTINFO    0x00000ff0/* naskfunc.nas */
void io_hlt(void);
void io_cli(void);
void io_sti(void);
void io_stihlt(void);
int io_in8(int port);
void io_out8(int port, int data);
int io_load_eflags(void);
void io_store_eflags(int eflags);
void load_gdtr(int limit, int addr);
void load_idtr(int limit, int addr);
int load_cr0(void);
void store_cr0(int cr0);
void asm_inthandler21(void);
void asm_inthandler27(void);
void asm_inthandler2c(void);
unsigned int memtest_sub(unsigned int start, unsigned int end);/* fifo.c */
struct FIFO8 {unsigned char *buf;int p, q, size, free, flags;
};
void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf);
int fifo8_put(struct FIFO8 *fifo, unsigned char data);
int fifo8_get(struct FIFO8 *fifo);
int fifo8_status(struct FIFO8 *fifo);/* 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);
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/* dsctbl.c */
struct SEGMENT_DESCRIPTOR {short limit_low, base_low;char base_mid, access_right;char limit_high, base_high;
};
struct GATE_DESCRIPTOR {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);
#define ADR_IDT         0x0026f800
#define LIMIT_IDT       0x000007ff
#define ADR_GDT         0x00270000
#define LIMIT_GDT       0x0000ffff
#define ADR_BOTPAK      0x00280000
#define LIMIT_BOTPAK    0x0007ffff
#define AR_DATA32_RW    0x4092
#define AR_CODE32_ER    0x409a
#define AR_INTGATE32    0x008e/* int.c */
void init_pic(void);
void inthandler27(int *esp);
#define PIC0_ICW1       0x0020
#define PIC0_OCW2       0x0020
#define PIC0_IMR        0x0021
#define PIC0_ICW2       0x0021
#define PIC0_ICW3       0x0021
#define PIC0_ICW4       0x0021
#define PIC1_ICW1       0x00a0
#define PIC1_OCW2       0x00a0
#define PIC1_IMR        0x00a1
#define PIC1_ICW2       0x00a1
#define PIC1_ICW3       0x00a1
#define PIC1_ICW4       0x00a1/* keyboard.c */
void inthandler21(int *esp);
void wait_KBC_sendready(void);
void init_keyboard(void);
extern struct FIFO8 keyfifo;
#define PORT_KEYDAT     0x0060
#define PORT_KEYCMD     0x0064/* mouse.c */
struct MOUSE_DEC {unsigned char buf[3], phase;int x, y, btn;
};
void inthandler2c(int *esp);
void enable_mouse(struct MOUSE_DEC *mdec);
int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat);
extern struct FIFO8 mousefifo;/* memory.c */
#define MEMMAN_FREES        4090    /* 大约是32KB */
#define MEMMAN_ADDR         0x003c0000
struct FREEINFO {   /* 可用信息 */unsigned int addr, size;
};
struct MEMMAN {     /* 内存管理 */int frees, maxfrees, lostsize, losts;struct FREEINFO free[MEMMAN_FREES];
};
unsigned int memtest(unsigned int start, unsigned int end);
void memman_init(struct MEMMAN *man);
unsigned int memman_total(struct MEMMAN *man);
unsigned int memman_alloc(struct MEMMAN *man, unsigned int size);
int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size);
unsigned int memman_alloc_4k(struct MEMMAN *man, unsigned int size);
int memman_free_4k(struct MEMMAN *man, unsigned int addr, unsigned int size);/* sheet.c */
#define MAX_SHEETS      256
struct SHEET {unsigned char *buf;int bxsize, bysize, vx0, vy0, col_inv, height, flags;
};
struct SHTCTL {unsigned char *vram;int xsize, ysize, top;struct SHEET *sheets[MAX_SHEETS];struct SHEET sheets0[MAX_SHEETS];
};
struct SHTCTL *shtctl_init(struct MEMMAN *memman, unsigned char *vram, int xsize, int ysize);
struct SHEET *sheet_alloc(struct SHTCTL *ctl);
void sheet_setbuf(struct SHEET *sht, unsigned char *buf, int xsize, int ysize, int col_inv);
void sheet_updown(struct SHTCTL *ctl, struct SHEET *sht, int height);
void sheet_refresh(struct SHTCTL *ctl, struct SHEET *sht, int bx0, int by0, int bx1, int by1);
void sheet_slide(struct SHTCTL *ctl, struct SHEET *sht, int vx0, int vy0);
void sheet_free(struct SHTCTL *ctl, struct SHEET *sht);
  1. 打开vc code,输入以下代码并保存为 dsctbl.c 存放在harib07d文件夹中。
/* 关于GDT,IDT等descriptor table的处理 */#include "bootpack.h"void init_gdtidt(void)
{struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) ADR_GDT;struct GATE_DESCRIPTOR    *idt = (struct GATE_DESCRIPTOR    *) ADR_IDT;int i;/* GDT的初始化 */for (i = 0; i <= LIMIT_GDT / 8; i++) {set_segmdesc(gdt + i, 0, 0, 0);}set_segmdesc(gdt + 1, 0xffffffff,   0x00000000, AR_DATA32_RW);set_segmdesc(gdt + 2, LIMIT_BOTPAK, ADR_BOTPAK, AR_CODE32_ER);load_gdtr(LIMIT_GDT, ADR_GDT);/* IDT的初始化 */for (i = 0; i <= LIMIT_IDT / 8; i++) {set_gatedesc(idt + i, 0, 0, 0);}load_idtr(LIMIT_IDT, ADR_IDT);/* IDT的设定 */set_gatedesc(idt + 0x21, (int) asm_inthandler21, 2 * 8, AR_INTGATE32);set_gatedesc(idt + 0x27, (int) asm_inthandler27, 2 * 8, AR_INTGATE32);set_gatedesc(idt + 0x2c, (int) asm_inthandler2c, 2 * 8, AR_INTGATE32);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;
}

ps: 。
7. 打vc code,输入以下代码并保存为 fifo.c,存放在harib07d文件夹中。

/* FIFO库 */#include "bootpack.h"#define FLAGS_OVERRUN      0x0001void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf)
/* 初始化 FIFO 缓冲区 */
{fifo->size = size;fifo->buf = buf;fifo->free = size; /* 缓冲区的大小 */fifo->flags = 0;fifo->p = 0;    /* 下一个数据写入位置 */fifo->q = 0;    /* 下一个数据读出位置 */return;
}int fifo8_put(struct FIFO8 *fifo, unsigned char data)
/* 向 FIFO 传送数据并保存 */
{if (fifo->free == 0) {/* 空余没有了,溢出 */fifo->flags |= FLAGS_OVERRUN;return -1;}fifo->buf[fifo->p] = data;fifo->p++;if (fifo->p == fifo->size) {fifo->p = 0;}fifo->free--;return 0;
}int fifo8_get(struct FIFO8 *fifo)
/* 从 FIFO 取得一个数据 */
{int data;if (fifo->free == fifo->size) {/* 如果缓冲区为空,则返回-1 */return -1;}data = fifo->buf[fifo->q];fifo->q++;if (fifo->q == fifo->size) {fifo->q = 0;}fifo->free++;return data;
}int fifo8_status(struct FIFO8 *fifo)
/* 报告一下到底积攒了多少数据 */
{return fifo->size - fifo->free;
}
  1. 打vc code,输入以下代码并保存为 graphic.c,存放在harib07d文件夹中。
/* u关于描画的处理 */#include "bootpack.h"void init_palette(void)
{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, 0x00, 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);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_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;  /* date */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 x 16) */
{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;
}
  1. 打vc code,输入以下代码并保存为 int.c,存放在harib07d文件夹中。
/* 与中断有关 */#include "bootpack.h"
#include <stdio.h>void init_pic(void)
/* PIC的初始化 */
{io_out8(PIC0_IMR,  0xff  );    /* 禁止所有中断 */io_out8(PIC1_IMR,  0xff  ); /* 禁止所有中断 */io_out8(PIC0_ICW1, 0x11  ); /* 边沿触发模式 (edge trigger mode) */io_out8(PIC0_ICW2, 0x20  ); /* IRQ0-7 由 INT20-27 接收 */io_out8(PIC0_ICW3, 1 << 2); /* PIC1 由 IRQ2 连接 */io_out8(PIC0_ICW4, 0x01  ); /* 无缓冲区模式 */io_out8(PIC1_ICW1, 0x11  ); /* 边沿触发模式 (edge trigger mode) */io_out8(PIC1_ICW2, 0x28  ); /* IRQ8-15 由 INT28-2f 接收 */io_out8(PIC1_ICW3, 2     );  /* PIC1 由 IRQ2 连接 */io_out8(PIC1_ICW4, 0x01  ); /* 无缓冲区域 */io_out8(PIC0_IMR,  0xfb  );  /* 11111011 PIC1 以外全部禁止 */io_out8(PIC1_IMR,  0xff  );   /* 11111111 禁止所有中断 */return;
}void inthandler27(int *esp)
/* 防止来自PIC0的不完整中断的措施 */
/* 在Athlon64X2机器等中,由于芯片组的便利性,该中断在PIC初始化时仅发生一次 */
/* 此中断处理功能不执行中断 */
/* 您为什么不做任何事情? */
/* 由于此中断是由PIC初始化期间的电气噪声产生的,*/
/* 您不需要认真做任何事情。 */
{io_out8(PIC0_OCW2, 0x67); /* 通知PIC IRQ-07已被接受(见7-1)*/return;
}
  1. 打vc code,输入以下代码并保存为 keyboard.c,存放在harib07d文件夹中。
/* 与键盘相关 */#include "bootpack.h"struct FIFO8 keyfifo;void inthandler21(int *esp)
{unsigned char data;io_out8(PIC0_OCW2, 0x61);   /* 通知PIC“IRQ-01”已经受理完毕 */data = io_in8(PORT_KEYDAT);fifo8_put(&keyfifo, data);return;
}#define PORT_KEYSTA                0x0064
#define KEYSTA_SEND_NOTREADY    0x02
#define KEYCMD_WRITE_MODE       0x60
#define KBC_MODE                0x47void wait_KBC_sendready(void)
{/* 等待键盘控制电路准备完毕  */for (;;) {if ((io_in8(PORT_KEYSTA) & KEYSTA_SEND_NOTREADY) == 0) {break;}}return;
}void init_keyboard(void)
{/* 初始化键盘控制电路 */wait_KBC_sendready();io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE);wait_KBC_sendready();io_out8(PORT_KEYDAT, KBC_MODE);return;
}
  1. 打vc code,输入以下代码并保存为 memory.c,存放在harib07d文件夹中。
/* 内存管理 */#include "bootpack.h"#define EFLAGS_AC_BIT       0x00040000
#define CR0_CACHE_DISABLE   0x60000000unsigned int memtest(unsigned int start, unsigned int end)
{char flg486 = 0;unsigned int eflg, cr0, i;/* 确认CPU是386还是486以上的 */eflg = io_load_eflags();eflg |= EFLAGS_AC_BIT; /* AC-bit = 1 */io_store_eflags(eflg);eflg = io_load_eflags();if ((eflg & EFLAGS_AC_BIT) != 0) { /* 如果是386,即使设定AC=1,AC的值还会自动回到0 */flg486 = 1;}eflg &= ~EFLAGS_AC_BIT; /* AC-bit = 0 */io_store_eflags(eflg);if (flg486 != 0) {cr0 = load_cr0();cr0 |= CR0_CACHE_DISABLE; /* 禁止缓存 */store_cr0(cr0);}i = memtest_sub(start, end);if (flg486 != 0) {cr0 = load_cr0();cr0 &= ~CR0_CACHE_DISABLE; /* 允许缓存 */store_cr0(cr0);}return i;
}void memman_init(struct MEMMAN *man)
{man->frees = 0;            /* 可用信息数目 */man->maxfrees = 0;      /* 用于观察可用状况:frees的最大值 */man->lostsize = 0;       /* 释放失败的内在的大小总和 */man->losts = 0;           /* 释放失败次数 */return;
}unsigned int memman_total(struct MEMMAN *man)
/* 报告空余内存大小的命令 */
{unsigned int i, t = 0;for (i = 0; i < man->frees; i++) {t += man->free[i].size;}return t;
}unsigned int memman_alloc(struct MEMMAN *man, unsigned int size)
/* 分配 */
{unsigned int i, a;for (i = 0; i < man->frees; i++) {if (man->free[i].size >= size) {/* 找到了足够大的内存 */a = man->free[i].addr;man->free[i].addr += size;man->free[i].size -= size;if (man->free[i].size == 0) {/* 如果free[i]变成了0,就减掉一条可用信息 */man->frees--;for (; i < man->frees; i++) {man->free[i] = man->free[i + 1]; /* 代入结构体 */}}    return a;}}return 0; /* 没有可用空间 */
}int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size)
/* 释放 */
{int i, j;/* 为便于归纳内存,将free[]放按照addr的顺序排列 *//* 所以,先决定应该放在哪里 */for (i = 0; i < man->frees; i++) {if (man->free[i].addr > addr) {break;}}/* free[i - 1].addr < addr < free[i].addr */if (i > 0) {/* 前面有可用内在 */if (man->free[i - 1].addr + man->free[i - 1].size == addr) {/* 可以与前面的可用内存归纳到一起 */man->free[i - 1].size += size;if (i < man->frees) {/* 后面也有 */if (addr + size == man->free[i].addr) {/* 也可以与后面的可用内存归纳到一起 */man->free[i - 1].size += man->free[i].size;/* man-free[i]删除 *//* free[i]变成0后归纳到前面去 */man->frees--;for (; i < man->frees; i++) {man->free[i] = man->free[i + 1]; /* 结构体赋值 */}}}return 0; /* 成功完成 */}}/* 不能与前面的可用空间归纳到一起 */if (i < man->frees) {/* 后面还有 */if (addr + size == man->free[i].addr) {/* 可以与后面的内容归纳到一起 */man->free[i].addr = addr;man->free[i].size += size;return 0; /* 成功完成 */}}/* 既不能与前面归纳到一起,也不能与后面归纳到一起 */if (man->frees < MEMMAN_FREES) {/* free[i]之后的,向后移动,腾出一点可用空间 */for (j = man->frees; j > i; j--) {man->free[j] = man->free[j - 1];}man->frees++;if (man->maxfrees < man->frees) {man->maxfrees = man->frees; /* 更新最大值 */}man->free[i].addr = addr;man->free[i].size = size;return 0; /* 成功完成 */}/* 不能往后移动 */man->losts++;man->lostsize += size;return -1; /* 失败 */
}unsigned int memman_alloc_4k(struct MEMMAN *man, unsigned int size)
{unsigned int a;size = (size + 0xfff) & 0xfffff000;a = memman_alloc(man, size);return a;
}int memman_free_4k(struct MEMMAN *man, unsigned int addr, unsigned int size)
{int i;size = (size + 0xfff) & 0xfffff000;i = memman_free(man, addr, size);return i;
}
  1. 打vc code,输入以下代码并保存为 mouse.c,存放在harib07d文件夹中。
/* 与鼠标相关 */#include "bootpack.h"struct FIFO8 mousefifo;void inthandler2c(int *esp)
/* 来自PS/2键盘的中断 */
{unsigned char data;io_out8(PIC1_OCW2, 0x64);   /* 通知PIC1 IRQ-12的受理已经完成 */io_out8(PIC0_OCW2, 0x62); /* 通知PIC0 IRQ-02的受理已经完成 */data = io_in8(PORT_KEYDAT);fifo8_put(&mousefifo, data);return;
}#define KEYCMD_SENDTO_MOUSE        0xd4
#define MOUSECMD_ENABLE         0xf4void enable_mouse(struct MOUSE_DEC *mdec)
{/* 激活鼠标 */wait_KBC_sendready();io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);wait_KBC_sendready();io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);/* 顺利的话,ACK(0xfa)会被传送过来 */mdec->phase = 0;    /* 等待0xfa的阶段 */return;
}int mouse_decode(struct MOUSE_DEC *mdec, unsigned char dat)
{if (mdec->phase == 0) {/* 等待鼠标的0xfa的阶段 */if (dat == 0xfa) {mdec->phase = 1;}return 0;}if (mdec->phase == 1) {/* 等待鼠标第一字节的阶段 */if ((dat & 0xc8) == 0x08) {/* 如果第一字节正确 */mdec->buf[0] = dat;mdec->phase = 2;}return 0;}if (mdec->phase == 2) {/* 等待鼠标第二字节的阶段 */mdec->buf[1] = dat;mdec->phase = 3;return 0;}if (mdec->phase == 3) {/* 等待鼠标第三字节的阶段 */mdec->buf[2] = dat;mdec->phase = 1;mdec->btn = mdec->buf[0] & 0x07;mdec->x = mdec->buf[1];mdec->y = mdec->buf[2];if ((mdec->buf[0] & 0x10) != 0) {mdec->x |= 0xffffff00;}if ((mdec->buf[0] & 0x20) != 0) {mdec->y |= 0xffffff00;}mdec->y = - mdec->y; /* 鼠标y方向与画面符号相反 */return 1;}return -1; /* 应该不可能到这里来 */
}
  1. 打vc code,输入以下代码并保存为 sheet.c,存放在harib07d文件夹中。
/* 画面叠加处理 */#include "bootpack.h"#define SHEET_USE     1struct SHTCTL *shtctl_init(struct MEMMAN *memman, unsigned char *vram, int xsize, int ysize)
{struct SHTCTL *ctl;int i;ctl = (struct SHTCTL *) memman_alloc_4k(memman, sizeof (struct SHTCTL));if (ctl == 0) {goto err;}ctl->vram = vram;ctl->xsize = xsize;ctl->ysize = ysize;ctl->top = -1; /* 一个SHEET都没有 */for (i = 0; i < MAX_SHEETS; i++) {ctl->sheets0[i].flags = 0; /* 标记为未使用 */}
err:return ctl;
}struct SHEET *sheet_alloc(struct SHTCTL *ctl)
{struct SHEET *sht;int i;for (i = 0; i < MAX_SHEETS; i++) {if (ctl->sheets0[i].flags == 0) {sht = &ctl->sheets0[i];sht->flags = SHEET_USE; /* 标记为正在使用 */sht->height = -1; /* 隐藏 */return sht;}}return 0; /* 所有的SHEET都处于正在使用状态 */
}void sheet_setbuf(struct SHEET *sht, unsigned char *buf, int xsize, int ysize, int col_inv)
{sht->buf = buf;sht->bxsize = xsize;sht->bysize = ysize;sht->col_inv = col_inv;return;
}void sheet_refreshsub(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1)
{int h, bx, by, vx, vy, bx0, by0, bx1, by1;unsigned char *buf, c, *vram = ctl->vram;struct SHEET *sht;for (h = 0; h <= ctl->top; h++) {sht = ctl->sheets[h];buf = sht->buf;/* 使用vx0~vy1,对bx0~by1进行转换 */bx0 = vx0 - sht->vx0;by0 = vy0 - sht->vy0;bx1 = vx1 - sht->vx0;by1 = vy1 - sht->vy0;if (bx0 < 0) { bx0 = 0; }if (by0 < 0) { by0 = 0; }if (bx1 > sht->bxsize) { bx1 = sht->bxsize; }if (by1 > sht->bysize) { by1 = sht->bysize; }for (by = by0; by < by1; by++) {vy = sht->vy0 + by;for (bx = bx0; bx < bx1; bx++) {vx = sht->vx0 + bx;c = buf[by * sht->bxsize + bx];if (c != sht->col_inv) {vram[vy * ctl->xsize + vx] = c;}}}}return;
}void sheet_updown(struct SHTCTL *ctl, struct SHEET *sht, int height)
{int h, old = sht->height; /* 存储设置前的高度信息 *//* 如果指定的高度过高或过低,则进行修正 */if (height > ctl->top + 1) {height = ctl->top + 1;}if (height < -1) {height = -1;}sht->height = height; /* 设定高度 *//* 下面主要是进行sheets[]的重新排列 */if (old > height) {    /* 比以前低 */if (height >= 0) {/* 把中间的往上提 */for (h = old; h > height; h--) {ctl->sheets[h] = ctl->sheets[h - 1];ctl->sheets[h]->height = h;}ctl->sheets[height] = sht;} else {   /* 隐藏 */if (ctl->top > old) {/* 把上面的降下来 */for (h = old; h < ctl->top; h++) {ctl->sheets[h] = ctl->sheets[h + 1];ctl->sheets[h]->height = h;}}ctl->top--; /* 由于显示中的图层减少了一个,所以最上面的图层高度下降 */}sheet_refreshsub(ctl, sht->vx0, sht->vy0, sht->vx0 + sht->bxsize, sht->vy0 + sht->bysize);} else if (old < height) {   /* 比以前高 */if (old >= 0) {/* 把中间的拉下来 */for (h = old; h < height; h++) {ctl->sheets[h] = ctl->sheets[h + 1];ctl->sheets[h]->height = h;}ctl->sheets[height] = sht;} else {   /* 由隐藏状态转为显示状态 *//* 奖已在上面的提上来 */for (h = ctl->top; h >= height; h--) {ctl->sheets[h + 1] = ctl->sheets[h];ctl->sheets[h + 1]->height = h + 1;}ctl->sheets[height] = sht;ctl->top++; /* 由于已显示的图层增加了1个,所以最上面的图层高度增加 */}sheet_refreshsub(ctl, sht->vx0, sht->vy0, sht->vx0 + sht->bxsize, sht->vy0 + sht->bysize);}return;
}void sheet_refresh(struct SHTCTL *ctl, struct SHEET *sht, int bx0, int by0, int bx1, int by1)
{if (sht->height >= 0) { /* 如果正在显示, 则按新图层的信息刷新画面 */sheet_refreshsub(ctl, sht->vx0 + bx0, sht->vy0 + by0, sht->vx0 + bx1, sht->vy0 + by1);}return;
}void sheet_slide(struct SHTCTL *ctl, struct SHEET *sht, int vx0, int vy0)
{int old_vx0 = sht->vx0, old_vy0 = sht->vy0;sht->vx0 = vx0;sht->vy0 = vy0;if (sht->height >= 0) { /* 如果正在显示, 则按新图层的信息刷新画面 */sheet_refreshsub(ctl, old_vx0, old_vy0, old_vx0 + sht->bxsize, old_vy0 + sht->bysize);sheet_refreshsub(ctl, vx0, vy0, vx0 + sht->bxsize, vy0 + sht->bysize);}return;
}void sheet_free(struct SHTCTL *ctl, struct SHEET *sht)
{if (sht->height >= 0) {sheet_updown(ctl, sht, -1); /* 如果牌显示状态,则先设定为隐藏 */}sht->flags = 0; /* "未使用"标志 */return;
}
  1. 打vc code,输入以下代码并保存为 asmhead.nas,存放在harib07d文件夹中。
; haribote-os boot asm
; TAB=4BOTPAK  EQU     0x00280000      ; bootpack装载处
DSKCAC  EQU     0x00100000      ; 磁盘缓存的地方
DSKCAC0 EQU     0x00008000      ; 磁盘高速缓存的场所(实时模式); 有关BOOT_INFO
CYLS    EQU     0x0ff0          ; 设定启动区
LEDS    EQU     0x0ff1
VMODE   EQU     0x0ff2          ; 关于颜色数目的信息,颜色的位数
SCRNX   EQU     0x0ff4          ; 分辨率的X(screen x)
SCRNY   EQU     0x0ff6          ; 分辨率的Y(screen y)
VRAM    EQU     0x0ff8          ; 图像缓冲区的开始地址ORG     0xc200          ; 这个程序要被装载到内存的什么地方呢?; 画面模式设定MOV      AL,0x13         ; VGA显卡,320x200x8位彩色MOV      AH,0x00INT      0x10MOV     BYTE [VMODE],8  ; 记录画面模式(C语言参照)MOV        WORD [SCRNX],320MOV     WORD [SCRNY],200MOV     DWORD [VRAM],0x000a0000; 用BIOS取得键盘各种LED指示灯的状态MOV        AH,0x02INT      0x16            ; keyboard BIOSMOV      [LEDS],AL; 使PIC不授受一切中断
;   如果要初始PIC的话,要在AT兼容的规范中,
;   如果不把这家伙放在CLI面前,我偶尔会举起来
;   稍后进行PIC的初始化MOV      AL,0xffOUT      0x21,ALNOP                      ; 如果连续OUT命令的话,可能会有不太好的机型OUT      0xa1,ALCLI                      ; 甚至禁止CPU层面插队; cpu从1 mb以上的内存,a20gate设定CALL  waitkbdoutMOV       AL,0xd1OUT      0x64,ALCALL waitkbdoutMOV       AL,0xdf         ; enable A20OUT     0x60,ALCALL waitkbdout; 保护模式过渡[INSTRSET "i486p"]              ; 用于记述想要使用的486命令LGDT    [GDTR0]         ; 暂定GDT设定MOV        EAX,CR0AND      EAX,0x7fffffff  ; 使bit31为0(为子禁止寻乎)OR      EAX,0x00000001  ; 使bit0为1(为子保护模式转移)MOV        CR0,EAXJMP      pipelineflush
pipelineflush:MOV       AX,1*8          ; 可读区段32bitMOV      DS,AXMOV        ES,AXMOV        FS,AXMOV        GS,AXMOV        SS,AX; bootpack的传送MOV       ESI,bootpack    ; 传输源MOV        EDI,BOTPAK      ; 传输目的地MOV      ECX,512*1024/4CALL  memcpy; 顺便磁盘数据也向原来的位置传送; 首先从引导扇区MOV     ESI,0x7c00      ; 传输源MOV        EDI,DSKCAC      ; 传输目的地MOV      ECX,512/4CALL   memcpy; 剩下的全部MOV        ESI,DSKCAC0+512    ; 传输源MOV        EDI,DSKCAC+512 ; 传输目的地MOV      ECX,0MOV        CL,BYTE [CYLS]IMUL  ECX,512*18*2/4  ; 从柱面数转换成字节数 /4SUB      ECX,512/4       ; 通过IPL减去CALL   memcpy; 我们已经完成了需要使用asmhead 进行的所有操作
; 放到bootpack中; 启动bootpackMOV        EBX,BOTPAKMOV       ECX,[EBX+16]ADD        ECX,3           ; ECX += 3;SHR        ECX,2           ; ECX /= 4;JZ      skip            ; 无需转移MOV       ESI,[EBX+20]   ; 传输源ADD        ESI,EBXMOV      EDI,[EBX+12]   ; 传输目的地CALL memcpy
skip:MOV        ESP,[EBX+12]   ; 堆栈初始值JMP      DWORD 2*8:0x0000001bwaitkbdout:IN        AL,0x64AND      AL,0x02JNZ     waitkbdout      ; 如果AND的结果不为0,请跳转至waitkbdouRETmemcpy:MOV     EAX,[ESI]ADD        ESI,4MOV        [EDI],EAXADD        EDI,4SUB        ECX,1JNZ        memcpy          ; 如果减法不为0,则返回memcpyRET
; memcpy也可以用字符串指令编写,除非你忘记了地址大小写前缀ALIGNB  16
GDT0:RESB   8               ; 空选择器DW        0xffff,0x0000,0x9200,0x00cf ; 读/定段32bitDW       0xffff,0x0000,0x9a28,0x0047 ; 可执行段32bit(用于bootpack)DW       0
GDTR0:DW        8*3-1DD     GDT0ALIGNB  16
bootpack:
  1. 打开 VC code 创建 ipl10.nas 文件,输入以下代码,也存放的harib07d中。
; haribote-ipl
; TAB=4CYLS    EQU     10              ; 要读取到什么程度ORG       0x7c00          ; 启动装载程序; 以下记述用于标准FAT12格式软盘JMP      entryDB     0x90DB      "HARIBOTE"        ; 磁盘名称(可以是任意字符串)DW        512             ; 每个扇区的大小(必须是512)DB       1               ; 簇的大小(必须为一个扇区)DW     1               ; FAT12的起始位置(一般从第一个扇区开始DB        2               ; FAT的个数(必须为2)DW      224             ; 根目录的大小(一般设成224项)DW      2880            ; 该磁盘的大小(必须是2880扇区)DB     0xf0            ; 该磁盘的种类(必须是0xf0DW       9               ; FAt的长度(必须是9扇区)DW        18              ; 一个磁道有几个扇区(必须是18)DW      2               ; 磁头数(必须是2)DD     0               ; 不使用分区,必须是0DD       2880            ; 磁盘大小DB        0,0,0x29        ; 意义不明固定DD      0xffffffff      ; (可能是)卷标号码DB     "HARIBOTEOS " ; 磁盘的名称(11字节)DB       "FAT12   "        ; 磁盘格式名称(8字节)RESB 18              ; 先空出18字节; 程序主体entry:MOV        AX,0            ; 初始化寄存器MOV     SS,AXMOV        SP,0x7c00MOV        DS,AX; 读磁盘MOV       AX,0x0820MOV        ES,AXMOV        CH,0            ; 柱面 0MOV       DH,0            ; 磁头 0MOV       CL,2            ; 扇区 2
readloop:MOV        SI,0            ; 记录失败次数的寄存器
retry:MOV       AH,0x02         ; AH=0x02 : 读入磁盘MOV        AL,1            ; 1 个扇区MOV      BX,0MOV     DL,0x00         ; A 驱动器INT      0x13            ; 调用磁盘BIOSJNC       next            ; 没出错时跳转到nextADD        SI,1            ; SI 加 1CMP     SI,5            ; 比较 SI 与 5JAE      error           ; SI >= 5 时,跳转到errorMOV      AH,0x00MOV      DL,0x00         ; A 驱动器INT      0x13            ; 重置驱动器JMP      retry
next:MOV        AX,ES           ; 把内存地址后移0x200ADD       AX,0x0020MOV        ES,AX           ; 因为没有 ADD ES,0x020 指令,所以这里稍微绕个弯ADD      CL,1            ; CL 加 1CMP     CL,18           ; 比较 CL 与 18JBE     readloop        ; 如果 CL <= 18,则跳转至readloop MOV       CL,1ADD     DH,1CMP     DH,2JB      readloop        ; 如果 DH < 2, 则跳转到readloopMOV      DH,0ADD     CH,1CMP     CH,CYLSJB       readloop        ; 如果 CH < CYLS,则跳转至readloop; 因为看完了实行haribote.sysMOV       [0x0ff0],CH     ; IPL读到什么地方结束JMP        0xc200error:MOV     SI,msg
putloop:MOV     AL,[SI]ADD      SI,1            ; SI 加 1CMP     AL,0JE      finMOV      AH,0x0e         ; 显示一个文字MOV     BX,15           ; 指定字符颜色INT     0x10            ; 调用显卡BIOSJMP       putloop
fin:HLT                     ; 让CPu停止,等待指令JMP     fin             ; 无限循环
msg:DB      0x0a, 0x0a      ; 换行两次DB        "load error"DB        0x0a            ; 换行DB      0RESB   0x7dfe-$        ; 重复0x00一直到0x7dfeDB     0x55, 0xaa
  1. 打开记事本,输入以下代码,另存为 make.bat, 同样放到harib07d中。
..\z_tools\make.exe %1 %2 %3 %4 %5 %6 %7 %8 %9
  1. 创建 Makefile,并输入以下代码并存放到harib07d中。
OBJS_BOOTPACK = bootpack.obj naskfunc.obj hankaku.obj graphic.obj dsctbl.obj \int.obj fifo.obj keyboard.obj mouse.obj memory.objTOOLPATH = ../z_tools/
INCPATH  = ../z_tools/haribote/MAKE     = $(TOOLPATH)make.exe -r
NASK     = $(TOOLPATH)nask.exe
CC1      = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet
GAS2NASK = $(TOOLPATH)gas2nask.exe -a
OBJ2BIM  = $(TOOLPATH)obj2bim.exe
MAKEFONT = $(TOOLPATH)makefont.exe
BIN2OBJ  = $(TOOLPATH)bin2obj.exe
BIM2HRB  = $(TOOLPATH)bim2hrb.exe
RULEFILE = $(TOOLPATH)haribote/haribote.rul
EDIMG    = $(TOOLPATH)edimg.exe
IMGTOL   = $(TOOLPATH)imgtol.com
COPY     = copy
DEL      = del# 默认default :$(MAKE) img# 文件生成规则ipl10.bin : ipl10.nas Makefile$(NASK) ipl10.nas ipl10.bin ipl10.lstasmhead.bin : asmhead.nas Makefile$(NASK) asmhead.nas asmhead.bin asmhead.lsthankaku.bin : hankaku.txt Makefile$(MAKEFONT) hankaku.txt hankaku.binhankaku.obj : hankaku.bin Makefile$(BIN2OBJ) hankaku.bin hankaku.obj _hankakubootpack.bim : $(OBJS_BOOTPACK) Makefile$(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \$(OBJS_BOOTPACK)
# 3MB+64KB=3136KBbootpack.hrb : bootpack.bim Makefile$(BIM2HRB) bootpack.bim bootpack.hrb 0haribote.sys : asmhead.bin bootpack.hrb Makefilecopy /B asmhead.bin+bootpack.hrb haribote.sysharibote.img : ipl10.bin haribote.sys Makefile$(EDIMG)   imgin:../z_tools/fdimg0at.tek \wbinimg src:ipl10.bin len:512 from:0 to:0 \copy from:haribote.sys to:@: \imgout:haribote.img# 一般规则%.gas : %.c bootpack.h Makefile$(CC1) -o $*.gas $*.c%.nas : %.gas Makefile$(GAS2NASK) $*.gas $*.nas%.obj : %.nas Makefile$(NASK) $*.nas $*.obj $*.lst# 命令img :$(MAKE) haribote.imgrun :$(MAKE) img$(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin$(MAKE) -C ../z_tools/qemuinstall :$(MAKE) img$(IMGTOL) w a: haribote.imgclean :-$(DEL) *.bin-$(DEL) *.lst-$(DEL) *.obj-$(DEL) bootpack.map-$(DEL) bootpack.bim-$(DEL) bootpack.hrb-$(DEL) haribote.syssrc_only :$(MAKE) clean-$(DEL) haribote.img
  1. 打开记事本,复制以下内容并保存为 hankaku.txt,且存放在harib07d中;ps:建议这一段代码直接复制不要看
这段代码过多,无法贴出来,请在网盘资源复制,projects/05_day/harib02f中hankaku.txt
编译及运行
  1. 双击 !cons_nt.bat,并在打开的命令行中输入 make run
  2. VMware中运行结果,如下图

    ps: 结果就是这样,因为本次实验的目的是提高叠加处理速度(2) (harib07d),可以试着移动鼠标看看,到鼠标画面移动了,以后会有更精彩。敬请期待!
    好的今天到这里harib07d就张结束了,请大家多多支持!!!

30天自制操作系统第10天harib07d相关推荐

  1. 索骥馆-DIY操作系统之《30天自制操作系统》扫描版[PDF]

    内容简介: <30天自制操作系统>是一本兼具趣味性.实用性与学习性的操作系统图书.作者从计算机的构造.汇编语言.C语言开始解说,让读者在实践中掌握算法.在这本书的指导下,从零编写所有代码, ...

  2. 为什么《30天自制操作系统》封面中的猫是两只尾巴

    刚刚在一社区,发了一贴,被指出一问题,询一高人,得一答案.这便是我没有关注到的封面上的那只猫,我想这也是很多读者没有关注到的.因为在我微博的200转发贴中,并没有人提到封面中的猫为何有两只尾巴.于是咨 ...

  3. 《30天自制操作系统》笔记(01)——hello bitzhuwei’s OS!

    <30天自制操作系统>笔记(01)--hello bitzhuwei's OS! 最初的OS代码 1 ; hello-os 2 ; TAB=4 3 4 ORG 0x7c00 ; 指明程序的 ...

  4. 《30天自制操作系统》笔记(04)——显示器256色

    <30天自制操作系统>笔记(04)--显示器256色 进度回顾 从最开始的(01)篇到上一篇为止,已经解决了开发环境问题和OS项目的顶层设计问题. 本篇做一个小练习:设置显卡显示256色. ...

  5. 30天自制操作系统——第五天

    第五天 参考<30天自制操作系统>GDT&IDT - 谷月轩 - 博客 梳理一下文件 现在我们拥有这么9个文件: ipl10.nas InitialProgramLoader, 占 ...

  6. 30天自制操作系统第三天

    操作系统实验日志3 学号 201708010402 姓名 徐冰娜 专业年级班级 实验日期 2019.9.28 实验项目 第3天:进入32位模式并导入C语言 智能1701 30天自制操作系统第三天 操作 ...

  7. 【操作系统】30天自制操作系统--(14)多任务1

    本章开始多任务的设计. 一 多任务的说明 多任务(multitask),指的是操作系统中,多个应用程序同时运行的状态.然而,对于单核CPU来说,同一个瞬间只能处理一个事情,不能做到左右互搏.一心二用的 ...

  8. 【操作系统】30天自制操作系统--(18)应用程序

    本章主要介绍了文件处理的相关操作以及尝试制作第一个应用程序hlt. 一 type命令 与Linux里面的type命令不同,Windows命令行中的type命令是用来查看文件内容的.在自制的操作系统中, ...

  9. 《30天自制操作系统》-day3(MAC)

    第3天 进入32位模式并导入C语言 基本配置 汇编语言内容 文件 hanbote.nas ipl.nas Makefile 原因 用法 基本配置 设备:Macbookpro(13-inch,2018) ...

  10. 30天自制操作系统——第1天 从计算机结构到汇编程序入门

    落灰一学期的<30天自制操作系统>,希望能够利用大二最后这几个月完成操作系统的制作,以下是我阅读本书所记录的笔记以及学习过程,愿顺利完成. 1.先动手操作 (1)安装"二进制编辑 ...

最新文章

  1. 我被裁员了!让保安把身患绝症的我被强赶出公司,亲身经历的噩梦!
  2. python http服务器_超简单的Python HTTP服务
  3. 限制php输出图像的固定,限制要显示的图像数php
  4. ubuntu声卡相关
  5. livebos--iframe使用
  6. 五、python模块以及包
  7. 基于OpenCL的mean filter性能
  8. MySQL not in查询不出数据(MySQL not in 无效)
  9. django-模板语言-传输各种数据类型
  10. leetcode python3 简单题232. Implement Queue using Stacks
  11. LeetCode 394: DecodeString (Java)
  12. VueRouter基础知识记录1
  13. 静态嵌套类和非静态嵌套类
  14. SPI 机制-插件化扩展功能
  15. Unity写lua代码的vs插件:BabeLua
  16. 微信核酸检测预约小程序系统毕业设计毕设(6)开题答辩PPT
  17. KMPlayer播放mkv视频不出声音的解决办法
  18. 华为机试真题 Java实现【最短木板长度】【100%通过率】【2022.11 Q4 新题】
  19. Go Cloud项目开源发布:Go语言将成为云端应用开发的首选语言?
  20. ESD静电二极管端口信号防护应用产品型号——SM712

热门文章

  1. AIMA 第三版 笔记
  2. Spark集群环境搭建+Maven、SBT编译部署+IDEA开发(二)
  3. 做一个视频通话给自己用吧
  4. Linux定时任务的基础操作
  5. oplayer 文件服务器,iPad万能播放器(OPlayer HD)
  6. 本地数据下,radiobutton和图片组合,利用adapter+listview进行单选
  7. 游戏服务器的常用架构
  8. Codeforces Round #469 (Div. 1 A-E)
  9. Flask蓝本(Blueprint)
  10. 网易 产品策划( 杭州研究员) 笔试题解