Wenn der externe Speicher (1 MB) in einem 8086-basierten System in Code, Daten, Stack und Extras unterteilt ist, die alle 64 kB groß sind, was machen wir dann mit dem Rest des Speichers? Wird es verschwendet?
Beim 8086 hat jedes Segment ja 64 KiB. Diese Segmente können sich jedoch bewegen.
Sie setzen einen "Segmentzeiger", der definiert, wo ein Segment beginnt. Er fungiert als Adress-Offset, der zur internen 16-Bit-Adresse des Programmzählers (oder eines anderen Indizierungsregisters) addiert wird.
Das Ändern der Segmentzeiger ist eine triviale Angelegenheit. Obwohl Sie also nur auf 64 KiB gleichzeitig zugreifen können, können Sie dieses 64-KiB-Fenster nach Belieben verschieben, um auf die gesamten 1 MiB Speicherplatz zuzugreifen.
Beachten Sie auch, dass sich diese Segment-Offsets alle 16 Bytes überlappten, da der 8086 ein 20-Bit-Adressierungsschema hatte.
Wenn Sie beispielsweise einen CS bei 0x0010 und einen SS bei 0x0011 hatten, [CS]:[0x0010] = [SS]:[0x0000]
Die Anzahl der Segmente bestimmt den Platz im Speicher. Segment 0 beginnt an der physikalischen 0-Adresse des Speichers. Segment 1 beginnt bei 0x10 Bytes von vorne, Segment 2 bei 0x20 usw.
Ja, Segmente beginnen jeweils mit 0x10 Bytes, sind aber 64k lang, was bedeutet, dass sie sich stark überlappen.
Es gibt Segmentregister: CS (Codesegment), DS (Datensegment), SS (Stapelsegment) und ES (Extrasegment). Byte-Grained-Adressen werden mit Pointer-Registern erhalten: IP (Instruction Pointer), SP (Stack Pointer) und BP (Base Pointer).
Die aktuell ausgeführte Anweisung befindet sich bei CS:IP (Segmentnummer von CS + IP-Bytes-Offset).
Wenn Sie mit Daten arbeiten, ohne das Segment explizit anzugeben, ist DS die Voreinstellung (zumindest in der Notation von Turbo Assembler). Zum Beispiel:
mov cx, [bp]
ist das gleiche wie:
mov cx, ds:[bp]
Ich bin mir über die genaue Syntax nicht sicher (es ist ungefähr 15 Jahre her, seit ich sie verwendet habe).
Sie können einem Segmentregister nicht direkt einen Wert zuweisen. Sie müssen dies über allgemeine Register tun, z.
mov ax, 100h
mov ds, ax
Um also ein Wort von der physikalischen Adresse 0x105 in BX zu laden, können Sie dies folgendermaßen tun:
xor ax, ax ; equal to mov ax, 0 but faster
mov ds, ax
mov ax, 105h
mov bx, [ax]
oder durch Verwendung eines anderen Segments:
mov ax, 10h
mov ds, ax
mov ax, 5
mov bx, [ax]
ds
voreingestellt ist – es ist die Art und Weise, wie der Befehlssatz funktioniert. Wenn Sie nämlich Segment überschreiben, generiert der Assembler das entsprechende Segment-Überschreibungspräfix, andernfalls generiert er Anweisungen ohne Präfix, und dies macht effektiv den ds
Standardwert (für Anweisungen, die diesem Prinzip gehorchen).ax
ist Ihre Verwendung von fehlerhaft. Es gibt keinen solchen Adressierungsmodus wie [ax]
. Sie können entweder [eax]
beginnend mit i386 verwenden oder sind auf [bx+si]
, [bx+di]
, [bp+si]
, [bp+di]
, [si]
, [di]
, [bp]
, beschränkt [bx]
.
Chris Stratton
Majenko
Herr Lister