30天自制操作系统——自写设计

写在前面:这是我在学习了一个学期的《30天自制操作系统》之后,用了差不多一个周的时间,所写出来的一个纸娃娃操作系统,有一个小的开机动画,可以输入密码,然后有一个小的画图程序。现在把他写出来,只是为了记录这一个学期的学习经历吧,至少证明自己学有所成,所有所获。

一、实验环境

硬件环境:计算机,无特殊配置要求
软件环境:QEMU虚拟机、批处理文件、相关编译工具等
语言环境:C语言、汇编语言

二、功能介绍及运行效果截图

1、开机:
a、通过使用定时器timer3实现对时间的严格把控
在这里插入图片描述
每0.1秒向缓冲区发送一个“1”
b、通过定义图层,实现开机动画
在这里插入图片描述
每一个图层都是开机动画的一帧,都是由一个85x80的数组实现的,写在我新建立的start.c文件中,通过不同的符号表示不同的颜色,来实现一张图案的绘制,多个图案连在一起,就构成了一段开机动画,并且可以色彩变换:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
c、首先定义图层的级别,最先要展示的图层设置为0级,其余的图层设置为-1级进行隐藏。同时,将每个图层的位置设置为(0,0)左上角。
在这里插入图片描述
然后,通过一个while死循环,跳出循环的条件是我所设置的一个标志量flagtime为10,而flagtime会在每次timer3向缓冲区输入一个1的时候进行增加,并且每0.6秒增加一次,然后根据不同的flagtime的值,来将不同的图层的级别设置为1,表示进行展示,而将当前的图层设置为-1,即进行隐藏
在这里插入图片描述
就可以设置一个长达6秒的开机动画。
d、在开机动画结束后,注意要将当前图层设置为隐藏的-1级别,而将我们下面要用的密码图层设置为1展示级别
在这里插入图片描述
由于为了让我的动画更炫酷一点,我增加了一个圆形的加载形式
并且,因为如果将所有的代码放到bootpack.c文件中,代码会运行的很慢,所以我在start.c文件中实现了对所有的开机动画图层的初始化:
在这里插入图片描述
而增加的一个圆形的加载,是在这里实现的
在这里插入图片描述
可以实现一个类似于圆形加载的效果,只不过更炫酷一点
效果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
然后,为了能够比较平滑的连接到密码输入界面,我需要考虑如何将这个开机动画回归到黑色的界面。
首先,加一个剑的移动的函数分支:
在这里插入图片描述
增加了这个函数分支之后,随着我给的时间表胡子良flagtime(在函数中为形参t)随时间增大,将会进入50的分支,进入该分支后,将会对剑图案的位置进行移动。
同时,需要对圆环的位置进行移动,增加一个分支:
在这里插入图片描述
通过这个分支,可以实现圆环的移动。
仅仅移动是不够的,我还要实现退出,在这里做一个雪花飘落的样子,就是增加如下的函数分支:
在这里插入图片描述
在这里插入图片描述
通过取余操作,可以实现类似于雪花的效果,最终结果如下所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2、输入密码:
a、首先通过字符数组的形式定义一个正确的账号和密码:
在这里插入图片描述
b、再定义另外两个字符数组用来存储我们所输入的字符
在这里插入图片描述
c、在一个while死循环内,跳出循环的条件是标志量flagkaiji为1,即输入正确的账号和密码并且同时按下了回车键。
首先会对缓冲区进行判断,如果缓冲区中有值并且这个值在256到511之间,表示此时是键盘输出产生的中断,然后我们对中断进行判断,用sprintf函数将整型数据转换为两位十六进制类型,然后用我写的panduan函数进行判断是什么按键被按下:
在这里插入图片描述
在这里插入图片描述
如果按下的按键并不是break或者是shift这种功能键,就进行判断。
如果是回车键,需要通过strcmp函数判断当前输入的字符串与正确的字符串,如果相等就对标志量flagkaiji进行赋值为1,并将当前的密码图层设置为隐藏的-1级别。
在这里插入图片描述
如果不相等,需要判断有没有输完,如果只是输完了账号一栏,说明我们还需要输入密码一栏,将我们的输入位置j和h调整为密码栏的位置即可:
在这里插入图片描述
如果已经输入完全了,说明此时输入者并不知道密码是什么,或者说输入的密码和账号是错误的,这里就可以将输入栏和密码栏进行刷新,然后将输入为止重新进行调整为开头,并输出一行提示错误的字符串“passwords error!!!”,注意,还需要将我们的存储数组进行清空。
在这里插入图片描述
最终结果如下:
输入密码界面:
在这里插入图片描述
如果输入错误的界面,会出现叉号,并可以重新输入:
在这里插入图片描述在这里插入图片描述
重新输入正确的密码则会开机,同样的,在这里设计了一个比较厉害的动画:
在这里插入图片描述在这里插入图片描述在这里插入图片描述
4、程序:
这里我的程序是直接使用的节点考试时所编写的画图程序,实现功能很多,这里会直接根据我的主函数,花费大量篇幅进行讲解,每一个功能会进行标红加粗处理:

  if (flagshuangji == 0) {
   shuangji++;}
  if (shuangji == 10000) {
   
   flagshuangji = 1;
   shuangji = 0;}
  sprintf(s, "%010d", shuangji);
  sheet_refresh(sht_back, 100, 80, 320, 100);

这是我用来判断双击和函数,通过标志量flagshaungji的值来表示两次鼠标左键点击之间的时间间隔,如果时间间隔足够小,说明是双击。

  io_cli();//关闭终端
  if (fifo32_status(&fifo) == 0) {
    io_sti();//如果缓冲区为空则开启中断
  } else {
   //如果缓冲区不为空,说明有服务请求运行,或者有中断发生
   i = fifo32_get(&fifo);//取出缓冲区的值,进行判断
   io_sti();
   if (256 <= i && i <= 511) {
    //如果是键盘操作
    sprintf(s, "%02X", i - 256);
    putfonts8_asc_sht(sht_back, 0, 16, COL8_FFFFFF, COL8_008484, s, 2);
panduan(s);

功能1、键盘输入:可以通过键盘输入字符,通过我自己编写的panduan函数判断所按下的按键是哪一个按键,并作出相应的操作

    if (strcmp(sss, "break") != 0 && strcmp(sss, "left shift") != 0 && strcmp(sss, "return") != 0 && flagwenben == 2 && flagguanbi == 0) {
   
     if (strcmp(sss, "hc") == 0) {
   
      boxfill8(buf_bigwin, binfo->scrnx, dise, j + 3, 16 * (h), j + 3, 16 * (h + 1) - 1);
      jj[h] = j;
      h = h + 1;
      if (h >= binfo->scrny/16-1) {
   h = binfo->scrny/16-1;}
      j = wbj;
      boxfill8(buf_bigwin, binfo->scrnx, zise, j + 3, 16 * (h), j + 3, 16 * (h + 1) - 1);}
/*如果按下的是回车键,那么需要实现换行操作,同时记录当前光标的位置,为下面的删除键操作做铺垫*/
     else if (strcmp(sss, "tg") == 0) {
   
      boxfill8(buf_bigwin, binfo->scrnx, dise, j + 3, 16 * (h), j + 3, 16 * (h + 1) - 1);
      j = j - 8*zihao;
      if (j < wbj) {
   h = h - 1;
       if (h < 2) {
   
        h = 2;
        j = wbj;
       }else {
   
        if (jj[h] <= wbj) {
   j = wbj;
        }else {
   
         if (jj[h] <= wbj) {
   j = wbj;
         }else {
   j = jj[h];
         }}}}
      boxfill8(buf_bigwin, binfo->scrnx, dise, j + 3, 16 * h, j + 3 + 8*zihao, 16 * h + 16);
      boxfill8(buf_bigwin, binfo->scrnx, zise, j + 3, 16 * (h), j + 3, 16 * (h + 1) - 1);}
/*如果按下的是删除键,那么就对前一个字符的位置(8*16像素)进行背景色的填充处理,但需要判断的是是否需要返回上一行,如果是则取出之前在回车处理中所存储的jj数组的相应位置的值*/
     else if (strcmp(sss, "dx") == 0) {
   
      flagdx = !flagdx;}
/*如果按下的是大小写切换键,那么就需要将标志量设置为相反的,以便为下面的输出做准备*/
     else {
   
      boxfill8(buf_bigwin, binfo->scrnx, dise, j + 3, 16 * h, j + 3 + 8*zihao, 16 * h + 16);
      if (flagdx == 0) {
   dahuaxiao(sss);}
      putfonts8_num(buf_bigwin, binfo->scrnx, j + 3, 16 * h, zise, sss,zihao);
      j = j + 8*zihao;
      if (j >= binfo->scrnx-5) {
   
       jj[h] = j - 8*zihao;
       h = h + 1;
       if (jj[h] <= wbj) {
   j = wbj;
       }else {
   j = jj[h];}}
      boxfill8(buf_bigwin, binfo->scrnx, zise, j + 3, 16 * h, j + 3, 16 * h + 16 - 1);
     }}
    sheet_refresh(sht_bigwin, 0, 0, binfo->scrnx, binfo->scrny-20);} 
/*如果是正常的按键输入,那么就通过我所写的函数进行字符的打印输出,这里就是我实现的第二个功能:*/

功能2、改变字号:通过我专门编写的putfonts8_num函数,可以输出不同字号的字符,打印在相应的位置,要注意的是需要判断是否需要换行

else if (512 <= i && i <= 767) {
    //如果是鼠标操作
    if (mouse_decode(&mdec, i - 512) != 0) {
   
     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';}
     putfonts8_asc_sht(sht_back, 32, 16, COL8_FFFFFF, COL8_008484, s, 15);

功能3、正常窗口拖动:可以拖动正常大小(180x140像素)的窗口,并且和鼠标一样,左边和上边不能出界,下边和右边可以出界

     if ((wx + 0 <= mx && mx <= wx + 120 && wy + 3 <= my && my <= wy + 20) && flag2 == 1 && flag == 1 && (mdec.btn & 0x01) != 0 && flagguanbi == 0) {
   //如果鼠标在窗口任务栏位置发生了点击并移动的操作
      mx += mdec.x;
      my += mdec.y;
      wx += mdec.x;
      wy += mdec.y;}

功能4、正常窗口画细线:可以在正常大小的窗口中实现画细线的操作,并且限定了画线的范围,随着鼠标的移动和点击,实现画线操作

     else if ((wx + 5 <= mx && mx <= wx + 175 && wy + 25 <= my && my <= wy + 135) && flag2 == 1 && flag == 1 && flagxiangpi == 0 && flagcu == 0 && flagguanbi == 0 && flagquse == 0 && flagtianchong == 0) {
   //如果鼠标在窗口的范围内并且窗口处于正常的打开状态
      fx = mx;
      fy = my;
      mx += mdec.x;
      my += mdec.y;
      int ax = mx, ay = my;
      if ((mdec.btn & 0x01) != 0) {
   
       if (wx + 5 <= mx && mx <= wx + 175 && wy + 25 <= my && my <= wy + 135) {
   
        if ((fx > mx && my > fy) || (fx < mx && my < fy)) {
   
         xian(buf_window, 180, zise, min(fx, mx) - wx, min(fy, my) - wy, max(fx, mx) - wx, max(fy, my) - wy, 1);
         xian(buf_bigwin, binfo->scrnx, zise, min(fx, mx) - wx, min(fy, my) - wy, max(fx, mx) - wx, max(fy, my) - wy, 1);}
        else {
   
         xian(buf_window, 180, zise, min(fx, mx) - wx, min(fy, my) - wy, max(fx, mx) - wx, max(fy, my) - wy, 0);
         xian(buf_bigwin, binfo->scrnx, zise, min(fx, mx) - wx, min(fy, my) - wy, max(fx, mx) - wx, max(fy
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值