Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Miky Gonzalez en 9 Octubre 2013, 19:26 pm



Título: [C] Kernel - Contru...ctor
Publicado por: Miky Gonzalez en 9 Octubre 2013, 19:26 pm
¡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
  1. .section multiboot
  2. // Cabezera multiboot
  3. .align 4
  4. .int 0x1badb002
  5. .int 0x0
  6. .int -0x1badb002
  7.  
  8. .section .text
  9.  
  10. // "init" es una función definida en init.c
  11. .extern init
  12.  
  13. // _start debe ser global, para que el enlazador pueda encontrarla y
  14. // usarla como punto de entrada.
  15. .global _start
  16. _start:
  17.    // Inicializar la pila
  18.    mov $kernel_stack, %esp
  19.  
  20.    // Llamar al código C
  21.    call init
  22.  
  23.    // Parar CPU - retorno desde código C
  24.    hlt
  25.  
  26. .section .bss
  27. .space 8192
  28. kernel_stack:
  29.  

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

Código
  1. void init(void) {
  2.    while(1) ;
  3. }

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
  1. /*  En _start debe iniciar la ejecución */
  2. ENTRY(_start)
  3. SECTIONS {
  4.    . = 0x100000;
  5.    .text : {
  6.        *(multiboot)
  7.        *(.text)
  8.    }
  9.    .data ALIGN(4096) : {
  10.        *(.data)
  11.    }
  12.    .rodata ALIGN(4096) : {
  13.        *(.rodata)
  14.    }
  15.    .bss ALIGN(4096) : {
  16.        *(.bss)
  17.    }
  18. }

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:

Código
  1. char *video = (char *) 0xB8000; // Dirección memoria video
  2. unsigned short int x = 0, y = 0; // Actual posición puntero
  3.  
  4. void putchar(char chr) {
  5.    if((chr == '\n') || (x > 79)) {
  6.        x = 0;
  7.        y++;
  8.    }
  9.    if(chr == '\n')
  10.        return;
  11.  
  12.    if(y > 24) {
  13.        int i;
  14.        for (i = 0; i < 2 * 24 * 80; i++)
  15.            video[i] = video[i + 160];
  16.  
  17.        for (; i < 2 * 25 * 80; i++)
  18.            video[i] = 0;
  19.        y--;
  20.    }
  21.  
  22.    video[2 * (y * 80 + x)] = chr;
  23.    video[2 * (y * 80 + x) + 1] = 0x07; // Color "default"
  24.  
  25.    x++;
  26.    return;
  27. }

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

Código
  1. int bucle_i;
  2. char *str1 = "Hola Mundo!"; // 11 carácteres
  3.  
  4. for(bucle_i = 0; bucle_i < 11; bucle_i++)
  5.    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:
Código
  1. void printf(char *str) {
  2.    int bucle_i = 0;
  3.  
  4.    for(; bucle_i < strlen(str); bucle_i++)
  5.        putchar(str[bucle_i]);
  6. }

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

[FUENTES]
  • http://osdev.org/
  • http://www.brokenthorn.com/
  • http://www.jamesmolloy.co.uk/

 Saludos,
     MikyGonzalez


Título: Re: [C] Kernel - Contru...ctor
Publicado por: Eternal Idol en 9 Octubre 2013, 22:45 pm
Si tenes alguna duda podes plantearla, si queres publicar "avances y código" existen recursos idoneos en Internet donde hacerlo.