2017-11-17 7 views
1

Ich habe einen grundlegenden Bootloader in Assembly gemacht, aber es springt nicht wirklich zum Kernel. Es sagt nur "Booten ...". Ich bin mir sicher, dass es nur ein dummer Fehler ist, den ich gemacht habe, wie an den falschen Ort zu springen. Es sollte eine Ausgabe wie "Booting ... Loaded!" Angezeigt werden. Ich habe auch versucht, es vor dem Laden auf 0 zu setzen, aber selbst das funktioniert nicht. Hier ist mein Code:Assembly Bootloader wird nicht zum Kernel springen

mov ax, 9ch 
mov ss, ax 
mov sp, 4096d 
mov ax, 7c0h 
mov ds, ax 
mov es, ax 

xor ah, ah 
int 13h 

clc 

mov si, msg2 
call print 

mov ah, 02h 
xor ax, ax 
mov es, ax 
mov bx, 0x7E00 
mov al, 1h 
mov ch, 0 
mov cl, 2h 
mov dh, 0 
int 13h 

jc error 

jmp 0x7E00 

mov si, msg3 
call print 

error: 
mov si, msg 
call print 
hlt 

print: 
lodsb 
cmp al, 0 
jz done 
mov ah, 0eh 
int 10h 
jmp print 
done: 
ret 

msg db "An error occured!!", 0 
msg2 db "Booting...", 0 
msg3 db "Did not jump to kernel correctly!" 

times 510-($-$$) db 0 
dw 0xAA55 

mov si, msgloaded 
call printl 
jmp $ 

printl: 
lodsb 
cmp al, 0 
jz donel 
mov ah, 0eh 
int 10h 
jmp print 
donel: 
ret 

msgloaded db "Loaded!", 0 

times 0x400-($-$$) db 0 

Alle Hilfe wird geschätzt. Ich werde jedem danken, der mir helfen kann. Vielen Dank!

+0

Vielleicht, weil Sie nicht einmal einen Sprung zum Kernel haben? – Jester

+0

Hoppla. Muss das versehentlich beim Kopieren in die Box gelöscht haben. Es tut uns leid. – programmer

+0

Auch Ihr 'int 13h' Anruf ist offensichtlich an der falschen Stelle (vor dem Einrichten der Argumente) ** und ** es lädt die Daten an die falsche Stelle. – Jester

Antwort

3

Für High-Level-Sprachen gibt es viele Hinweise darauf, was der Programmierer in den Strukturschleifen enthalten wollte, wie Variablennamen gewählt wurden, definiert/enums, etc .; und es ist einfach, wartbaren Code ohne Kommentare zu schreiben.

Für die Assemblersprache gibt es keine gut gewählten Variablennamen und keine Variablentypen (zB ax sagt dem Leser nicht, ob es ein Zeiger auf eine Zeichenfolge oder eine Giraffenhöhe ist oder ...), Anweisungen zeigen oft nicht die Absicht (zB lea könnte verwendet werden, um mit einer Konstanten zu multiplizieren und könnte nicht verwendet werden, um eine effektive Adresse zu laden), Kontrollfluss ist viel flexibler (zB so etwas wie ein do(condition1) { } while(condition2) ist völlig in Ordnung) und goto (sowohl jmp und bedingte Verzweigungen wie jc) werden oft benutzt.

Aus diesem Grund verwendet eine gut geschriebene/wartbare Assemblersprache viele Kommentare. Genauer gesagt, verwenden Sie Kommentare auf der rechten Seite, um Ihre Absichten zu beschreiben. Auf diese Weise können Sie überprüfen, ob die Absichten korrekt sind, indem Sie Kommentare lesen, und dann prüfen, ob die Absicht korrekt implementiert wurde, indem Sie die Anweisung in jeder Zeile mit ihrem Kommentar vergleichen. Es macht es viel einfacher, Fehler zu vermeiden und Fehler viel leichter zu finden.

Hier ist die erste Hälfte des Codes mit Kommentaren:

;Memory Layout 
; 
; 0x009C:0x1000 = 0x000019C0 = stack top 
; 0x07C0:0x0000 = 0x00007C00 = load address 
; 0x0000:0x7E00 = 0x00007E00 = kernel address 

%define STACK_SEGMENT  0x009C 
%define STACK_TOP_OFFSET 0x1000 
%define LOAD_SEGMENT  0x07C0 
%define KERNEL_SEGMENT  0x0000 
%define KERNEL_OFFSET  0x7E00 

;_______________________________________________ 

;Entry point 
; 
;Input 
; dl = BIOS boot device number 

    mov ax, STACK_SEGMENT 
    mov ss, ax 
    mov sp, STACK_TOP_OFFSET 
    mov ax, LOAD_SEGMENT 
    mov ds, ax 
    mov es, ax 

;Reset disk system 
; 
;Note: This should be completely unnecessary. We know the BIOS 
;  disk services are working correctly and don't need 
;  to be reset because the BIOS just used it successfully 
;  to load this code into memory. 

    xor ah, ah   ;ah = BIOS "reset disk system" function number 
    int 13h    ;Call BIOS disk services 
    clc     ;Unnecessary 

;Display welcome message 

    mov si, msg2 
    call print 

;Load kernel from disk 
; dl = BIOS boot device number 

    mov ah, 02h   ;ah = BIOS "read sectors" function number 
    xor ax, ax   ;ax = KERNEL_SEGMENT 
    mov es, ax 
    mov bx, KERNEL_OFFSET ;es:bx = address to load kernel 
    mov al, 1h   ;al = number of sectors to read 
    mov ch, 0    ;ch = cylinder number for first sector 
    mov cl, 2h   ;cl = sector number for first sector 
    mov dh, 0    ;dh = head number for first sector 
    int 13h    ;Call BIOS disk services 

    jc error    ;Handle error if there was one 

;Pass control to "kernel" 

    jmp KERNEL_SEGMENT:KERNEL_OFFSET 

Hier ist der Teil, der Ihre Fehler offensichtlich macht:

      ;ah = BIOS "read sectors" function number 
          ;ax = KERNEL_SEGMENT 

Im Wesentlichen richtig, wenn Sie kommentierten Code, würden Sie haben bemerkte, dass das Laden KERNEL_SEGMENT in ax die BIOS-Funktionsnummer überschreibt (die in den höchsten 8 Bits von ax war). Dies bewirkt, dass dieser Codeabschnitt die BIOS-Funktion "Festplattensystem zurücksetzen" aufruft und überhaupt nichts von der Festplatte lädt. Wenn es zu dem Punkt springt, an den der Kernel später geladen werden sollte (aber nicht war), ist dieser Speicher wahrscheinlich noch voll von Nullen, weil er nicht benutzt wurde, aber voller Nullen wird als add Anweisungen von der CPU dekodiert. so führt die CPU glücklich die add Anweisungen seit Jahren aus.

Hinweis: Es gibt einen anderen (nicht verwandten) Fehler - Ihr Code zum Drucken von Zeichenfolgen verwendet lodsb, die vom Richtungsflag abhängt; Aber Sie tun keine cld Anweisung, um das Richtungsflag zu setzen, also abhängig vom (undefinierten) Zustand, in dem das BIOS dieses Flag zurückließ, könnte es stattdessen Müll drucken.

+0

'0x07C0: 0x0000 = 0x00007C00 = Adresse laden '-> nein, hängt vom BIOS ab. Und das '0000: 7C00' ist viel häufiger, aber immer noch startet ein robust genug Bootloader immer mit weitem Sprung, um" cs: ip "auf den erwarteten Zustand zu" normalisieren ". – Ped7g

+0

Also, was muss ich tun? Ich habe versucht, ah direkt vor dem Int 13h Anruf, aber selbst das funktioniert nicht. – programmer

+0

@ Ped7g: Ja, und nein. Nichts in diesem Code hängt tatsächlich von 'CS' ab (und es sollte immer noch gut funktionieren, wenn BIOS stattdessen '0x0000: 0x7C00' verwendet); und dieser Kommentar (und die% define) dokumentieren die Absicht, die für Daten verwendet wurde/wird (z. B. DS, die geladen wird und zum Drucken von Zeichenfolgen verwendet wird). Ein 'jmp LOAD_SEGMENT: start' wäre schön (und könnte zukünftige Fehler vermeiden). – Brendan

Verwandte Themen