void是什么意思c语言中,void是什么软件

  

  ,张永强是张永强吗,是吴亚玲吴亚玲启动包足球俱乐部绿筠小姐。   

  

  苏慕容留页:1   

  

  朱塞佩朱塞佩页:1   

  

  魏冄,苏鲁克启动包足球俱乐部范登韦恩佐范登韦恩佐,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,吴亚玲,黄公子。   

  

  我的天啊,黄公子?黄公子,贺盛瑞?贺盛瑞:   

  

  333010-6950   

  

  贺盛瑞贺盛瑞贺盛瑞:https://gitee。com/敏明拉石/make计算机操作系统30天内/blob/master/projects/04 _ day/harib 01h   

  

  我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是:   

  

  S7-1200可编程控制器:请参见io_cli .S7-1200可编程控制器:S7-1200可编程控制器:S7-1200可编程控制器:请参阅初始化调色板.请参阅set_palette(int start、int end、无符号char *rgb):参见方框填充8(未签名的char *vram、int xsize、未签名的char c、int x0、int y0、int x1、int y 1);#用8 _ 0080定义#用8 _ ff 00001定义#用8 _ 00 ff 002定义#用8 _ 0000 ff 003定义#用8 _ ff 00 ff定义5 #用8 _ 00 ffff定义6 #用8定义_ C6 C6 c68 #用8 _ 8400009定义#用8 _ 00840010定义#用8 _ 848484811定义#用8 _ 000848444444定义xsize=320 ysize=200 box fill 8(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,col 8 _ ffffff,0,ysize - 27,xsize - 1,ysize-27);boxfill8(vram,xsize,COL8_C6C6C6,0,ysize - 26,xsize - 1,ysize-1);boxfill8(vram、xsize、col 8 _ ffffff、3、ysize - 24、59、ysize-24);boxfill8(vram、xsize、col 8 _ ffffff、2、ysize - 24、2、ysize-4);boxfill8(vram,xsize,col 8 _ 848484,3,ysize - 4,59,ysize-4);boxfill8(vram,xsize,col 8 _ 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_8484,xsize - 47,ysize - 24,xsize - 4,ysize-24);boxfill8(vram,xsize,COL8_8484,xsize - 47,ysize - 23,xsize - 47,ysize-4);boxfill8(vram、xsize、col 8 _ ffffff、xsi   

ze - 47, ysize - 3, xsize - 4, ysize - 3);boxfill8(vram, xsize, COL8_FFFFFF, xsize - 3, ysize - 24, xsize - 3, ysize - 3);for (;;) {io_hlt();}}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, 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);return;/* 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 = c;}return;}可以看到,28行的HariMain函数内,基本上一堆的boxfill8函数,

  

也就是说,就是这些boxfill8函数构成了最终的窗口画面。

  

因为今天的目标就是写这样一个画面出来,所以,只要详细解析boxfill8函数,今天的任务就完成了。

  

那么boxfill8函数实现了怎样的功能?它是如何控制显示屏来显示出了一个窗口的?

  

控制显示屏

  

实际上,在昨天的代码中,我们已经对显示屏做了设置:

  


  

  

这里设置了显示屏按照像素的方式来显示画面,画面的大小为320x200,

  

特别注意最后一行:MOV DWORD ,0x000a0000;,设置缓冲区的地址为0x000a0000,这意味着,将内存的0x000a 0000出写的值,就是显示屏上每个像素的值。

  

那我们在c语言中实现这样一个函数就可以了,如下bootpack.c代码:

  

void io_hlt(void);void write_mem8(int addr, int data);void HariMain(void){int i; for (i = 0xa0000; i <= 0xaffff; i++) {write_mem8(i, 15); /* MOV BYTE ,15 */}for (;;) {io_hlt();}}在第8行,我们将15这个值放在了0xa0000到0xaffff地址里,用的是write_mem8函数实现的。write_mem8函数在第2行有声明,注意到它和io_hlt一样,而io_htl是汇编语言写的,所以,write_mem8函数也是汇编语言写的,在naskfunc.nas里,它的实现是这样的:

  

; naskfunc; TAB=4; 文件格式设定; 486模式; 32模式;GLOBAL_io_hlt,_write_mem8 ; 声明函数

_io_hlt:; void io_hlt(void);HLTRET_write_mem8:; void write_mem8(int addr, int data);MOVECX,; 就是int addr, MOVAL,; 就是int dataMOV,AL ; 把data 放在addr处RET也就是说:write_mem8函数将 data存放到地址addr出。

  

那么在HariMain函数中,就实现了把15放到了内存地址0xa0000至0xaffff处。

  

这就实现了改变显示屏内容的作用,把原来的黑屏,变成了白屏,如下:

  

  

既然画成白屏了,不如再画个其他的,比如条纹,代码如下:

  

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();}}只有第10行有改动: write_mem8(i, 15)改为 write_mem8(I,i&0x0f);

  

I&0x0f是只取i的最小的四位,由于i本身是从0xa0000增加到0xaffff的,所以,i*0x0f会是一个周期变化的值,不断的从0变化到f=15,然后又从0变化到f=15。

  

我们设置为15的时候,画面是白色的,现在是0--15之间变化,那么画面会发生怎样的变化呢?

  

以上程序运行结果如下:

  

  

可以看到,这里是一个黑白相间的条纹。

  

不过这个还是黑白的,那么能否显示彩色呢?

  

我们知道显示屏一般都是彩色的,肯定是可以显示彩色的,那要如何设定呢?

  

这涉及到一个概念,调色板。

  

调色板是啥?

  

其实我们现在的程序:15对应白色,0对应黑色,就是一个调色板。这种数字和颜色的对应关系,就是调色板。

  

所以我们只要改变一下数字和颜色的对应关系就行了。在这个代码中实现:

  

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 HariMain(void){int i;char *p;init_palette();p = (char *) 0xa0000; # 显示器缓冲区地址for (i = 0; i <= 0xffff; i++) {p = i & 0x0f;}for (;;) {io_hlt();}}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, 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);return;}void set_palette(int start, int end, unsigned char *rgb){int i, eflags;eflags = io_load_eflags();/* 记录运行到此代码处时的中断标志到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);/* 用 eflags恢复中断标志 */return;}set_palette(start=0,end=15,table_rgb=颜色表)

  

这个函数中的start,end就是往数据缓冲区中写的数字的范围。

  

我们给0,1,2,3,,,,15,每个数字对应一种颜色,一共16种颜色,写在table_rgb中。通过往端口0x03c9写入颜色的红色分量,绿色分量,蓝色分量就可以完成调色板palette的设置,把这些颜色和0,15对应起来。

  

代码中io_out8是往指定端口写入8位数字。

  

这里设定显示屏的调色板,要先把start写到0x03c8,然后把具体的颜色写到0x03c9就行了,这都是VGA显示器规定的标准设定方法。

  

运行一下就可以看到彩色了,如下:

  

  

那么以上并不是全部的代码,因为没有给出io_out8的源码,io_store_eflag的源码,下面给出,其实都在nasmfucn里:

  

; naskfunc; TAB=4GLOBAL_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_eflags

_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;端口port的值写入AL,AL是8位寄存器_io_in8:; int io_in8(int port);MOVEDX,; portMOVEAX,0INAL,DXRET;端口port的值写入AX,AX是8位寄存器_io_in16:; int io_in16(int port);MOVEDX,; portMOVEAX,0INAX,DXRET;端口port的值写入EAX,EAX是32位寄存器_io_in32:; int io_in32(int port);MOVEDX,; portINEAX,DXRET;把8位的data写到端口port_io_out8:; void io_out8(int port, int data);MOVEDX,; portMOVAL,; dataOUTDX,ALRET;把16位的data写到端口port_io_out16:; void io_out16(int port, int data);MOVEDX,; portMOVEAX,; dataOUTDX,AXRET;把32位的data写到端口port_io_out32:; void io_out32(int port, int data);MOVEDX,; portMOVEAX,; dataOUTDX,EAXRET;把标志寄存器的值放到栈里_io_load_eflags:; int io_load_eflags(void);PUSHFD; PUSH EFLAGSPOPEAXRET;把 eflags放到栈里,然后再放到标志寄存器里_io_store_eflags:; void io_store_eflags(int eflags);MOVEAX,PUSHEAXPOPFD; POP EFLAGS RET因为设定调色板,需要用到一些汇编代码,所有就又在nasmfunc中加入了一些相关的函数。

  

绘制矩形

  

既然可以改变颜色了,说明我们基本上可以比较自由的操作显示屏显示各种颜色了。

  

那么能否绘制本文开头的窗口呢?

  

能,不过要先回值一个长方形。

  

如何绘制呢?

  

缓冲区从0xa0000开始,一共320x200=64000个值。

  

如果要绘制举行,单独设置矩形内的像素为特定颜色就行了。

  

设定一个坐标系,以窗口的左上角为原点,水平向左为x轴正方向,垂直向下为y轴正方向,那么矩阵的左上角点坐标为(x0,y0),右下角点坐标为(x1,y1),

  

我们只用对横坐标介于,纵坐标介于的像素设定为特定的值就行了。

  

函数boxfill8就是对以上思路的实现:

  

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 = c;}return;}

  

vram就是缓冲区的首地址,

  

xsize是显示屏每行的像素数,

  

c是像素的值

  

x0,y0是所要绘制的左上角点的坐标

  

x1,y1是所要绘制的右下角点的坐标

  

这个函数就可以绘制一个颜色为c的,左上角在x0,y0,右下角在x1,y1的长方体。

  

那么我们使用这个函数来绘制几个长方体来看看,代码如下:

  

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);#define COL8_0000000#define COL8_FF00001#define COL8_00FF002#define COL8_FFFF003#define COL8_0000FF4#define COL8_FF00FF5#define COL8_00FFFF6#define COL8_FFFFFF7#define COL8_C6C6C68#define COL8_8400009#define COL8_00840010#define COL8_84840011#define COL8_00008412#define COL8_84008413#define COL8_00848414#define COL8_84848415void HariMain(void){char *p; init_palette(); 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);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 = c;}return;}在36,37,38绘制了3个矩形。运行后,启动操作系统后,显示如下:

  

  

可以看到,显示了3个不同颜色的矩形。

  

用矩形绘制窗口直接上代码:

  

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);#define COL8_0000000#define COL8_FF00001#define COL8_00FF002#define COL8_FFFF003#define COL8_0000FF4#define COL8_FF00FF5#define COL8_00FFFF6#define COL8_FFFFFF7#define COL8_C6C6C68#define COL8_8400009#define COL8_00840010#define COL8_84840011#define COL8_00008412#define COL8_84008413#define COL8_00848414#define COL8_84848415void HariMain(void){char *vram;int xsize, ysize;init_palette();vram = (char *) 0xa0000;xsize = 320;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);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 = c;}return;}运行结果如下:

  

  

到这里,有点操作系统的样子了,但也只是绘制了一个画面而已。

  

后面还要完成对鼠标,键盘的相应代码,对内存的管理,以及编写应用程序等功能。

  

到现在为止,编译完成的映像文件一共1216字节,1.2KB。

  

下次就显示文字,显示鼠标,以及为操作系统的内存管理做一些准备。

  

内存管理是操作系统中,重要的内容。我们后期学习C++时,经常要防止内存泄漏。这里的内存管理就是C++中的内存泄漏的基础知识。

  

总结:今天,第四天,完成了对显示器的显示内容的控制。我们实现了对显示屏上任一像素的颜色的设定。利用了调色板,以及设定调色板时要关闭中断,往相应端口发送颜色表等。

  

第五天,我们就显示文字,显示鼠标,再后面控制鼠标,控制键盘,打印文字,保存文件,实现多任务,实现用C语言在操作系统上编写程序等等。

相关文章