Sistema operativo de 64 bits para arquitectura x86, construido desde cero. Implementa la cadena de arranque completa: desde GRUB/Multiboot2 hasta la transición de modo 32→64 bits y un kernel con salida de texto por VGA.
┌─────────────────────────────────────────────┐
│ Bootloader GRUB │ (protocolo Multiboot2)
│ targets/x86_64/iso/boot/ │
└────────────────────┬────────────────────────┘
│ carga kernel.bin, pone en eax el magic de Multiboot2
▼
┌─────────────────────────────────────────────┐
│ Cabecera Multiboot2 │ src/impl/x86_64/boot/header.asm
│ Magic: 0xe85250d6 | Arch: i386 │
└────────────────────┬────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ Arranque en 32 bits │ src/impl/x86_64/boot/main.asm
│ - Valida Multiboot2, CPUID, long mode │
│ - Construye tablas de páginas de 4 niveles │
│ - Habilita PAE + paginación │
│ - Activa long mode via MSR │
│ - Carga GDT 64 bits, salto lejano │
└────────────────────┬────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ Punto de entrada 64 bits │ src/impl/x86_64/boot/main64.asm
│ - Limpia registros de segmento │
│ - Llama a kernel_main() │
└────────────────────┬────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ Kernel (C) │ src/impl/kernel/main.c
│ - Limpieza de pantalla y colores │
│ - Utilidades de conversión entero/cadena │
│ - Punto de entrada kernel_main() │
└────────────────────┬────────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ Driver de texto VGA │ src/impl/x86_64/vga.c
│ - E/S mapeada en memoria (0xb8000) │
│ - Modo texto 80×25, 16 colores │
│ - Scroll, saltos de línea, cursor │
└─────────────────────────────────────────────┘
| Archivo | Descripción |
|---|---|
header.asm |
Cabecera Multiboot2 (número mágico + checksum). Permite que GRUB identifique y cargue el kernel. |
main.asm |
Arranque en modo protegido de 32 bits. Valida capacidades del hardware, construye tablas de páginas de 4 niveles con páginas de 2 MB (mapeo de identidad del primer 1 GB), habilita PAE y long mode via MSR, carga una GDT de 64 bits y realiza un salto lejano al código de 64 bits. |
main64.asm |
Primer código en 64 bits. Pone a cero todos los registros de segmento de datos y llama a kernel_main(). |
| Archivo | Descripción |
|---|---|
main.c |
Punto de entrada del kernel (kernel_main). Limpia la pantalla, establece colores, imprime mensajes de arranque y ejercita las utilidades de conversión entero/cadena (itoa, ItoA). |
| Archivo | Descripción |
|---|---|
vga.c |
Driver del buffer de texto VGA. Escribe struct Char (carácter + byte de color) directamente en la dirección física 0xb8000. Gestiona el movimiento del cursor, saltos de línea, desbordamiento de pantalla y scroll. |
| Archivo | Descripción |
|---|---|
vga.h |
API pública del driver VGA: print_clear(), print_char(), print_str(), print_newline(), print_set_color(). Define también las 16 constantes de color de la paleta VGA. |
| Archivo | Descripción |
|---|---|
linker.ld |
Ubica primero .multiboot_header, luego .text, a partir de 1 MB (0x100000). El punto de entrada es el símbolo start de main.asm. |
iso/boot/grub/grub.cfg |
Menú de GRUB: timeout cero, carga kernel.bin via multiboot2. |
my-own-operating-system/
├── buildenv/
│ └── Dockerfile # Entorno de compilación cruzada (x86_64-elf-gcc + nasm + grub)
├── src/
│ ├── intf/
│ │ └── vga.h # Interfaz pública del driver VGA
│ └── impl/
│ ├── kernel/
│ │ └── main.c # Punto de entrada del kernel (kernel_main)
│ └── x86_64/
│ ├── boot/
│ │ ├── header.asm # Cabecera Multiboot2
│ │ ├── main.asm # Arranque 32 bits + configuración de long mode
│ │ └── main64.asm # Entrada 64 bits, llama a kernel_main
│ └── vga.c # Driver de texto VGA
├── targets/
│ └── x86_64/
│ ├── linker.ld # Script del linker (disposición de memoria)
│ └── iso/boot/grub/
│ └── grub.cfg # Configuración del bootloader GRUB
├── Makefile # Reglas de compilación, enlazado y creación de ISO
├── build.sh # Script de build con Docker
└── test.sh # Runner de pruebas con QEMU
| Herramienta | Uso |
|---|---|
| Docker | Proporciona el entorno de compilación cruzada en contenedor |
| QEMU | Emula una máquina x86_64 para ejecutar la ISO del kernel |
En macOS (Homebrew):
brew install docker qemuEn Debian/Ubuntu:
sudo apt install docker.io qemu-system-x86El build se ejecuta dentro de un contenedor Docker basado en randomdude/gcc-cross-x86_64-elf. Incluye:
x86_64-elf-gcc— compilador C cruzado (sin stdlib, target bare-metal)nasm— ensamblador para archivos.asmxorriso+grub-pc-bin— creación de ISO con GRUB
Construir la imagen Docker (solo la primera vez o tras modificar buildenv/Dockerfile):
docker build -t mario21ic/my-own-os:builder buildenv/./build.shInternamente ejecuta make build-x86_64 dentro del contenedor. El Makefile:
- Compila todos los
.cbajosrc/impl/kernel/ysrc/impl/x86_64/con:x86_64-elf-gcc -c -I src/intf -ffreestanding - Ensambla todos los
.asmbajosrc/impl/x86_64/con:nasm -f elf64 - Enlaza todos los objetos via
targets/x86_64/linker.ldgenerandodist/x86_64/kernel.bin:x86_64-elf-ld -n -T targets/x86_64/linker.ld - Empaqueta una ISO arrancable con
grub-mkrescue:dist/x86_64/kernel.iso
./test.shLanza:
qemu-system-x86_64 -cdrom dist/x86_64/kernel.isoQEMU arranca la ISO, GRUB carga kernel.bin y la salida del kernel aparece en la ventana de QEMU.
./build.sh && ./test.shsrc/intf/vga.h
└── incluido por src/impl/kernel/main.c
y src/impl/x86_64/vga.c
src/impl/x86_64/boot/header.asm ─────────┐
src/impl/x86_64/boot/main.asm ──────────┤ enlazados por linker.ld
src/impl/x86_64/boot/main64.asm ──────────┤ entrada: start (main.asm)
src/impl/x86_64/vga.c ──────────┤
src/impl/kernel/main.c ──────────┘
│
└──→ dist/x86_64/kernel.bin
│
└──→ targets/x86_64/iso/boot/kernel.bin (symlink)
│
└──→ dist/x86_64/kernel.iso (grub-mkrescue)
Flujo de ejecución en tiempo de arranque:
GRUB → start (main.asm, 32 bits)
→ valida el magic de Multiboot2 (eax)
→ verifica soporte de CPUID / long mode
→ mapea 1 GB con páginas de 2 MB
→ habilita PAE + long mode + paginación
→ carga GDT 64 bits, salto lejano
→ long_mode_start (main64.asm, 64 bits)
→ kernel_main() (main.c)
→ print_clear() / print_set_color() / print_str()
→ buffer VGA 0xb8000 (vga.c)
- Archivo C en cualquier lugar bajo
src/impl/kernel/osrc/impl/x86_64/: el wildcard del Makefile lo toma automáticamente. - Archivo ASM en cualquier lugar bajo
src/impl/x86_64/: igual — NASM lo ensambla y el linker lo incluye. - Nuevo header de interfaz: colocarlo en
src/intf/e incluirlo con#include "tuarchivo.h".
- Arranca en hardware real y QEMU via GRUB/Multiboot2
- Transición de modo 32 bits → 64 bits (long mode) con paginación y GDT correctas
- Salida de texto VGA: 80×25 caracteres, 16 colores de primer plano/fondo, scroll
- Utilidades básicas del kernel:
itoa(entero a cadena), familiaprint_*
- Serie de YouTube en la que se basa este proyecto: https://www.youtube.com/watch?v=FkrpUaGThTQ&list=PLZQftyCk7_SeZRitx5MjBKzTtvk0pHMtp&index=1
- OSDev Wiki — referencia completa para desarrollo de sistemas operativos
- Especificación Multiboot2
MIT © 2021 Mario IC