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