|
|
Line 1: |
Line 1: |
- | =EL GDT (Global Table Descriptor)=
| + | Esta página fue movida a [http://wiki.todoprogra.com/index.php?title=El_GDT El GDT] gracias! |
- | ==GDT==
| + | |
- | | + | |
- | El GDT es una estructura de datos para definir los privilegios de diferentes áreas de la memoria.
| + | |
- | | + | |
- | La tabla de descriptores es un array de entradas de 8 bytes que contienen descriptores, puede contener cualquier cantidad de descritores hasta un máximo de 8192 descriptores. La primera entrada del GDT no es usada por el procesador (descriptor nulo).
| + | |
- | | + | |
- | ==GDTR==
| + | |
- | | + | |
- | El GDT es apuntado por un registro especial de 48 bits llamado '''GDTR'''. El puntero al GDT debe contener esta información:
| + | |
- |
| + | |
- | *'''LIMIT''': Los primeros 16 bits indican el tamaño del segmento del GDT.
| + | |
- | *'''BASE''': Los siguientes 32 bits indican en dónde se encuentra el GDT en el espacio lineal de 4Gb de la memoria. Se puede calcular de esta forma (ASM):
| + | |
- | <pre>
| + | |
- | puntero_gdt:
| + | |
- | | + | |
- | dw final_gdt-inicio_gdt-1 ;LIMIT
| + | |
- | dd inicio_gdt ;BASE
| + | |
- | </pre>
| + | |
- | | + | |
- | ==Segmentos==
| + | |
- | | + | |
- | El GDT contiene un número de entradas llamadas '''Segment Descriptors''', ''estos descriptores de segmento'' indican en que parte de la memoria empieza, termina y los privilegios asociados con esta entrada. Cada descriptor del GDT indica si el área de la memoria es para uso del sistema (ring 0) o para el uso de las aplicaciones (ring 3). Los anillos (rings) indican al procesador si está permitido ejecutar instrucciones especiales (por ejemplo: ''cli'').
| + | |
- | | + | |
- | La estructura de una entrada del descriptor es:
| + | |
- | *Limite (segment limit) 2 bytes.
| + | |
- | *Base (base adress) 2 bytes: La dirección lineal en donde empieza el segmento.
| + | |
- | *Base (base) 1 byte:
| + | |
- | *Acceso (access) 1 byte: contiene los siguiente bits:
| + | |
- | **Presencia (1 bit) = debe estar puesto a 1 si el segmento es válido
| + | |
- | **Privilegio (2 bit) = contiene el nivel de privilegios (ring 0 = kernel, ring 3 = aplicaciones).
| + | |
- | **Ejecutable (1 bit) = 1 si es segmento de codigo, 0 si es segmento de datos.
| + | |
- | **Dirección (1 bit) =
| + | |
- | ***Segmento de Código: relacionado con los privilegios
| + | |
- | ***Segmento de Datos: 1 indica que el segmento crece hacia abajo, 0 que crece hacia arriba.
| + | |
- | **Lectura y Escritura (1 bit) =
| + | |
- | ***Segmento de Código: Si está permitida la lectura de este segmento. (en un segmento de datos nunca puede escribirse)
| + | |
- | ***Segmento de Datos: Si está permitida la escritura de este segmento. (en un segmento de datos siempre se puede leer)
| + | |
- | **Accedido (1 bit) = el procesador lo pone a 1 cuando accede a el.
| + | |
- | *Banderas 2 =
| + | |
- | **Granularidad (1 bit) = 0 si el límite está bloques de 1 byte (granulación de bytes), 1 si el límite está en bloques de 4Kib (granulación de páginas).
| + | |
- | **Tamaño (1 bit) = 0 si el segmento define un modo protegido de 16 bits, 1 si es modo protegido de 32 bits.
| + | |
- | | + | |
- | <pre>
| + | |
- | ;--------------------------------------------------------------------------------------------------------;
| + | |
- | ; Limite Bajo (2b) ; Base Baja (2b) ; Base Media (1b) ; Acceso (1b) ; Granularidad (1b) ; Base Alta (1b) ;
| + | |
- | ;--------------------------------------------------------------------------------------------------------;
| + | |
- | </pre>
| + | |
- | | + | |
- | ''todo: información más detallada?''
| + | |
- | | + | |
- | ==Implementación==
| + | |
- | | + | |
- | Esta es la implementación de NULL-OS con el GDT: | + | |
- | | + | |
- | ==='''boot.asm'''===
| + | |
- | <pre>
| + | |
- | ;--------------------------;
| + | |
- | ; NULL OS (boot.asm) ;
| + | |
- | ; version: 0.0.1 ;
| + | |
- | ; autor: movaxes ;
| + | |
- | ; fecha: 6/2/07 ;
| + | |
- | ;--------------------------;
| + | |
- | [BITS 32]
| + | |
- | | + | |
- | %include "gdt.asm"
| + | |
- | | + | |
- | global boot ;donde inicia nuestro kernel
| + | |
- | extern _main ;esta funcion se encuentra en main.c
| + | |
- | | + | |
- | ;Multiboot Header
| + | |
- | | + | |
- | MULTIBOOT_PAGE_ALIGN equ 1<<0
| + | |
- | MULTIBOOT_MEMORY_MAP equ 1<<1
| + | |
- |
| + | |
- | MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
| + | |
- | MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_MAP
| + | |
- | MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
| + | |
- | | + | |
- | SECTION .text
| + | |
- | ALIGN 4
| + | |
- | multiboot_header:
| + | |
- | | + | |
- | dd MULTIBOOT_HEADER_MAGIC
| + | |
- | dd MULTIBOOT_HEADER_FLAGS
| + | |
- | dd MULTIBOOT_CHECKSUM
| + | |
- | | + | |
- | ;nuestro stack (pila) de 16kb:
| + | |
- | | + | |
- | KERNEL_STACK equ 0x4000
| + | |
- | | + | |
- | boot:
| + | |
- | | + | |
- | mov esp,stack+KERNEL_STACK ;apuntamos a nuestra pila
| + | |
- |
| + | |
- | push eax ;ponemos en la pila MULTIBOOT_HEADER_MAGIC
| + | |
- | push ebx ;ponemos en la pila MULTIBOOT_MEMORY_MAP
| + | |
- |
| + | |
- | call gdt_set ;ponemos el GDT
| + | |
- | call _main ;llamamos a main en main.c
| + | |
- | cli
| + | |
- | hlt ;detiene el CPU
| + | |
- | jmp $ ;loop infinito
| + | |
- |
| + | |
- | SECTION .bss
| + | |
- | ALIGN 32
| + | |
- | stack:
| + | |
- | | + | |
- | resb KERNEL_STACK
| + | |
- | </pre>
| + | |
- | | + | |
- | ==='''gdt.asm'''===
| + | |
- | <pre>
| + | |
- | ;--------------------------;
| + | |
- | ; NULL OS (gdt.asm) ;
| + | |
- | ; version: 0.0.2 ;
| + | |
- | ; autor: movaxes ;
| + | |
- | ; fecha: 13/2/07 ;
| + | |
- | ;--------------------------;
| + | |
- | [BITS 32] | + | |
- | ;----------------;
| + | |
- | ;gdt_set ;
| + | |
- | ;----------------;
| + | |
- | | + | |
- | gdt_set:
| + | |
- | | + | |
- | lgdt [puntero_gdt] ;carga el GDTR
| + | |
- | mov ax, 0x10 ;
| + | |
- | mov ds, ax ;Apuntamos el segmento de datos a 0x10
| + | |
- | mov es, ax ;...
| + | |
- | mov fs, ax
| + | |
- | mov gs, ax
| + | |
- | mov ss, ax
| + | |
- | | + | |
- | jmp 0x08:gdt_set_end ;cargamos el CS
| + | |
- |
| + | |
- | gdt_set_end:
| + | |
- | | + | |
- | ret ;fin de gdt_set
| + | |
- | | + | |
- | ;----------------;
| + | |
- | | + | |
- | puntero_gdt: ;nuestro puntero al GDT
| + | |
- | | + | |
- | dw GDT_END-GDT_INIT-1 ;limite (fin del gdt - inicio del gdt - 1)
| + | |
- | dd GDT_INIT ;base
| + | |
- |
| + | |
- | ;----------------;
| + | |
- | ;GDT ;
| + | |
- | ;----------------;
| + | |
- | GDT_INIT:
| + | |
- | ;----------------;
| + | |
- | NULL_SEG equ $-GDT_INIT ;Descriptor nulo (NULL = 0x0):
| + | |
- | | + | |
- | dw 0 ;Limite del Segmento
| + | |
- | dw 0 ;00..15 de la dirección base
| + | |
- | db 0 ;16..23 de la dirección base
| + | |
- | db 0 ;Permisos de acceso al segmento:
| + | |
- | ;(presencia,privilegio,ejecutable,direccion,r/w,accedido)
| + | |
- | db 0 ;Granularidad, Tamaño del los optcodes (16 o 32), limite de 16..19
| + | |
- | db 0 ;24..31 de la dirección base
| + | |
- | ;----------------;
| + | |
- | K_CODE_SEG equ $-GDT_INIT ;segmento de Codigo del kernel:
| + | |
- | | + | |
- | dw 0xFFFF
| + | |
- | dw 0
| + | |
- | db 0
| + | |
- | db 10011010b
| + | |
- | db 11001111b
| + | |
- | db 0
| + | |
- | ;----------------;
| + | |
- | K_DATA_SEG equ $-GDT_INIT ;segmento de Datos del Kernel:
| + | |
- | | + | |
- | dw 0FFFFh
| + | |
- | dw 0
| + | |
- | db 0
| + | |
- | db 10010010b
| + | |
- | db 11001111b
| + | |
- | db 0
| + | |
- | ;----------------;
| + | |
- | U_CODE_SEG equ $-GDT_INIT ;segmento de Codigo de usuario:
| + | |
- | | + | |
- | dw 0FFFFh
| + | |
- | dw 0
| + | |
- | db 0
| + | |
- | db 11111010b
| + | |
- | db 11001111b
| + | |
- | db 0
| + | |
- | ;----------------;
| + | |
- | U_DATA_SEG equ $-GDT_INIT ;segmento de Datos de usuario:
| + | |
- | | + | |
- | dw 0xFFFF
| + | |
- | dw 0
| + | |
- | db 0
| + | |
- | db 11110010b
| + | |
- | db 11001111b
| + | |
- | db 0
| + | |
- | ;----------------;
| + | |
- | GDT_END: ;fin del GDT
| + | |
- | ;----------------;
| + | |
- | </pre>
| + | |
- | | + | |
- | ==='''main.c'''===
| + | |
- | <pre>
| + | |
- | /*--------------------------;
| + | |
- | ; NULL OS (main.c) ;
| + | |
- | ; version: 0.0.1 ;
| + | |
- | | + | |
- | ; autor: movaxes ;
| + | |
- | ; fecha: 6/2/07 ;
| + | |
- | ;--------------------------*/
| + | |
- | | + | |
- | //esta es nuestra funcion _main llamada desde boot.asm
| + | |
- | //los argumentos que pasamos son:
| + | |
- | //MULTIBOOT_HEADER_MAGIC
| + | |
- | //MULTIBOOT_MEMORY_INFO
| + | |
- | //los cuales estan en la pila (stack)
| + | |
- | void _main(void* mm, unsigned int magic)
| + | |
- | {
| + | |
- | //todo:...
| + | |
- | }
| + | |
- | </pre>
| + | |
- | | + | |
- | ==='''link.ld'''=== | + | |
- | <pre>
| + | |
- | ENTRY (boot)
| + | |
- | SECTIONS{
| + | |
- | . = 0x00100000;
| + | |
- | | + | |
- | .text :{
| + | |
- | *(.text)
| + | |
- | }
| + | |
- | | + | |
- | .rodata ALIGN (0x1000) : {
| + | |
- | *(.rodata)
| + | |
- | }
| + | |
- | | + | |
- | .data ALIGN (0x1000) : {
| + | |
- | *(.data)
| + | |
- | }
| + | |
- | | + | |
- | .bss : {
| + | |
- | _sbss = .;
| + | |
- | *(COMMON)
| + | |
- | *(.bss)
| + | |
- | _ebss = .;
| + | |
- | }
| + | |
- | }
| + | |
- | </pre>
| + | |
- | | + | |
- | ==='''build.sh:'''===
| + | |
- | <pre>
| + | |
- | #!/bin/bash
| + | |
- | echo --- compilando *.asm
| + | |
- | nasm -f elf boot.asm -o boot.o
| + | |
- | nasm -f elf gdt.asm -o gdt.o
| + | |
- | echo --- compilando *.c
| + | |
- | #gcc -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc -fno-builtin -I./include -c -o main.o main.c
| + | |
- | gcc -o main.o -c main.c -Wall -Werror -nostdlib -nostartfiles -nodefaultlibs
| + | |
- | echo --- linking *.o
| + | |
- | ld -T link.ld -o kernel.bin boot.o main.o gdt.o
| + | |
- | echo --- borrando *.o
| + | |
- | rm *.o
| + | |
- | echo --- EXITO!!
| + | |
- | </pre>
| + | |
- | | + | |
- | ===Compilar y Probar el Kernel===
| + | |
- | Para compilar solo escribe en un terminal:
| + | |
- | <pre>
| + | |
- | $sh build.sh
| + | |
- | </pre>
| + | |
- | | + | |
- | Para poder probar tu nuevo kernel puedes usar GRUB (mira: [http://www.editthis.info/movaxes/Usando_GRUB Usando GRUB] para saber cómo puedes hacerlo)
| + | |
- | | + | |
- | <br>
| + | |
- | <br>
| + | |