开发环境
操作系统:32位ubuntu 汇编编译器:nasm 虚拟机: bochs
版本0.1
代码如下
; 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
[bits 32]
[section .text]
global _start
_start:
mov ax, 24
mov gs, ax
mov edi, (80 * 11 + 79) * 2
mov ah, 0x0c
mov al, 'K'
mov [gs:edi], ax
end:
hlt
jmp end
通过readelf -a kernel.bin命令,可以得到代码在文件kernel.bin中的偏移量。 本例编译后为0x1000, 将它除以扇区大小(512),得到8,因为kernel.bin在引导扇区后面,还要加一。 所以代码在第十个扇区。 bootsec.asm 文件编译后,作为软盘的引导扇区。
; nasm bootsec.asm -o bootsec.bin
; dd if=bootsec.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:
dw 0xffff
dw 0x0000
dw 0x9a00
dw 0x00cf
gdt_data:
dw 0xffff
dw 0x0000
dw 0x92c0
dw 0x00cf
gdt_video:
dw 0xffff
dw 0x8000
dw 0x920b
dw 0x0000
gdtlen equ $ - gdt
gdtptr dw gdtlen -1
dd 0
; 使用0x13中断,将软盘的第十个扇区读入内存0x10000处。
start:
mov ax, 0x1000
mov es, ax
mov bx, 0
mov ax, 0x0201
mov cx, 0x000a
mov dx, 0
int 0x13
into_kernel:
xor eax, eax
mov ax, cs
shl eax, 4
add eax, gdt
mov dword [gdtptr + 2], eax
lgdt [gdtptr]
cli
in al, 0x92
or al, 00000010b
out 0x92, al
mov eax, cr0
or eax, 1
mov cr0, eax
jmp dword 0x8:0x10000
fill:
times 510-($ - $$) db 0
dw 0xaa55
下面代码中,9200写成92c0,结果在加载IDT的时候,死活加载不上,坑了两天。
gdt_data:
dw 0xffff
dw 0x0000
dw 0x92c0
dw 0x00cf