Я весь день пытался в этом разобраться. Я следую руководству по написанию загрузчика, и я застрял, когда дело доходит до правильного входа в защищенный режим. Я не знаю, что делаю не так, и весь день гуглил. Я компилирую с помощью NASM
Это результат, который я получаю в Bochs dbg:
Это говорит о том, что процессор действительно входит в защищенный режим, и вскоре после этого я получаю ошибки. Это вторая переписанная мною работа, направленная прежде всего на то, чтобы войти в защищенный режим без ошибок. Мне бы хотелось, чтобы кто-нибудь мог сказать мне, что я делаю неправильно.
Мой код выглядит следующим образом:
bootloader.asm
global _start
_start:
[bits 16]
[org 0x7c00]
mov bp, 0x8000
mov sp, bp
mov bx, welcomeString
call print_func
call print_newline_func
call switch_to_pm
jmp $
%include "io.asm"
%include "print.asm"
%include "gdt.asm"
welcomeString:
db 'Hello. Welcome to OS', 13, 10,0
switch_to_pm:
cli
lgdt [gdt_descriptor]
mov eax, cr0
or eax, 0x1
mov cr0, eax
[bits 32]
jmp CODE_SEG:init_pm
init_pm:
mov ax, DATA_SEG
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ebp, 0x90000
mov esp, ebp
call BEGIN_PM
BEGIN_PM:
mov ebx, MSG_PM
call print_string_pm
jmp $
MSG_PM:
db 'success', 0
times 510-($-$$) db 0
dw 0xaa55
io.asm
BOOT_DRIVE:
db 0
ReadDisk: ; Reads from drive dl amount of sectors to read dh
push dx ; Store dx to stack
mov ah, 0x02 ; BIOS read sector code
mov al, dh ; Read dh sectors
mov ch, 0x00 ; Select cyl 0
mov dh, 0x00 ; Select 1st track,
mov cl, 0x02 ; Select 2nd sector (1st after boot sector)
int 0x13 ; Read interrupt code
jc disk_error ; Jump if error
pop dx
cmp dh, al ; jump if sectors expected != sectors read
jne disk_error
ret
errorString:
db 'Disk Read Error.',13,10,0
disk_error:
mov bx, errorString
call print_func
ret
gdt.asm
gdt_start:
gdt_null: ; null descriptor
dd 0x0
dd 0x0
gdt_code: ; the code segment descriptor
; base =0x0 , limit =0 xfffff ,
; 1st flags : ( present )1 ( privilege )00 ( descriptor type )1 -> 1001 b
; type flags : ( code )1 ( conforming )0 ( readable )1 ( accessed )0 -> 1010 b
; 2nd flags : ( granularity )1 (32 - bit default )1 (64 - bit seg )0 ( AVL )0 -> 1100 b
dw 0xffff ; Limit (bits 0-15)
dw 0x0 ; Base (bits 0 - 15)
db 0x0 ; Base (bits 16 - 23)
db 10011010b ; 1st flags, type flags
db 11001111b ; 2nd flags, limit (bits 16-19)
db 0x0 ; Base (bits 24-31)
gdt_data: ; the data segment descriptor
; Same as code segment except for the type flags :
; type flags : ( code )0 ( expand down )0 ( writable )1 ( accessed )0 -> 0010 b
dw 0xffff ; Limit (bits 0-15)
dw 0x0 ; Base (bits 0-15)
db 0x0 ; Base (bits 16-23)
db 10010010b ; 1st flags, type flags
db 11001111b ; 2nd flags
db 0x0 ; Base (bits 24-31)
gdt_end: ; Put this label to calculate size of GDT
gdt_descriptor:
dw gdt_end - gdt_start - 1 ; GDT size, always 1 less than true size
dd gdt_start ; start address of GDT
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start
print.asm
print_func:
push bx
mov ah, 0x0e
;add bx, 0x7c00 ; calculate correct address
print_loop:
cmp byte [bx], 0 ; if char at bx == 0, jump to exit.
je print_exit
mov al, [bx] ; move char at bx into al
int 0x10 ; print
inc bx ; increment bx
jmp print_loop ; loop to start of func
print_exit:
pop bx
ret
print_newline_func:
push ax
mov ah, 0x0e
mov al, 10
int 0x10
mov al, 13
int 0x10
pop ax
ret
print_hex_func:
push ax
push bx
push cx
mov ah, 0x0e
mov al, '0'
int 0x10
mov al, 'x'
int 0x10 ; print 0x
;add bx, 0x7c00
mov cx, [bx]
shr cx, 12
call PrintAsciiFromHex
mov cx, [bx]
shr cx, 8
call PrintAsciiFromHex
mov cx, [bx]
shr cx, 4
call PrintAsciiFromHex
mov cx, [bx]
call PrintAsciiFromHex
pop ax
pop bx
pop cx
ret
PrintAsciiFromHex:
shl cx, 12
shr cx, 12
cmp cx, 9
jg Add55
add cx, 48
jmp Skip
Add55:
add cx, 55
Skip:
mov al, cl
int 0x10
ret
AddressPointer:
dw 0
PrintAddress: ; Moves address of bx into value of AddressPointer
mov [AddressPointer], bx ; Passes address of address pointer into bs
mov bx, AddressPointer ; prints value of address pointer, therefore printing address
call print_hex_func
ret
[bits 32]
; Define some constants
VIDEO_MEMORY equ 0xb8000
WHITE_ON_BLACK equ 0x0f
; prints a null - terminated string pointed to by EDX
print_string_pm:
pusha
mov edx, VIDEO_MEMORY ; Set edx to the start of vid mem.
print_string_pm_loop :
mov al , [ ebx ] ; Store the char at EBX in AL
mov ah , WHITE_ON_BLACK ; Store the attributes in AH
cmp al , 0 ; if (al == 0) , at end of string , so
je print_string_pm_done ; jump to done
mov [edx] , ax ; Store char and attributes at current
; character cell.
add ebx , 1 ; Increment EBX to the next char in string.
add edx , 2 ; Move to next character cell in vid mem.
jmp print_string_pm_loop ; loop around to print the next char.
print_string_pm_done :
popa
ret ; Return from the function