Hallo Besucher, der Thread wurde 1k mal aufgerufen und enthält 5 Antworten

letzter Beitrag von kinzi am

Offset der Speicheradressierung erklärbar?

  • Hallo!

    Ich wollte wissen ob es möglich ist, jemanden der kein Informatik Studium hat, auf einfache Art und Weise zu erklären wie logische Adressen eines x86 berechnet werden? Vor allem was der"Offset" ist interessiert mich. Ich finde zwar ein paar Sachen aber mein Verstand will nicht so!

    Ich lese immer wieder:

    Adresse = Segment × 16 + Offset


    Verstehe das mit Offset nicht.

    Gibt es eventuell eine Möglichkeit es "einfacher" zu erklären?

    Ich möchte mich nicht damit abfinden es nicht zu verstehen.


    Bedanke mich im voraus.

    Grüße

  • Das Offset ist der "Zeiger" innerhalb des Segments. Also innerhalb des 64k Blocks.

    Oder eben das untere Wort der Adresse.


    Da der 8086 20 Adressleitungen, aber nur 16 Bit Register hat, kann er nicht einfach so eine komplette Adresse speichern.


    Daher Segment (das wird per Hardware mal 16 genommen) und Offset, das dann dazuaddiert wird.


    Ein Segment kann max. 64k (Offset 0 bis FFFF, da 16-Bittig) gross sein, mindestens aber 16 Bytes. Der CPU ist das aber schnuppe.


    Man könnte es auch analog zum c128 sehen. Das Offset ist der normale Adressraum eines 6510, das Segment die 64k Bank. Wenn das einfacher ist. :)

  • Die von dir zitierte Formel "Adresse = Segment x 16 + Offset" ist das in Hardware gegossene Verfahren mit dem eine 8088 oder 8086 CPU aus zwei 16-Bit-Angaben, eben Segment und Offset, eine 20-Bit-Adresse berechnet.


    Die Register in einer 8088 oder 8086 CPU sind nur 16 Bit breit, die CPU hat aber 20 Adreßleitungen und damit einen Adreßraum von 1 MB. Mit 16 Bit könnte sie zunächst mal überhaupt nur 64 KB adressieren, und das wäre dann nicht besser gewesen als die unmittelbaren Vorgänger-CPUs, 8080 bzw. 8085.


    In anderen Computern wurden als Abhilfe immer gleich ganze 64 KB umgeschaltet, das hat z.B. der C128 so gemacht. Wenn man aber für bestimmte Sachen im Speicher gar nicht so viel Platz braucht, ist das etwas verschwenderisch. Die Segmente liegen aber - wenn man das jeweilige Segmentregister um 1 erhöht - jeweils 16 Byte versetzt, damit kann man nun - mit wenig Verschnitt, die Anfangsadresse z.B. einer Datenstruktur auf eine durch 16 Byte teilbare Adresse legen und mit dem Offset adressiert man in diese Datenstruktur hinein.


    So "schön" wie hier gerade beschreiben haben das allerdings nur wenige Programme genutzt. 8088 und 8086 haben ein Code-Segment-Register (CS), ein Stack-Segment-Register (SS) ein Daten-Segment-Register (DS) und ein Extra-Daten-Segment-Register (ES). Meistens haben sich die Programme nicht die Mühe gemacht, die Segment-Register umzusetzen und so wurde der 8088 oder 8086 nur als 16-Bit-CPU mit vier 64 KB Abschnitten gebraucht. Mehr Speicher hatten die ersten PCs auch ohnehin kaum. Im Extremfall wurden sogar alle vier Segmente "aufeinander" gelegt.

  • Das Lustige ist, dass beide Werte 16bit sind. Nur, das Segment bestimmt die gröbere Addressierung (in 16 Byte-Schritten), das Offset die feineren 65535 Bytes. Es gibt daher viele unterschiedlche Segment-/Offset-Werte, die auf die gleiche Adresse zeigen:


    Segment Offset

    $A010 $0000 -> $a0100

    $A000 $0100 -> $a0100


    Das war eine unglaubliche Krätze bei hohen Auflösungen, wenn der Speicher für eine Grafikseite immer nur ausschnittweise (65536 Bytes bei $a0000) eingeblendet werden konnte. Wenn man dann genau um diese Grenzen herum malen musste, war das furchtbar lästige Rechnerei und Bank-Switcherei. Es war ein Segen, als es später die Linear Frame Buffers kamen.


    Lustig #2: Im 32-Bit-Modus gibt es den Segment/Offset-Modus eigentlich auch (damit könnte ein 32-Bit-Prozess mehr als die bekannten 4GB ansprechen). Das wollte sich aber wirklich niemand mehr antun.

  • Code
    1. Adresse = Segment × 16 + Offset
    2. A19 A18 A17 A16 A15 A14 A13 A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A0
    3. S15 S14 S13 S12 S11 S10 S9 S8 S7 S6 S5 S4 S3 S2 S1 S0
    4. O15 O14 O13 O12 O11 O10 O9 O8 O7 O6 O5 O4 O3 O2 O1 O0

    Die resultierenden Adressbits A19..A0, entsprechend dem externen Adressbus des 8086/8088, werden aus den zwei nur 16-Bit breiten Registern für "Segment" (S15...S0) und "Offset" (O15...O0) berechnet.


    Daher sind 0000:FFF0 = 000F:FF00 = 00FF:F000 = 0FFF:0000 .


    (Irgendwann kam übrigens einer drauf, dass man damit sogar 64 kB mehr als 1 MB adressieren kann, da wurde dann das berühmte "A20 Gate" dafür erfunden, um die "High Memory Area" (DOS :winke: ) zu nutzen.)