发布于 

30天自制操作系统(25)

DAY25_增加命令行窗口

1.蜂鸣器发声

蜂鸣器发声
EDX=20
EAX=声音频率(单位是mHz,即毫赫兹)
例如当EAX=4400000时,则发出440Hz的声音
频率设为0则表示停止发声
int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax) 
{
(中略)
} else if (edx == 20) {
if (eax == 0) {
i = io_in8(0x61);
io_out8(0x61, i & 0x0d);
} else {
i = 1193180000 / eax;
io_out8(0x43, 0xb6);
io_out8(0x42, i & 0xff);
io_out8(0x42, i >> 8);
i = io_in8(0x61);
io_out8(0x61, (i | 0x03) & 0x0f);
}
}
return 0;
}

2.增加更多的颜色(1)

修改graphic.c

void init_palette(void) 
{
static unsigned char table_rgb[16 * 3] = {
(中略)
};
unsigned char table2[216 * 3];
int r, g, b;
set_palette(0, 15, table_rgb);
for (b = 0; b < 6; b++) {
for (g = 0; g < 6; g++) {
for (r = 0; r < 6; r++) {
table2[(r + g * 6 + b * 36) * 3 + 0] = r * 51;
table2[(r + g * 6 + b * 36) * 3 + 1] = g * 51;
table2[(r + g * 6 + b * 36) * 3 + 2] = b * 51;
}
}
}
set_palette(16, 231, table2);
return;
}

3.增加更多的颜色(2)

我们可以用两种颜色交替排列,看上去就像这两种颜色混合在一起一样,这就是要点。颜色的混合方式我们考虑了下面3种(算上完全不混合的情况,一共有5种)。
25.1

4. 窗口初始位置

因此我们希望让窗口总是显示在画面的中央,而且显示窗口时的图层高度也不能总是固定为3,而是要判断当前画面中窗口的数量并自动显示在最上面。

5. 增加命令行窗口(1)

于是,我们这次只修改bootpack.c,将命令行窗口的相关变量(buf_cons、sht_cons、task_cons和cons)各准备2个,分别分给命令行1和命令行2。

6.增加命令行窗口(2)

struct CONSOLE *cons = (struct CONSOLE *) *((int *) 0x0fec);

这里的cons变量是用来判断“要向哪个命令行窗口输出字符”的关键。该变量的值是从内存地址0x0fec读取出来的,而无论从哪个任务读取这个内存地址中的值,得到的肯定都是同一个值,因此不管在哪个窗口中运行a.hrb,都只能在固定的其中一个窗口中显示字符。

7. 增加命令行窗口(3)

问题出在cmd_app身上

set_segmdesc(gdt + 1003, finfo->size - 1, (int) p, AR_CODE32_ER + 0x60); 
set_segmdesc(gdt + 1004, segsiz - 1, (int) q, AR_DATA32_RW + 0x60);
(中略)
start_app(0x1b, 1003 * 8, esp, 1004 * 8, &(task->tss.esp0));

首先,color.hrb在某个窗口中被运行,启动程序一切顺利,然后显示窗口并绘图,接下来等待键盘输入并进入休眠状态。到这里为止没有任何问题。
然后我们在另外一个窗口中运行color.hrb,程序也顺利启动了,显示窗口并绘图,随后进入休眠状态。然而在这个时候,问题其实已经发生了。这是怎么回事呢?因为我们为color.hrb准备的1003号代码段和1004号数据段,被color2.hrb所用的段给覆盖掉了。
因此,当按下回车键唤醒color.hrb时,就会发生异常情况——明明应该去运行color.hrb的,结果却错误地运行了color2.hrb,这样当然会出错了。

8.增加命令行窗口(4)

这次的修改也很简单,首先将原来task_cons[0]的地方改为key_wintask和shttask,这样一来,用键盘强制结束时会以当前输入窗口为对象,而用鼠标点击“×”按钮时会以被点击的窗口为对象。

9.变得更像真正的操作系统(1)

10.变得更像真正的操作系统(2)

这样肯定不行,因为命令行窗口任务的优先级比较低,只有当bootpack.c的HariMain休眠之后才会运行命令行窗口任务,而如果不运行这个任务的话,FIFO缓冲区就不会被初始化,这就相当于我们在向一个还没初始化的FIFO强行发送数据,于是造成fifo32_put混乱而导致重启。