0

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

kumarp
  • 135
  • 3
  • 11
  • 1
    The reboot maybe caused by a triple fault. Does Qemu have a way to log all faults? – prl Jul 12 '21 at 08:20
  • You might want to load esp before the call. I'm not sure whether the upper bits of esp are guaranteed to be zero. – prl Jul 12 '21 at 08:34
  • Are you sure Qemu loads your code at 7c00? – prl Jul 12 '21 at 08:35
  • @prl I did **qemu boot.bin -D ./log.txt**. But qemu did not log anything in the file – kumarp Jul 12 '21 at 09:35
  • 1
    Try running qemu with the following options: ```-d int -no-reboot -no-shutdown``` (and ```-D``` if you want to log to a file). That should tell you which exception(s) occurred, and it will stop after the first triple fault instead of rebooting endlessly. – sj95126 Jul 12 '21 at 16:39
  • @sj95126 **check_exception old: 0x8 new 0xd** is the last output on the command prompt. What does it mean? Any idea? – kumarp Jul 12 '21 at 16:42

1 Answers1

2

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.

kumarp
  • 135
  • 3
  • 11