CÓMO ARRANCA EL SISTEMA OPERATIVO MS-DOS + WINDOWS’951 DESENSAMBLADO2 DE LOS SECTORES DE PARTICIÓN Y DE ARRANQUE Marzo 1997 Marco Antonio y Pedro Pablo Gómez Martín marcoypedro@retemail.es 1 Sistema mixto: instalado Windows’95 primera edición, con la opción de conservar el sistema operativo anterior, el MS-DOS 6.22. Antes de empezar a arrancar, pulsando F4, arrancaba el MS-DOS, en vez de Windows 95. 2 Este desensamblado se hizo únicamente con fines didácticos, para entender el funcionamiento del arranque. ARRANQUE DEL SISTEMA INTEL x86 Cuando el ordenador se enciende, los procesadores INTEL están preparados para que su primera instrucción a ejecutar sea la situada en FFFF:0000. En esta posición, está colocada la ROM-BIOS, de modo que lo primero que ejecuta la CPU al encenderse son las instrucciones de la BIOS. En ellas, hay rutinas de verificación de la integridad del sistema, comprobandose el buen funcionamiento del procesador con algunas operaciones, la buena comunicación con la tarjeta gráfica, de las disqueteras, etc. De estas comprobaciones, la más conocida es el chequeo de la memoria. Tras comprobar el buen funcionamiento del equipo, la BIOS establece sus variables internas. Entre ellas están la cantidad de memoria del sistema punteros a estructuras de control como el buffer del teclado, etc. Además, busca las posibles ampliaciones BIOS que pudiera haber en la controladora de disco, tarjeta gráfica, etc, y captura las interrupciones BIOS, que permiten al sistema un manejo de las operaciones de E/S de forma independiente al hardware. Una vez hecho todo esto, debe ceder el control al sistema operativo. Para evitar la dependencia de la BIOS con un sistema operativo concreto, lo que hace es cargar un sector determinado (el primero) de las unidades de almacenamiento, de modo que el sistema operativo que pudiera haber sido instalado en ellas debe haberse encargado de ocupar ese sector que, una vez cargado y ejecutado por la BIOS, dará las instrucciones necesarias al procesador para comenzar la carga del S.O. La BIOS, por lo tanto, tras terminar su inicialización, leerá el primer sector de la unidad A:. Si no lo consigue, tratará de leer el primero de la unidad C:. Si tampoco lo consiguiera, avisaría al usuario y 'ejecutaría' ROM-BASIC, o, en su defecto, detendría completamente el sistema . En algunos casos, el orden de acceso a las unidades puede ser cambiado mediante el SETUP de la BIOS. En los disquettes, el primer sector es ya el sector de arranque del sistema operativo. Sin embargo, en los discos duros no lo es. El primer sector tiene la llamada tabla de partición que contiene las posibles (hasta 4) particiones del disco duro. En ella está indicado el 'dueño' de cada partición, su comienzo, su final, y si es o no partición de arranque. En ese mismo sector, hay, además de la tabla, un pequeño código que analiza la tabla y obra en consecuencia, ejecutando el primer sector, ahora sí sector de arranque, de la partición que esté especificada como activa en la tabla. Ese código es el que se ha analizado más abajo. Para acabar, dos anotaciones. La BIOS, antes de dar el control al primer sector de la unidad comprueba si es un sector ejecutable o no lo es, para evitar cuelgues del sistema al ejecutar sectores no válidos. Si es o no ejecutable aparece indicado en los dos últimos bytes que deben ser 55h y AAh para que la BIOS ejecute el sector. Por último, he dicho que en la tabla de partición sólo entran cuatro posibles particiones. Sin embargo el MS-DOS (o el Windows'95) admiten más de cuatro. Esto es debido a que crean una partición de arranque (C:), y una partición extendida, que son las incluidas en la tabla de partición. Pero la extendida tiene, a su vez, en su primer sector una nueva tabla de partición con una partición primaria, que será ella misma, y otra extendida, indicando la siguiente. Aparece así una especie de 'lista enlazada', de modo que se permiten más de 20 particiones (hasta que se acaben las letras). Nada más. Aquí va el código. SECTOR DE PARTICION DEL DISCO DURO. LA BIOS LO CARGA INICIALMENTE EN LA POSICION 0000:7C00 0DBD:7C00 0DBD:7C01 0DBD:7C03 0DBD:7C05 0DBD:7C08 0DBD:7C0A 0DBD:7C0B 0DBD:7C0C 0DBD:7C0D 0DBD:7C0E 0DBD:7C0F 0DBD:7C10 0DBD:7C13 0DBD:7C16 0DBD:7C17 0DBD:7C18 FA 33C0 8ED0 BC007C 8BF4 50 07 50 1F FB FC BF0006 B90001 F2 A5 EA1D060000 CLI XOR MOV MOV MOV PUSH POP PUSH POP STI CLD MOV MOV REPNZ MOVSW JMP 0DBD:7C1D 0DBD:7C20 0DBD:7C22 0DBD:7C25 0DBD:7C27 0DBD:7C2A 0DBD:7C2C 0DBD:7C2F 0DBD:7C31 0DBD:7C33 BEBE07 B304 803C80 740E 803C00 751C 83C610 FECB 75EF CD18 MOV MOV CMP JZ CMP JNZ ADD DEC JNZ INT 0DBD:7C35 8B14 0DBD:7C37 8B4C02 MOV MOV 0DBD:7C3A 0DBD:7C3C 0DBD:7C3F 0DBD:7C41 0DBD:7C43 0DBD:7C46 0DBD:7C48 0DBD:7C4B 0DBD:7C4C 0DBD:7C4E 0DBD:7C50 0DBD:7C51 0DBD:7C54 0DBD:7C56 0DBD:7C58 0DBD:7C59 0DBD:7C5B MOV ADD DEC JZ CMP JZ MOV LODSB CMP JZ PUSH MOV MOV INT POP JMP JMP 8BEE 83C610 FECB 741A 803C00 74F4 BE8B06 AC 3C00 740B 56 BB0700 B40E CD10 5E EBF0 EBFE ; Deteniene las interrupciones ; Coloca los registros de segmento ; en el segmento actual (0000h) ; coloca la pila dentro de ese ; segmento. Ajusta los valores de ; SI y DI para copiarse (pero no ; el sector entero, sino sólo el ; código) a la posición ; 0000:0600 para dejar el espacio ; libre para el sector de arranque ; de la partición del dusco duro DI,0600 ; que contiene el S.O. CX,0100 ; Copia 256 bytes, que es lo que ; ocupa el código ejecutable y las ; cadenas de texto de error. 0000:061D ; Salta a la siguiente instrucción ; de su nuevo emplazamiento. SI,07BE ; Busca en la tabla de particiones BL,04 ; situada a partir de 0000:07BE BYTE PTR [SI],80 ; la partición de arranque. 7C35 ; Si la encuentra, continúa. BYTE PTR [SI],00 7C48 SI,+10 BL 7C22 ; Si no, salta a ejecutar una 18 ; hipotética ROM-BASIC. AX,AX SS,AX SP,7C00 SI,SP AX ES AX DS ; Aquí sigue tras encontrar la ; partición de arranque. DX,[SI] ; Almacena el nº de la unidad, el CX,[SI+02] ; cabezal, sector y cilindro donde ; comienza la partición (DX y CX). BP,SI ; Busca otra posible partición de SI,+10 ; arranque, para encontrar un poBL ; sible error en la tabla de par7C5D ; tición. BYTE PTR [SI],00 7C3C SI,068B ; Aquí salta si hay algún error ; en la tabla de partición. AL,00 ; Muestra el mensaje: 7C5B ; SI ; 'Invalid partition table' BX,0007 ; AH,0E ; en la pantalla, (página 0, 10 ; color 7), SI ; 7C4B ; 7C5B ; y realiza un bucle sin fín. ; Aquí salta si no hay error en la tabla de ; información de comienzo de la partición. 0DBD:7C5D BF0500 MOV DI,0005 0DBD:7C60 BB007C MOV BX,7C00 0DBD:7C63 B80102 MOV AX,0201 0DBD:7C66 57 PUSH DI 0DBD:7C67 CD13 INT 13 0DBD:7C69 5F POP DI 0DBD:7C6A 730C JNB 7C78 0DBD:7C6C 33C0 XOR AX,AX 0DBD:7C6E CD13 INT 13 0DBD:7C70 4F DEC DI 0DBD:7C71 75ED JNZ 7C60 0DBD:7C73 BEA306 MOV SI,06A3 0DBD:7C76 EBD3 JMP 7C4B particiones. Tiene en DX y CX la ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; Carga el primer sector de la partición de arranque, usando los datos sacados de la tabla de partición. Coloca en DI un contador (inicialmente a 5) que indica el número de intentos que se van a realizar si hay error en la lectura del nuevo sector de arranque. Si al quinto intento no lo consigue, muestra: 'Error loading operating system' y detiene el ordenador, usando la misma rutina que en el caso del error en la tabla de partición ; Aquí salta si no hubo error al cargar el nuevo sector, que ahora se encuen; tra en la posición 0000:7C00, 'pisando' ya los datos de la tabla de parti; ciones. 0DBD:7C78 BEC206 MOV SI,06C2 ; Mira si el sector cargado es de 0DBD:7C7B BFFE7D MOV DI,7DFE ; arranque (últimos dos bytes con 0DBD:7C7E 813D55AA CMP WORD PTR [DI],AA55 ; AA55h). Si lo es, lo 0DBD:7C82 75C7 JNZ 7C4B ; ejecuta, y si no lo es, muestra: 0DBD:7C84 8BF5 MOV SI,BP ; 'Missing operating system' 0DBD:7C86 EA007C0000 JMP 0000:7C00 ; y detiene el sistema, con la ; rutina de siempre. ; ; ; ; ; Registros antes de saltar al sector de arranque: AX = 0000 BX = 7C00 CX = <Cilindro-sector> DX = <Unidad-Cabezal> CS = 0000 DS = 0000 ES = 0000 SS = 0000 SP = 7C00 (?) BP = 06C2 SI = 06C2 DI = 7DFE VOLCADO DE MEMORIA TRAS LA ULTIMA INSTRUCCION 0DBD:7C80 0DBD:7C90 69 64 0DBD:7CA0 6C 65 0DBD:7CB0 20 6F 0DBD:7CC0 6D 00 0DBD:7CD0 69 6E 0DBD:7CE0 6F 00 0DBD:7CF0 00 00 0DBD:7D00 00 00 Después son todo 20 70 00 45 70 65 4D 69 67 20 00 00 00 00 00 00 0's 61 72 72 73 73 00 00 00 72 72 61 73 79 00 00 00 74 6F 74 69 73 00 00 00 69-74 72-20 69-6E 6E-67 74-65 00-00 00-00 00-00 69 6C 67 20 6D 00 00 00 6F 6F 20 6F 00 00 00 00 49 6E 61 73 70 00 00 00 6E 20 64 79 65 80 00 00 76 74 69 73 72 58 00 00 61 61 6E 74 61 13 00 00 6C 62 67 65 74 19 00 00 Inval id partition tab le.Error loading operating syste m.Missing operat ing system...X.. o............... ................ ........... 80 00 00 00 55 01 00 00 00 AA .. ...??.?......... ...?........-... ................ ..............U. VOLCADO DE LA TABLA DE PARTICIONES, GUARDADAS EN EL MISMO SECTOR 0DBD:7DB0 0DBD:7DC0 0DBD:7DD0 0DBD:7DE0 0DBD:7DF0 01 01 00 00 00 E5 00 00 06 05 00 00 3F 3F 00 00 3F FF 00 00 E4 CD 00 00 3F C0 00 00 00-00 16-0E 00-00 00-00 00 00 00 00 81 C0 00 00 16 D5 00 00 0E 2D 00 00 00 00 00 00 SECTOR DE ARRANQUE DE LA UNIDAD C: MS-DOS + WINDOWS'95 Como este sector de arranque es un poquito más complicado que el código del sector de partición, explicaré antes su funcionamiento. La misión del sector es comprobar que existe una copia del sistema operativo en disco. Si existe dicha copia, la ejecuta, y si no, muestra un mensaje de error al usuario pidiendo que se cambie el disco y que se pulse una tecla. Hay que darse cuenta de que el sector de arranque de la partición activa del disco duro es igual que el sector de arranque que pone el sistema operativo en el primer sector de los disquettes al formatearlos, de ahí que deba comprobar si está o no el DOS grabado en el disco. Para detectar si está el disco tiene el sistema operativo, busca en el primer sector del directorio raíz el archivo IO.SYS. Si lo está, lo carga en memoria (posición 0070:0000), y lo ejecuta. Hasta aquí, la teoría de la inicialización del MS-DOS. Pero el sector que vamos a analizar nosotros es MS-DOS + WINDOWS'95. La principal diferencia es que primero busca el archivo WINBOOT.SYS, si lo encuentra, lo carga y lo ejecuta. Si no lo encuentra, busca el archivo IO.SYS. Si lo encuentra lo ejecuta, y si no, muestra ya el mensaje de error. Hay, sin embargo, unas cuantas 'chapuzas' en medio (by Micro$oft). Tras encontrar cualquiera de los dos archivos, se cargan solo los cuatro sectores del fichero, y sobre los datos cargados, se hacen dos comprobaciones que ¡¡sólo las cumple el WINBOOT.SYS!! ¡¡Qué marginación!! ¡¡¿¿Qué pasa si está el IO.SYS, y no el WINBOOT.SYS??!! ¡Lo carga, pero no lo ejecuta! J*der, que locura. Bueno, olvidemos todo esto, y centremonos un poco más en el código. Porque la teoría de lo que hace es bien sencilla, pero hacerlo... ¡no hay que olvidar que estamos ayudando al ordenador a nacer!. Para acceder al disco solo disponemos de las funciones de lectura de la BIOS, a la que hay que dar el nº de sector de la pista, el cilindro y la cabeza de lectura. Y nosotros, queremos ya acceder al directorio raíz, cuya posición depende de la partición desde donde estemos arrancando, del número de FAT que tenga dicha partición, del espacio que ocupe la FAT, y de un montón de cosas más. ¿Cómo podemos encontrar por lo tanto el directorio raíz? Bueno, bueno, bueno. Antes, expliquemos un poco cómo estructura el MS-DOS los discos, pues este sector de arranque es del MS-DOS, y ya cuenta con que las estructuras del disco están creadas. En primer lugar, está el sector lógico de la partición número 0, que es donde se sitúa el sector de arranque que, desde un disquette, es cargado por la BIOS directamente, y que desde el disco duro, es cargado por el BootTrap del sector de partición. Después viene la FAT (File Alocation Table), que contiene información sobre las posiciones donde están grabados cada archivo dentro del disco. Esta estructura es muy importante dentro del disco, hasta el punto de que si se corrompiese, la información del disco se perdería. Por tanto, el MS-DOS, para evitar esto, mantiene, tras la primera FAT, otra (u otras) copias de la FAT, como 'copias de seguridad'. Tras las posibles copias, se encuentra la información del directorio raíz, que contiene los nombres de los archivos o directorios situados en el directorio raíz del disco, además de su longitud, atributos, fecha, y el primer cluster que ocupa dentro del disco. El tamaño de todos estos datos es variable, dependiendo del número de 'entradas' (de archivos) que se quieran tener, como máximo, en el directorio raíz. Por último, se sitúa la zona de datos, dividida en clusters, donde se graba finalmente el contenido de cada archivo o subdirectorio. Vemos por lo tanto que para saber el número del primer sector del directorio raíz hay que saber el número de copias de la FAT y el número de sectores que ocupa cada una; y para saber donde comienza la zona de datos hay que saber el número de entradas del directorio raíz. Por si esto fuera poco, previendo que el espacio asignado al sector de arranque de la partición se quede pequeño, existe la posibilidad de dejar varios sectores entre el sector de arranque y el primer sector de la primera FAT para el programa de arranque. Además, como hay que averiguar el número de sector del DISCO al que queremos acceder, y no de la PARTICION, debemos saber el número de sectores desde el principio del disco hasta el principio de la partición desde la que estamos arrancando. Vemos pues que para acceder al directorio raíz y a la zona de datos, necesitamos conocer bastantes cosas sobre el tamaño de las estructuras del disco. ¿Como las averiguamos? Afortunadamente, el tamaño de estas estructuras queda fijado al formatear el disco, al igual que el sector de arranque, por lo que dentro de este sector se graban, además del código, una serie de datos muy útiles para poder acceder a las zonas del disco. Estan situadas al principio del sector, entre una instrucción de salto al código que evita la 'ejecución' de los datos, y el propio código. Entre estos datos, hay también información sobre la estructura física del disco, es decir el número de pistas, el número de sectores por pista, etc. Esto es debido a que con los datos anteriores, calculabamos el número de sector del disco al que queríamos acceder, pero para la BIOS esto no es suficiente, pues debemos darle, como ya se ha dicho, el número de cilindro (pista), el número de cabeza (cara) donde se debe leer, y el número de sector dentro de la pista al que queremos acceder, para lo que necesitamos saber la estructura física del medio de almacenamiento. Por último, antes de pasar a explicar las variables y el código, decir que tras la parte ejecutable, vuelve a haber otra zona de datos conteniendo las cadenas de error que se muestran al usuario, y las cadenas de los archivos que se buscan en el disco. VARIABLES (Sacadas de ‘MS-DOS Avanzado’ y ‘PC-INTERNO 2.0’) Pos Significado En esta implementación 7C00 JMP SHORT Codigo EB3Ch 7C02 NOP 90h ; En algunas implementaciones es un JMP largo, y no aparece el ; NOP, al necesitar la codificación de la instrucción 3 bytes. 7C03 Nombre del fabricante MSWIN4.0 7C0B Bytes por sector 0200h 7C0D Sectores por cluster 10h 7C0E Sectores para el arranque, incluyendo 0001h el ya cargado. 7C10 Número de FAT’s 02h 7C11 Número de entradas en el raíz. 0200h 7C13 Sectores totales en la partición. 0000h (no usado, pocos bytes) 7C15 Byte de descripción del medio. (?) F8h 7C16 Número de sectores por FAT 00E2h 7C18 Sectores por pista 003Fh 7C1A Número de cabezas 0040h 7C1C Nº de sectores desde el principio de la unidad hasta el principio de la partición. 7C20 Sectores totales en la partición. Usa cuatro bytes, y si se completa 7C24 Número físico de la unidad. 7C26 ?????????????????????? 7C27 Número de serie del volumen 7C2B Etiqueta del volúmen (no usada en esta implementación). 7C36 Sistema de ficheros 7C3E Puntero a la cadena del archivo que se busca en el raíz. 10h 000E1681h 0080h 29h 22276CE8h 10h ‘FAT16 7DF1h ‘ CÓDIGO El código se carga en la posición 0000:7C00. En ese punto está la instrucción de salto ya citada, que salta, en esta implementación, hasta la posición 0000:7C40, desde donde comenzamos. 0DBD:7C40 0DBD:7C41 0DBD:7C43 0DBD:7C45 0DBD:7C48 0DBD:7C49 0DBD:7C4A 0DBD:7C4D 0DBD:7C50 0DBD:7C51 0DBD:7C52 0DBD:7C53 0DBD:7C54 0DBD:7C57 0DBD:7C5A 0DBD:7C5D 0DBD:7C5F 0DBD:7C60 0DBD:7C61 0DBD:7C62 0DBD:7C63 0DBD:7C64 0DBD:7C67 0DBD:7C6B 0DBD:7C6E 0DBD:7C71 0DBD:7C72 0DBD:7C75 0DBD:7C77 0DBD:7C79 FA 33C9 8ED1 BCFC7B 16 07 BD7800 C57600 1E 56 16 55 BF2205 897E00 894E02 B10B FC F3 A4 06 1F BD007C C645FE0F 8B4618 8845F9 FB 386624 7C04 CD13 723C CLI XOR MOV MOV PUSH POP MOV LDS PUSH PUSH PUSH PUSH MOV MOV MOV MOV CLD REPZ MOVSB PUSH POP MOV MOV MOV MOV STI CMP JL INT JB 0DBD:7C7B 0DBD:7C7E 0DBD:7C7F 0DBD:7C82 0DBD:7C85 0DBD:7C88 0DBD:7C8B 0DBD:7C8D 8A4610 98 F76616 03461C 13561E 03460E 13D1 50 MOV CBW MUL ADD ADC ADD ADC PUSH CX,CX SS,CX SP,7BFC SS ES BP,0078 SI,[BP+00] DS SI SS BP DI,0522 [BP+00],DI [BP+02],CX CL,0B ; ; ; ; Anula las interrupciones, y coloca la pila, y los registros de segmentos SS y ES. ; ; ; ; ; ; ; ; ; ; Carga en DS:SI la posición del DDPT, o tabla de parámetros de disquette, con información BIOS, y lo mete en la pila. Modifica la INT 1Eh a 0000:0522, que debe apuntar a la DDPT, y copia en esa posición la DDPT que había construído la BIOS. ES ; Tras esto, modifica algunos DS ; valores de la tabla (retarBP,7C00 ; do para la próxima operación BYTE PTR [DI-02],0F ; de E/S, y sectores AX,[BP+18] ; por pista). [DI-07],AL [BP+24],AH 7C7B 13 7CB7 ; ; ; ; ; AL,[BP+10] ; ; WORD PTR [BP+16]; AX,[BP+1C] ; DX,[BP+1E] ; AX,[BP+0E] ; DX,CX ; AX Realiza RESET de la controladora de discos si está arrancando desde disquette (creo). Si hay error, muestra mensaje, si no, sigue. Halla en DX:AX el número de sectores en el disco hasta el primer sector del directorio raíz usando los datos del final, y los mete en la pila (los usará luego), y en 0000:7BFC 0DBD:7C8E 0DBD:7C8F 0DBD:7C92 0DBD:7C95 0DBD:7C98 0DBD:7C9B 0DBD:7C9D 0DBD:7CA0 0DBD:7CA2 0DBD:7CA3 0DBD:7CA5 0DBD:7CA8 0DBD:7CAB 0DBD:7CAC 0DBD:7CAD 0DBD:7CB0 0DBD:7CB2 0DBD:7CB4 0DBD:7CB7 52 8946FC 8956FE B82000 8B7611 F7E6 8B5E0B 03C3 48 F7F3 0146FC 114EFE 5A 58 BB0007 8BFB B101 E89400 7247 PUSH MOV MOV MOV MOV MUL MOV ADD DEC DIV ADD ADC POP POP MOV MOV MOV CALL JB DX [BP-04],AX [BP-02],DX AX,0020 SI,[BP+11] SI BX,[BP+0B] AX,BX AX BX [BP-04],AX [BP-02],CX DX AX BX,0700 DI,BX CL,01 7D4B 7D00 0DBD:7CB9 0DBD:7CBB 0DBD:7CBD 0DBD:7CBF 0DBD:7CC0 0DBD:7CC3 0DBD:7CC4 0DBD:7CC5 0DBD:7CC6 0DBD:7CC8 0DBD:7CC9 0DBD:7CCB 0DBD:7CCD 0DBD:7CD0 0DBD:7CD2 382D 7419 B10B 56 8B763E F3 A6 5E 744A 4E 740B 03F9 83C715 3BFB 72E5 CMP JZ MOV PUSH MOV REPZ CMPSB POP JZ DEC JZ ADD ADD CMP JB [DI],CH 7CD6 CL,0B SI SI,[BP+3E] 0DBD:7CD4 0DBD:7CD6 0DBD:7CD8 0DBD:7CDB 0DBD:7CDE 0DBD:7CE0 0DBD:7CE2 EBD7 2BC9 B8D87D 87463E 3CD8 7599 BE807D JMP SUB MOV XCHG CMP JNZ MOV 7CAD CX,CX AX,7DD8 AX,[BP+3E] AL,D8 7C7B SI,7D80 0DBD:7CE5 0DBD:7CE6 0DBD:7CE7 0DBD:7CE9 0DBD:7CEA 0DBD:7CEC 0DBD:7CEE 0DBD:7CF0 0DBD:7CF2 0DBD:7CF4 0DBD:7CF7 0DBD:7CF9 0DBD:7CFB 0DBD:7CFE AC 98 03F0 AC 84C0 7417 3CFF 7409 B40E BB0700 CD10 EBEE BE837D EBE5 LODSB CBW ADD LODSB TEST JZ CMP JZ MOV MOV INT JMP MOV JMP SI 7D12 SI 7CD6 DI,CX DI,+15 DI,BX 7CB9 SI,AX AL,AL 7D05 AL,FF 7CFB AH,0E BX,0007 10 7CE9 SI,7D83 7CE5 ; ; ; ; ; ; Calcula el número de sectores que ocupa el directorio raíz, (cada entrada son 32 bytes), y suma el resultado al nº de sectores anteriores, dejando el resultado en 0000:7BFC ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; Obtiene de la pila en DX:AX el nº del primer sector del raíz. Usando una rutina, a la que luego llegaremos, carga en la posición 0000:0700 ese primer sector. Si hay error muestra el mensaje, y reinicia. Esto forma ahora parte de un bucle, que busca, en el sector del raíz cargado, el nombre del archivo situado en 0000:[0000:7C3E] (en un principio a WINBOOT.SYS) Aquí hay un error. Solo ha cargado el primer sector del raíz, pero busca el nombre como si lo hubiese cargado entero :-??? ; ; ; ; ; ; ; ; ; ; Aquí salta si en el raíz no encuentra el archivo de arranque buscado. Si estaba buscando 'WINBOOT.SYS' cambia el puntero, y repite la búsqueda con 'IO.SYS' (usando la misma rutina), y si estaba buscando ya el IO.SYS muestra un mensaje, y rearranca. ; ; ; ; ; ; ; ; ; ; ; ; ; ; Rutina de escribir mensajes. Se le pasa en DS:SI una especie de puntero a la cadena, la cual deberá terminar en FFh. Tras escribirla, modifica SI, para que apunte a la cadena 'Cambie el disco y presione una tecla', que acaba en 00h, y llamandose a sí misma la escribe. Tras esto, usando la INT 16h, espera que se pulse una tecla, y después reinicia el sistema con 0DBD:7D00 0DBD:7D03 0DBD:7D05 0DBD:7D07 0DBD:7D09 0DBD:7D0A 0DBD:7D0B 0DBD:7D0D 0DBD:7D10 BE817D EBE0 33C0 CD16 5E 1F 8F04 8F4402 CD19 MOV JMP XOR INT POP POP POP POP INT SI,7D81 7CE5 AX,AX 16 SI DS [SI] [SI+02] 19 ; la INT 19h 0DBD:7D12 0DBD:7D15 0DBD:7D18 0DBD:7D1B 0DBD:7D1D 0DBD:7D1F 0DBD:7D20 0DBD:7D21 0DBD:7D24 0DBD:7D26 0DBD:7D29 0DBD:7D2C 0DBD:7D2F 0DBD:7D30 0DBD:7D32 0DBD:7D35 0DBD:7D36 0DBD:7D38 0DBD:7D3C 0DBD:7D3E 0DBD:7D44 0DBD:7D46 BE827D 8B7D0F 83FF02 72C8 8BC7 48 48 8A4E0D F7E1 0346FC 1356FE BB0007 53 B104 E81600 5B 72C8 813F4D5A 75A7 81BF0002424A 759F EA00027000 MOV MOV CMP JB MOV DEC DEC MOV MUL ADD ADC MOV PUSH MOV CALL POP JB CMP JNZ CMP JNZ JMP SI,7D82 ; Aquí salta cuando encuentra DI,[DI+0F] ; en el raíz el fichero busDI,+02 ; cado. Mirando en la entrada 7CE5 ; del directorio, saca el AX,DI ; cluster de comienzo del arAX ; chivo. Si es diferente de 2, AX ; muestra error de disco con CL,[BP+0D] ; la rutina anterior. Si es 2, CX ; calcula el SECTOR de comienAX,[BP-04] ; zo, usando el nº de sector DX,[BP-02] ; de comienzo de la zona de BX,0700 ; datos guardado en 0:7BFC, y BX ; el nº de sectores*cluster. CL,04 ; Usando una rutina propia, 7D4B ; carga los 4 primeros secBX ; tores del archivo en 0:0700 7D00 ; (=0070:0000), que, supongo, WORD PTR [BX],5A4D ; se encargarán de cargar 7CE5 ; el archivo completo. Antes WORD PTR [BX+0200],4A42 ; de darle el control 7CE5 ; comprueba los dos primeros 0070:0200 ; bytes del archivo, que deben ; ser 'MZ' (archivo ejecuta; ble), y las dos primeras ; instrucciones: INC DX; ; DEC DX. Si el archivo no ; cumple alguna de las condi; ciones, muestra el error, y ; si las cumple, lo ejecuta, a ; partir de la posición ; 0070:0200 (la parte anterior ; deben ser datos.) He mirado ; y las condiciones solo las ; cumple el WINBOOT.SYS :-??? ; He dicho que solo carga cua; tro sectores del archivo. ; Esto lo hace así porque debe ; situar al programa en la po; sición 0000:0700. Sin embar; go, en la posición 0000:7C00 ; está éste sector de arranque, ; con los datos de la unidad ; de almacenamiento, que no ; deben ser 'pisadas'. Por ; tanto, tiene poco espacio ; para cargar todo el .SYS, ; y la única solución es car; gar un pequeño trozo, que ; se encargará de 'cargarse' ; a sí mismo en una zona de ; memoria más conveniente. 0DBD:7D4B 0DBD:7D4C 0DBD:7D4D 0DBD:7D4E 0DBD:7D4F 0DBD:7D50 0DBD:7D52 0DBD:7D55 0DBD:7D56 0DBD:7D59 0DBD:7D5A 0DBD:7D5C 0DBD:7D5F 0DBD:7D61 0DBD:7D64 0DBD:7D66 0DBD:7D68 0DBD:7D6A 0DBD:7D6C 0DBD:7D6F 0DBD:7D71 0DBD:7D72 0DBD:7D73 0DBD:7D74 0DBD:7D76 0DBD:7D77 0DBD:7D79 0DBD:7D7A 0DBD:7D7D 0DBD:7D7F 50 52 51 91 92 33D2 F77618 91 F77618 42 87CA F7761A 8AF2 8A5624 8AE8 D0CC D0CC 0ACC B80102 CD13 59 5A 58 7209 40 7501 42 035E0B E2CC C3 ; ; AX ; DX ; CX ; CX,AX ; DX,AX ; DX,DX ; WORD PTR [BP+18]; CX,AX ; WORD PTR [BP+18]; DX CX,DX WORD PTR [BP+1A] DH,DL DL,[BP+24] CH,AL AH,1 AH,1 CL,AH AX,0201 13 CX DX AX 7D7F AX 7D7A DX BX,[BP+0B] 7D4B PUSH PUSH PUSH XCHG XCHG XOR DIV XCHG DIV INC XCHG DIV MOV MOV MOV ROR ROR OR MOV INT POP POP POP JB INC JNZ INC ADD LOOP RET [Libro de los Virus: Virus de BOOT ;-) ] Esta es la rutina de carga, que convierte el nº de sector al formato BIOS (cabeza, cilindro, etc.) Carga 'CX' sectores a partir del número de sector DX:AX y los deja en ES:BX. Requiere que BP=7C00, y DS=0000 DATOS DEL PRINCIPIO DEL SECTOR, CON EL JMP EB3E90 0DBD:7C00 0DBD:7C10 0DBD:7C20 0DBD:7C30 EB 02 81 20 3E 00 16 20 90 02 0E 20 4D 00 00 20 53 00 80 20 57 F8 00 20 49 E2 29 46 4E-34 00-3F E8-6C 41-54 2E 00 27 31 30 40 22 36 00 00 20 20 02 3F 20 20 10 00 20 20 01 00 20 F1 00 00 20 7D .>.MSWIN4.0..... ........?.@.?... ......).l'" FAT16 .} DATOS FINALES, TRAS EL CODIGO. Los dos últimos bytes (AA55) indican al sector de partición que este sector es ejecutable. 0DBD:7D80 0DBD:7D90 0DBD:7DA0 0DBD:7DB0 0DBD:7DC0 0DBD:7DD0 0DBD:7DE0 0DBD:7DF0 03 69 6F 43 20 74 53 00 18 73 FF 61 79 65 59 57 01 74 0D 6D 20 63 53 49 27 65 0A 62 70 6C 4D 4E 0D 6D 45 69 72 61 53 42 0A 61 72 65 65 0D 44 4F 44 20 72 20 73 0A 4F 4F 69-73 69-6E 6F-72 65-6C 69-6F 00-49 53-20 54-20 63 63 20 20 6E 4F 20 53 6F 6F 45 20 65 20 20 59 20 72 2F 64 20 20 53 53 64 72 53 69 75 20 59 00 65 65 FF 73 6E 20 53 00 20 63 0D 63 61 20 80 55 73 74 0A 6F 20 20 01 AA ...'..Disco de s istema incorrect o...Error E/S... Cambie el disco y presione una tecla...IO SYSMSDOS SYS.. .WINBOOT SYS..U.