Fault when attempting to jmp after entering protected mode - assembly bootloader

Viewed 54

I've been trying all day to figure this out. I'm following a tutorial on writing a bootloader and I'm stuck when it comes to entering protected mode properly. I don't know what I'm doing wrong and I've been googling all day. I'm compiling using NASM

This is the output I get in Bochs dbg:

enter image description here

It is saying that the CPU is indeed entering protected mode, and I am getting errors shortly after that. This is the second re-writing of this i've done, aiming primarily to get in to protected mode without errors. I'd love if anyone could tell me what I'm doing wrong.

My code is as follows:

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
1 Answers

Solved by returning to [bits 16] after the 32 bit function in print.asm and moving jmp to above the change to [bits 32]

Related