5、结构体、文字显示与GDT/IDT初始化
来源:互联网 发布:物性数据库 编辑:程序博客网 时间:2024/05/07 10:15
接收启动信息
bootpack.c节选
void HariMain(void) //程序从此处开始运行,函数名不能改{ char *vram; //BYTE类型地址 int xsize, ysize; short *binfo_scrnx, *binfo_scrny; //WORD类型地址 int *binfo_vram; //DWORD类型地址 init_palette(); //设置调色板 binfo_scrnx = (short *) 0x0ff4; //0x0ff4是为了与asmhead.nas保持一致出现的 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(); }}
试用结构体
bootpack.c节选
struct BOOTINFO { char cyls, leds, vmode, reserve; short scrnx, scrny; char *vram;};void HariMain(void){ char *vram; int xsize, ysize; struct BOOTINFO *binfo; init_palette(); binfo = (struct BOOTINFO *) 0x0ff0; xsize = (*binfo).scrnx; ysize = (*binfo).scrny; vram = (*binfo).vram; init_screen(vram, xsize, ysize); for (;;) { io_hlt(); }}
试用箭头记号
bootpack.c节选
void HariMain(void) //程序从此处开始运行,函数名不能改{ struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0; init_palette(); init_screen(binfo->vram, binfo->scrnx, binfo->scrny); //显示背景 for (;;) { io_hlt(); }}
显示字符
bootpack.c节选
void HariMain(void) //程序从此处开始运行,函数名不能改{ struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0; static char font_A[16] = //存储字符A { 0x00, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00 }; init_palette(); init_screen(binfo->vram, binfo->scrnx, binfo->scrny); //显示背景 putfont8(binfo->vram, binfo->scrnx, 10, 10, COL8_FFFFFF, font_A); //输出字符A for (;;) { io_hlt(); }}//x,y表示起始像素点位置void putfont8(char *vram, int xsize, int x, int y, char c, char *font){ int i; char *p, d; for (i = 0; i < 16; i++) //字符的存储:每行8位,共16行,所以一个字符用16个字节 { 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;}
make run
增加字体
沿用OSASK的字体数据
hankaku.txt中的节选
char 0x41...........**......**......**......**.....*..*....*..*....*..*....*..*...******..*....*..*....*..*....*.***..***................char 0x42........****.....*..*....*...*...*...*...*...*...*..*....****....*...*...*....*..*....*..*....*..*...*..*****...
Makefile中的变动
MAKEFONT = $(TOOLPATH)makefont.exeBIN2OBJ = $(TOOLPATH)bin2obj.exe#使用makefont.exe编译hankaku.txt字库hankaku.bin : hankaku.txt Makefile $(MAKEFONT) hankaku.txt hankaku.bin#然后连接所必须的接口信息,生成目标文件hankaku.obj,这样就可以与bootpack.obj连接了hankaku.obj : hankaku.bin Makefile $(BIN2OBJ) hankaku.bin hankaku.obj _hankaku#使用obj2bim.exe将bootpack.obj生成二进制映像文件bootpack.bim,#这一步是因为C语言不能编写所有的程序,有一部分用汇编来写,然后链接到C语言程序上 bootpack.bim : bootpack.obj naskfunc.obj hankaku.obj Makefile $(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \ bootpack.obj naskfunc.obj hankaku.obj# 3MB+64KB=3136KB
bootpack.c节选
void HariMain(void) //程序从此处开始运行,函数名不能改{ struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0; extern char hankaku[4096]; //在源程序以外准备的数据,都需要加上extern init_palette(); //设置调色板 init_screen(binfo->vram, binfo->scrnx, binfo->scrny); //设置背景 //显示字符 putfont8(binfo->vram, binfo->scrnx, 8, 8, COL8_FFFFFF, hankaku + 'A' * 16); putfont8(binfo->vram, binfo->scrnx, 16, 8, COL8_FFFFFF, hankaku + 'B' * 16); putfont8(binfo->vram, binfo->scrnx, 24, 8, COL8_FFFFFF, hankaku + 'C' * 16); putfont8(binfo->vram, binfo->scrnx, 40, 8, COL8_FFFFFF, hankaku + '1' * 16); putfont8(binfo->vram, binfo->scrnx, 48, 8, COL8_FFFFFF, hankaku + '2' * 16); putfont8(binfo->vram, binfo->scrnx, 56, 8, COL8_FFFFFF, hankaku + '3' * 16); for (;;) { io_hlt(); }}
make run
显示字符串
bootpack.c节选
void HariMain(void) //程序从此处开始运行,函数名不能改{ struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0; extern char hankaku[4096]; //在源程序以外准备的数据,都需要加上extern init_palette(); //设置调色板 init_screen(binfo->vram, binfo->scrnx, binfo->scrny); //设置背景 //显示字符串 putfonts8_asc(binfo->vram, binfo->scrnx, 8, 8, COL8_FFFFFF, "ABC 123"); putfonts8_asc(binfo->vram, binfo->scrnx, 31, 31, COL8_000000, "Haribote OS."); putfonts8_asc(binfo->vram, binfo->scrnx, 30, 30, COL8_FFFFFF, "Haribote OS."); for (;;) { io_hlt(); }}void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s){ extern char hankaku[4096]; for (; *s != 0x00; s++) //字符串都是以0x00结尾的 { putfont8(vram, xsize, x, y, c, hankaku + *s * 16); x += 8; } return;}
make run
显示变量值
bootpack.c中的变动
#include <stdio.h>void HariMain(void) //程序从此处开始运行,函数名不能改{ struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0; extern char hankaku[4096]; //在源程序以外准备的数据,都需要加上extern char s[40]; init_palette(); //设置调色板 init_screen(binfo->vram, binfo->scrnx, binfo->scrny); //设置背景 //显示字符串 putfonts8_asc(binfo->vram, binfo->scrnx, 8, 8, COL8_FFFFFF, "ABC 123"); putfonts8_asc(binfo->vram, binfo->scrnx, 31, 31, COL8_000000, "Haribote OS."); putfonts8_asc(binfo->vram, binfo->scrnx, 30, 30, COL8_FFFFFF, "Haribote OS."); //sprintf不是按指定格式输出,只是将输出内容作为字符串写在内存中,可应用于所有操作系统 sprintf(s, "scrnx = %d", binfo->scrnx); putfonts8_asc(binfo->vram, binfo->scrnx, 16, 64, COL8_FFFFFF, s); for (;;) { io_hlt(); }}void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s){ extern char hankaku[4096]; for (; *s != 0x00; s++) //字符串都是以0x00结尾的 { putfont8(vram, xsize, x, y, c, hankaku + *s * 16); x += 8; } return;}
make run
显示鼠标指针
与显示字符的思想类似。
bootpack.c变动
void HariMain(void) //程序从此处开始运行,函数名不能改{ struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0; char s[40], mcursor[256]; int mx, my; init_palette(); //设置调色板 init_screen(binfo->vram, binfo->scrnx, binfo->scrny); //设置背景 //显示鼠标 mx = (binfo->scrnx - 16) / 2; 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); putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, s); for (;;) { io_hlt(); }}//制作要显示的字符void init_mouse_cursor8(char *mouse, char bc){ 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;}//进行显示,只需将buf中的数据复制到vram中//vxsize与vysize与vram有关,vysize=0xa0000, vxsize=320//pxsize与pysize是想要显示图像的大小,因为鼠标指针大小为16*16,所以两个值都为16//buf指定图形存放地址,bxsize指定每一行含有的像素值,与pxsize大体相同//px0与py0为要显示字符的起始像素点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;}
make run
GDT与IDT的初始化
两者都是与CPU有关的设定
GDT global (segment) descriptor table,全局段号记录表
IDT interrupt descriptor table,中断记录表
asmhead.nas需要增加设定,因为之前只是为运行bootpack.c做了一些设定,这一步跳过。
bootpack.c节选
struct BOOTINFO //12字节{ char cyls, leds, vmode, reserve; short scrnx, scrny; char *vram;};struct SEGMENT_DESCRIPTOR { //8字节 short limit_low, base_low; char base_mid, access_right; char limit_high, base_high;};struct GATE_DESCRIPTOR { //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 init_gdtidt(void){ //0x270000到0x27ffff设为GDT,因为这一块内存没有特殊用途 struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) 0x00270000; //0x26f800到0x26ffff设为IDT struct GATE_DESCRIPTOR *idt = (struct GATE_DESCRIPTOR *) 0x0026f800; int i; /* GDT的初始化*/ for (i = 0; i < 8192; i++) { //完成对8192个段的设定 set_segmdesc(gdt + i, 0, 0, 0); //将每个段的上限、基址、访问权限都设为0 } //将1号段上限设为4G,地址为0,表示CPU所能管理的全部内存本身 set_segmdesc(gdt + 1, 0xffffffff, 0x00000000, 0x4092); //将2号段上限设为512KB,地址为0x280000,正好是bootpack.hrb可以执行的地方 set_segmdesc(gdt + 2, 0x0007ffff, 0x00280000, 0x409a); load_gdtr(0xffff, 0x00270000); //因为C语言不能给GDTR赋值,所以写成汇编 /* IDT的初始化 */ for (i = 0; i < 256; i++) { set_gatedesc(idt + i, 0, 0, 0); } 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;}
段的地址在CPU中被称为基址,所以用了base这样的变量名,为了兼容,它分为low(2字节),mid(1字节),high(1字节),然后按顺序填入相应的数值。
段的上限只能使用20位,在段属性中一个标志位Gbit,为1的时候limit的单位不解释成字节(byte),而解释成页(page),1页是4KB。20位段的上限分别写入limit_high和limit_low中,再将段属性写入limit_high高4位中。
对于12位段的访问权属性ar(access_right),高四位放在limit_high高4位中。
0x00:未使用的记录表
0x92:系统专用,可读写的段,不可执行。
0x9a:系统专用,可执行的段,可读不可写。
0xf2 :应用程序用,可读写的段,不可执行。
0xfa : 应用程序,可执行的段,可读不可写。
naskfunc.nas中添加
GLOBAL _load_gdtr, _load_idtr_load_gdtr: ; void load_gdtr(int limit, int addr); MOV AX,[ESP+4] ; limit MOV [ESP+6],AX LGDT [ESP+6] RET _load_idtr: ;void load_idtr(intlimit,int addr); MOV AX,[ESP+4] ; limit MOV [ESP+6],AX LIDT [ESP+6] RET
load_getr用来指定段的上限和地址值赋值给名为GDTR的48位寄存器。LGDT指令用来从指定位置读取6个字节,然后赋值给GDTR寄存器。DOWRD[ESP+4]中存放段的上限,如0x0000ffff,DWORD[ESP+8]中存放地址,如0x002700,按字节写出为ffff00000002700(靠右边为低位),为了执行LGDT,希望成为ffff00002700形式。
make run后没有什么变化
- 5、结构体、文字显示与GDT/IDT初始化
- 五、结构体、文字显示与GDT/IDT初始化
- 结构体,文字显示与GDT/IDT初始化
- 第5天 结构体、文字显示与GDT/IDT初始化
- [读书笔记]30 天自制操作系统 day5 结构体, 文字显示与GDT/IDT初始化
- 05day 文字显示 GDT/IDT初始化
- GDT和IDT的初始化
- GDT和IDT的初始化
- GDT/IDT
- 1个人开发操作系统之GDT和IDT的初始化
- LInux 描述符GDT, IDT & LDT结构定义
- 遍历IDT表和分析GDT表结构
- About GDT LDT IDT
- About GDT LDT IDT
- IDT GDT LDT
- 段、GDT/IDT 相关知识点
- gdt初始化
- IDT 结构
- 第七届河南省赛 zzuoj 10400: B.海岛争霸 (并查集&最短路(djs))
- How to install/remove different Desktop/Window Manager in Kali Linux
- C语言指针-----指针与数组
- 在spring中配置mongodb的用户名和密码
- 第七届河南省赛 zzuoj 10399: F.Turing equation (模拟)
- 5、结构体、文字显示与GDT/IDT初始化
- JAVA学习笔记(一)——开始
- Android的AnalogClock和DigitalClock
- 内嵌汇编 %0,%1 是什么
- 联想高管:虚拟运营商用户数已达1100万
- UITextField使用总结
- 第七届河南省赛 zzuoj 10396: H.Rectangles (LIS)
- The Definitive Guide to Getting Your Linux Desktop Back
- sql注入xss攻击常见形式和解决方法