2010-04-13 26 views
5

He estado trabajando a través de los tutoriales on this webpage que progresivamente crea un gestor de arranque que muestra Hello World.Hola World bootloader no funciona

El segundo tutorial (donde intentamos obtener una "A") funciona perfectamente, ¡y sin embargo, el primer tutorial no funciona para nada! (El BIOS ignora por completo el disquete y se inicia directamente en Windows). Este es un problema menor, aunque se agradecería cualquier explicación.

El problema real es que no puedo obtener el tercer tutorial para trabajar. En cambio, al generar "Hello World", aparece un carácter inusual (y un cursor parpadeante) en la esquina inferior izquierda de la pantalla. Se parece un poco a una cara sonriente dentro de un rectángulo redondeado. ¿Alguien sabe cómo hacer que Hello World se muestre como debería?

Respuesta

7

Dices "inicia directamente en Windows" así que supongo que estás usando una PC física. Nota futura para hacer: ¡Siempre use un emulador para el desarrollo! Es simplemente más fácil. Me gusta Bochs para OSDeving porque tiene buenas funciones de depuración. Ahora, sobre la posible solución.

Hay muchas BIOS defectuosas que rompen las especificaciones informales de la PC IBM para la dirección de carga 0x7C00.

Esto puede causar muchos problemas con las direcciones de memoria y cosas así durante el montaje. Así que al principio parece a esto:

[BITS 16] ;tell the assembler that its a 16 bit code 
[ORG 0x7C00] ;this tells the assembler where the code will be loaded at when it runs on your machine. It uses this to compute the absolute addresses of labels and such. 

jmp word 0:flush ;#FAR jump so that you set CS to 0. (the first argument is what segment to jump to. The argument(after the `:`) is what offset to jump to) 
;# Without the far jmp, CS could be `0x7C0` or something similar, which will means that where the assembler thinks the code is loaded and where your computer loaded the code is different. Which in turn messes up the absolute addresses of labels. 
flush: ;#We go to here, but we do it ABSOLUTE. So with this, we can reset the segment and offset of where our code is loaded. 
mov BP,0 ;#use BP as a temp register 
mov DS,BP ;#can not assign segment registers a literal number. You have to assign to a register first. 
mov ES,BP ;#do the same here too 
;#without setting DS and ES, they could have been loaded with the old 0x7C0, which would mess up absolute address calculations for data. 

Sede, alguna carga en 0x07C0:0000 y la mayor parte de la carga (y su correcta considerado) a 0x0000:7C00. Es la misma dirección plana, pero las diferentes configuraciones de segmento realmente pueden arruinar direcciones de memoria absolutas. Así que vamos a eliminar la "magia" del ensamblador y ver lo que parece (nota no garantizo direcciones para ser completamente correcta con esto. No sé el tamaño de todos los códigos de operación)

jmp word 0:0x7C04 ;# 0x7C04 is the address of the `flush` label 
... 

por lo , saltamos a una dirección absoluta.

Ahora bien.¿Qué pasa cuando no hacemos esto?

tomar este programa, por ejemplo:

mov ax,[mydata] 
hlt 

mydata: dw 500 ;#just some data 

Esto desmonta a algo así como

mov ax,[0x7C06] 

Oh, así que utiliza el direccionamiento absoluto, así que ¿cómo puede ir mal? Bueno, ¿y si DS es realmente 0x7C0? entonces, en lugar de obtener el ensamblador esperado 0:0x7C06 obtendrá 0x7C0:0x7C06 que son no la misma dirección plana.

Espero que esto lo ayude a comprender. Sin embargo, es realmente un tema complicado y requiere un tiempo de programación de bajo nivel para comprenderlo por completo.

+0

Hola, gracias por la respuesta. Lamentablemente, su código no es sintaxis correcto en NASM. Me dice que hay una discrepancia en el tamaño del operando (??) en la línea que comienza con "jmp FAR 0x0000 ...". Aún así, gracias por agradecer la sugerencia del emulador. – DarkOwl

+0

@Newbie sí, mi sintaxis de NASM es un poco oxidado, intento 'jmp word 0: begin' – Earlz

+0

Acabo de instalar Bochs y arranqué el código de tutorial original en él. ¡El código de cada tutorial ahora funciona! La pregunta es, ¿es mi BIOS phyiscal que no es estándar, o es el código? (¿Seguro que todas las BIOS compatibles con x86 deben cumplir con los mismos estándares?) De todos modos, intentaré su enmienda en el BIOS físico de mi PC. – DarkOwl

1

Creo que el problema probablemente esté relacionado con el origen especificado.

[ORG 0x7C00] ;Origin, tell the assembler that where the code will 

Según la conversación que hemos tenido, parece que la dirección no está pronosticada de alguna manera. Simplemente podría ser que DS el registro del segmento de datos no es lo que espera. En realidad, puede ser capaz de obtener la lista original de la página Web para trabajar mediante la adición de un empujón y el pop de ds antes de la llamada para mostrar la cadena como esta,

push cs 
pop ds 

Si no funciona el siguiente código.

[ORG 0x000] ; switched to 0 since we are going to try to correct it ourself 

call nextinstruction 
nextinstruction: ; get the return address of the call into dx 
pop dx    ; which is essentially the start of the code + 3 (3 bytes for the call instruction) 
MOV SI, HelloString ;Store string pointer to SI 
add si, dx   ; add IP from start of program 
sub si, 3   ; subtract the 3 the call instruction probably took 
push cs 
pop ds    ; make ds the same as cs. 
CALL PrintString ;Call print string procedure 
JMP $  ;Infinite loop, hang it here. 

Este código se da cuenta de la compensación en tiempo de ejecución del código que se está ejecutando y también se asegura de DS es el punto en el mismo segmento. A menos que se indique lo contrario, las instrucciones que involucran SI generalmente también usan DS como su segmento de código para hacer referencia a la memoria.

DS es un registro de segmentos y es posible que desee leer algo como el Art of Assembly para obtener más información.

Earlz también está haciendo el mismo tipo de cosas, simplemente asegurándose de que los registros sean correctos para que la dirección de la memoria se haga referencia correctamente. Es solo que él sabe más sobre los detalles del sector de arranque que yo.

+0

Como dije, el tutorial 2 funciona bien, lo que demuestra que el BIOS está configurado correctamente para arrancar desde un disquete. Solo cuando se le dice que haga NADA PERO HACER (tutorial 1) que el BIOS lo ignora. Tengo que ser honesto, soy nuevo en todo esto de la carga de arranque, este tutorial es todo lo que he hecho. Supuse que * estaba * cargando a través del sector de arranque, ¿qué te hace pensar que no? Además, a medida que el tutorial se expanins, el programa se compila utilizando NASM en un archivo binario sin formato (no un archivo COM). Pero le daré una oportunidad a su sugerencia. – DarkOwl

+0

Cierto, malinterpreté lo que dijiste. En ese caso, sospecho que el origen sigue siendo la causa del problema, pero es probable que averiguar la causa real requiera imprimir el IP del registro para descubrir el origen real. Veré si puedo encontrar algo para ayudar. –

+0

OK, he intentado su sugestión. Todavía no recibo "Hello World", pero tampoco consigo ese personaje de cara inusual. Simplemente tengo un cursor parpadeante hacia la esquina superior izquierda (en oposición a la esquina inferior, donde anteriormente había estado el carácter inusual). – DarkOwl