开发环境
操作系统: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], axend: 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=notruncorg 0x7c00jmp startgdt: dw 0 dw 0 dw 0 dw 0gdt_code: dw 0xffff dw 0x0000 dw 0x9a00 dw 0x00cfgdt_data: dw 0xffff dw 0x0000 dw 0x92c0 dw 0x00cfgdt_video: dw 0xffff dw 0x8000 dw 0x920b dw 0x0000gdtlen equ $ - gdtgdtptr 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 0x13into_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:0x10000fill: times 510-($ - $$) db 0 dw 0xaa55
下面代码中,9200写成92c0,结果在加载IDT的时候,死活加载不上,坑了两天。
gdt_data: dw 0xffff dw 0x0000 dw 0x92c0 dw 0x00cf