universidad central del ecuador facultad de

Anuncio
UNIVERSIDAD CENTRAL DEL ECUADOR
FACULTAD DE INGENIERÍA, CIENCIAS FÍSICAS Y MATEMÁTICA
CARRERA INGENIERÍA INFORMÁTICA
ESTUDIO, DESARROLLO E IMPLEMENTACIÓN DE UN GESTOR DE
ARRANQUE PARA COMPUTADORAS PC COMPATIBLES X86 QUE INICIAN
EN MODO REAL.
TRABAJO DE GRADUACIÓN PREVIA LA OBTENCIÓN DEL TÍTULO DE
INGENIERO INFORMÁTICO.
AUTOR: Figueroa Cañar Víctor Bolívar
TUTOR: Ing. Jorge Arturo Morales Cardoso
QUITO - ECUADOR
2015
DEDICATORIA
Dedico el presente trabajo de tesis a Dios por cuidarme y guiarme en cada
momento de mi vida, a mis padres Luis Antonio y María Beatriz por su
permanente apoyo, por plasmar en mi educación, valores y disciplina ante todas
las cosas que he desarrollado en mi vida, a mis hermanos Luis, Andrés y Nélida
por su ayuda y consejos, me han inspirado a lo largo de mi vida personal y
profesional.
Dedico a mi Familia y amigos/as que han estado en los momentos que los he
necesitado con su apoyo, entusiasmo y alegría.
A todos ustedes gracias por su incondicional apoyo y entusiasmo que me han
inspirado para poder culminar el presente tema de tesis.
Víctor Figueroa
II
AGRADECIMIENTO
Agradezco la colaboración, enseñanza y ayuda de los Ing. Jorge Morales
como tutor de tesis, Ing. Mauro Rosas como revisor de tesis, por su apoyo
durante el desarrollo del
tema de tesis, a los docentes
de la carrera de
Ingeniería Informática por impartir sus conocimientos los cuales me ayudaron a
culminar el tema.
Agradezco a toda mi familia por su apoyo y cariño inagotable, gracias por estar
siempre juntos.
Agradezco a mis amigos/as de la Universidad con los cuales compartí
inolvidables momentos, gracias por su apoyo.
Víctor Figueroa
III
AUTORIZACIÓN DE LA AUTORÍA INTELECTUAL
Yo, Figueroa Cañar Víctor Bolívar en calidad de autor del trabajo de
investigación
o
tesis
IMPLEMENTACIÓN
realizada
DE
UN
sobre
GESTOR
ESTUDIO,
DE
DESARROLLO
ARRANQUE
E
PARA
COMPUTADORAS PC COMPATIBLES X86 QUE INICIAN EN MODO REAL,
por la presente autorizo a la UNIVERSIDAD CENTRAL DEL ECUADOR, hacer
uso de todos los contenidos que me pertenecen o de parte de los que contiene
esta obra, con fines académicos o de investigación.
Los derechos que como autor me corresponden, con excepción de la presente
autorización, seguirán vigentes a mi favor, de conformidad con los establecidos
en los artículos 5, 6, 8, 19 y demás pertinentes de la ley de Propiedad
Intelectual y su Reglamento.
Quito, Día 21 Mes Abril 2015
---------------------------FIRMA
Figueroa Cañar Víctor Bolívar
CC. 1716500317
IV
CERTIFICACIÓN
En calidad de tutor del proyecto de investigación: ESTUDIO, DESARROLLO E
IMPLEMENTACIÓN
DE
UN
GESTOR
DE
ARRANQUE
PARA
COMPUTADORAS PC COMPATIBLES X86 QUE INICIAN EN MODO REAL,
presentado y desarrollado por el señor: Figueroa Cañar Víctor Bolívar , previo a
la obtención del Título de Ingeniero Informático considero que el proyecto reúne
los requisitos necesarios.
En la ciudad de Quito a los 21 días del mes de Abril del 2015
Atentamente
-------------------------------Ing. Jorge Arturo Morales Cardoso
Tutor de Tesis
V
INFORME SOBRE CULMINACIÓN Y APROBACIÓN DE TESIS
Quito, DM 21 de Abril del 2015
Señor Ingeniero
Boris Herrera
DIRECTOR DE LA CARRERA DE INGENIERÍA INFORMÁTICA
Presente.-
Señor Director:
Yo, Jorge Arturo Morales Cardoso, Docente de la Carrera de Ingeniería
Informática, de la Facultad de Ingeniería Ciencias Físicas y Matemáticas de la
Universidad Central del Ecuador y en calidad de tutor.
Certifico
Luego de las revisiones técnicas realizadas por mi persona al proyecto de
investigación “ESTUDIO, DESARROLLO E IMPLEMENTACIÓN DE UN
GESTOR DE ARRANQUE PARA COMPUTADORAS PC COMPATIBLES X86
QUE INICIAN EN MODO REAL” llevando a cabo por parte del egresado de la
Carrera de Ingeniería Informática, señor Víctor Bolívar Figueroa Cañar, con
CC. 1716500317 ha concluido de manera exitosa, consecuentemente el
indicado egresado podrá continuar con los trámites de graduación
correspondientes de acuerdo a lo que estipula las normativas y direcciones
legales.
Por la atención que digne al presente, reitero mi agradecimiento.
Atentamente
Ing. Jorge Arturo Morales Cardoso
CATEDRÁTICO DE LA CARRERA DE INGENIERÍA INFORMÁTICA
Tutor
VI
RESULTADO DEL TRABAJO DE GRADUACION
VII
CONTENIDO
DEDICATORIA ................................................................................................... II
AGRADECIMIENTO .......................................................................................... III
AUTORIZACIÓN DE LA AUTORÍA INTELECTUAL ......................................... IV
CERTIFICACIÓN ................................................................................................ V
INFORME SOBRE CULMINACIÓN Y APROBACIÓN DE TESIS .................... VI
RESULTADO DEL TRABAJO DE GRADUACION .......................................... VII
LISTA DE FIGURAS ........................................................................................ XII
LISTA DE TABLAS ......................................................................................... XIV
RESUMEN ........................................................................................................ XV
ABSTRACT ..................................................................................................... XVI
CERTIFICADO DE TRADUCCIÓN ................................................................ XVII
TÍTULO DEL TRADUCTOR .......................................................................... XVIII
INTRODUCCIÓN ................................................................................................ 1
CAPITULO 1....................................................................................................... 2
1.
PRESENTACION DEL PROBLEMA ....................................................... 2
1.1 Planteamiento del Problema............................................................... 2
1.2 Formulación del Problema .................................................................. 4
1.3 Justificación ......................................................................................... 4
1.4 Objetivos de la Investigación ............................................................... 5
1.4.1 Objetivo General ............................................................................. 5
1.4.2 Objetivos Específicos ...................................................................... 5
1.6 Alcance................................................................................................ 6
1.7 Limitaciones ........................................................................................ 7
1.8 Contribuciones .................................................................................... 8
1.9 Herramientas ....................................................................................... 9
CAPITULO 2..................................................................................................... 10
2.
MARCO METODOLÓGICO.................................................................... 10
2.1 Diseño de la Investigación................................................................. 10
2.2 Antecedentes .................................................................................... 11
2.3 Fundamentación Teórica ................................................................... 12
2.3.1 Evolución De Los Sistemas Operativos y Computadores ............. 12
2.3.1.1 Primera Generación (1946-1958) ............................................ 13
2.3.1.2 Segunda Generación (1955 a 1965) ........................................ 13
VIII
2.3.1.3 Tercera Generación (1965 a 1980) .......................................... 14
2.3.1.4 Cuarta Generación (1965 a 1980) ........................................... 14
2.3.1.5 Historia Hechos Relevantes ..................................................... 15
2.3.2 Microprocesador ........................................................................... 16
2.3.2.1 Concepto ................................................................................. 16
2.3.2.2 Evolución del microprocesador ................................................ 16
2.3.2.3 Arquitectura ............................................................................. 18
2.3.2.4 Registros .................................................................................. 19
2.3.2.5 Unidad aritmética lógica ........................................................... 22
2.3.3 Memoria ......................................................................................... 24
2.3.3.1 Tipos de Memoria .................................................................... 24
2.3.3.1.1 Memoria RAM .................................................................... 24
2.3.3.1.1 Memoria ROM ................................................................... 25
2.3.3.2 Memoria Principal .................................................................... 26
2.3.3.3 Arquitectura de la Memoria Principal ....................................... 26
2.3.4 Manejo de Memoria ....................................................................... 30
2.3.4.1 Segmentación .......................................................................... 30
2.3.4.2 Direccionamiento .................................................................... 31
2.3.4.3 Modos de Direccionamiento .................................................... 32
2.3.5 Disco Duro ................................................................................. 36
2.3.5.1 Estructura Física De Un Disco Duro ........................................ 36
2.3.5.2 Estructura Física: Cabezas, Cilindros Y Sectores.................... 39
2.3.5.3 Direccionamiento De Sectores En Discos Duros .................... 40
2.3.5.3.1 Direccionamiento CHS ...................................................... 40
2.3.5.3.2 Direccionamiento CHS Extendida...................................... 41
2.3.5.3.3 Direccionamiento LBA ....................................................... 42
2.3.6 Sistema De Numeración Computacional Y Unidades De
Información ............................................................................................. 44
2.3.6.1 Sistema Binario ........................................................................ 44
2.3.6.2 Sistema Octal........................................................................... 44
2.3.6.3 Sistema Decimal ...................................................................... 44
2.3.6.4 Sistema Hexadecimal .............................................................. 45
2.3.6.5 Unidades De Información ........................................................ 45
2.3.7 BIOS .......................................................................................... 46
2.3.7.1 El área de parámetros de la BIOS ........................................... 47
2.3.7.2 Vectores de Interrupción .......................................................... 49
2.3.7.3 Servicios De La BIOS .............................................................. 50
2.3.8 Lenguaje Ensamblador .............................................................. 51
2.3.9 Lenguaje C................................................................................. 52
2.3.10
Herramientas de programación .............................................. 53
2.3.10.1 Editores .................................................................................. 53
IX
2.4
2.5
2.6
2.7
2.3.10.2 Ensambladores ...................................................................... 55
2.3.10.3 Enlazadores ........................................................................... 56
2.3.10.4 GCC ....................................................................................... 57
Investigación Experimental ................................................................ 58
Plan de Recolección de Información ................................................... 58
Plan de Procesamiento de Información ............................................... 59
Modelo de Desarrollo .......................................................................... 59
CAPITULO 3..................................................................................................... 62
3 DISEÑO DE LA SOLUCIÓN.................................................................... 62
3.1 Antecedentes .................................................................................... 62
3.2 Gestor de Arranque ........................................................................... 62
3.2.1 Codificación y Funcionamientos de los Gestores de Arranque ... 63
3.3 MBR .................................................................................................. 64
3.4. NTLDR ............................................................................................ 65
3.4.1 Estudio NTLDR ........................................................................... 65
3.4.1 .1 Sección de Código............................................................... 66
3.4.1 .2. Sección de Mensaje de Errores ............................................. 67
3.4.1 .3 Sección definida por Windows ............................................ 67
3.4.1 .4 Sección Tabla de Particiones .............................................. 68
3.4.1 .5. Sección de Firma ................................................................ 72
3.4.2. Des ensamblaje de la Sección de Código ................................. 73
3.4.2. 1. Primera Parte Del Código ................................................... 73
3.4.2. 2. Segunda Parte Del Código ................................................. 74
3.4.2. 3. Tercera Parte Del Código ................................................... 76
3.4.2. 4. Cuarta Parte Del Código .................................................... 77
3.4.2. 5. Quinta Parte Del Código. ................................................... 78
3.4.2. 6. Sexta Parte Del Código ..................................................... 84
3.4.3. Alcance estudio NTLDR............................................................ 86
3.5 GRUB LEGACY .............................................................................. 86
3.5.1 Introducción GRUB .................................................................... 86
3.5.2 Historia de GRUB ...................................................................... 87
3.5.3 Características de GRUB ............................................................ 87
3.5.4 Creación de un disquete de arranque GRUB ............................. 92
3.5.5 Realizar un CD-ROM Booteable con GRUB .............................. 93
3.5.5 Construcción y Compilación de GRUB .................................... 101
3.5.6 Estudio del Código de GRUB .................................................. 108
3.5.6 .1 Estudio Del Código De La Primera Etapa.......................... 109
3.5.7 .1 Primera parte del Código .................................................. 121
3.5.7 .2 Segunda parte del Código ................................................ 122
3.5.7.3 Tercera parte del Código ................................................... 123
X
3.5.7.4 Cuarta parte del Código..................................................... 124
3.5.7.5 Quinta parte del Código ..................................................... 128
3.6 Modificación del Gestor de Arranque GRUB .................................. 144
3.6.1 Modificación Del Archivo stage1.S............................................ 145
3.6.2 Modificación del Archivo stage1.h............................................ 159
3.6.3 Modificación del Archivo char_io.c ........................................... 162
3.6.4 Presentación Del funcionamiento De Grub Legacy Modificado.
........................................................................................................... 199
3.6.4.1 Pantalla Inicial Grub Legacy Modificado ............................... 200
3.6.4.2 Grub Legacy Modificado Chainloader ................................... 200
3.7 Desarrollo de MUCE (MBR de la Universidad Central del Ecuador) 201
3.7.1 Código de MUCE ...................................................................... 201
CAPITULO 4................................................................................................... 206
4.1 PRUEBAS ................................................................................................ 206
4.1.1 Presentación Funcionamiento MUCE............................................. 206
4.1.1.1 Pantalla Inicial MUCE................................................................ 206
4.1.1.2 Pantalla Inicio Windows Xp ................................................ 207
4.2 CONCLUSIONES ....................................................................................... 207
4.3 RECOMENDACIONES ................................................................................. 208
BIBLIOGRAFIA .............................................................................................. 209
XI
LISTA DE FIGURAS
Figura 1. Abstracción de Interfaz Aplicaciones y S.O. ...................................... 12
Figura 2. Procesamiento por Lotes ................................................................... 13
Figura 3. Arquitectura de Microprocesador o CPU 8086. ................................. 18
Figura 4. Esquema de Bloques de una ALU Típica. ......................................... 23
Figura 5. Memoria Típica. ................................................................................. 24
Figura 6. Arquitectura de la Memoria Principal. ................................................ 26
Figura 7. Segmentación de Memoria ................................................................ 31
Figura 8. Direccionamiento Directo. .................................................................. 33
Figura 9. Direccionamiento indirecto mediante registro. ................................... 34
Figura 10. Direccionamiento por Registro Base ............................................... 34
Figura 11. Direccionamiento indexado.............................................................. 35
Figura 12. Disco Duro. ...................................................................................... 36
Figura 13. Estructura Física De Un Disco Duro. ............................................... 36
Figura 14. Estructura física de un disco duro. ................................................... 39
Figura 15. Editor Assembler Editor. .................................................................. 54
Figura 16. Editor Nasm-IDE. ............................................................................. 54
Figura 17. Etapas de gcc. ................................................................................. 57
Figura 18. Flujo General de Inicio de la Pc. ...................................................... 62
Figura 19. Flujo de Selección y Carga de Código de Arranque. ....................... 63
Figura 20. Sector Cero Disco Duro con Windows XP. ...................................... 65
Figura 21. Sección de código de NTLDR. ......................................................... 66
Figura 22. Sección de Mensaje de Errores. ...................................................... 67
Figura 23. Sección definida por Windows parte 1. ............................................ 67
Figura 24. Sección definida por Windows parte 2. ............................................ 68
Figura 25. NTLDR Sección Tabla de Particiones.............................................. 68
Figura 26. NTLDR Tipo de Particiones. ............................................................ 71
Figura 27. Tabla de Particiones Hexadecimal................................................... 71
Figura 28. NTLDR Firma. .................................................................................. 72
Figura 29. Terminal en Modo Grafico. ............................................................ 102
Figura 30. Comando cd. ................................................................................. 102
Figura 31. Comando zcat. ............................................................................... 103
Figura 32. Ejecución del comando zcat. ......................................................... 103
Figura 33. Creación del directorio grub-097. ................................................... 104
Figura 34. Contenido del directorio grub-097. ................................................. 104
Figura 35. Archivos del directorio stage1. ....................................................... 105
Figura 36. Ingreso Subdirectorio Grub-0.97. ................................................... 105
Figura 37. Ejecución de ./configure CC=gcc34 ............................................... 106
Figura 38. Listado de ./configure CC=gcc34. .................................................. 106
XII
Figura 39. Ejecución del archivo install. .......................................................... 107
Figura 40. Salida del comando make install. .................................................. 107
Figura 41. Código hexadecimal de GRUB Primera Etapa. ............................. 109
Figura 42. Configuración des ensamblaje. ...................................................... 110
Figura 43. Ingreso a Directorio stage1. ........................................................... 114
Figura 44. Creación de archivo total fuente stage1. ........................................ 115
Figura 45. Código hexadecimal diferenciado de GRUB Primera Etapa. ......... 120
Figura 46. Código Hexadecimal GRUB parte 1 .............................................. 121
Figura 47. Código Hexadecimal GRUB parte 2. ............................................. 122
Figura 48. Código Hexadecimal GRUB parte 2. ............................................. 123
Figura 49. Inico Grub Legacy Modificado. ...................................................... 200
Figura 50. Inico Grub Legacy Chainloader. .................................................... 200
Figura 51. Inicio MUCE. .................................................................................. 206
Figura 52. MUCE Iniciando XP ....................................................................... 207
XIII
LISTA DE TABLAS
Tabla 1. Evolución De Los Microprocesadores. ................................................ 17
Tabla 2. Registros del Microprocesador 80386................................................. 19
Tabla 3. Uso común de los registros de propósito general. .............................. 19
Tabla 4. Uso común de los registros de segmento. .......................................... 19
Tabla 5. Registros apuntadores del microprocesador....................................... 20
Tabla 6. Banderas del microprocesador. .......................................................... 21
Tabla 7. Tipos de Memoria. .............................................................................. 25
Tabla 8. Direccionamiento CHS. ....................................................................... 40
Tabla 9. Especificación ATA. ............................................................................ 41
Tabla 10. Unidades de Información Microprocesador. ...................................... 46
Tabla 11. Área De Parámetros De La BIOS. .................................................... 48
Tabla 12. Tipos de Datos de Programación C. ................................................ 52
Tabla 13. Etapas del Gestor de Arranque. ........................................................ 63
Tabla 14. Almacenamiento del Master Boot Record de NTLDR. ...................... 66
Tabla 15. Estructura de la tabla de particiones. ................................................ 69
Tabla 16. NTLDR código fuente documentado parte 1. .................................... 74
Tabla 17. NTLDR código fuente documentado parte 2. .................................... 75
Tabla 18. NTLDR código fuente documentado parte 3. .................................... 76
Tabla 19. NTLDR código fuente documentado parte 4. .................................... 77
Tabla 20. NTLDR código fuente documentado parte 5. .................................... 83
Tabla 21. NTLDR código fuente documentado parte 6. .................................... 85
Tabla 22. Archivo de Configuración de Menú de GRUB. .................................. 99
Tabla 23. Codigo NTLDR. ............................................................................... 114
Tabla 24. Codigo GRUB parte 1. .................................................................... 121
Tabla 25. Código GRUB desensamblado parte 1. .......................................... 122
Tabla 26. Código GRUB parte 2. .................................................................... 123
Tabla 27. Código GRUB Parte 3. .................................................................... 124
Tabla 28. Código GRUB parte 4. .................................................................... 128
Tabla 29. Código GRUB parte 5. .................................................................... 131
Tabla 30. Código GRUB parte 6. .................................................................... 136
Tabla 31. Código GRUB parte 7. .................................................................... 137
Tabla 32. Código GRUB parte 8. .................................................................... 138
Tabla 33. Código GRUB parte 9. .................................................................... 141
Tabla 34. Código GRUB parte 10. .................................................................. 143
Tabla 35. Firma Código GRUB parte 11. ........................................................ 144
XIV
RESUMEN
ESTUDIO, DESARROLLO E IMPLEMENTACIÓN DE UN GESTOR DE
ARRANQUE PARA COMPUTADORAS PC COMPATIBLES X86 QUE INICIAN
EN MODO REAL
Las computadoras que al encender inician en modo real realizan un proceso
denominado POST (Power On Selft) que se encarga de verificar que el
hardware de la pc esté funcionando correctamente, almacene en memoria las
interrupciones de la BIOS (Basic Input/Output System), busque un dispositivo
de arranque (disco duro, disquetera, DVD, etc.), cargue a memoria su código de
arranque y otorgue el procesamiento de la pc dicho código es denominado MBR
(Master Boot Record).
Los gestores de arranque que son los que tiene el código del MBR como un
módulo, inyectan el MBR en los dispositivos de almacenamiento (Disco duros,
cds, dvs etc.), convirtiéndoles así en dispositivos de arranque.
El presente proyecto pretende dar una visión general de cómo funciona un
gestor de arranque, que es necesario para que la pc pueda reconocer un
dispositivo de arranque, entender como el código del MBR es desarrollado en
lenguaje ensamblador y lenguaje c, como este es transformado a lenguaje de
máquina, como este es entendido y ejecutado por la pc. Tener un entendimiento
de cómo interactúa el hardware y el software del gestor de arranque para
dotarle a la máquina de “inteligencia”. Se realizará un estudio de los gestores de
arranque NTLDR y GRUB LEGACY, se modificará y construirá GRUB LEGACY
y se desarrollará un MBR propio.
DESCRIPTORES:
LENGUAJE ENSAMBLADOR / LENGUAJE C / BOOTLOADER / GESTOR DE
ARRANQUE / GRUB / GCC.
XV
ABSTRACT
STUDY, DEVELOPMENT AND IMPLEMENTATION OF A MANAGER OF
STARTING TO COMPUTERS X86 PC COMPATIBLE TO BEGIN IN REAL
MODE.
Computers that start in real mode perform a process called POST (Power On
Selft) responsible of verifying that the pc hardware is works properly, loads into
memory the interruptions of BIOS (Basic Input / Output System), searches a
boot device (hard drive, floppy drive, DVD, etc.), loads memory boot code and
grants processing of the pc, this code is so-called MBR (Master Boot Record).
The bootloaders; which have the MBR code as a module, they inject the MBR
into of the storage devices (hard disk, CDs, dvs etc.) making them become
bootloaders.
The aim of the present project is to give an overview about how a bootloader
works; which is necessary for the PC to recognize a boot device, understand
how the MBR code is developed in assembly language and C language; as this
transformed into machine language; as this is understood and executed by the
pc. Having an understanding of how the hardware and software of the boot
loader interact in order to provide to the machine "intelligence". A study about
NTLDR, GRUB LEGACY, will be implemented, GRUB LEGACY will be modified
and built, and new MBR well be developed.
DESCRIPTORS:
ASSEMBLY LANGUAGE / LANGUAGE C / Bootloader / MANAGER START /
GRU / GCC.
XVI
CERTIFICADO DE TRADUCCIÓN
Quito 04 de Abril del 2105
CERTIFICADO DE TRADUCCIÓN
EL M. Sc. IZA PIARPUEZAN CARLOS EDUARDO, identificado con cedula de ciudanía
1719197764, con título de tercer nivel en LICENCIADA EN CIENCIAS DE LA EDUCACIÓN
MENCIÓN INGLES, de la Universidad Central del Ecuador.
CERTIFICA:
Que el documento anexo del resumen del tema de tesis denominado: ESTUDIO, DESARROLLO E
IMPLEMENTACIÓN DE UN GESTOR DE ARRANQUE PARA COMPUTADORAS PC COMPATIBLES
X86 QUE INICIAN EN MODO REAL, redactado en idioma español es traducción fiel y completa al
idioma inglés.
El interesado puede hacer uso del presente documento conforme lo considere necesario.
Atentamente
M. Sc. IZA PIARPUEZAN CARLOS EDUARDO.
XVII
TÍTULO DEL TRADUCTOR
XVIII
INTRODUCCIÓN
Los gestores de arranque son los encargados de iniciar un determinado
Sistema Operativo ya sea propietario o software libre, es decir es el primer
fragmento de código que la computadora lee y ejecuta desde un dispositivo de
arranque.
La mayoría de gestores de arranque se dividen en dos etapas.
La primera etapa consiste en un fragmento de código la mayoría de veces
escrito en lenguaje ensamblador que debe ocupar un tamaño exacto de 512
bytes cuyos bytes 511, 512 deben ser 0x55 y 0xAA respectivamente, la
principal función de la primera etapa es buscar, cargar a memoria la segunda
etapa y ceder el procesamiento de la pc a esta.
La segunda etapa es cargada y cedida el procesamiento de la pc por la primera
etapa, la principal función de la segunda etapa es encontrar el kernel del
Sistema Operativo que se desea iniciar, cargarlo a memoria y transferir el
procesamiento de la pc a este.
El presente documento da a conocer el estudio, desarrollo, alcance e
implementación de un gestor de arranque para computadoras pc compatibles
x86 que inician en modo real.
El principal objetivo del presente trabajo de investigación es modificar el código
de un gestor de arranque de software libre, entender su funcionamiento y
desarrollar un gestor de arranque para computadoras pc compatibles x86. Para
lo cual se realizara un estudio de los principales gestores de arranque en la
actualidad, su estructura lógica y física, como son cargados a memoria, como
son ejecutados por la BIOS al prender el computador, como se comunican con
el hardware y como inician un determinado sistema operativo.
1
CAPITULO 1
1.
PRESENTACION DEL PROBLEMA
1.1
Planteamiento del Problema
Sin un software una computadora es una máquina inservible que tiene partes
electrónicas y mecánicas interconectadas, El software es la parte fundamental
de la llamada “inteligencia” de las computadoras. El software es el que le
proporciona la capacidad de almacenar información correctamente ordenada
para su posterior uso. Los algoritmos de software del sistema operativo
mantienen toda la complejidad de manejo del hardware de la pc alejado de las
aplicaciones que sobre él se ejecutan.
El principal software de una computadora es el Sistema Operativo ya que este
es el encargado de gestionar, planificar, asegurar el correcto funcionamiento de
las aplicaciones que sobre el corren.
Los sistemas operativos no dan ninguna funcionalidad al usuario final motivo
por el cual no genera valor. Pero los sistemas Operativos permite que las
aplicaciones que el usuario final utiliza se ejecuten creando así dependencia del
Sistema Operativo.
Los gestores de arranque son los encargados de crear un código denominado
bootloader que es inyectado en los dispositivos de almacenamiento para que
cuando la pc encienda cargue a memoria el bootloader, el bootloader tiene por
objetivo encontrar el kernel del sistema operativo descomprimirlo cargarlo a
memoria y pasarle el control de la pc. Así el primer código que dota de
“inteligencia” al computador es un gestor de arranque.
Todo Sistema Operativo tiene una organización o autor que desarrollo dicho
Sistema Operativo, como por ejemplo en el caso de Unix cuyo propietario es la
compañía
AT&T. En la década de 1970 Unix se puso a disposición de
Universidades, Compañías y al gobierno de EEUU por medio de licencias, las
2
cuales permitían a los investigadores revisar el código fuente de Unix. Hasta en
1977 la Universidad de Berkeley desarrollo, público y licencio un sistema
operativo muy parecido a Unix, el cual fue nombrado Berkeley Software
Distribution (BSD), que represento una notable competencia para UNIX.
AT&T percatándose de lo riesgoso que es ofrecer el código UNIX para
investigación decide a partir de la v7, restringir este beneficio. Así los
investigadores del código de UNIX ya tenían prohibido su revisión.
Andrew S. Tanenbaum que impartía clases de Sistemas Operativos en la
Universidad Libre de Ámsterdam, en vista de que ya no podía dar clases
impartiendo el código fuente de UNIX desarrollo un nuevo sistema operativo al
cual nombro MINIX por ser un clon de Unix pero mucho más pequeño para que
sus alumnos lo puedan entender en el transcurso de un semestre.
Este hecho nos indica que cualquier software por más licencias de código libre
que tenga, estas puedes hacerse más restrictivas, privando así a los
investigadores de los código fuente estudiar la estructura del software, proponer
cambios, mejoras etc.
Contextualización
El estudio, modificación y desarrollo de un gestor de arranque deja un
entendimiento claro de cómo el código fuente de un programa es transformado
a lenguaje maquina o binario y como este da funcionalidad a las partes de la
computadora en cada ciclo de reloj de la pc.
La manera más segura de dejar de depender de Sistemas Operativos
desarrollados en otros países es desarrollar un sistema operativo propio y este
debe estar en constante evolución por parte de una institución educativa como
la Universidad Central del Ecuador, o de una empresa puramente ecuatoriana,
solo así seremos independientes al menos en lo que respecta al software.
3
1.2
Formulación del Problema
¿Cuál es la ventaja de desarrollar el Proyecto de Estudio, Desarrollo E
Implementación De Un Gestor De Arranque Para Computadoras Pc
Compatibles X86 Que Inician En Modo Real?
1.3
Justificación
Las principales industria del software venden o dan soporte a aplicaciones que
se ejecutan en un determinado sistema operativo, creando así negocio para la
aplicación que están ofreciendo y dependencia de su sistema operativo.
Un sistema operativo es iniciado por un gestor de arranque que es el
responsable de descomprimirle cargarlo a memoria y cederle el control de la pc.
Los gestores de arranque propietarios o de software libre están en continua
evolución. Una vez que el código fuente base ya no se adecua al hardware
nuevo se vuelve a rescribir todo el código como es el caso de GRUB, gestor de
arranque más utilizado por las distribuciones Linux.
La manera de crear independencia en software es desarrollar un sistema
operativo y por ende el gestor de arranque que lo inicia.
El desarrollo del presente trabajo de fin de carrera permitirá aportar a la
comunidad a través del sitio web http://www.softwaredesarrollo.com/, software
de gestor de arranque en su formato binario, cuyo código será libre y
documentado técnicamente, además se facilitara el proceso que se llevó a cabo
y las herramientas de software libre que se utilizaran para la construcción del
gestor de arranque.
Se aportara a través del sitio web http://www.softwaredesarrollo.com/, como se
logró modificar el gestor de arranque GRUB, indicando el proceso que se utilizó
y las herramientas en software libres ocupadas.
4
La importancia del presente trabajo de tesis radica en dar a conocer la
importancia de los gestores de arranque al iniciar la pc, y demostrar que su
complejidad se la puede investigar con los conocimientos obtenidos en la
carrera de Ingeniería Informática, proporcionando así más documentación y
herramientas a las personas que deseen realizar una investigación sobre los
gestores de arranque.
1.4
Objetivos de la Investigación
1.4.1 Objetivo General
Modificar y desarrollar un software de gestor de arranque para computadoras pc
compatibles x86 que inician en modo real.
1.4.2 Objetivos Específicos

Poner a disposición de la comunidad, software de un gestor de
arranque documentado,
las herramientas necesarias para su
construcción, ejecución con el objetivo de facilitar su estudio, mejora y
solución
de
errores
etc.
A
través
del
sitio
web
www.softwaredesarrollo.com.

Realizar un estudio de los principales gestores de arranque que
existen en el mercado.

Modificar un gestor de arranque de software libre.

Desarrollar un gestor de arranque básico.

Difundir la importancia de crear gestores de arranque y sistemas
operativos a nivel de un país.
5
1.6
Alcance
La investigación
y desarrollo del presente tema
de fin de carrera tiene el
siguiente alcance:

Investigar el funcionamiento lógico y práctico del gestor de arranque
GRUB LEGACY, su código fuente y el software necesario para su
construcción y ejecución.

Indicar la importancia de desarrollar software a nivel de lenguaje
ensamblador para la creación y modificación de gestores de arranque.

Modificar el gestor de arranque GRUB LEGALICY, indicar el proceso y
las herramientas necesarias para su modificación, así también las
herramientas necesarias para procesar, ensamblar y enlazar el software
modificado.

Crear un software de gestor de arranque básico.

El gestor de arranque está restringido a pc compatibles x86 que inician
en modo real.

El gestor de arranque podrá ejecutarse a través del disco duro, CD y
Usb.

Diseñar,
desarrollar
e
implementar
el
sitio
web
www.softwaredesarrollo.com.

Poner a disposición de la comunidad toda la documentación y software
libre que se genere del desarrollo del tema de fin de carrera a través del
sitio web www.softwaredesarrollo.com.
6
1.7
Limitaciones
Para la investigación y desarrollo del presente tema de tesis se presentaron las
siguientes limitaciones:

No se tiene documentación, código de los gestores de arranque
propietarios.

Utilizar las librerías de GNU GCC para compilar los programas
desarrollados en lenguaje en ensamblador y lenguaje c.

Se tuvieron que emplear herramientas de software libre de ingeniería
inversa para investigar la estructura de los gestores de arranque de
código propietario.

Al utilizar herramientas de software libre se tiene el inconveniente de no
con contar con suficiente documentación para la modificación y
construcción del gestor de arranque, lo cual demora su investigación y
construcción.

Se contrató un web hosting en una empresa privada para aportar a la
comunidad el trabajo desarrollado.
7
1.8
Contribuciones
Las contribuciones que se lograría al desarrollar el presente tema de fin de
carrera son:

Aportar a la comunidad la importancia de crear software que se pueda
ejecutar sin la necesidad de un sistema operativo.

Aportar como se logró modificar el gestor de arranque más utilizado por
las distribuciones Linux su reconstrucción y ejecución en este caso
GRUB LEGACY.

Aportar a la comunidad el sitio web www.softwaredesarrollo.com.
Diseñado, desarrollado e implementado por el autor del tema de fin de
carrera.

A través del sitio web www.softwaredesarrollo.com, la comunidad podrá
descargar el software y documentación que se genere del desarrollo del
tema de fin de carrera.

Aportar con código fuente, técnicamente documentado, de libre
descarga, modificación y ejecución.

Proporcionar las herramientas en software libre y el proceso que se
realizó para la construcción del gestor de arranque.

Aportar como guía de aprendizaje para todos aquellos programadores
que deseen introducirse el desarrollo de bajo nivel, y su combinación con
lenguaje c.
8
1.9
Herramientas
Para el desarrollo modificación e investigación sobre los gestores de arranque
son necesarias las siguientes herramientas en software y hardware:
1. Hardware Computador

PC de 64 bits
2. Software

Sistema operativos host
i. Windows 7 de 64 bits.

Máquina Virtual
i. Virtual Box
ii. Bochs
iii. Quemu

Sistemas operativos huéspedes
i. Windows 98.
ii. Windows Xp de 32 bits
iii. Windows 7 de 64 bits
iv. Linux Centos de 32 bits
v. Linux Centos de 64 bits
vi. Linux Fedora

Aplicaciones
i. Gnu gcc diferentes versiones
ii. HexEdit 32 y 64 bits
iii. Nasm
iv. Alink
v. Gnu as
vi. Gnu link
9
CAPITULO 2
2.
MARCO METODOLÓGICO
2.1
Diseño de la Investigación
El presente trabajo de fin de carrera desea implementar la importancia de
generar un gestor de arranque y un sistema operativo a nivel de universidad,
tomando como caso de uso la historia y evolución de los sistemas operativos
sus gestores de arranque, la gran dependencia que genera un sistema
operativo para el usuario final de una pc.
La investigación a realizar en este proyecto es una investigación experimental
que va permitir por medio de la manipulación del código del gestor de arranque
de software libre GRUB investigar su funcionamiento, lo cual generará
experiencia y documentación.
Con el conocimiento obtenido procederemos a desarrollar un prototipo de un
gestor de arranque desde cero.
La documentación técnica y de usuario que se generará será puesta a
disposición de la comunidad a través del sitio web www.softwaredesarrollo.com
el cual es desarrollado y administrado por el autor del tema de tesis, la
comunidad interesada puede estudiar, ofrecer mejoras, cambios etc. Asi
logrando
conocimiento y el interés por desarrollar software a bajo nivel y
desarrollo de sistemas operativos.
Para el desarrollo y la implementación del diseño de la investigación se deben
estudiar los siguientes hechos y la siguiente teoría. Con el fin de profundizar en
el tema y tener argumentos que respalden las decisiones tomadas en el
presente tema de tesis.
10
2.2
Antecedentes
Los gestores de arranque aparecen con el desarrollo de los sistemas operativos
ya que el gestor de arranque es el encargado de ejecutar un determinado
sistema operativo cuando se inicia el encendido de la computadora.
El gestor de arranque no es parte del sistema operativo, este el encargado de
cargar a memoria el kernel del sistema operativo. Una vez cargado el kernel el
sistema operativo no utiliza ninguna librería del gestor de arranque para su
continuo funcionamiento.
Los gestores de arranque han evolucionado conforme evolucionaron los
sistemas operativos, pero los gestores de arranque siguen iniciando su
ejecución en modo real para tener compatibilidad con hardware antiguo.
Existen varios gestores de arranque en el mercado entre los más principales
tenemos:

GRUB, LILO.- Gestores de arranque de Linux están bajo licencia GNU
GPLv3 y BSD respectivamente.

NTLDR.- Gestor de arranque de Windows, bajo licencia de Microsoft.

BOOTX (Apple).- Gestor de arranque de Mac OSX, bajo licencia de
Apple.
Al investigar los gestores de arranque se comprenderá el funcionamiento
interno del computador y los concepto de BIOS, hardware, memoria
procesador, sistemas de archivos, disco duro, tarjeta de video, pixeles, sistema
de numeración binaria, hexadecimal y decimal, así como la comunicación entre
los distintos dispositivos de la PC, lenguaje ensamblador y lenguaje C.
11
2.3
Fundamentación Teórica
A continuación se presenta la fundamentación teórica y las herramientas de
software libre que se requieren para la investigación, modificación y desarrollo
de un gestor de arranque.
2.3.1 Evolución De Los Sistemas Operativos y Computadores
Los sistemas operativos dan la plataforma para que las aplicaciones finales de
usuario se puedan ejecutar, es decir ocultan la parte fea con la parte hermosa,
como se muestra en la figura 1.
Figura 1. Abstracción de Interfaz Aplicaciones y S.O.
Autor: Andrew S. Tanenbaum.
Fuente: Sistemas Operativos Modernos 3ra edición.
Los sistemas operativos han estado estrechamente relacionados a través de la
historia con la arquitectura de las computadoras en las que se ejecutan.
La primera computadora digital verdadera fue diseñada por el matemático
inglés Charles Babbage, la cual nunca logró funcionar de manera apropiada,
debido a que era puramente mecánica y la tecnología de su era no podía
producir las ruedas, engranes y dientes con la alta precisión que requería. La
máquina analítica no tenía un sistema operativo.
12
2.3.1.1 Primera Generación (1946-1958)
En esta época las computadoras eran sumamente grandes, utilizaban gran
cantidad de electricidad, generaban gran cantidad de calor y eran sumamente
lentas. Funcionaban con válvulas de vacio, usaban tarjetas perforadas para
ingresar los datos y los programas, utilizaban cilindros magnéticos para
almacenar información e instrucciones internas y se utilizaban exclusivamente
en el ámbito científico o militar. La programación implicaba la modificación
directa de los cartuchos,
2.3.1.2 Segunda Generación (1955 a 1965)
Las computadoras usaban transistores para procesar información, usaban
pequeños anillos magnéticos para almacenar información e instrucciones.
Producían gran cantidad de calor y eran sumamente lentas. Se mejoraron los
programas de computadoras que fueron desarrollados durante la primera
generación.
Se desarrollaron nuevos lenguajes de programación como COBOL y
FORTRAN, los cuales eran comercialmente accesibles. Y se desarrolló el
sistema de procesamiento por lotes.
Figura 2. Procesamiento por Lotes
Autor: Andrew S. Tanenbaum.
Fuente: Sistemas Operativos, Diseño e implementación 2da edición.
En la segunda generación las maquinas no tenían sistemas operativos.
13
2.3.1.3 Tercera Generación (1965 a 1980)
Comienza a utilizarse los circuitos integrados, lo cual permitió abaratar costos al
tiempo que se aumentaba la capacidad de procesamiento y se reducía el
tamaño de las máquinas. La tercera generación de computadoras emergió con
el desarrollo de circuitos integrados (pastillas de silicio) en las que se colocan
miles de componentes electrónicos en una integración en miniatura. El PDP-8
de la Digital Equipment Corporation fue el primer miniordenador.
Se diseñó el sistema conocido como MULTICS (MULTiplexed Information and
Computing Service, Servicio de Información y Cómputo MULTiplexado), fue un
éxito parcial. Se diseñó para dar soporte a cientos de usuarios en una máquina
que era sólo un poco más potente que una PC basada en el Intel 386.
Posteriormente, Ken Thompson, uno de los científicos de cómputo en Bell Labs
que trabajó en el proyecto MULTICS, encontró una pequeña minicomputadora
PDP-7 que nadie estaba usando y se dispuso a escribir una versión simple de
MULTICS para un solo usuario. Más adelante, este trabajo se convirtió en el
sistema operativo UNIX, que se hizo popular en el mundo académico, las
agencias gubernamentales y muchas compañías.
2.3.1.4 Cuarta Generación (1965 a 1980)
Está caracterizada por la integración sobre los componentes electrónicos, lo
que propició la aparición del microprocesador, es decir un único circuito
integrado en el que se reúnen los elementos básicos de la máquina. Se
desarrolló el microprocesador con micro compactación. Se colocan más
circuitos dentro de un "chip". "LSI - Large Scale Integration circuit". "VLSI - Very
Large Scale Integration circuit". Cada "chip" puede hacer diferentes tareas. Un
"chip" sencillo actualmente contiene la unidad de control y la unidad de
aritmética/lógica. El tercer componente, la memoria primaria, es operado por
otros "chips". Se reemplaza la memoria de anillos magnéticos por la memoria
de "chips" de silicio. Se desarrollan las microcomputadoras, computadoras
personales o PC. Tambien se desarrollan las supercomputadoras.
14
2.3.1.5 Historia Hechos Relevantes
Cuando Intel presentó el microprocesador 8080 en 1974, pidió a uno de sus
consultores, Gary Kildall, que escribiera un sistema operativo para dicho
procesador. Kildall escribió un sistema operativo basado en disco conocido
como CP/M (Control Program for Microcomputers; Programa de Control para
Microcomputadoras)
Kildall compro los derechos de CP/M. y formó una compañía llamada Digital
Research para desarrollar y vender el CP/M. Se escribieron muchos programas
de aplicación para ejecutarse en CP/M, lo cual le permitió dominar por completo
el mundo de la micro computación durante un tiempo aproximado de 5 años.
A principios de la década de 1980, IBM diseñó la IBM PC, y busco un sistema
operativo, contactaron con Bill Gates y Gary Kildall, terminaron negociando con
Bill Gates, y el fundo Microsoft con el sistema operativo MS-DOS,
posteriormente se fueron dando evoluciones apareciendo Windows 95,
Milinium, XP, Windows 7 etc.
Andrew´s Tanenbaum viéndose limitado por el cambio del licencia de AT&T de
no poder enseñar su código, en 1987 libera un clon de UNIX llamado MINIX el
cual tiene un objetivo puramente educacional.
El deseo de una versión de producción (en vez de educativa) gratuita de MINIX
llevó al estudiante finlandés, llamado Linus Torvalds, a escribir Linux. Este
sistema estaba inspirado por MINIX, además de que fue desarrollado en este
sistema y originalmente ofrecía soporte para varias características de MINIX
(por ejemplo, el sistema de archivos de MINIX).
Linus Tolvards y la organización FFS (Free Software Foundation) de Richard
Stallman se fusionan y se desarrolla el sistema operativo conocido como GNU
Linux.
15
2.3.2 Microprocesador
2.3.2.1 Concepto
Es un circuito electrónico sumamente integrado que actúa como unidad central
de proceso de un ordenador.
El microprocesador ejecuta instrucciones almacenadas como números binarios
organizados secuencialmente en la memoria principal. La ejecución de las
instrucciones se puede realizar en varias fases. Cada una de estas fases se
realiza en uno o varios ciclos de CPU, dependiendo de la estructura del
procesador y concretamente de su grado de segmentación. La duración de
estos ciclos viene determinada por la frecuencia de reloj y nunca podrá ser
inferior al tiempo requerido para realizar la tarea individual.
2.3.2.2 Evolución del microprocesador
Los microprocesadores nacieron de la evolución de los circuitos integrados.
1971: El Intel 4004
El 4004 fue el primer microprocesador del mundo
en un simple chip, fue
desarrollado por Intel. Era un CPU de 4 bits y también fue el primero disponible
comercialmente. Originalmente diseñado para la compañía japonesa Busicom
para ser usado en su línea de calculadoras, dio camino a la manera para dotar
de «inteligencia» a objetos inanimados, así como la computadora personal.
Microprocesador
Año
Fabricante
4004
1971 Intel
8086
AMD, Harris,
Mostek, Fujitsu,
1978
NEC, Toshiba,
OKI, Siemens
80286
1982
80386
1985 Intel
AMD, Harris,
IBM, Siemens
Bits
Pins
Clock
Caracteristicas
4
16-dip
.1MHz
Primer
Microprocesador
16
40
510MHz
Primer 16-bit CPU;
8088 (1979); IBM PC
(1981)
16
68LCC/PGA
6 MHZ20MHz
32
132-PGA
1633MHz
16
Soporta Memoria
Virtual; IBM PC AT
(1984)
Primer 32-bit CPU;
Cache; Multitarea
Microprocesador
80486
Año
1989
Fabricante
Intel
Bits
Pins
32
16PGA,176TQFP
Clock
100MHz
Pentium
1993
Intel
32
273PGA,320TCP
60MH233Mhz
Pentium II
1997
Intel
32
528-LGA, 615BGA
233MH500Mhz
Pentium III
1999
Intel
32
370-PGA2, 495BGA2
400M1Ghz
Pentium 4
2000
Intel
32
423-PGA, 478PGA
1.52Ghz
Multi Core
2006
Intel
64
479-775
1-3Ghz
i3,i5,i7
2008
INTEL
64
437-1366
1.6 3.5Ghz
Athlon
Sempron64
2011
AMD
64
939
2800+
hasta
3600
Athlon 64
2011
AMD
64
939
3000+
hasta
3800
Athlon 64 con
Socket AM2
2011
AMD
64
939
3200+ y
3800
Athlon 64 X2
2011
AMD
64
939
3800+h
asta
4800
Caracteristicas
Cache nivel L1
Superscalar: 2IU, 1-FPU; MMX
(1995)
RISC 2-IU,2FPU,3-LDST, 2MMX; Xeon,
Celeron
2-IU,2-FPU,3LDST, 2-MMX, 2SSE; Mobile (M)
HT (2002); 4M
(2003); Xeon MP
(2003); Centrino
(2003)
D (2005); Core 2
(2006); Dual
Core (2006);
Quad Core
(2007)
i7-920 (2008): 4
cores; i7-980
(2011): 6 cores
Athlon
Sempron64 con
socket AM2
Athlon 64 con
Socket 939,
Nucleos Venice
y Manchester
Athlon 64 con
Socket AM2.
Athlon 64 X2
con Socket 939,
dos micros en
en el mismo
espacio,
Tenemos dos
núcleos:
Manchester,
Toledo
Tabla 1. Evolución De Los Microprocesadores.
Autor: Tesista
Fuentes: http://www.wadalbertia.org/docs/EvolucionProcesadoresIntel.pdf.
http://www.intel.la/content/www/xl/es/homepage.html.
17
2.3.2.3 Arquitectura
El microprocesador se compone de un grupo de unidades interrelacionadas
como se muestra en la figura 3.
Aunque la arquitectura del microprocesador varía considerablemente de un
diseño a otro, el diseño se basa en la arquitectura del microprocesador 8086.
Figura 3. Arquitectura de Microprocesador o CPU 8086.
Autor: Tesista.
Fuente: http://es.wikipedia.org/wiki/Intel_8086_y_8088.
18
2.3.2.4 Registros
En la siguiente tabla se muestran los registros del procesador 8086, su número,
tamaño y su uso común en la programación.
Tipo de registro
De propósito general
De segmento
Apuntador de instrucción
Apuntadores
Número y tamaño
4 registros de 16 bits
4 registros de 16 bits
1 registro de 32 bits
4 registros de 16 bits
Descripción
Almacenan datos. Para uso del programador
Permiten direccionar la memoria
Apunta a la siguiente instrucción a ejecutar
Se usan para direccionar memoria.
Tabla 2. Registros del Microprocesador 80386.
Autor: Tesista.
Fuente: Conocimientos adquiridos del tesista.
Registros de Propósito General: Los registros de propósito general AX, BX,
CX y DX son los únicos que se pueden direccionar como una palabra o como
una parte de un byte. El último byte de la izquierda es la parte "alta", y el último
byte de la derecha es la parte "baja".
Registro
ax
bx
cx
dx
Descripción
Acumulador para operaciones aritmético lógicas
Registro base para acceder a memoria
Contador para algunas instrucciones
Registro de datos usado para algunas operaciones de entrada/salida
Tabla 3. Uso común de los registros de propósito general.
Autor: Tesista.
Fuente: Conocimientos adquiridos del tesista.
Registros de Segmento: Se utilizan para referenciar áreas de memoria. La
siguiente tabla muestra los registros de segmento de los microprocesadores
compatibles x86 y su uso en la programación.
Registro de segmento
cs
ds
ss
es
fs
Descripción
Segmento de código
Segmento de datos
Segmento de pila
segmento extra
segmento extra
Tabla 4. Uso común de los registros de segmento.
Autor: Tesista.
Fuente: Conocimientos adquiridos del tesista.
19
El contenido de los registros de segmento es interpretado de diferente forma
dependiendo si el procesador se encuentra trabajando en modo real o en modo
protegido.
Registros Apuntadores: La función común de los registros apuntadores es
contener la dirección de memoria de una estructura de datos o código, ya sea
para acceder a un elemento de la estructura, también como apuntador de base
inicial o final de la estructura en memoria.
Registro
ip
di
si
sp
bp
Descripción
Apuntador de instrucción o contador de programa
Apuntador a destino para operaciones con cadenas de caracteres
Apuntador a origen para operaciones con cadenas de caracteres
Apuntador de pila
Apuntador de marco o base de pila
Tabla 5. Registros apuntadores del microprocesador.
Autor: Tesista.
Fuente: Conocimientos adquiridos del tesista.
Entre los registros apuntadores el más principal es el apuntador de instrucción o
contador de programa.
Registro IP o Contador de Programa: Es un registro que almacena la
dirección donde se encuentra la siguiente instrucción del programa a ejecutar.
La unidad de control va incrementando el valor de este registro a medida que
recupera instrucciones y los operandos asociados. También lo modifica cuando
se ejecuta un salto, condicional o incondicional, estableciendo la nueva
dirección de la que se recuperarán los códigos de instrucción.
Registro SI (source index): El registro índice fuente de 16 bits es requerido
por algunas operaciones con cadenas de caracteres.
Registro DI (destination index): El registro índice destino (destination index)
también es requerido por algunas operaciones con cadenas de caracteres.
20
Registro SP (stack pointer): El apuntador de pila de 16 bits está asociado con
el segmento SS y proporciona un valor de desplazamiento que se refiere a la
palabra actual que está siendo procesada en la pila.
Registro BP (base pointer): El apuntador base de 16 bits facilita la referencia
de parámetros dentro de la pila.
Banderas: Proveen una manera de obtener información acerca del estado
actual de la máquina y el resultado de procesamiento de una instrucción.
Bandera
CF
PF
AF
ZF
SF
TF
IF
DF
OF
Bit
0
2
4
6
7
8
9
10
11
Descripción
Bandera de acarreo (carry flag)
Bandera de paridad (parity flag)
Bandera de acarreo auxiliar (adjust flag)
Bandera de cero (zero flag)
Bandera de signo (sign flag)
Bandera de depuración(trap flag)
Bandera de Interrupcion(interruption flag)
Bandera de dirección (direction flag)
Bandera de desbordamiento (overflow flag)
Tabla 6. Banderas del microprocesador.
Autor: Tesista.
Fuente: Conocimientos adquiridos del tesista.
CF (carry flag): Después de una operación aritmética contiene el acarreo del bit
de mayor orden, también almacena el contenido del último bit en una operación
de desplazamiento o de rotación, es decir se activa en un uno cuando existe
acarreo después de una operación aritmética.
PF (parity flag): Indica si el número de bits 1 despues de una operación es par
(0=número de bits 1 es impar; 1=número de bits 1 es par).
AF (adjust flag): Se pone a 1 si se produce un acarreo entre los bits 7 y 8
trabajando con 16 bits o entre los bits 3 y 4 trabajando con 8 bits. Se utiliza para
ajustes decimales en operaciones en BCD.
ZF (zero flag): Se pone a 1 cuando el resultado de la última operación es cero,
o cuando al comparar dos cadenas el resultado es de igualdad.
21
SF (sign flag): Se pone a 1 si el resultado es negativo, o cuando al comparar
dos cadenas, el resultado es de no igualdad.
TF (trap flag): Permite la operación del procesador en modo de depuración
(paso a paso).
IF (interruption flag): Controla el disparo de las interrupciones (1=habilita las
interrupciones;
0=deshabilita
las
interrupciones).
La
interrupción
no
enmascarable es la única que no puede ser bloqueada por esta bandera. El
estado de la bandera IF se controla con las instrucciones STI y CLI.
DF (direction flag): Controla la selección de incremento o decremento de los
registros SI y DI en las operaciones con cadenas de caracteres (1=decremento
automático; 0=incremento). La bandera DF se controla con las instrucciones
STD y CLD.
OF (overflow, desbordamiento): Indica desbordamiento del bit de mayor
orden después de una operación aritmética de números con signo (1=existe
overflow; 0=no existe overflow). Para operaciones sin signo, no se toma en
cuenta esta bandera.
2.3.2.5 Unidad aritmética lógica
Es el elemento que lleva a cabo las operaciones aritméticas, como suma, resta
y lógicas al nivel de bits según el álgebra de Boole.
En la mayoría de los casos la ALU (Arithmetic Logic Unit) asume como
operando implícito el dato almacenado en el acumulador pudiendo existir según
la instrucción a ejecutar operandos
adicionales. También influye en su
funcionamiento el contenido del registro de estado.
22
Figura 4. Esquema de Bloques de una ALU Típica.
Autor: Tesista.
Fuente: Lenguaje ensamblador 2009 - Fco. Charte Ojeda pag 38.
Sobre la base de esta arquitectura abstracta, cada fabricante lleva a cabo la
arquitectura física de sus microprocesadores según parámetros reales: ancho
de palabra, ancho del bus de direcciones, cantidad de registros internos,
operaciones que pueda llevar a cabo la ALU, etc.
Para ejecutar cada instrucción la CPU realiza los siguientes pasos:
1. Leer de la memoria la instrucción a ejecutar y guardarla en un registro
interno de la CPU.
2. Identificar la instrucción que acaba de leer.
3. Comprobar si la instrucción necesita datos que se encuentran en
memoria, si es el caso, determina la localización de los mismos.
4. Buscar los datos en memoria y guardarlos en registro dentro de la CPU.
5. Ejecutar la instrucción.
6. El resultado puede ser almacenado en memoria o retenido esperando la
siguiente instrucción o incluso generar comunicación con otros
elementos externos a la CPU.
7. Comienza un nuevo ciclo empezando con el primer paso.
23
2.3.3 Memoria
La memoria es la parte del ordenador en la que se guardan o almacenan los
programas (las instrucciones y los datos).
Figura 5. Memoria Típica.
Autor: Tesista.
Fuente: http://www.cem-sa.com.mx/products-page/subensambles/ram/memoria-ram-2gbddr3-kingston-1333mhz-pc/
Los datos almacenados en memoria tienen que pasar, en un momento u otro, al
microprocesador para que éste pueda servirse de ellos y, en caso necesario,
manipularlos.
La división de memorias entre primario, secundario, terciario, fuera de línea, se
basa en la distancia desde la CPU a la memoria.
2.3.3.1 Tipos de Memoria
A las memorias usadas en la pc se las puede clasificar en dos tipos básicos, la
memoria RAM y la memoria ROM.
2.3.3.1.1 Memoria RAM
La Memoria de Acceso Aleatorio (Random Access Memory) es una memoria
construida sobre semiconductores donde la información se almacena en celdas
de memoria que pueden adquirir uno de los dos valores del código binario.
Las memorias de acceso aleatorio son memorias en la que se puede leer y
escribir información. Permite el acceso a cualquier información que contenga
24
con la misma velocidad. Esto significa que se puede acceder aleatoriamente a
cualquier información almacenada sin que se afecte la eficiencia del acceso.
Requiere energía constante para mantener la información almacenada es decir
sin energía pierde todos los datos.
2.3.3.1.1 Memoria ROM
Memoria de solo lectura (read-only memory), utilizado en ordenadores y
dispositivos electrónicos, que permite solo la lectura de la información y no su
escritura, independientemente de la presencia o no de una fuente de energía.
Los datos almacenados en la ROM no se pueden modificar, o al menos no de
manera rápida o fácil. Sin embargo, las ROM más modernas, como EPROM y
Flash EEPROM, efectivamente se pueden borrar y volver a programar varias
veces, aun siendo descritos como "memoria de sólo lectura" (ROM).
Retiene la información almacenada incluso si no recibe corriente eléctrica
constantemente.
La siguiente tabla muestra las características de las memorias usadas en una
computadora.
Tipo Memoria
Random Access
Memory (RAM)
Read Only Memory
(ROM)
Programmable ROM
(PROM)
Propósito
Memoria Lec/Esc
Memoria de solo
Lectura
Erasable PROM
(EPROM)
Memoria Flash
Electrically Erasable
PROM (EEPROM)
Memoria sobre
todo de Lectura
Borrado
Eléctrico a
nivel byte
Modo de
Escritura
Eléctricamente
Volatilidad
Volátil
Máscaras
No Posible
Luz UV a
nivel chip
Eléctrico a
nivel bloque
No Volátil
Eléctricamente
Eléctrico a
nivel byte
Tabla 7. Tipos de Memoria.
Autor: Tesista.
Fuente: Conocimientos adquiridos del tesista.
25
2.3.3.2 Memoria Principal
La memoria principal en una computadora es una memoria de acceso aleatorio
o RAM. Esta es la parte de la computadora que almacena software del sistema
operativo, software de aplicaciones y otra información para la unidad central de
procesamiento (CPU) y así tener acceso rápido y directo cuando sea necesario
para realizar las tareas. Se llama "acceso aleatorio" porque la CPU puede
acceder directamente a una sección de la memoria principal, y no debe
emprender el proceso en un orden secuencial. La memoria principal es uno de
los tipos de memoria más rápidas, y tiene la capacidad de permitir que los datos
sean leídos, escritos y modificados. Cuando la computadora está apagada, todo
el contenido almacenado en RAM se borra. La memoria principal está
disponible en dos tipos: la memoria dinámica de acceso aleatorio (DRAM) y la
memoria estática de acceso aleatorio (SRAM).
2.3.3.3 Arquitectura de la Memoria Principal
La arquitectura de la memoria que se revisara es la de modo real, ya que esta
es la forma de la memoria cuando inicia el funcionamiento de una pc.
Figura 6. Arquitectura de la Memoria Principal.
Autor: Pablo Turmero.
Fuente: http://www.monografias.com/trabajos104/arquitectura-computadorasmemoria/arquitectura-computadoras-memoria.shtml.
26
Memoria Convencional
Los primeros 640 Kb de la memoria del sistema constituyen la memoria
convencional. Este es el área disponible para el uso de los programas DOS
convencionales, junto con muchos controladores, programas residentes. Se
encuentra en la dirección 00000h a 9FFFFh.
Memoria Superior
Está comprendida entre los 640 y los 1024 Kb, ocupando los últimos 384 Kb por
encima de la memoria convencional y por debajo del primer Mb de memoria,
por lo que se puede manejar de manera similar a la memoria convencional,
puesto que está dentro del rango de direccionamiento del microprocesador.
Está constituida por la RAM de video, Memoria Expandida y la Memoria
Shadow o Rom BIOS.
Bloque Memoria RAM de Video
Es donde la imagen sobre la pantalla es almacenada en forma digital, con una
unidad de memoria asignada a cada elemento de la imagen (bit, byte o bytes).
El contenido entero de la memoria es leído de 44 a 75 veces en un segundo
mientras se muestra la imagen sobre la pantalla del monitor. Mientras tanto la
PC puede tratar de escribir una nueva imagen sobre la memoria.
Bloque Memoria Expandida
Este tipo de memoria se diseñó para los microprocesadores inferiores de la
familia x86, es decir, los 8086/8088, cuyo diseño tiene limitado de forma
absoluta el direccionamiento de más de 20 bits. La especificación inicial fue
llamada LIM (Lotus/Intel/Microsoft), mediante la cual se permitía a cualquier PC
el acceso hasta a un máximo de 4 megabytes que se vieron ampliados hasta 8
en la versión L1M 4.0.
¿Cómo puede un 8086/8088 direccionar esto? Muy simple: no puede. Por ello
se utiliza un método bastante antiguo como es la paginación de la memoria.
27
En la paginación se dispone de varios bancos de memoria que se dividen en
páginas de 16 kilobytes. Un circuito integrado especializado, como puede ser el
PPI 8255, se encarga de intercambiar estas páginas, permitiendo ver al
microprocesador sólo algunas de ellas en un determinado momento.
Por lo tanto, el microprocesador sólo puede acceder a algunas de estas
páginas, que se vuelcan en una determinada porción de memoria en el rango
accesible por el microprocesador.
En los sistemas DOS, este tipo de memoria se emplea mediante un controlador,
llamado normalmente EMM.SYS, que añade un nuevo servicio a una de las
interrupciones del DOS. Gracias a ella se puede acceder a esta memoria y
establecer las páginas que deben estar activas en cada momento a través del
marco de página.
Bloque Memoria BIOS
Espacio de BIOS en RAM se detalla más adelante.
Memoria Extendida
En el momento en que aparece el microprocesador 80286, con su capacidad
para direccionar hasta 16 megabytes de memoria gracias al bus de 24 bits,
nace la que se denomina memoria extendida. En un sistema 286 o superior que
tenga más de un megabyte de memoria, ésta puede utilizarse directamente
siempre que trabajemos en el modo nativo del microprocesador, no el de
emulación 8086 o modo real. Pero hay un problema: el DOS no está preparado
para utilizar este modo protegido y facilitar a las aplicaciones el uso de esa
memoria.
Soluciones:
Consiste en utilizar un controlador que trate dicha memoria extendida como
expandida, simulando las páginas y trabajando según el esquema descrito en el
punto previo. Este método tiene la ventaja de permitir que funcionen
28
correctamente muchos programas que están preparados para funcionar
utilizando memoria expandida. Pero es la única ventaja.
La memoria extendida se puede dividir, a su vez, en varias categorías: memoria
alta y memoria extendida propiamente dicha.
Bloque Memoria alta
Son los primeros 64 Kb, menos 16 bytes, del segundo Mb de la memoria de
sistema. Técnicamente son los primeros 64 Kb de la memoria extendida. Suele
ser usada por el DOS para preservar más memoria convencional. Ocupa las
direcciones 100000h a 10FFEFh. Como se ha mencionado anteriormente el
microprocesador 8086 dispone de un bus de direcciones de 20 bit, lo que le
posibilita el acceso a 1 MB de memoria y sus registros son de 16 bits, por lo que
puede acceder a direcciones en el rango de 216 bytes = 64 Kb, pero gracias al
direccionamiento [segmento: dirección] podemos obtener una dirección lineal de
20 bits. Por lo tanto, toda la memoria por encima de la dirección FFFF: 000Fh
no es accesible por medio de un direccionamiento inmediato, puesto que esta
dirección equivale al punto lineal de 0FFFFh*10h+Fh = FFFFFh = 1048575d.
Supongamos la dirección FFFF: 0010h equivalente al punto lineal 1048576d ya
está en el rango de los 21 bits, lo que provocaría el desbordamiento del bus y
su recorte al valor 0. Los microprocesadores más modernos ya cuentan con un
bus de direcciones más grande, por ejemplo el 80286 con 24 bits está
compuesto de 24 líneas: A0, A1, A2,..., A23, anuladas de la línea A20 en
adelante para emular el modo real. Habilitar la línea A20 permite direccionar
localidades en la HMA, puesto que evitaríamos el desbordamiento al acceder a
más de 1 MB. Desde el MS-DOS 5.0 podemos elegir el ubicar su motor en la
HMA, liberando espacio de la memoria convencional para nuestro uso.
29
2.3.4 Manejo de Memoria
Todos los pc en la actualidad al iniciar su funcionamiento están en modo real lo
que es decir se ejecutan como un microprocesador 8086 con todos sus
limitantes de gestión de memoria.
2.3.4.1 Segmentación
Los microprocesador 8086, cuenta externamente con 20 líneas de direcciones,
con lo cual puede direccionar hasta 1 MB (00000h--FFFFFh) de localidades de
memoria. En los días en los que este microprocesador fue diseñado, alcanzar 1
MB de direcciones de memoria era algo extraordinario, sólo que existía un
problema, internamente todos los registros del microprocesador tenian una
longitud de 16 bits, con lo cual sólo se pueden direccionar 64 KB de localidades
de memoria. Resulta obvio que con este diseño se desperdicia una gran
cantidad de espacio de almacenamiento, la solución a este problema fue la
segmentación.
La segmentación consiste en dividir la memoria de la computadora en
segmentos. Un segmento es un grupo de localidades con una longitud mínima
de 16 bytes y máxima de 64 KB.
A cada uno de estos segmentos se le asigna una dirección inicial y ésta es
almacenada en los registros de segmento correspondiente, CS para el código,
DS para los datos, ES para el segmento extra y SS para la pila.
De esta forma, si un programa intentaba acceder a un dato ubicado en el
desplazamiento „D‟ del segmento apuntado por el registro ds, la traducción a
una dirección lineal consistía en tomar el contenido de dicho registro,
multiplicarlo por 0x10 y sumarle el desplazamiento „D‟.
30
Figura 7. Segmentación de Memoria
Autor: Amelia Ferreira © 2008.
Fuente: http://learnassembler.com/regseg.html.
En el modo protegido, el registro de segmento ya no contiene la dirección base
del segmento, sino un selector de segmento, el cual permite seleccionar un
descriptor de segmento. EL descriptor de segmento no es más que una
estructura de ocho bytes, la cual posee un formato definido y contiene entre
otras cosas la dirección base del segmento en cuestión.
Existen otros métodos de gestión de memoria con los microprocesadores
actuales como el manejo de memoria lineal, paginación, paginación
segmentada etc. Estos métodos salen del ámbito de la investigación.
2.3.4.2 Direccionamiento
La capacidad de direccionamiento de un microprocesador viene determinada
directamente por el tamaño de los registros encargados de mantener las
direcciones de memoria y su bus de direcciones.
En el caso de los procesadores x86 éstos son los registros de segmento y otros
que se usan como desplazamiento sobre ese segmento. Los primeros
procesadores de la familia x86, concretamente el 8086 y 8088, eran
microprocesadores de 16 bits, con registros de 16 bits para el direccionamiento.
31
Esto en principio limitaría la cantidad de memoria a la que se puede acceder a
64 Kbyte, lo cual era una limitación.
La solución a este problema fue con la utilización combinada de dos registros,
uno de segmento y otro de desplazamiento, para acceder a una mayor cantidad
de memoria.
2.3.4.3 Modos de Direccionamiento
Los llamados modos de direccionamiento son las diferentes maneras de
especificar en informática un operando dentro de una instrucción. Cómo se
especifican e interpretan las direcciones de memoria según las instrucciones.
Un modo de direccionamiento especifica la forma de calcular la dirección de
memoria efectiva de un operando mediante el uso de la información contenida
en registros y / o constantes, contenida dentro de una instrucción de la máquina
o en otra parte
El tipo de direccionamiento esta en función de los operandos de la instrucción.

Direccionamiento de registro

Direccionamiento inmediato

Direccionamiento directo

Direccionamiento indirecto mediante registro

Direccionamiento indirecto por registro base

Direccionamiento indexado

Direccionamiento indexado respecto a una base
Direccionamiento de Registro
Cuando ambos operando son un registro.
Ejemplo:
MOV AX, BX
Transfiere el contenido de BX en AX
Direccionamiento Inmediato
Cuando el operando origen es una constante.
32
Ejemplo:
MOV AX, 500
Carga en AX el valor 500.
Direccionamiento Directo
Cuando el operando es una dirección de memoria. Ésta puede ser especificada
con su valor entre [ ], o bien mediante una variable definida previamente.
Ejemplo:
MOV BX, [1000]
Almacena en BX el contenido de la dirección de memoria DS: 1000.
MOV AX, TABLA
Almacena en AX el contenido de la dirección de memoria DS: TABLA.
Figura 8. Direccionamiento Directo.
Autor: Amelia Ferreira © 2008.
Fuente: http://learnassembler.com/regseg.html.
Direccionamiento indirecto mediante registro
Cuando el operando está en memoria en una posición contenida en un registro
(BX, BP, SI o DI).
Ejemplo:
MOV AX, [BX]
Almacena en AX el contenido de la dirección de memoria DS: [BX]
33
Figura 9. Direccionamiento indirecto mediante registro.
Autor: Amelia Ferreira © 2008.
Fuente: http://learnassembler.com/regseg.html.
MOV [BP], CX
Almacena en la dirección apuntada por BP en contenido de CX.
Direccionamiento por Registro Base
Cuando el operando esta en memoria en una posición apuntada por el registro
BX o BP al que se le añade un determinado desplazamiento
Ejemplo:
MOV AX, [BP] + 2
Almacena en AX el contenido de la posición de memoria que resulte de sumar
2 al contenido de BP (dentro de segmento de pila). Equivalente a:
MOV AX, [BP + 2]
Figura 10. Direccionamiento por Registro Base
Autor: Amelia Ferreira © 2008.
Fuente: http://learnassembler.com/regseg.html.
34
Este tipo de direccionamiento permite acceder, de una forma cómoda, a
estructuras de datos que se encuentran en memoria.
Direccionamiento Indexado
Cuando la dirección del operando es obtenida como la suma de un
desplazamiento más un índice (DI, SI).
Ejemplo:
MOV AX, TABLA [DI]
Almacena en AX el contenido de la posición de memoria apuntada por el
resultado de sumarle a TABLA el contenido de DI.
Figura 11. Direccionamiento indexado.
Autor: Amelia Ferreira © 2008.
Fuente: http://learnassembler.com/regseg.html.
Direccionamiento Indexado Respecto a Una Base
Cuando la dirección del operando se obtiene de la suma de un registro base
(BP o BX), de un índice (DI, SI) y opcionalmente un desplazamiento.
Ejemplo:
MOV AX, TABLA [BX] [DI]
Almacena en AX el contenido de la posición de memoria apuntada por la suma
de TABLA, el contenido de BX y el contenido de DI.
35
2.3.5 Disco Duro
En informática, un disco duro o disco rígido (Hard Disk Drive, HDD) es
un dispositivo de almacenamiento de datos no volátil que emplea un sistema
de grabación magnética para almacenar datos digitales. Se compone de uno o
más platos o discos rígidos, unidos por un mismo eje que gira a gran velocidad
dentro de una caja metálica sellada. Sobre cada plato, y en cada una de sus
caras, se sitúa un cabezal de lectura/escritura que flota sobre una delgada
lámina de aire generada por la rotación de los discos.
Figura 12. Disco Duro.
Autor: Tesista.
Fuente: http://www.consejosgratis.es/instalar-un-segundo-disco-duro-en-mi-ordenador/.
https://www.hack-urbano.com/como-borrar-por-completo-un-disco-duro/
2.3.5.1 Estructura Física De Un Disco Duro
Figura 13. Estructura Física De Un Disco Duro.
Autor: Tesista.
Fuente:Imágenes Google.
36
1. Gabinete.- Los discos se encuentran en un gabinete herméticamente
sellado, de modo que el aire exterior que contiene una gran cantidad de
partículas suspendidas, no penetren al interior de la unidad, a menos
que pase por unos filtros especiales que retiran todas las partículas
indeseables y permiten el flujo de aire limpio dentro del disco. Si bien, por
algún tiempo se manejó que los discos duros venían al vacío, esto no es
cierto, ya que, para su funcionamiento es indispensable que se forme un
colchón de aire entre la superficie del disco y la cabeza magnética, algo
imposible si la unidad estuviera al vacío.
2. Circuitos Electrónicos.- En la parte exterior del gabinete, hay una placa
de circuitos electrónicos con varios chips que establecen la comunicación
entre la computadora y el interior del disco duro. Esta placa contiene los
circuitos de intercambio de datos, los amplificadores que graban los
datos en la superficie de los platos y aquellos que recogerán los
minúsculos pulsos que captan las cabezas de lectura, amplificándolos y
decodificándolos para enviarlos al microprocesador. También incluye los
conectores para alimentar el disco duro con +5 y +12 volts (hay discos
que trabajan con +5 volts e incluso con menos para máquinas portátiles);
en esta placa también se configura la unidad como disco único, master o
slave. Aun cuando estos elementos básicos conforman un disco duro, es
posible encontrar otros, como un brazo para auto estacionado de cabeza
LED's indicadores de actividad del disco, etc., sin embargo, la estructura
básica de la unidad es la misma.
3. Actuador.- Es un motor que mueve la estructura que contiene las
cabezas de lectura entre el centro y el borde externo de los discos. Un
"actuador" usa la fuerza de un electro magneto empujado contra
magnetos fijas para mover las cabezas a través del disco. La
controladora manda más corriente a través del electro magneto para
mover las cabezas cerca del borde del disco. En caso de una pérdida de
poder, un resorte mueve la cabeza nuevamente hacia el centro del disco
37
sobre una zona donde no se guardan datos. Dado que todas las cabezas
están unidas al mismo “rotor”
ellas se mueven al unísono.
El desplazamiento de las cabezas de lectura/escritura sobre la superficie
de los platos, es necesaria para lograr la recuperación de los datos
almacenados en un disco. En discos antiguos, el desplazamiento lo
realizaba un motor de pasos conectado al brazo donde iban montadas
las cabezas en la actualidad, estos motores han sido sustituidos por una
"bobinas de voz" (voice coil), las cuales permiten movimientos más
precisos
y,
lo
más
importante,
pueden
autocorregir
pequeñas
desviaciones que pudiera haber en el proceso de búsqueda de un track
de información (además de permitir desplazamientos más veloces. Para
su funcionamiento, esta bobina de voz necesita un par de imanes
permanentes que producen un campo magnético de cierta intensidad.
Sumergida en dicho campo, se encuentra la bobina que está adosada en
el brazo de cabezas (puede darse la situación contraria: un imán pegado
al brazo y las bobinas rodeándolo) de modo que cuando circula una
corriente a través de la bobina, por la atracción y repulsión magnéticas, el
brazo de las cabezas tiende a moverse manejando la magnitud de
corriente que circule por la bobina, se puede controlar el desplazamiento
de las cabezas sobre la superficie del disco.
4. Platos de soporte.- La pieza más importante de todo disco duro son uno
o más platos de aluminio, vidrio o cerámica, recubiertos por un fina capa
de material ferromagnético de unas cuantas micras de espesor (de entre
3 y 8 micras en los discos modernos. Aquí es donde, finalmente, se
almacena la información binaria.
5. Brazos.- En un extremo tiene montadas las cabezas magnéticas y en el
otro los elementos necesarios para lograr el desplazamiento de ellas a
través de la superficie del disco.
6. Cabezas de grabación y lectura.- Para realizar la lectura y escritura de
datos en la superficie de los discos, se necesitan dos cabezas de
grabación y lectura, una por cada cara del disco (por supuesto que si hay
38
más de un plato, habrá más cabezas). Las cabezas están unidas por un
elemento al que se denomina "actuador". Antes las cabezas eran simples
piezas de ferrita (similares a las que se incluyen en cualquier grabadora
de casetes casera), pero en la actualidad se fabrican en miniatura, por un
método parecido al de los circuitos integrados (cabezas tipo thin film), o
se trata de complejos elementos magneto-resistivos que permiten
enormes densidades de grabación, redundando en discos cada vez más
pequeños y de mayor capacidad.
7. Preamplificadores.
8. Conexión de Alimentación.
9. Bloque de Configuración (Jumper).
10. Puerto de Entrada/Salida.
2.3.5.2 Estructura Física: Cabezas, Cilindros Y Sectores
Cada una de las dos superficies magnéticas de cada plato se denomina cara. El
número total de caras de un disco duro coincide con el de cabezas. Cada una
de estas caras se divide en anillos concéntricos llamados pistas. Finalmente
cada pista se divide en sectores.
El termino cilindro se utiliza para referirse a la misma pista de todos los discos
de una pila.
Figura 14. Estructura física de un disco duro.
Autor: Tesista.
Fuente: http://es.slideshare.net/gematic/tico-disco-duro.
39
2.3.5.3 Direccionamiento De Sectores En Discos Duros
La información se organiza en sectores dentro del disco duro. Los discos duros
para PC son formateados a bajo nivel por su fabricante con un tamaño de 512
bytes cada uno. La escritura y lectura de sectores en los discos duros se lleva a
cabo empleando los servicios BIOS INT 13h y sus extensiones. Los servicios
BIOS INT 13h originales especifican la dirección de un sector mediante tres
números: Cylinder, Head, Sector (cilindro, cabeza y sector).
2.3.5.3.1 Direccionamiento CHS
Al diseñar el PC XT en 1983, los ingenieros de IBM establecieron que los
servicios BIOS relativos al manejo de disco duro serían activados por la línea
IRQ5 (IRQ6 se destinaba al disquete). Esta línea generaba la interrupción 19
(13h), cuya rutina de servicio disponía de seis servicios estándar: re
inicialización, obtención del estado, lectura, escritura, verificación de sectores, y
formateo de pistas.
Estos servicios ofrecen la posibilidad de leer y escribir en las unidades de disco
a nivel de sectores individuales para lo que, además del número de unidad, se
requiere pasar a la rutina los valores de geometría correspondientes (Cilindro,
Cabeza y Sector concretos) lo que se conoce como direccionamiento CHS
("Cilinder Head Sector").
La especificación de IBM establecía que los
siguientes valores para dichos parámetros.
Tamaño n
del campo (bits)
Cilindro 10
Cabeza 8
Sector
6
Valor máximo
teórico 2n
1,024
256
64
Rango
permitido
0-1,023
0-255
1-63
Total
utilizable
1,024
256
63
Tabla 8. Direccionamiento CHS.
Autor: Tesista.
Fuente: http://www.zator.com/Hardware/H6_2.htm
40
Especificación ATA
Aparte de lo anterior, la especificación ATA establecía otras limitaciones para
los valores de Cilindro, Cabeza y Sector, eran las siguientes:
Tamaño
del campo (bits)
Cilindro 16
Cabeza 4
Sector
8
Valor máximo
teórico
65,536
16
256
Rango
permitido
0-65,535
0-15
1-255
Total
utilizable
65,536
16
255
Tabla 9. Especificación ATA.
Autor: Tesista.
Fuente: http://www.zator.com/Hardware/H6_2.htm
BIOS estándar con unidad IDE
La instalación de una unidad IDE en un PC tradicional (de BIOS estándar)
supone que para estar dentro de ambas normas, deberían utilizarse los valores
más restrictivos de ambas que serían los siguientes:
Cilindros: 1,024
Cabezas: 16
Sectores: 63
Estos números nos conducen a un total máximo de 1024 x 16 x 63 = 1,032,192
clúster, es decir, 528,482,304 bytes (528 MB). Este sería el máximo espacio de
disco direccionable mediante los servicios de la interrupción 13h estándar BIOS
con una controladora ATA/IDE.
2.3.5.3.2 Direccionamiento CHS Extendida
Soportada por un nuevo tipo de BIOS extendidas ("Enhanced BIOS") que
aparecieron a partir de 1993/94.
41
En realidad el direccionamiento CHS extendido es un truco aritmético por el que
se informa a la BIOS que el disco instalado (suponemos que es una unidad
IDE) tiene un número de cilindros, cabezas y sectores distintos de los reales,
pero adaptado a lo que puede manejar la BIOS (lo que se denomina geometría
trasladada). Para ello, si el número de cilindros del dispositivo IDE es superior
a los 1024 soportados por la BIOS, se divide este número por 2, 4, 8 o 16, hasta
que el valor resultante sea igual o menor que los mentados 1024. El valor
resultante es el que se pasa a la BIOS como número de cilindros. Por su parte,
el número de cabezas se multiplica por el factor 2, 4, 8 o 16 utilizado, y éste es
el que se suministra a la BIOS (podríamos decir que se cambian cilindros por
cabezas).
Nota: A pesar del límite teórico de 256, en la práctica ningún disco IDE/ATA
ofrece especificaciones con más de 63 sectores lógicos por pista. La razón es
que sobrepasar el límite de 63 de la BIOS estándar hubiese complicado aún
más las cosas.
2.3.5.3.3 Direccionamiento LBA
Como la capacidad de los discos crecía de forma imparable, pronto se hizo
necesario sobrepasar también el límite de los 8,455 GB de la interrupción 13h
de la BIOS. Para esto se ideó un sistema denominado LBA ("Logical Block
Addressing), que implica un sistema radicalmente distinto de direccionar los
clúster.
En lugar de referirse a ellos en términos geométricos (Cilindro, Cabeza y
Sector), a cada clúster se les asigna un número único, Número de
Sector. Para ello se numeran 0, 1, 2, ... N-1, donde N es el número total de
sectores del disco.
Actualmente LBA es el sistema dominante para
direccionamiento de discos grandes, puesto que desde que alcanzaron el límite
de 8.455 GB, se hizo imposible expresar su geometría en términos de Cilindro,
Cabeza y Sector.
42
Observe
en
realidad
LBA
es
un
sistema
radicalmente
nuevo
de
direccionamiento que, en principio, no implica por sí mismo ampliar ningún
límite. Aunque desde luego, las BIOS que detectan sistemas LBA también
disponen de la traducción adecuada para solventar las limitaciones de la
combinación BIOS/ATA (saltar la limitación de 528 MB o incluso la de 8.455
GB). Esta traducción es la que resuelve el paso de la barrera, ya que la
interrupción 13h no sabe nada sobre direccionamientos LBA.
Por supuesto todas las nuevas unidades de disco soportan LBA, y cuando esta
circunstancia es auto-detectada por la BIOS, se establece automáticamente
este modo de direccionamiento y se habilita la traducción correspondiente.
Esta traducción es parecida a la ECHS, aunque el algoritmo es diferente; se
denomina traducción auxiliar LBA. La diferencia substancial es que en ECHS,
la BIOS traslada los parámetros utilizados por la interrupción 13h desde la
geometría trasladada a la geometría local del disco. En la traducción LBA, la
BIOS traslada la geometría trasladada directamente en un número de sector.
Con posterioridad al establecimiento del sistema, se empezó a utilizar una
extensión conocida como LBA48, que aumentaba de 24 a 48 los bits
reservados para representar los números de sector.
Asumiendo que el
formateo se realiza en sectores de 512 Bytes, el método permite unidades con
un máximo teórico de 512 x 248 = 144.11 Peta bytes (millones de Gigas).
43
2.3.6 Sistema De Numeración Computacional Y Unidades De Información
En informática se usan diversos sistemas de numeración para poder
representar datos entre los más principales tenemos.
2.3.6.1 Sistema Binario
Es un sistema de numeración que es usado internamente por el hardware de
las computadoras actuales. Se basa en la representación de cantidades
utilizando los dígitos 1 y 0, por tanto su base es dos (número de dígitos de
sistemas). Cada digito de un número representado en este sistema se
representa en BIT (contracción de binary digit).
Los ordenadores trabajan internamente con dos niveles de voltaje, por lo que
su sistema de numeración natural es el sistema binario (encendido '1', apagado
'0').
2.3.6.2 Sistema Octal
Es un sistema de numeración cuya base es 8, es decir, utiliza 8 símbolos para
la representación de cantidades. Estos sistemas es de los llamados
posiciónales y la posición de sus cifras se mide con la relación a la coma
decimal que en caso de no aparecer se supone implícitamente a la derecha del
número. Estos símbolos son: 0 1 2 3 4 5 6 7.
Los números octales pueden construirse a partir de números binarios
agrupando cada tres dígitos consecutivos de estos últimos (de derecha a
izquierda) y obteniendo su valor decimal. En informática, a veces se utiliza la
numeración octal en vez de la hexadecimal. Tiene la ventaja de que no requiere
utilizar otros símbolos diferentes de los dígitos.
2.3.6.3 Sistema Decimal
Es uno de los sistema denominado posiciónales, utilizando un conjunto de
símbolos cuyo significado depende fundamentalmente de su posición relativa al
símbolo, denominado coma (,) decimal que en caso de ausencia se supone
colocada a la derecha. Utiliza como base el 10, que corresponde al número del
símbolo que comprende para la representación de cantidades; estos símbolos
son: 0 1 2 3 4 5 6 7 8 9.
44
2.3.6.4 Sistema Hexadecimal
Es un sistema posicional de numeración en el que su base es 16, por tanto,
utilizara 16 símbolos para la representación de cantidades. Estos símbolos son:
0123456789ABCDEF
Su uso actual está muy vinculado a la informática. Esto se debe a que un dígito
hexadecimal representa cuatro dígitos binarios (4 bits = 1 nibble); por tanto, dos
dígitos hexadecimales representan ocho dígitos binarios (8 bits = 1 byte, (que
como es sabido es la unidad básica de almacenamiento de información).
Dado que nuestro sistema usual de numeración es de base decimal, y por ello
sólo disponemos de diez dígitos, se adoptó la convención de usar las seis
primeras letras del alfabeto latino para suplir los dígitos que nos faltan: A = 10,
B = 11, C = 12, D = 13, E = 14 y F = 15. Como en cualquier sistema de
numeración posicional, el valor numérico de cada dígito es alterado
dependiendo de su posición en la cadena de dígitos, quedando multiplicado por
una cierta potencia de la base del sistema, que en este caso es 16.
2.3.6.5 Unidades De Información
En los sistemas actuales es habitual medir la información en gigabytes,
aproximadamente mil millones de bytes, pero existen otras unidades
intermedias también muy empleadas, como el Kbyte o kilobyte y el megabyte.
Al hablar de procesadores es habitual medir su capacidad de direccionamiento
en bits, al igual que la de los registros internos con que cuenta. Así, la mayoría
de los procesadores actuales, entre los que se cuentan los compatibles x86 o
los PowerPC de los Mac, son procesadores de 32/64 bits, ya que ése es el
direccionamiento máximo para el que tienen capacidad.
45
Los procesadores tienen su unidad de información por el tamaño de los
registros internos y el bus de datos. Así en el microprocesador 8086 que tiene
registros internos de 16 bits su palabra es de 16 bits, en el caso del 80386 que
tiene registros internos de 32 bits su palabra es de 32 bits.
Como todos los procesadores en la actualidad compatibles x86, heredan la
arquitectura del 8086 se puede definir la tabla de unidad de información.
Byte
Nombre
Nemónico Tamaño(bits)
BYTE
8
Palabra
WORD
16
Doble Palabra
DWORD
32
Cuádruple Palabra QWORD
64
Tabla 10. Unidades de Información Microprocesador.
Autor: Tesista.
Fuente:Conocimientos adquiridos del tesista.
2.3.7 BIOS
La BIOS es un un circuito integrado, que acompaña al resto de los elementos
que existen en la placa principal del ordenador. Se aloja en una memoria tipo
EPROM. Básicamente se trata de un programa que toma el control cuando el
ordenador se pone en marcha, llevando a cabo todo el proceso de
comprobación y detección de memoria y dispositivos, configurando un área de
memoria con datos de control de los dispositivos y, finalmente, transfiriendo el
control al programa de arranque que corresponda, normalmente alojado en un
disco duro, disquete o CD-ROM.
Durante ese proceso de inicio, la BIOS configura en la memoria una serie de
vectores de interrupción.
Éstos facilitan el acceso a los servicios que ofrece la propia BIOS, servicios que
evitan que tengamos que comunicarnos directamente con cada dispositivo y,
por tanto, tengamos que conocer todos los detalles sobre su funcionamiento.
46
La gestión de interrupciones en modo protegido es diferente al empleado en
modo real, por lo que desde sistemas que usan el modo protegido, todos los de
32 bits que funcionan sobre procesadores Pentium, Core o compatibles, no es
posible el acceso directo a la BIOS. Existen, no obstante, alternativas a los
servicios de la BIOS y caminos alternativos para llegar a ella.
2.3.7.1 El área de parámetros de la BIOS
Como se describió anteriormente, la BIOS es un programa que se encarga de la
puesta en marcha o iniciación del ordenador, aparte de ofrecer servicios de bajo
nivel tanto al sistema operativo como a las aplicaciones. Este programa, alojado
en memoria que sólo puede ser leída, necesita un área de lectura/escritura para
almacenar parámetros que no son constantes, como el tamaño de la memoria
instalada en el sistema, el número de unidades de disco, el estado actual del
teclado, etc. Para todos estos datos se reserva un área de memoria RAM,
conocida como área de parámetros de la BIOS, que está justo detrás de la tabla
de vectores de interrupción, siendo su tamaño variable según la BIOS
específica de que se trate.
La dirección de inicio de esta área de parámetros es, por lo general es, 0:1024
o, 40h: 0h, que es equivalente a la anterior. El segmento se expresa en párrafos
(16 bytes), que 1024 dividido entre 16 es 64 y que 64 en hexadecimal es 40h.
Asumiendo que utilizamos 40h como segmento, la dirección de cada variable
existente en el área de parámetros de la BIOS tendrá como referencia el
desplazamiento 0.
En la siguiente tabla se enumera la dirección, tamaño y contenido de algunos
elementos del área de parámetros de la BIOS. Esta configuración se remonta a
los tiempos de la aparición del PC por lo que, en la actualidad, puede no
contener una información completamente exacta.
47
Offset
00h- 06h
08h- 0Eh
10h
Tamaño
Descripción
WORD
Dirección E/S base del primer-cuarto puerto serie (0 si no instalado)
WORD
Dirección E/S base del primer-tercer puerto paralelo (0 si no instalado)
WORD
Hardware instalado:
bits 15-14: número de puertos paralelos
bit 13: [PC Convertible] = 1 si hay modem interno
bit 12: reservado
bits 11- 9: número de puertos serie
bit 8: reservado
bits 7- 6: número de disqueteras - 1
bits 5- 4: modo de vídeo inicial
bit 3: reservado
bit 2: [máquinas PS] = 1 si hay dispositivo apuntador
[máquinas no PS] reservado
bit 1: = 1 si hay coprocesador
bit 0: = 1 si hay disquete disponible para arrancar
Tabla 11. Área De Parámetros De La BIOS.
Autor: Tesista.
Fuente: http://es.wikipedia.org/wiki/Llamada_de_interrupci%C3%B3n_del_BIOS
A más de los datos anteriores podemos los siguientes:
Datos de configuración del hardware: Contiene las direcciones de hasta 4
puertos seriales y 4 puertos paralelos, información del hardware y cantidad de
memoria RAM instalados, y cierta información del estado de inicialización.
Datos del Teclado: Contiene el buffer del teclado (16 caracteres), el estado de
varias teclas como ambas teclas de CTRL y ALT, las teclas INS, NumLook,
CapsLook, etc., y un byte para almacenar el carácter generado con un código
de 3 dígitos usando ALT + teclado numérico.
Datos del Disquete: Contiene el estado de la disquetera y de su controlador.
Datos del Video: Contenía información de estado de la tarjeta de video activa.
Datos del Casete: Contiene información de estado de la unidad de casete.
Datos del Timer: Contenía un contador de Tics, (que ocurría 18,2 veces por
segundo), desde que el computador se encendía. Servía para determinar cuál
era la hora del día.
48
2.3.7.2 Vectores de Interrupción
En informática el vector de interrupciones es un vector que contiene el valor que
apunta a la dirección en memoria del gestor de una interrupción.
En los procesadores Intel de la línea X86, hay dos tipos de interrupciones: por
hardware y por software.
El método para realizar la interfaz con el BIOS es el de las interrupciones de
software. A continuación se listan algunas interrupciones del BIOS.
INT 00H: División entre cero. Llamada por un intento de dividir entre cero.
Muestra un mensaje y por lo regular se cae el sistema.
INT 01H: Un solo pasó. Usado por DEBUG y otros depuradores para permitir
avanzar por paso a través de la ejecución de un programa.
INT 02H: Interrupción no enmascarare. Usada para condiciones graves de
hardware, tal como errores de paridad, que siempre están habilitados. Por lo
tanto un programa que emite una instrucción CLI (limpiar interrupciones) no
afecta estas condiciones.
INT 03H: Punto de ruptura. Usado por depuración de programas para detener la
ejecución.
INT 04H: Desbordamiento. Puede ser causado por una operación aritmética,
aunque por lo regular no realiza acción alguna.
INT 05H: Imprime pantalla. Hace que el contenido de la pantalla se imprima.
Emita la INT 05H para activar la interrupción internamente, y presione las teclas
Cltr + PrtSC para activarla externamente. La operación permite interrupciones y
guarda la posición del cursor.
INT 08H: Sistema del cronometro. Una interrupción de hardware que actualiza
la hora del sistema y (si es necesario) la fecha. Un chip temporizador
programable genera una interrupción cada 54.9254 milisegundos, casi 18.2
veces por segundo.
49
INT 09H: Interrupción del teclado. Provocada por presionar o soltar una tecla en
el teclado.
INT OBH, INT OCH: Control de dispositivo serial. Controla los puertos COM1 y
COM2, respectivamente.
INT 0DH, INT OFH: Control de dispositivo paralelo. Controla los puertos LPT1 y
LPT2, respectivamente.
INT 0EH: Control de disco flexible. Señala actividad de disco flexible, como la
terminación de una operación de E/S.
INT 10H: Despliegue en vídeo. Acepta el número de funciones en el AH para el
modo de pantalla, colocación del cursor, recorrido y despliegue.
INT 11H: Determinación del equipo. Determina los dispositivos opcionales en el
sistema y regresa el valor en la localidad 40:10H del BIOS al AX. (A la hora de
encender el equipo, el sistema ejecuta esta operación y almacena el AX en la
localidad 40:10H).
INT 12H: Determinación del tamaño de la memoria. En el AX, regresa el
tamaño de la memoria de la tarjeta del sistema, en términos de kilobytes
contiguos.
INT 13H: Entrada/salida de disco. Acepta varias funciones en el AH para el
estado del disco, sectores leídos, sectores escritos, verificación, formato y
obtener diagnóstico.
2.3.7.3 Servicios De La BIOS
La BIOS ofrece servicios para manipular la pantalla, acceder a los discos,
enviar datos a la impresora, leer el teclado o comunicarnos mediante los
puertos serie. Con el uso de los vectores de interrupción.
50
2.3.8 Lenguaje Ensamblador
El lenguaje ensamblador trabaja con nemónicos, que son grupos de caracteres
alfanuméricos que simbolizan las órdenes o tareas a realizar. El lenguaje
ensamblador expresa las instrucciones de una forma más natural al hombre a la
vez que es muy cercana al microprocesador, ya que cada una de esas
instrucciones se corresponde con otra en código máquina.
La traducción de los nemónicos a código máquina entendible por el
microprocesador la lleva a cabo un programa ensamblador. El programa escrito
en lenguaje ensamblador se denomina código fuente. El programa ensamblador
proporciona a partir de este fichero el correspondiente código máquina.
Código Fuente
Está compuesto por una sucesión de líneas de texto. Cada línea puede
estructurarse en hasta cuatro campos o columnas separadas por uno o más
espacios o tabulaciones entre sí.

Campo de etiquetas.- Expresiones alfanuméricas escogidas por el
usuario para identificar una determinada línea. Todas las etiquetas tienen
asignado el valor de la posición de memoria en la que se encuentra el
código al que acompañan.

Campo de código.- Corresponde al nemónico de una instrucción, de
una directiva o de una llamada a macro.

Campo de operandos y datos.- Sonoperandos que precisa el nemónico
utilizado. Según el código, puede haber dos, uno o ningún operando.

Campo de comentarios.- Dentro de una línea, todo lo que se encuentre
a continuación de (;) o dentro de /**/ será ignorado por el programa
ensamblador y considerado como comentario.
Al programar en ensamblador no sólo se utiliza el conjunto de instrucciones y
registros de un cierto microprocesador sino que, además, se usarán dichas
instrucciones para acceder a elementos hardware, como el adaptador de vídeo,
el teclado o los buses de comunicaciones de una cierta arquitectura de
ordenador. De igual manera, para efectuar ciertas tareas se utilizarán servicios
puestos a disposición de las aplicaciones por el sistema operativo.
51
2.3.9 Lenguaje C
C es un lenguaje de programación creado en 1972 por Dennis M. Ritchie en los
Laboratorios Bell como evolución del anterior lenguaje B.
Es un lenguaje orientado a la implementación de Sistemas Operativos,
concretamente Unix. C es apreciado por la eficiencia del código que produce y
es el lenguaje de programación más popular para crear software de sistemas,
aunque también se utiliza para crear aplicaciones. “Se trata de un lenguaje de
tipos de datos estáticos, débilmente tipificado, de medio nivel pero con muchas
características de bajo nivel. Dispone de las estructuras típicas de los lenguajes
de alto nivel pero, a su vez, dispone de construcciones del lenguaje que
permiten un control a muy bajo nivel. Los compiladores suelen ofrecer
extensiones al lenguaje que posibilitan mezclar código en ensamblador con
código C o acceder directamente a memoria o dispositivos periféricos.”
(Fuente: http://es.wikipedia.org/wiki/C_%28lenguaje_de_programaci%C3%B3n%29)
Propiedades

Un
núcleo
del
lenguaje
simple,
con
funcionalidades
añadidas
importantes, como funciones matemáticas y de manejo de archivos,
proporcionadas por bibliotecas.

Un sistema de tipos que impide operaciones sin sentido.
Declaración en C
Char
Short
Int
Unsigned
long int
unsigned long
char *
Float
Doublé
long doublé
Tipo de datos
byte
palabra
doble palabra
doble palabra
doble palabra
doble palabra
doble palabra
precisión simple
precisión doble
precisión extendida
Sufijo de gas
b
w
l
l
l
l
l
s
l
t
Tamaño (en bytes)
1
2
4
4
4
4
4
4
8
12
Tabla 12. Tipos de Datos de Programación C.
Autor: Tesista.
Fuente: Conocimientos adquiridos tesista.
52
2.3.10 Herramientas de programación
Para poder programar en ensamblador se precisa de algunas herramientas
básicas, como un editor para introducir el código, un ensamblador para traducir
el código a lenguaje de maquina y un enlazador para crear archivos binarios
puros enlazar librerías del sistema según sea necesario etc..
Aparte también se necesitan módulos con declaraciones de macros, estructuras
de datos y funciones, utilidades para generar archivos de recursos, etc. Todo
ello, lógicamente, para el sistema operativo concreto sobre el que se pretende
programar.
2.3.10.1 Editores
Editor de textos son aplicaciones que permiten introducir el código, guardarlo en
un archivo, recuperarlo y, en general, efectuar todas las tareas habituales de
edición. Se puede usar virtualmente cualquier editor de texto sin formato, desde
el EDIT de DOS, el Bloc de notas de Windows o vi de Unix hasta los editores
integrados en entornos de desarrollo como Visual Studio, Eclipse y similares.
Existen editores específicos, que se podrían denominar entornos integrados de
desarrollo o IDE, que ahorran trabajo al contar con opciones para efectuar el
ensamblado, enlace, incluso, la ejecución sin necesidad de abandonar la
edición de código.
Entre los más conocidos editores con interfaz de desarrollo tenemos:
Assembler Editor: Editor, compilador y enlazador de programas escritos en
lenguaje ensamblador compatible con TASM, MASM. Se pude instalar en
plataformas de Microsoft.
53
Figura 15. Editor Assembler Editor.
Autor: Tesista.
Fuente: Captura de pantalla.
Nasm-IDE: Editor, compilador y enlazador, es compatible solo con nasm y
Windows DOS.
NasmEdit: Igual que Nasm-IDE pero es compatible con cualquier plataforma
que pueda ejecutar java 2.
Figura 16. Editor Nasm-IDE.
Autor: Tesista.
Fuente: Captura de pantalla.
54
2.3.10.2 Ensambladores
Un ensamblador es como un compilador de cualquier lenguaje, el ensamblador
toma un archivo de texto con código fuente como entrada y, en respuesta,
genera un nuevo archivo con esas mismas sentencias pero en lenguaje de un
determinado procesador.
Los más conocidos ensambladores para x86 son los siguientes:
Masm: Es el ensamblador más usado en DOS y Windows, está desarrollado
por la misma empresa que creó dichos sistemas Microsoft.
Es bastante potente y puede utilizarse para crear programas DOS y Windows,
así como bibliotecas y controladores de dispositivos. Como los demás
ensambladores, MASM se invoca desde la línea de comandos directamente o,
en caso de contar con él, desde un editor previa configuración.
Nasm: Net Wide Assembler, es un ensamblador bajo licencia BSD para
plataformas Intel x86, permite escribir programas en 16, 32, 64 bits.
Es compatible para múltiples plataformas, entre ellas DOS, Windows y Linux.
Esto conlleva una gran ventaja, ya que podemos usar exactamente la misma
herramienta en todos los sistemas, sin tener que cambiar de sintaxis,
parámetros, etc.
Nasm puede generar como salida varios formatos binarios.
Gas (GNU Assembler): Principal ensamblador en plataformas Linux, tiene
licencia de software libre, es compatible con la sintaxis de AT&T, permite
generar como salida varios formatos binarios.
Otros Ensambladores: Existen otros ensambladores como TASM (Turbo
Assembler), A86 etc.
55
2.3.10.3 Enlazadores
Los ensambladores son traductores que toman el código fuente y, partiendo de
cada sentencia, generan una secuencia de bytes, por regla general muy corta,
que es el código objeto.
El conjunto de todas las secuencias de bytes, una por instrucción, se
almacenan en un archivo que no es directamente ejecutable.
Dicho archivo contiene una versión de nuestro programa en el lenguaje de la
máquina, pero no cuenta con la información adicional necesaria para que el
sistema operativo o el procesador sepa gestionarlo.
El enlazador es La herramienta encargada de tomar el código objeto generado
por el ensamblador, añadir los encabezados apropiados y producir un nuevo
archivo ya ejecutable esto es el conocido como linker o enlazador.
En el caso para generar gestores de arranque el enlazador produce código
puramente binario sin bibliotecas que dependan del sistema operativo en
tiempo de ejecución.
Por regla general, cada ensamblador cuenta con su propio enlazador.
Si utiliza MASM el enlazador será LINK. Para TASM el correspondiente
enlazador es TLINK. NASM no se acompaña de un enlazador propio, aunque
puede utilizarse cualquiera de distribución libre como es ALINK o bien, en el
caso de Linux, usar el propio del sistema LINK.
56
2.3.10.4 GCC
GNU C Compiler fue iniciado en 1984 para crear un sistema operativo basado
en software libre similar a UNIX y, así promover la libertad y la cooperación
entre usuarios de ordenadores y programadores.
GCC es un compilador rápido, muy flexible, y riguroso con el estándar de C
ANSI. Como ejemplo de sus múltiples virtudes, se tiene que gcc puede
funcionar como compilador cruzado para un gran número de arquitecturas
distintas. Gcc no proporciona un entorno IDEs, es solo una herramienta más a
utilizar en el proceso. Gcc se encarga de realizar (o encargar el trabajo a otras
utilidades) el pre procesado del código, la compilación, y el enlazado.
Dicho de otra manera, se proporciona a gcc código fuente en C, y él nos
devuelve un archivo binario compilado para nuestra arquitectura.
Gcc no genera código binario alguno, sino código ensamblado. La fase de
ensamblado a código binario la realiza el ensamblador de GNU (gas), y el
enlazado de los objetos resultantes, el enlazador de GNU (ld). Este proceso es
transparente para el usuario, ya que a no ser que se lo especifiquemos, gcc
realiza el paso desde código en C a un binario ejecutable automáticamente.
A través del tiempo GCC ha sido extendido para dar soporte a muchos
lenguajes adicionales, incluyendo Fortran, ADA, Java y Objective-C, C, C++.
A continuación se describen las etapas correspondientes al conjunto de
herramientas de compilación gcc que permite traducir programas escritos en el
lenguaje de programación C.
Figura 17. Etapas de gcc.
Autor: Amelia Ferreira © 2008.
Fuente: http://learnassembler.com/entorno.html.
57
2.4
Investigación Experimental
En la realización del proyecto de fin de carrera, para la investigación
experimental se analiza como las variables independientes de la investigación
afectan al aprendizaje y desarrollo de nuevos gestores de arranque y sistemas
operativos, que en este caso es la falta de información del código por parte del
software propietario y la escasa documentación técnica por parte del software
libre.
Razón por la cual se desarrolla documentación técnica del código del gestor de
arranque grub, su funcionamiento, como modificarlo y reconstruirlo.
Con los conocimientos obtenidos se procederá a crear un prototipo de gestor de
arranque. Dando a la comunidad más documentación para que se pueda
profundizar en el tema y aportar nuevas ideas, corregir errores etc.
2.5 Plan de Recolección de Información
Una vez planteada la investigación y realizada todos los estudios sobre las
herramientas necesarias en la administración de los gestores de arranque se
efectúa la recolección de información con el fin de dar respuesta al problema
planteado como propuesta de tesis.
Las técnicas que se utilizó para recolectar información son:

Lectura del funcionamientos de los gestores de arranque propietarios en
este caso Windows.

Técnicas de Ingeniería inversa aplicadas a los gestores de arranque
propietarios.

Lectura del funcionamiento de los gestores de arranque de código libre
en este caso LILO y GRUB Legacy.

Técnicas de ingeniería inversa aplicada a los gestores de arranque de
código libre, si bien se tiene acceso al código se debió probar su
funcionamiento práctico.

Métodos de depuración de código tanto para los gestores de arranque
propietarios como de software libre.
58
2.6 Plan de Procesamiento de Información
Con la información recopilada se procedecio a determinar cuál gestor de
arranque permite profundizar su estudio dando como resultado el gestor de
arranque GRUB LEGACY por los siguientes motivos:

Grub Legacy tiene varios años funcionando lo que ha permitido
profundizar en el estudio del código.

El código de GRUB Legacy es más pequeño que los gestores de la
actualidad lo que permite seguir el funcionamiento del código.

Grub Legacy es de software libre con licencia GNU GPL lo que permite
modificar su código, reconstruir el ejecutable y poner el código
modificado y su ejecutable a disposición de la comunidad para libre uso.

GRUB LEGACY permite una mejor fuente de información si bien ya no
tiene desarrollo permite obtener una visión clara del funcionamiento del
gestor de arranque ya que su código fue evolucionando y se tiene
acceso a sus distintas versiones.
2.7 Modelo de Desarrollo
El modelo a utilizarse para el desarrollo del proyecto fue un modelo de prototipo
que es un modelo a escala o facsímil de lo real, pero no tan funcional para que
equivalga a un producto final, ya que no lleva a cabo la totalidad de las
funciones necesarias del software final. Proporcionando una retroalimentación
temprana por parte de los usuarios acerca de la aplicación del software.
El objetivo de utilizar el modelo de desarrollo de prototipo es centrarse en una
representación de los aspectos del software que sean visibles para el usuario
final que en este caso será la configuración de la interfaz con el usuario y la
documentación técnica de cómo se codifico el software.
Con un modelo de prototipo no vamos a centrar en los aspectos básicos del
gestor de arranque para dar un entendimiento global de su funcionamiento.
59
FASES MÉTODO DE PROTOTIPOS
Estas fases se implementaran en el diseño de la solución en el capitulo 3. Lo
siguiente que se presenta es un resumen de lo que se realizará en cada fase
teniendo en cuenta el modelo de desarrollo de prototipos..
Investigación preliminar
Se
determinará el problema y su ámbito, la importancia y los efectos
potenciales que tendrán sobre la organización, identificar una idea general de la
solución para realizar un estudio de factibilidad que determine la factibilidad de
una solución software.
Definición de los requerimientos del sistema
Esta es la fase más importante de todo el ciclo de vida del método de
prototipos, el objetivo en esta fase es determinar todos los requerimientos y
deseos que el proyecto que está deseando implementar.
Esta etapa es un proceso que busca aproximar las visiones del usuario y del
desarrollador mediante sucesivas iteraciones.
Diseño y construcción
Lo que se consigue en esta fase en obtener un prototipo inicial, aquí el
desarrollador debe concentrarse en construir un sistema con la máxima
funcionalidad.
Evaluación
Se modifica y se evalúa cuantas veces sea necesario hasta que se tenga claro
conocimiento del funcionamiento del gestor de arranque y se genera
documentación técnica.
60
Diseño técnico
En esta etapa el sistema debe ser rediseñado y tener la respectiva
documentación guiándose en los estándares que tiene la organización la cual
servirá como ayuda en mantenciones futuras del mismo.
En este punto existen dos etapas:
Producción de una documentación de diseño la cual específica y describe la
estructura del software, interfaces de usuario, funciones y el control de flujo.
Producción de todo lo requerido para promover cualquier mantención futura del
software.
Programación y prueba
En esta etapa es donde los cambios identificados en el diseño técnico son
implementados y probados para asegurar la corrección y completitud de los
mismos con respecto a los requerimientos.
Las pruebas serán de realizarse tantas veces sea necesarias para verificar
cualquier tipo de anomalía en el sistema.
Operación y mantención
En esta fase se realiza ya la instalación y mantención del software.
Si existiese el caso en el cual se requiera una manutención entonces el proceso
de prototipo es repetido y se definirá un nuevo conjunto de requerimientos.
61
CAPITULO 3
3 DISEÑO DE LA SOLUCIÓN
3.1 Antecedentes
Para la creación, modificación y estudio de los gestores de arranque no existen
herramientas de cuarta generación, solo se tiene a disposición enlazadores
ensambladores, preprocesadores, por lo tanto para el diseño de la solución se
procedió a revisar la teoría del funcionamiento de los gestores de arranque y
con las herramientas antes mencionadas en el capítulo 2, se procedió a realizar
pruebas iterativas con modificaciones del código, aplicación de técnicas de
ingeniería inversa etc. Logrando generar la siguiente documentación, como
caso de uso se modificara el gestor de arranque GRUB LEGACY.
3.2 Gestor de Arranque
Los gestores de arranque contienen el primer programa que la computadora
carga al iniciar su funcionamiento.
La computadora al encender realiza un proceso denominado POST (Power On
Self Test auto prueba de encendido) este proceso se encuentra quemado en la
memoria ROM de la pc, es un proceso de verificación e inicialización de los
componentes de entrada y salida en un sistema de cómputo que se encarga de
configurar y diagnosticar el estado del hardware, una vez que termina su
verificación carga a memoria desde un dispositivo arrancable código de 512
bytes de tamaño y procede a darle el control de la pc.
Encendido
PC
Post(Power
On Selft)
Cargar y ejecutar
programa
arrancable.
Figura 18. Flujo General de Inicio de la Pc.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
62
Para seleccionar un dispositivo arrancable la pc busca dentro de los dispositivos
configurados coma de arranque y selecciona el primero que cumpla como
dispositivo arrancable como lo muestra la siguiente figura.
Figura 19. Flujo de Selección y Carga de Código de Arranque.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
3.2.1 Codificación y Funcionamientos de los Gestores de Arranque
El funcionamiento del gestor de arranque se lo dividirá en tres etapas
Primera Etapa
Tamaño en Bytes
Segunda Etapa
512
Tercera Etapa
variable
variable
Cargar a memoria y Cargar a memoria Cargar a memoria y
Función
ejecutar segunda
y ejecutar tercera ejecutar Sistema
etapa
etapa
Operativo
Tabla 13. Etapas del Gestor de Arranque.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
63
Primera Etapa
El código de la primera etapa debe tener un tamaño de exactamente 512 bytes.
Su último número hexadecimal deber ser 0x55AA, que es el número.
La primera etapa debe ser inyectada en el sector de arranque de los
dispositivos de almacenamiento. Con esta inyección de código el dispositivo de
almacenamiento se convierte en un dispositivo de arranque.
La primera etapa es generalmente es escrita solo en leguaje ensamblador pero
como ya se vio anteriormente en el proceso de compilación de gcc todo
programa escrito en lenguaje de alto nivel tiene que pasar por una etapa de
ensamblaje.
El motivo de escribir su código en lenguaje ensamblador es que al momento de
enlazarle para producir el código binario puro este debe medir exactamente 512
bytes y sus últimos números hexadecimales deben ser 0x55AA.
En lenguaje ensamblador podemos delimitar el tamaño de nuestro archivo
binario puro.
El código de la primera etapa del gestor de arranque o la primera etapa del
gestor de arranque es denominado MBR Master Boot Record.
3.3 MBR
El MBR (master boot record) es conocido como registro de arranque principal,
o como registro de arranque maestro, el MBR debe estar almacenado en el
primer sector ("sector cero") de un dispositivo de almacenamiento de datos,
como un disco duro.
El funcionamiento del MBR difiere en los casos de los gestores de código
propietario como de código libre. En el caso de Microsoft se realizó el estudio
del gestor de arranque NTLDR, en el caso de GNU Linux se realizó un estudio
del gestor de arranque GRUB
64
3.4. NTLDR
NTLDR (New Technology Loader) es el gestor de arranque de las plataformas
de Windows en sus distintas versiones hasta Windows XP.
3.4.1 Estudio NTLDR
Se realizó un estudio sobre el NTLDR que inicia el Sistema Operativo XP de 32
bits Servipack 2.
Debido a que el MBR debe encontrarse en el sector cero o sector de arranque
del disco duro se procede a examinar los 512 bytes del sector que en la
especificación CHS vendría ser Cilindro cero, Cabecera cero, sector 1.
Ejecutamos la herramienta de software libre HexEdit instalado sobre el Sistema
Operativo XP como administrador y
abrimos el código hexadecimal
almacenado en el disco duro.
Figura 20. Sector Cero Disco Duro con Windows XP.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
65
El código de 512 bytes de tamaño del gestor de arranque NTLDR se divide en
la sección de código, sección de errores, sección definida por Windows, sección
de tabla de particiones, sección de firma.
Dirección
0x0000
0x013C
0x01B4
0x01BC
0x01BE
0x01FE
Descripción
Sección código
Sección de errores
Sección definida por Windows
2 bytes; normalmente 0x0000
Tabla de particiones del disco duro.
Firma del MBR (0x55AA)
Tabla 14. Almacenamiento del Master Boot Record de NTLDR.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
3.4.1 .1 Sección de Código
La sección de código corresponde a los primeros 300 bytes como se muestra
en la siguiente figura.
Figura 21. Sección de código de NTLDR.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
El estudio de la sección de código se lo dejara para su revisión más adelante en
el tema Desensamblaje de la Sección de Código debido a que se debe tener
información de los demás secciones del MBR del gestor de arranque NTLDR.
66
3.4.1 .2. Sección de Mensaje de Errores
El objetivo de la sección de mensajes de errores es presentar en pantalla al
usuario de la pc que no se pudo encontrar una partición valida en el disco duro
que se pueda continuar su ejecución.
Nota: Se detalla que es una partición valida en la sección de tabla de
particiones.
Figura 22. Sección de Mensaje de Errores.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
Como se observa en la figura anterior la sección de Errores del gestor de
arranque NTLDR tiene almacenado el mensaje Tabla de partición no valida.
Error al cargar el sistema operativo. Falta el sistema operativo en código ascci.
3.4.1 .3 Sección definida por Windows
Las secciones definidas por Windows son dos:
En la primera sección definida por Windows en el NTLDR va desde el byte
0x01B5 al byte 0x01B7, tres bytes, lo que representan es la longitud en bytes
del mensaje de error esto difiere a causa de los distintos idiomas en que se
instala el gestor de arranque.
Figura 23. Sección definida por Windows parte 1.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
67
En la segunda sección definida por Windows en el NTLDR va desde el byte
0x01B8 la byte 0x01BB, lo que representan es la firma del disco duro, el
sistema operativo utiliza estos bytes para determinar la información del disco.
Figura 24. Sección definida por Windows parte 2.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
En el gestor de arranque del NTLDR podemos observar que la primera parte
indica que la longitud del mensaje de error es de 0x6E o 111 caracteres.
En la segunda parte es la firma del disco que es usada por el registro de
Windows este código es muy importante para el manejo del sistema operativo.
3.4.1 .4 Sección Tabla de Particiones
Figura 25. NTLDR Sección Tabla de Particiones.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
La tabla de particiones en el NTLDR consta de 64 bytes, comenzando en el
byte 0x01BE hasta el byte 0x01FD, los 64 bytes comprenden 4 registros de
particiones de 16 bytes denominadas primarias o 3 registros de particiones
primarias y 1 registro de una partición extendida.
Se revisara teoría sobre la tabla de particiones para proceder al verificar como
está constituida la sección de tabla de particiones en el gestor de arranque
NTLDR en la sección Estudio de la tabla de particiones del gestor de
arranque NTLDR.
Partición de Disco
68
Una partición de un disco duro o unidad flash es una división lógica de una
unidad física para poder organizar el almacenamiento, en la cual se alojan y
organizan los archivos mediante un sistema de archivos.
Un disco duro puede dividirse en varias particiones. Cada partición funciona
como si fuera un disco duro independiente.
El propósito a conseguir es que se pueda utilizar un solo disco físico, como
varios discos lógicos independientes.
Al instalar dos sistemas operativos sobre un mismo disco duro no sería factible
realizarlo sin la técnica de la partición, se necesitarían dos discos físicos, con la
técnica de la partición se pueden instalar n sistemas operativos sobre un disco
duro al menos hasta que la capacidad de almacenamiento del disco duro lo
permita. Creando una partición para cada sistema operativo que se desea
instalar.
Los disquetes generalmente no se particionan. No hay ninguna razón técnica
para ello, pero dado que son tan pequeños, particionarlos sería útil sólo en
extrañas ocasiones.
Los CD-ROM tampoco se suelen particionar, ya que es más fácil utilizarlos
como un disco grande, y raramente existe la necesidad de tener varios sistemas
operativos en uno de ellos.
En el registro de la tabla de particiones se indica que partición se encuentra
activa cual es el tamaño de dicha partición. Solo una partición puede estar
activa.
La siguiente figura muestra un ejemplo de cómo está estructurado registro de
tabla de particiones en el MBR.
Tabla de Partición 64 bytes
Partición
Tamaño
Registro Partición 1
16 BYTES
Registro Partición 2
16 BYTES
Registro Partición 3
16 BYTES
Registro Partición 4
16 BYTES
Tabla 15. Estructura de la tabla de particiones.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
69
El PC al cargar el MBR el cual contiene el registro de la tabla de particiones
buscara la partición primaria o lógica que contiene el sistema operativo, una
vez que la encuentra procede a cargar el sistema operativo desde dicha
partición.
Estructura De Un Registro De Partición
Un registro de de partición tiene un tamaño de 16 bytes los cuales se
estructuran en el siguiente orden:

1 Byte: Marca de arranque si el bit 7 está activo es una partición de
arranque, los otros bits deben ser ceros.

3 Bytes: Indica la especificación CHS (Cilindro, cabecera, sector) de
inicio.

1 Byte: Tipo de sistema de archivo de la partición. Ejemplo: 00 Sin
sistema de archivo, 01 Fat12 etc.

3 Bytes: Indica la especificación CHS (Cilindro, cabecera, sector) final.

4 Bytes: Indica la especificación LBA(Logical Block Addressing)

4 Bytes: Tamaño de la partición que está definiendo en sectores
Tipos De Particiones
Existen tres tipos de de particiones:

Partición Primaria: Son las divisiones primarias del disco, solo puede
haber 4 de éstas o 3 primarias y una extendida. Depende del registro de
tabla de particiones. Un disco físico completamente formateado consiste,
en realidad, de una partición primaria que ocupa todo el espacio del
disco y posee un sistema de archivos. A este tipo de particiones,
prácticamente cualquier sistema operativo puede detectarlas y asignarles
una unidad, siempre y cuando el sistema operativo reconozca su formato
(sistema de archivos).
70

Partición Extendida: También conocida como partición secundaria es
otro tipo de partición que actúa dentro de una partición primaria, sirve
para contener múltiples unidades lógicas en su interior. Su objetivo
principal es romper la limitación de 4 particiones primarias en un solo
disco físico. Solo puede existir una partición de este tipo por disco, y solo
sirve para contener particiones lógicas. Por lo tanto, es el único tipo de
partición que no soporta un sistema de archivos directamente.

Partición Lógica: Ocupa una porción de la partición extendida o la
totalidad de la misma, la cual se ha formateado con un tipo específico de
sistema de archivos (FAT32, NTFS, ext2,...) y se le ha asignado una
unidad, así el sistema operativo reconoce las particiones lógicas o su
sistema de archivos. Puede haber un máximo de 23 particiones lógicas
en una partición extendida. Linux impone un máximo de 15, incluyendo
las 4 primarias, en discos SCSI y en discos IDE 8963.
Figura 26. NTLDR Tipo de Particiones.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
Estudio de la Tabla de Particiones del Gestor de Arranque NTLDR
La estructura del registro de la tabla de particiones del gestor de arranque
NTLDR es el siguiente.
Figura 27. Tabla de Particiones Hexadecimal.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
71
Partición 1

1 Byte: 80 en binario 1000 000: Lo cual indica el bit 7 está activo es decir
la primera partición es la partición activa o de arranque.

3 Bytes: 01 01 00: Indica que la primera partición inicia en el cilindro 0
cabecera 1 sector 1.

1 Byte: 07: Indica que la partición esta formateada con el sistema de
archivos NTFS

3 Bytes: FE FF FF: Indica que la partición finaliza en el cilindro 1024,
cabecera 16 sector 63.

4 Bytes: 3F 00 00 00: Indica que la partición iniciara en el sector 3F o 63
en decimal en caso de soportar LBA

4 Bytes: B2 8C 7F 02: Indica que el el tamaño de la partición es 02 7F 8C
B2 o en decimal 41913522 sectores suponiendo que cada sector es de
512 bytes el tamaño es de 20 GB.
Partición 2, 3, 4
Las particiones están inactivas y no están formateadas con ningún sistema de
archivo.
3.4.1 .5. Sección de Firma
La firma es un estándar para indicarle a la pc que es un master boot record.
Todo MBR debe terminar con el código en hexadecimal 55 AA los dos últimos
bytes de código de 512 bytes.
Figura 28. NTLDR Firma.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
Como se observa en la figura el gestor de arranque NTLDR termina con la firma
55 AA que indica que es un MBR.
72
3.4.2. Des ensamblaje de la Sección de Código
Existen diversas maneras para desensamblar el código en hexadecimal como
por ejemplo copiar el código a un archivo utilizando una herramienta en código
libre como gcc y proceder a desensamblar dicho archivo igualmente utilizando
una herramienta de software libre como por ejemplo objdump.
En
este
caso
se
utilizara
como
herramienta
la
página
web
http://www2.onlinedisassembler.com/odaweb/, en esta página se escogen como
parámetros los siguientes:

Arquitectura=i8086: Debido a que al iniciar el funcionamiento del pc esta
se encuentra en modo real y el modo real emula un microprocesador
8086.

Base Address=0x7C00: Por el motivo que este código será cargado a
memoria en la dirección 0x7C00.
Y se procede a desensamblar dividiéndole en partes para su mejor
comprensión. Adicional se ha comentado técnicamente el código.
3.4.2. 1. Primera Parte Del Código
Memoria
0x7C00
0x7C02
0x7C04
0x7C07
0x7C08
Hexadecimal
33c0
8ed0
bc007c
fb
50
Instrucción Ensamblador(GAS)
xor %ax,%ax
mov %ax,%ss
mov $0x7c00,%sp
Sti
push %ax
0x7C09
7
pop %es
0x7C0a
50
push %ax
0x7C0b
1f
pop %ds
0x7C0c
fc
Cld
0x7C0d
be1b7c
mov $0x7c1b,%si
73
Comentario
/*Establece ax=0*/
/*Establece ss=0*/
/*Establece sp=0x7C00*/
/*Activa Interrupciones*/
/*Apila el valor 0 (ax=0)*/
/*Des apila valor 0 y establece
es=0*/
/*Apila el valor 0 (ax=0)*/
/*des apila valor 0 y establece
ds=0*/
/*Limpia flag de dirección*/
/*Establece SI=0x7c1b 0x7c1b Es
la dirección de memoria que se
copiara a otra dirección.*/
Memoria Hexadecimal Instrucción Ensamblador(GAS)
0x7C10
bf1b06
mov $0x61b,%di
0x7C13
50
push %ax
0x7C14
57
push %di
0x7C15
b9e501
mov $0x1e5,%cx
0x7C18
f3a4
rep movsb %ds:(%si),%es:(%di)
0x7C1a
cb
Comentario
/*Establece DI=0x61b 0x61b Es la
dirección de memoria donde se
almacenara el código que se copió
anteriormente */
/*Apila el valor 0 (ax=0)*/
/*Apila el valor 0x61b
(di=0x61b)*/
/*Establece cx=0x1e5 485 en
hexadecimal
/*Instrucción que copiara cx bytes
de la dirección de si a di */
/*Instrucción que establecerá el
valor de cs e ip con los valores de
la apilados así: CS=0 IP=0x0x61b*/
Lret
Tabla 16. NTLDR código fuente documentado parte 1.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
En resumen lo que la primera parte del código hace es copiar 445 bytes de
información que se encuentra en la memoria partir de la dirección 0: 0x7c1b a
la dirección 0: 0x61b y procede a ejecutar el código desde esta dirección.
Se procede a desensamblar el código restante configurando la nueva dirección
en la página web antes descrita.
3.4.2. 2. Segunda Parte Del Código
Memoria Hexadecimal
0x061b
bdbe07
Instrucción Ensamblador(GAS)
mov $0x7be,%bp
0x061e
b104
mov $0x4,%cl
0x0620
386
cmp %ch,0x0(%bp)
74
Comentario
/*Establece bp=0x7be
Ubicación de la primera
entrada en la tabla de
particiones*/
/*Estable cl=4 Máximo 4
entradas. Numero de
particiones primarias*/
/*Compara el primer byte
de la partición primaria con
el valor de ch que es 0 para
verificar si encuentra
activa.*/
Memoria
Hexadecimal
Instrucción Ensamblador(GAS)
0x0623
7c09
jl 0x0000062e
0x0625
7513
jne 0x0000063a
0x0627
83c510
add $0x10,%bp
0x062a
e2f4
loop 0x00000620
0x062c
cd18
int $0x18
Comentario
/*Si el valor del primer
byte de la partición
primaria es mayor que ch,
esta sería la partición
activa y continuamos
revisando los parámetros
de está dando un salto a la
dirección 0:062e*/
/*Si el valor del primer
byte de la primera
partición primaria tampoco
es igual a ch, esta sería una
partición no valida y
damos un salto a la
dirección 0:063a*/
/*Adiciona 16 bytes al
valor de bp para verificar si
la siguiente partición
primaria esta activa.*/
/*Salta a la dirección
0:0620 para buscar una
partición primaria activa.
La iteración la hace cl
veces en este cl =4*/
/*Ejecuta int18h la cual
indica un mensaje de error
ya que no encontró
ninguna partición primaria
activa.*/
Tabla 17. NTLDR código fuente documentado parte 2.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
En resumen la segunda parte del código intenta encontrar una partición primaria
activa en la tabla de particiones. El primer byte de una entrada indica si es una
partición activa (80 h) o no (00 h) cualesquiera otro valor significa que el registro
de la tabla de partición no es válida. Si ninguno de los cuatro registros en la
tabla de particiones está activo, se muestra el mensaje de error "no válido".
Al encontrar un registro de partición activo valido continua con la siguiente
sección de código.
75
3.4.2. 3. Tercera Parte Del Código
Memoria Hexadecimal
0x062e
8bf5
Instrucción Ensamblador(GAS)
mov %bp,%si
0x0630
83c610
add $0x10,%si
0x0633
49
dec %cx
0x0634
7419
je 0x0000064f
0x0636
382c
cmp %ch,(%si)
0x0638
74f6
je 0x00000630
Comentario
/*Establece el valor de si
con la dirección del primer
byte de la primera partición
activa encontrada.*/
/*Adiciona 16 bytes al valor
de la dirección que
contiene si.*/
/*Decrementa el valor de
cx para verificar si existen
registros de particiones*/
/*Comprueba cuando cx
llega a cero es decir ya no
existen registros de
particiones por comprobar
y salta a la dirección
0:064f*/
/*Comprueba que el primer
byte de las particiones que
le siguen a la partición
primaria activa con el valor
de cx=0*/
/*Der ser el valor igual a
cero salta a la dirección
0:0630 para buscar más
registros de particiones.*/
Tabla 18. NTLDR código fuente documentado parte 3.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
En resumen lo que la tercera parte de código comprueba que no haya más
particiones activas de no haberlo salta a la quinta parte del código, caso
contrario continua a la cuarta parte del código que es la siguiente.
76
3.4.2. 4. Cuarta Parte Del Código
Memoria Hexadecimal
0x063a
a0b507
Instrucción Ensamblador(GAS)
mov 0x7b5,%al
0x063d
b407
mov $0x7,%ah
0x063f
8bf0
mov %ax,%si
0x0641
ac
lods %ds:(%si),%al
0x0642
3c00
cmp $0x0,%al
0x0644
74fc
je 0x00000642
0x0646
bb0700
mov $0x7,%bx
0x0649
b40e
mov $0xe,%ah
0x064b
cd10
int $0x10
0x064d
ebf2
jmp 0x00000641
Comentario
/*Establece el valor de la
dirección 0:07B5 a al en
este caso el valor es 2c el
primer byte de la sección
definida por Windows.*/
/*Establece el valor de
ah=0x07 */
Establece el valor de si con
el de ax en este caso si =
0x72C
/*Carga un byte del valor
de la dirección ds:si al
registro al y aumenta un
byte así. Esto es pone el
primer carácter del
mensaje de error en el
registro al*/
/*Compara el valor de al
con 0 para verificar que
ellos caracteres del
mensaje de error se
acabaron*/
/*Al acabar de imprimir el
mensaje de error ejecuta
un bucle infinito saltando a
la dirección 0:0642*/
/*Establece el modo de
texto y modo grafico*/
/*Estable la función de la
int 10h*/
/*Ejecuta la interrupción de
BIOS 10h*/
/*Salta a la posición de
dirección 0:0641 para iterar
los caracteres del mensaje
de error*/
Tabla 19. NTLDR código fuente documentado parte 4.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
En resumen la cuarta parte del código imprime un mensaje de error en la
pantalla y genera un bucle infinito.
77
3.4.2. 5. Quinta Parte Del Código.
Memoria
Hexadecimal
Instrucción Ensamblador(GAS)
0x064f
884e10
mov %cl,0x10(%bp)
0x0652
e84600
call 0x0000069b
0x0655
732a
jae 0x00000681
0x0657
fe4610
incb 0x10(%bp)
0x065a
807e040b
cmpb $0xb,0x4(%bp)
0x065e
740b
je 0x0000066b
0x0660
807e040c
cmpb $0xc,0x4(%bp)
0x0664
7405
je 0x0000066b
0x0666
a0b607
mov 0x7b6,%al
0x0669
75d2
jne 0x0000063d
0x066b
0x066f
80460206
83460806
Comentario
/*Establece el valor de cl
a la dirección que
almacena bp +16 bytes.
En este caso cero.*/
/*Llama a la función
almacenada en memoria
que comienza en la
posición 0x069b*/
/*Salta a la dirección
0:0681 si cf esta
desactivada*/
/*Incrementa en byte de
(bp+16) en esta caso 1*/
/*Verifica el sistema de
archivos de la partición
con 0xb partición fat32*/
/*Si la tabla de
particiones es fat32 salta
a la dirección 0:066b*/
/*Verifica el sistema de
archivos de la partición
con 0xc partición fat32
lba*/
/*Si la tabla de
particiones es fat32 lba
salta a la dirección
0:066b*/
/*Establece el valor de
0x7b6 a al*/
/*Salta a la dirección
0:063d. Para imprimir
mensaje de error*/
addb $0x6,0x2(%bp)
/*Adiciona el valor de 6
al registro de partición
del número de la
cabecera inicial de la
partición*/
addw $0x6,0x8(%bp)
/*Adiciona el valor de 6
al registro de partición
del número de sectores
en caso de soportar lba*/
78
Memoria
Hexadecimal
Instrucción Ensamblador(GAS)
0x0673
83560a00
adcw $0x0,0xa(%bp)
0x0677
e82100
call 0x0000069b
0x067a
7305
jae 0x00000681
0x067c
a0b607
mov 0x7b6,%al
0x067f
ebbc
jmp 0x0000063d
0x0681
813efe7d55aa
cmpw $0xaa55,0x7dfe
0x0687
740b
je 0x00000694
0x0689
807e1000
cmpb $0x0,0x10(%bp)
0x068d
74c8
je 0x00000657
0x068f
a0b707
mov 0x7b7,%al
0x0692
eba9
jmp 0x0000603d
0x0694
8bfc
mov %sp,%di
0x0696
1e
push %ds
0x0697
57
push %di
0x0698
8bf5
mov %bp,%si
79
Comentario
/*Realiza la suma de cero
+la dirección (bp+11). No
hace nada */
/*Llama a la función
069b para leer el sector
de la primera partición*/
/*Si la lectura tuvo éxito
salta a la dirección
0681*/
/*Si la lectura no tuvo
éxito establece
al=0x7b6*/
/*Salta a la dirección
0:063d para imprimir
mensaje de error*/
/*Compara el valor
0x55AA con el valor de la
dirección 0x7DFE, el valor
de la dirección 0:07dfe es
0x55AA la firma*/
/*Si la comparación
anterior son iguales salta
a la dirección 0x0694*/
/*Realiza la comparación
entre el valor 0 y el valor
de (bp+10). Al haber
error de lectura la
dirección (bp+16)
aumenta un valor*/
/*Al ser (bp+16) cero se
da otra oportunidad de
lectura. Salta a la
dirección 0:0657*/
/*Establece el valor
0:07b7 en al*/
/*Salta a la dirección
0:0603d para imprimir
mensaje de error.*/
/*Establece el valor de sp
a di. Ahora di tiene
0x7C00*/
/*Apila ds, Apila 0*/
/*Apila di, apila
0x07c00*/
/*Establece bp a si*/
Memoria
Hexadecimal
Instrucción Ensamblador(GAS)
0x069a
cb
lret
0x069b
bf0500
mov $0x5,%di
0x069e
8a5600
mov 0x0(%bp),%dl
0x06a1
b408
mov $0x8,%ah
0x06a3
cd13
int $0x13
0x06a5
7223
jb 0x000006ca
0x06a7
8ac1
mov %cl,%al
0x06a9
243f
and $0x3f,%al
0x06ab
98
cbtw
0x06ac
8ade
mov %dh,%bl
80
Comentario
/*Salta a la dirección
apilada. 0:07C00. Ejecuta
el primer sector de la
partición primaria en
este caso el VBR*/
/*Establece el valor de
DI=5*/
/*Establece el valor de la
dirección almacenada en
bp a dl, en esta caso
dl=0x80*/
/*Establece le valor
ah=0x8, Establece la
función 8 de la
interrupción 13h*/
/*Ejecuta la interrupción
13h función 8.
Obteniendo los
parámetros del disco
duro en este caso. ch #
de cilindros, cl sectores
por pista, dh # de
cabeceras, dl #
controlador y en la
dirección es:di almacena
11 bytes con la
información de la tabla
base del disco.*/
/*Si la lectura de los
parámetros del de la
interrupción 13h dio
error salta a la dirección
0:06ca*/
/*Establece el valor de cl
a al. Al sectores por
pista*/
/*Realiza un and
00111111 y al, ya que el
número de sectores esta
en los primeros 6 bits.*/
/*Establece el valor de al
en ax.*/
/*Establece el valor de
dh en bl, bl contiene
ahora el número de
cabeceras del disco.*/
Memoria
Hexadecimal
Instrucción Ensamblador(GAS)
0x06ae
8afc
mov %ah,%bh
0x06b0
43
inc %bx
0x06b1
f7e3
mul %bx
0x06b3
8bd1
mov %cx,%dx
0x06b5
86d6
xchg %dl,%dh
0x06b7
b106
mov $0x6,%cl
0x06b9
d2ee
shr %cl,%dh
0x06bb
42
inc %dx
0x06bc
f7e2
mul %dx
0x06be
39560a
cmp %dx,0xa(%bp)
0x06c1
7723
ja 0x000006e6
81
Comentario
/*Establece el valor de ah
a bh. En cualquier caso
0*/
/*Incrementa el valor de
bx, bx contiene el
número de cabeceras del
disco.*/
/*Realiza la
multiplicación de ax por
bx. El número de caberas
por sectores por pista. Y
la almacena en dx:ax, en
realidad solo en ax.*/
/*Establece el valor de cx
a dx. Dx contiene el
número de sectores por
pista y el número de
cilindros*/
/*Realiza un intercambio
de datos entre dh, dl*/
/*Establece el valor de 6
a cl*/
/*Recorre 6 bits a la
derecha el valor de dh.
Ahora se tiene en dx el
número de cilindros en
los primeros 10 bits*/
/*Incrementa el valor de
dx*/
/*Realiza la
multiplicación de dx por
ax, El número de cilindros
por el número de
cabeceras y sectores por
pista.*/
/*Realiza la comparación
entre dx y el valor al que
apunta bp +10 bits, en
este caso es el registro de
tabla de particiones valor
00 00*/
/*Si la comparación de
(bp+10) es mayor que dx
salta a la dirección 6e6,
La BIOS admite int13h
extendida */
Memoria
Hexadecimal
Instrucción Ensamblador(GAS)
0x06c3
7205
jb 0x000006ca
0x06c5
394608
cmp %ax,0x8(%bp)
0x06c8
731c
jae 0x000006e6
0x06ca
b80102
mov $0x201,%ax
0x06cd
bb007c
mov $0x7c00,%bx
0x06d0
8b4e02
mov 0x2(%bp),%cx
0x06d3
8b5600
mov 0x0(%bp),%dx
0x06d6
cd13
int $0x13
0x06d8
7351
jae 0x0000072b
82
Comentario
/*Si la comparación de
(bp+10) es menor que dx
salta a la dirección 6ca*/
/*Dada la comparación
anterior fue igual
compara (bp+8) con ax*/
/*Si (bp+8) es mayor o
igual que ax salta a la
dirección 0:06e6. La BIOS
admite la int 13h
extendida*/
/*Establece el valor
ah=02, al=01, Parámetros
de la interrupción 13h,
función=02 y lectura de
01 sector.*/
/*Establece el valor de
0x7c00 a bx. Al ejecutar
la int13h a partir de la
dirección es:bx, se
almacenara el sector
leído.*/
/*Establece el valor del
registro de particiones
del número de cilindro y
numero de sector en que
inicia la partición a cx. El
objetivo es leer el primer
sector de la partición.*/
/*Establece el
Controlador del registro
de partición a dx. En el
caso disco duro 80*/
/*Ejecuta la int 13h. Lee
el primer sector de la
partición primaria activa
y lo almacena en
memoria a partir de la
dirección 0:07c00*/
/*Salta a la posición de
memoria 0:072b si la
lectura del disco tuvo
éxito cf desactivada. Y
retorna*/
Memoria
Hexadecimal
Instrucción Ensamblador(GAS)
0x06da
4f
dec %di
0x06db
744e
je 0x0000072b
0x06dd
320000
xor %ah,%ah
0x06df
8a5600
mov 0x0(%bp),%dl
0x06e2
cd13
int $0x13
0x06e4
ebe4
jmp 0x000006ca
Comentario
/*La lectura del disco no
tuvo éxito. Dec di*/
/*Comprueba que di
haya llegado a cero y de
ser así salta a la dirección
0:072b y retorna*/
/*Establece ah=0*/
/*Establece el valor al
que apunta bp a dl. En
este caso dl contiene el
controlador del disco
80*/
/*Realiza la int 13 h
función cero. Resetea el
disco*/
/*Salta a la dirección
0:06ca, Para intentar
volver a leer el disco*/
Tabla 20. NTLDR código fuente documentado parte 5.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
En resumen la quinta parte del código lo que realiza es leer el primer sector de
la partición primaria activa, lo carga a la posición 0x7c00 y le cede el control de
procesamiento.
La lectura del primer sector de la partición activa se la realiza en base a la
especificación de su registro de la tabla de partición.
En caso de encontrar error en la lectura realiza un reseteo del disco y vuelve a
intentar una vez más si la segunda vez continua con error muestra el mensaje
de error.
También en la quinta parte del código verifica si los parámetros del registro de
la tabla de particiones que esta como activo soporta lba y de ser así ejecuta la
secta parte del código caso contrario lee el primer sector de la partición primaria
en base a los parámetros de la especiación CHS que tiene el registro de la tabla
de particiones.
83
3.4.2. 6. Sexta Parte Del Código
Memoria Hexadecimal Instrucción Ensamblador(GAS)
0x06e6
8a5600
mov 0x0(%bp),%dl
0x06e9
60
pusha
0x06ea
bbaa55
mov $0x55aa,%bx
0x06ed
b441
mov $0x41,%ah
0x06ef
cd13
int $0x13
0x06f1
7236
jb 0x000007029
0x06f3
81fb55aa
cmp $0xaa55,%bx
0x06f7
7530
jne 0x000007029
0x06f9
f6c101
test $0x1,%cl
0x06fc
742b
je 0x000007029
0x06fe
0x06ff
61
60
Popa
pusha
Comentario
/*Establece el valor de (bp) a dl,
en este caso 0x80 el controlador
del driver*/
/*Apila ax*/
/*Establece el valor de 0x55aa en
bx. Parámetros de la función
extendida 13h*/
/*Establece el valor de 41 en ah.
Parámetros de la función
extendida 13h*/
/*Ejecuta al int 13h:CF Activada
en error (no hay extensiones),
limpia si no hay error
AH = ?? Número de la versión
mayor de las extensiones (01h =
1.x, 20h = 2.0 / EDD-1.0, 21h = 2.1
/ EDD-1.1, 30h = EDD-3.0)
AL = ?? Uso Interno
BX = AA55h Devuelve AA55h si
están instaladas
CX = ?? Lista de bits de las
extensiones instaladas (Bit 0-15)
DH = ?? Versión de las
extensiones (v2.0,no presente en
1.x)*/
/*Salta a la dirección 0:0729 3n
caso de error de lectura.*/
/*Compara el valor aa55 con el
valor de bx para ver si están
instaladas la extensiones de la
int13h*/
/*Si la comparación anterior no
son iguales salta a la posición
0:0729, Indica error en la lectura*/
/*Realiza una comparación ente
0001 y el valor de cl.*/
/*Si en la comparación anterior cl
es menor o igual a 1 salta a la
dirección 0:0129 para dar un
mensaje de error*/
/*Des apila ax*/
/*Apila ax*/
84
Memoria Hexadecimal Instrucción Ensamblador(GAS)
Comentario
0x7000
6a00
push $0x0
/*Apila cero*/
0x7002
6a00
push $0x0
/*Apila cero*/
/*Apila el valor de (bp+10)
primera parte del valor del sector
0x7004
ff760a
pushw 0xa(%bp)
en que inicia la partición primaria
que soporta lba*/
/*Apila el valor de (bp+10)
segunda parte del valor del sector
0x7007
ff7608
pushw 0x8(%bp)
en que inicia la partición primaria
que soporta lba*/
0x700a
6a00
push $0x0
/*Apila el numero 0: No se usa*/
0x700c
68007c
push $0x7c00
/*Apila el número 07c00*/
/*Apila el numero 1: Numero de
0x700f
6a01
push $0x1
sectores a leer*/
/*Apila el número 16, tamaño del
0x7011
6a10
push $0x10
DAP. Disk Address Packet*/
0x7013
b442
mov $0x42,%ah
/*Establece el 0x42 en ah. */
/*Establece el valor de sp a sí.
0x7015
8bf4
mov %sp,%si
Ahora si 0x7c00*/
/*Ejecuta la int 13 con función
42h, Lee el primer sector de la
0x7017
cd13
int $0x13
partición primaria y lo almacena
en la dirección 0:07c00*/
/*Des apila y su valor lo pone en
0x701a
61
Popa
ax*/
/*Si la lectura tuvo éxito salta a la
0x701b
730e
jae 0x00000702b
posición 0:0720b*/
/*La lectura no tuvo éxito y
0x701d
4f
dec %di
decrementa di*/
/*Si di =0 retorna con error ya que
0x701e
740b
je 0x00000702b
se activa cf*/
0x7020
320000
xor %ah, %ah
/*Establece ah=0*/
/*Establece el valor de bp a dl, en
0x7022
8a5600
mov 0x0(%bp),%dl
este caso el controlador*/
0x7025
cd13
int $0x13
/*Ejecuta la interrupción 13 h
función 0, Respeta el disco*/
0x7027
ebd6
jmp 0x000006ff
/*Intenta nuevamente la lectura
del disco. Saltando a l 0:06ff*/
0x702a
f9
Stc
0x702b
c3
/*Activa la bandera de acarreo
para indicar error de lectura*/
/*Termina y retorna*/
Ret
Tabla 21. NTLDR código fuente documentado parte 6.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
85
En resumen la sexta parte del código se trata cuando la BIOS soporta la función
extendida 13h, Y se procede a leer el primer de la partición primaria leyendo los
parámetros de la sección lba. Y se procede almacenar el primer sector a la
dirección 0:07c00.
3.4.3. Alcance estudio NTLDR
El alcance del estudio del gestor de arranque del NTLDR es solo de la sección
que corresponde al MBR. El MBR del gestor de arranque NTLDR tiene como
objetivo cargar a memoria el VBR que no se examinara. Solo se dirá que el
VBR contiene el OEM ID (id de la empresa manufacturera), la BPB (BIOS
Parameter Block) y el código para encontrar y cargar el kernel de Windows.
3.5 GRUB LEGACY
3.5.1 Introducción GRUB
GNU GRUB es un gestor de arranque muy potente, que puede cargar una gran
variedad de sistemas operativos libres, así como sistemas operativos
propietarios con un método denominado Chain Loading.
Una de las características importantes de GRUB es la flexibilidad, GRUB
entiende varios sistemas de archivos y formatos ejecutables del núcleo, por lo
que puede cargar un sistema operativo, sin registrar la posición física de su
núcleo en el disco. De este modo se puede cargar el kernel sólo especificando
su nombre de archivo y la unidad y la partición donde reside el kernel.
Al arrancar con GRUB, puede utilizar una interfaz de línea de comandos o una
interfaz de menú. Mediante la interfaz de línea de comandos se debe escribir la
especificación de la unidad y el nombre de archivo del kernel manualmente.
En la interfaz de menú, sólo tiene que seleccionar un sistema operativo con las
teclas de flecha. El menú se basa en un archivo de configuración que se
prepara de antemano. Mientras que en el menú se puede cambiar al modo de
línea de comandos, y viceversa. Se puede editar las entradas del menú antes
de usarlos.
86
3.5.2 Historia de GRUB
GRUB se originó en 1995, cuando Eric Boleyn estaba tratando de arrancar el
GNU Hurd con la Universidad de Utah Mach 4 microkernel (ahora conocido
como GNU Mach). Erich y Brian Ford diseñaron el Multiboot, porque estaban
decididos a no añadir a la gran cantidad de métodos de arranque PC
mutuamente incompatibles.
Erich comenzó modificando el gestor de arranque de FreeBSD para que
soportara arranque múltiple. Pronto se dio cuenta de que sería mucho más fácil
de escribir su propio gestor de arranque desde cero que seguir trabajando en el
gestor de arranque de FreeBSD, y así inicio GRUB.
3.5.3 Características de GRUB
El requisito principal para GRUB es que sea compatible con la especificación de
arranque múltiple.
Los otros objetivos, enumerados en el orden aproximado de importancia, son:

Funciones básicas deben ser sencillo para los usuarios finales.

Funcionalidad rica para apoyar expertos del kernel y diseñadores.

La compatibilidad hacia atrás para arrancar FreeBSD, NetBSD,
OpenBSD y Linux. Núcleos de propiedad (como DOS, Windows NT y OS
/ 2) son compatibles a través de una función de la cadena de carga.
A excepción de los modos específicos de compatibilidad ((chain-loading and the
Linux piggyback format), todos los núcleos se iniciarán en el mismo estado que
en el Multiboot Specification. Sólo los núcleos cargados a 1 megabyte o
superior están actualmente soportados. Cualquier intento de cargar por debajo
de ese límite simplemente resultar en una falla inmediata y un mensaje de
informe de errores el problema.
Además de las características anteriores, GRUB tiene las siguientes
características:
87

Reconocer múltiples formatos ejecutables.- Apoyo muchas de las
variantes más a.out ELF. Las tablas de símbolos también se cargan.

Apoyar kernels no Multiboot.-
Apoyar muchos de los diferentes
núcleos de 32 bits libres que carecen de cumplimiento de arranque
múltiple (principalmente FreeBSD, NetBSD, OpenBSD y Linux). Chainloading de otros gestores de arranque también es compatible.

Módulos múltiples de carga.- Totalmente compatible con la función de
arranque múltiple de cargar varios módulos.

Cargar un archivo de configuración.-
Apoyar a un archivo de
configuración de texto legible por humanos con comandos de arranque
predefinidos. También puede cargar otro archivo de configuración
dinámica e incrustar un archivo de configuración preestablecida en un
archivo de imagen de GRUB. La lista de comandos son un superconjunto
de comandos admitidos en la línea

Proporcionar una interfaz de menú.-
Una interfaz de menú con
comandos de arranque predefinidos, con un tiempo de espera
programable. No hay límite fijo en el número de entradas de arranque.

Tiene una interfaz de línea de comandos flexibles.- Una interfaz de
línea de comandos bastante flexible, accesible desde el menú, está
disponible para editar los comandos predefinidos, o escribir un nuevo
comando de arranque establecido a partir de cero. Si no hay ningún
archivo de configuración está presente, GRUB cae a la línea de
comandos.

Soporte de múltiples tipos de sistemas de archivos.- Soporte de
múltiples tipos de sistemas de ficheros de forma transparente, además
de una notación de lista de bloques explícito útil. Los tipos de sistemas
de archivos soportados son BSD FFS, DOS FAT16 y FAT32, Minix fs,
ext2fs Linux, ReiserFS, JFS, XFS, y VSTA fs.

Soporte descompresión automática.- Puede descomprimir archivos
que se comprimieron por gzip. Esta función es a la vez automática y
transparente para el usuario (es decir, todas las funciones operan en el
88
contenido sin comprimir de los archivos especificados). Esto reduce
considerablemente el tamaño del archivo y la carga del tiempo, una
particular gran beneficio para disquetes.
Es concebible que algunos módulos del núcleo se deben cargar en un
estado comprimido, por lo que un comando del módulo de carga
diferente se puede especificar para evitar la descompresión de los
módulos.

Acceder a los datos en cualquier dispositivo instalado.- La lectura de
datos de soporte de cualquiera o todos los disquetes o disco duro (s)
reconocido por la BIOS, independientemente del ajuste del dispositivo
raíz.

Ser independiente de las traducciones de la geometría de unidad.- A
diferencia de muchos otros gestores de arranque, GRUB hace que la
traducción en particular unidad irrelevante. Una unidad instalada y
funcionando con una traducción se puede convertir en otra traducción,
sin efectos adversos o cambios en la configuración de GRUB.

Detectar todas RAM instalada.- GRUB generalmente puede encontrar
toda la memoria RAM instalada en una máquina compatible con PC.
Utiliza una técnica de consulta BIOS avanzada para encontrar todas las
regiones de memoria.

Apoyo a modo de Dirección de bloque lógico.- En las llamadas de
disco tradicionales (llamado modo CHS), hay un problema de traducción
de geometría, es decir, la BIOS no puede acceder a más de 1024
cilindros, por lo que el espacio accesible se limita a al menos 508 MB y
un máximo de 8 GB. GRUB no puede resolver este problema
universalmente, ya que no hay interfaz estándar utilizado en todas las
máquinas. Sin embargo, varias máquinas más nuevas tienen el modo de
interfaz nueva, direcciones de bloques lógicos (LBA). GRUB detecta
automáticamente si el modo LBA está disponible y lo usa si está
disponible. En el modo LBA, GRUB puede acceder a todo el disco.
89

El arranque de red de apoyo.- GRUB es básicamente un gestor de
arranque basado en disco, pero también tiene soporte de red. Puede
cargar imágenes del sistema operativo de una red mediante el protocolo
TFTP.

Apoyar terminales remotos.- Para apoyar a los ordenadores sin
consola, GRUB proporciona soporte del terminal remoto, de modo que
usted puede controlar GRUB desde un host remoto. Sólo el apoyo
terminal serie se implementa en el momento.
Convención de nomenclatura de GRUB
La forma de especificar una unidad / partición es la siguiente:
En primer lugar, GRUB requiere que el nombre del dispositivo este separado
por una coma del número de partición y los dos deben encerrarse con (), el
número de partición omite para referirse a toda la unidad física.
Los nombres de los dispositivos son:

fd0, fd1, fdn significa que es un disquete, n es el n-esimo número de
unidad.

hd0, hd1, hdn significa que es un disco duro, n es el n-esimo número de
unidad.
El número de partición:

0,1,2,….n significa la n-esima partición del disco.
Ejemplos:

(Fd0)
El número '0' es el número de la unidad, que se contará a partir de cero.
Esta expresión significa que GRUB usará todo el disco.
90

(Hd0,1)
Aquí, hd significa que es una unidad de disco duro. El primer entero 0
indica el número de la unidad, es decir, el primer disco duro, mientras
que el segundo entero 1, indica el número de partición (o el número de
segmento pc en la terminología BSD). Una vez más, se debe tener en
cuenta que los números de partición se cuentan desde cero, no de uno.
Esta expresión significa la segunda partición de la primera unidad de
disco duro. En este caso, GRUB utiliza una partición del disco, en lugar
de todo el disco.

(Hd0,4)
Especifica la primera partición extendida de la primera unidad de disco
duro. Tenga en cuenta que los números de partición para particiones
extendidas se cuentan desde `4 ', independientemente del número real
de particiones primarias en el disco duro.

(Hd1, a)

Esto significa el BSD partición „a‟ del segundo disco duro. Si se necesita
especificar qué número de segmento PC se debe utilizar, se debe usar
(hd1,0, a) . Si el número de segmento pc se omite, búsquedas de GRUB
de la primera partición pc que tiene un BSD „a‟ partición.
Por supuesto, para acceder en realidad los discos o particiones con GRUB, es
necesario utilizar la especificación del dispositivo en un comando, como:
‘root (fd0)’ o ‘unhide (hd0,2)’
Para averiguar qué número especifica una partición que desea, la línea de
comandos de GRUB se tiene la opción de completar el argumento. Esto
significa que, por ejemplo, sólo se tiene que escribir:
‘root (‘
Seguido un <TAB>, y GRUB mostrará la lista de unidades, particiones o
nombres de archivos. Por lo tanto, es bastante fácil de determinar el nombre de
la partición de destino, incluso con un mínimo conocimiento de la sintaxis.
91
Nota: Se debe tener en cuenta que GRUB no distingue entre IDE SCSI. GRUB
cuenta el número de unidades desde cero, independientemente de su tipo.
Normalmente, cualquier número de unidad IDE es menor que cualquier número
de unidades SCSI, aunque eso no es cierto si se cambia la secuencia de
arranque mediante el canje de IDE y SCSI en el BIOS.
Para especificar un archivo considere el siguiente ejemplo:
‘(Hd0,0) / vmlinuz’
Especifica el archivo llamado „vmlinuz ', que se encuentra en la primera
partición del primer disco duro. Se debe tener en cuenta que la realización
argumento funciona con nombres de archivo, también.
3.5.4 Creación de un disquete de arranque GRUB
Para pode crear un disquet de arranque GRUB tenemos algunas opciones:

Tener instalado la versión de GRUB en el disco duro que se le va a
copiar a disco. Veamos un ejemplo suponiendo que tenemos instalado
Linux en una versión de 32 bits y su gestor de arranque GRUB:
# cd /usr/lib/grub/i386-pc
dd if=stage1 of=/dev/fd0 bs=512 count=1
1+0 records in
1+0 records out
# dd if=stage2 of=/dev/fd0 bs=512 seek=1
153+1 records in
153+1 records out

Descargar el código de la versión de GRUB que se desee compilar y
generar los ejecutables, copiarlos al disquet. Esta opción se verá en
detalle en la opción de creación de ejecutables de GRUB.

Iniciar un cd con GRUB y por medio de comandos copiarlos al disquet.
92
3.5.5 Realizar un CD-ROM Booteable con GRUB
GRUB soporta el modo no emulación en la especificación El Torito 5. Esto
significa que se puede utilizar el CD-ROM de GRUB y no se tiene que hacer un
archivo de imagen de disco flexible o disco, que pueda causar problemas de
compatibilidad.
Para arrancar desde un CD-ROM, GRUB usa una Etapa 2 especial llamada
stage2_eltoritol. Los únicos archivos GRUB que se necesita habilitar en el CDROM de arranque son stage2_eltorito y opcionalmente un archivo de
configuración menú.lst. No es necesario utilizar stage1 o stage2, porque El
Torito es bastante diferente del proceso de arranque estándar.
Ejemplo de procedimientos para hacer una imagen de CD-ROM de arranque,
suponiendo que tengo instalado una distribución del sistema operativo Linux de
32 bits y como gestor de arranque GRUB.
En primer lugar se
debe de hacer un directorio superior de la imagen de
arranque, por ejemplo „iso‟:
$ mkdir iso
Crear un directorio para GRUB:
$ mkdir -p iso / boot / grub
Copiar el archivo stage2_eltorito:
$ cp
/usr/lib/grub/ i386-pc/stage2_eltorito
93
iso/boo/grub
Si se desea, hacer que el archivo de configuración menu.lst este bajo iso/boo /
grub y copiar todos los archivos y directorios para el disco en el directorio iso /.
Por último, se debe hacer un archivo de imagen ISO9660 así:
$ mkisofs -R -b boot/grub/stage2_eltorito -no-emul-boot \
-boot-load-size 4 -boot-info-table -o grub.iso iso
Esto produce un archivo llamado grub.iso, que luego se puede quemar en un
CD (o DVD).
Puede utilizar el dispositivo `(cd) 'para acceder a un CD-ROM en su archivo de
configuración. Esto no es necesario; GRUB ajusta automáticamente el
dispositivo raíz a `(cd) 'al arrancar desde un CD-ROM. Sólo es necesario hacer
referencia a `(cd) 'si quiere acceder a otras unidades también.
Instalación de GRUB de forma nativa
Precaución: La instalación stage1 de GRUB de esta manera, borrará el sector
de arranque normal utilizado por el sistema operativo.
GRUB actualmente puede arrancar GNU Mach, Linux, FreeBSD, NetBSD, y
OpenBSD directamente.
Para instalar GRUB en el entorno nativo de la pc se se tendrá que utilizar un
disco de arranque GRUB, un CD-ROM de arranque GRUB y reiniciar el equipo
con él Disco o del CD-ROM
Al encender la pc, GRUB se auto iniciará y mostrará la interfaz de línea de
comandos.
En primer lugar, se debe establecer como dispositivo raíz de GRUB, la partición
que contiene el directorio de arranque, o el dispositivo de arranque así:
grub> root (hd0,0)
94
Al no estar seguro de qué partición ocupa este directorio, Se debe utilizar el
comando find así:
grub> find / boot / grub / stage1
El comando find buscará el nombre del archivo / boot / grub / stage1 y mostrara
los dispositivos que contienen el archivo.
Una vez que se haya configurado correctamente el dispositivo raíz, se debe
ejecutar el comando setup.
grub> setup (hd0)
Este comando instalará el gestor de arranque GRUB en el Master Boot Record
(MBR) de la primera unidad. Si se quiere poner GRUB en el sector de arranque
de una partición en lugar de ponerlo en el primer sector de la unidad,
especifique la partición en la que desea instalar GRUB.
grub> setup (hd0,0)
Después de utilizar el comando de instalación. Se debe iniciar la pc sin el
disquete o CD-ROM.
Instalación de GRUB utilizando grub-install
Precaución: Este procedimiento es menos seguro, porque hay varias formas
en las que el equipo puede llegar a no arrancar. Por ejemplo, la mayoría de
sistemas operativos no tienen métodos en el que GRUB puede mapear los
drivers de la BIOS correctamente. En estos casos GRUB asimila datos por
defecto. Esto tendrá éxito en la mayoría de los casos, pero no siempre. Por lo
tanto, GRUB le proporciona un archivo de mapa llamado el mapa de
dispositivos, que se debe corregir si es incorrecto.
95
Para instalar GRUB utilizando el comando grub-install se debe poner como
argumento el dispositivo o la partición en la que se instalara GRUB.
Por Ejemplo:
# Grub-install / dev / hda
# Grub-install '(hd0)'
# Grub-install hd0
Para la instalación el Disco Floppy
# Mke2fs / dev / fd0
# Mount -t ext2 / dev / fd0 / mnt
# Grub-install --root-directorio = / mnt fd0
# Umount / mnt
Para unidades que se montan se debe utilizar el comando:
# Grub-install-directorio --root = / boot / dev / had
Se debe tener en cuenta que grub-install es en realidad sólo una secuencia de
comandos de shell y la verdadera tarea es realizada por el shell de grub.
Arranque de un Sistema Operativo
GRUB puede cargar núcleos compatibles con Multiboot de una manera
consistente, sin embargo existen Sistemas Operativos libres que tengan que
usarce métodos especiales.
GRUB tiene dos métodos de arranque distintos que son carga directa y
aplicando chain-loadin.
En términos generales, la carga directa es más conveniente, ya que no es
necesario instalar ni mantener otros gestores de arranque. GRUB es lo
suficientemente flexible como para cargar un sistema operativo desde un disco /
partición arbitraria. Sin embargo, el método chain-loading es necesario ya que
GRUB no soporta todos los sistemas operativos existentes de forma nativa.
96
Carga Directa
Grub Utiliza el Multiboot especification.
GRUB puede arrancar cualquier sistema operativo de arranque múltiplecompatible con los siguientes pasos:

Establecer el dispositivo raíz de GRUB a la unidad donde las imágenes
del sistema operativo se almacenan con el comando root.

Cargar la imagen del núcleo con el comando kernel.

Si se necesita módulos, estos se deben cargar con el comando module o
modulenounzip.

Ejecutar el comando boot.
4.1.2 Carga otro gestor de arranque para arrancar sistemas operativos no
compatibles
Método Chain-loading
Para arrancar un sistema operativo no compatible (por ejemplo, Windows 95, xp
vista etc ), se debe utilizar el método chain-loading que lo que realiza es cargar
a memoria el vbr del sistema operativo y transferirle el control.
Los pasos para cargar y ejecutar el método Chain-Loading son:

Establecer el dispositivo raíz de GRUB a la partición por medio del
comando rootnoverify así:
grub> rootnoverify (hd0,0)

Activar la bandera en la partición usando el comando makeactive.
grub> makeactive
97

Cargar el gestor de arranque de la partición ejecutando el comando
chainloader
grub> chainloader +1
El argumento +1 en el comando chianloader indica que se deber leer y
cargar a memoria el tamaño exacto de un sector o 512 bytes, de la
primera partición activa.
Configuración
Grub usa un archivo de configuración para crear la lista en la interfaz de menú
de GRUB de los sistemas operativos para el arranque, básicamente permite al
usuario seleccionar un grupo predefinido de comandos para su ejecución.
Para activar el menú de GRUB se necesita que el archivo de configuración este
en el directorio de arranque.
Como ejemplo se estudiara un archivo de configuración:
El archivo de configuración debe contener configuraciones generales.
Estructura del archivo de configuración
El archivo de configuración de la interfaz de menú de GRUB es
/boot/grub/grub.conf. Los comandos para configurar las preferencias globales
para la interfaz de menú están ubicados al inicio del archivo, seguido de las
diferentes estrofas para cada sistema operativo o kernels listados en el menú.
El siguiente es un ejemplo de archivo de configuración de menú de GRUB muy
básico diseñado para arrancar bien sea Red Hat Enterprise Linux o Microsoft
Windows 2000:
98
default=0
timeout=10
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title Red Hat Enterprise Linux AS (2.6.8-1.523)
root (hd0,0)
kernel /vmlinuz-2.6.8-1.523 ro root=/dev/VolGroup00/LogVol00 rhgb quiet
initrd /initrd-2.6.8-1.523.img
# section to load Windows
title Windows
rootnoverify (hd0,0)
chainloader +1
Tabla 22. Archivo de Configuración de Menú de GRUB.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
Default <opción>
Indica que la primera opción title se ejecutara por defecto en este caso iniciara
Red Hat Enterprise Linux como el sistema operativo predeterminado.
Timeout <tiempo>
Indica el tiempo de espera que tiene el usuario para seleccionar una opción de
arranque, si el tiempo de espera se consume en su totalidad se seleccionara la
opción por defecto selecciona en default. En este caso le dará al usuario una
espera de 10 segundos para seleccionar un sistema operativo diferente a Red
Hat y que establezca un arranque automático después de 10 segundos. Se
proporcionan dos secciones, una para cada entrada de sistema, con comandos
específicos para la tabla de partición del sistema.
Chainloader </ruta/a/archivo>
Carga el archivo especificado como gestor de encadenamiento. Se debe
reemplazar </ruta/a/archivo> con la ruta absoluta al gestor de encadenamiento.
99
Si el archivo está ubicado en el primer sector de la partición especificada, puede
utilizar la notación de lista de bloques, +1.
Color <color-normal> <color-seleccionado>
Le permite configurar los colores específicos que se usarán en el menú. Se
configuran dos colores: uno de fondo y otro de primer plano. Use nombres de
colores simples, tales como red/black para rojo/negro.
Fallback <entero>
El parámetro <entero> es el número del título de la entrada que deberá
probarse si falla el primer intento.
Hiddenmenu
Si se utiliza, no se podrá mostrar la interfaz de menú de GRUB, cargando la
entrada default (predeterminada) cuando caduca el período timeout (tiempo de
espera). El usuario puede ver el menú estándar de GRUB si pulsa la tecla [Esc].
Initrd </ruta/a/initrd>
Permite a los usuarios especificar un disco RAM inicial para utilizarlo al
arrancar. Se debe reemplazar </ruta/a/initrd> con la ruta absoluta al disco RAM
inicial.
Kernel </ruta/a/kernel> <opción-1> <opción-N>
Especifica el archivo del kernel a cargar cuando se arranca el sistema
operativo. Se pueden pasar múltiples opciones al kernel cuando éste se cargue.
Password=<contraseña>
Si se utiliza, el usuario que no conozca la contraseña no podrá modificar las
entradas de esta opción de menú de GRUB.
Opcionalmente, se puede especificar un archivo de configuración de menú
alternativo después de la directriz password=<contraseña>. En este caso,
100
GRUB reiniciará la etapa 2 del gestor de arranque y utilizará este archivo de
configuración alternativo para crear el menú. Si se omite este archivo de
configuración alternativo del comando, el usuario que sepa la contraseña podrá
modificar el archivo de configuración actual.
Root (<tipo-dispositivo><numero-dispositivo>,<partición>)
Configura la partición raíz para GRUB, tal como (hd0,0) y monta la partición.
Rootnoverify (<tipo-dispositivo><numero-dispositivo>,<partición>)
Configura la partición raíz para GRUB, tal como el comando root pero no monta
la partición.
Splashimage=<ruta-a-imagen>
Especifica la ubicación de la imagen de pantalla splash que se utilizará al
arrancar.
Title <título-de-grupo>
Establece un título que se utilizará con un grupo de comandos concreto para
cargar un sistema operativo.
3.5.5 Construcción y Compilación de GRUB
Grub al ser software libre se cuenta con el código para su estudio y
modificación, así los requisitos necesarios en que se construyó y compilo son
los siguientes:

Sistema Operativo Host: Windows 7 de 64 bits.

Virtualizador: Virtual Box versión 4.3.20

Sistema Operativo Guest: GNU Linux Centos de 32 bits versión 6.5

Versión de gcc Red Hat 4.4.7-11

Versión de binutils-2.20.51.0.2-5.42.el6.i68

grub-0.97.tar.gz
101
Proceso
Una vez obtenido grub-0.97.tar.gz a través del sitio ftp:
ftp://alpha.gnu.org/gnu/grub/grub-0.97.tar.gz, y colocado en algún directorio del
Sistema Operativo Centos.
1. Se debe abrir una terminal.
Figura 29. Terminal en Modo Grafico.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
2. Por medio del comando cd se debe posicionar en la carpeta en que se
encuentra el archivo comprimido grub-0.97.tar.gz. En el caso del ejemplo
se encuentra en el directorio de descarga de root.
Figura 30. Comando cd.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
102
3. Se procede a desempaquetar y descomprimir GRUB versión 0.97, con el
comando siguiente comando:
zcat grub-0.97.tar.gz | tar xvf –
Figura 31. Comando zcat.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
Lo cual indicara en la salida de la terminal que se crearon archivos
adicionales.
Figura 32. Ejecución del comando zcat.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
103
En el caso de ejemplo se creó un Directorio de nombre grub-0.97 dentro
del directorio de descargas.
Figura 33. Creación del directorio grub-097.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
El directorio grub-0.97 es el descomprimido y tiene todas las fuentes de
grub.
Figura 34. Contenido del directorio grub-097.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
104
Para verificar que archivos se crean, se tomara como ejemplo el
subdirectorio de grub stage1.
Figura 35. Archivos del directorio stage1.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
4. Ingresamos al directorio de grub-0.97 por medio del comando cd
cd grub-0.97
Figura 36. Ingreso Subdirectorio Grub-0.97.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
En este paso podemos revisar los archivos makefile, el directorio stage1,
stage2 y el código de los diferentes archivos, compilarlos como se desee
en forma individual y global. Para el caso de estudio se lo realizara de
forma global.
105
5. Ejecutamos el archivo de configuración global con el comando:
./configure CC=gcc34
Figura 37. Ejecución de ./configure CC=gcc34
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
La ejecución crea archivos adicionales en el directorio grub-0.97,
modifica archivos makefile que permiten la construcción de los
ejecutables e imagines binarias del código de grub.
Figura 38. Listado de ./configure CC=gcc34.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
106
6. Ejecutamos el archivo install que se configuro con el comando anterior
así:
# make install
Figura 39. Ejecución del archivo install.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
Figura 40. Salida del comando make install.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
107
Como se observa en la salida de la terminal se crearon más archivos
dentro del directorio y subdirectorios de grub-0.97. Algunos de estos
archivos son los ejecutable e imagines binarias puras que se puede
utilizar para crear discos, CD-ROM arrancables.
Para el caso de uso se observara el subdirectorio stage1 de grub-0.97
Como se observa en la figura anterior se tiene los archivos makefile:
MakeFile, MakeFile.am, MakeFile.in
El código fuente:
Stage1.h, stage1.S
Un archivo objeto:
Stage1.o
Un archivo ejecutable:
Stage1.exec
Una imagen binaria pura:
Stage1
A excepción del código fuente los demás archivos se crearon a partir de
ejecutar el archivo de configuración global y el archivo de instalación
global.
3.5.6 Estudio del Código de GRUB
Para realizar un estudio detallado del funcionamiento de GRUB se aplicara
técnicas de ingeniería inversa a la imagen pura de la primera etapa y se
compara con el código libre que proporciona grub, para verificar como funciona.
El código fuente de la primera etapa de GRUB consta de dos archivos el
stage1.h y el stage1.S. El primero es el archivo de cabecera en donde se
definen las constantes, parámetros y demás atributos usados en stage1.S. Se
unirá ambos archivos en uno solo para realizar la comparación del código.
108
3.5.6 .1 Estudio Del Código De La Primera Etapa
La primera etapa de GRUB es el MBR de grub, la imagen binaria que en la
primera etapa se crea se debe almacenar o inyectar en el primer sector o sector
de arranque del dispositivo.
Así la imagen binaria de la primera etapa debe tener un tamaño exacto de 512
bytes y terminar con la firma que caracteriza a un MBR que es el código
hexadecimal 0x55AA.
Código En Hexadecimal
El código hexadecimal de la imagen binaria pura que se creó al construir grub
es:
Figura 41. Código hexadecimal de GRUB Primera Etapa.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
109
Como se observa en la figura anterior la primera etapa de GRUB tiene un
tamaño de 512 bytes y sus dos últimos bytes son 0x55AA, es decir su código es
característico de un gestor de arranque.
Al aplicar la herramienta de Ingeniería Inversa a la imagen binaria de la primera
etapa de GRUB con la página web:
http://www2.onlinedisassembler.com/odaweb/,
Obtendremos
el
código
en
lenguaje ensamblador.
Así configuramos la página web con los parámetros en que se inicia un gestor
de arranque y desensamblamos GRUB.
Figura 42. Configuración des ensamblaje.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
Al desensamblar y eliminar las partes que no son código ensamblador tenemos:
Dirección
.data:0x00007C00
.data:0x00007C02
.data:0x00007C4a
.data:0x00007C4b
.data:0x00007C4d
.data:0x00007C50
.data:0x00007C52
.data:0x00007C54
.data:0x00007C59
.data:0x00007C5b
Hexadecimal
eb48
90
fa
eb07
f6c280
7502
b280
ea597c0000
31c0
8ed8
110
Ensamblador
jmp 0x00007c4a
nop
cli
jmp 0x00007c54
test $0x80,%dl
jne 0x00007c54
mov $0x80,%dl
ljmp $0x0,$0x7c59
xor %ax,%ax
mov %ax,%ds
Dirección
.data:0x00007C5d
.data:0x00007C5f
.data:0x00007C62
.data:0x00007C63
.data:0x00007C66
.data:0x00007C68
.data:0x00007C6a
.data:0x00007C6c
.data:0x00007C6d
.data:0x00007C70
.data:0x00007C73
.data:0x00007C76
.data:0x00007C78
.data:0x00007C7a
.data:0x00007C7d
.data:0x00007C7f
.data:0x00007C80
.data:0x00007C81
.data:0x00007C83
.data:0x00007C87
.data:0x00007C89
.data:0x00007C8c
.data:0x00007C8e
.data:0x00007C90
.data:0x00007C93
.data:0x00007C95
.data:0x00007C99
.data:0x00007C9c
.data:0x00007Ca0
.data:0x00007Ca5
.data:0x00007Ca9
.data:0x00007Cae
Hexadecimal
8ed0
bc0020
fb
a0407c
3cff
7402
88c2
52
be7f7d
e83401
f6c280
7454
b441
bbaa55
cd13
5a
52
7249
81fb55aa
7543
a0417c
84c0
7505
83E103
7437
668b4c10
be057c
c644ff01
668b1e447c
c7041000
c744020100
66895c08
.data:0x00007Cb2
c744060070
.data:0x00007Cb7
.data:0x00007Cba
.data:0x00007Cbd
.data:0x00007Cc1
.data:0x00007Cc3
.data:0x00007Cc5
.data:0x00007Cc7
.data:0x00007Cca
.data:0x00007Ccc
6631c0
894404
6689440c
b442
cd13
7205
bb0070
eb7d
b408
111
Ensamblador
mov %ax,%ss
mov $0x2000,%sp
sti
mov 0x7c40,%al
cmp $0xff,%al
je 0x00007c6c
mov %al,%dl
push %dx
mov $0x7d7f,%si
call 0x000001a7
test $0x80,%dl
je 0x00007ccc
mov $0x41,%ah
mov $0x55aa,%bx
int $0x13
pop %dx
push %dx
jb 0x00007ccc
cmp $0xaa55,%bx
jne 0x00007ccc
mov 0x7c41,%al
test %al,%al
jne 0x00007c95
and $0x1,%cx
je 0x00007ccc
mov 0x10(%si),%ecx
mov $0x7c05,%si
movb $0x1,-0x1(%si)
mov 0x7c44,%ebx
movw $0x10,(%si)
movw $0x1,0x2(%si)
mov %ebx,0x8(%si)
movw
$0x7000,0x6(%si)
xor %eax,%eax
mov %ax,0x4(%si)
mov %eax,0xc(%si)
mov $0x42,%ah
int $0x13
jb 0x00007ccc
mov $0x7000,%bx
jmp 0x00000149
mov $0x8,%ah
Dirección
.data:0x00007Cce
.data:0x00007Cd0
.data:0x00007Cd2
.data:0x00007Cd5
.data:0x00007Cd9
.data:0x00007Cdc
.data:0x00007Cdf
.data:0x00007Ce3
.data:0x00007Ce6
.data:0x00007Ce8
.data:0x00007Ce9
.data:0x00007Ced
.data:0x00007Cef
.data:0x00007Cf1
.data:0x00007Cf4
.data:0x00007Cf6
.data:0x00007Cf8
.data:0x00007Cf9
.data:0x00007Cfc
.data:0x00007Cfe
.data:0x00007D00
.data:0x00007D03
.data:0x00007D06
.data:0x00007D0a
.data:0x00007D0d
.data:0x00007D10
.data:0x00007D13
.data:0x00007D16
.data:0x00007D1a
.data:0x00007D1d
.data:0x00007D20
.data:0x00007D23
.data:0x00007D25
.data:0x00007D28
.data:0x00007D2b
.data:0x00007D2e
.data:0x00007D30
.data:0x00007D32
.data:0x00007D35
.data:0x00007D36
.data:0x00007D39
.data:0x00007D3c
.data:0x00007D3e
Hexadecimal
cd13
730a
f6c280
0f84ea00
e98d00
be057c
c644ff00
6631c0
88f0
40
66894404
31d2
88ca
c1e202
8,80E+09
88f4
40
894408
31c0
88d0
c0e802
668904
66a1447c
6631d2
66f734
88540a
6631d2
66f77404
88540b
89440c
3b4408
7d3c
8a540d
c0e206
8a4c0a
fec1
08d1
8a6c0c
5a
8a740b
bb0070
8ec3
31db
112
Ensamblador
int $0x13
jae 0x00007cdc
test $0x80,%dl
je 0x000001c3
jmp 0x00000169
mov $0x7c05,%si
movb $0x0,-0x1(%si)
xor %eax,%eax
mov %dh,%al
inc %ax
mov %eax,0x4(%si)
xor %dx,%dx
mov %cl,%dl
shl $0x2,%dx
mov %ch,%al
mov %dh,%ah
inc %ax
mov %ax,0x8(%si)
xor %ax,%ax
mov %dl,%al
shr $0x2,%al
mov %eax,(%si)
mov 0x7c44,%eax
xor %edx,%edx
divl (%si)
mov %dl,0xa(%si)
xor %edx,%edx
divl 0x4(%si)
mov %dl,0xb(%si)
mov %ax,0xc(%si)
cmp 0x8(%si),%ax
jge 0x00000161
mov 0xd(%si),%dl
shl $0x6,%dl
mov 0xa(%si),%cl
inc %cl
or %dl,%cl
mov 0xc(%si),%ch
pop %dx
mov 0xb(%si),%dh
mov $0x7000,%bx
mov %bx,%es
xor %bx,%bx
Dirección
.data:0x00007D40
.data:0x00007D43
.data:0x00007D45
.data:0x00007D47
.data:0x00007D49
.data:0x00007D4d
.data:0x00007D4e
.data:0x00007D4f
.data:0x00007D52
.data:0x00007D54
.data:0x00007D56
.data:0x00007D58
Hexadecimal
b80102
cd13
722a
8cc3
8e06487c
60
1e
b90001
8edb
31f6
31ff
fc
.data:0x00007D59
f3a5
.data:0x00007D5b
.data:0x00007D5c
.data:0x00007D5d
.data:0x00007D61
.data:0x00007D64
.data:0x00007D67
.data:0x00007D69
.data:0x00007D6c
.data:0x00007D6f
.data:0x00007D71
.data:0x00007D74
.data:0x00007D77
.data:0x00007D7a
.data:0x00007D7d
.data:0x00007Da0
.data:0x00007Da3
.data:0x00007Da5
.data:0x00007Da7
.data:0x00007Da8
.data:0x00007Daa
.data:0x00007Dac
.data:0x00007Dc3
.data:0x00007Dc6
.data:0x00007Dc8
.data:0x00007Dca
.data:0x00007Dcb
.data:0x00007Dcd
.data:0x00007Dd0
.data:0x00007Dd2
1f
61
ff26427c
be857d
e84000
eb0e
be8a7d
e83800
eb06
be947d
e83000
be997d
e82a00
ebfe
bb0100
b40e
cd10
ac
3c00
75f4
c3
bebd7d
31c0
cd13
46
8a0c
80f900
750f
beda7d
113
Ensamblador
mov $0x201,%ax
int $0x13
jb 0x00000171
mov %es,%bx
mov 0x7c48,%es
pusha
push %ds
mov $0x100,%cx
mov %bx,%ds
xor %si,%si
xor %di,%di
cld
rep movsw
%ds:(%si),%es:(%di)
pop %ds
popa
jmp *0x7c42
mov $0x7d85,%si
call 0x000001a7
jmp 0x00000177
mov $0x7d8a,%si
call 0x000001a7
jmp 0x00000177
mov $0x7d94,%si
call 0x000001a7
mov $0x7d99,%si
call 0x000001a7
jmp 0x0000017d
mov $0x1,%bx
mov $0xe,%ah
int $0x10
lods %ds:(%si),%al
cmp $0x0,%al
jne 0x000001a0
ret
mov $0x7dbd,%si
xor %ax,%ax
int $0x13
inc %si
mov (%si),%cl
cmp $0x0,%cl
jne 0x000001e1
mov $0x7dda,%si
Dirección
.data:0x00007Dd5
.data:0x00007Dd8
.data:0x00007De1
.data:0x00007De4
.data:0x00007De7
.data:0x00007De9
.data:0x00007Deb
.data:0x00007Ded
.data:0x00007Def
.data:0x00007Df1
.data:0x00007Df3
Hexadecimal
e8cfff
eb9d
bb0070
b80102
b500
b600
cd13
72d7
b601
b54f
e9e6fe
Ensamblador
call 0x000001a7
jmp 0x00000177
mov $0x7000,%bx
mov $0x201,%ax
mov $0x0,%ch
mov $0x0,%dh
int $0x13
jb 0x000001c6
mov $0x1,%dh
mov $0x4f,%ch
jmp 0x00007cdc
Tabla 23. Codigo NTLDR.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
Nota: Para saber que partes del código hexadecimal fueron eliminadas, se
puede seguir la columna de dirección, este código hexadecimal representa
parámetros del gestor de arranque.
Para estudiar el código libre de grub se unirá el archivo de cabecera stage1.h y
el código stage1.S en uno solo stage1Total.
Unión de los archivos de Primera Etapa.
Para Unir los archivos de la primera etapa que se crearon por la construcción
de GRUB se utilizara la herramienta de Linux gcc así:
1. Se tiene que abrir una terminal y por medio del uso del comando cd de
Linux y una ruta absoluta se procede a colocar en el directorio de stage1.
Figura 43. Ingreso a Directorio stage1.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
114
2. Ejecutamos el comando grub colocando argumentos que detengan el
proceso en momento de ensamblaje. Así como el código de la primera
etapa esta en código ensamblador. El comando gcc pre procesara los
archivos uniéndoles, compilara el archivo en este paso la compilación lo
que hará es eliminar comentarios y los parámetros definidos en la
cabecera serán colocados en cualquier parte que el archivo stage1.S lo
tenga registrado, y tratara de ensamblar el archivo en el ensamblaje no
se realizara ningún proceso ya que el código que se le paso es lenguaje
ensamblador logrando así el objetivo de tener un solo archivo con el que
se pueda estudiar el código más fácilmente.
Figura 44. Creación de archivo total fuente stage1.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
Como se verifica en la figura anterior se crea un archivo denominado
stage1Total, al ejecutar el comando:
# gcc -S stage1.S -I /root/Downloads/grub-0.97/ >
stage1Total
El archivo stage1Total contiene el siguiente código ensamblador:
.file "stage1.S"
.text
.code16
.globl _start;
_start:
jmp after_BPB
nop
. = _start + 4
115
mode: .byte 0
disk_address_packet:
sectors:.long 0
heads:
.long 0
cylinders:
.word 0
sector_start: .byte 0
head_start:
.byte 0
cylinder_start: .word 0
. = _start + 0x3e
stage1_version:
.byte 3, 2
boot_drive:
.byte 0xFF
force_lba:
.byte 0
stage2_address:
.word 0x8000
stage2_sector:
.long 1
stage2_segment:
.word 0x800
after_BPB:
cli
boot_drive_check:
jmp 1f
testb $0x80, %dl
jnz 1f
movb $0x80, %dl
1:
ljmp $0, $(real_start-_start+0x7c00)
real_start:
xorw %ax, %ax
movw %ax, %ds
movw %ax, %ss
movw $0x2000, %sp
sti
.byte 0xa0; .word (boot_drive-_start+0x7c00)
cmpb $0xFF, %al
je 1f
movb %al, %dl
1:
pushw %dx
movw $(notification_string-_start+0x7c00), %si;
call message
testb $0x80, %dl
jz chs_mode
movb $0x41, %ah
movw $0x55aa, %bx
int $0x13
popw %dx
pushw %dx
jc chs_mode
cmpw $0xaa55, %bx
116
jne chs_mode
.byte 0xa0;
.word (force_lba-_start+0x7c00)
testb %al, %al
jnz lba_mode
andw $1, %cx
jz chs_mode
lba_mode:
movl 0x10(%si), %ecx
movw $(disk_address_packet-_start+0x7c00), %si
movb $1, -1(%si)
movl (stage2_sector-_start+0x7c00), %ebx
movw $0x0010, (%si)
movw $1, 2(%si)
movl %ebx, 8(%si)
movw $0x7000, 6(%si)
xorl %eax, %eax
movw %ax, 4(%si)
movl %eax, 12(%si)
movb $0x42, %ah
int $0x13
jc chs_mode
movw $0x7000, %bx
jmp copy_buffer
chs_mode:
movb $8, %ah
int $0x13
jnc final_init
testb $0x80, %dl
jz floppy_probe
jmp hd_probe_error
final_init:
movw $(sectors-_start+0x7c00), %si
movb $0, -1(%si)
xorl %eax, %eax
movb %dh, %al
incw %ax
movl %eax, 4(%si)
xorw %dx, %dx
movb %cl, %dl
shlw $2, %dx
movb %ch, %al
movb %dh, %ah
incw %ax
movw %ax, 8(%si)
xorw %ax, %ax
movb %dl, %al
117
shrb $2, %al
movl %eax, (%si)
setup_sectors:
movl (stage2_sector-_start+0x7c00), %eax
xorl %edx, %edx
divl (%si)
movb %dl, 10(%si)
xorl %edx, %edx
divl 4(%si)
movb %dl, 11(%si)
movw %ax, 12(%si)
cmpw 8(%si), %ax
jge geometry_error
movb 13(%si), %dl
shlb $6, %dl
movb 10(%si), %cl
incb %cl
orb %dl, %cl
movb 12(%si), %ch
popw %dx
movb 11(%si), %dh
movw $0x7000, %bx
movw %bx, %es
xorw %bx, %bx
movw $0x0201, %ax
int $0x13
jc read_error
movw %es, %bx
copy_buffer:
movw (stage2_segment-_start+0x7c00), %es
pusha
pushw %ds
movw $0x100, %cx
movw %bx, %ds
xorw %si, %si
xorw %di, %di
cld
rep
movsw
popw %ds
popa
jmp *(stage2_address)
geometry_error:
movw $(geometry_error_string-_start+0x7c00), %si;
call message
jmp general_error
hd_probe_error:
movw $(hd_probe_error_string-_start+0x7c00), %si;
118
call message
jmp general_error
read_error:
movw $(read_error_string-_start+0x7c00), %si;
call message
general_error:
movw $(general_error_string-_start+0x7c00), %si;
call message
stop:
jmp stop
notification_string: .string "GRUB "
geometry_error_string: .string "Geom"
hd_probe_error_string: .string "Hard Disk"
read_error_string: .string "Read"
general_error_string: .string " Error"
1:
movw $0x0001, %bx
movb $0xe, %ah
int $0x10
message:
lodsb
cmpb $0, %al
jne 1b
ret
. = _start + 0x1b8
nt_magic:
.long 0 .word 0
part_start:
. = _start + 0x1be
probe_values:
.byte 36, 18, 15, 9, 0
floppy_probe:
movw $(probe_values-1 -_start+0x7c00), %si
probe_loop:
xorw %ax, %ax
int $0x13
incw %si
movb (%si), %cl
cmpb $0, %cl
jne 1f
movw $(fd_probe_error_string-_start+0x7c00), %si;
call message
jmp general_error
fd_probe_error_string: .string "Floppy"
1:
movw $0x7000, %bx
movw $0x201, %ax
119
movb $0, %ch
movb $0, %dh
int $0x13
jc probe_loop
movb $1, %dh
movb $79, %ch
jmp final_init
. = _start + 0x1fe
.word 0xaa55
Código stage1Total
Estructura del Código
Examinando el código libre de GRUB en el directorio stage1, y el código que se
genera de la aplicación de herramienta de ingeniería inversa podemos
estructurar el código hexadecimal de la siguiente manera:
Figura 45. Código hexadecimal diferenciado de GRUB Primera Etapa.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
120
Al Código de GRUB lo podemos estructurar en tres partes principales:
La sección de código que se muestra en amarillo.
La sección de mensajes mostrada en verde.
La sección firma mostrada en rojo.
La sección de parámetros mostrada en los demás colores excepto el blanco.
Nota: la sección de blanco en código no se utiliza es necesaria para dar
formato a la posición del código.
El código libre que se unió y el código que se obtuvo de la ingeniería inversa se
procederán a estudiar teniendo en cuenta la estructura antes indicada.
Se dividirá la sección de código según sea necesario para diferenciar partes
como funciones, saltos de código que leen parámetros de configuración,
cambian parámetros, y como la primera etapa del código carga la segunda
etapa.
3.5.7 .1 Primera parte del Código
Figura 46. Código Hexadecimal GRUB parte 1
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
Código
Comentario
.file "stage1.S" /*Indica el nombre del archivo*/
/*Directiva de gas que indica la sección de código*/
.text
.code16
.globl _start;
_start:
jmp after_BPB
nop
/*Directiva que indica que el código debe ser generado como de 16 bits*/
/*Directiva que indica el inicio del código.*/
/*Etiqueta de inicio del código*/
/*Salta a la etiqueta BPB(BIOS parámetros bloque)*/
/*Instrucción nula*/
Tabla 24. Codigo GRUB parte 1.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
121
Dirección
Hexadecimal
.data:0x00007C00 eb48
.data:0x00007C02 90
Ensamblador
Comentario
/*Salta a la d122irección
jmp 0x00007c4a
0:07c4a*/
nop
/*Instrucción nula*/
Tabla 25. Código GRUB desensamblado parte 1.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
La primera secion del código toma los primeros 3 bytes, su función es saltar la
sección de condifiguracion de parámetro de bloque de BIOS y demás
parámetros de configuración. En este caso salta a la posición de memoria
0:07c4a que es donde inicia la cuarta parte del código.
3.5.7 .2 Segunda parte del Código
Figura 47. Código Hexadecimal GRUB parte 2.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
Color Hexadecimal
Código
Comentario
/*Salta 4 bytes desde el inicio*/
. = _start + 4
/*Asigna el valor de 0 al byte en la
quinta posición del código, representa
el mode*/
mode: .byte 0
disk_address_packet:
/*Etiqueta, indica el inicio del bloque
del direccionamiento del disco. */
sectors: .long 0
/*Almacena en 4 bytes el numero de
sectores*/
heads: .long 0
/*Almacena en 4 bytes el numero de
cabeceras*/
cylinders: .word 0
/*Almacena en una palabra o dos bytes
el numero de cilindros*/
/*Etiqueta indica el bloque del sector de
inicio.*/
/*Alamacena en un byte el valor 0*/
sector_start:
.byte 0
122
Color Hexadecimal
Código
Comentario
/*Etiqueta indica el bloque de la
cabecera de inicio.*/
/*Alamacena en un byte el valor 0*/
head_start:
.byte 0
/*Etiqueta indica el bloque de el cilindro
de inicio.*/
cylinder_start:
/*Almacena en una palabra dos bytes el
valor 0 */
.word 0
/*Salta al byte 0x3e, al byte 62 en
decimal*/
. = _start + 0x3e
Tabla 26. Código GRUB parte 2.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
La segunda parte del código su objetivo es crear posiciones en memoria de la
estructura del disco, como son el numero de sectores, el numero de cabeceras,
el sector de inicio.
En el código existen etiquetas estas no ocupan ningún esapcio en el código
binario ya que sirven para dar mecanismo al código, saltos, bucles, etc.
En esta parte de código existe el nemotécnico .=_start+nn, esta significa que
desde el inicio del código almacenara valores nulos n veces, el objetivo es
estructurar el código.
Los parámetros que se crean en esta parte del código sus valores son
reescritos al ejecutarse las demás prociones del código.
Este bloque es conocido como el bloque de parameros del BIOS.
3.5.7.3 Tercera parte del Código
Figura 48. Código Hexadecimal GRUB parte 2.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
123
Color
Hexadecimal
Código
Comentario
stage1_version:
/*Etiqueta que identifica la versión */
.byte 3, 2
/*Almacena doy bytes con valor 3 y 2 son
la versiones*/
boot_drive:
.byte 0xFF
/*Etiqueta que identifica el controlador
de inicio*/
/*Almacena el byte 0xFF*/
force_lba:
.byte 0
/*Etiqueta que indica si el dispositivo
acepta lba*/
/*Almacena el valor cero como byte*/
stage2_address:
/*Etiqueta que inidica la posion en la
iniciara la etapa 2*/
.word 0x8000
/*Alamacena el valor 0x800 como
palabra*/
stage2_sector:
/*Etiqueta que indica el numero de
sectores de la etapa 2*/
.long 1
/*Almacena el valor 1 en cuatro bytes*/
stage2_segment:
/*Etiqueta que inidica el segmento de
etapa 2*/
.word 0x800
/*Alamacena el valor 0x800 en dos bytes
o como palabra.*/
Tabla 27. Código GRUB Parte 3.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
En la tercera etapa del código se configuran parámetros de la primera y
segunda etapa de GRUB, como la versión de GRUB, si soporta lba, el sector de
inicio de la segunda etapa, el tamaño de la segunda epata en sectores etc.
Algunos de estos valores cambian conforme se ejecuta el código.
3.5.7.4 Cuarta parte del Código
Para el estudio de la cuarta parte del código se unira el código desensamblado
y el código libre de GRUB, se comentara las líneas del programa.
124
Código
Dirección Nemotécnico Desensamblado
Código Libre
0x7C4a
0x7C4b
Fa
eb07
cli
jmp
0x00007c54
Comentario
after_BPB:
/*Etiqueta que indica el fin
del Bloque BPB*/
cli
/*Establece en cero las
banderas de interrupción.
Desabilitando las
interrupciones
enmascarables*/
boot_drive_check:
/*Etiqueta que indica el
Bloque donde se puede
comparar el controlador
de inicio*/
jmp 1f
/*Salta a la etiqueta 1:,
Actualmente en la posición
0x7c54*/
0x7C4d
f6c280
test $0x80,%dl
testb $0x80, %dl
/*Realiza una operación
and entre el valor 0x80 y
dl, las BIOS antes de dar el
control al mbr almacenan
valores de configuración
por ejemplo colocan el
controlador del dispositivo
de donde van a arrancar
en dl*/
0x7C50
7502
jne 0x00007c54
jnz 1f
/*Salta a la etiqueta 1 o
dirección 0:07c54, si dl no
tiene el 0x80*/
0x7C52
b280
mov $0x80,%dl
movb $0x80, %dl
/*Mueve el valor 0x80 a
dl*/
1:
/*Etiqueta de código*/
ljmp $0, $(real_start_start+0x7c00)
/*Salta a la posicionde
memoria cs,ip, en este
caso 0:07c59*/
real_start:
/*Etiqueta de código, su
valor lo calcula el
compilador pero solo para
estructurar el código.*/
0x7C54
ea597c0000
ljmp
$0x0,$0x7c59
125
Código
Dirección Nemotécnico Desensamblado Código Libre
Comentario
0x7C59
31c0
xor %ax,%ax
xorw %ax, %ax
/*Establece en ax =0*/
0x7C5b
8ed8
mov %ax,%ds
movw %ax, %ds
/*Mueve el valor de ax a
ds, Establece ds=0*/
0x7C5d
8ed0
mov %ax,%ss
movw %ax, %ss
/*Mueve el valor de ax a
ss, Establece ss=0*/
0x7C5f
bc0020
mov
$0x2000,%sp
movw $0x2000, %sp
/*Establece en sp el
numero 0x2000*/
0x7C62
Fb
sti
sti
/*Activa las banderas de
interrupción*/
0x7C63
a0407c
.byte 0xa0; .word
mov 0x7c40,%al (boot_drive_start+0x7c00)
/*Mueve el valor de la
dirección 0:0x7C40 a al, es
el valor de boot_drive
actualmente 0xff*/
0x7C66
3cff
cmp $0xff,%al
cmpb $0xFF, %al
/*Realiza una
comparación 0xFF con al*/
0x7C68
7402
je 0x00007c6c
je 1f
/*Si en la comparación
anterior sus valore eran
iguales salta a la proxima
etiqueta 1:, o lo que es lo
mismo a la dirección
0x7C6C*/
0x7C6a
88c2
mov %al,%dl
movb %al, %dl
/*Mueve el contenido del
registro al a dl*/
1:
/*Etiqueta del código*/
push %dx
pushw %dx
/*Apila el valor de dx*/
mov
$0x7d7f,%si
movw
$(notification_string_start+0x7c00), %si;
/*Mueve el valor de de la
dirección en que inicia
notification_ string a si, Se
prepara para imprimir un
mensaje*/
0x7C6c
0x7C6d
0x7C70
52
be7f7d
e83401
call 0x00007da7 call message
126
/*llama a la función
message, que inicia en la
dirección 0:07da7*/
Código
Dirección Nemotécnico Desensamblado Código Libre
0x7C73
f6c280
test $0x80,%dl
Comentario
testb $0x80, %dl
/*Realiza una operación
and de el valor de 0x80 con
dl*/
0x7C76
7454
je 0x00007ccc
jz chs_mode
/*Si la operación test o and
anterior dio igula a cero
salta a la etiqueta
chs_mode o 0:07ccc. Para
ver la estructara del disco
en la especificacion chs*/
0x7C78
b441
mov $0x41,%ah
movb $0x41, %ah
/*Establece el valor de
ox41h a ah, Es para
comprobar si soprta lba*/
0x7C7a
bbaa55
mov
$0x55aa,%bx
movw $0x55aa, %bx
/*Parametro de la int
13h*/
0x7C7d
cd13
int $0x13
int $0x13
/*Ejecuta la int 13h CF
Activada en error (no hay
extensiones)
AH = Número de la versión
mayor de las extensiones
BX = 55AAh Devuelve
55AAh si están instaladas
CX = bits de las
extensiones instaladas (Bit
0-15)
DH = Versión de las
extensiones*/
0x7C7f
0x7C80
5ª
52
pop %dx
push %dx
popw %dx
pushw %dx
/*Apila dx*/
/*Des apila dx*/
0x7C81
7249
jb 0x00007ccc
jc chs_mode
/*Si la anterio int 13h
activo cf no acepta lba y
salta a la etiqueta
chs_mode*/
0x7C83
81fb55aa
cmp
$0xaa55,%bx
cmpw $0xaa55, %bx
/*Compara la palabra
0xaa55 con bx, para
verificar que soporta lba*/
jne chs_mode
/*En caso de no soportar
lba salta a la etiqueta
chs_mode*/
0x7C87
7543
jne 0x00007ccc
127
Código
Dirección Nemotécnico Desensamblado Código Libre
Comentario
0x7C89
a0417c
.byte 0xa0; .word
mov 0x7c41,%al (force_lba_start+0x7c00)
0x7C8c
84c0
test %al,%al
testb %al, %al
/*Realiza una comparación
and para verificar si al es
cero*/
0x7C8e
7505
jne 0x00007c95 jnz lba_mode
/*Si al no es cero sal ta a la
etiqueta lba_mode*/
and $0x1,%cx
andw $1, %cx
/*Realiza una operación
and entre el valor 1 y cx,
Actualmente cx contiene
bits de las extensiones
instaladas*/
jz chs_mode
/*Si la operación and dio
cero salta a la etiqueta
chs_mode*/
0x7C90
0x7C93
83E103
7437
je 0x00007ccc
/*Mueve el valor de la
direccion0:07c41 a al.
Etiqueta de lba*/
Tabla 28. Código GRUB parte 4.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
La cuarta parte del código lo que realiza es crear una pila establecer los valores
de segementos de datos, segmento extra etc. Imprime un mensaje. Verifica si la
BIOS soporta el equema lba de ser así salta a la quinta parte del código en la
que se revisa los parámetros de lba, caso sontrario salta a la sexta parte del
código donde se revisa el esquema chs.
3.5.7.5 Quinta parte del Código
Código
Dirección Nemotécnico
Desensamblado
Código Libre
lba_mode:
128
Comentario
/*Etiqueta de
código, Indica el
inicio del bloque
de la
especificacion
lba*/
Código
Dirección Nemotécnico
0x7C95
0x7C99
0x7C9c
0x7Ca0
0x7Ca5
0x7Ca9
668b4c10
be057c
c644ff01
668b1e447c
c7041000
c744020100
Desensamblado
Código Libre
Comentario
/*Mueve 4 bytes
de la dirección
0:si+16 a ecx,
Puede mover 4
bytes si se este
menejando modo
real*/
mov
0x10(%si),%ecx
movl 0x10(%si), %ecx
mov $0x7c05,%si
movw
$(disk_address_packet_start+0x7c00), %si
/*Mueve la
dirección de
disk_adress_packet
a si*/
movb $1, -1(%si)
/*Mueve el valor
de 1 un byte antes
de la dirección que
almacena si, Este
valor representa el
modo*/
movl (stage2_sector_start+0x7c00), %ebx
/*Mueve la
dirección de
stage2_sector_start
a ebx, el valor de
1*/
movw $0x0010, (%si)
/*Establece el valor
0x0010 a la
dirección que
apunta si, si apunta
a
disk_adress_packet
quedando en
memoria 10 00, el
tamaño del dap es
de 0x10 */
movw $1, 2(%si)
/*Establece el valor
de 0x0001 a los 2
bytes siguiente que
apunta si,
quedando el dap 10
00 01 00*/
movb $0x1,0x1(%si)
mov 0x7c44,%ebx
movw $0x10,(%si)
movw
$0x1,0x2(%si)
129
Código
Dirección Nemotécnico
Desensamblado
Código Libre
0x7Cae
66895c08
mov
%ebx,0x8(%si)
movl %ebx, 8(%si)
0x7Cb2
c744060070
movw
$0x7000,0x6(%si)
movw $0x7000, 6(%si)
0x7Cb7
6631c0
xor %eax,%eax
xorl %eax, %eax
0x7Cba
894404
mov %ax,0x4(%si)
movw %ax, 4(%si)
0x7Cbd
6689440c
mov %eax,0xc(%si)
movl %eax, 12(%si)
130
Comentario
/*Mueve el valor
de ebx actualmente
1 a la dirección que
apunta el registro si
mas 8 bytes.
Absoluto numero
de inicio de los
sectores a ser
leido.Quedando
dap 10 00 01 00 ??
?? ?? ?? 01 00 00
00*/
/*Mueve la palabra
0x7000 a la
dirección apuntada
por si +6 bytes
reprensenta la
dirección de
memoria donce se
lamacenarn los
sectores leidos.
Quedando dap 10
00 01 00 ?? ?? 00
70 01 00 00 00
00*/
/*Establece
eax=0*/
/*Mueve el valor
de ax=0 a la
dirección que
apunta si, para
completar el
numero de
sectores leidos,
quedando el dap
así: 10 00 01 00 00
00 00 70 01 00 00
00 00*/
/*Mueve el valor
de eax a la
dirección que
apunta si + 12
bytes, Paa
completar el dap.*/
Código
Dirección Nemotécnico
Desensamblado
Código Libre
0x7Cc1
b442
mov $0x42,%ah
movb $0x42, %ah
0x7Cc3
cd13
int $0x13
int $0x13
0x7Cc5
7205
jb 0x00007ccc
jc chs_mode
0x7Cc7
bb0070
mov $0x7000,%bx
movw $0x7000, %bx
0x7Cca
eb7d
jmp 0x00007D49
jmp copy_buffer
Comentario
/*Establece el valor
de 0x42h a ah*/
/*Ejecuta la int 13h
con función 42 h,
para ller los
sectores del disco
según los
parámetros de dl y
si, Si hay error ctiva
cf*/
/*En caso de la
int13h ejecutar
error salta a la
etiqueta
chs_mode*/
/*Establece le valor
de 0x7000 a bx*/
/*Salta a a copiar el
buffer, o a la
dirección 0:7D49*/
Tabla 29. Código GRUB parte 5.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
La quinta parte del código configura los parámetros de la especificación lba, y
lee del disco el sector de la segunda etapa
La información leída del disco la almacena en memoria, para en la quinta parte
del código volver a copiarla a otro lado de memoria.
Sexta parte del Código
Código
Dirección Nemotécnico
0x7Ccc
b408
Desensamblado
mov $0x8,%ah
Código Libre
Comentario
chs_mode:
/*Etiqueta de
código*/
movb $8, %ah
/*Establece el
valor de 0x8 a ah.
Función 8h*/
131
Código
Dirección Nemotécnico
Desensamblado
Código Libre
0x7Cce
cd13
int $0x13
int $0x13
0x7Cd0
730ª
jae 0x00007cdc
jnc final_init
0x7Cd2
f6c280
test $0x80,%dl
testb $0x80, %dl
0x7Cd5
0f84ea00
je 0x00007dc3
jz floppy_probe
0x7Cd9
e98d00
jmp 0x00007d69
jmp hd_probe_error
final_init:
0x7Cdc
be057c
mov $0x7c05,%si
movw $(sectors_start+0x7c00), %si
0x7Cdf
c644ff00
movb $0x0,0x1(%si)
movb $0, -1(%si)
0x7Ce3
6631c0
xor %eax,%eax
xorl %eax, %eax
132
Comentario
/*Ejecuta la
interrupción 13
función 8h , para
obtener los
parámetros del
disco*/
/*Se la lectura de
los parámetros no
da error salta a
final_init o a la
dirección
0:07cdc*/
/*Realiza una
operación and bit
a bit del valor
0x80 con dl*/
/*Si la operación
and dio cero salta
a la etiqueta
floppy_probe
cuya dirección es
0:7dc3*/
/*Salta a ejecutar
un mensaje de
error a la
dirección
0:7d69*/
/*Etiqueta de
código*/
/*Mueve el valor
de la dirección de
la etiqueta sector
a si. En este caso
0x7c05*/
/*Establece el
valor de cero a la
dirección que
apunta si menos
un byte, en este
caso es el mode*/
/*Establece
eax=0*/
Código
Dirección Nemotécnico
Desensamblado
Código Libre
Comentario
/*Mueve el valor
de dh a al, dh es
una valor
almacenado por
la BIOS antes de
dar el control al
MBR*/
0x7Ce6
88f0
mov %dh,%al
movb %dh, %al
0x7Ce8
40
inc %ax
incw %ax
0x7Ce9
66894404
mov %eax,0x4(%si)
movl %eax, 4(%si)
0x7Ced
31d2
xor %dx,%dx
xorw %dx, %dx
/*Establece
dx=0*/
0x7Cef
88ca
mov %cl,%dl
movb %cl, %dl
/*Mueve el valor
de cl a dl*/
0x7Cf1
c1e202
shl $0x2,%dx
shlw $2, %dx
0x7Cf4
8800000000
mov %ch,%al
movb %ch, %al
0x7Cf6
88f4
mov %dh,%ah
movb %dh, %ah
/*Mueve el valor
de dh a ah*/
0x7Cf8
40
inc %ax
incw %ax
0x7Cf9
894408
mov %ax,0x8(%si)
movw %ax, 8(%si)
0x7Cfc
31c0
xor %ax,%ax
xorw %ax, %ax
/*Incrementa ax
en una unidad*/
/*Mueve el valor
de ax a la
dirección de si + 8
bytes. Representa
el número de
cilindros */
/*Establece
ax=0*/
0x7Cfe
88d0
mov %dl,%al
movb %dl, %al
0x7D00
c0e802
shr $0x2,%al
shrb $2, %al
133
/*Incrementa en
una unidad el
valor de ax*/
/*Mueve el valor
de eax a la
dirección que
apunta si + 4
bytes, el número
de cabeceras*/
/*Desplaza 2 bits
a la izquierda el
valor de dx*/
/*Mueve ch a al*/
/*Mueve el valor
de dl a al*/
/*Recorre 2 bits a
a la derecha el
valor de al*/
Código
Dirección Nemotécnico
0x7D03
668904
Desensamblado
mov %eax,(%si)
Código Libre
movl %eax, (%si)
setup_sectors:
0x7D06
66a1447c
mov 0x7c44,%eax
movl (stage2_sector_start+0x7c00), %eax
0x7D0a
6631d2
xor %edx,%edx
xorl %edx, %edx
0x7D0d
66f734
divl (%si)
divl (%si)
0x7D10
88540ª
mov %dl,0xa(%si)
movb %dl, 10(%si)
0x7D13
6631d2
xor %edx,%edx
xorl %edx, %edx
0x7D16
66f77404
divl 0x4(%si)
divl 4(%si)
0x7D1a
88540b
mov %dl,0xb(%si)
movb %dl, 11(%si)
134
Comentario
/*Mueve el valor
de eax a la
dirección que
almacena si.
Representa el
número de
sectores*/
/*Etiqueta de
Código*/
/*Mueve la
dirección que
contiene la
etiqueta
stage2_sector a
eax, en este caso
0x7c44*/
/*Establece
edx=0*/
/*Divide el valor
de eax para el
valor que
almacena la
dirección de si*/
/*Mueve el valor
de dl a la
dirección de
memoria si +10
bytes. Representa
el sector de inicio
de la segunda
etapa*/
/*Establece
edx=0*/
/*Divide el valor
de eax para el
valor que
almacena la
dirección de si + 4
bytes*/
/*Mueve el valor
de dl a la
dirección de si
+11 bytes*/
Código
Dirección Nemotécnico
Desensamblado
Código Libre
Comentario
/*Mueve el valor
de ax a la
dirección de si
+12 bytes*/
/*Realiza una
comparación
entre el valor de
la dirección de si
+8 bytes y el
registro dl */
0x7D1d
89440c
mov %ax,0xc(%si)
movw %ax, 12(%si)
0x7D20
3b4408
cmp 0x8(%si),%ax
cmpw 8(%si), %ax
0x7D23
7d3c
jge 0x00007d61
jge geometry_error
0x7D25
8a540d
mov 0xd(%si),%dl
movb 13(%si), %dl
0x7D28
c0e206
shl $0x6,%dl
shlb $6, %dl
/*Recorre 6 bits a
la izquierda del
registro dl*/
0x7D2b
8a4c0a
mov 0xa(%si),%cl
movb 10(%si), %cl
/*Mueve el valor
de la dirección de
si +10 bytes a cl*/
0x7D2e
fec1
inc %cl
incb %cl
0x7D30
08d1
or %dl,%cl
orb %dl, %cl
0x7D32
8a6c0c
mov 0xc(%si),%ch
movb 12(%si), %ch
0x7D35
5ª
pop %dx
popw %dx
0x7D36
8a740b
mov 0xb(%si),%dh
movb 11(%si), %dh
0x7D39
bb0070
mov $0x7000,%bx
movw $0x7000, %bx
135
/*Salta a la
dirección 0:07d61
si existe error*/
/*Mueve el valor
de la dirección de
si + 14 bytes a
dl*/
/*Incrementa el
valor de cl*/
/*Realiza la
operación or
entre dl y cl
almacenado el
resultado en cl,
suma dl , cl*/
/*Mueve el valor
de la dirección de
si +12 bytes a
ch*/
/*des apila dx*/
/*Mueve el valor
de la dirección de
si +11 bytes a
dh*/
/*Mueve el valor
de 0x7000 a bx*/
Código
Dirección Nemotécnico
Desensamblado
Código Libre
Comentario
0x7D3c
8ec3
mov %bx,%es
movw %bx, %es
/*Mueve el valor
de bx a es*/
0x7D3e
31db
xor %bx,%bx
xorw %bx, %bx
/*Establece el
valor de bx =0*/
0x7D40
b80102
mov $0x201,%ax
movw $0x0201, %ax
0x7D43
cd13
int $0x13
int $0x13
0x7D45
722ª
jb 0x00000171
jc read_error
0x7D47
8cc3
mov %es,%bx
movw %es, %bx
/*Establece los
parámetros de la
función ah=02, al
=01 de la int13h*/
/*Ejecuta la int
13h para leer los
sectores de la
etapa 2 con los
valores antes
configurados*/
/*Si la lectura da
error salta a la
etiqueta
read_error que es
la dirección
0:7d71*/
/*Muestra el
valor de es a bx*/
Tabla 30. Código GRUB parte 6.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
La sexta parte del código configura los parámetros de la especificación chs y
verifica que todo este normal caso contrario salta a imprimir mensajes de error.
Carga a memoria el sector de segunda etapa igual que la quinta parte solo que
en esta ocasión con la especificación chs.
Continúa con la séptima parte del código.
136
Séptima parte del Código
Código
Dirección Nemotécnico
0x7D49
8e06487c
0x7D4d
0x7D4e
60
1e
0x7D4f
b90001
Desensamblado
Código Libre
mov 0x7c48,%es
movw
(stage2_segment_start+0x7c00), %es
pusha
push %ds
pusha
pushw %ds
mov $0x100,%cx
movw $0x100, %cx
0x7D52
8edb
mov %bx,%ds
movw %bx, %ds
0x7D54
0x7D56
31f6
31ff
xor %si,%si
xor %di,%di
xorw %si, %si
xorw %di, %di
0x7D58
Fc
cld
cld
0x7D59
f3a5
rep movsw
%ds:(%si),%es:(%di)
rep movsw
Comentario
/*Mueve el valor en
palabra o dos bytes
del que apunta la
dirección
stage2_segment_start
a es. En este caso
0x80 00*/
/*Apila ax*/
/*Apila ds*/
/*Establece el valor
de 0x100 a cx*/
/*Mueve el valor de
bx a ds, bx
almacenaba 0x7000*/
/*Establece si =0*/
/*Establece di=0*/
/*Limpia la bandera
de dirección*/
/*Repite cx veces e
movimiento de la
palabra de ds:si a
es:di, en esta ocasión
cx=256. Es decir
mueve el bloque que
leyó del disco y los
traslada a la dirección
80000:0*/
Tabla 31. Código GRUB parte 7.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
La séptima parte del código lo que realiza es copiar 512 bytes desde la posición
de memoria 7000:000 a la dirección de memoria 8000:000.
137
Octava parte del Código
Código
Dirección Nemotécnico
Desensamblado
Código Libre
Comentario
/*Des apila ds
establece ds=0*/
0x7D5b
1f
pop %ds
popw %ds
0x7D5c
61
popa
popa
0x7D5d
ff26427c
jmp *0x7c42
jmp *(stage2_address)
/*Des apila ax,
Establece ax=0*/
/*Salta a la
dirección
contenida en la
dirección de
stage2_adress , en
este caso 0x8000,.
Aquí termina
etapa 1 pasa a la
etapa 2*/
Tabla 32. Código GRUB parte 8.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
La octava parte del código realiza la limpieza del registro de datos y del
acumulador. Salta a la dirección 0x8000:0x000 que es el inicio del código de la
segunda etapa
Novena parte del código
Código
Dirección Nemotécnico Desensamblado
Código Libre
geometry_error:
0x7D61
0x7D64
be857d
e84000
mov
$0x7d85,%si
Comentario
/*Etiqueta de código*/
/*Mueve el valor de la
dirección de la etiqueta
movw
geometry_error_string
$(geometry_error_stringa si. Se prepara para
_start+0x7c00), %si;
imprimir mensaje de
error*/
call 0x000001a7
call message
138
/*Llama a la función
message para imprimir
mensaje de error*/
Código
Dirección Nemotécnico Desensamblado
0x7D67
eb0e
jmp
0x00000177
0x7D69
be8a7d
mov
$0x7d8a,%si
0x7D6c
e83800
call 0x000001a7
0x7D6f
eb06
jmp
0x00000177
0x7D71
be947d
mov
$0x7d94,%si
0x7D74
e83000
call 0x000001a7
Código Libre
Comentario
jmp general_error
/*Salta a la dirección
de la etiqueta general
error para imprimir el
mensaje de error
general*/
hd_probe_error:
/*Etiqueta de código*/
/*Mueve el valor de la
dirección de la etiqueta
movw
hd_probe_error_string
$(hd_probe_error_stringa si. Se prepara para
_start+0x7c00), %si;
imprimir mensaje de
error*/
call message
/*Llama a la función
message para imprimir
mensaje de error*/
jmp general_error
/*Salta a la dirección
de la etiqueta general
error para imprimir el
mensaje de error
general*/
read_error:
/*Etiqueta de código*/
movw
$(read_error_string_start+0x7c00), %si;
/*Mueve el valor de la
dirección de la etiqueta
read_error_string a si.
Se prepara para
imprimir mensaje de
error*/
call message
/*Llama a la función
message para imprimir
mensaje de error*/
general_error:
/*Etiqueta de código*/
139
Código
Dirección Nemotécnico Desensamblado
0x7D77
0x7D7a
0x7D7d
be997d
e82a00
Ebfe
mov
$0x7d99,%si
Código Libre
Comentario
movw
$(general_error_string_start+0x7c00), %si;
/*Mueve el valor de la
dirección de la etiqueta
general_error_string a
si. Se prepara para
imprimir mensaje de
error*/
call message
/*Llama a la función
message para imprimir
el mensaje de error*/
stop:
/*Etiqueta de código*/
jmp stop
/*Salta a la etiqueta de
código stop. Crea un
bucle infinito*/
call 0x00007da7
jmp
0x00007d7d
/*Etiqueta de código
notification_string: .string
que representa el inicio
"GRUB "
de la cadena GRUB*/
geometry_error_string:
.string "Geom"
/*Etiqueta de código
que representa el inicio
de la cadena Geom*/
hd_probe_error_string:
.string "Hard Disk"
/*Etiqueta de código
que representa el inicio
de la cadena Hard
Disk*/
/*Etiqueta de código
read_error_string: .string
que representa el inicio
"Read"
de la cadena GRUB*/
general_error_string:
.string " Error"
/*Etiqueta de código
que representa el inicio
de la cadena Error*/
/**/
0x7D7d
Ebfe
jmp
0x0000017d
1:
140
/*Etiqueta de código*/
Código
Dirección Nemotécnico Desensamblado
0x7Da0
0x7Da3
0x7Da5
0x7Da7
0x7Da8
0x7Daa
0x7Dac
bb0100
b40e
cd10
Ac
3c00
75f4
c3
mov $0x1,%bx
mov $0xe,%ah
Código Libre
Comentario
movw $0x0001, %bx
/*Establece el valor de
1 a bx, sirve para el
modo grafico
específicamente pagina
1*/
movb $0xe, %ah
/*Establece el valor de
0xe a ah, es la función
de imprimir un
carácter*/
int $0x10
/*Ejecuta la
interrupción 10h
función 0xe, Imprimir
carácter*/
message:
/*Etiqueta que indica el
inicio de la función
message*/
lodsb
/*Almacena el valor de
ds:si a al*/
cmpb $0, %al
/*Compara si el valor
almacenado en al es
cero, esto indica que se
alcanzó el fin de la
cadena*/
jne 1b
/*Si el valor anterior de
al no es cero salta a la
dirección de memoria
0:7da0*/
ret
/*Termino de imprimir
la cadena y regresa a la
posición de memoria
donde fue llamado la
función message*/
. = _start + 0x1b8
/*Completa de ceros
para que a estructurar
el código de la primera
etapa de grub*/
int $0x10
lods
%ds:(%si),%al
cmp $0x0,%al
jne 0x00007da0
ret
Tabla 33. Código GRUB parte 9.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
141
La novena parte del código contiene etiquetas de mensajes, la función que
imprime dichos mensajes, La etiqueta que genera un bucle infinito que es
llamada cuando se produce un error.
Décima parte del código
Código
Dirección Nemotécnico
Desensamblado
Código Libre
floppy_probe:
0x7Dc3
bebd7d
mov $0x7dbd,%si
31c0
int $0x13
inc %si
incw %si
/*Incrementa el valor
de si*/
8a0c
mov (%si),%cl
movb (%si), %cl
/*Mueve el valor de la
dirección que
contiene si a cl*/
80f900
cmp $0x0,%cl
cmpb $0, %cl
/*Realiza una
comparación del valor
de cero con cl*/
0x7Dca
46
0x7Dcb
0x7Dcd
0x7Dd5
xorw %ax, %ax
int $0x13
cd13
0x7Dd2
xor %ax,%ax
/*Etiqueta de
código*/
/*Establece ax=0*/
/*Ejecuta la
interrupción 13h con
función 0h para
resetear el disco*/
0x7Dc8
0x7Dd0
/*Etiqueta de
código*/
movw $(probe_values-1 /*Establece el valor
-_start+0x7c00), %si
de 0x7dbd a si*/
probe_loop:
0x7Dc6
Comentario
750f
jne 0x00007de1
beda7d
/*Mueve el valor de la
dirección de
movw
fd_probe_error_string
mov $0x7dda,%si $(fd_probe_error_stringa si. Se prepara para
_start+0x7c00), %si;
imprimir mensaje de
error*/
e8cfff
jne 1f
/*En caso de no ser
iguales salta a la
dirección 0x7de1*/
call 0x000001a7
call message
142
/*Llama a la función
message para
imprimir error*/
Código
Dirección Nemotécnico
Desensamblado
Código Libre
0x7Dd8
jmp 0x00000177
jmp general_error
/*Salta a la etiqueta
general_error, la
dirección es 0x7d77*/
fd_probe_error_string:
.string "Floppy"
/*Etiqueta de código
que representa la
cadena Floppy*/
eb9d
1:
0x7De1
bb0070
Comentario
/*Etiqueta de
código*/
movw $0x7000, %bx
/*Mueve el valor
0x7000 a bx*/
mov $0x201,%ax
movw $0x201, %ax
/*Almacena los
valores de
configuración de la int
13 h en este caso
ah=2, al=1*/
mov $0x7000,%bx
0x7De4
b80102
0x7De7
b500
mov $0x0,%ch
movb $0, %ch
/*Establece el valor
de ch=0. Limpia ch*/
0x7De9
b600
mov $0x0,%dh
movb $0, %dh
/*Establece el valor
de dh=0, limpia el
valor de dh*/
0x7Deb
cd13
int $0x13
int $0x13
/*Ejecuta la int 13h
para leer el sector de
la segunda parte de
GRUB del disco*/
0x7Ded
72d7
jb 0x000001c6
jc probe_loop
/*En caso de dar error
salta a la etiqueta
probe_loop, cuya
dirección es 0x7Dc6*/
0x7Def
b601
mov $0x1,%dh
movb $1, %dh
/*Mueve el valor de 1
a dh*/
0x7Df1
b54f
mov $0x4f,%ch
movb $79, %ch
/*Mueve el valor de
79 a ch*/
0x7Df3
e9e6fe
jmp 0x00007cdc
jmp final_init
/*Salta a la etiqueta
0:7cdc*/
. = _start + 0x1fe
/*Completa de ceros
los bytes restantes
para que mida 510
bytes*/
Tabla 34. Código GRUB parte 10.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
143
La décima parte del código es para verificar si el disco de arranque es un disco
floppy. Y completa los 510 bytes.
Onceava parte del código
Dirección
0x7Dfe
Nemotécnico
0x55aa
Código
Desensamblado
Código Libre
.word 0xaa55
.word 0xaa55
Comentario
/*Firma de Arranque*/
Tabla 35. Firma Código GRUB parte 11.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
3.6 Modificación del Gestor de Arranque GRUB
Se puede modificar el código del Gestor de arranque GRUB LEGACY ya que es
software libre y está bajo licencia GNU GPL.
La modificación del Gestor de Arranque grub se la realizara tanto en la primera
etapa como en la segunda etapa.
Se modificara sus mensajes de error, sus mensajes de presentación, sus
comentarios para que aparezcan en pantalla en lenguaje español.
Con las herramientas antes indicadas en la construcción de GRUB LEGACY,
procederemos a construir el código de GRUB Modificado.
Debido al tamaño en código de los archivos de GRUB, en este documento se
presentara los archivos que fueron modificados.
144
3.6.1 Modificación Del Archivo stage1.S
Archivo stage1.S
/*
* SISTEMA : GRUB LEGACY MODIFICADO
* MODULO : UNIVERSIDAD CENTRAL DEL ECUADOR
* PROCESO : Stage1.S
* DESCRIPCIÓN : Código en lenguaje ensamblador de 16 bits que tiene un tamaño exacto de
* 512, su función es leer de un dispositivo de la pc la segunda etapa de GRUB,
* cargarlo a memoria y cederle el control de la pc. Emitir mensajes de error cuando se
* producen.
* ANALISTAS : Ing. Mauro Rosas, Ing. Jairo Navarro, Ing. Jorge Morales
* PROGRAMADOR : Figueroa Cañar Victor Bolívar
* FECHA CREACIÓN, MODIFICACIÓN: 05 de Abril del 2015
* LICENCIA: GNU GPL versión 2 o mayor.
*/
#include <stage1.h>
/* Direcciones Absolutas
*Esto permite al ensamblador generar la dirección de memoria sin soporte del linker.*/
#define ABS(x) (x-_start+0x7c00)
/*Imprime la cadena de mensaje que se le pase como argumento.*/
#define MSG(x) movw $ABS(x), %si; call message
/* Mueve el valor de x a al, lo hace directamente en código hexadecimal ya que los binutils no
* lo pueden generar.*/
#define MOV_MEM_TO_AL(x) .byte 0xa0; .word x
.file
"stage1.S"
145
.text
/* Indica a gas que genere código de 16 bits, tal que trabaje en modo real. */
.code16
.globl _start;
/*Etiqueta de inicio del código de ejecución*/
_start:
jmp
after_BPB
nop
. = _start + 4
/*Bloque de configuración del BIOS Parameter Block, en esquema chs o lba.*/
mode:
.byte
0
disk_address_packet:
sectors:
.long
0
.long
0
heads:
cylinders:
.word 0
sector_start:
.byte
0
head_start:
.byte
0
cylinder_start:
.word 0
/* Finalizo el BPB (BIOS parameter block). */
. = _start + STAGE1_BPBEND
146
stage1_version:
.byte
COMPAT_VERSION_MAJOR, COMPAT_VERSION_MINOR
boot_drive:
.byte
GRUB_INVALID_DRIVE /* El controlador del disco desde
*donde se cargara stage2.*/
force_lba:
.byte
0
stage2_address:
.word 0x8000
stage2_sector:
.long
1
stage2_segment:
.word 0x800
after_BPB:
/*Configuración general*/
cli
/*
* En esta fase solo salta a la etiqueta próxima 1:
*/
boot_drive_check:
jmp
1f
/* El siguiente bloque nunca es ejecutado*/
testb
$0x80, %dl
jnz
1f
movb $0x80, %dl
/*Fin bloque sin ejecutar*/
147
1:
/*
* Salta a la dirección de memoria 0000:7C00 + la posición
* de la etiqueta real_start.
*/
ljmp
$0, $ABS(real_start)
real_start:
/* Establece ds y ss desde cero*/
xorw
%ax, %ax
movw %ax, %ds
movw %ax, %ss
/* Establece el tamaño de la pila */
movw $STAGE1_STACKSEG, %sp
sti
/*
* Comprueba si se tiene una referencia de disco forzado aquí
*/
MOV_MEM_TO_AL(ABS(boot_drive))
cmpb $GRUB_INVALID_DRIVE, %al
je
1f
movb %al, %dl
1:
/* Almacena en la pila el controlador referenciado primero*/
pushw %dx
/* Imprime una notificación de mensaje en pantalla */
148
MSG(notification_string)
/* No prueba esquema LBA si la unidad es un disquete */
testb
$STAGE1_BIOS_HD_FLAG, %dl
jz
chs_mode
/* Prueba si LBA es soportado */
movb $0x41, %ah
movw $0x55aa, %bx
int
$0x13
/*
* %dl pudo haber sido reescrito por INT 13, AH=41H.
* Esto sucede por ejemplo en la AST BIOS 1.04.
* Des apila el valor de dx que se apilo y lo vuelve apilar.
* es decir restablece el valor de dl
*/
popw %dx
pushw %dx
/*Usa el esquema CHS si falla */
jc
chs_mode
cmpw $0xaa55, %bx
jne
chs_mode
/* Prueba si LBA es soportado, si force_lba es cero */
MOV_MEM_TO_AL(ABS(force_lba))
testb
%al, %al
jnz
lba_mode
andw $1, %cx
jz
chs_mode
149
lba_mode:
/* Guarda el total número de sectores. */
movl
0x10(%si), %ecx
/* Establece %si a el dpa (disk address packet) */
movw $ABS(disk_address_packet), %si
/* Establece el modo a no cero */
movb $1, -1(%si)
movl
ABS(stage2_sector), %ebx
/* Establece el tamaño del dpa */
movw $0x0010, (%si)
/* Los bloques*/
movw $1, 2(%si)
/* La absoluta dirección.*/
movl
%ebx, 8(%si)
/* El segmento direccional de memoria. */
movw $STAGE1_BUFFERSEG, 6(%si)
xorl
%eax, %eax
movw %ax, 4(%si)
movl
%eax, 12(%si)
/*
* Llama a la interrupción BIOS "INT 0x13 Función 0x42" para leer sectores
* desde disco y almacenarlos en memoria
*
*
Llama con:
%ah = 0x42
%dl = Numero controlador
150
*
*
%ds:%si = segmento:desplazamiento de dpa
Retorna:
*
%al = 0x0 satisfactorio; error código de falla
*/
movb $0x42, %ah
int
$0x13
/* Si LBA no es soportado intenta con el esquema CHS */
jc
chs_mode
movw $STAGE1_BUFFERSEG, %bx
jmp
copy_buffer
chs_mode:
/*
* Determina la geometría del disco duro con ayuda de interrupciones
* de la BIOS!
*/
movb $8, %ah
int
$0x13
jnc
final_init
/*
* En caso de fallar prueba con el controlador del Disquete
*/
testb
$STAGE1_BIOS_HD_FLAG, %dl
jz
floppy_probe
/* El disco duro tiene problemas y se imprime un mensaje de error */
jmp
hd_probe_error
151
final_init
movw $ABS(sectors), %si
/* Establece el modo a cero */
movb $0, -1(%si)
/* Guarda el número de cabeceras */
xorl
%eax, %eax
movb %dh, %al
incw
%ax
movl
%eax, 4(%si)
xorw
%dx, %dx
movb %cl, %dl
shlw
$2, %dx
movb %ch, %al
movb %dh, %ah
/* Guarda el número de cilindros */
incw
%ax
movw %ax, 8(%si)
xorw
%ax, %ax
movb %dl, %al
shrb
$2, %al
/* Guarda el número de sectores */
movl
%eax, (%si)
setup_sectors:
/* Cargar el inicio del sector lógico (mitad inferior) */
movl
ABS(stage2_sector), %eax
/* Establece cero edx */
152
xorl
%edx, %edx
/* Divide por el número de sectores */
divl
(%si)
/* Guarda el sector de inicio */
movb %dl, 10(%si)
xorl
%edx, %edx
divl
4(%si)
/* Divide por el número de cabeceras */
/* Guarda la cabecera de inicio*/
movb %dl, 11(%si)
/* Guarda el cilindro de inicio */
movw %ax, 12(%si)
/* Comprueba que la geometría sea la correcta*/
cmpw 8(%si), %ax
jge
geometry_error
/*
* El siguiente bloque configura la geometría del disco.
*/
/*Obtiene los bits de mayor precedencia del cilindro*/
movb 13(%si), %dl
shlb
$6, %dl
/* recorre 6 bits a la izquierda */
movb 10(%si), %cl
/* Obtiene el sector */
incb
/* Normaliza el sector (sectores van
%cl
desde 1-N, a 0-(N-1) ) */
orb
%dl, %cl
153
movb 12(%si), %ch
/*Cilindros en ch */
/* Restablece dx */
popw %dx
/* Numero de cabeceras */
movb 11(%si), %dh
/*
* Interrupción BIOS "INT 0x13 Función 0x2" lee sectores del disco y los
* almacena en memoria
*
Parámetros:
%ah = 0x2
*
%al = número de sectores
*
%ch = cilindro
*
%cl = sector (bits 6-7 son los bits altos "cilindro")
*
%dh = cabecera
*
%dl = drive (0x80 para el disco doro,
*
0x0 para el disquete)
*
*
%es:%bx = segmento:desplazamiento de memoria
Retorna:
*
%al = 0x0 satisfactorio; error código de falla
*/
movw $STAGE1_BUFFERSEG, %bx
movw %bx, %es
xorw
%bx, %bx
/* Establece bx=0 */
movw $0x0201, %ax /* función 2, leer 1 sector */
int
$0x13
jc
read_error
movw %es, %bx
copy_buffer:
movw ABS(stage2_segment), %es
154
/*
* Se apila ax y ds en caso de que etapa 2
* necesite utilizar estos valores.
*/
pusha
pushw %ds
movw $0x100, %cx
movw %bx, %ds
xorw
%si, %si
xorw
%di, %di
cld
rep
movsw
popw %ds
popa
/* Inicia Etapa 2*/
jmp
*(stage2_address)
/*Fin de la Etapa 1 */
/*
* Error en la traducción en la geometría del BIOS.
*/
geometry_error:
MSG(geometry_error_string)
jmp
general_error
/*
* Error prueba del disco fallo.
155
*/
hd_probe_error:
MSG(hd_probe_error_string)
jmp
general_error
/*
* Error lectura sobre el disco.
*/
read_error:
MSG(read_error_string)
general_error:
MSG(general_error_string)
/* Crea un bucle infinito después de fallo irreparable */
stop:
jmp
stop
notification_string:
.string "MOD U. CENTRAL GRUB"
geometry_error_string: .string "Geom"
hd_probe_error_string: .string "Hard"
read_error_string:
.string "Read"
general_error_string: .string " Error"
/*
* message: Imprime en pantalla la cadena apuntada por si
*/
/*
* Usa BIOS "int 10H Función 0Eh" para escribir caracteres en modo
* teletipo
*
%ah = 0xe
%al = carácter
*
%bh = page
%bl = color de fondo (modo gráfico)
*/
156
1:
movw $0x0001, %bx
movb $0xe, %ah
int
$0x10
message:
lodsb
cmpb $0, %al
jne
1b
/* Si no finaliza cadena repite bucle*/
ret
/*
* Windows NT rompe compatibilidad se embebe un
* Número especial aquí.
*/
. = _start + STAGE1_WINDOWS_NT_MAGIC
nt_magic:
.long 0
.word 0
part_start:
. = _start + STAGE1_PARTSTART
probe_values:
.byte
36, 18, 15, 9, 0
floppy_probe:
/*
* Realiza prueba de disquete.
*/
movw $ABS(probe_values-1), %si
probe_loop:
157
/* Resetea controlador de disquete INT 13h AH=0 */
xorw
%ax, %ax
int
$0x13
incw
%si
movb (%si), %cl
/* Si el número de sectores es cero imprime mensaje de error. */
cmpb $0, %cl
jne
1f
MSG(fd_probe_error_string)
jmp
general_error
fd_probe_error_string: .string "Floppy"
1:
/* Lectura Realizada*/
movw $STAGE1_BUFFERSEG, %bx
movw $0x201, %ax
movb $0, %ch
movb $0, %dh
int
$0x13
/* Si existe error salta a la etiqueta "probe_loop" */
jc
probe_loop
movb $1, %dh
movb $79, %ch
jmp
final_init
. = _start + STAGE1_PARTEND
/* Los dos últimos bytes deben contener la firma que indica que es arrancable*/
.word STAGE1_SIGNATURE
Archivo: Stage1.S
158
3.6.2 Modificación del Archivo stage1.h
Archivo Stage1.h
/*
* SISTEMA : GRUB LEGACY MODIFICADO
* MODULO : UNIVERSIDAD CENTRAL DEL ECUADOR
* PROCESO : Stage1.h
* DESCRIPCIÓN : Cabecera del archivo stage1.S, contiene etiquetas de
* definiciones para poder compilar el archivo stage1.S
* ANALISTAS : Ing. Mauro Rosas, Ing. Jairo Navarro, Ing. Jorge Morales
* PROGRAMADOR : FIGUEROA CAÑAR VICTOR BOLÍVAR
* FECHA CREACIÓN, MODIFICACIÓN: 05 de Abril del 2015
* LICENCIA: GNU GPL versión 2 o mayor.
*/
#ifndef STAGE1_HEADER
#define STAGE1_HEADER
1
/* Se define el número de versión, tal que Stage1 pueda conocer este. */
#define COMPAT_VERSION_MAJOR
3
#define COMPAT_VERSION_MINOR
2
#define COMPAT_VERSION
((COMPAT_VERSION_MINOR << 8) \
| COMPAT_VERSION_MAJOR)
/* La firma que identifica al MBR */
#define STAGE1_SIGNATURE
0xaa55
/* El desplazamiento en bytes al terminar el BPB (BIOS Parameter Block). */
#define STAGE1_BPBEND
0x3e
/* El desplazamiento en bytes de la mayor versión */
159
#define STAGE1_VER_MAJ_OFFS
0x3e
/* El desplazamiento de BOOT_DRIVE. */
#define STAGE1_BOOT_DRIVE 0x40
/* El desplazamiento de FORCE_LBA. */
#define STAGE1_FORCE_LBA
0x41
/* El desplazamiento de STAGE2_ADDRESS. */
#define STAGE1_STAGE2_ADDRESS
0x42
/* El desplazamiento de STAGE2_SECTOR. */
#define STAGE1_STAGE2_SECTOR
0x44
/* El desplazamiento de STAGE2_SEGMENT. */
#define STAGE1_STAGE2_SEGMENT
0x48
/* El desplazamiento de BOOT_DRIVE_CHECK. */
#define STAGE1_BOOT_DRIVE_CHECK 0x4b
/* The offset of a magic number used by Windows NT. */
#define STAGE1_WINDOWS_NT_MAGIC
0x1b8
/* El desplazamiento del inicio de la tabla de partición. */
#define STAGE1_PARTSTART
0x1be
/* El desplazamiento del fin de la tabla de partición. */
#define STAGE1_PARTEND
0x1fe
/* The segmento de pila. */
#define STAGE1_STACKSEG
0x2000
160
/* El segmento de memoria de disco. La memoria de disco debe ser 32K de longitud como
mínimo */
#define STAGE1_BUFFERSEG
0x7000
/* La dirección de los parámetros del controlador */
#define STAGE1_DRP_ADDR
0x7f00
/* El tamaño total de los parámetros del controlador */
#define STAGE1_DRP_SIZE
0x42
/* La bandera para el numero controlador de la BIOS a designar un disco duro o un disquete
*/
#define STAGE1_BIOS_HD_FLAG
0x80
/* El numero de un controlador invalido. */
#define GRUB_INVALID_DRIVE 0xFF
#endif
Archivo: Stage1.h
161
3.6.3 Modificación del Archivo char_io.c
Archivo char_io.c
/*
* SISTEMA : GRUB LEGACY MODIFICADO
* MODULO : UNIVERSIDAD CENTRAL DEL ECUADOR
* PROCESO: char_io.c
* DESCRIPCIÓN: Rutinas en lenguaje c de ingreso de datos a través del teclado, formas de
representar mensajes en pantalla. Manejo de errores en datos Etc.
* ANALISTAS : Ing. Mauro Rosas, Ing. Jairo Navarro, Ing. Jorge Morales
* PROGRAMADOR : FIGUEROA CAÑAR VICTOR BOLÍVAR
* FECHA CREACIÓN, MODIFICACIÓN: 05 de Abril del 2015
* LICENCIA: GNU GPL versión 2 o mayor.
*/
#include <shared.h>
#include <term.h>
#ifdef SUPPORT_HERCULES
# include <hercules.h>
#endif
#ifdef SUPPORT_SERIAL
# include <serial.h>
#endif
#ifndef STAGE1_5
struct term_entry term_table[] =
{
{
"console",
0,
console_putchar,
console_checkkey,
162
console_getkey,
console_getxy,
console_gotoxy,
console_cls,
console_setcolorstate,
console_setcolor,
console_setcursor
},
#ifdef SUPPORT_SERIAL
{
"serial",
/* Un serial dispositivo debe ser inicializado.*/
TERM_NEED_INIT,
serial_putchar,
serial_checkkey,
serial_getkey,
serial_getxy,
serial_gotoxy,
serial_cls,
serial_setcolorstate,
0,
0
},
#endif /* Soporte Serial*/
#ifdef SUPPORT_HERCULES
{
"hercules",
0,
hercules_putchar,
console_checkkey,
console_getkey,
hercules_getxy,
163
hercules_gotoxy,
hercules_cls,
hercules_setcolorstate,
hercules_setcolor,
hercules_setcursor
},
#endif /* Soporte Hercules */
/* Esta debe ser la última entrada */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
/* This must be console. */
struct term_entry *current_term = term_table;
int max_lines = 24;
int count_lines = -1;
int use_pager = 1;
#endif
void
print_error (void)
{
if (errnum > ERR_NONE && errnum < MAX_ERR_NUM)
#ifndef STAGE1_5
/* llama al método printf("\7\n %s\n", err_list[errnum]); */
printf ("\nError %u: %s\n", errnum, err_list[errnum]);
#else /* STAGE1_5 */
printf ("Error %u\n", errnum);
#endif /* STAGE1_5 */
}
164
char *
convert_to_ascii (char *buf, int c,...)
{
unsigned long num = *((&c) + 1), mult = 10;
char *ptr = buf;
#ifndef STAGE1_5
if (c == 'x' || c == 'X')
mult = 16;
if ((num & 0x80000000uL) && c == 'd')
{
num = (~num) + 1;
*(ptr++) = '-';
buf++;
}
#endif
do
{
int dig = num % mult;
*(ptr++) = ((dig > 9) ? dig + 'a' - 10 : '0' + dig);
}
while (num /= mult);
/* Reordena a la correcta dirección. */
{
char *ptr1 = ptr - 1;
char *ptr2 = buf;
while (ptr1 > ptr2)
{
int tmp = *ptr1;
165
*ptr1 = *ptr2;
*ptr2 = tmp;
ptr1--;
ptr2++;
}
}
return ptr;
}
void
grub_putstr (const char *str)
{
while (*str)
grub_putchar (*str++);
}
void
grub_printf (const char *format,...)
{
int *dataptr = (int *) &format;
char c, str[16];
dataptr++;
while ((c = *(format++)) != 0)
{
if (c != '%')
grub_putchar (c);
else
switch (c = *(format++))
{
#ifndef STAGE1_5
case 'd':
case 'x':
166
case 'X':
#endif
case 'u':
*convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0;
grub_putstr (str);
break;
#ifndef STAGE1_5
case 'c':
grub_putchar ((*(dataptr++)) & 0xff);
break;
case 's':
grub_putstr ((char *) *(dataptr++));
break;
#endif
}
}
}
#ifndef STAGE1_5
int
grub_sprintf (char *buffer, const char *format, ...)
{
/* Emula unificacion con printf() */
int *dataptr = (int *) &format;
char c, *ptr, str[16];
char *bp = buffer;
dataptr++;
while ((c = *format++) != 0)
167
{
if (c != '%')
*bp++ = c; /* apila(c); */
else
switch (c = *(format++))
{
case 'd': case 'u': case 'x':
*convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0;
ptr = str;
while (*ptr)
*bp++ = *(ptr++); /* putchar(*(ptr++)); */
break;
case 'c': *bp++ = (*(dataptr++))&0xff;
/* Apila((*(dataptr++))&0xff); */
break;
case 's':
ptr = (char *) (*(dataptr++));
while ((c = *ptr++) != 0)
*bp++ = c; /* Apila(c); */
break;
}
}
*bp = 0;
return bp - buffer;
}
168
void
init_page (void)
{
cls ();
grub_printf ("\n AUTOR: vfigueroa GRUB MODIFICADO versión 0.01 (%dK baja / %dK alta
memoria)\n\n", mbi.mem_lower, mbi.mem_upper);
}
/* El número de entradas de la historia. */
static int num_history = 0;
static char *
get_history (int no)
{
if (no < 0 || no >= num_history)
return 0;
return (char *) HISTORY_BUF + MAX_CMDLINE * no;
}
/* Adiciona CMDLINE a la historia del buffer. */
static void
add_history (const char *cmdline, int no)
{
grub_memmove ((char *) HISTORY_BUF + MAX_CMDLINE * (no + 1),
(char *) HISTORY_BUF + MAX_CMDLINE * no,
MAX_CMDLINE * (num_history - no));
grub_strcpy ((char *) HISTORY_BUF + MAX_CMDLINE * no, cmdline);
if (num_history < HISTORY_SIZE)
num_history++;
169
}
static int
real_get_cmdline (char *prompt, char *cmdline, int maxlen,
int echo_char, int readline)
{
/* Esta función es complicada tal que se explicara el concepto.
* Una sección es una parte de la línea que debe ser mostrada en
* pantalla, pero una sección nunca es mostrada con otra sección
* simultáneamente.
* Cada sección es básicamente 77 caracteres o menos, pero la excepción
* es la primera sección, que es 78 o menos caracteres, porque el
* punto de partida es especial. Se detalla más abajo.
* La primera sección contiene un prompt y una línea de comandos (o la
* primera parte de una línea de comandos cuando es demasiado largo para
* estar en pantalla). Así, en la primera sección, el número de caracteres
* de la línea de comandos desplegados es de 78 menos el largo del prommpt
* (o menor)
* Si la linea de comandos tiene más caracteres , '>' is puesto a la
* posición 78 (cero original),para informar al usuario de los caracteres
* escondidos.
* Otras secciones siempre tienen '<' en la primera posición, ya que allí
*
Esta absolutamente una sección antes de cada sección. Si esta es una
*
sección después de otra sección, esta sección consiste de 77 caracteres
* Y el símbolo '>' en la última posición. La ultima sección tiene 77 o
*
menos caracteres y no tiene el símbolo '>'
* Cada otra sección distinta de las ultimas compartes algunos caracteres
* Con la sección previa. Esta región es llamada 'margen'. Si el cursor es
* puesto a él margen que es compartido por la primera sección y la segunda,
* La primera sección es desplegada. caso contrario la sección desplegada es
* cambiada a la otra sección, solo si el cursor es puesto fuera de la seccion.
170
*/
#define CMDLINE_WIDTH
78
#define CMDLINE_MARGIN
10
int xpos, lpos, c, section;
/* El tamaño del PROMPT. */
int plen;
/* El tamaño de la linea de comandos. */
int llen;
/* El índice para la historia */
int history = -1;
/* La sección de memoria de trabajo para la linea de comandos */
char *buf = (char *) CMDLINE_BUF;
/* Limpieza de la memoria */
char *kill_buf = (char *) KILL_BUF;
/*Las declaraciones de las funciones anidadas son prefijadas con
* la etiqueta 'auto' */
auto void cl_refresh (int full, int len);
auto void cl_backward (int count);
auto void cl_forward (int count);
auto void cl_insert (const char *str);
auto void cl_delete (int count);
auto void cl_init (void);
/* Retrocede al cursor */
void cl_backward (int count)
171
{
lpos -= count;
/* Si el cursor está en la primera sección, despliega la primera sección
* en lugar de la segunda */
if (section == 1 && plen + lpos < CMDLINE_WIDTH)
cl_refresh (1, 0);
else if (xpos - count < 1)
cl_refresh (1, 0);
else
{
xpos -= count;
if (current_term->flags & TERM_DUMB)
{
int i;
for (i = 0; i < count; i++)
grub_putchar ('\b');
}
else
gotoxy (xpos, getxy () & 0xFF);
}
}
/* Retrocede al cursor */
void cl_forward (int count)
{
lpos += count;
/* Si el cursor sale de pantalla, desplaza la pantalla hacia la
* derecha. */
if (xpos + count >= CMDLINE_WIDTH)
172
cl_refresh (1, 0);
else
{
xpos += count;
if (current_term->flags & TERM_DUMB)
{
int i;
for (i = lpos - count; i < lpos; i++)
{
if (! echo_char)
grub_putchar (buf[i]);
else
grub_putchar (echo_char);
}
}
else
gotoxy (xpos, getxy () & 0xFF);
}
}
/* Limpia la pantalla. Si FULL es verdadero, redibuja el full linea,
* caso contrario, solo LEN caracteres desde LPOS. */
void cl_refresh (int full, int len)
{
int i;
int start;
int pos = xpos;
if (full)
{
/* Recalcula la sección numérica. */
if (lpos + plen < CMDLINE_WIDTH)
173
section = 0;
else
section = ((lpos + plen - CMDLINE_WIDTH)
/ (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN) + 1);
/* Desde el inicio al final. */
len = CMDLINE_WIDTH;
pos = 0;
grub_putchar ('\r');
/* Si esta sección es la primera, Imprime el prompt, caso contrario,
* imprime '<'. */
if (section == 0)
{
grub_printf ("%s", prompt);
len -= plen;
pos += plen;
}
else
{
grub_putchar ('<');
len--;
pos++;
}
}
/* Calcula el índice al iniciar escribiendo BUF y el resultado lo
*coloca sobre la pantalla. */
if (section == 0)
{
int offset = 0;
174
if (! full)
offset = xpos - plen;
start = 0;
xpos = lpos + plen;
start += offset;
}
else
{
int offset = 0;
if (! full)
offset = xpos - 1;
start = ((section - 1) * (CMDLINE_WIDTH - 1 - CMDLINE_MARGIN)
+ CMDLINE_WIDTH - plen - CMDLINE_MARGIN);
xpos = lpos + 1 - start;
start += offset;
}
/* Imprime BUF. Si ECHO_CHAR no es cero, lo coloca en otro lugar */
for (i = start; i < start + len && i < llen; i++)
{
if (! echo_char)
grub_putchar (buf[i]);
else
grub_putchar (echo_char);
pos++;
}
/* Llena el resto de líneas con espacios. */
for (; i < start + len; i++)
{
grub_putchar (' ');
175
pos++;
}
/*S el cursor está en la última posición, coloca '>' o un espacio,
dependiendo de la cantidad de caracteres en BUF. */
if (pos == CMDLINE_WIDTH)
{
if (start + len < llen)
grub_putchar ('>');
else
grub_putchar (' ');
pos++;
}
/* Regresa a XPOS. */
if (current_term->flags & TERM_DUMB)
{
for (i = 0; i < pos - xpos; i++)
grub_putchar ('\b');
}
else
gotoxy (xpos, getxy () & 0xFF);
}
/* Inicializa la linea de comandos. */
void cl_init (void)
{
/* No distingue de otras líneas y mensajes de error */
grub_putchar ('\n');
/* Imprime todas las líneas y establece la posición aquí */
cl_refresh (1, 0);
176
}
/* Inserta STR a BUF. */
void cl_insert (const char *str)
{
int l = grub_strlen (str);
if (llen + l < maxlen)
{
if (lpos == llen)
grub_memmove (buf + lpos, str, l + 1);
else
{
grub_memmove (buf + lpos + l, buf + lpos, llen - lpos + 1);
grub_memmove (buf + lpos, str, l);
}
llen += l;
lpos += l;
if (xpos + l >= CMDLINE_WIDTH)
cl_refresh (1, 0);
else if (xpos + l + llen - lpos > CMDLINE_WIDTH)
cl_refresh (0, CMDLINE_WIDTH - xpos);
else
cl_refresh (0, l + llen - lpos);
}
}
/* Elimina COUNT caracteres en BUF. */
void cl_delete (int count)
{
grub_memmove (buf + lpos, buf + lpos + count, llen - count + 1);
llen -= count;
177
if (xpos + llen + count - lpos > CMDLINE_WIDTH)
cl_refresh (0, CMDLINE_WIDTH - xpos);
else
cl_refresh (0, llen + count - lpos);
}
plen = grub_strlen (prompt);
llen = grub_strlen (cmdline);
if (maxlen > MAX_CMDLINE)
{
maxlen = MAX_CMDLINE;
if (llen >= MAX_CMDLINE)
{
llen = MAX_CMDLINE - 1;
cmdline[MAX_CMDLINE] = 0;
}
}
lpos = llen;
grub_strcpy (buf, cmdline);
cl_init ();
while ((c = ASCII_CHAR (getkey ())) != '\n' && c != '\r')
{
/* Si READLINE es no cero, maneja readline como clave de enlace. */
if (readline)
{
switch (c)
{
case 9:
{
int i;
/* POS puntos del primer espacio después de un comando. */
178
int pos = 0;
int ret;
char *completion_buffer = (char *) COMPLETION_BUF;
int equal_pos = -1;
int is_filename;
/* Encuentra la primera palabra. */
while (buf[pos] == ' ')
pos++;
while (buf[pos] && buf[pos] != '=' && buf[pos] != ' ')
pos++;
is_filename = (lpos > pos);
/* Encuentra la posición del carácter '=' después de un
*comando, y reemplaza esta con un espacio. */
for (i = pos; buf[i] && buf[i] != ' '; i++)
if (buf[i] == '=')
{
equal_pos = i;
buf[i] = ' ';
break;
}
/* Encuentra la posición del primer carácter en esta
* palabra */
for (i = lpos; i > 0 && buf[i - 1] != ' '; i--) ;
/* Invalida la cache, a causa el usuario debe cambiar discos
*removibles */
buf_drive = -1;
/* Copia esta palabra a COMPLETION_BUFFER y la
* completa. */
179
grub_memmove (completion_buffer, buf + i, lpos - i);
completion_buffer[lpos - i] = 0;
ret = print_completions (is_filename, 1);
errnum = ERR_NONE;
if (ret >= 0)
{
/* Encuentra, para insertar COMPLETION_BUFFER. */
cl_insert (completion_buffer + lpos - i);
if (ret > 0)
{
/* Si hay más que un candidato, entonces imprime
* la lista. */
grub_putchar ('\n');
print_completions (is_filename, 0);
errnum = ERR_NONE;
}
}
/* Restaura la linea de comandos. */
if (equal_pos >= 0)
buf[equal_pos] = '=';
if (ret)
cl_init ();
}
break;
case 1:
/* C-a ir al principio de la linea */
cl_backward (lpos);
break;
case 5:
/* C-e ir al final de la linea */
cl_forward (llen - lpos);
180
break;
case 6:
/* C-f adelantar un carácter */
if (lpos < llen)
cl_forward (1);
break;
case 2:
/* C-b retroceder un caracter */
if (lpos > 0)
cl_backward (1);
break;
case 21:
/* C-u Limpiar el inicio de la linea */
if (lpos == 0)
break;
/* Copiar la cadena que se va a eliminar a KILL_BUF. */
grub_memmove (kill_buf, buf, lpos);
kill_buf[lpos] = 0;
{
int count = lpos;
cl_backward (lpos);
cl_delete (count);
}
break;
case 11:
/* C-k Limpiar el final de la linea */
if (lpos == llen)
break;
/* Copiar la cadena que se va a eliminar a KILL_BUF. */
grub_memmove (kill_buf, buf + lpos, llen - lpos + 1);
cl_delete (llen - lpos);
break;
case 25:
/* C-y Eliminar buffer */
cl_insert (kill_buf);
break;
case 16:
/* C-p buscar el comando anterior */
181
{
char *p;
if (history < 0)
/* Guarda el buffer trabajado. */
grub_strcpy (cmdline, buf);
else if (grub_strcmp (get_history (history), buf) != 0)
/* Si BUF es modificado, adicionar este dentro de la lista
* historia. */
add_history (buf, history);
history++;
p = get_history (history);
if (! p)
{
history--;
break;
}
grub_strcpy (buf, p);
llen = grub_strlen (buf);
lpos = llen;
cl_refresh (1, 0);
}
break;
case 14:
/* C-n buscar el comando anterior */
{
char *p;
if (history < 0)
{
break;
}
else if (grub_strcmp (get_history (history), buf) != 0)
/* Si BUF es modificado, adicionar este dentro de la lista
historia */
182
add_history (buf, history);
history--;
p = get_history (history);
if (! p)
p = cmdline;
grub_strcpy (buf, p);
llen = grub_strlen (buf);
lpos = llen;
cl_refresh (1, 0);
}
break;
}
}
/* ESC, C-d y C-h son siempre manejadores. Actualmente C-d no esta
* funcional si READLINE es cero, como el cursor no puede
* retroceder. */
switch (c)
{
case 27:
/* ESC inmediatamente retorna a 1 */
return 1;
case 4:
/* C-d Elimina carácter bajo cursor */
if (lpos == llen)
break;
cl_delete (1);
break;
case 8:
/* C-h Tecla espaceadora */
# ifdef GRUB_UTIL
case 127:
/* also Tecla espaceadora */
# endif
if (lpos > 0)
183
{
cl_backward (1);
cl_delete (1);
}
break;
default:
/* Inserta imprimibles caracteres dentro de la
linea */
if (c >= ' ' && c <= '~')
{
char str[2];
str[0] = c;
str[1] = 0;
cl_insert (str);
}
}
}
grub_putchar ('\n');
/* Si ECHO_CHAR es NUL, remueve los espacios primarios. */
lpos = 0;
if (! echo_char)
while (buf[lpos] == ' ')
lpos++;
/* Copia el buffer de trabajo a CMDLINE. */
*grub_memmove (cmdline, buf + lpos, llen - lpos + 1);
/* Si la readline como característica es encendida and CMDLINE no es
* vacío, adiciona este dentro de la lista de historia. */
if (readline && lpos < llen)
add_history (cmdline, 0);
184
return 0;
}
/* No usar esto con MAXLEN mayor que 1600 o superior. El problema
* es que GET_CMDLINE depende sobre el tamaño apropiado de la pantalla.
* Por lo tanto toda pantalla es de unos 2000 caracteres, menos el
* PROMPT, y espacio para errores y líneas de estatus, etc. MAXLEN debe ser
* al menos uno, y PROMPT y CMDLINE deben ser cadenas validas(not nulas
* or de cero longitud).
* Si ECHO_CHAR es no cero, echo está en lugar del carácter escrito. */
int
get_cmdline (char *prompt, char *cmdline, int maxlen,
int echo_char, int readline)
{
int old_cursor;
int ret;
old_cursor = setcursor (1);
/* Debido a que es difícil tratar con diferentes situaciones
* simultáneamente, casos menos funcionales se manejan aquí.
* Asumo que TERM_NO_ECHO
* implica TERM_NO_EDIT. */
if (current_term->flags & (TERM_NO_ECHO | TERM_NO_EDIT))
{
char *p = cmdline;
int c;
/* Aseguramos que MAXLEN no es muy largo. */
if (maxlen > MAX_CMDLINE)
maxlen = MAX_CMDLINE;
185
/* Imprimimos solo el prompt. El contenido de CMDLINE es simplemente
* descartado, dado si este no es vacío. */
grub_printf ("%s", prompt);
/* Reúne caracteres hasta que se incorpore una nueva linea. */
while ((c = ASCII_CHAR (getkey ())) != '\n' && c != '\r')
{
/* Retorna inmediatamente si ESC es presionada. */
if (c == 27)
{
setcursor (old_cursor);
return 1;
}
/* Imprimibles caracteres son adicionados dentro de CMDLINE. */
if (c >= ' ' && c <= '~')
{
if (! (current_term->flags & TERM_NO_ECHO))
grub_putchar (c);
/* Caracteres espacios precedentes deben ser ignorados. */
if (c != ' ' || p != cmdline)
*p++ = c;
}
}
*p = 0;
if (! (current_term->flags & TERM_NO_ECHO))
grub_putchar ('\n');
setcursor (old_cursor);
return 0;
}
186
/* Complicadas características se dejan a real_get_cmdline. */
ret = real_get_cmdline (prompt, cmdline, maxlen, echo_char, readline);
setcursor (old_cursor);
return ret;
}
int
safe_parse_maxint (char **str_ptr, int *myint_ptr)
{
char *ptr = *str_ptr;
int myint = 0;
int mult = 10, found = 0;
if (*ptr == '0' && tolower (*(ptr + 1)) == 'x')
{
ptr += 2;
mult = 16;
}
while (1)
{
/* Esta continuación hace uso de la equivalencia:
* (A >= B && A <= C) <=> ((A - B) <= (C - B))
* cuando C > B y A es sin signo. */
unsigned int digit;
digit = tolower (*ptr) - '0';
if (digit > 9)
{
digit -= 'a' - '0';
if (mult == 10 || digit > 5)
187
break;
digit += 10;
}
found = 1;
if (myint > ((MAXINT - digit) / mult))
{
errnum = ERR_NUMBER_OVERFLOW;
return 0;
}
myint = (myint * mult) + digit;
ptr++;
}
if (!found)
{
errnum = ERR_NUMBER_PARSING;
return 0;
}
*str_ptr = ptr;
*myint_ptr = myint;
return 1;
}
#endif /* STAGE1_5 */
#if !defined(STAGE1_5) || defined(FSYS_FAT)
int
grub_tolower (int c)
{
if (c >= 'A' && c <= 'Z')
188
return (c + ('a' - 'A'));
return c;
}
#endif /* ! STAGE1_5 || FSYS_FAT */
int
grub_isspace (int c)
{
switch (c)
{
case ' ':
case '\t':
case '\r':
case '\n':
return 1;
default:
break;
}
return 0;
}
#if !defined(STAGE1_5) || defined(FSYS_ISO9660)
int
grub_memcmp (const char *s1, const char *s2, int n)
{
while (n)
{
if (*s1 < *s2)
return -1;
else if (*s1 > *s2)
return 1;
s1++;
s2++;
n--;
189
}
return 0;
}
#endif /* ! STAGE1_5 || FSYS_ISO9660 */
#ifndef STAGE1_5
int
grub_strncat (char *s1, const char *s2, int n)
{
int i = -1;
while (++i < n && s1[i] != 0);
while (i < n && (s1[i++] = *(s2++)) != 0);
s1[n - 1] = 0;
if (i >= n)
return 0;
s1[i] = 0;
return 1;
}
#endif /* ! STAGE1_5 */
#if !defined(STAGE1_5) || defined(FSYS_VSTAFS)
int
grub_strcmp (const char *s1, const char *s2)
{
while (*s1 || *s2)
{
if (*s1 < *s2)
return -1;
else if (*s1 > *s2)
return 1;
s1 ++;
s2 ++;
}
190
return 0;
}
#endif /* ! STAGE1_5 || FSYS_VSTAFS */
#ifndef STAGE1_5
/* Espera a pulsar una tecla y retornar al código. */
int
getkey (void)
{
return current_term->getkey ();
}
/* Compruebe si el código clave está disponible. */
int
checkkey (void)
{
return current_term->checkkey ();
}
#endif /* ! STAGE1_5 */
/* Despliega un ASCII carácter. */
void
grub_putchar (int c)
{
if (c == '\n')
grub_putchar ('\r');
#ifndef STAGE1_5
else if (c == '\t' && current_term->getxy)
{
int n;
191
n = 8 - ((current_term->getxy () >> 8) & 3);
while (n--)
grub_putchar (' ');
return;
}
#endif /* ! STAGE1_5 */
#ifdef STAGE1_5
/* In Stage 1.5, solo el normal consola es soportado. */
console_putchar (c);
#else /* ! STAGE1_5 */
if (c == '\n')
{
/* Interno 'more' como caracteristica. */
if (count_lines >= 0)
{
count_lines++;
if (count_lines >= max_lines - 2)
{
int tmp;
/* Es importante desactivar las características temporalmente,
* a causa la siguiente llamada a grub_printf deberá imprimir
* nuevas lineas. */
count_lines = -1;
if (current_term->setcolorstate)
current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
grub_printf ("\n[Hit return to continue]");
192
if (current_term->setcolorstate)
current_term->setcolorstate (COLOR_STATE_NORMAL);
do
{
tmp = ASCII_CHAR (getkey ());
}
while (tmp != '\n' && tmp != '\r');
grub_printf ("\r
\r");
/* Reinicia el conteo de líneas. */
count_lines = 0;
return;
}
}
}
current_term->putchar (c);
#endif /* ! STAGE1_5 */
}
#ifndef STAGE1_5
void
gotoxy (int x, int y)
{
current_term->gotoxy (x, y);
}
int
getxy (void)
{
return current_term->getxy ();
}
193
void
cls (void)
{
/* Si el terminal esta inhibido, no hay manera de limpiar el terminal. */
if (current_term->flags & TERM_DUMB)
grub_putchar ('\n');
else
current_term->cls ();
}
int
setcursor (int on)
{
if (current_term->setcursor)
return current_term->setcursor (on);
return 1;
}
#endif /* ! STAGE1_5 */
int
substring (const char *s1, const char *s2)
{
while (*s1 == *s2)
{
/* Enlaza las cadenas exactamente. */
if (! *(s1++))
return 0;
s2 ++;
}
/* S1 es una subcadena de S2. */
194
if (*s1 == 0)
return -1;
/* S1 no es una subcadena. */
return 1;
}
#ifndef STAGE1_5
/* Termina la cadena STR con NUL. */
int
nul_terminate (char *str)
{
int ch;
while (*str && ! grub_isspace (*str))
str++;
ch = *str;
*str = 0;
return ch;
}
char *
grub_strstr (const char *s1, const char *s2)
{
while (*s1)
{
const char *ptr, *tmp;
ptr = s1;
tmp = s2;
while (*tmp && *ptr == *tmp)
ptr++, tmp++;
if (tmp > s2 && ! *tmp)
return (char *) s1;
195
s1++;
}
return 0;
}
int
grub_strlen (const char *str)
{
int len = 0;
while (*str++)
len++;
return len;
}
#endif /* ! STAGE1_5 */
int
memcheck (int addr, int len)
{
#ifdef GRUB_UTIL
auto int start_addr (void);
auto int end_addr (void);
auto int start_addr (void)
{
int ret;
# if defined(HAVE_START_SYMBOL)
asm volatile ("movl $start, %0" : "=a" (ret));
# elif defined(HAVE_USCORE_START_SYMBOL)
asm volatile ("movl $_start, %0" : "=a" (ret));
# endif
return ret;
}
196
auto int end_addr (void)
{
int ret;
# if defined(HAVE_END_SYMBOL)
asm volatile ("movl $end, %0" : "=a" (ret));
# elif defined(HAVE_USCORE_END_SYMBOL)
asm volatile ("movl $_end, %0" : "=a" (ret));
# endif
return ret;
}
if (start_addr () <= addr && end_addr () > addr + len)
return ! errnum;
#endif /* GRUB_UTIL */
if ((addr < RAW_ADDR (0x1000))
|| (addr < RAW_ADDR (0x100000)
&& RAW_ADDR (mbi.mem_lower * 1024) < (addr + len))
|| (addr >= RAW_ADDR (0x100000)
&& RAW_ADDR (mbi.mem_upper * 1024) < ((addr - 0x100000) + len)))
errnum = ERR_WONT_FIT;
return ! errnum;
}
void *
grub_memmove (void *to, const void *from, int len)
{
if (memcheck ((int) to, len))
{
int d0, d1, d2;
197
if (to < from)
{
asm volatile ("cld\n\t"
"rep\n\t"
"movsb"
: "=&c" (d0), "=&S" (d1), "=&D" (d2)
: "0" (len),"1" (from),"2" (to)
: "memory");
}
else
{
asm volatile ("std\n\t"
"rep\n\t"
"movsb\n\t"
"cld"
: "=&c" (d0), "=&S" (d1), "=&D" (d2)
: "0" (len),
"1" (len - 1 + (const char *) from),
"2" (len - 1 + (char *) to)
: "memory");
}
}
return errnum ? NULL : to;
}
void *
grub_memset (void *start, int c, int len)
{
char *p = start;
if (memcheck ((int) start, len))
198
{
while (len -- > 0)
*p ++ = c;
}
return errnum ? NULL : start;
}
#ifndef STAGE1_5
char *
grub_strcpy (char *dest, const char *src)
{
grub_memmove (dest, src, grub_strlen (src) + 1);
return dest;
}
#endif /* ! STAGE1_5 */
#ifndef GRUB_UTIL
# undef memcpy
/* GCC emite referencias a memcpy() para estructurar copias etc. */
void *memcpy (void *dest, const void *src, int n) __attribute__ ((alias ("grub_memmove")));
#endif
Archivo char_io.c
3.6.4 Presentación Del funcionamiento De Grub Legacy Modificado.
En las siguientes imágenes se presenta el funcionamiento del gestor de
arranque Grub Legacy Modificado. Una vez que Grub Legacy Modificado ha
sido inyectado en un dispositivo de almacenamiento (CD, USB, Disco Duro etc).
199
3.6.4.1 Pantalla Inicial Grub Legacy Modificado
La siguiente pantalla se muestra al iniciar Grub Legacy Modificado.
Figura 49. Inico Grub Legacy Modificado.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
3.6.4.2 Grub Legacy Modificado Chainloader
En la siguiente pantalla muestra los comandos necesarios para iniciar un
sistema operativo que no sea de distribución GNU/Linux.
Figura 50. Inico Grub Legacy Chainloader.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
200
Nota: Grub Legacy Modificado acepta los mismos comandos que Grub Legacy
ya que es un clon.
3.7 Desarrollo de MUCE (MBR de la Universidad Central del Ecuador)
Muce es un Master Boot Record para computadores compatibles x86 que
inician en modo real, MUCE es construido en el estudio, investigación y
desarrollo del presente tema de tesis.
El código de MUCE es de licencia GNU GPL, y está bajo los derechos de
código de temas de tesis de la Universidad Central del Ecuador.
En el código de MUCE se encuentra disponible a la comunidad en la página
web: www.softwaredesarrollo.com, y en el presente documento de tema de
tesis.
3.7.1 Código de MUCE
Archivo Código de MUCE
/*
* SISTEMA : MUCE (MBR Universidad Central del Ecuador)
* MODULO : UNIVERSIDAD CENTRAL DEL ECUADOR
* PROCESO : Etapa 1 MUCE
* DESCRIPCIÓN : Master Boot record en lenguaje ensamblador que permite
* arrancar desde un dispositivo de almacenamiento, y su función es
* copiar los primeros 512 bytes a otra parte de la memoria para cargar
* el sector de arranque del disco duro a memoria y cederle el
* procesamiento.
* ANALISTAS : Ing. Mauro Rosas, Ing. Jairo Navarro, Ing. Jorge Morales
* PROGRAMADOR : FIGUEROA CAÑAR VICTOR BOLÍVAR
* FECHA CREACIÓN, MODIFICACIÓN: 05 de Abril del 2015
* LICENCIA: GNU GPL versión 2 o mayor.
201
*/
.code16
.section .text
.globl _start
_start:
movw $512, %cx /*Establece cx=512 para mover 512 bytes de
*memoria*/
movw $0x7c00, %bx/*Establece el inicio de dirección de memoria
*de donde se comenzara a copiar los datos*/
/* El siguiente código copia los datos de la posición asignada a bx a un
* desplazamiento de 512 bytes*/
cMem:
movb (%bx), %ah
movb %ah,0x0200(%bx)
addw $0x0001,%bx
loop cMem
jmp ini+512/*Salta de la posición del segmento 0:7c00 a la
*posición del segmento 0:7e00, como el código fue
*movido a esta posición continua ejecutando el
*mismo código pero en otra posición de memoria.*/
ini:
movw $hello,%si
call PrintString
movb $0x02,%ah
xorb %bh,%bh
202
movw $0x0100,%dx
int $0x10
movw $prog,%si
call PrintString
movb $0x02,%ah
xorb %bh,%bh
movw $0x0200,%dx
int $0x10
movw $muce,%si
call PrintString
movb $0x02,%ah
xorb %bh,%bh
movw $0x0400,%dx
int $0x10
movw $press,%si
call PrintString
xorb %ah,%ah
int $0x16
readSector:
xorw %ax,%ax
movw %ax, %es
movb $0x02, %ah
movb $0x01, %al
movw $0x7C00,%bx
xorb %ch,%ch
movb $0x01,%cl
movw $0x0080,%dx
int $0x13
jc Error
203
movw $0x7C00,%bx
movw (%bx),%ax
call ImpHex
jmp loop
Error:
call ImpHex
jmp loop
ImpHex:
movw %ax, area
movb $0x0C,%cl
shrax:
movw area,%ax
shrw %cl,%ax
andb $0x0F, %al
cmpb $0x0A, %al
jc IsNumber
addb $0x37,%al
call int10
jmp shraxbucle
IsNumber:
addb $0x30,%al
call int10
shraxbucle:
subb $0x04,%cl
jnc shrax
ret
/*Inicio de proceso que imprime caracteres con la int 10h*/
PrintString:
lodsb
204
cmpb $0x00, %al
jnz Continue
ret
Continue:
call int10
jmp PrintString
int10:
movb $0x0E,%ah
int $0x10
ret
/*Fin de Proceso de impresion*/
loop:
cli
xorw %ax,%ax
movw %ax,%ds
movw %ax,%es
movw %ax,%ss
sti
jmp (0x7c00-512)
jmp loop
/*Mensajes de Impresion en la pantalla*/
hello: .string "AUTOR: UNIVERSIDAD CENTRAL DEL ECUADOR"
prog: .string "PROGRAMADOR: Victor Figueroa"
muce: .string "MBR MUCE"
press: .string "Presione una tecla para iniciar desde el disco duro"
area: .space, 100
.org 510
.byte 0x55
.byte 0xAA/*Firma del código MBR*/
Archivo Código de MUCE
205
CAPITULO 4
4.1 Pruebas
4.1.1 Presentación Funcionamiento MUCE
En las siguientes capturas de pantalla se presenta el funcionamiento de MUCE.
En general es un gestor de arranque básico, que una vez iniciado solicita el
ingreso de un enter para cargar el MBR del disco duro.
4.1.1.1 Pantalla Inicial MUCE
Figura 51. Inicio MUCE.
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
206
4.1.1.2 Pantalla Inicio Windows Xp
Al dar enter iniciara el sistema operativo en este caso Windows xp.
Figura 52. MUCE Iniciando XP
Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
4.2 Conclusiones



Con el desarrollo de los temas de tesis se puede concluir que una vez
comprendido todo el funcionamiento interno de la computadora, el
funcionamiento de los gestores de arranque todos tienen básicamente
los mismos métodos de operación, por lo que una vez entendido y
modificado un gestor de arranque se puede construir un clon o uno
propio.
Se concluye también que el acceso al disco duro a través de su tabla de
particiones es un riesgo de seguridad de datos y un mecanismo de
recuperación de datos, dependiendo de cómo se desee utilizar este
mecanismo.
La principal conclusión es que si se pudo investigar y modificar un gestor
de arranque y algunos desarrolladores de gestores de arranque como
grub opinan que es grub tiene la misma o mayor complejidad que el
kernel de los sistema GNU/Linux, se puede desarrollar un sistema
operativo.
207
4.3 Recomendaciones




La importancia de generar un gestor de arranque y darle soporte por
parte de una unidad educativa como la Universidad Central del Ecuador
dotara de independencia en cuanto al software ya que este el inicio de
todo desarrollo de software.
Se debe estudiar tanto el código libre como el código propietario para
encontrar similitudes y ventajas de un sistema respecto de otro. Así se
pueden tomar mejores decisiones al momento de generar clones de
sistema operativos.
Se recomienda que todo software desarrollado este bajo licencia GPL, ya
que esta da libertades a otros usuarios de estudiar, modificar y ejecutar
el código como más crean conveniente.
Por último se puede recomendar que si se tiene el ejecutable de un
código se puede ejecutar herramientas de ingeniería inversa para ver
cómo está estructurado el código, la lógica de su programación y con
esto podemos realizar clones del software estudiado.
208
BIBLIOGRAFIA
1. WEB: Lenguaje Ensamblador:
http://es.wikipedia.org/wiki/Lenguaje_ensamblador
2. Libro: Lenguaje C:
KERNIGHAN, Brian Wilson & RITCHIE, Dennis Macalistair. (2008). El
Lenguaje De Programación C.
3. WEB: Gestor de arranque:
http://www.linuxeslibre.com.ar/tutos_pre_liloygrub.html
http://www.codeproject.com/Articles/668422/Writing-a-boot-loader-inAssembly-and-C-Part.
http://www.codeproject.com/Articles/664165/Writing-a-boot-loader-inAssembly-and-C-Part
http://thestarman.pcministry.com/asm/mbr/GRUB.htm
https://elendill.wordpress.com/tag/mbr/
http://www.zator.com/Hardware/H8_1_2c.htm
4. Libro: Lenguaje Ensamblador, Nasm, Masm:
CHARTE OJEDA, Francisco. (2009). Lenguaje ensamblador.
5. WEB: GRUB LEGACY
http://gnu.ist.utl.pt/software/grub/grub-legacy-devel.en.html
209
Descargar