assemblyx86nasmprotected-mode

Jump to Protected Mode is restarting QEMU


I have successfully written code for real mode. But the trouble started with 32-bit Protected Mode. Before jumping to Protected Mode, I have disabled interrupts using cli, loaded GDT using lgdt and set 32-bit mode bit in cr0. But QEMU is rebooting infinitely. Following are the codes

boot.asm:

[BITS 16]
            BOOTSEG equ 0x7c00
            DATASEG equ 0x07c0
            STACKSEG equ 0x17c0
            EXTRASEG equ 0x37c0
            STACKPOINT equ 0x0000

            BLACKONWHITE equ 0x0F
            YELLOWONBLUE equ 0x1E

            VIDEO_MEMORY equ 0xb8000

            global _start

_start:

            xor ax, ax

            mov ax, STACKSEG
            mov ss, ax              ;initializing stack segment
            mov sp, STACKPOINT
            
            mov ax, DATASEG
            mov ds, ax              ;initializing data segment

            mov ax, EXTRASEG
            mov es, ax               ;initializing extra segment

            call Switch_To_Pm

            %include "./screen.asm"
            %include "./lib.asm"
            %include "./gdt.asm"
            %include "./protected_mode/switch_to.asm"

[bits  32]

Begin_Pm:
            jmp $

            times 510 - ($ - $$) db 0

            dw 0xAA55

gdt.asm:

gdt_start:

null_descriptor:
                dd 0x0
                dd 0x0

code_descriptor:
                dw 0xffff
                dw 0x0
                db 0x0
                db 10011010b
                db 11001111b
                db 0x0

data_descriptor:
                dw 0xffff
                dw 0x0
                db 0x0
                db 10010010b
                db 11001111b
                db 0x0

gdt_end:

gdt_descriptor:
                dw gdt_end - gdt_start - 1
                dd gdt_start

CODE_SEG equ code_descriptor - gdt_start

DATA_SEG equ data_descriptor - gdt_start

protected_mode/switch_to.asm:

    [BITS 16]
Switch_To_Pm:
                cli
                lgdt [gdt_descriptor]
                mov eax , cr0
                or eax , 0x1
                mov cr0 ,eax
                jmp CODE_SEG:Init_Pm

[BITS 32]

Init_Pm:
                mov ax, DATA_SEG
                mov ds, ax
                mov ss, ax
                mov es, ax
                mov fs, ax
                mov gs, ax

                call Begin_Pm

lib.asm contains a delay routine using int 0x15 and screen.asm contains BIOS routines to print text in real mode.

Following are the commands I used to build

nasm -fbin -o boot.bin boot.asm
qemu boot.bin

Don't know why but QEMU is rebooting infinitely. Code till real mode worked well. Probably there is a problem with switching to Protected Mode.

Prior thanks to any help


Solution

  • I think I have identified where the problem is. The problem is with the line jmp CODE_SEG:Init_Pm in protected_mode/switch_to.asm. I should add an offset of 0x7c00 to the far jump.
    Instead I used [org 0x7c00] and rewrote both real mode and protected mode codes, it worked.