I have need to make a very small bootable x86 program (needs to fit in ~12kB). I faired very well in the emulators, both QEMU and BOCHS had no problem with anything I was doing. However, when I went and put it on a pen drive, the code chirps along happily until it enters protected mode on CR0. I can verify that by the characters it prints to the screen.
It does this on two different systems I've checked. All real systems don't work, QEMU and BOCHS don't even give me warnings.
About the only thing I figure I might be doing wrong is I only set up a GDT, and it's flat.
This doesn't seem to be a problem I can find anyone else having :-/
Code: Select all
/*
Copyright 2009 Charles Lohr under the MIT/X11 License.
This code is a bootloader and switches to flat 4G code, 4G data protected mode.
It then calls C code.
*/
//Useful article: http://thiscouldbebetter.wordpress.com/2011/03/17/entering-protected-mode-from-assembly
.code16
.global loader
//Code runs from 0x7c00
.align 4
.org 0x00
bootstart:
//Configure the stack
mov $0xc000, %sp
//Configure the segments
mov $0x0000, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
//First, preserve drive letter.
push %dx
//Print out the letter 1, so we know it's working.
mov $0x0e31, %ax
mov $0x00, %bx
int $0x10
**EDIT (but no change)**
//Enable a20
mov $0x2401, %ax
int $0x15
//Verify a20 was set.
mov %ah, %al
mov $0x0e, %ah
add $0x30, %al
mov $0x00, %ebx
int $0x10
**END EDIT**
//Just in case we have a dumb bios that set our code segment.
ljmp $0x00, $continuestart
continuestart:
//Copy over first few sectors of hard disk into ram.
mov %al, %dl
mov $0x0208, %ax //# of sectors to read.
mov $0x0002, %cx //Track = 0, sector = 2
pop %dx
mov $0x00, %dh //Head = 0, Drive = (whatever drive we started with)
mov $0x0000, %bx
mov %bx, %es //Segment of output
mov $0x7e00, %bx //Pointer of output
int $0x13
mov %ah, %al
mov $0x0e, %ah
add $0x30, %al
mov $0x00, %ebx
int $0x10
//Setup our real big GDT
cli
pusha
lgdt (GDT_ptr)
popa
//Enter protected mode
mov %cr0, %eax
or 1, %eax [b]NEEDS TO BE %1[/B]
mov %eax, %cr0
//Jump to correct data selector, and enter 32-bit mode
*edit* If I put a hlt here, it halts.
jmpl $0x08, $later2
later2:
*edit* If I put a hlt here, it does not halt.
Here's my GDT:
Code: Select all
//GDT, Flat 4GiB
//http://wiki.osdev.org/GDT_Tutorial
GDT:
.long 0x00000000
.long 0x00000000
//Descriptor (0x9a, RW, Execute) (Code32)
.long 0x0000ffff
.long 0x00CF9A00
//Descriptor (0x92, RW) (Data32)
.long 0x0000ffff
.long 0x00cf9200
//Code16
.long 0x0000ffff
.long 0x000f9a00
//Data16
.long 0x0000ffff
.long 0x000f9200
GDT_end:
GDT_ptr:
.word GDT_end - GDT // For limit storage
.long GDT // For base storage