2010-04-13 18 views
5

Ho lavorato attraverso le esercitazioni on this webpage che crea progressivamente un bootloader che visualizza Hello World.Hello World bootloader non funziona

Il secondo tutorial (in cui cerchiamo di ottenere una "A" da stampare) funziona perfettamente, eppure il primo tutorial non funziona affatto per me! (Il BIOS ignora completamente il dischetto e avvia direttamente in Windows). Questo è meno di un problema, anche se qualsiasi spiegazione sarebbe apprezzata.

Il vero problema è che non riesco a far funzionare il terzo tutorial. Invece di emettere "Hello World", ottengo un carattere insolito (e il cursore lampeggiante) nell'angolo in basso a sinistra dello schermo. Assomiglia un po 'a una faccina dentro un rettangolo arrotondato. Qualcuno sa come far visualizzare Hello World come dovrebbe?

risposta

7

Si dice "avvia direttamente in Windows", quindi presumo che si stia utilizzando un PC fisico. Nota futura da fare: usa sempre un emulatore per lo sviluppo! È solo più facile Mi piace Bochs per OSDeving perché ha delle belle funzionalità di debug. Ora, sulla possibile soluzione.

Esistono numerosi BIOS buggy che interrompono le specifiche informali del PC IBM per l'indirizzo di caricamento 0x7C00.

Questo può dare un sacco di problemi con gli indirizzi di memoria e così ogni volta che si sta assemblando. Quindi, fare l'inizio simile a questa:

[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, alcuni carico a 0x07C0:0000 e la maggior parte del carico (e la sua ritenuto corretto) a 0x0000:7C00. È lo stesso indirizzo piatto, ma le diverse impostazioni del segmento possono rovinare gli indirizzi di memoria assoluti. Quindi cerchiamo di rimuovere la "magia" del assembler e vediamo come si presenta (nota non garantisco indirizzi per essere completamente corrette in questo. Non so le dimensioni di tutti i codici operativi)

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

Così , passiamo a un indirizzo assoluto.

Ora quindi.Cosa succede quando non lo facciamo?

prendere questo programma, ad esempio:

mov ax,[mydata] 
hlt 

mydata: dw 500 ;#just some data 

Questo smonta a qualcosa di simile

mov ax,[0x7C06] 

Oh, beh utilizza indirizzamento assoluto, così come potrebbe andare storto? Bene, cosa succede se DS è in realtà 0x7C0? quindi invece di ottenere l'assembler previsto 0:0x7C06 otterrà 0x7C0:0x7C06 che sono non lo stesso indirizzo piatto.

Spero che questo ti aiuti a capire. È un argomento davvero complicato e richiede un po 'di programmazione di basso livello per comprendere appieno.

+0

Ciao, grazie per la risposta. Sfortunatamente il tuo codice non è sintatticamente corretto in NASM. Mi dice che c'è una mancata corrispondenza nella dimensione dell'operando (??) sulla riga che inizia con "jmp FAR 0x0000 ...". Ancora, grazie per il suggerimento dell'emulatore. – DarkOwl

+0

@Newbie yea la mia sintassi NASM è un po 'arrugginita prova 'jmp word 0: begin' – Earlz

+0

Appena installato Bochs e avviato il codice tutorial originale in esso. La forma del codice ogni esercitazione ora funziona! La domanda è, è il mio BIOS phyiscal che è non standard, o è il codice? (Sicuramente tutti i BIOS compatibili x86 devono rispettare gli stessi standard ???) Proverò comunque il tuo ammendamento sul BIOS fisico del mio PC. – DarkOwl

1

Penso che il problema sia correlato all'origine specificata.

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

Sulla base della conversazione che stiamo facendo sembra che l'indirizzo non sia come previsto in qualche modo. Potrebbe semplicemente essere DS che il registro dei segmenti di dati non è quello che ti aspetti. Si potrebbe effettivamente essere in grado di ottenere l'elenco originale dalla pagina web di lavorare con l'aggiunta di una spinta e pop del ds prima della chiamata per visualizzare la stringa in questo modo,

push cs 
pop ds 

In caso contrario il seguente codice funziona.

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

Questo codice capisce l'offset in fase di esecuzione del codice e in esecuzione anche si assicura DS è il punto allo stesso segmento. A meno che le istruzioni altrimenti note che coinvolgono SI generalmente usano anche DS come loro segmento di codice per fare riferimento alla memoria.

DS è un registro di segmenti e potresti voler leggere qualcosa come lo Art of Assembly per saperne di più.

Earlz sta anche facendo lo stesso genere di cose, solo assicurandosi che i registri siano corretti in modo che l'indirizzo di memoria sia riferito correttamente. È solo che sa più cose specifiche del settore di avvio di me.

+0

Come ho detto, il tutorial 2 funziona correttamente, dimostrando che il BIOS è impostato correttamente per l'avvio da un floppy. È solo quando viene detto di fare NOTHING BUT HANG (tutorial 1) che il BIOS lo ignora. Devo essere sincero, sono nuovo per questa intera cosa del bootloading - questo tutorial è tutto ciò che ho fatto. Supponevo che * stavo caricando tramite il settore di avvio: cosa ti fa pensare che non lo sia? Inoltre, man mano che il tutorial si espande, il programma viene compilato utilizzando la NASM in un file binario non elaborato (non un file COM). Ma darò comunque una tua proposta. – DarkOwl

+0

Vero, ho interpretato male ciò che hai detto. In tal caso, sospetto che l'origine sia ancora la causa del problema, ma è probabile che per capire la vera causa sia necessario stampare l'IP del registro per capire l'origine effettiva. Vedrò se riesco a trovare qualcosa per aiutare. –

+0

OK, ho provato la tua congestione. Non riesco ancora a ottenere "Hello World", ma non ottengo più nemmeno quel carattere insolito. Semplicemente ottengo un cursore lampeggiante verso l'alto a sinistra (a differenza dell'angolo in basso, dove in precedenza si trovava il personaggio insolito). – DarkOwl