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.
Vielleicht, weil Sie nicht einmal einen Sprung zum Kernel haben? – Jester
Hoppla. Muss das versehentlich beim Kopieren in die Box gelöscht haben. Es tut uns leid. – programmer
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