Невозможно переключиться из реального режима в защищенный в загрузчике x86 - PullRequest
1 голос
/ 27 мая 2020

Я создаю загрузчик со ссылкой на this

У меня есть две проблемы относительно этого.

  1. Когда я запускаю код на qemu, он никогда не переходит к функции switch_to_pm.

  2. Когда я добавляю '.include load.s 'в файле main.s, то он застревает в ljmp.

Может ли кто-нибудь дать мне какие-то указания по этому поводу?

main.s

section .data
MSG_PROT:
        .asciz "Protected mode"

.section .text
.global start16
start16:
        mov $0x9000, %bp
        mov %bp, %sp

        mov $'C', %al
        mov $0x0E, %ah
        int $0x10

        call switch_to_pm


.code32
.type BEGIN_PM, @function
.global BEGIN_PM
BEGIN_PM:

        lea MSG_PROT, %ebx
        #call print_string_pm

        . = start16 + 510
        .word 0xaa55

load.s

.section .data
        .include "gdt.S"

.section .text
.code16
.type switch_to_pm, @function
.global switch_to_pm
switch_to_pm:

        mov $'Z', %al
        mov $0x0E, %ah
        int $0x10

        cli
        lgdt (gdt_descriptor)
        mov %cr0, %eax
        or $0x01, %eax
        mov %eax, %cr0
        ljmp $CODE_SEG, $init_pm


.code32
init_pm:
        lea DATA_SEG, %ax
        mov %ax, %ds
        mov %ax, %ss
        mov %ax, %es
        mov %ax, %fs
        mov %ax, %gs

        mov $0x90000, %ebp
        mov %ebp, %esp
        call BEGIN_PM

gdt.S


gdt_start:
    .double 0x00000000
    .double 0x00000000

gdt_code:
    .word 0xffff        #segment length or limit 00 -15
    .word 0x0000        #segment base 00 - 15
    .byte 0x00      #segment base 16 - 23
    .byte 0b10011010    # flags (8 bit)
                #   Type : lower 4 bit
                #       from upper (11th bit) to lower (8th bit) in upper byte
                #       1. code : 1 for code segment, since it is code segment
                #       2. conforming : 0 , by not conforming means code in a segment with a lower privilege may not                    #        call code , key to memory protection
                #       3. Readable: 1, if readable , 0 for executable
                #       4. accessed : 0, this is often used for debugging and virtual memory techniques.

                 #  upper 4 bit ( from 15th bit to 11th bit)
                #       1. present : 1 , since segment is present in the memory - used for virtual memory
                #       2. DPL (privilige) : 0, ring 0 represent highestt privilige( occupies 2 bit)
                #       3. Descriptor : 1 for code segment , 0 for data segment

    .byte 0b11001111    # flags (8 bit)
                #   from 16th bit to 23 bit
                #       1. lower 4 bit represent segment limit.
                #       2.  AVL : used for debugging. set it 0
                #       3.  L: set it for 64 bit. 0 , for 32 bit segment
                #       4.  D/b (default operation) : 1, for 32 bit operation, 0 for 16 bit operation
                #       5.  Granularity: 1, if set , this multiplies our limit by 4k, so 0xffff becomes 0xffff000, allowing segment to span 4 gb of memory 
    .byte 0x00


gdt_data:
    .word 0xffff
    .word 0x0000
    .byte 0x00
    .byte 0b10010010
    .byte 0b11001111
    .byte 0x00
gdt_end:

gdt_descriptor:
    .word gdt_end - gdt_start - 1
    .long gdt_start

.equ CODE_SEG, gdt_code - gdt_start
.equ DATA_SEG, gdt_data - gdt_start
...