虽然不是在图形模式下,但成功初始化gdt, idt,且开启了键盘中断,代码及其结构依然很糟糕了,不过还是有点小兴奋,庆幸今天没白努力!

因为昨天实验图形模式使用C语言有很多问题,无奈之下,只好硬肯汇编了,所以多数代码在boot.s中用汇编实现的,至于c中的一堆代码当然是从别人的文章中摘抄的(呵呵这也算原创),图中是敲击键盘后显示的代码,后面多余的字符,也不知是怎么回事,今天太晚了,休息一会儿吧。

boot.s

bits 32

global _start, _imgic, _addr
extern _kernel_main, _printf

_start:
    jmp begin
align 8
header_start:
    dd 0xe85250d6
    dd 0x0
    dd header_end - header_start
    dd - (0xe85250d6 + 0x0 + (header_end - header_start))
    
add_tag_start:
    dw 0x2
    dw 0x0
    dd add_tag_end - add_tag_start
    dd header_start
    dd _start
    dd 0x0
    dd 0x0
add_tag_end:

entry_add_tag_start:
    dw 0x3
    dw 0x1
    dd entry_add_tag_end - entry_add_tag_start
    dd begin
entry_add_tag_end:
align 8

;framebuffer_tag_start:
;    dw 0x5
;    dw 0x1
;    dd framebuffer_tag_end - framebuffer_tag_start
;    dd 1024
;    dd 768
;    dd 32
;framebuffer_tag_end:
align 8

    dw 0x0
    dw 0x0
    dd 0x8
header_end:
align 8

begin:
    mov esp, my_stack
    push 0
    popf
    
    mov [_imgic], eax
    mov [_addr], ebx
    
    mov al, 0xff
    out 0x21, al
    nop
    out 0xa1, al
    nop
    
    
    cli
    lidt [idtr]
    lgdt [gdtr]
    

    mov eax, 0x8
    mov ds, eax
    mov es, eax
    mov fs, eax
    mov gs, eax
    mov ss, eax
    mov esp, my_stack
    
    mov eax, [_imgic]
    mov ebx, [_addr]
    
    jmp dword 0x10 : mystart
mystart:

    call setup_idt
    call setup_key
    call setup_mouse
    
    call init_pic
    call open_key_mouse

    sti
    push dword [_addr]
    push dword [_imgic]
    call _kernel_main
    
times 0x400 dd 0
my_stack:


str0: db "ignore_int!"
str1: db "key_interrupt!"
str2: db "mouse!"

_imgic: dd 0
_addr: dd 0

gdtr:
    dw gdt_end - gdt_start - 1
    dd gdt_start

idtr:
    dw 256 * 8 - 1
    dd idt_start

align 8
idt_start:
    times 256 dq 0
    
gdt_start:
    dq 0x0000000000000000 ;0
    dq 0x00c0920000000fff ;0x8
    dq 0x00c09a0000000fff ;0x10
    dq 0x00c0920b8000000f ;0x18
gdt_end:

align 8
ignore_int:
    push ds
    push es
    push fs
    push gs
    pushad
    push str0
    call _printf
    add esp, 4
    popad
    pop gs
    pop fs
    pop es
    pop ds
    iret
    
key_interrupt:
    push ds
    push es
    push fs
    push gs
    pushad
    push str1
    call _printf
    add esp, 4
    popad
    pop gs
    pop fs
    pop es
    pop ds
    iret
    
mouse_interrupt:
    push ds
    push es
    push fs
    push gs
    pushad
    push str2
    call _printf
    add esp, 4
    popad
    pop gs
    pop fs
    pop es
    pop ds
    iret
    
setup_idt:
    lea edx, [ignore_int]
    mov eax, 0x100000
    mov ax, dx
    mov dx, 0x8e00
    lea edi, [idt_start]
    mov ecx, 256
rp_sidt:
    mov [edi], eax
    mov [edi + 4], edx
    add edi, 8
    dec ecx
    jne rp_sidt
    ret


setup_key:
    lea edx, [key_interrupt]
    mov eax, 0x100000
    mov ax, dx
    mov dx, 0x8e00
    mov ecx, 0x21
    lea esi, [idt_start + ecx * 8]
    mov [esi], eax
    mov [esi + 4], edx
    ret
    
setup_mouse:
    lea edx, [mouse_interrupt]
    mov eax, 0x100000
    mov ax, dx
    mov dx, 0x8e00
    mov ecx, 0x2c
    lea esi, [idt_start + ecx * 8]
    mov [esi], eax
    mov [esi + 4], edx
    ret
    
init_pic:
    mov al, 0x11
    out 0x20, al
    nop
    out 0xa0, al
    nop
    mov al, 0x20
    out 0x21, al
    nop
    mov al, 0x28
    out 0xa1, al
    nop
    mov al, 0x4
    out 0x21, al
    nop
    mov al, 0x2
    out 0xa1, al
    nop
    mov al, 0x1
    out 0x21, al
    nop
    out 0xa1, al
    nop
    mov al, 0xff
    out 0x21, al
    nop
    out 0xa1, al
    nop
    ret

open_key_mouse:
    mov al, 0xf9
    out 0x21, al
    nop
    mov al, 0xff
    out 0xa1, al
;    mov al, 0xef
;    out 0xa1, al
    nop
    ret
    

    

kernel.c

#include "multiboot2.h"

#define COLUMNS 80
#define LINES 24
#define ATTRIBUTE 7
#define VIDEO 0xB8000

extern int image;
extern int addr;

static int xpos;
static int ypos;
static volatile unsigned char *video;

static void cls (void);
static void itoa (char *buf, int base, int d);
static void putchar (int c);
void printf (const char *format, ...);

int kernel_main (unsigned int eax, unsigned int ebx) {
    cls();
    printf("eax = 0x%x   ", eax);
    printf("ebx = 0x%x   ", ebx);
    printf("\n");

    while (1) {
        
    }
    return 1;
}

/*  Clear the screen and initialize VIDEO, XPOS and YPOS. */
     static void
     cls (void)
     {
       int i;
     
       video = (unsigned char *) VIDEO;
     
       for (i = 0; i < COLUMNS * LINES * 2; i++)
         *(video + i) = 0;
     
       xpos = 0;
       ypos = 0;
     }
     
     /*  Convert the integer D to a string and save the string in BUF. If
        BASE is equal to 'd', interpret that D is decimal, and if BASE is
        equal to 'x', interpret that D is hexadecimal. */
     static void
     itoa (char *buf, int base, int d)
     {
       char *p = buf;
       char *p1, *p2;
       unsigned long ud = d;
       int divisor = 10;
     
       /*  If %d is specified and D is minus, put `-' in the head. */
       if (base == 'd' && d < 0)
         {
           *p++ = '-';
           buf++;
           ud = -d;
         }
       else if (base == 'x')
         divisor = 16;
     
       /*  Divide UD by DIVISOR until UD == 0. */
       do
         {
           int remainder = ud % divisor;
     
           *p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
         }
       while (ud /= divisor);
     
       /*  Terminate BUF. */
       *p = 0;
     
       /*  Reverse BUF. */
       p1 = buf;
       p2 = p - 1;
       while (p1 < p2)
         {
           char tmp = *p1;
           *p1 = *p2;
           *p2 = tmp;
           p1++;
           p2--;
         }
     }
     
     /*  Put the character C on the screen. */
     static void
     putchar (int c)
     {
       if (c == '\n' || c == '\r')
         {
         newline:
           xpos = 0;
           ypos++;
           if (ypos >= LINES)
             ypos = 0;
           return;
         }
     
       *(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
       *(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE;
     
       xpos++;
       if (xpos >= COLUMNS)
         goto newline;
     }
     
     /*  Format a string and print it on the screen, just like the libc
        function printf. */
     void
     printf (const char *format, ...)
     {
       char **arg = (char **) &format;
       int c;
       char buf[20];
     
       arg++;
     
       while ((c = *format++) != 0)
         {
           if (c != '%')
             putchar (c);
           else
             {
               char *p, *p2;
               int pad0 = 0, pad = 0;
     
               c = *format++;
               if (c == '0')
                 {
                   pad0 = 1;
                   c = *format++;
                 }
     
               if (c >= '0' && c <= '9')
                 {
                   pad = c - '0';
                   c = *format++;
                 }
     
               switch (c)
                 {
                 case 'd':
                 case 'u':
                 case 'x':
                   itoa (buf, c, *((int *) arg++));
                   p = buf;
                   goto string;
                   break;
     
                 case 's':
                   p = *arg++;
                   if (! p)
                     p = "(null)";
     
                 string:
                   for (p2 = p; *p2; p2++);
                   for (; p2 < p + pad; p2++)
                     putchar (pad0 ? '0' : ' ');
                   while (*p)
                     putchar (*p++);
                   break;
     
                 default:
                   putchar (*((int *) arg++));
                   break;
                 }
             }
         }
     }
 

猜你喜欢

转载自blog.csdn.net/weixin_39410618/article/details/81712938