Why can I not output a pixel to the Linear Framebuffer?
Posted: Tue Sep 30, 2025 11:56 am
Hello guys! I get the multiboot info, but I can not get a pixel going on the screen no matter what, can someone tell me what I am doing wrong? I am still learning OSDev, it's messy cause it's just an initial release where I am just testing stuff out
my linker.ld
```
ENTRY(start)
SECTIONS {
. = 1K;
.boot :
{
*(.multiboot)
}
.text :
{
*(.text)
}
}
```
```
// grub.cfg
set timeout=10
set default=0
set gfxpayload=keep
menuentry "zxOS" {
multiboot /boot/kernel.bin
}
```
```asm
; multiboot.asm
section .multiboot
align 4
dd 0x1BADB002
dd (1<<0)|(1<<1)|(1<<2)
dd -(0x1BADB002 + ((1<<0)|(1<<1)|(1<<2)))
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 1024
dd 768
dd 32
```
```asm
; boot.asm
global start
extern kernel_main
section .text
bits 32
start:
push ebx
push eax
call kernel_main
end:
hlt
jmp end
```
```cpp
#ifndef IO_H
#define IO_H
#include "stdint.h"
static inline void outb(uint16_t port, uint8_t val) {
__asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port));
}
static inline uint8_t inb(uint16_t port) {
uint8_t ret;
__asm__ volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
}
#endif
```
```cpp
#ifndef MULTIBOOT_INFO_H
#define MULTIBOOT_INFO_H
#include "stdint.h"
typedef struct __attribute__((packed)) multiboot_info {
uint32_t flags;
uint32_t mem_lower;
uint32_t mem_upper;
uint32_t boot_device;
uint32_t cmdline;
uint32_t mods_count;
uint32_t mods_addr;
uint32_t syms[4];
uint32_t mmap_length;
uint32_t mmap_addr;
uint32_t drives_length;
uint32_t drives_addr;
uint32_t config_table;
uint32_t boot_loader_name;
uint32_t apm_table;
uint32_t vbe_control_info;
uint32_t vbe_mode_info;
uint16_t vme_mode;
uint16_t vbe_interface_seg;
uint16_t vbe_interface_off;
uint16_t vbe_interface_len;
uint64_t framebuffer_addr;
uint32_t framebuffer_pitch;
uint32_t framebuffer_width;
uint32_t framebuffer_height;
uint8_t framebuffer_bpp;
uint8_t framebuffer_type;
uint8_t color_info[5];
} multiboot_info_t;
#endif
```
```cpp
// kernel.c
#include "multiboot_info.h"
#include "stdint.h"
#include "io.h"
void kernel_main(uint32_t magic, multiboot_info_t* mbi) {
if (magic != 0x2BADB002) {}
if (mbi->flags & (1 << 12)) {
uint8_t rp = mbi->color_info[0];
uint8_t gp = mbi->color_info[2];
uint8_t bp = mbi->color_info[4];
uint32_t red_pixel = (255 << rp); // full red
uint32_t green_pixel = (255 << gp); // full green
uint32_t blue_pixel = (255 << bp); // full blue
uint32_t* framebuffer = (uint32_t*)(uint32_t)mbi->framebuffer_addr;
framebuffer[mbi->framebuffer_pitch / 4] = red_pixel;
while (1) {}
}
while (inb(0x64) & 0x02) {}
// Pulse CPU reset
outb(0x64, 0xFE);
}
```
```
all:
nasm -f elf32 src/asm/multiboot.asm -o output/multiboot.o
nasm -f elf32 src/asm/boot.asm -o output/boot.o
gcc -m32 -ffreestanding -fno-builtin -fno-pie -fno-stack-protector -Iinclude -g -c src/c/kernel.c -o output/kernel.o
ld -m elf_i386 --nmagic --output=iso/boot/kernel.bin --script=linker.ld \
output/multiboot.o output/boot.o output/kernel.o
grub-mkrescue -o os.iso iso
```
I run with qemu-system-x86_64.exe os.iso
What could the issue be? Any help is appreciated!
my linker.ld
```
ENTRY(start)
SECTIONS {
. = 1K;
.boot :
{
*(.multiboot)
}
.text :
{
*(.text)
}
}
```
```
// grub.cfg
set timeout=10
set default=0
set gfxpayload=keep
menuentry "zxOS" {
multiboot /boot/kernel.bin
}
```
```asm
; multiboot.asm
section .multiboot
align 4
dd 0x1BADB002
dd (1<<0)|(1<<1)|(1<<2)
dd -(0x1BADB002 + ((1<<0)|(1<<1)|(1<<2)))
dd 0
dd 0
dd 0
dd 0
dd 0
dd 0
dd 1024
dd 768
dd 32
```
```asm
; boot.asm
global start
extern kernel_main
section .text
bits 32
start:
push ebx
push eax
call kernel_main
end:
hlt
jmp end
```
```cpp
#ifndef IO_H
#define IO_H
#include "stdint.h"
static inline void outb(uint16_t port, uint8_t val) {
__asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port));
}
static inline uint8_t inb(uint16_t port) {
uint8_t ret;
__asm__ volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
}
#endif
```
```cpp
#ifndef MULTIBOOT_INFO_H
#define MULTIBOOT_INFO_H
#include "stdint.h"
typedef struct __attribute__((packed)) multiboot_info {
uint32_t flags;
uint32_t mem_lower;
uint32_t mem_upper;
uint32_t boot_device;
uint32_t cmdline;
uint32_t mods_count;
uint32_t mods_addr;
uint32_t syms[4];
uint32_t mmap_length;
uint32_t mmap_addr;
uint32_t drives_length;
uint32_t drives_addr;
uint32_t config_table;
uint32_t boot_loader_name;
uint32_t apm_table;
uint32_t vbe_control_info;
uint32_t vbe_mode_info;
uint16_t vme_mode;
uint16_t vbe_interface_seg;
uint16_t vbe_interface_off;
uint16_t vbe_interface_len;
uint64_t framebuffer_addr;
uint32_t framebuffer_pitch;
uint32_t framebuffer_width;
uint32_t framebuffer_height;
uint8_t framebuffer_bpp;
uint8_t framebuffer_type;
uint8_t color_info[5];
} multiboot_info_t;
#endif
```
```cpp
// kernel.c
#include "multiboot_info.h"
#include "stdint.h"
#include "io.h"
void kernel_main(uint32_t magic, multiboot_info_t* mbi) {
if (magic != 0x2BADB002) {}
if (mbi->flags & (1 << 12)) {
uint8_t rp = mbi->color_info[0];
uint8_t gp = mbi->color_info[2];
uint8_t bp = mbi->color_info[4];
uint32_t red_pixel = (255 << rp); // full red
uint32_t green_pixel = (255 << gp); // full green
uint32_t blue_pixel = (255 << bp); // full blue
uint32_t* framebuffer = (uint32_t*)(uint32_t)mbi->framebuffer_addr;
framebuffer[mbi->framebuffer_pitch / 4] = red_pixel;
while (1) {}
}
while (inb(0x64) & 0x02) {}
// Pulse CPU reset
outb(0x64, 0xFE);
}
```
```
all:
nasm -f elf32 src/asm/multiboot.asm -o output/multiboot.o
nasm -f elf32 src/asm/boot.asm -o output/boot.o
gcc -m32 -ffreestanding -fno-builtin -fno-pie -fno-stack-protector -Iinclude -g -c src/c/kernel.c -o output/kernel.o
ld -m elf_i386 --nmagic --output=iso/boot/kernel.bin --script=linker.ld \
output/multiboot.o output/boot.o output/kernel.o
grub-mkrescue -o os.iso iso
```
I run with qemu-system-x86_64.exe os.iso
What could the issue be? Any help is appreciated!