##版本0.2 设置IDT,开启时钟中断
代码如下
kernel.asm
; nasm -f elf kernel.asm -o kernel.o
; ld -s -Ttext 0x10000 kernel.o -o kernel.bin
; dd if=kernel.bin of=a.img bs=512 seek=1 conv=notrunc
[section .text]
[bits 32]
global _start
_start:
mov ax, 16
mov ds, ax
mov es, ax
mov ss, ax
mov esp, 0x7c00
mov ax, 24
mov gs, ax
lidt [idtptr]
call print
call init8259a
sti
end:
jmp end
print:
mov edi, (80 * 11 + 79) * 2
mov ah, 0x0c
mov al, 'K'
mov [gs:edi], ax
ret
_clock:
clock equ _clock - $$ + 0x10000 ; 0x10000就是ld中的入口地址
inc byte [gs:((80 * 11 + 79) * 2)]
mov edi, (80 * 11 + 78) * 2
mov ah, 0x0c
mov al, 'I'
mov [gs:edi], ax
mov al, 0x20
out 0x20, al
iretd
init8259a:
mov al, 0x11
out 0x20, al
call io_delay
out 0xa0, al
call io_delay
mov al, 0x20
out 0x21, al
call io_delay
mov al, 0x28
out 0xa1, al
call io_delay
mov al, 0x04
out 0x21, al
call io_delay
mov al, 0x02
out 0xa1, al
call io_delay
mov al, 0x01
out 0x21, al
call io_delay
out 0xa1, al
call io_delay
mov al, 11111110b ;
out 0x21, al
call io_delay
mov al, 11111111b
out 0xa1, al
call io_delay
ret
io_delay:
nop
nop
nop
nop
ret
idt:
%rep 255
dw (clock & 0xffff)
dw 8
dw 0x8e00
dw (clock >> 16)
%endrep
idtlen equ $-idt
idtptr dw idtlen-1
dd idt
通过readelf -a kernel.bin, 可以知道.text的大小是0x8ac,4个多扇区,所以直接读入内存5个扇区。
bootsect.asm
; nasm bootsect.asm -o bootsect.bin
; dd if=bootsect.bin of=a.img bs=512 count=1 conv=notrunc
org 0x7c00
jmp start
gdt:
dw 0
dw 0
dw 0
dw 0
gdt_code: ; 基址为0,大小4GB的32位可执行代码段
dw 0xffff
dw 0x0000
dw 0x9a00
dw 0x00cf
gdt_data: ; 基址为0,大小4GB的32位可读写数据段
dw 0xffff
dw 0x0000
dw 0x9200
dw 0x00cf
gdt_video: ; 基址为0xb8000,大小64KB的可读写显存段
dw 0xffff
dw 0x8000
dw 0x920b
dw 0x0000
gdtlen equ $ - gdt
gdtptr dw gdtlen -1
dd gdt
start:
; 利用0x13号BIOS中断,将软盘kernel.bin中的.text读入内存0x1000:0x0000(实模式)。
mov ax, 0x1000
mov es, ax
mov bx, 0
mov ax, 0x0205 ; 读入5个扇区
mov cx, 0x000a
mov dx, 0
int 0x13
into_kernel:
; 加载GDT
lgdt [gdtptr]
; 关中断
cli
; 开启A20线
in al, 0x92
or al, 00000010b
out 0x92, al
; 打开保护模式
mov eax, cr0
or eax, 1
mov cr0, eax
; 进入保护模式
jmp dword 0x8:0x10000 ; 0x8, 可执行代码段gdt_code
fill:
times 510-($ - $$) db 0
dw 0xaa55