2010-04-13 5 views
5

J'ai travaillé à travers les tutoriels on this webpage qui crée progressivement un chargeur de démarrage qui affiche Hello World.Hello World bootloader ne fonctionne pas

Le 2ème tutoriel (où nous essayons d'obtenir un "A" à sortir) fonctionne parfaitement, et pourtant le 1er tutoriel ne fonctionne pas du tout pour moi! (Le BIOS ignore complètement la disquette et démarre directement dans Windows). C'est moins un problème, bien que toutes les explications seraient appréciées.

Le vrai problème est que je n'arrive pas à faire fonctionner le 3ème tutoriel. Au lieu de sortir "Hello World", je reçois un caractère inhabituel (et un curseur clignotant) dans le coin inférieur gauche de l'écran. Cela ressemble un peu à un smiley à l'intérieur d'un rectangle arrondi. Est-ce que quelqu'un sait comment afficher Hello World comme il se doit?

Répondre

7

Vous dites "démarrer directement dans Windows" donc je suppose que vous utilisez un PC physique. Note à venir à faire: Toujours utiliser un émulateur pour le développement! C'est juste plus facile. J'aime Bochs pour OSDeving parce qu'il a de jolies fonctionnalités de débogage. Maintenant, sur la solution possible.

Il y a beaucoup de BIOS buggés qui cassent les spécifications informelles du PC IBM pour l'adresse de chargement 0x7C00.

Cela peut donner beaucoup de problèmes avec les adresses de mémoire et autres lors de l'assemblage. Alors faites le début ressembler à ceci:

[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. 

Voir, une charge à 0x07C0:0000 et plus la charge (et son considérée comme propre à) à 0x0000:7C00. C'est la même adresse plate, mais les différents paramètres de segment peuvent vraiment bousiller des adresses mémoire absolues. Donc, nous allons enlever la « magie » de l'assembleur et voir à quoi il ressemble (note que je ne vous garantis adresses être tout à fait correct avec cela. Je ne sais pas la taille de tous les opcodes)

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

Alors , nous sautons à une adresse absolue.

Maintenant alors.Que se passe-t-il lorsque nous ne faisons pas cela?

prendre ce programme par exemple:

mov ax,[mydata] 
hlt 

mydata: dw 500 ;#just some data 

Ce désassemble à quelque chose comme

mov ax,[0x7C06] 

Oh, eh bien, il utilise l'adressage absolu, alors comment pourrait-il aller mal? Eh bien, que si DS est effectivement 0x7C0? alors au lieu d'obtenir l'assembleur prévu 0:0x7C06 il obtiendra 0x7C0:0x7C06 qui sont pas la même adresse plate.

J'espère que cela vous aide à comprendre. C'est vraiment un sujet compliqué et prend un moment de programmation de bas niveau pour bien comprendre.

+0

Salut, merci pour la réponse. Malheureusement, votre code n'est pas syntaxiquement correct dans NASM. Il me dit qu'il y a une discordance dans la taille de l'opérande (??) sur la ligne commençant par "jmp FAR 0x0000 ...". Encore, merci pour le conseil émulateur merci. – DarkOwl

+0

@Newbie yea ma syntaxe NASM est un peu rouillé essayer 'jmp word 0: begin' – Earlz

+0

Juste installé Bochs et a démarré le code tutoriel original en elle. Le code forme chaque tutoriel fonctionne maintenant! La question est, est-ce mon BIOS phyiscal qui est non standard, ou est-ce le code? (Certainement tous les BIOS compatibles x86 doivent se conformer aux mêmes standards ???) Je vais quand même essayer votre amendement sur le BIOS physique de mon PC. – DarkOwl

1

Je pense que le problème est susceptible d'être lié à l'origine spécifiée.

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

D'après la conversation que nous avons eue, il semble que l'adresse ne soit pas prédite d'une manière ou d'une autre. Il se pourrait simplement que DS le registre de segment de données ne soit pas ce que vous attendez. Vous pourriez effectivement être en mesure d'obtenir la liste originale de la page Web pour travailler en ajoutant un coup de pouce et pop ds avant l'appel pour afficher la chaîne comme celui-ci,

push cs 
pop ds 

Sinon le code suivant fonctionne.

[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. 

Ce code devinera le décalage lors de l'exécution du code en cours d'exécution et assure également que DS est le point sur le même segment. Sauf indication contraire, les instructions impliquant SI utilisent généralement DS comme segment de code pour référencer la mémoire. DS est un registre de segment et vous voudrez peut-être lire quelque chose comme le Art of Assembly pour en savoir plus.

Earlz fait également le même genre de chose, en s'assurant simplement que les registres sont corrects afin que l'adresse mémoire soit correctement référencée. C'est juste qu'il en sait plus sur les spécificités du secteur de démarrage que moi.

+0

Comme je l'ai dit, le tutoriel 2 fonctionne bien, prouvant que le BIOS est correctement configuré pour démarrer à partir d'une disquette. C'est seulement quand on lui dit de NE RIEN FAIRE HANG (tutoriel 1) que le BIOS l'ignore. Je dois être honnête, je suis nouveau à tout ce chargement de démarrage - ce tutoriel est tout ce que j'ai fait. J'ai supposé que je * chargeait * via le secteur de démarrage - ce qui vous fait penser que je ne suis pas? En outre, comme le tutoriel expire, le programme est compilé en utilisant NASM dans un fichier binaire brut (pas un fichier COM). Mais je vais quand même essayer votre suggestion. – DarkOwl

+0

C'est vrai, j'ai mal interprété ce que vous avez dit. Dans ce cas, je soupçonne que l'origine est toujours la cause du problème, mais déterminer la cause réelle est susceptible d'exiger l'impression de l'adresse IP du registre pour déterminer l'origine réelle. Je vais voir si je peux trouver quelque chose pour aider. –

+0

OK, j'ai essayé votre suggestion. Je ne reçois toujours pas "Hello World", mais je ne reçois plus ce caractère inhabituel. J'ai simplement un curseur clignotant vers le coin supérieur gauche (par opposition au coin inférieur, où le caractère inhabituel a été précédemment). – DarkOwl