Octocontrabass wrote:GCC can't generate code that uses or understands segmentation, so it's limited to 64kB of addressable memory with 16-bit addressing. Since your kernel binary is linked to 0x9000, you end up with only 28kB of usable address space.
You're right, and I've already figured out how to solve it. Basically, the problems comes from the fact that the .data section, which was placed after .text, was used to store both real mode and protected mode data. Since the .text section grew too much, real mode data was placed beyond 64K, and therefore became unaddressable (not because memory beyond 64K is unaddressable in real mode, but because GCC only addresses data using the offset and never changes the segment pointer). The solution was to simply create a different section for real mode data and place it before .text, i.e. (.data16 is the new section for real mode data)
Code: Select all
ENTRY(entry)
SECTIONS {
/**
* This is the physical address the kernel will be loaded to
* it must match the value of LOAD_SEGMENT in the bootloader
*/
. = 0x9000;
.boot : {
*(.entry)
*(.data16)
}
.text : {
*(.text)
}
.rodata : {
*(.rodata)
}
.data : {
*(.data)
}
.bss : {
*(COMMON)
*(.bss)
}
kernelEnd = .;
}
Using GCC attributes, it's possible to specify the section in which C++ definitions should be placed by adding
to the definition.
Octocontrabass wrote:(You also don't check the carry flag, so even if you do somehow manage to pack everything into that small space, it still won't work properly.)
You're right. It didn't cause me any issues so far, but that's still a bug.
Octocontrabass wrote:The real problem here is that you're detecting memory, enabling A20, and switching to protected mode in your kernel. All of that only has to happen once, so why not put it in the bootloader?
That's more of a design decision rather than a problem. I didn't want to have a second stage bootloader, so I packed what I could into the boot-sector (basically finding and loading the kernel) and the rest is up to the kernel.
iansjack wrote:You are telling the assembler that you want to produce 16-bit code, but how is the C compiler supposed to know that? This is a recipe for disaster.
It's hacky, but it does work. Linux did it too.