universidad central del ecuador facultad de … · durante el desarrollo del tema de tesis, a los...
TRANSCRIPT
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
II
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
III
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
IV
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 realizada sobre ESTUDIO, DESARROLLO E
IMPLEMENTACIÓN DE UN GESTOR DE ARRANQUE 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
V
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
VI
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
VII
RESULTADO DEL TRABAJO DE GRADUACION
VIII
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
IX
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
X
2.3.10.2 Ensambladores ...................................................................... 55
2.3.10.3 Enlazadores ........................................................................... 56
2.3.10.4 GCC ....................................................................................... 57
2.4 Investigación Experimental ................................................................ 58
2.5 Plan de Recolección de Información ................................................... 58
2.6 Plan de Procesamiento de Información ............................................... 59
2.7 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
XI
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
XII
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
XIII
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
XIV
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
XV
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.
XVI
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.
XVII
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.
XVIII
TÍTULO DEL TRADUCTOR
1
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.
2
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
3
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.
4
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.
5
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.
6
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.
7
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.
8
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.
9
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
10
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.
11
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.
12
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.
13
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.
14
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.
15
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.
16
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 Bits Pins Clock Caracteristicas
4004 1971 Intel 4 16-dip .1MHz Primer Microprocesador
8086 1978
AMD, Harris, Mostek, Fujitsu, NEC, Toshiba, OKI, Siemens
16 40 5-10MHz
Primer 16-bit CPU; 8088 (1979); IBM PC (1981)
80286 1982 AMD, Harris, IBM, Siemens
16 68-LCC/PGA
6 MHZ-20MHz
Soporta Memoria Virtual; IBM PC AT (1984)
80386 1985 Intel 32 132-PGA 16-33MHz
Primer 32-bit CPU; Cache; Multitarea
17
Microprocesador Año Fabricante Bits Pins Clock Caracteristicas
80486 1989 Intel 32 16PGA,176TQFP 100MHz Cache nivel L1
Pentium 1993 Intel 32 273PGA,320TCP 60MH-233Mhz
Superscalar: 2-IU, 1-FPU; MMX (1995)
Pentium II 1997 Intel 32 528-LGA, 615-BGA
233MH-500Mhz
RISC 2-IU,2-FPU,3-LDST, 2-MMX; Xeon, Celeron
Pentium III 1999 Intel 32 370-PGA2, 495-BGA2
400M-1Ghz
2-IU,2-FPU,3-LDST, 2-MMX, 2-SSE; Mobile (M)
Pentium 4 2000 Intel 32 423-PGA, 478-PGA
1.5-2Ghz
HT (2002); 4M (2003); Xeon MP (2003); Centrino (2003)
Multi Core 2006 Intel 64 479-775 1-3Ghz
D (2005); Core 2 (2006); Dual Core (2006); Quad Core (2007)
i3,i5,i7 2008 INTEL 64 437-1366 1.6 -3.5Ghz
i7-920 (2008): 4 cores; i7-980 (2011): 6 cores
Athlon Sempron64
2011 AMD 64 939 2800+ hasta 3600
Athlon Sempron64 con socket AM2
Athlon 64 2011 AMD 64 939 3000+ hasta 3800
Athlon 64 con Socket 939, Nucleos Venice y Manchester
Athlon 64 con Socket AM2
2011 AMD 64 939 3200+ y 3800
Athlon 64 con Socket AM2.
Athlon 64 X2 2011 AMD 64 939 3800+hasta 4800
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.
18
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.
19
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 Número y tamaño Descripción
De propósito general 4 registros de 16 bits Almacenan datos. Para uso del programador
De segmento 4 registros de 16 bits Permiten direccionar la memoria
Apuntador de instrucción 1 registro de 32 bits Apunta a la siguiente instrucción a ejecutar
Apuntadores 4 registros de 16 bits 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 Descripción
ax Acumulador para operaciones aritmético lógicas
bx Registro base para acceder a memoria
cx Contador para algunas instrucciones
dx 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 Descripción
cs Segmento de código
ds Segmento de datos
ss Segmento de pila
es segmento extra
fs segmento extra
Tabla 4. Uso común de los registros de segmento. Autor: Tesista.
Fuente: Conocimientos adquiridos del tesista.
20
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 Descripción
ip Apuntador de instrucción o contador de programa
di Apuntador a destino para operaciones con cadenas de caracteres
si Apuntador a origen para operaciones con cadenas de caracteres
sp Apuntador de pila
bp 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.
21
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 Bit Descripción
CF 0 Bandera de acarreo (carry flag)
PF 2 Bandera de paridad (parity flag)
AF 4 Bandera de acarreo auxiliar (adjust flag)
ZF 6 Bandera de cero (zero flag)
SF 7 Bandera de signo (sign flag)
TF 8 Bandera de depuración(trap flag)
IF 9 Bandera de Interrupcion(interruption flag)
DF 10 Bandera de dirección (direction flag)
OF 11 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.
22
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.
23
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.
24
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-2gb-
ddr3-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
25
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 Propósito Borrado Modo de Escritura
Volatilidad
Random Access Memory (RAM)
Memoria Lec/Esc Eléctrico a nivel byte
Eléctricamente Volátil
Read Only Memory (ROM) Memoria de solo
Lectura No Posible
Máscaras
No Volátil
Programmable ROM (PROM)
Eléctricamente
Erasable PROM (EPROM)
Memoria sobre todo de Lectura
Luz UV a nivel chip
Memoria Flash Eléctrico a nivel bloque
Electrically Erasable PROM (EEPROM)
Eléctrico a nivel byte
Tabla 7. Tipos de Memoria. Autor: Tesista.
Fuente: Conocimientos adquiridos del tesista.
26
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-computadoras-
memoria/arquitectura-computadoras-memoria.shtml.
27
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.
28
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
29
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.
30
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‟.
31
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.
32
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.
33
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]
34
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.
35
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.
36
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.
37
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
38
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
39
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.
40
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)
Valor máximo teórico 2n
Rango permitido
Total utilizable
Cilindro 10 1,024 0-1,023 1,024
Cabeza 8 256 0-255 256
Sector 6 64 1-63 63 Tabla 8. Direccionamiento CHS.
Autor: Tesista. Fuente: http://www.zator.com/Hardware/H6_2.htm
41
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)
Valor máximo teórico
Rango permitido
Total utilizable
Cilindro 16 65,536 0-65,535 65,536
Cabeza 4 16 0-15 16
Sector 8 256 1-255 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.
42
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.
43
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).
44
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.
45
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:
0 1 2 3 4 5 6 7 8 9 A B C D E F
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.
46
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.
Nombre Nemónico Tamaño(bits)
Byte 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.
47
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.
48
Offset Tamaño Descripción
00h- 06h WORD Dirección E/S base del primer-cuarto puerto serie (0 si no instalado)
08h- 0Eh WORD Dirección E/S base del primer-tercer puerto paralelo (0 si no instalado)
10h 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.
49
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.
50
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.
51
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.
52
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 Tipo de datos Sufijo de gas Tamaño (en bytes)
Char byte b 1
Short palabra w 2
Int doble palabra l 4
Unsigned doble palabra l 4
long int doble palabra l 4
unsigned long doble palabra l 4
char * doble palabra l 4
Float precisión simple s 4
Doublé precisión doble l 8
long doublé precisión extendida t 12 Tabla 12. Tipos de Datos de Programación C.
Autor: Tesista. Fuente: Conocimientos adquiridos tesista.
53
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.
54
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.
55
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.
56
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.
57
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.
58
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.
59
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.
60
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.
61
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.
62
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.
Figura 18. Flujo General de Inicio de la Pc. Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
Encendido
PC
Post(Power
On Selft)
Cargar y ejecutar
programa
arrancable.
63
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 Segunda Etapa Tercera Etapa
Tamaño en Bytes 512 variable variable
Función
Cargar a memoria y
ejecutar segunda
etapa
Cargar a memoria
y ejecutar tercera
etapa
Cargar a memoria y
ejecutar Sistema
Operativo
Tabla 13. Etapas del Gestor de Arranque. Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
64
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
65
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.
66
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 Descripción
0x0000 Sección código
0x013C Sección de errores
0x01B4 Sección definida por Windows
0x01BC 2 bytes; normalmente 0x0000
0x01BE Tabla de particiones del disco duro.
0x01FE 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.
67
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.
68
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
69
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.
70
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).
71
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.
72
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.
73
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 Hexadecimal Instrucción Ensamblador(GAS) Comentario
0x7C00 33c0 xor %ax,%ax /*Establece ax=0*/
0x7C02 8ed0 mov %ax,%ss /*Establece ss=0*/
0x7C04 bc007c mov $0x7c00,%sp /*Establece sp=0x7C00*/
0x7C07 fb Sti /*Activa Interrupciones*/
0x7C08 50 push %ax /*Apila el valor 0 (ax=0)*/
0x7C09 7 pop %es /*Des apila valor 0 y establece es=0*/
0x7C0a 50 push %ax /*Apila el valor 0 (ax=0)*/
0x7C0b 1f pop %ds /*des apila valor 0 y establece ds=0*/
0x7C0c fc Cld /*Limpia flag de dirección*/
0x7C0d be1b7c mov $0x7c1b,%si /*Establece SI=0x7c1b 0x7c1b Es la dirección de memoria que se copiara a otra dirección.*/
74
Memoria Hexadecimal Instrucción Ensamblador(GAS) Comentario
0x7C10 bf1b06 mov $0x61b,%di
/*Establece DI=0x61b 0x61b Es la dirección de memoria donde se almacenara el código que se copió anteriormente */
0x7C13 50 push %ax /*Apila el valor 0 (ax=0)*/
0x7C14 57 push %di /*Apila el valor 0x61b (di=0x61b)*/
0x7C15 b9e501 mov $0x1e5,%cx /*Establece cx=0x1e5 485 en hexadecimal
0x7C18 f3a4 rep movsb %ds:(%si),%es:(%di) /*Instrucción que copiara cx bytes de la dirección de si a di */
0x7C1a cb Lret /*Instrucción que establecerá el valor de cs e ip con los valores de la apilados así: CS=0 IP=0x0x61b*/
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 Instrucción Ensamblador(GAS) Comentario
0x061b bdbe07 mov $0x7be,%bp /*Establece bp=0x7be Ubicación de la primera entrada en la tabla de particiones*/
0x061e b104 mov $0x4,%cl /*Estable cl=4 Máximo 4 entradas. Numero de particiones primarias*/
0x0620 386 cmp %ch,0x0(%bp) /*Compara el primer byte de la partición primaria con el valor de ch que es 0 para verificar si encuentra activa.*/
75
Memoria Hexadecimal Instrucción Ensamblador(GAS) Comentario
0x0623 7c09 jl 0x0000062e
/*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*/
0x0625 7513 jne 0x0000063a
/*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*/
0x0627 83c510 add $0x10,%bp
/*Adiciona 16 bytes al valor de bp para verificar si la siguiente partición primaria esta activa.*/
0x062a e2f4 loop 0x00000620
/*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*/
0x062c cd18 int $0x18
/*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.
76
3.4.2. 3. Tercera Parte Del Código
Memoria Hexadecimal Instrucción Ensamblador(GAS) Comentario
0x062e 8bf5 mov %bp,%si /*Establece el valor de si con la dirección del primer byte de la primera partición activa encontrada.*/
0x0630 83c610 add $0x10,%si /*Adiciona 16 bytes al valor de la dirección que contiene si.*/
0x0633 49 dec %cx /*Decrementa el valor de cx para verificar si existen registros de particiones*/
0x0634 7419 je 0x0000064f /*Comprueba cuando cx llega a cero es decir ya no existen registros de particiones por comprobar y salta a la dirección 0:064f*/
0x0636 382c cmp %ch,(%si) /*Comprueba que el primer byte de las particiones que le siguen a la partición primaria activa con el valor de cx=0*/
0x0638 74f6 je 0x00000630 /*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.
77
3.4.2. 4. Cuarta Parte Del Código
Memoria Hexadecimal Instrucción Ensamblador(GAS) Comentario
0x063a a0b507 mov 0x7b5,%al /*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.*/
0x063d b407 mov $0x7,%ah /*Establece el valor de ah=0x07 */
0x063f 8bf0 mov %ax,%si Establece el valor de si con el de ax en este caso si = 0x72C
0x0641 ac lods %ds:(%si),%al /*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*/
0x0642 3c00 cmp $0x0,%al /*Compara el valor de al con 0 para verificar que ellos caracteres del mensaje de error se acabaron*/
0x0644 74fc je 0x00000642 /*Al acabar de imprimir el mensaje de error ejecuta un bucle infinito saltando a la dirección 0:0642*/
0x0646 bb0700 mov $0x7,%bx /*Establece el modo de texto y modo grafico*/
0x0649 b40e mov $0xe,%ah /*Estable la función de la int 10h*/
0x064b cd10 int $0x10 /*Ejecuta la interrupción de BIOS 10h*/
0x064d ebf2 jmp 0x00000641 /*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.
78
3.4.2. 5. Quinta Parte Del Código.
Memoria Hexadecimal Instrucción Ensamblador(GAS) Comentario
0x064f 884e10 mov %cl,0x10(%bp)
/*Establece el valor de cl a la dirección que almacena bp +16 bytes. En este caso cero.*/
0x0652 e84600 call 0x0000069b
/*Llama a la función almacenada en memoria que comienza en la posición 0x069b*/
0x0655 732a jae 0x00000681 /*Salta a la dirección 0:0681 si cf esta desactivada*/
0x0657 fe4610 incb 0x10(%bp) /*Incrementa en byte de (bp+16) en esta caso 1*/
0x065a 807e040b cmpb $0xb,0x4(%bp) /*Verifica el sistema de archivos de la partición con 0xb partición fat32*/
0x065e 740b je 0x0000066b /*Si la tabla de particiones es fat32 salta a la dirección 0:066b*/
0x0660 807e040c cmpb $0xc,0x4(%bp)
/*Verifica el sistema de archivos de la partición con 0xc partición fat32 lba*/
0x0664 7405 je 0x0000066b
/*Si la tabla de particiones es fat32 lba salta a la dirección 0:066b*/
0x0666 a0b607 mov 0x7b6,%al /*Establece el valor de 0x7b6 a al*/
0x0669 75d2 jne 0x0000063d /*Salta a la dirección 0:063d. Para imprimir mensaje de error*/
0x066b 80460206 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*/
0x066f 83460806 addw $0x6,0x8(%bp)
/*Adiciona el valor de 6 al registro de partición del número de sectores en caso de soportar lba*/
79
Memoria Hexadecimal Instrucción Ensamblador(GAS) Comentario
0x0673 83560a00 adcw $0x0,0xa(%bp) /*Realiza la suma de cero +la dirección (bp+11). No hace nada */
0x0677 e82100 call 0x0000069b /*Llama a la función 069b para leer el sector de la primera partición*/
0x067a 7305 jae 0x00000681 /*Si la lectura tuvo éxito salta a la dirección 0681*/
0x067c a0b607 mov 0x7b6,%al /*Si la lectura no tuvo éxito establece al=0x7b6*/
0x067f ebbc jmp 0x0000063d /*Salta a la dirección 0:063d para imprimir mensaje de error*/
0x0681 813efe7d55aa cmpw $0xaa55,0x7dfe
/*Compara el valor 0x55AA con el valor de la dirección 0x7DFE, el valor de la dirección 0:07dfe es 0x55AA la firma*/
0x0687 740b je 0x00000694 /*Si la comparación anterior son iguales salta a la dirección 0x0694*/
0x0689 807e1000 cmpb $0x0,0x10(%bp)
/*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*/
0x068d 74c8 je 0x00000657
/*Al ser (bp+16) cero se da otra oportunidad de lectura. Salta a la dirección 0:0657*/
0x068f a0b707 mov 0x7b7,%al /*Establece el valor 0:07b7 en al*/
0x0692 eba9 jmp 0x0000603d /*Salta a la dirección 0:0603d para imprimir mensaje de error.*/
0x0694 8bfc mov %sp,%di /*Establece el valor de sp a di. Ahora di tiene 0x7C00*/
0x0696 1e push %ds /*Apila ds, Apila 0*/
0x0697 57 push %di /*Apila di, apila 0x07c00*/
0x0698 8bf5 mov %bp,%si /*Establece bp a si*/
80
Memoria Hexadecimal Instrucción Ensamblador(GAS) Comentario
0x069a cb lret
/*Salta a la dirección apilada. 0:07C00. Ejecuta el primer sector de la partición primaria en este caso el VBR*/
0x069b bf0500 mov $0x5,%di /*Establece el valor de DI=5*/
0x069e 8a5600 mov 0x0(%bp),%dl
/*Establece el valor de la dirección almacenada en bp a dl, en esta caso dl=0x80*/
0x06a1 b408 mov $0x8,%ah
/*Establece le valor ah=0x8, Establece la función 8 de la interrupción 13h*/
0x06a3 cd13 int $0x13
/*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.*/
0x06a5 7223 jb 0x000006ca
/*Si la lectura de los parámetros del de la interrupción 13h dio error salta a la dirección 0:06ca*/
0x06a7 8ac1 mov %cl,%al /*Establece el valor de cl a al. Al sectores por pista*/
0x06a9 243f and $0x3f,%al
/*Realiza un and 00111111 y al, ya que el número de sectores esta en los primeros 6 bits.*/
0x06ab 98 cbtw /*Establece el valor de al en ax.*/
0x06ac 8ade mov %dh,%bl
/*Establece el valor de dh en bl, bl contiene ahora el número de cabeceras del disco.*/
81
Memoria Hexadecimal Instrucción Ensamblador(GAS) Comentario
0x06ae 8afc mov %ah,%bh /*Establece el valor de ah a bh. En cualquier caso 0*/
0x06b0 43 inc %bx
/*Incrementa el valor de bx, bx contiene el número de cabeceras del disco.*/
0x06b1 f7e3 mul %bx
/*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.*/
0x06b3 8bd1 mov %cx,%dx
/*Establece el valor de cx a dx. Dx contiene el número de sectores por pista y el número de cilindros*/
0x06b5 86d6 xchg %dl,%dh /*Realiza un intercambio de datos entre dh, dl*/
0x06b7 b106 mov $0x6,%cl /*Establece el valor de 6 a cl*/
0x06b9 d2ee shr %cl,%dh
/*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*/
0x06bb 42 inc %dx /*Incrementa el valor de dx*/
0x06bc f7e2 mul %dx
/*Realiza la multiplicación de dx por ax, El número de cilindros por el número de cabeceras y sectores por pista.*/
0x06be 39560a cmp %dx,0xa(%bp)
/*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*/
0x06c1 7723 ja 0x000006e6
/*Si la comparación de (bp+10) es mayor que dx salta a la dirección 6e6, La BIOS admite int13h extendida */
82
Memoria Hexadecimal Instrucción Ensamblador(GAS) Comentario
0x06c3 7205 jb 0x000006ca /*Si la comparación de (bp+10) es menor que dx salta a la dirección 6ca*/
0x06c5 394608 cmp %ax,0x8(%bp) /*Dada la comparación anterior fue igual compara (bp+8) con ax*/
0x06c8 731c jae 0x000006e6
/*Si (bp+8) es mayor o igual que ax salta a la dirección 0:06e6. La BIOS admite la int 13h extendida*/
0x06ca b80102 mov $0x201,%ax
/*Establece el valor ah=02, al=01, Parámetros de la interrupción 13h, función=02 y lectura de 01 sector.*/
0x06cd bb007c mov $0x7c00,%bx
/*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.*/
0x06d0 8b4e02 mov 0x2(%bp),%cx
/*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.*/
0x06d3 8b5600 mov 0x0(%bp),%dx
/*Establece el Controlador del registro de partición a dx. En el caso disco duro 80*/
0x06d6 cd13 int $0x13
/*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*/
0x06d8 7351 jae 0x0000072b
/*Salta a la posición de memoria 0:072b si la lectura del disco tuvo éxito cf desactivada. Y retorna*/
83
Memoria Hexadecimal Instrucción Ensamblador(GAS) Comentario
0x06da 4f dec %di /*La lectura del disco no tuvo éxito. Dec di*/
0x06db 744e je 0x0000072b
/*Comprueba que di haya llegado a cero y de ser así salta a la dirección 0:072b y retorna*/
0x06dd 320000 xor %ah,%ah /*Establece ah=0*/
0x06df 8a5600 mov 0x0(%bp),%dl
/*Establece el valor al que apunta bp a dl. En este caso dl contiene el controlador del disco 80*/
0x06e2 cd13 int $0x13 /*Realiza la int 13 h función cero. Resetea el disco*/
0x06e4 ebe4 jmp 0x000006ca /*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.
84
3.4.2. 6. Sexta Parte Del Código
Memoria Hexadecimal Instrucción Ensamblador(GAS) Comentario
0x06e6 8a5600 mov 0x0(%bp),%dl /*Establece el valor de (bp) a dl, en este caso 0x80 el controlador del driver*/
0x06e9 60 pusha /*Apila ax*/
0x06ea bbaa55 mov $0x55aa,%bx /*Establece el valor de 0x55aa en bx. Parámetros de la función extendida 13h*/
0x06ed b441 mov $0x41,%ah /*Establece el valor de 41 en ah. Parámetros de la función extendida 13h*/
0x06ef cd13 int $0x13
/*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)*/
0x06f1 7236 jb 0x000007029 /*Salta a la dirección 0:0729 3n caso de error de lectura.*/
0x06f3 81fb55aa cmp $0xaa55,%bx
/*Compara el valor aa55 con el valor de bx para ver si están instaladas la extensiones de la int13h*/
0x06f7 7530 jne 0x000007029 /*Si la comparación anterior no son iguales salta a la posición 0:0729, Indica error en la lectura*/
0x06f9 f6c101 test $0x1,%cl /*Realiza una comparación ente 0001 y el valor de cl.*/
0x06fc 742b je 0x000007029
/*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*/
0x06fe 61 Popa /*Des apila ax*/
0x06ff 60 pusha /*Apila ax*/
85
Memoria Hexadecimal Instrucción Ensamblador(GAS) Comentario
0x7000 6a00 push $0x0 /*Apila cero*/
0x7002 6a00 push $0x0 /*Apila cero*/
0x7004 ff760a pushw 0xa(%bp)
/*Apila el valor de (bp+10) primera parte del valor del sector en que inicia la partición primaria que soporta lba*/
0x7007 ff7608 pushw 0x8(%bp)
/*Apila el valor de (bp+10) segunda parte del valor del sector 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*/
0x700f 6a01 push $0x1 /*Apila el numero 1: Numero de sectores a leer*/
0x7011 6a10 push $0x10 /*Apila el número 16, tamaño del DAP. Disk Address Packet*/
0x7013 b442 mov $0x42,%ah /*Establece el 0x42 en ah. */
0x7015 8bf4 mov %sp,%si /*Establece el valor de sp a sí. Ahora si 0x7c00*/
0x7017 cd13 int $0x13
/*Ejecuta la int 13 con función 42h, Lee el primer sector de la partición primaria y lo almacena en la dirección 0:07c00*/
0x701a 61 Popa /*Des apila y su valor lo pone en ax*/
0x701b 730e jae 0x00000702b /*Si la lectura tuvo éxito salta a la posición 0:0720b*/
0x701d 4f dec %di /*La lectura no tuvo éxito y decrementa di*/
0x701e 740b je 0x00000702b /*Si di =0 retorna con error ya que se activa cf*/
0x7020 320000 xor %ah, %ah /*Establece ah=0*/
0x7022 8a5600 mov 0x0(%bp),%dl /*Establece el valor de bp a dl, en 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 /*Activa la bandera de acarreo para indicar error de lectura*/
0x702b c3 Ret /*Termina y retorna*/ Tabla 21. NTLDR código fuente documentado parte 6.
Autor: Tesista. Fuente: Desarrollo de tema de tesis.
86
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.
87
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:
88
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). Chain-
loading 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
89
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.
90
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.
91
(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.
92
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.
93
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 CD-
ROM 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 iso/boo/grub
94
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)
95
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.
96
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.
97
Carga Directa
Grub Utiliza el Multiboot especification.
GRUB puede arrancar cualquier sistema operativo de arranque múltiple-
compatible 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
98
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:
99
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.
100
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,
101
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
102
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.
103
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.
104
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.
105
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.
106
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.
107
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.
108
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.
109
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.
110
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 Hexadecimal Ensamblador
.data:0x00007C00 eb48 jmp 0x00007c4a
.data:0x00007C02 90 nop
.data:0x00007C4a fa cli
.data:0x00007C4b eb07 jmp 0x00007c54
.data:0x00007C4d f6c280 test $0x80,%dl
.data:0x00007C50 7502 jne 0x00007c54
.data:0x00007C52 b280 mov $0x80,%dl
.data:0x00007C54 ea597c0000 ljmp $0x0,$0x7c59
.data:0x00007C59 31c0 xor %ax,%ax
.data:0x00007C5b 8ed8 mov %ax,%ds
111
Dirección Hexadecimal Ensamblador
.data:0x00007C5d 8ed0 mov %ax,%ss
.data:0x00007C5f bc0020 mov $0x2000,%sp
.data:0x00007C62 fb sti
.data:0x00007C63 a0407c mov 0x7c40,%al
.data:0x00007C66 3cff cmp $0xff,%al
.data:0x00007C68 7402 je 0x00007c6c
.data:0x00007C6a 88c2 mov %al,%dl
.data:0x00007C6c 52 push %dx
.data:0x00007C6d be7f7d mov $0x7d7f,%si
.data:0x00007C70 e83401 call 0x000001a7
.data:0x00007C73 f6c280 test $0x80,%dl
.data:0x00007C76 7454 je 0x00007ccc
.data:0x00007C78 b441 mov $0x41,%ah
.data:0x00007C7a bbaa55 mov $0x55aa,%bx
.data:0x00007C7d cd13 int $0x13
.data:0x00007C7f 5a pop %dx
.data:0x00007C80 52 push %dx
.data:0x00007C81 7249 jb 0x00007ccc
.data:0x00007C83 81fb55aa cmp $0xaa55,%bx
.data:0x00007C87 7543 jne 0x00007ccc
.data:0x00007C89 a0417c mov 0x7c41,%al
.data:0x00007C8c 84c0 test %al,%al
.data:0x00007C8e 7505 jne 0x00007c95
.data:0x00007C90 83E103 and $0x1,%cx
.data:0x00007C93 7437 je 0x00007ccc
.data:0x00007C95 668b4c10 mov 0x10(%si),%ecx
.data:0x00007C99 be057c mov $0x7c05,%si
.data:0x00007C9c c644ff01 movb $0x1,-0x1(%si)
.data:0x00007Ca0 668b1e447c mov 0x7c44,%ebx
.data:0x00007Ca5 c7041000 movw $0x10,(%si)
.data:0x00007Ca9 c744020100 movw $0x1,0x2(%si)
.data:0x00007Cae 66895c08 mov %ebx,0x8(%si)
.data:0x00007Cb2 c744060070 movw $0x7000,0x6(%si)
.data:0x00007Cb7 6631c0 xor %eax,%eax
.data:0x00007Cba 894404 mov %ax,0x4(%si)
.data:0x00007Cbd 6689440c mov %eax,0xc(%si)
.data:0x00007Cc1 b442 mov $0x42,%ah
.data:0x00007Cc3 cd13 int $0x13
.data:0x00007Cc5 7205 jb 0x00007ccc
.data:0x00007Cc7 bb0070 mov $0x7000,%bx
.data:0x00007Cca eb7d jmp 0x00000149
.data:0x00007Ccc b408 mov $0x8,%ah
112
Dirección Hexadecimal Ensamblador
.data:0x00007Cce cd13 int $0x13
.data:0x00007Cd0 730a jae 0x00007cdc
.data:0x00007Cd2 f6c280 test $0x80,%dl
.data:0x00007Cd5 0f84ea00 je 0x000001c3
.data:0x00007Cd9 e98d00 jmp 0x00000169
.data:0x00007Cdc be057c mov $0x7c05,%si
.data:0x00007Cdf c644ff00 movb $0x0,-0x1(%si)
.data:0x00007Ce3 6631c0 xor %eax,%eax
.data:0x00007Ce6 88f0 mov %dh,%al
.data:0x00007Ce8 40 inc %ax
.data:0x00007Ce9 66894404 mov %eax,0x4(%si)
.data:0x00007Ced 31d2 xor %dx,%dx
.data:0x00007Cef 88ca mov %cl,%dl
.data:0x00007Cf1 c1e202 shl $0x2,%dx
.data:0x00007Cf4 8,80E+09 mov %ch,%al
.data:0x00007Cf6 88f4 mov %dh,%ah
.data:0x00007Cf8 40 inc %ax
.data:0x00007Cf9 894408 mov %ax,0x8(%si)
.data:0x00007Cfc 31c0 xor %ax,%ax
.data:0x00007Cfe 88d0 mov %dl,%al
.data:0x00007D00 c0e802 shr $0x2,%al
.data:0x00007D03 668904 mov %eax,(%si)
.data:0x00007D06 66a1447c mov 0x7c44,%eax
.data:0x00007D0a 6631d2 xor %edx,%edx
.data:0x00007D0d 66f734 divl (%si)
.data:0x00007D10 88540a mov %dl,0xa(%si)
.data:0x00007D13 6631d2 xor %edx,%edx
.data:0x00007D16 66f77404 divl 0x4(%si)
.data:0x00007D1a 88540b mov %dl,0xb(%si)
.data:0x00007D1d 89440c mov %ax,0xc(%si)
.data:0x00007D20 3b4408 cmp 0x8(%si),%ax
.data:0x00007D23 7d3c jge 0x00000161
.data:0x00007D25 8a540d mov 0xd(%si),%dl
.data:0x00007D28 c0e206 shl $0x6,%dl
.data:0x00007D2b 8a4c0a mov 0xa(%si),%cl
.data:0x00007D2e fec1 inc %cl
.data:0x00007D30 08d1 or %dl,%cl
.data:0x00007D32 8a6c0c mov 0xc(%si),%ch
.data:0x00007D35 5a pop %dx
.data:0x00007D36 8a740b mov 0xb(%si),%dh
.data:0x00007D39 bb0070 mov $0x7000,%bx
.data:0x00007D3c 8ec3 mov %bx,%es
.data:0x00007D3e 31db xor %bx,%bx
113
Dirección Hexadecimal Ensamblador
.data:0x00007D40 b80102 mov $0x201,%ax
.data:0x00007D43 cd13 int $0x13
.data:0x00007D45 722a jb 0x00000171
.data:0x00007D47 8cc3 mov %es,%bx
.data:0x00007D49 8e06487c mov 0x7c48,%es
.data:0x00007D4d 60 pusha
.data:0x00007D4e 1e push %ds
.data:0x00007D4f b90001 mov $0x100,%cx
.data:0x00007D52 8edb mov %bx,%ds
.data:0x00007D54 31f6 xor %si,%si
.data:0x00007D56 31ff xor %di,%di
.data:0x00007D58 fc cld
.data:0x00007D59 f3a5 rep movsw %ds:(%si),%es:(%di)
.data:0x00007D5b 1f pop %ds
.data:0x00007D5c 61 popa
.data:0x00007D5d ff26427c jmp *0x7c42
.data:0x00007D61 be857d mov $0x7d85,%si
.data:0x00007D64 e84000 call 0x000001a7
.data:0x00007D67 eb0e jmp 0x00000177
.data:0x00007D69 be8a7d mov $0x7d8a,%si
.data:0x00007D6c e83800 call 0x000001a7
.data:0x00007D6f eb06 jmp 0x00000177
.data:0x00007D71 be947d mov $0x7d94,%si
.data:0x00007D74 e83000 call 0x000001a7
.data:0x00007D77 be997d mov $0x7d99,%si
.data:0x00007D7a e82a00 call 0x000001a7
.data:0x00007D7d ebfe jmp 0x0000017d
.data:0x00007Da0 bb0100 mov $0x1,%bx
.data:0x00007Da3 b40e mov $0xe,%ah
.data:0x00007Da5 cd10 int $0x10
.data:0x00007Da7 ac lods %ds:(%si),%al
.data:0x00007Da8 3c00 cmp $0x0,%al
.data:0x00007Daa 75f4 jne 0x000001a0
.data:0x00007Dac c3 ret
.data:0x00007Dc3 bebd7d mov $0x7dbd,%si
.data:0x00007Dc6 31c0 xor %ax,%ax
.data:0x00007Dc8 cd13 int $0x13
.data:0x00007Dca 46 inc %si
.data:0x00007Dcb 8a0c mov (%si),%cl
.data:0x00007Dcd 80f900 cmp $0x0,%cl
.data:0x00007Dd0 750f jne 0x000001e1
.data:0x00007Dd2 beda7d mov $0x7dda,%si
114
Dirección Hexadecimal Ensamblador
.data:0x00007Dd5 e8cfff call 0x000001a7
.data:0x00007Dd8 eb9d jmp 0x00000177
.data:0x00007De1 bb0070 mov $0x7000,%bx
.data:0x00007De4 b80102 mov $0x201,%ax
.data:0x00007De7 b500 mov $0x0,%ch
.data:0x00007De9 b600 mov $0x0,%dh
.data:0x00007Deb cd13 int $0x13
.data:0x00007Ded 72d7 jb 0x000001c6
.data:0x00007Def b601 mov $0x1,%dh
.data:0x00007Df1 b54f mov $0x4f,%ch
.data:0x00007Df3 e9e6fe 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.
115
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
116
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
117
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
118
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;
119
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
120
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.
121
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*/
.text /*Directiva de gas que indica la sección de código*/
.code16 /*Directiva que indica que el código debe ser generado como de 16 bits*/
.globl _start; /*Directiva que indica el inicio del código.*/
_start: /*Etiqueta de inicio del código*/
jmp after_BPB /*Salta a la etiqueta BPB(BIOS parámetros bloque)*/
nop /*Instrucción nula*/
Tabla 24. Codigo GRUB parte 1. Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
122
Dirección Hexadecimal Ensamblador Comentario
.data:0x00007C00 eb48 jmp 0x00007c4a /*Salta a la d122irección 0:07c4a*/
.data:0x00007C02 90 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
. = _start + 4 /*Salta 4 bytes desde el inicio*/
mode: .byte 0 /*Asigna el valor de 0 al byte en la quinta posición del código, representa el mode*/
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*/
sector_start: /*Etiqueta indica el bloque del sector de inicio.*/
.byte 0 /*Alamacena en un byte el valor 0*/
123
Color Hexadecimal Código Comentario
head_start: /*Etiqueta indica el bloque de la cabecera de inicio.*/
.byte 0 /*Alamacena en un byte el valor 0*/
cylinder_start: /*Etiqueta indica el bloque de el cilindro de inicio.*/
.word 0 /*Almacena en una palabra dos bytes el valor 0 */
. = _start + 0x3e
/*Salta al byte 0x3e, al byte 62 en decimal*/
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.
124
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: /*Etiqueta que identifica el controlador de inicio*/
.byte 0xFF /*Almacena el byte 0xFF*/
force_lba: /*Etiqueta que indica si el dispositivo acepta lba*/
.byte 0 /*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.
125
Código
Dirección Nemotécnico Desensamblado Código Libre Comentario
after_BPB: /*Etiqueta que indica el fin del Bloque BPB*/
0x7C4a Fa cli 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*/
0x7C4b eb07 jmp 0x00007c54
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*/
0x7C54 ea597c0000 ljmp $0x0,$0x7c59
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.*/
126
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 mov 0x7c40,%al .byte 0xa0; .word (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*/
0x7C6c 52 push %dx pushw %dx /*Apila el valor de dx*/
0x7C6d be7f7d 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*/
0x7C70 e83401 call 0x00007da7 call message /*llama a la función message, que inicia en la dirección 0:07da7*/
127
Código
Dirección Nemotécnico Desensamblado Código Libre Comentario
0x7C73 f6c280 test $0x80,%dl 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 5ª pop %dx popw %dx /*Apila dx*/
0x7C80 52 push %dx pushw %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*/
0x7C87 7543 jne 0x00007ccc jne chs_mode /*En caso de no soportar lba salta a la etiqueta chs_mode*/
128
Código
Dirección Nemotécnico Desensamblado Código Libre Comentario
0x7C89 a0417c mov 0x7c41,%al .byte 0xa0; .word (force_lba-_start+0x7c00)
/*Mueve el valor de la direccion0:07c41 a al. Etiqueta de lba*/
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*/
0x7C90 83E103 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*/
0x7C93 7437 je 0x00007ccc jz chs_mode /*Si la operación and dio cero salta a la etiqueta chs_mode*/
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 Comentario
lba_mode:
/*Etiqueta de código, Indica el inicio del bloque de la especificacion lba*/
129
Código
Dirección Nemotécnico Desensamblado Código Libre Comentario
0x7C95 668b4c10 mov 0x10(%si),%ecx
movl 0x10(%si), %ecx
/*Mueve 4 bytes de la dirección 0:si+16 a ecx, Puede mover 4 bytes si se este menejando modo real*/
0x7C99 be057c mov $0x7c05,%si movw $(disk_address_packet-_start+0x7c00), %si
/*Mueve la dirección de disk_adress_packet a si*/
0x7C9c c644ff01 movb $0x1,-0x1(%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*/
0x7Ca0 668b1e447c mov 0x7c44,%ebx movl (stage2_sector-_start+0x7c00), %ebx
/*Mueve la dirección de stage2_sector_start a ebx, el valor de 1*/
0x7Ca5 c7041000 movw $0x10,(%si) 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 */
0x7Ca9 c744020100 movw $0x1,0x2(%si)
movw $1, 2(%si)
/*Establece el valor de 0x0001 a los 2 bytes siguiente que apunta si, quedando el dap 10 00 01 00*/
130
Código
Dirección Nemotécnico Desensamblado Código Libre Comentario
0x7Cae 66895c08 mov %ebx,0x8(%si)
movl %ebx, 8(%si)
/*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*/
0x7Cb2 c744060070 movw $0x7000,0x6(%si)
movw $0x7000, 6(%si)
/*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*/
0x7Cb7 6631c0 xor %eax,%eax xorl %eax, %eax /*Establece eax=0*/
0x7Cba 894404 mov %ax,0x4(%si) movw %ax, 4(%si)
/*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*/
0x7Cbd 6689440c mov %eax,0xc(%si) movl %eax, 12(%si)
/*Mueve el valor de eax a la dirección que apunta si + 12 bytes, Paa completar el dap.*/
131
Código
Dirección Nemotécnico Desensamblado Código Libre Comentario
0x7Cc1 b442 mov $0x42,%ah movb $0x42, %ah /*Establece el valor de 0x42h a ah*/
0x7Cc3 cd13 int $0x13 int $0x13
/*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*/
0x7Cc5 7205 jb 0x00007ccc jc chs_mode
/*En caso de la int13h ejecutar error salta a la etiqueta chs_mode*/
0x7Cc7 bb0070 mov $0x7000,%bx movw $0x7000, %bx /*Establece le valor de 0x7000 a bx*/
0x7Cca eb7d jmp 0x00007D49 jmp copy_buffer /*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 Desensamblado Código Libre Comentario
chs_mode: /*Etiqueta de
código*/
0x7Ccc b408 mov $0x8,%ah movb $8, %ah /*Establece el valor de 0x8 a ah. Función 8h*/
132
Código
Dirección Nemotécnico Desensamblado Código Libre Comentario
0x7Cce cd13 int $0x13 int $0x13
/*Ejecuta la interrupción 13 función 8h , para obtener los parámetros del disco*/
0x7Cd0 730ª jae 0x00007cdc jnc final_init
/*Se la lectura de los parámetros no da error salta a final_init o a la dirección 0:07cdc*/
0x7Cd2 f6c280 test $0x80,%dl testb $0x80, %dl
/*Realiza una operación and bit a bit del valor 0x80 con dl*/
0x7Cd5 0f84ea00 je 0x00007dc3 jz floppy_probe
/*Si la operación and dio cero salta a la etiqueta floppy_probe cuya dirección es 0:7dc3*/
0x7Cd9 e98d00 jmp 0x00007d69 jmp hd_probe_error
/*Salta a ejecutar un mensaje de error a la dirección 0:7d69*/
final_init: /*Etiqueta de
código*/
0x7Cdc be057c mov $0x7c05,%si movw $(sectors-_start+0x7c00), %si
/*Mueve el valor de la dirección de la etiqueta sector a si. En este caso 0x7c05*/
0x7Cdf c644ff00 movb $0x0,-0x1(%si)
movb $0, -1(%si)
/*Establece el valor de cero a la dirección que apunta si menos un byte, en este caso es el mode*/
0x7Ce3 6631c0 xor %eax,%eax xorl %eax, %eax /*Establece eax=0*/
133
Código
Dirección Nemotécnico Desensamblado Código Libre Comentario
0x7Ce6 88f0 mov %dh,%al movb %dh, %al
/*Mueve el valor de dh a al, dh es una valor almacenado por la BIOS antes de dar el control al MBR*/
0x7Ce8 40 inc %ax incw %ax /*Incrementa en una unidad el valor de ax*/
0x7Ce9 66894404 mov %eax,0x4(%si) movl %eax, 4(%si)
/*Mueve el valor de eax a la dirección que apunta si + 4 bytes, el número de cabeceras*/
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 /*Desplaza 2 bits a la izquierda el valor de dx*/
0x7Cf4 8800000000 mov %ch,%al movb %ch, %al /*Mueve ch a al*/
0x7Cf6 88f4 mov %dh,%ah movb %dh, %ah /*Mueve el valor de dh a ah*/
0x7Cf8 40 inc %ax incw %ax /*Incrementa ax en una unidad*/
0x7Cf9 894408 mov %ax,0x8(%si) movw %ax, 8(%si)
/*Mueve el valor de ax a la dirección de si + 8 bytes. Representa el número de cilindros */
0x7Cfc 31c0 xor %ax,%ax xorw %ax, %ax /*Establece ax=0*/
0x7Cfe 88d0 mov %dl,%al movb %dl, %al /*Mueve el valor de dl a al*/
0x7D00 c0e802 shr $0x2,%al shrb $2, %al /*Recorre 2 bits a a la derecha el valor de al*/
134
Código
Dirección Nemotécnico Desensamblado Código Libre Comentario
0x7D03 668904 mov %eax,(%si) movl %eax, (%si)
/*Mueve el valor de eax a la dirección que almacena si. Representa el número de sectores*/
setup_sectors: /*Etiqueta de
Código*/
0x7D06 66a1447c mov 0x7c44,%eax movl (stage2_sector-_start+0x7c00), %eax
/*Mueve la dirección que contiene la etiqueta stage2_sector a eax, en este caso 0x7c44*/
0x7D0a 6631d2 xor %edx,%edx xorl %edx, %edx /*Establece edx=0*/
0x7D0d 66f734 divl (%si) divl (%si)
/*Divide el valor de eax para el valor que almacena la dirección de si*/
0x7D10 88540ª mov %dl,0xa(%si) movb %dl, 10(%si)
/*Mueve el valor de dl a la dirección de memoria si +10 bytes. Representa el sector de inicio de la segunda etapa*/
0x7D13 6631d2 xor %edx,%edx xorl %edx, %edx /*Establece edx=0*/
0x7D16 66f77404 divl 0x4(%si) divl 4(%si)
/*Divide el valor de eax para el valor que almacena la dirección de si + 4 bytes*/
0x7D1a 88540b mov %dl,0xb(%si) movb %dl, 11(%si) /*Mueve el valor de dl a la dirección de si +11 bytes*/
135
Código
Dirección Nemotécnico Desensamblado Código Libre Comentario
0x7D1d 89440c mov %ax,0xc(%si) movw %ax, 12(%si)
/*Mueve el valor de ax a la dirección de si +12 bytes*/
0x7D20 3b4408 cmp 0x8(%si),%ax cmpw 8(%si), %ax
/*Realiza una comparación entre el valor de la dirección de si +8 bytes y el registro dl */
0x7D23 7d3c jge 0x00007d61 jge geometry_error /*Salta a la dirección 0:07d61 si existe error*/
0x7D25 8a540d mov 0xd(%si),%dl movb 13(%si), %dl
/*Mueve el valor de la dirección de si + 14 bytes a 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 /*Incrementa el valor de cl*/
0x7D30 08d1 or %dl,%cl orb %dl, %cl
/*Realiza la operación or entre dl y cl almacenado el resultado en cl, suma dl , cl*/
0x7D32 8a6c0c mov 0xc(%si),%ch movb 12(%si), %ch
/*Mueve el valor de la dirección de si +12 bytes a ch*/
0x7D35 5ª pop %dx popw %dx /*des apila dx*/
0x7D36 8a740b mov 0xb(%si),%dh movb 11(%si), %dh
/*Mueve el valor de la dirección de si +11 bytes a dh*/
0x7D39 bb0070 mov $0x7000,%bx movw $0x7000, %bx /*Mueve el valor de 0x7000 a bx*/
136
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
/*Establece los parámetros de la función ah=02, al =01 de la int13h*/
0x7D43 cd13 int $0x13 int $0x13
/*Ejecuta la int 13h para leer los sectores de la etapa 2 con los valores antes configurados*/
0x7D45 722ª jb 0x00000171 jc read_error
/*Si la lectura da error salta a la etiqueta read_error que es la dirección 0:7d71*/
0x7D47 8cc3 mov %es,%bx movw %es, %bx /*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.
137
Séptima parte del Código
Código
Dirección Nemotécnico Desensamblado Código Libre Comentario
0x7D49 8e06487c mov 0x7c48,%es movw
(stage2_segment-_start+0x7c00), %es
/*Mueve el valor en palabra o dos bytes del que apunta la dirección stage2_segment_start a es. En este caso 0x80 00*/
0x7D4d 60 pusha pusha /*Apila ax*/
0x7D4e 1e push %ds pushw %ds /*Apila ds*/
0x7D4f b90001 mov $0x100,%cx movw $0x100, %cx /*Establece el valor de 0x100 a cx*/
0x7D52 8edb mov %bx,%ds movw %bx, %ds /*Mueve el valor de bx a ds, bx almacenaba 0x7000*/
0x7D54 31f6 xor %si,%si xorw %si, %si /*Establece si =0*/
0x7D56 31ff xor %di,%di xorw %di, %di /*Establece di=0*/
0x7D58 Fc cld cld /*Limpia la bandera de dirección*/
0x7D59 f3a5 rep movsw
%ds:(%si),%es:(%di) rep movsw
/*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.
138
Octava parte del Código
Código
Dirección Nemotécnico Desensamblado Código Libre Comentario
0x7D5b 1f pop %ds popw %ds /*Des apila ds establece ds=0*/
0x7D5c 61 popa popa /*Des apila ax, Establece ax=0*/
0x7D5d ff26427c jmp *0x7c42 jmp *(stage2_address)
/*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 Comentario
geometry_error: /*Etiqueta de código*/
0x7D61 be857d mov
$0x7d85,%si
movw $(geometry_error_string-
_start+0x7c00), %si;
/*Mueve el valor de la dirección de la etiqueta geometry_error_string a si. Se prepara para imprimir mensaje de error*/
0x7D64 e84000 call 0x000001a7 call message /*Llama a la función message para imprimir mensaje de error*/
139
Código
Dirección Nemotécnico Desensamblado Código Libre Comentario
0x7D67 eb0e jmp
0x00000177 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*/
0x7D69 be8a7d mov
$0x7d8a,%si
movw $(hd_probe_error_string-
_start+0x7c00), %si;
/*Mueve el valor de la dirección de la etiqueta hd_probe_error_string a si. Se prepara para imprimir mensaje de error*/
0x7D6c e83800 call 0x000001a7 call message /*Llama a la función message para imprimir mensaje de error*/
0x7D6f eb06 jmp
0x00000177 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*/
0x7D71 be947d mov
$0x7d94,%si
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*/
0x7D74 e83000 call 0x000001a7 call message /*Llama a la función message para imprimir mensaje de error*/
general_error: /*Etiqueta de código*/
140
Código
Dirección Nemotécnico Desensamblado Código Libre Comentario
0x7D77 be997d mov
$0x7d99,%si
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*/
0x7D7a e82a00 call 0x00007da7 call message /*Llama a la función message para imprimir el mensaje de error*/
stop: /*Etiqueta de código*/
0x7D7d Ebfe jmp
0x00007d7d jmp stop
/*Salta a la etiqueta de código stop. Crea un bucle infinito*/
notification_string: .string
"GRUB "
/*Etiqueta de código que representa el inicio 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*/
read_error_string: .string
"Read"
/*Etiqueta de código que representa el inicio 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: /*Etiqueta de código*/
141
Código
Dirección Nemotécnico Desensamblado Código Libre Comentario
0x7Da0 bb0100 mov $0x1,%bx movw $0x0001, %bx
/*Establece el valor de 1 a bx, sirve para el modo grafico específicamente pagina 1*/
0x7Da3 b40e mov $0xe,%ah movb $0xe, %ah
/*Establece el valor de 0xe a ah, es la función de imprimir un carácter*/
0x7Da5 cd10 int $0x10 int $0x10
/*Ejecuta la interrupción 10h función 0xe, Imprimir carácter*/
message: /*Etiqueta que indica el inicio de la función message*/
0x7Da7 Ac lods
%ds:(%si),%al lodsb
/*Almacena el valor de ds:si a al*/
0x7Da8 3c00 cmp $0x0,%al cmpb $0, %al
/*Compara si el valor almacenado en al es cero, esto indica que se alcanzó el fin de la cadena*/
0x7Daa 75f4 jne 0x00007da0 jne 1b
/*Si el valor anterior de al no es cero salta a la dirección de memoria 0:7da0*/
0x7Dac c3 ret 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*/
Tabla 33. Código GRUB parte 9. Autor: Tesista.
Fuente: Desarrollo de tema de tesis.
142
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 Comentario
floppy_probe:
/*Etiqueta de código*/
0x7Dc3 bebd7d mov $0x7dbd,%si movw $(probe_values-1
-_start+0x7c00), %si /*Establece el valor de 0x7dbd a si*/
probe_loop:
/*Etiqueta de código*/
0x7Dc6 31c0 xor %ax,%ax xorw %ax, %ax /*Establece ax=0*/
0x7Dc8 cd13 int $0x13 int $0x13
/*Ejecuta la interrupción 13h con función 0h para resetear el disco*/
0x7Dca 46 inc %si incw %si /*Incrementa el valor de si*/
0x7Dcb 8a0c mov (%si),%cl movb (%si), %cl /*Mueve el valor de la dirección que contiene si a cl*/
0x7Dcd 80f900 cmp $0x0,%cl cmpb $0, %cl /*Realiza una comparación del valor de cero con cl*/
0x7Dd0 750f jne 0x00007de1 jne 1f /*En caso de no ser iguales salta a la dirección 0x7de1*/
0x7Dd2 beda7d mov $0x7dda,%si movw
$(fd_probe_error_string-_start+0x7c00), %si;
/*Mueve el valor de la dirección de fd_probe_error_string a si. Se prepara para imprimir mensaje de error*/
0x7Dd5 e8cfff call 0x000001a7 call message /*Llama a la función message para imprimir error*/
143
Código
Dirección Nemotécnico Desensamblado Código Libre Comentario
0x7Dd8 eb9d 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*/
1:
/*Etiqueta de código*/
0x7De1 bb0070 mov $0x7000,%bx movw $0x7000, %bx /*Mueve el valor 0x7000 a bx*/
0x7De4 b80102 mov $0x201,%ax movw $0x201, %ax
/*Almacena los valores de configuración de la int 13 h en este caso ah=2, al=1*/
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.
144
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
Código
Dirección Nemotécnico Desensamblado Código Libre Comentario
0x7Dfe 0x55aa .word 0xaa55 .word 0xaa55 /*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.
145
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"
146
.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
heads:
.long 0
cylinders:
.word 0
sector_start:
.byte 0
head_start:
.byte 0
cylinder_start:
.word 0
/* Finalizo el BPB (BIOS parameter block). */
. = _start + STAGE1_BPBEND
147
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*/
148
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 */
149
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
150
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
151
* %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
152
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 */
153
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 %cl /* Normaliza el sector (sectores van
desde 1-N, a 0-(N-1) ) */
orb %dl, %cl
154
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
155
/*
* 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.
156
*/
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)
*/
157
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:
158
/* 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
159
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 */
160
#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
161
/* 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
162
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,
163
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,
164
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 */
}
165
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;
166
*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':
167
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)
168
{
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;
}
169
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++;
170
}
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.
171
*/
#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)
172
{
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)
173
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)
174
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;
175
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 (' ');
176
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);
177
}
/* 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;
178
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. */
179
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. */
180
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);
181
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 */
182
{
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 */
183
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)
184
{
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);
185
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;
186
/* 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;
}
187
/* 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)
188
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')
189
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--;
190
}
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 ++;
}
191
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;
192
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]");
193
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 ();
}
194
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. */
195
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;
196
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;
}
197
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;
198
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))
199
{
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).
200
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.
201
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.
202
*/
.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
203
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
204
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
205
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
206
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.
207
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.
208
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.
209
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-in-
Assembly-and-C-Part.
http://www.codeproject.com/Articles/664165/Writing-a-boot-loader-in-
Assembly-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