Home > Software design >  Failing to write to video memory in 32 bit mode
Failing to write to video memory in 32 bit mode

Time:04-24

I have been researching and writing a bootloader. In order to switch to 32 bit mode I used this tutorial: https://www.youtube.com/watch?v=pXzortxPZR8&list=PLxN4E629pPnKKqYsNVXpmCza8l0Jb6l8-&index=4

It says to write to video memory you can use

mov [0xb8000], byte 'A'

This does not actually write anything. I know the code is successflly beinbg loaded by the stage 1 bootloader as the nextStage text is being written to the screen whilst it's still in 16 bit mode. Is this error because of my code to write to memory or am I not successfully switching to 32 bit mode in the first place?

[bits 16]
[org 0x7e00]

mov bx, nextStage
call print

;Enable A20 bit, allowing memory > 1Mib
in al, 0x92
or al, 2
out 0x92, al

;GDT = Global Descriptor Table
;Defines memory layout
;Works with sections of memory, we need 3

;Required for some weird reason
GDTNullSeg:
    dd 0x0
    dd 0x0

;Defines segment for storing code
GDTCodeSeg:
    dw 0xFFFF       ;Limit
    dw 0x0000       ;Base (low)
    db 0x00         ;Base (medium)
    db 0b10011010   ;Flags
    db 0b11001111   ;Flags   Upper Limit
    db 0x00         ;Base (high)

;Defines segment for storing data
GDTDataSeg:
    dw 0xFFFF
    dw 0x0000
    db 0x00
    db 0b10010010
    db 0b11001111
    db 0x00

;This is how code and data are seperated so they can be stored in the same place in a von neumnan architecture

GDTEnd:

;What is passed to CPU register when GDT is passed, describes GDT
descriptorGDT:
    GDTSize:
        ;GDT size
        dw GDTEnd - GDTNullSeg - 1
        ;GDT address
        dd GDTNullSeg

GDTCodeSegSize equ GDTCodeSeg - GDTNullSeg
GDTDataSegSize equ GDTDataSeg - GDTNullSeg

cli
lgdt [descriptorGDT]
mov eax, cr0
or eax, 1
mov cr0, eax
;Far jump, GDTCodeSeg is the segment to jump too, startProtectedMode is the offset (location to jump to in that segment)
;Needed to flush cpu pipelines as if we are changing mode while unknown things are happerning it could lead to unexpected results
jmp GDTCodeSeg:startProtectedMode

jmp $

%include "src/print.asm"

nextStage: db "Successfully entered 2nd stage bootloader.", 0

[bits 32]
startProtectedMode:
    ;Before anything else we need to point segment registers to new data defined in GDT
    mov ax, GDTDataSeg
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    ;Redefine stack pointer to larger value now we have 4GiB of memory to work with
    mov ebp, 0x90000
    mov esp, ebp

    mov al, 'A'
    mov ax, 0x0F
    mov [0xb8000], ax

    jmp $

times 512-($-$$) db 0

EDIT: As per Sep Rolands answer I have moved the GDT definition and changed the writing to video memory code leading to:

---

jmp $

%include "src/print.asm"
%include "src/GDT.asm"

stage2Info: db 0xA, 0xD, "Successfully entered stage 2 bootloader.", 0

---

    ;mov esp, ebp

    mov ax, 0x0F41
    mov [0xb8000], ax

    jmp $

---

However this causes a boot loop.

CodePudding user response:

Once your code has printed the nextStage message and has enabled A20, execution falls through in the GDT data! Results are unpredictable.
Either put those data items elsewhere, or insert a jmp to that cli instruction.

Correct code:

mov ax, 0x0F41   ; BrightWhiteOnBlack 'A'
mov [0xb8000], ax

CodePudding user response:

The jmp instruction to 32 bit mode was incorrect:

jmp GDTCodeSeg:startProtectedMode

Should be:

jmp GDTCodeSegSize:startProtectedMode

Also this similar issue:

mov ax, GDTDataSeg

Should be:

mov ax, GDTDataSegSize
  • Related