Odd issue when using puts() implementation
Posted: Sat Feb 15, 2025 12:14 pm
I'm in the process of switching a codebase of mine from GRUB to a custom bootloader so I can have more control over the booting process. Anyways, I got kernel loading working, and when I tried to actually print something, nothing showed up!
Here's the bootloader code:
stage0.asm
stage1.asm
Here's the kernel code:
I link like this:
and then concatenate the stage1 output with the output from the linker.
I should note that doing the following things work:
What's going on here? I read that it has something to do with .rodata not being linked, but if that was true, then set_color wouldn't work -- but it does. Thanks in advance.
Here's the bootloader code:
stage0.asm
Code: Select all
[org 0x7c00]
[bits 16]
xor ax, ax
mov ds, ax
mov es, ax
mov sp, 0x7c00
mov bp, sp
mov ax, 0x0003
int 0x10
; BIOS should put boot drive in dl
mov [BOOT_DRIVE], dl
; mov ax, 0x020F ;; 02 = read, 0F = sectors
mov ah, 02h
mov al, 32
mov bx, 0x7e00
mov dl, [BOOT_DRIVE]
mov cx, 0x0002
mov dh, 0x00
int 0x13
jc Failed
cli
lgdt [GDT_descriptor]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp 0x08:0x7e00 ;; !!
jmp $
BOOT_DRIVE: db 0
GDT_start:
GDT_null:
dd 0x0
dd 0x0
GDT_code:
dw 0xffff
dw 0x0
db 0x0
db 0b10011010
db 0b11001111
db 0x0
GDT_data:
dw 0xffff
dw 0x0
db 0x0
db 0b10010010
db 0b11001111
db 0x0
GDT_end:
GDT_descriptor:
dw GDT_end - GDT_start - 1
dd GDT_start
Failed:
mov ax, 0x0e5a
int 0x10
jmp $
times 510-($-$$) db 0
dw 0xaa55
Code: Select all
[extern _start]
[bits 32]
;; Setup stack
mov ax, 0x10
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ebp, 0x9000
mov esp, ebp
call _start
jmp $
Code: Select all
volatile uint16_t* vga_buffer = (uint16_t*)0xB8000;
int x_pos = 0; int y_pos = 0;
uint8_t color = VGA_COLOR_WHITE;
void putc(unsigned char c){
uint16_t attrib = (0 << 4) | (color & 0x0F);
volatile uint16_t * where;
where = (volatile uint16_t *)0xB8000 + (y_pos * 80 + x_pos);
*where = c | (attrib << 8);
if(++x_pos >= 80){
x_pos = 0;
y_pos++;
}
}
void set_color(uint8_t col){
color = col;
}
void puts(char* str){
while(*str){
putc(*str);
*str++;
}
}
void _start(){
set_color(0x2);
puts("Hello World");
}
Code: Select all
OUTPUT_FORMAT(binary)
ENTRY(_start)
SECTIONS
{
. = 0x7e00;
.text : ALIGN(0x1000)
{
*(.text)
}
.data : ALIGN(0x1000)
{
*(.data)
}
.rodata : ALIGN(0x1000)
{
*(.rodata)
}
.bss : ALIGN(0x1000)
{
*(COMMON)
*(.bss)
}
}
I should note that doing the following things work:
Code: Select all
putc('H');
Code: Select all
char str[] = "Hello";
for(int i = 0; i < str[i] != '\0'; i++){
putc(str[i]);
}
Code: Select all
char str[] = "Hello";
puts(str);