2010-04-13 11 views
5

Pracowałem nad samouczkami on this webpage, które stopniowo tworzą bootloader wyświetlający Hello World.Program rozruchowy Hello World nie działa

Drugi tutorial (gdzie staramy się uzyskać wynik "A") działa idealnie, a jednak pierwszy tutorial w ogóle nie działa dla mnie! (BIOS całkowicie ignoruje dyskietkę i uruchamia się bezpośrednio w systemie Windows). Jest to mniejszy problem, chociaż wszelkie wyjaśnienia byłyby doceniane.

Prawdziwym problemem jest to, że nie mogę uruchomić trzeciego tutoriala. Zamiast wyświetlać "Hello World", otrzymuję niezwykły znak (i ​​migający kursor) w lewym dolnym rogu ekranu. Wygląda trochę jak buźka w zaokrąglonym prostokącie. Czy ktoś wie, jak wyświetlić Hello World, aby wyświetlał się tak, jak powinien?

Odpowiedz

7

Mówisz "bootuj prosto do Windowsa", więc zakładam, że używasz fizycznego komputera. Przyszłe uwagi: Zawsze używaj emulatora do programowania! To po prostu łatwiejsze. Lubię Bochs dla OSDeving, ponieważ ma on dobre funkcje debugowania. Teraz przejdź do możliwego rozwiązania.

Istnieje wiele błędnych BIOSów, które łamią nieformalne specyfikacje komputera IBM dla adresu ładowania 0x7C00.

Może to powodować wiele problemów z adresami pamięci i takimi, ilekroć się montuje. Tak uczynić początek wyglądać następująco:

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

See, pewne obciążenie przy 0x07C0:0000 i największe obciążenia (i jej uznać wypada) przy 0x0000:7C00. Jest to ten sam adres płaski, ale różne ustawienia segmentu mogą naprawdę zepsuć adresy pamięci absolutnej. Warto więc usunąć „magii” w asemblerze i zobaczyć jak to wygląda (należy pamiętać, że nie gwarantują adresy być całkowicie poprawne z tym. Nie wiem, rozmiar wszystkich rozkazy)

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

tak , skaczemy do absolutnego adresu.

Teraz.Co się dzieje, gdy tego nie robimy?

wziąć ten program na przykład:

mov ax,[mydata] 
hlt 

mydata: dw 500 ;#just some data 

ten demontuje się do czegoś podobnego

mov ax,[0x7C06] 

Och, dobrze wykorzystuje adresowanie bezwzględne, tak jak to może się nie udać? A co, jeśli DS faktycznie jest 0x7C0? wtedy zamiast oczekiwać, że asembler będzie oczekiwał 0:0x7C06, otrzyma on 0x7C0:0x7C06, który nie ma takiego samego płaskiego adresu.

Mam nadzieję, że pomoże to zrozumieć. To naprawdę skomplikowany temat, który zajmuje trochę czasu w programowaniu na niskim poziomie, aby w pełni go zrozumieć.

+0

Cześć, dziękuję za odpowiedź. Niestety Twój kod nie jest poprawny pod względem składni w NASM. Mówi mi, że istnieje niedopasowanie wielkości operandu (??) na początku linii "jmp FAR 0x0000 ...". Mimo to, dziękuję za wskazówkę dla emulatora. – DarkOwl

+0

@Newbie tak, moja składnia NASM jest nieco zardzewiała spróbuj 'jmp word 0: begin' – Earlz

+0

Właśnie zainstalowałem Bochs i załadowałem oryginalny kod samouczka do niego. Kod każdego tutoriala działa teraz! Pytanie brzmi, czy to mój BIOS phyiscal jest niestandardowy, czy też jest to kod? (Z pewnością wszystkie BIOSy zgodne z x86 muszą być zgodne z tymi samymi standardami ???). Spróbuję jednak poprawek na fizycznym BIOSie mojego komputera. – DarkOwl

1

Myślę, że problem prawdopodobnie będzie związany z określonym pochodzeniem.

Na podstawie rozmowy, którą prowadziliśmy, okazuje się, że adres nie jest w jakikolwiek sposób przewidywany. Może się zdarzyć, że rejestr segmentów danych DS nie jest tym, czego oczekujesz. Może rzeczywiście być w stanie uzyskać oryginalny wpis ze strony internetowej do pracy poprzez dodanie push i pop DS przed wywołaniem do wyświetlania tekstowej takiego,

push cs 
pop ds 

Jeśli nie następujący kod działa.

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

Kod ten domyśla się przesunięcie w czasie wykonywania istoty uruchomienie kodu, a także dba o DS jest punkt do tego samego segmentu. O ile nie zaznaczono inaczej, instrukcje z udziałem SI na ogół również wykorzystują DS jako swój segment kodu do odniesienia do pamięci.

DS jest rejestrem segmentów i możesz chcieć przeczytać coś takiego, jak Art of Assembly, aby dowiedzieć się więcej.

Earlz również robi to samo, po prostu upewniając się, że rejestry są poprawne, aby poprawnie przywołać adres pamięci. Po prostu wie więcej o specyfice sektora bootowego niż ja.

+0

Jak już powiedziałem, samouczek 2 działa dobrze, co udowadnia, że ​​BIOS jest poprawnie skonfigurowany do uruchamiania z dyskietki. Dopiero wtedy, gdy zostanie powiedziane, aby zrobić NIC, ALE HANG (samouczek 1), BIOS go ignoruje. Muszę być szczery, że jestem nowy w tym całym procesie ładowania - ten samouczek jest wszystkim, co zrobiłem. Zakładam, że * było * ładowanie przez sektor rozruchowy - co sprawia, że ​​myślisz, że nie jestem? Ponadto, jak samouczek się rozwija, program jest kompilowany przy użyciu NASM do surowego pliku binarnego (nie pliku COM). Ale i tak dam ci swoją sugestię. – DarkOwl

+0

To prawda, błędnie zinterpretowałem to, co powiedziałeś. W takim przypadku podejrzewam, że pochodzenie jest nadal przyczyną problemu, ale ustalenie faktycznej przyczyny prawdopodobnie będzie wymagało wydrukowania adresu IP rejestru w celu ustalenia rzeczywistego pochodzenia. Zobaczę, czy uda mi się coś wymyślić. –

+0

OK, próbowałem twojej sugestii. Nadal nie dostaję "Hello World", ale nie dostaję już tej niezwykłej twarzy. Po prostu mrugam kursorem w lewą górną lewą stronę (w przeciwieństwie do dolnego rogu, gdzie wcześniej znajdował się niezwykły znak). – DarkOwl