0x09_自制操作系统My-OS实现Timer

一般机器都会有一个计时器的设备,在一定时间内不断发送中断信号,我们接收这个中断信号搞一个timer++这就是计时器了

把class06改07

 

naskfunc.asm

; naskfunc
; TAB=4

[FORMAT "WCOFF"]                ; 制作目标文件的模式    
[INSTRSET "i486p"]                ; 使用到486为止的指令
[BITS 32]                        ; 3制作32位模式用的机器语言
[FILE "naskfunc.asm"]            ; 文件名
    GLOBAL _io_hlt,_write_mem8,_io_cli,_io_sti,_io_get8,_io_set8,_io_stihlt
    GLOBAL _io_load_eflags,_io_store_eflags,_asm_inthandler21
    GLOBAL _load_gdtr, _load_idtr,_load_cr0,_store_cr0
    GLOBAL _memtest_sub,_asm_inthandler20
    EXTERN _inthandler21,_inthandler20

[SECTION .text]

_io_hlt:    ; void io_hlt(void);
        HLT
        RET

_io_cli:    ; void io_cli(void);
        CLI
        RET

_io_sti:    ; void io_sti(void);
        STI
        RET

_io_get8:    ; int io_get8(int port);
        MOV        EDX,[ESP+4]        ; port
        MOV        EAX,0
        IN        AL,DX
        RET

_io_set8:    ; void io_set8(int port, int data);
        MOV        EDX,[ESP+4]        ; port
        MOV        AL,[ESP+8]        ; data
        OUT        DX,AL
        RET

_io_stihlt:    ; void io_stihlt(void);
        STI
        HLT
        RET

_write_mem8: ; void write_mem8(int addr, int data);
        MOV ECX,[ESP+4] ; taking content of add
        MOV AL,[ESP+8] ; taking content of data
        MOV [ECX],AL ; *ecx=al
        RET
_io_load_eflags:    ; int io_load_eflags(void);
        PUSHFD        ; PUSH EFLAGS 
        POP        EAX
        RET

_io_store_eflags:    ; void io_store_eflags(int eflags);
        MOV        EAX,[ESP+4]
        PUSH    EAX
        POPFD        ; POP EFLAGS 
        RET
_load_gdtr:        ; void load_gdtr(int limit, int addr);
        MOV        AX,[ESP+4]        ; limit
        MOV        [ESP+6],AX
        LGDT    [ESP+6]
        RET

_load_idtr:        ; void load_idtr(int limit, int addr);
        MOV        AX,[ESP+4]        ; limit
        MOV        [ESP+6],AX
        LIDT    [ESP+6]
        RET
_asm_inthandler21:
        PUSH    ES
        PUSH    DS
        PUSHAD
        MOV        EAX,ESP
        PUSH    EAX
        MOV        AX,SS
        MOV        DS,AX
        MOV        ES,AX
        CALL    _inthandler21
        POP        EAX
        POPAD
        POP        DS
        POP        ES
        IRETD
_memtest_sub: ; unsigned int memtest_sub(unsigned int start, unsigned int end)
        PUSH EDI ; (由于还要使用EBX, ESI, EDI)
        PUSH ESI
        PUSH EBX
        MOV ESI,0xaa55aa55 ; pat0 = 0xaa55aa55;
        MOV EDI,0x55aa55aa ; pat1 = 0x55aa55aa;
        MOV EAX,[ESP+12+4] ; i = start;
mts_loop:
        MOV EBX,EAX
        ADD EBX,0xffc ; p = i + 0xffc;
        MOV EDX,[EBX] ; old = *p;
        MOV [EBX],ESI ; *p = pat0;
        XOR DWORD [EBX],0xffffffff ; *p ^= 0xffffffff;
        CMP EDI,[EBX] ; if (*p != pat1) goto fin;
        JNE mts_fin
        XOR DWORD [EBX],0xffffffff ; *p ^= 0xffffffff;
        CMP ESI,[EBX] ; if (*p != pat0) goto fin;
        JNE mts_fin
        MOV [EBX],EDX ; *p = old;
        ADD EAX,0x1000 ; i += 0x1000;
        CMP EAX,[ESP+12+8] ; if (i <= end) goto mts_loop;
        JBE mts_loop
        POP EBX
        POP ESI
        POP EDI
        RET
mts_fin:
        MOV [EBX],EDX ; *p = old;
        POP EBX
        POP ESI
        POP EDI
        RET
_load_cr0:        ; int load_cr0(void);
        MOV        EAX,CR0
        RET
_store_cr0:        ; void store_cr0(int cr0);
        MOV        EAX,[ESP+4]
        MOV        CR0,EAX
        RET
_asm_inthandler20:
        PUSH ES
        PUSH DS
        PUSHAD
        MOV EAX,ESP
        PUSH EAX
        MOV AX,SS
        MOV DS,AX
        MOV ES,AX
        CALL _inthandler20
        POP EAX
        POPAD
        POP DS
        POP ES
        IRETD

head.h

/*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);
int load_cr0(void);
void store_cr0(int cr0);
void load_gdtr(int limit, int addr);
void load_idtr(int limit, int addr);
void asm_inthandler20(void);
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
unsigned int memtest_sub(unsigned int start, unsigned int end);

/*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);
void inthandler20(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);


//memory.c
#define MEMMAN_ADDR 0x003c0000
#define EFLAGS_AC_BIT 0x00040000
#define CR0_CACHE_DISABLE 0x60000000

#define MEMMAN_FREES 4090 /* 大约是32KB*/
struct FREEINFO { /* 可用信息 */
    unsigned int addr, size;
};
struct MEMMAN { /* 内存管理 */
    int frees, maxfrees, lostsize, losts;
    struct FREEINFO free[MEMMAN_FREES];
};
void memman_init(struct MEMMAN *man);
unsigned int memman_total(struct MEMMAN *man);
unsigned int memtest(unsigned int start, unsigned int end);
int memman_free(struct MEMMAN *man, unsigned int addr, unsigned int size);
unsigned int memman_alloc(struct MEMMAN *man, unsigned int size);
void memory();
unsigned int memman_alloc_4k(struct MEMMAN *man, unsigned int size);
int memman_free_4k(struct MEMMAN *man, unsigned int addr, unsigned int size);
/*timer.c*/
#define PIT_CTRL 0x0043
#define PIT_CNT0 0x0040
struct TIMERCTL {
    unsigned int count;
};

timer.c

#include "include/head.h"

struct TIMERCTL timerctl;

void init_pit(void)
{
    io_set8(PIT_CTRL, 0x34);
    io_set8(PIT_CNT0, 0x9c);
    io_set8(PIT_CNT0, 0x2e);
    timerctl.count = 0;
    
    return;
}

interupt.c

#include "include/head.h"

struct FIFO8 keyfifo;
extern struct TIMERCTL timerctl;

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;
}
void inthandler20(int *esp)
{
    io_set8(PIC0_OCW2, 0x60); /* 把IRQ-00信号接收完了的信息通知给PIC */
    /* 暂时什么也不做 */
    timerctl.count++;
    return;
}

注册idt

/* GDT、IDT、descriptor table 关系处理 */


#include "include/head.h"

void init_gdtidt(void)
{
    struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *) ADR_GDT;
    struct GATE_DESCRIPTOR    *idt = (struct GATE_DESCRIPTOR    *) ADR_IDT;
    int i;

    /* GDT初始化 */
    for (i = 0; i <= LIMIT_GDT / 8; i++) {
        set_segmdesc(gdt + i, 0, 0, 0);
    }
    set_segmdesc(gdt + 1, 0xffffffff,   0x00000000, AR_DATA32_RW);
    set_segmdesc(gdt + 2, LIMIT_BOTPAK, ADR_BOTPAK, AR_CODE32_ER);
    load_gdtr(LIMIT_GDT, ADR_GDT);

    /* IDT初始化 */
    for (i = 0; i <= LIMIT_IDT / 8; i++) {
        set_gatedesc(idt + i, 0, 0, 0);
    }
    load_idtr(LIMIT_IDT, ADR_IDT);

    /* IDT设置*/    
    set_gatedesc(idt + 0x21, (int) asm_inthandler21, 2 * 8, AR_INTGATE32);
    set_gatedesc(idt + 0x20, (int) asm_inthandler20, 2 * 8, AR_INTGATE32);

/* IDT的设定 */
    return;
}

void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar)
{
    if (limit > 0xfffff) {
        ar |= 0x8000; /* G_bit = 1 */
        limit /= 0x1000;
    }
    sd->limit_low    = limit & 0xffff;
    sd->base_low     = base & 0xffff;
    sd->base_mid     = (base >> 16) & 0xff;
    sd->access_right = ar & 0xff;
    sd->limit_high   = ((limit >> 16) & 0x0f) | ((ar >> 8) & 0xf0);
    sd->base_high    = (base >> 24) & 0xff;
    return;
}

void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar)
{
    gd->offset_low   = offset & 0xffff;
    gd->selector     = selector;
    gd->dw_count     = (ar >> 8) & 0xff;
    gd->access_right = ar & 0xff;
    gd->offset_high  = (offset >> 16) & 0xffff;
    return;
}

main.c

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

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

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

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

    init_palette();
    init_pit();

    io_set8(PIC0_IMR, 0xf8); /* 开放PIC1和键盘中断(11111001) */
 
    memory();
    for (;;) {
        io_hlt();
        boxfill8(binfo->vram, binfo->scrnx, 1,0,24,binfo->scrnx, 40);
        sprintf(s, "%010d", timerctl.count);
        putfonts8_asc(binfo->vram, binfo->scrnx, 24, 24, 7, s);
        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里面加入timer.obj

 

运行:

cd class07
..\z_tools\make.exe run

 

 

posted @ 2023-03-18 16:30  Z_Chan  阅读(21)  评论(0编辑  收藏  举报