首页 > 其他分享 >0x07_自制操作系统My-OS实现输出字符到屏幕

0x07_自制操作系统My-OS实现输出字符到屏幕

时间:2023-02-27 20:45:10浏览次数:74  
标签:struct int My void 0x07 fifo char OS define

<iframe frameborder="no" height="240" src="https://catalogue.codepowders.com/my-os-cata.html" style="position: absolute; width: 100%; height: 100%; left: 0; top: 0" width="320"></iframe>

接上一课class04,这是他的运行结果

 

收到了键盘的中断,现在想的当然是怎么把输入的文字显示到屏幕上,做成一个最简单的IO

 

这是class04的目录结构,现在我们把他换成class05

我们现在要读取键盘的数据,然后显示在屏幕上面

interrupt.c

#include "include/head.h"


void inthandler21(int *esp)
/* 来自PS/2键盘的中断 */
{
    unsigned char data,s[256];
    io_set8(PIC0_OCW2, 0x61); /* 通知PIC,说IRQ-01的受理已经完成 */
    data = io_get8(PORT_KEYDAT);
    struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;

    boxfill8(binfo->vram, binfo->scrnx, 0,0,0,binfo->scrnx, binfo->scrny);
    sprintf(s, "key = %d", data);
    putfonts8_asc(binfo->vram, binfo->scrnx, 8, 8, 7, s);

    return;
}

直接修改中断函数里面的代码即可,主要就是获取data然后输出

head.h

/*interrupt.c*/
#define PORT_KEYDAT 0x0060

这个是数据的地址,你要修改一下head.h,刚刚的那个函数要用的

 运行:

cd class05
..\z_tools\make.exe run

如果你发现你的键盘按一下就没用了可能是现在的键盘有点新,你可以把大写锁定打开,如果你不想这么麻烦,你可以自己买老键盘,最好2010之前的也可以买罗技k120这个型号的我就是这个试着没问题

还有我把main.c的输出那几句删了避免显示重叠

 

今天还没完呢,我还得讲一下fifo,first in first out,这个东西是用来缓存数据的,我刚刚给你们的键盘输入是不是还行,但是这个有个问题就是你按键盘的时候pic完全为键盘+屏幕输出服务,比如你用pic搞计时器,计时器会受影响,屏幕输出要花时间的pic等不起,或许你看不出来但是这对pic影响很大,所以我们要先把数据保存下来然后慢慢的输出,这时候pic就只负责保存数据到内存,不要显示。

fifo.c

#include "include/head.h"

void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf){
    fifo->size = size;
    fifo->buf = buf;
    fifo->free = size;
    fifo->flags = 0;
    fifo->p = 0; 
    fifo->q = 0;
    return;
}

int fifo8_put(struct FIFO8 *fifo, unsigned char data)
{
    if (fifo->free == 0) {
        fifo->flags |= FLAGS_OVERRUN;
        return -1;
    }
    fifo->buf[fifo->p] = data;
    fifo->p++;
    if (fifo->p == fifo->size) {
        fifo->p = 0;
    }
    fifo->free--;
    return 0;
}

int fifo8_get(struct FIFO8 *fifo){
    int data;
    if (fifo->free == fifo->size) {
        return -1;
    }
    data = fifo->buf[fifo->q];
    fifo->q++;
    if (fifo->q == fifo->size) {
        fifo->q = 0;
    }
    fifo->free++;
    return data;
}

int fifo8_status(struct FIFO8 *fifo){
    return fifo->size - fifo->free;
}

代码给你们直接用就是,我解释也解释不清,我乃cv工程师不需要知道原理

/*fifo.c*/
struct FIFO8 {
    unsigned char *buf;
    int p, q, size, free, flags;
};
#define FLAGS_OVERRUN    0x0001
void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf);
int fifo8_put(struct FIFO8 *fifo, unsigned char data);
int fifo8_get(struct FIFO8 *fifo);
int fifo8_status(struct FIFO8 *fifo);

这个添加到head.h里面去都是fifo要用的

/*naskfunc.asm*/
void io_stihlt();
void io_hlt(void);
void io_cli(void);
void io_sti(void);
int io_get8(int port);
void io_set8(int port, int data);
void write_mem8(int addr, int data);
int io_load_eflags(void);
void io_store_eflags(int eflags);

void load_gdtr(int limit, int addr);
void load_idtr(int limit, int addr);

void asm_inthandler21(void);

/* asmhead.nas */
struct BOOTINFO { /* 0x0ff0-0x0fff */
    char cyls; /* 启动区读磁盘读到此为止 */
    char leds; /* 启动时键盘的LED的状态 */
    char vmode; /* 显卡模式为多少位彩色 */
    char reserve;
    short scrnx, scrny; /* 画面分辨率 */
    char *vram;
};
#define ADR_BOOTINFO 0x00000ff0

/*graphic.c*/
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);
void putfont8(char *vram, int xsize, int x, int y, char c, char *font);
void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s);

/*font*/
extern char font[4096];

/* dsctbl.c */
struct SEGMENT_DESCRIPTOR {
    short limit_low, base_low;
    char base_mid, access_right;
    char limit_high, base_high;
};
struct GATE_DESCRIPTOR {
    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);
#define ADR_IDT            0x0026f800
#define LIMIT_IDT        0x000007ff
#define ADR_GDT            0x00270000
#define LIMIT_GDT        0x0000ffff
#define ADR_BOTPAK        0x00280000
#define LIMIT_BOTPAK    0x0007ffff
#define AR_DATA32_RW    0x4092
#define AR_CODE32_ER    0x409a
#define AR_INTGATE32    0x008e

/* pic.c */
void init_pic(void);
#define PIC0_ICW1        0x0020
#define PIC0_OCW2        0x0020
#define PIC0_IMR        0x0021
#define PIC0_ICW2        0x0021
#define PIC0_ICW3        0x0021
#define PIC0_ICW4        0x0021
#define PIC1_ICW1        0x00a0
#define PIC1_OCW2        0x00a0
#define PIC1_IMR        0x00a1
#define PIC1_ICW2        0x00a1
#define PIC1_ICW3        0x00a1
#define PIC1_ICW4        0x00a1

/*interrupt.c*/
#define PORT_KEYDAT 0x0060

void inthandler21(int *esp);

/*fifo.c*/
struct FIFO8 {
    unsigned char *buf;
    int p, q, size, free, flags;
};
#define FLAGS_OVERRUN    0x0001
void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf);
int fifo8_put(struct FIFO8 *fifo, unsigned char data);
int fifo8_get(struct FIFO8 *fifo);
int fifo8_status(struct FIFO8 *fifo);

加粗你懂吧,都是新加的,上面单独这句也要,之前说了,是键盘接收数据的地址

修改interrupt.c

#include "include/head.h"

struct FIFO8 keyfifo;

void inthandler21(int *esp)
/* 来自PS/2键盘的中断 */
{
    unsigned char data;
    io_set8(PIC0_OCW2, 0x61); /* 通知PIC,说IRQ-01的受理已经完成 */
    data = io_get8(PORT_KEYDAT);
    fifo8_put(&keyfifo, data);
    return;
}

就是保存数据了,fifo还要初始化,我们在main里面初始化,在main的死循环里面读取

main.c

#include "include/head.h"
#include <string.h>

struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
extern struct FIFO8 keyfifo;

void Main(void){
    int i;char s[256];
    char keybuf[256];

    init_gdtidt();
    init_pic();
    io_sti();
    fifo8_init(&keyfifo, 32, keybuf);

    init_palette();
    io_set8(PIC0_IMR, 0xf9); /* 开放PIC1和键盘中断(11111001) */

    for (;;) {
        io_hlt();
        if (fifo8_status(&keyfifo)== 0) {
            io_stihlt();
        } else {
            int i = fifo8_get(&keyfifo);
            io_sti();    
            if(i<129)
            {
                boxfill8(binfo->vram, binfo->scrnx, 0,0,0,binfo->scrnx, binfo->scrny);
                sprintf(s, "key = %d", i);
                putfonts8_asc(binfo->vram, binfo->scrnx, 8, 8, 7, s);
            }else{
                boxfill8(binfo->vram, binfo->scrnx, 0,0,0,binfo->scrnx, binfo->scrny);
                sprintf(s, "key = -");
                putfonts8_asc(binfo->vram, binfo->scrnx, 8, 8, 7, s);
            }
            
        }
    }
}

加粗懂我意思吧,最后修改Makefile就可以编译运行了

 运行:

cd class05
..\z_tools\make.exe run

 

 

  自制操作系统合集 原文地址:https://www.cnblogs.com/Frank-dev-blog/category/2249116.html 项目github地址rick521/My-OS (github.com)给我点颗star

 

标签:struct,int,My,void,0x07,fifo,char,OS,define
From: https://www.cnblogs.com/Frank-dev-blog/p/17161820.html

相关文章

  • MySQL 学习(三)索引有哪些缺点?
    任何事物都有其两面性,索引有优点,必定也会有缺点,那索引有什么缺点呢? 1、创建索引和维护索引要耗费时间就好比图书馆借书和还书都是需要图书管理员来的维护,如果长期没人管,图......
  • java.net.URL getHost因#@同时存在时优先级问题导致的SSRF
    #作为锚点,后面的会忽略;@作为登录信息,前面的会忽略对于java.net.URL取主机getHost()函数,当#@同时存在时,高版本#优先,取#前的;低版本@优先,取@后的。从而导致低版本(具体各......
  • DOS命令
    图形化操作的弊端:消耗内存运行速度慢命令行操作优点:不消耗内存运行速度快DOS命令行:按住win+R,在运行输入框中,输入cmd,敲回车默认C:\Users\86185>切换为其......
  • CF813E - Army Creation
    这道题的主流做法是主席树。考虑离线怎么做,首先是莫队,但是很明显莫队很难往在线扩展。那么考虑线段树。首先进行一些分析,我们可以对于每个\(a\),将第\(i\)个\(a\)和......
  • mysql报错 ERROR 1805 (HY000): Column count of mysql.user is wrong. Expected 45,
    ERROR1805(HY000):Columncountofmysql.useriswrong.Expected45,found43.Thetableisprobablycorrupted低版本mysql迁移到高版本出现的用户表错误解决办......
  • docker安装mysql
    前言:docker安装mysql前需要在系统安装docker环境,安装docker环境这里就不演示了,​​https://www.runoob.com/docker/centos-docker-install.html​​这里有centos安装docker......
  • SSM框架-MyBatis学习日记2
    在上一篇的日记中,我成功搭建了MyBatis的工作环境,至此只需要通过配置UserMapper和UserMapper.xml即可完成对数据库的增删查改工作。以下是UserMapper.xml中配置的部分:<?xm......
  • mysql数据库的级联复制
    今天分享的是mysql数据库中的级联复制,要想实现mysql的级联复制首先要进行建立主从复制,在其基础上增加新的主机。范例:实现级联复制需要在中间的从服务器启用以下配置,实现中......
  • Linux 中iostat 命令详解
    iostat命令详解iostat主要是统计磁盘活动情况。iostat有以下缺陷:iostat的输出结果大多数是一段时间内的平均值,因此难以反映峰值情况iostat仅能对系统整体情况进行分析......
  • 如何选择Python与C++之间的胶水:Boost.Python,Cython,pybind11,SWIG
    Python作为一门胶水语言,它与C/C++之间的兼容性(Interoperability)我认为是它相比其他动态语言脱颖而出的最大原因。Python原生支持的是与C语言的接口,Python的发行版自带有Pyt......