[C] Kernel - Contru...ctor

Iniciado por Miky Gonzalez, 9 Octubre 2013, 19:26 PM

0 Miembros y 1 Visitante están viendo este tema.

Miky Gonzalez

¡ADVERTENCIA!: Este tema contiene datos de otras páginas. Existe código ensamblador en el código.

Primero de todo, deberían revisar como funciona el ordenador para poder entender la práctica que aquí les pongo. No lo voy a explicar, hay muchos sitios donde se explica el funcionamiento interno de un ordenador.

El código fuente de mi Kernel se divide en varios archivos, para mantener el código ensamblador necesario apartado del código C. Empezaré por el primer archivo que debo crear:

Código (asm) [Seleccionar]
.section multiboot
// Cabezera multiboot
.align 4
.int 0x1badb002
.int 0x0
.int -0x1badb002

.section .text

// "init" es una función definida en init.c
.extern init

// _start debe ser global, para que el enlazador pueda encontrarla y
// usarla como punto de entrada.
.global _start
_start:
   // Inicializar la pila
   mov $kernel_stack, %esp

   // Llamar al código C
   call init

   // Parar CPU - retorno desde código C
   hlt

.section .bss
.space 8192
kernel_stack:


El próximo archivo que deberiamos crear sería el código C (init.c):

void init(void) {
   while(1) ;
}


Por último necesitamos un enlazador que nos permita enlazar correctamente el código C y el código ensamblador para poder usarlo en nuestro bootloader (yo usaré GRUB2):

Código (asm) [Seleccionar]
/*  En _start debe iniciar la ejecución */
ENTRY(_start)
SECTIONS {
   . = 0x100000;
   .text : {
       *(multiboot)
       *(.text)
   }
   .data ALIGN(4096) : {
       *(.data)
   }
   .rodata ALIGN(4096) : {
       *(.rodata)
   }
   .bss ALIGN(4096) : {
       *(.bss)
   }
}


Hasta ahora, compilando nuestro código y virtualizándolo (por ejemplo yo uso QEMU), nos saldrá la pantalla de como GRUB carga nuestro Kernel, pero... ¿cómo sabemos que lo cargo?.
La dirección de memoria de video (estándar - sin paginación) es la dirección 0x8B000. Sabiendo esto y que hay 25 columnas por 80 filas, y que se necesita un valor de color letra, podemos escribir un "Hola mundo" en pantalla:

char *video = (char *) 0xB8000; // Dirección memoria video
unsigned short int x = 0, y = 0; // Actual posición puntero

void putchar(char chr) {
   if((chr == '\n') || (x > 79)) {
       x = 0;
       y++;
   }
   if(chr == '\n')
       return;

   if(y > 24) {
       int i;
       for (i = 0; i < 2 * 24 * 80; i++)
           video[i] = video[i + 160];

       for (; i < 2 * 25 * 80; i++)
           video[i] = 0;
       y--;
   }

   video[2 * (y * 80 + x)] = chr;
   video[2 * (y * 80 + x) + 1] = 0x07; // Color "default"

   x++;
   return;
}


Con esto, desde nuestro código init, podríamos hacer:

int bucle_i;
char *str1 = "Hola Mundo!"; // 11 carácteres

for(bucle_i = 0; bucle_i < 11; bucle_i++)
   putchar(str1[bucle_i]);


Esto sería nuestra gran primitiva función printf de C. Podríamos crear una función strlen y usar de esta forma:
void printf(char *str) {
   int bucle_i = 0;

   for(; bucle_i < strlen(str); bucle_i++)
       putchar(str[bucle_i]);
}


Eso es todo, intentaré publicar avances y código de mi kernel.

[FUENTES]
Mi blog personal, con información acerca de programación, seguridad, desarrollo y electrónica:

EN CONSTRUCCIÓN

Eternal Idol

Si tenes alguna duda podes plantearla, si queres publicar "avances y código" existen recursos idoneos en Internet donde hacerlo.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón