操做系統:32位ubuntu 彙編編譯器:nasm 虛擬機: bochsubuntu
; 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 文件編譯後,做爲軟盤的引導扇區。ide
; 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