图
因为昨天实验图形模式使用C语言有很多问题,无奈之下,只好硬肯汇编了,所以多数代码在boot.s中用汇编实现的,至于c中的一堆代码当然是从别人的文章中摘抄的(呵呵这也算原创),图中是敲击键盘后显示的代码,后面多余的字符,也不知是怎么回事,今天太晚了,休息一会儿吧。
百度网盘下载地址:
https://pan.baidu.com/s/1_-IznMWL3z1CROziiD6mCw
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;
}
}
}
}