《30天自制操作系统》读书笔记(4) 绘图

暑假果然是滋生懒散的温床. (╯‵□′)╯︵┻━┻

好久不动都忘记之前做到哪里了, 上次好像做到了C语言的引入, 这一节所做的东西都相当轻松, 将会绘制出操作系统的基本界面.

 

  • 绘图的原理

  按照书中所说, 将值写入到显存中就能在屏幕上显示相应的像素, 在asmhead.nas 中有这一段:

 1 CYLS    EQU    0x0ff0    ; 设定启动区    
 2 LEDS    EQU    0x0ff1    
 3 VMODE    EQU    0x0ff2    ; 关于颜色数目的信息,颜色的位数    
 4 SCRNX    EQU    0x0ff4    ; 分辨率 X(Screen X)    
 5 SCRNY    EQU    0x0ff6    ; 分辨率 Y(Screen Y)    
 6 VRAM    EQU    0x0ff8    ; 图像缓冲区的起始地址    
 7 
 8     ORG    0xc200        
 9 
10 
11 
12     MOV    AL,0x13    ; VGA 显卡    
13     MOV    AH,0x00
14     INT    0x10
15     MOV    BYTE [VMODE],8    ; 记录画面模式    
16     MOV    WORD [SCRNX],320
17     MOV    WORD [SCRNY],200
18     MOV    DWORD [VRAM],0x000a0000

 

调用十号中断来指定显卡模式, 后面的几个MOV指令用来储存和显示有关的关键信息(为什么不直接用常量呢?), 在bootpack.c中有

1 struct BOOTINFO { /* 0x0ff0-0x0fff */
2     char cyls; /* 启动区读硬盘读到何处为止 */
3     char leds; /* 启动时LED的状态*/
4     char vmode; /* 显卡模式*/
5     char reserve;
6     short scrnx, scrny; /* 分辨率*/
7     char *vram;
8 };

这里就将结构体指针指向了这些信息, 可以知道VRAM的地址是0xa0000想指定地址写入数据, 当然是用指针, 将VRAM声明为一个数组即可.

作者顺便指出了数组的操作array[index] 仅是一个语法糖, a[i] 等价于*(a + i), 当然也等价于*(i + a), 所以很神奇的, a[i] 和 i[a] 在C语言里是等效的.

 

 

  • 设定调色板

  作者替我们指定了300x200 8位的颜色模式, 如何将 0xffffff 的颜色值映射0~0xfff的空间里? 一一对应显然是不可能的, 事实上8位色彩模式中, 0到0xfff这255中颜色是由我们自己指定的, 譬如说0可以对应红色0xff0000, 这种对应关系显然被储存起来, 这就是调色板(palette),作者给出了16中颜色的对应关系, 其中14号色被我改了, 调色板的数据结构如下(就一个unsigned char数组):

 1     static unsigned char table_rgb[16 * 3] =
 2            {
 3         0x00, 0x00, 0x00,    /*  0:黑色*/
 4         0xff, 0x00, 0x00,    /*  1:亮红*/
 5         0x00, 0xff, 0x00,    /*  2:亮绿*/
 6         0xff, 0xff, 0x00,    /*  3:亮黄*/
 7         0x00, 0x00, 0xff,    /*  4:亮蓝*/
 8         0xff, 0x00, 0xff,    /*  5:亮紫*/
 9         0x00, 0xff, 0xff,    /*  6:浅亮蓝*/
10         0xff, 0xff, 0xff,    /*  7:白色*/
11         0xc6, 0xc6, 0xc6,    /*  8:亮灰*/
12         0x84, 0x00, 0x00,    /*  9:暗红*/
13         0x00, 0x84, 0x00,    /* 10:暗绿*/
14         0x84, 0x84, 0x00,    /* 11:暗黄*/
15         0x00, 0x00, 0x84,    /* 12:暗青*/
16         0x84, 0x00, 0x84,    /* 13:暗紫*/
17         0x5b, 0x9b, 0xd5,    /* 14:浅灰蓝5B,9B,D5*/
18         0x84, 0x84, 0x84    /* 15:暗灰*/
19     };

 

如何让我们设置调色板生效? 作者给出了如下步骤:

  这里的0x03c9 是设备端口号, 屏蔽和恢复中断使用CLI和STI两个指令, 在naskfunc.nas里面封装成了函数io_cli(); 和 io_stl(), CLI(Clear interrupt flag) 将中断标志(interrupt flag)置零, STI(Set interrupt flag)则是将中断标志置一. 设置调色板的时候需要屏蔽中断, 但不知道当前的状态是什么, 所以在CLI之前要保存中断标志的状态. 中断标志保存在32位寄存器EFLAGS上, 由16位的FLAGS扩展而来, 下图应该是FLAGS 的示意图:中断标志位于第9位. 0 位是进位标志, 2是奇偶标志, 4 是辅助进位标志, 6是零标志, 7是符号标志, 8,10额…忘了, 11是溢出标志…使用指令PUSHFD和POPFD储存和恢复整个EFLAGS的状态, 封装为io_load_eflags()函数和io_store_eflags(eflags)函数.

 

对端口的读写要使用IN 指令和 OUT指令, 注意这里的IN是读取而OUT是写入.

结合以上的知识, 设置调色板的函数如下:

 1 void set_palette(int start, int end, unsigned char *rgb)
 2 {
 3     int i, eflags;
 4     eflags = io_load_eflags();    /*记录中断标志的值 */
 5     io_cli();                     /*禁止中断 */
 6     io_out8(0x03c8, start);
 7     for (i = start; i <= end; i++)
 8            {
 9         io_out8(0x03c9, rgb[0] / 4);    
10         io_out8(0x03c9, rgb[1] / 4);
11         io_out8(0x03c9, rgb[2] / 4);
12         rgb += 3;
13     }
14     io_store_eflags(eflags);    /* 恢复中断标志*/
15     return;
16 }

 

有个疑惑便是rgb[0] 为什么要除以四再写入, 如果去掉这一句颜色会变得很灰…有谁知道的还望告知…(/4不就是往左移动两位?)

 

  • 绘制界面

  我们写了一个叫做boxfill8的函数用来绘制矩形, 并用它来构建我们的基本界面:

二维屏幕和一维的地址换算关系如下: addr = 0xa0000 + x + y * 320

void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1);

参数的意思分别是: 显存地址, 换算参数(屏幕宽度), 颜色, 矩形的四个点.

使用以下的代码画出界面:

 1 void init_screen8(char *vram, int x, int y)
 2 {
 3     boxfill8(vram, x, COL8_008484,  0, 0,          x -  1, y - 29);    //绘制桌面填充灰蓝色
 4     boxfill8(vram, x, COL8_C6C6C6,  0, y - 28, x -  1, y - 28);    //第一条阴影
 5     boxfill8(vram, x, COL8_FFFFFF,  0, y - 27, x -  1, y - 27);    //绘制第二条阴影
 6     boxfill8(vram, x, COL8_C6C6C6,  0, y - 26, x -  1, y -  1);    //绘制任务栏主体
 7 
 8     boxfill8(vram, x, COL8_FFFFFF,  3, y - 24, 59, y - 24);        //绘制"开始"按钮 周围六条直线 
 9     boxfill8(vram, x, COL8_FFFFFF,  2, y - 24,  2, y -  4);
10     boxfill8(vram, x, COL8_848484,  3, y -  4, 59, y -  4);
11     boxfill8(vram, x, COL8_848484, 59, y - 23, 59, y -  5);
12     boxfill8(vram, x, COL8_000000,  2, y -  3, 59, y -  3);
13     boxfill8(vram, x, COL8_000000, 60, y - 24, 60, y -  3);
14 
15     boxfill8(vram, x, COL8_848484, x - 47, y - 24, x -  4, y - 24);//绘制状态栏 四条直线 
16     boxfill8(vram, x, COL8_848484, x - 47, y - 23, x - 47, y -  4);
17     boxfill8(vram, x, COL8_FFFFFF, x - 47, y -  3, x -  4, y -  3);
18     boxfill8(vram, x, COL8_FFFFFF, x -  3, y - 24, x -  3, y -  3);
19     return;
20 }

 

得到的界面如下:

屏幕下方左右两个"按钮"放大看:

其实就是在原来的底色上画多了几条直线, 左边的是6条, 右边的是4条.

看情况, 这将会是我们的操作系统的桌面.

 

  • 显示字符

  使用了asmhead.nas 后我们进入了32位模式(似乎是保护模式), 不可以使用int 0x13中断了, 因此要显示字符只能自己画.

作者使用8x16 的矩阵来表示一个字符, 不知道真正的字体文件*.ttf是否用这样的方式储存…

换算成16进制是:

这样的表示方法难以调整, 所以作者使用了一个文本文档来描画字体, 在这个文本文档里面8是:

char 0x38
........
...**...
..*..*..
.*....*.
.*....*.
.*....*.
..*..*..
...**...
..*..*..
.*....*.
.*....*.
.*....*.
..*..*..
...**...
........
........

 

然后伟大的作者又搬出了自己的"编译器", makefont.exe, (╯‵□′)╯︵┻━┻), 神烦的"别人家的编译器", 这也意味这Makefile又要改动了…如何画出字符和字符串呢?

写一个很厉害的putfont8函数:

 1 void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
 2 {
 3     int i;
 4     char *p, d /* data */;
 5     for (i = 0; i < 16; i++) {
 6         p = vram + (y + i) * xsize + x;
 7         d = font[i];
 8         if ((d & 0x80) != 0) { p[0] = c; }
 9         if ((d & 0x40) != 0) { p[1] = c; }
10         if ((d & 0x20) != 0) { p[2] = c; }
11         if ((d & 0x10) != 0) { p[3] = c; }
12         if ((d & 0x08) != 0) { p[4] = c; }
13         if ((d & 0x04) != 0) { p[5] = c; }
14         if ((d & 0x02) != 0) { p[6] = c; }
15         if ((d & 0x01) != 0) { p[7] = c; }
16     }
17     return;
18 }

 

让特地的数和字体数据相与,判断特定位是否为1, 很厉害的做法.

显示字符串的函数:

1 void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s)
2 {
3     extern char hankaku[4096];
4     for (; *s != 0x00; s++) {
5         putfont8(vram, xsize, x, y, c, hankaku + *s * 16);
6         x += 8;
7     }
8     return;
9 }

 

在主函数里调用

1 putfonts8_asc(binfo->vram, binfo->scrnx, 8, 8, COL8_FFFFFF, "ABC 123");
2 putfonts8_asc(binfo->vram, binfo->scrnx, 31, 31, COL8_000000, "OS.");
3 putfonts8_asc(binfo->vram, binfo->scrnx, 30, 30, COL8_FFFFFF, "OS."); 

 

结果如下:

 

  • 显示变量值

为了显示变量值, 作者使用了名为GO的编译器里的sprintf函数,(这货是GO语言的GO吗?), Sprintf函数就是将指定内容格式化输出到字符流中, 然后我们再将这个字符显示出来, 达到显示变量内容的目的.

添加头文件stdio.h, 主函数加入以下语句:

1     int mx = (binfo->scrnx - 16) / 2;        //水平居中
2     int my = (binfo->scrny - 28 - 16) / 2;    //排除任务栏垂直居中
3     sprintf(s, "(%d, %d)", mx, my);
4     putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, s); 

 

效果如下:

 

  • 显示鼠标指针

  鼠标的显示和字符大同小异, 但是这里使用字符来储存而不是二进制, 因为需要填充色, 边缘色和背景色…作者画的鼠标实在难看, 我用的是@BIT_祝威 写好的鼠标, 特此感谢!

 1 /* 16*16 Mouse */
 2     static char cursor[16][16] = {
 3         "*...............",
 4         "**..............",
 5         "*O*.............",
 6         "*OO*............",
 7         "*OOO*...........",
 8         "*OOOO*..........",
 9         "*OOOOO*.........",
10         "*OOOOOO*........",
11         "*OOOOOOO*.......",
12         "*OOOO*****......",
13         "*OO*O*..........",
14         "*O*.*O*.........",
15         "**..*O*.........",
16         "*....*O*........",
17         ".....*O*........",
18         "......*........."
19     };

 

 事前将上面的图案处理成颜色信息cursor[], 再使用putblock8_8函数将鼠标画出来, 效果如下:

 这次就做到这里…按书中的指示将代码分装成几个文件, 下面是当前改动的代码:

 

 这次的大部分代码在graphic.c

  1 #include "bootpack.h"
  2 
  3 void init_palette(void)
  4 {
  5     static unsigned char table_rgb[16 * 3] =
  6            {
  7         0x00, 0x00, 0x00,    /*  0:黑色*/
  8         0xff, 0x00, 0x00,    /*  1:亮红*/
  9         0x00, 0xff, 0x00,    /*  2:亮绿*/
 10         0xff, 0xff, 0x00,    /*  3:亮黄*/
 11         0x00, 0x00, 0xff,    /*  4:亮蓝*/
 12         0xff, 0x00, 0xff,    /*  5:亮紫*/
 13         0x00, 0xff, 0xff,    /*  6:浅亮蓝*/
 14         0xff, 0xff, 0xff,    /*  7:白色*/
 15         0xc6, 0xc6, 0xc6,    /*  8:亮灰*/
 16         0x84, 0x00, 0x00,    /*  9:暗红*/
 17         0x00, 0x84, 0x00,    /* 10:暗绿*/
 18         0x84, 0x84, 0x00,    /* 11:暗黄*/
 19         0x00, 0x00, 0x84,    /* 12:暗青*/
 20         0x84, 0x00, 0x84,    /* 13:暗紫*/
 21         0x5b, 0x9b, 0xd5,    /* 14:浅灰蓝5B,9B,D5*/
 22         0x84, 0x84, 0x84    /* 15:暗灰*/
 23     };
 24     set_palette(0, 15, table_rgb);
 25     return;
 26 
 27     /* static char,储存数据, 相当于DB*/ 
 28 }
 29 
 30 void set_palette(int start, int end, unsigned char *rgb)
 31 {
 32     int i, eflags;
 33     eflags = io_load_eflags();    /*记录中断标志的值 */
 34     io_cli();                     /*禁止中断 */
 35     io_out8(0x03c8, start);
 36     for (i = start; i <= end; i++)
 37            {
 38         io_out8(0x03c9, rgb[0] / 4);    
 39         io_out8(0x03c9, rgb[1] / 4);
 40         io_out8(0x03c9, rgb[2] / 4);
 41         rgb += 3;
 42     }
 43     io_store_eflags(eflags);    /* 恢复中断标志*/
 44     return;
 45 }
 46 
 47 void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1)
 48 {
 49     int x, y;
 50     for (y = y0; y <= y1; y++) {
 51         for (x = x0; x <= x1; x++)
 52             vram[y * xsize + x] = c;
 53     }
 54     return;
 55 }
 56 
 57 void init_screen8(char *vram, int x, int y)
 58 {
 59     boxfill8(vram, x, COL8_008484,  0, 0,          x -  1, y - 29);    //绘制桌面填充灰蓝色
 60     boxfill8(vram, x, COL8_C6C6C6,  0, y - 28, x -  1, y - 28);    //第一条阴影
 61     boxfill8(vram, x, COL8_FFFFFF,  0, y - 27, x -  1, y - 27);    //绘制第二条阴影
 62     boxfill8(vram, x, COL8_C6C6C6,  0, y - 26, x -  1, y -  1);    //绘制任务栏主体
 63 
 64     boxfill8(vram, x, COL8_FFFFFF,  3, y - 24, 59, y - 24);        //绘制"开始"按钮 周围六条直线 
 65     boxfill8(vram, x, COL8_FFFFFF,  2, y - 24,  2, y -  4);
 66     boxfill8(vram, x, COL8_848484,  3, y -  4, 59, y -  4);
 67     boxfill8(vram, x, COL8_848484, 59, y - 23, 59, y -  5);
 68     boxfill8(vram, x, COL8_000000,  2, y -  3, 59, y -  3);
 69     boxfill8(vram, x, COL8_000000, 60, y - 24, 60, y -  3);
 70 
 71     boxfill8(vram, x, COL8_848484, x - 47, y - 24, x -  4, y - 24);//绘制状态栏 四条直线 
 72     boxfill8(vram, x, COL8_848484, x - 47, y - 23, x - 47, y -  4);
 73     boxfill8(vram, x, COL8_FFFFFF, x - 47, y -  3, x -  4, y -  3);
 74     boxfill8(vram, x, COL8_FFFFFF, x -  3, y - 24, x -  3, y -  3);
 75     return;
 76 }
 77 
 78 void putfont8(char *vram, int xsize, int x, int y, char c, char *font)
 79 {
 80     int i;
 81     char *p, d /* data */;
 82     for (i = 0; i < 16; i++) {
 83         p = vram + (y + i) * xsize + x;
 84         d = font[i];
 85         if ((d & 0x80) != 0) { p[0] = c; }
 86         if ((d & 0x40) != 0) { p[1] = c; }
 87         if ((d & 0x20) != 0) { p[2] = c; }
 88         if ((d & 0x10) != 0) { p[3] = c; }
 89         if ((d & 0x08) != 0) { p[4] = c; }
 90         if ((d & 0x04) != 0) { p[5] = c; }
 91         if ((d & 0x02) != 0) { p[6] = c; }
 92         if ((d & 0x01) != 0) { p[7] = c; }
 93     }
 94     return;
 95 }
 96 
 97 void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s)
 98 {
 99     extern char hankaku[4096];
100     for (; *s != 0x00; s++) {
101         putfont8(vram, xsize, x, y, c, hankaku + *s * 16);
102         x += 8;
103     }
104     return;
105 }
106 
107 void init_mouse_cursor8(char *mouse, char bc)
108 /* 16*16 Mouse */
109 {
110     static char cursor[16][16] = {
111         "*...............",
112         "**..............",
113         "*O*.............",
114         "*OO*............",
115         "*OOO*...........",
116         "*OOOO*..........",
117         "*OOOOO*.........",
118         "*OOOOOO*........",
119         "*OOOOOOO*.......",
120         "*OOOO*****......",
121         "*OO*O*..........",
122         "*O*.*O*.........",
123         "**..*O*.........",
124         "*....*O*........",
125         ".....*O*........",
126         "......*........."
127     };
128     int x, y;
129 
130     for (y = 0; y < 16; y++) {
131         for (x = 0; x < 16; x++) {
132             if (cursor[y][x] == '*') {
133                 mouse[y * 16 + x] = COL8_000000;
134             }
135             if (cursor[y][x] == 'O') {
136                 mouse[y * 16 + x] = COL8_FFFFFF;
137             }
138             if (cursor[y][x] == '.') {
139                 mouse[y * 16 + x] = bc;
140             }
141         }
142     }
143     return;
144 }
145 
146 void putblock8_8(char *vram, int vxsize, int pxsize,
147     int pysize, int px0, int py0, char *buf, int bxsize)
148 {
149     int x, y;
150     for (y = 0; y < pysize; y++) {
151         for (x = 0; x < pxsize; x++) {
152             vram[(py0 + y) * vxsize + (px0 + x)] = buf[y * bxsize + x];
153         }
154     }
155     return;
156 }
View Code

bootpack.c

 1 #include <stdio.h>
 2 #include "bootpack.h"
 3 
 4 void HariMain(void)
 5 {
 6     struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0;
 7     char s[40], mcursor[256];    
 8     int mx, my;
 9 
10     init_gdtidt();
11     init_palette();
12     init_screen8(binfo->vram, binfo->scrnx, binfo->scrny);
13     mx = (binfo->scrnx - 16) / 2;        //水平居中 
14     my = (binfo->scrny - 28 - 16) / 2;    //排除任务栏垂直居中
15     init_mouse_cursor8(mcursor, COL8_008484);
16     putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16);
17     sprintf(s, "(%d, %d)", mx, my);
18     putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, s);
19 
20     for (;;)
21     {
22         io_hlt();
23     }
24 }
View Code

bootpack.h

 1 /* asmhead.nas */
 2 struct BOOTINFO { /* 0x0ff0-0x0fff */
 3     char cyls; /* 启动区读硬盘读到何处为止 */
 4     char leds; /* 启动时LED的状态*/
 5     char vmode; /* 显卡模式*/
 6     char reserve;
 7     short scrnx, scrny; /* 分辨率*/
 8     char *vram;
 9 };
10 #define ADR_BOOTINFO    0x00000ff0
11 
12 /* naskfunc.nas */
13 void io_hlt(void);
14 void io_cli(void);
15 void io_out8(int port, int data);
16 int io_load_eflags(void);
17 void io_store_eflags(int eflags);
18 void load_gdtr(int limit, int addr);
19 void load_idtr(int limit, int addr);
20 
21 /* graphic.c */
22 void init_palette(void);
23 void set_palette(int start, int end, unsigned char *rgb);
24 void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1);
25 void init_screen8(char *vram, int x, int y);
26 void putfont8(char *vram, int xsize, int x, int y, char c, char *font);
27 void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s);
28 void init_mouse_cursor8(char *mouse, char bc);
29 void putblock8_8(char *vram, int vxsize, int pxsize,
30     int pysize, int px0, int py0, char *buf, int bxsize);
31 #define COL8_000000        0
32 #define COL8_FF0000        1
33 #define COL8_00FF00        2
34 #define COL8_FFFF00        3
35 #define COL8_0000FF        4
36 #define COL8_FF00FF        5
37 #define COL8_00FFFF        6
38 #define COL8_FFFFFF        7
39 #define COL8_C6C6C6        8
40 #define COL8_840000        9
41 #define COL8_008400        10
42 #define COL8_848400        11
43 #define COL8_000084        12
44 #define COL8_840084        13
45 #define COL8_008484        14
46 #define COL8_848484        15
47 
48 /* dsctbl.c */
49 struct SEGMENT_DESCRIPTOR {
50     short limit_low, base_low;
51     char base_mid, access_right;
52     char limit_high, base_high;
53 };
54 struct GATE_DESCRIPTOR {
55     short offset_low, selector;
56     char dw_count, access_right;
57     short offset_high;
58 };
59 void init_gdtidt(void);
60 void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar);
61 void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar);
62 #define ADR_IDT        0x0026f800
63 #define LIMIT_IDT    0x000007ff
64 #define ADR_GDT        0x00270000
65 #define LIMIT_GDT    0x0000ffff
66 #define ADR_BOTPAK    0x00280000
67 #define LIMIT_BOTPAK    0x0007ffff
68 #define AR_DATA32_RW    0x4092
69 #define AR_CODE32_ER    0x409a
View Code

naskfunc.nas

 1 ;naskfunc
 2 
 3 [FORMAT "WCOFF"]    ; 制作目标文件的模式
 4 [INSTRSET "i486p"]
 5 [BITS 32]        ; 制作32位模式用的机器语言
 6 
 7 
 8 [FILE "naskfunc.nas"]    ; 源文件名信息
 9 
10             ; 程序中包含的函数名
11     GLOBAL    _io_hlt, _io_cli, _io_sti, _io_stihlt
12     GLOBAL    _io_in8,  _io_in16,  _io_in32
13     GLOBAL    _io_out8, _io_out16, _io_out32
14     GLOBAL    _io_load_eflags, _io_store_eflags
15     GLOBAL    _load_gdtr, _load_idtr    
16 
17 ; 实际的函数
18 
19 [SECTION .text]    ;
20 
21 _io_hlt:    
22     HLT
23     RET
24 _io_cli:    ; void io_cli(void);
25     CLI
26     RET
27 
28 _io_sti:    ; void io_sti(void);
29     STI
30     RET
31 
32 _io_stihlt:    ; void io_stihlt(void);
33     STI
34     HLT
35     RET
36 
37 _io_in8:    ; int io_in8(int port);
38     MOV    EDX,[ESP+4]    ; port
39     MOV    EAX,0
40     IN    AL,DX
41     RET
42 
43 _io_in16:    ; int io_in16(int port);
44     MOV    EDX,[ESP+4]    ; port
45     MOV    EAX,0
46     IN    AX,DX
47     RET
48 
49 _io_in32:    ; int io_in32(int port);
50     MOV    EDX,[ESP+4]    ; port
51     IN    EAX,DX
52     RET
53 
54 _io_out8:    ; void io_out8(int port, int data);
55     MOV    EDX,[ESP+4]    ; port
56     MOV    AL,[ESP+8]    ; data
57     OUT    DX,AL
58     RET
59 
60 _io_out16:    ; void io_out16(int port, int data);
61     MOV    EDX,[ESP+4]    ; port
62     MOV    EAX,[ESP+8]    ; data
63     OUT    DX,AX
64     RET
65 
66 _io_out32:    ; void io_out32(int port, int data);
67     MOV    EDX,[ESP+4]    ; port
68     MOV    EAX,[ESP+8]    ; data
69     OUT    DX,EAX
70     RET
71 
72 _io_load_eflags:    ; int io_load_eflags(void);
73     PUSHFD    ; PUSH EFLAGS 
74     POP    EAX
75     RET
76 
77 _io_store_eflags:    ; void io_store_eflags(int eflags);
78     MOV    EAX,[ESP+4]
79     PUSH    EAX
80     POPFD    ; POP EFLAGS 
81     RET
82 
83 _load_gdtr:        ; void load_gdtr(int limit, int addr);
84         MOV    AX,[ESP+4]        ; limit
85         MOV    [ESP+6],AX
86         LGDT    [ESP+6]
87         RET
88 
89 _load_idtr:        ; void load_idtr(int limit, int addr);
90         MOV    AX,[ESP+4]        ; limit
91         MOV    [ESP+6],AX
92         LIDT    [ESP+6]
93         RET
View Code

Makefile

 1 OBJS_BOOTPACK = bootpack.obj naskfunc.obj hankaku.obj graphic.obj dsctbl.obj
 2 
 3 TOOLPATH = ../z_tools/
 4 INCPATH  = ../z_tools/haribote/
 5 
 6 MAKE     = $(TOOLPATH)make.exe -r
 7 NASK     = $(TOOLPATH)nask.exe
 8 CC1      = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet
 9 GAS2NASK = $(TOOLPATH)gas2nask.exe -a
10 OBJ2BIM  = $(TOOLPATH)obj2bim.exe
11 MAKEFONT = $(TOOLPATH)makefont.exe
12 BIN2OBJ  = $(TOOLPATH)bin2obj.exe
13 BIM2HRB  = $(TOOLPATH)bim2hrb.exe
14 RULEFILE = $(TOOLPATH)haribote/haribote.rul
15 EDIMG    = $(TOOLPATH)edimg.exe
16 DEL      = del
17 SHORTCUT = "D:\Program Files\Oracle\VirtualBox\VirtualBox.exe" --comment "OS1" --startvm "a5c4b0e6-e142-4720-98ee-056911204b29"
18 
19 default :
20     $(MAKE) install
21     $(MAKE) run
22     $(MAKE) clean
23 
24 ipl10.bin : ipl10.nas Makefile
25     $(NASK) ipl10.nas ipl10.bin ipl10.lst
26 
27 asmhead.bin : asmhead.nas Makefile
28     $(NASK) asmhead.nas asmhead.bin asmhead.lst
29 
30 hankaku.bin : hankaku.txt Makefile
31     $(MAKEFONT) hankaku.txt hankaku.bin
32 
33 hankaku.obj : hankaku.bin Makefile
34     $(BIN2OBJ) hankaku.bin hankaku.obj _hankaku
35 
36 bootpack.bim : $(OBJS_BOOTPACK) Makefile
37     $(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \
38         $(OBJS_BOOTPACK)
39 # 3MB+64KB=3136KB
40 
41 bootpack.hrb : bootpack.bim Makefile
42     $(BIM2HRB) bootpack.bim bootpack.hrb 0
43 
44 haribote.sys :asmhead.bin bootpack.hrb Makefile
45     copy /B asmhead.bin+bootpack.hrb haribote.sys
46 
47 haribote.img : ipl10.bin haribote.sys Makefile
48     $(EDIMG)   imgin:../z_tools/fdimg0at.tek \
49         wbinimg src:ipl10.bin len:512 from:0 to:0 \
50         copy from:haribote.sys to:@: \
51         imgout:haribote.img
52 
53 %.gas : %.c Makefile
54     $(CC1) -o $*.gas $*.c
55 
56 %.nas : %.gas Makefile
57     $(GAS2NASK) $*.gas $*.nas
58 
59 %.obj : %.nas Makefile
60     $(NASK) $*.nas $*.obj $*.lst
61 
62 install:
63     $(MAKE) haribote.img
64 
65 run :
66     echo Running... 
67     $(SHORTCUT)
68     echo Finished
69 
70 clean :
71     -$(DEL) *.bin
72     -$(DEL) *.lst
73     -$(DEL) *.gas
74     -$(DEL) *.obj
75     -$(DEL) bootpack.nas
76     -$(DEL) bootpack.map
77     -$(DEL) bootpack.bim
78     -$(DEL) bootpack.hrb
79     -$(DEL) haribote.sys
80     -$(DEL) *.*~
81     -$(DEL) *~
82     echo Cleaned.
View Code

 

转载于:https://www.cnblogs.com/lastavengers/p/3895833.html

关于并网继电器的继电器自检逻辑及实现方式 对于常规的光伏并网逆变器来说,继电器控制至关重要。继电器一般位于逆变电感后,共模电感前,用于将逆变电压与电网电压脱开,一般国外有双继电器的安规强制认证要求,国内目前只需要单继电器要求(后续应该会有双继电器要求,个人感觉) 阅读详情

相关推荐

CoppeliaSim(原V-REP)新手上路

CoppeliaSim(原V-REP)是一个机器人仿真平台,里面有很多来自别的公司的机器人模型以及完备的物理引擎,我们可以通过python,c++,matlab等语言控制里面的机器人。,您也可以在官网中Downloads里找您需要的版本,一般只需要下载EDU版本就可以了,我下载的是v4.1.0 windows EDU版本。在版本V4之前,CoppeliaSim叫V-REP,在官网可以下载到之前的V-REP版本。

qq_37051669的博客 4万+

[Rx86OS-X] 内存管理·简

平台 处理器:Intel Celeron® Dual-CoreCPU 操作系统:Windows 7 专业版 x86 阅读书籍:《30天自制操作系统》—川合秀实[2015.04.05-04.06] 工具:../toolset/ 1 内存使用情况 编写完鼠标移动程序后,内存分布如下。 Figure1. 内存使用情况 2 检测可用内存容量大小 x86保护模式

记一忘三二 1983

多模态情感识别(MER)数据集实战指南:从IEMOCAP到应用落地

本文提供了多模态情感识别(MER)从数据集到应用落地的完整实战指南。以经典IEMOCAP数据集为例,详细讲解了音频、视觉、文本等多模态数据的预处理、特征提取与融合技术,并分享了模型训练调优心得及面向智能客服、在线教育等场景的部署考量,帮助开发者快速构建高效可用的MER系统。

h3i4j的博客 1070

《30天自制操作系统》笔记(09)——绘制窗口

《30天自制操作系统》笔记(09)——绘制窗口 进度回顾 上一篇中介绍了图层式窗口管理的思路和算法。在此基础上,本篇就解决绘制窗口及其简单的优化问题。 这里稍微吐槽一下《30天自制操作系统》原作者。全书我刚刚看了三分之一,写得确实不错,但是我能感受到原作者是习惯用汇编语言和汇编思维来写程序的。虽然书里尽量使用了C语言,但给我一种用C写汇编的感觉。也可能是原作者故意简化了OS开发过程,方便初...

weixin_33785108的博客 214

告别‘线束丛林’:手把手拆解车身域控制器(BCM/PEPS/网关)的硬件选型与PCB布局要点

本文深入解析车身域控制器的硬件选型与PCB布局要点,涵盖主控MCU选择、通信接口设计、电源架构优化及EMC设计等关键环节。通过实战案例分享,帮助工程师解决高密度集成带来的电源完整性、热管理和信号隔离挑战,实现更稳定高效的汽车电子系统设计。

weixin_42567279的博客 394

电影票购票小程序搭建(源码部署)

答:为用户提供便捷的购票方式,包括授权登录、个性化推荐、在线选座、订单管理等功能,同时在界面设计上注重用户友好性,简化用户的购票流程。答:通过展示电影院的优惠活动和票价信息,同时提供电影推荐功能,根据用户的历史购票记录和电影评分推荐个性化的电影列表,吸引用户购票。编写页面逻辑代码:使用JavaScript编写小程序页面的逻辑代码,实现电影列表的获取、电影详情的展示、座位选择的逻辑等。设计小程序界面:使用WXML和WXSS编写小程序的界面代码,实现电影列表的展示、电影详情的样式、座位选择页面的布局等。

2301_79072569的博客 2068

30天自制操作系统笔记(四)

首先我们先展示一下第四天的成果: 图一:显示纯色 图二:显示格子 图三:使用调色板显示格子 图四:画正方形 最后的图为一个小界面: 第四天的内容其实不难,但是由于前三天写的代码部分有问题,导致今天调试了一天才找到问题所在问题的更正已经在下面的源文件中指出。 代码中唯一没有指出的是Makefile文件中的溢出小错误,将文件名字写错啦具体为: naskfunc.o...

369540808 232

【故障排查】telnet连接失败:端口23不可达的深度分析与解决方案

本文深度剖析了telnet连接失败,特别是端口23不可达的常见原因与系统性解决方案。文章从客户端本地配置、服务器端服务与防火墙、中间网络路径三个层面,提供了详细的排查步骤与命令,并强调了Telnet协议的安全风险,建议使用SSH等更安全的替代方案进行远程管理与端口测试。

weixin_29306011的博客 898

【读书笔记-《30天自制操作系统》-28】Day29

本篇首先完善文件压缩的功能,完成操作系统功能的开发,然后进行应用程序的开发。首先完成了C语言的几个标准函数,然后完成了bball程序与外星人游戏程序的开发。

Ocean1994的博客 1161

手把手教你学SOME/IP「3.2.1.发布/订阅行为」

本文详细介绍了SOME/IP协议中的服务发现机制,重点解析了发布/订阅行为的流程。主要内容包括:1)服务发布与Method通信流程,涵盖find/offer报文交互、TTL保活机制及异常处理;2)服务订阅与Event通信流程,包括subscribe/ack报文交互和组播延迟机制;3)特殊场景如快速发送、半周期回复、重置订阅等机制。通过邮局订阅报纸的类比,帮助理解服务发现的核心原理,并强调流程图对于问题定位的重要性。文章为SOME/IP协议的工程实现提供了实用指导。

nihaoljq2010的博客 1221

[QMT量化交易小白入门]-三十四、让deepseek分析北京炒家的首板策略后,在打板前增加了选股范围(量化python代码解析)

print(f'开始盘前选股')这行代码定义了一个名为的函数,当调用这个函数时,会首先打印出“开始盘前选股”的信息,表明选股流程正式启动。1、可根据情况增删部分条件,目前盘前选股目前可以选出140多支,比之前全市场监听带宽压力小了很多。2、还可以自行添加其他选股条件,比如换手率计算,炸板可能性检测。3、xtdata的数据是有可能缺失的,自己写策略时,有可能需要剔除,或者从第三方库校正,比如部分股票的流通股数。

木头大左的博客 2698

【读书笔记-《30天自制操作系统》-25】Day26

本篇仍然是围绕着命令行窗口做文章。首先优化命令行窗口的移动速度,然后增加多个命令行窗口功能。接着优化了命令行窗口的关闭,最后增加了两个命令start与ncst。

Ocean1994的博客 1371

在 Esp32 摄像头上实现边缘脉冲 FOMO 物体检测

本文将详细介绍如何在 Esp32 摄像头上实现边缘脉冲 FOMO 物体检测,并提供实现源码

DT程序员的博客 705

《30天自制操作系统》读书笔记(5) GDT&IDT

梳理项目结构 项目做到现在, 前头的好多东西都忘了, 还是通过Makefile重新理解一下整个项目是如何编译的: 现在我们拥有这么9个文件: ipl10.nasInitialProgramLoader, 占用了软盘的第一个扇区并符合启动盘的规范, 默认被载入地址是0x7c00 到 0x7e00, 负责将10个柱面读入到0x8200到0x34fff...

dingjin9321的博客 208

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

30天自制操作系统读书笔记(六)

首先先整理下(转自谷月轩的博客) 现在我们拥有这么9个文件: ipl10.nasInitialProgramLoader, 占用了软盘的第一个扇区并符合启动盘的规范, 默认被载入地址是0x7c00 到 0x7e00, 负责将10个柱面读入到0x8200到0x34fff (10个柱面共10*2*18 = 360 个扇区但是第一个没有被读入); asmhead.nas ...

bahunj93679的博客 195

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

30天自制操作系统(Mac版)读书笔记(day4.1)

添加绘制其他矩形的代码。

Niap的博客 141

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

30天自制操作系统读书笔记(四)

想要在画面里画点什么东西,就需要往VRAM的内存区里写入点什么东西。 但是如何写入呢? 作者先用了汇编: _write_mem8: ; void write_mem8(int addr, int data); MOV ECX,[ESP+4] ; [ESP +...

weixin_30794491的博客 86

30天自制操作系统(Mac版)读书笔记(day4)

本章主要是要在C语言当中,实现对内存的修改。

Niap的博客 152

【图灵日文书汇总】图书无国界,我们要师夷长技以自强

很早就听说2012,但一晃我们即将静候2013了!末日预言并没有打败任何人,人们依旧按部就班的生活,对待工作也没有消极懈怠,反而更加积极向上了。图灵人亦是如此!@图灵教育 今年出版了一百多本技术书籍,包括十多本原创图书,其中《思考的乐趣:Matrix67数学笔记》更是获得了无数人的认可,跃居图灵原创畅销榜榜首! 除了在原创方面可喜可贺之外,图灵翻译出版的几本日文书,也是非常给力,广获好评!...

图灵教育官方博客 285

读书笔记之Android绘图机制及图像处理值色彩处理的相关技巧

1.屏幕的尺寸信息 屏幕大小:寸,屏幕对角线的长度 分辨率:手机屏幕像素点的个数,720*1280. PPI:每英寸像素又被称为DPI。他是由对角线的像素点除以屏幕的大小的得到的。 独立像素密度:dp,同样像素大小的长度在不同密度的屏幕上显示长度不同。 2.2D绘图基础 系统通过canvas对象提供绘图方法,像画圆,画线,画矩形等等。。。设置paint笔的的一些参数。具体画法可

zah1234567的博客 492

《Android群英传》---读书笔记4

《Android群英传》—读书笔记4标签: android中级 读书笔记Android绘图机制与处理技巧Android屏幕相关知识略2D绘图基础系统通过提供的Canvans对象来提供绘图,如下所示: drawPoint; drawRect; drawRoundRect;//绘制圆角矩形 drawLine;//绘制直线 drawLines;//绘制多条直线 drawVertices;绘制多

yarsnwoing的博客 480

读书笔记 - js高级程序设计 - 第十五章 使用Canvas绘图

读书笔记 - js高级程序设计 - 第十三章 事件 canvas 具备绘图能力的2D上下文 及文本API 很多浏览器对WebGL的3D上下文支持还不够好 有时候即使浏览器支持,操作系统如果缺缺乏必要的绘图驱动程序,则浏览器即使支持了也没用 <canvas> var drawing = document.getEle...

weixin_30786657的博客 186

JS高级程序设计读书笔记(第十五章 使用Canvas绘图)

canvas元素负责在页面中设定一个区域,然后通过js动态地在这个区域中绘制图形。   1. 基本用法  1.1 要使用canvas元素,必须先设置其width和height属性,指定绘图区域的大小。出现在开始标签和结束标签中的内容是后备信息,如果浏览器不支持canvas元素,就会显示这些信息。1.2 要在画布上绘图,需要取得绘图上下文(getContext())1.3 使用toData

didiaidada的专栏 646
上一篇: [转]高精度乘法计算
下一篇: 《30天自制操作系统》读书笔记(5) GDT&IDT
dingjin9321
博客等级 码龄11年 0粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值