AW: [ASSEMBLER] Interrupt in Interrupt Tabelle einfügen
Hab's aber trotzdem noch so umgebastelt, dass das jetzt in der zweiten Zeile steht. Ist einfach optisch schöner. Woher hast du eigentlich das mit den 160+ gewusst? Ausprobiert? Oder ist eine Zeile im VMWare Player standardmäßig 160 Zeichen (0 bis 159) lang?
Das war mehr oder weniger geraten. 80 Spalten x 25 Zeilen ist so mehr oder weniger Standard-Textmodus. Und da der Videospeicher auch nur ein (großes) Array ist, habe ich es einfach mal nach der Formel (zeile * 80 + spalte) versucht, wobei zeile = 1 und spalte = 0 -> 80. Da aber nach jedem Zeichen-Byte noch so ein Options-Byte (Farbe) kam, musste ich das ganze noch mit 2 multiplizieren. So bin ich auf die 160 gekommen.
1. Wie ergibt sich die blau markierte Binärzahl? In dezimal ergibt das 31, aber das sagt mir jetzt auch nicht mehr. Von diesem Wert kommt die weiße Schrift auf blauem Hintergund, soviel weiß ich. Aber wie genau? Ich habe hier nur das als "Erklärung":
Du hast immer ein Byte für das Zeichen und ein Byte für Darstellungsoptionen. In dem zweiten Byte ist unter anderem die Vorder- und Hintergrundfarbe bitweise kodiert (als Rotanteil R, Grünanteil G und Blauanteil B). Das ist in dem Bild eigentlich ganz gut zu erkennen.
2. Wieso brauche ich in der boot.asm beim Ausgabeteil manchmal Hex-Werte für den Offset (z.B.: mov byte [es:0x0B], 00011111b) und hier in der sect2.asm konnte ich das jetzt ganz normal von 160 bis 171 runterschreiben? Oder ist eh das auch irgendwie Hex und ich seh's nicht?
Das sind alles nur Zahlen. Der CPU ist es egal, ob du die nun Dezimal, Hex oder Binär hinschreibst - zumindest wenn sie den gleichen Wert darstellen. Es macht z. B. keinen Unterschied, ob ich 0x02, 2 oder 10b schreibe. Die Angabe der Binärzahl soll hier vielmehr verdeutlichen, welche Flags des Darstellungsbytes gesetzt sind (schreib mal die Bitfolge unter die roten Kästchen in dem Bild, da siehst du dann, welche Flags gesetzt sind).
3. Wie komme ich auf all das hier:
Code:
mov ah,0x02
mov al,1
mov ch,0
mov cl,2
mov dh,0
mov dl,0
mov bx,0
Du hast zwar irgendwo mal als Kommentar geschrieben "Lesekopf setzen" und dergleichen, aber ganz klar ist mir das trotzdem nicht.
Hier kann ich mir zumindest anschauen, welche Register (?) nötig sind, um einen Sektor von einem Laufwerk zu lesen, aber wie komme ich auf die Zahlen? Und wo kommt das ch und cl her und was ist das?
Dazu musst du wissen, wie zum Beispiel eine Diskette aufgebaut ist. Normalerweise müsste man die Grenzen dieser Zahlen auch programmtechnisch ermitteln. Es gab ja schließlich Disketten in unterschiedlichen Größen und deshalb auch unterschiedlicher Geometrie (das ist der Fachbegriff dafür). Bei Festplatten ist die ganze Sache ähnlich (Zylinder, Köpfe, Sektoren [CHS] schon mal gehört?).
Wie kommt man nun zu CL/CH? Da wir im 16 Bit Realmode arbeiten, gibt es nur 16 Bit große Register, z. B. AX, BX, CX, DX. Das sind die sog. General Purpose Register. Du kannst aber jeweils auf die oberen und unteren 8 Bit getrennt zugreifen. So enthält CH die oberen 8 Bit und CL die unteren. Das sind aber keine separaten Register, wenn du CL/CH änderst, ändert sich auch der Wert in CX beispielsweise. Im 32 Bit Modus gibt es dann wieder größere Register (z. B. EAX, EBX, ECX, EDX), bei denen das ähnlich funktioniert. CX sind dann die unteren 16 Bit aus ECX, CL die unteren 8 aus CX. Es gibt hier allerdings keinen Registernamen für die oberen 16 Bit.
4. Wir haben noch einen Übungsblock vor uns, wo wir wahrscheinlich wieder 4 so "kleine" Aufgaben erledigen müssen. Kannst du mir irgendwas empfehlen, das ich mir durchüberlegen sollte, um da ein Bisschen mehr Verständnis für das ganze Register/Assembler-Zeug zu entwickeln? Wie/Wo hast du das gelernt, wenn man fragen darf?
Hilfreich ist auf jeden Fall auch das NASM Handbuch. Anders als bei Hochsprachen wie C gibt es teils große Unterschiede zwischen den einzelnen Assemblern. Die Grundsyntax der Mnemonics (so heißen diese Befehle wie mov, push, int) ist meist ähnlich, aber das drumherum variiert stark (Makro-Funktionen, if-else-Konstrukte, Schleifen, ...). Deshalb ist das Portieren von Code, der in Assembler 1 geschrieben wurde, nach Assembler 2 eine mitunter ziemlich frustrierende und langwierige Aufgabe. Eigentlich ist ziemlich viel, was mit Assembler zu tun hat, frustrierend und langwierig

Allein wenn du für eine andere CPU-Architektur entwickelst, kannst du oft einfach alles neu schreiben. Bei C ist das alles einfacher
Das
hier ist ein ganz gutes (Linux-)Tutorial zu Assemblerprogrammierung. Vor allem weil der Autor auch mit NASM arbeitet, was aus dem oben genannten Grund für dich sicherlich einfacher sein wird. Da lernst du jetzt zwar nicht, wie du ein Betriebssystem schreibst, aber die ASM Grundlagen werden meiner Meinung nach ganz gut rübergebracht.
Ich habe mir mein Wissen selbst angeeignet (wie eigentlich alle meine Programmierfertigkeiten). Vor ein paar Jahren habe ich mich mal intensiver mit OS Entwicklung beschäftigt. Mit Assembler hatte ich aber vorher schon öfters gearbeitet. Es ist halt alles etwas mühselig, aber nunja, Übung macht den Meister

Wobei ich jetzt nicht sagen würde, ich könnte fließend Assemblercode schreiben - geschweige denn guten (was noch mal ein ganz anderes komplexes Thema ist). Lesen klappt aber eigentlich ganz gut. Es ist halt wirklich low-level und nicht so abstrakt wie eine höhere Programmiersprache.