操作系统开发:切换到32位模式会破坏我的代码



edit:当我在32后移动所有内容时,我的问题解决了可能是原因?

(英语不好(你好,我试图为了娱乐而写一个简单的操作是否正常显示

没有工作
`> `
`>succesfully loaded  = if loaded succesfully > failed = if not `
`>Do you want to boot kernel mode Y/N       then gets input`
`>Booting in kernel mode = if Y   null = if no`

但是,在我添加了lgdt和其他切换到32位之后,它根本没有显示任何内容,所以我认为切换在某种程度上清除了屏幕,因此我尝试使用pm在pm中使用print_string_pm函数在PM中打印物品,但我仍然没有什么使用

nasm -fbin bootload.asm -o bootload.bin

编译引导程序

我的代码可能有什么问题,请帮助?

这是代码:

BITS 16
[ORG 0x7c00]
global _boot_start
_boot_start:
    cli
    mov bx,0x9000
    mov bp,bx
    mov sp,bx
    sti 
    pusha
    mov ax, 0x0000     
    mov ds, ax         
    mov es, ax
    popa
    mov [bootdev], dl

    mov bx, MSG_START       
    call print_string

    mov dl, [bootdev]             
    mov dh, 1             
    mov bx, 0x1000         
    call disk_load
    mov bx, MSG_YESNO
    call print_string
    call get_yes_no
    mov bx, MSG_BOOT_KERNEL
    call print_string

    lgdt [gdt_descriptor]
    mov eax , cr0 
    or eax , 0x1 
    mov cr0 , eax
    jmp CODE_SEG:pm
    BITS 32
    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 beg_pm
    beg_pm:
    mov ebx,MSG_BOOT_32
    call print_string_pm
    call KERNEL_OFFSET
    jmp $
;******************************************************************
print_string:       
.loop:
    mov al,[bx]
    cmp al,0
    je return
    push bx
    mov ah,0Eh
    int 10h
    pop bx
    inc bx
    jmp .loop
return:
    ret 
;******************************************************************
get_yes_no:
    pusha 
.loop:
    mov ah, 00h
    int 16h
    cmp ah, 15h
    je .yes
    cmp ah, 31h
    je .no
    jmp .loop
    ret
.no:
    mov bx, No
    call print_string
    mov ah, 00h
    int 13h 
    jmp $
.yes:   
    mov bx, Yes
    call print_string
    jmp .done
.done:
    popa
    ret 
;******************************************************************
disk_load:
    push dx
    mov ah, 02h    
    mov al, dh    
    mov ch, 0x00   
    mov dh, 0x00  
    mov cl, 0x02   
    int 0x13       
    pop dx
    jc disk_error 
    cmp dh, al 
    jne disk_error_double
    mov bx,MSG_LOAD_SUCC
    call print_string
    ret 
disk_error:
    mov bx,MSG_LOAD_FAIL 
    call print_string
    jmp $
disk_error_double:
    mov bx,MSG_LOAD_FAIL_C
    call print_string
    jmp $
;******************************************************************
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 
; Global Descriptor table
; GDT
gdt_start :
gdt_null : ; the mandatory null descriptor
dd 0x0 ; 'dd ' means define double word ( i.e. 4 bytes )
dd 0x0
gdt_code : 
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 : 
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 , Limit ( bits 16 -19)
db 0x0 ; Base ( bits 24 -31)
gdt_end : 
gdt_descriptor :
dw gdt_end - gdt_start - 1 
dd gdt_start 
CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start   


MSG_START DB ">",13,10,0
MSG_LOAD_SUCC DB "> Succesfully loaded",13,10,0
MSG_LOAD_FAIL DB "> Failed to load Please try to restart the system",13,10,0
MSG_LOAD_FAIL_C DB "> Error while loading",13,10,0
MSG_YESNO DB "> Do you want to boot up in kernel mode Y/N :",0
MSG_BOOT_KERNEL DB 13,10,"> Booting in kernel mode",0
MSG_BOOT_32 DB "32 bit pm",13,10,0
Yes db "Y",0
No db "N",0
bootdev: db 0
KERNEL_OFFSET equ 0x1000 
VIDEO_MEMORY equ 0xb8000
WHITE_ON_BLACK equ 0x0f
times 510-($-$$) db 0
dw 0xaa55

这是我的内核代码:

int kmain()
{

    char* vm = 0xb8000;
    *vm = 'X';

}

和我的内核条目

[BITS 32]
[extern _kmain]
call _kmain 
jmp $

我使用follwing线来构建我的磁盘图像:

nasm -fbin bootload.asm -o bootload.bin
gcc -ffreestanding -c kernel.c -o kernel.o
nasm kernel_entry.asm -f elf -o k_entry.o
ld -T NUL -o kernel.tmp -Ttext 0x1000 k_entry.o kernel.o
objcopy -O binary -j .text  kernel.tmp kernel.bin
copy /b bootload.bin+kernel.bin os-image.bin 

我将忽略没有SS和其他问题的SP的问题。请参阅问题下的评论,以清理代码。

您的主要问题是切换到使用bits 32编码的32位指令。将编码设置为32位后,将其编码为32位,直到更改为止(使用bits 16(。您可以做的最简单的事情是将标签pm的代码移至超过所有16位代码的点。移动所有这些行(删除原件(:

BITS 32
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 beg_pm
beg_pm:
mov ebx,MSG_BOOT_32
call print_string_pm
call KERNEL_OFFSET
jmp $

到您拥有的32位代码的开始。这似乎是print_string_pm标签。因此,当移动时看起来像:

    [snip]
disk_error_double:
    mov bx,MSG_LOAD_FAIL_C
    call print_string
    jmp $
    BITS 32
    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 beg_pm
    beg_pm:
    mov ebx,MSG_BOOT_32
    call print_string_pm
    call KERNEL_OFFSET
    jmp $
;******************************************************************
print_string_pm :
    pusha
    [snip]

disk_error_double的代码是您的16位代码中的最后一个,print_string_pm是32位代码的开始。我们只需将pm代码放在disk_error_double之后和print_string_pm之前。


进入受保护模式之前,您需要关闭中断,直到设置中断描述符表(IDT(。在mov cr0 , eax之前放置cli指令。如果在受保护模式下首次中断时,不执行此操作将导致三重故障并重新启动。

最新更新