org 0x7c00
BOOTDRIVE equ 0x9000
flatcode equ 0x0008
flatdata equ 0x0010
flatstack equ 0x0010
[bits 16]
section .text
bspstart:
xor ax,ax ;some BIOS required
mov ds,ax
mov byte [BOOTDRIVE],dl
mov ax,0x8000
mov ss,ax
mov sp,0
mov cx,2000 ;80x25*2
xor si,si
mov di,1
mov ax,0xb800
mov ds,ax
cleanscreen:
mov byte [ds:si],0x0
add si,2
mov byte [ds:di],0xf
add di,2
loop cleanscreen
xor ax,ax
mov ds,ax ;restore ax to load GDTR
Read_Disk_INT0x13: ;Read/Write Harddisk/Floppy provided by BIOS INT 0x13 ;cannot use in 32bits mode and 64bits mode
mov ah,0x2 ;function ID 0x2 read_sector; 0x3 write_sector
mov al,0x2 ;count of read/write sector
mov ch,0x0 ;location(cylider)
mov dh,0x0 ;location()
mov cl,0x2 ;location(sector)
mov byte dl,[BOOTDRIVE] ;type of drive(0x0~0x7f floppy drive;0x80~0xff hard drive)
mov bx,0x0
mov es,bx ;es:bx target memory area
mov bx,0x7e00
int 13h
cli ;after int 0x13 inst execute, the IF bit was enabled. we must to disable it.
jc Read_Disk_Error
Read_Disk_OK:
lgdt [GDT_PROP]
in al,0x92
or al,2
out 0x92,al
mov eax,0x1
mov cr0,eax
jmp dword flatcode:bsp_protected_mode_init_segreg
[bits 32]
bsp_protected_mode_init_segreg:
mov ax,flatdata
mov ds,ax
mov ax,flatstack
mov ss,ax
mov esp,0x00200000
loadpage:
mov eax,flatdata
mov ds,eax
mov es,eax
mov esi,temp_pt
mov edi,0x00100000
mov ecx,temp_pt_end - temp_pt
cld
rep movsb
mov esi,temp_pdt
mov edi,0x00101000
mov ecx,temp_pdt_end - temp_pdt
cld
rep movsb
mov esi,temp_pdpt
mov edi,0x00102000
mov ecx,temp_pdpt_end - temp_pdpt
cld
rep movsb
mov esi,temp_pml4
mov edi,0x00103000
mov ecx,temp_pml4_end - temp_pml4
cld
rep movsb
bsp_init_long_mode:
call checkcpuid
call checkia32e
mov ax,flatdata
mov ds,ax
mov eax,0x20
mov cr4,eax
mov eax,0x00103000 ;pml4
mov cr3,eax
mov ecx,0xc0000080
rdmsr
or eax,1 << 8
wrmsr
cli
mov eax,0x80000001
mov cr0,eax
jmp dword flatcode:bsp_long_mode
temp_pt:
dq 0x00000000000b8001
dq 0x00000000000b8001
dq 0x0000000000000001
dq 0x0000000000000001
dq 0x0000000000000001
dq 0x0000000000000001
dq 0x0000000000104001 ;stack at 0x00104000
dq 0x0000000000007001 ;bootloader
temp_pt_end:
temp_pdt:
dq 0x0000000000100001
temp_pdt_end:
temp_pdpt:
dq 0x0000000000101001
temp_pdpt_end:
temp_pml4:
dq 0x0000000000102001
temp_pml4_end:
GDT_PROP:
dw GDT_TABLE_32_END - GDT_TABLE_ENTRY_32 - 1
dd GDT_TABLE_ENTRY_32
GDT_TABLE_ENTRY_32:
dq 0x0000000000000000 ;Empty Entry
dq 0x00cf9a000000ffff ;code
dq 0x00cf92000000ffff ;data&stack
GDT_TABLE_32_END:
GDT_PROP_64:
dw GDT_TABLE_64_END - GDT_TABLE_ENTRY_64 - 1
dq GDT_TABLE_ENTRY_64
GDT_TABLE_ENTRY_64:
dq 0x0000000000000000
dq 0x00af9a000000ffff
dq 0x00af92000000ffff
GDT_TABLE_64_END:
[bits 16]
BIOS_13H_ERROR:
db 'PizzaLoader:(0x0) Disk Error! System Halted.'
Read_Disk_Error:
mov ax,0x0
mov ds,ax
xor si,si
mov bx,BIOS_13H_ERROR
mov cx,44
Print_Disk_Error:
mov dx,0x0
mov ds,dx
mov byte al,[ds:bx] ;read BIOS_13H_ERROR
add bx,1
mov dx,0xb800
mov ds,dx
mov byte [ds:si],al ;write 0xb8000
add si,2
loop Print_Disk_Error
jmp cpuhlt
cpuhlt:
hlt
times 510 - ($ - $$) db 0x0
db 0x55, 0xaa
[bits 32]
NO_CPUID_ERROR:
db 'PizzaLoader:(0x1)The Processor does not support CPUID instruction, System Halted.'
checkcpuid:
pushfd
pop eax
mov ecx,eax
xor eax,1<<21
push eax
popfd
pushfd
pop eax
push ecx
popfd
xor eax,ecx
jz nocpuid
ret
nocpuid:
mov ax,flatdata
mov ds,ax
mov esi,0x000b8000
mov ebx,NO_CPUID_ERROR
mov ecx,81
Print_no_CPUID_Error:
mov byte al,[ebx] ;read NO_CPUID_ERROR
add ebx,1
mov byte [esi],al ;write 0xb8000
add esi,2
loop Print_no_CPUID_Error
hlt
NO_IA32E_ERROR:
db 'PizzaLoader:(0x2)The Processor does not support 64-bits mode, System Halted.'
checkia32e:
mov eax, 0x80000000 ; Set the A-register to 0x80000000.
cpuid ; CPU identification.
cmp eax, 0x80000001 ; Compare the A-register with 0x80000001.
jb noia32e ; It is less, there is no long mode.
ret
noia32e:
mov ax,flatdata
mov ds,ax
mov esi,0x000b8000
mov ebx,NO_IA32E_ERROR
mov ecx,76
Print_no_IA32E_Error:
mov byte al,[ebx] ;read NO_CPUID_ERROR
add ebx,1
mov byte [esi],al ;write 0xb8000
add esi,2
loop Print_no_IA32E_Error
hlt
[bits 64]
bsp_long_mode:
lgdt [GDT_PROP_64]
mov rax,flatdata
mov ds,rax
mov ss,rax
mov sp,0x00006000
call Load_Kernel
hlt
Load_Kernel:
mov rsi,0x00000000
mov rbx,loading_kernel_Message
mov rcx,21
Print_Loading_Kernel_Message:
mov byte al,[rbx] ;read message
add rbx,1
mov byte [rsi],al ;write 0x000b8000
add rsi,2
loop Print_Loading_Kernel_Message
ret
loading_kernel_Message:
db 'Loading Mio Kernel...'
[bits 64]
restart:
mov dx,0xcf9
mov al,0xe
out dx,al
这是我的完整代码,运行结果如下:
Kn’chmf?Lhn?Jdqmdk———
文本输出的 ASCII 代码比应有的低 1,因此在字母表中比应有的早 1 个字母。应为“正在加载...”