2009-11-17 7 views

Antwort

37

auf einer 16-Bit x86 segmentierten Speicherarchitektur, werden vier Register verwendet, um die jeweiligen Segmente zu verweisen:

  • DS → Datensegment
  • CS → Codesegment
  • SS → Stapelsegment
  • ES → Extra Segment

Eine logische Adresse auf dieser Architektur segment:offset geschrieben. Um jetzt die Frage zu beantworten:

  • Nahzeiger beziehen sich (als Offset) auf das aktuelle Segment.

  • Far Pointer verwenden Segmentinformationen und einen Offset, um über Segmente hinweg zu zeigen. Um sie zu verwenden, müssen DS oder CS auf den angegebenen Wert geändert werden, der Speicher wird dereferenziert und dann der ursprüngliche Wert von DS/CS wiederhergestellt. Beachten Sie, dass die Zeigerarithmetik für sie den Segmentteil des Zeigers nicht verändert, sodass das Überlaufen des Offset es nur umschließt.

  • Und dann gibt es riesige Zeiger, die normalisiert sind, um das höchstmögliche Segment für eine gegebene Adresse zu haben (im Gegensatz zu fernen Zeigern).

  • Auf 32-Bit- und 64-Bit-Architekturen verwenden Speichermodelle Segmente oder gar nicht.

    +3

    Dies wäre klarer, wenn Sie erklären, was ein Segment (und ein Offset bei einem) ist. "Segmente", wie sie von DOS verwendet werden, sind ein wenig geheimnisvoll, imho. – quark

    21

    Ferne und nahe Zeiger wurden in alten Plattformen wie DOS verwendet.

    Ich glaube nicht, dass sie in modernen Plattformen relevant sind. Aber Sie können über sie lernen here und here (wie von anderen Antworten hingewiesen). Grundsätzlich ist ein Zeiger eine Möglichkeit, den adressierbaren Speicher in einem Computer zu erweitern. I.E. adressieren mehr als 64k Speicher in einer 16-Bit-Plattform.

    +1

    Ich glaube, dass einige Betriebssysteme auf mehr als 4 GB Speicher auf einem 32-Bit-System zugreifen können. In diesem Fall sind solche erweiterten Zeigertypen notwendig. Es ist jedoch selten, dass das Betriebssystem Anwendungen im Benutzermodus Zugriff auf mehr als 4 GB in einer solchen Umgebung ermöglicht. –

    +0

    Ja. Dies liegt daran, dass der physikalische x86-Adressbus 36 Bit breit für 32-Bit-Maschinen ist. Der logische Adressraum ist jedoch immer noch auf 32 Bit beschränkt. Die PAE-Erweiterungen stellen den "zusätzlichen" Speicher zur Verfügung (in der Tat mittels Bankswitching, IIRC). Das eigentliche Problem ist, dass die MMU mehr oder weniger herausgehalten wird (keine mmap, COW, usw.). Aber der Speicher kann als Diskettenspeicher für Apps verwendet werden, die ihre eigene Pufferung durchführen. Oder das Betriebssystem, das die Bank- und MMU-Manipulation übernimmt. – wildplasser

    +0

    PAE verwendet zusätzliche Bits in dem PTE der MMU, um vier zusätzliche Bits von Seitenrahmeninformationen zu adressieren. Es gibt keine Bank, die zu meinem Wissen wechselt. –

    3

    Ein Zeiger hält grundsätzlich Adressen. Wie wir alle wissen, ist Intel Speicherverwaltung in 4 Segmente unterteilt. Wenn also eine Adresse, auf die ein Zeiger zeigt, innerhalb desselben Segments liegt, handelt es sich um einen Near-Zeiger. Daher werden nur 2 Bytes für den Offset benötigt. Auf der anderen Seite, wenn ein Zeiger auf eine Adresse zeigt, die außerhalb des Segments (das heißt in einem anderen Segment) ist, dann ist dieser Zeiger ein Far-Zeiger. Es besteht aus 4 Bytes: zwei für das Segment und zwei für den Offset.

    +1

    Willkommen bei StackOverflow. Wenn Sie eine Frage wie diese vor ein paar Jahren mit einer akzeptierten Antwort mit einer ordentlichen Anzahl von Upstimmen sehen, ist es sicherlich noch erlaubt, die Frage zu beantworten, aber Sie werden wahrscheinlich nur dann Up-Stimmen erhalten, wenn Sie Die Antwort ist gut geschrieben und liefert genaue neue Informationen, die keine der anderen Antworten bietet. Ich bin mir nicht sicher, ob deine Antwort diesen Standard erfüllt. –

    +0

    "Intel Speicherverwaltung ist in 4 Segmente unterteilt"? Es kann 4 Segmentregister geben (ich bin nicht sicher), aber es gibt viel mehr als 4 Segmente. Sie haben nicht wirklich erklärt, wie dies bei einem 16-Bit-System funktioniert, bei dem Segmente und Offsets erforderlich waren. Sie sollten dann 32-Bit-Systeme abdecken und angeben, ob 64-Bit-Systeme wesentlich andere (im Gegensatz zu nur größeren) Eigenschaften aufweisen. –

    0

    Vier Register werden verwendet, um auf vier Segmente in der 16-Bit-x86-Architektur mit segmentierten Speichern zu verweisen. DS (Datensegment), CS (Codesegment), SS (Stapelsegment) und ES (zusätzliches Segment). Eine logische Adresse auf dieser Plattform ist Segment: Offset, in Hexadezimal.

    Nahzeiger beziehen sich (als Offset) auf das aktuelle Segment.

    Far Pointer verwenden Segmentinformationen und einen Offset, um über Segmente hinweg zu zeigen. Um sie zu verwenden, müssen DS oder CS auf den angegebenen Wert geändert werden, der Speicher wird dereferenziert und dann der ursprüngliche Wert von DS/CS wiederhergestellt.Beachten Sie, dass die Zeigerarithmetik für sie den Segmentteil des Zeigers nicht verändert, sodass das Überlaufen des Offset es nur umschließt.

    Und dann gibt es riesige Zeiger, die normalisiert sind, um das höchstmögliche Segment für eine gegebene Adresse zu haben (im Gegensatz zu fernen Zeigern).

    Bei 32-Bit- und 64-Bit-Architekturen verwenden Speichermodelle Segmente oder nicht.

    +0

    Nun, diese Register werden tatsächlich für verschiedene Zwecke verwendet. Wie Sie selbst erwähnt haben, registriert sich CODE, DATA, STACK, EXTRA. Natürlich gibt es AX, BX, DX, CX auch. Aber CS war für CODE, DS war für DATA, SS war für Stack und ES - um bestehende Daten- und Code-Variablen zu erweitern. AX/BX/CX/DX in DOS Zeiten war sehr wichtig. Wie jedes andere Register. Wenn Interrupt-Funktionen (INT) aufgerufen wurde, verließen sich viele von ihnen auf tatsächliche Registrierungswerte. –

    0

    Gut in DOS war es irgendwie lustig mit Registern zu tun. Und Segmente. Alles über maximale Zählkapazitäten von RAM.

    Heute ist es ziemlich irrelevant. Alles, was Sie lesen müssen, ist der Unterschied zwischen virtuellem/Benutzerbereich und Kernel.

    Seit win nt4 (als sie Ideen von * nix gestohlen haben) begannen Microsoft-Programmierer, sogenannte User/Kernel-Speicherbereiche zu verwenden. Und seither den direkten Zugriff auf physikalische Controller vermieden. Seitdem wurde ein Problem gelöst, das auch den direkten Zugriff auf Speichersegmente betrifft. - Alles wurde R/W durch OS.

    Aber wenn Sie darauf bestehen, zu verstehen und zu manipulieren weit/nahe Zeiger betrachten Linux Kernel-Quelle und wie es funktioniert - Sie werden neuer kommen, denke ich.

    Und wenn Sie noch CS (Code Segment)/DS (Datensegment) in DOS verwenden müssen. Schauen Sie sich diese:

    https://en.wikipedia.org/wiki/Intel_Memory_Model http://www.digitalmars.com/ctg/ctgMemoryModel.html

    Ich möchte perfekte Antwort darauf hinweisen, unten .. von Lundin. Ich war zu faul, um richtig zu antworten. Lundin gab eine sehr detaillierte und sinnvolle Erklärung "Daumen hoch"!

    20

    Da niemand DOS erwähnt, vergessen wir alte DOS-PC-Computer und betrachten dies aus einer allgemeinen Sicht. Dann wird sehr vereinfacht, geht es wie folgt:


    Jede CPU einen Datenbus aufweist, der die maximale Datenmenge ist die CPU in einem einzelnen Befehl verarbeiten kann, das heißt gleich der Größe seiner Register. Die Datenbusbreite wird in Bits ausgedrückt: 8 Bits oder 16 Bits oder 64 Bits usw. Hier kommt der Begriff "64-Bit-CPU" her - es bezieht sich auf den Datenbus.

    Jede CPU hat einen Adressbus, auch mit einer bestimmten Busbreite, ausgedrückt in Bits. Jede Speicherzelle in Ihrem Computer, auf die die CPU direkt zugreifen kann, hat eine eindeutige Adresse. Der Adressbus ist groß genug, um den gesamten adressierbaren Speicher abzudecken, den Sie haben.

    Zum Beispiel, wenn ein Computer 65536 Byte Speicher verfügt, können Sie diese mit einem 16-Bit-Adressbus decken, 2^16 = 65536

    Meistens, aber nicht immer, die Datenbusbreite ist so breit wie die Adreßbusbreite. Es ist schön, wenn sie dieselbe Größe haben, da sie sowohl den CPU-Befehlssatz als auch die dafür geschriebenen Programme übersichtlicher halten. Wenn die CPU eine Adresse berechnen muss, ist es praktisch, wenn diese Adresse klein genug ist, um in die CPU-Register zu passen (bei Adressen oft als Indexregister bezeichnet).

    Die nicht standardmäßigen Schlüsselworte far und near werden verwendet, um Zeiger auf Systemen zu beschreiben, bei denen der Speicher über die normale Busbreite der CPU-Adresse hinaus adressiert werden muss.

    Zum Beispiel könnte es für eine CPU mit 16-Bit-Datenbus zweckmäßig sein, auch einen 16-Bit-Adreßbus zu haben. Aber derselbe Computer benötigt möglicherweise auch mehr als 2^16 = 65536 Bytes = 64 KB adressierbarer Speicher.

    Die CPU wird dann in der Regel spezielle Anweisungen (die etwas langsamer sind), die es ermöglicht, Speicher jenseits dieser 64 KB adressieren. Zum Beispiel kann die CPU ihre großen Speicher in nSeiten teilt (auch manchmal Bänke, Segmente und andere solche Begriffe, dass eine andere Sache von einer CPU zu einem anderen bedeuten könnten), wo jede Seite 64kb ist. Es wird dann ein "Seiten" -Register haben, das zuerst gesetzt werden muss, bevor der erweiterte Speicher adressiert wird. In ähnlicher Weise wird es besondere Anweisungen beim Aufrufen/Zurückgeben von Unterroutinen im Erweiterungsspeicher haben.

    Damit ein C-Compiler die korrekten CPU-Anweisungen für den erweiterten Speicher generiert, wurden die nicht standardmäßigen Schlüsselwörter near und far erfunden. Nicht-Standard, da sie nicht durch den C-Standard spezifiziert sind, aber sie sind de facto Industriestandard und fast jeder Compiler unterstützt sie in irgendeiner Weise.

    far bezieht sich auf Speicher, der sich im erweiterten Speicher befindet, über die Breite des Adressbusses hinaus. Da es sich auf Adressen bezieht, verwenden Sie es am häufigsten beim Deklarieren von Zeigern. Zum Beispiel: int * far x; bedeutet "Gib mir einen Zeiger, der auf erweiterten Speicher zeigt". Und der Compiler wird dann wissen, dass er die speziellen Anweisungen erzeugen sollte, die benötigt werden, um auf diesen Speicher zuzugreifen. In ähnlicher Weise erzeugen Funktionszeiger, die far verwenden, spezielle Anweisungen, um zu dem Erweiterungsspeicher zu springen oder von diesem zurückzukehren. Wenn Sie nicht far verwenden, dann würden Sie einen Zeiger auf den normalen, adressierbaren Speicher bekommen, und Sie würden auf etwas völlig anderes zeigen.

    near ist hauptsächlich für Konsistenz mit far enthalten; Es bezieht sich auf alles im adressierbaren Speicher, was einem regulären Zeiger entspricht. Es ist also hauptsächlich ein nutzloses Schlüsselwort, abgesehen von einigen seltenen Fällen, in denen Sie sicherstellen möchten, dass der Code innerhalb des adressierbaren Standardspeichers abgelegt wird. Sie könnten dann etwas explizit als near bezeichnen. Der typischste Fall ist Low-Level-Hardware-Programmierung, wo Sie Interrupt-Service-Routinen schreiben. Sie werden hardwaremäßig von einem Interruptvektor mit fester Breite aufgerufen, der der Adreßbusbreite entspricht. Das bedeutet, dass die Interrupt-Service-Routine im standardmäßigen adressierbaren Speicher sein muss.


    Die berühmteste Verwendung von far und near ist vielleicht der erwähnten alte MS DOS-PC, der heute als sehr alt und deshalb von mildem Interesse angesehen wird.

    Aber diese Schlüsselwörter existieren auch auf moderneren CPUs! Vor allem in Embedded-Systemen, wo sie für so ziemlich jede 8- und 16-Bit-Mikrocontroller-Familie auf dem Markt existieren, da diese Mikrocontroller typischerweise eine Adreßbusbreite von 16 Bit, aber manchmal mehr als 64kb Speicher haben.

    Wenn Sie eine CPU haben, in der Sie Speicher über die Adressbusbreite hinaus adressieren müssen, benötigen Sie far und near. Im Allgemeinen sind solche Lösungen jedoch verpönt, da es ziemlich mühsam ist, auf sie zu programmieren und immer den erweiterten Speicher in Betracht zu ziehen.

    Einer der Hauptgründe, warum der 64-Bit-PC entwickelt wurde, war der, dass die 32-Bit-PCs an den Punkt kamen, an dem die Speicherbelegung das Adreßbuslimit erreichte 4 GB RAM. 2^32 = 4,29 Milliarden Bytes = 4 GB. Um die Verwendung von mehr RAM zu ermöglichen, mussten die Optionen entweder auf eine aufwändige erweiterte Speicherlösung wie in den DOS-Tagen zurückgreifen oder die Computer einschließlich ihres Adressbusses auf 64 Bit erweitern.

    +0

    Große Antwort! Sehr informativ. –

    +0

    "verwendet, um Zeiger auf Systemen zu beschreiben, in denen Sie Speicher adressieren müssen, der über die normale Busbreite der CPU-Adresse hinausgeht" - nein, der 8086 hatte einen 20-Bit-Adressbus. Bei der Speichersegmentierung wurden größere Adressen generiert, ohne die Zeigergröße zu vergrößern. "Hier kommt der Begriff" 64 Bit CPU "her - er bezieht sich auf den Datenbus." - Nein, es bezieht sich auf die Breite des Integer-Registers. Datenbusse sind normalerweise breiter, wobei der L1-Cache ein SIMD-Register von 128 Bits laden kann und höhere Ebenen der Speicherhierarchie noch breiter sind. Adressbusse sind in der Regel schmaler; die MMU hat möglicherweise keinen physikalischen 64-Bit-Adressraum. – Potatoswatter

    Verwandte Themen