Writing individual fixed characters works, however, when I try to use my string printing function, like this:
Code: Select all
console_write_string("Hello, kernel world!\n");
Since I had some strings in my second stage bootloader, for example, at 0x80F, I tried passing that address to the string printing function, only to notice that the function read exactly 0x80 bytes AHEAD of where I want it to read! I observed later that this happened to ALL pointers in my C code, including the VGA text buffer pointer — even though I specified 0xB8000, I had to subtract 0x80 to be able to write to the character at (0, 0) in the buffer.
When simply appending "-0x80" after all addresses, pointers and so on, everything works flawlessly, but this seems like a really bad hack I shouldn't have to deal with. What might cause this problem? Here's how I compile and link my kernel:
Code: Select all
gcc -c -Os -Oz -arch i386 -g -Wmost -fno-builtin -static -fomit-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -mno-sse2 -nostartfiles -nodefaultlibs -std=c99 -Wno-unused-variable -mfpmath=387 -fno-stack-protector -I. -ffreestanding *.c
gcc -static -Wl,-preload -Wl,-e,_loader -Wl,-segaddr,__TEXT,3000 -ffreestanding -nostdlib -arch i386 -o kernel.o -Wl,-segalign,20 *.o
gobjcopy -O binary kernel.o kernel.bin
In addition, I loaded this into QEMU and stepped through the code with gdb — my function gets the proper logical address, which, when I examine memory, contains my string, and when I subtract the offset to which the kernel is loaded also matches the location of the string in my flat binary, so I feel like I'm making some mistake with configuring the processor. My GDT is as follows, although I doubt it to be an issue as it's identical to the ones used by basically everyone else:
Code: Select all
608 gdt_start:
609 00000430 0000000000000000 dd $00, $00
610
611 ; Code segment
612 00000438 FFFF dw $0FFFF
613 0000043A 0000 dw $0000
614 0000043C 00 db $00
615 0000043D 9A db $9A
616 0000043E CF db $0CF
617 0000043F 00 db $00
618
619 ; Data segment
620 00000440 FFFF dw $0FFFF
621 00000442 0000 dw $0000
622 00000444 00 db $00
623 00000445 92 db $92
624 00000446 CF db $0CF
625 00000447 00 db $00