Hallo Besucher, der Thread wurde 4,6k mal aufgerufen und enthält 30 Antworten

letzter Beitrag von Zirias/Excess am

Port-Befehl in C

  • Ich habe jetzt mal ein anderes HI-TECH-C genommmen von hier 2x dsk d71
    http://www.zimmers.net/anonftp/pub/cpm/unsorted/index.html
    Habe beide auf eine d81 gepackt.


    Jetzt funktioniert es mit dem outp.


    gruss

  • C selbst kennt keinen Portbefehl weil es das Konzept von I/O-Ports nicht in gleicher Form auf jedem Rechner gibt.

    Die Begründung würde ich nicht ganz so stehen lassen: C versucht ja gerade, von Unterschieden zwischen verschiedenen Maschinen zu abstrahieren. Sehr viele Maschinen-Details sind bewusst völlig offen gehalten.


    Allerdings hat man trotzdem ein paar wenige Dinge festgelegt, vermutlich um die Sprache simpel zu halten -- eine dieser Festlegungen ist: Es gibt genau einen Adressraum. Dessen Layout ist zwar komplett frei (der darf "Löcher" haben, oder sogar Überlappungen, wie bei segmentierter Adressierung), aber es gibt eben nur einen. "Port I/O" passt da leider nicht dazu, da die I/O Ports in einem separaten Adressraum liegen. Deshalb muss man entweder auf inline Assembly oder auf implementierungsspezifische Erweiterungen zurückgreifen. Das äquivalente Problem ergibt sich bei der Programmierung auf Harvard-Architekturen, mit separatem Adressraum für Programm und Daten.


    MMIO ("memory mapped") dagegen, wie auf dem C64, wird von C direkt unterstützt, da I/O hier in den einen Adressraum integriert ist. Die nötige Garantie, dass Zugriffe auf jeden Fall durchgeführt werden, erhält man mit volatile (MMIO war ein Grund, volatile überhaupt einzuführen).


    tl;dr der Grund ist vermutlich nicht, dass sich I/O-Ports, wenn vorhanden, von Maschine zu Maschine unterscheiden -- von anderen Unterschieden wird schließlich auch abstrahiert. Der Grund ist eine schlichte Designentscheidung der Sprache: Ein Adressraum :)

  • Die Begründung würde ich nicht ganz so stehen lassen: C versucht ja gerade, von Unterschieden zwischen verschiedenen Maschinen zu abstrahieren. Sehr viele Maschinen-Details sind bewusst völlig offen gehalten.

    Genau.


    Zitat

    Allerdings hat man trotzdem ein paar wenige Dinge festgelegt, vermutlich um die Sprache simpel zu halten -- eine dieser Festlegungen ist: Es gibt genau einen Adressraum.

    Meines Wissens gibt es diese Festlegung nicht. Dagegen spricht beispielsweise, dass Grösser-/Kleinervergleich zweier Pointer nur in ausgewählten Situationen definiert ist und z.B. der >/<-Vergleich von Pointern, die von zwei unterschiedlichen Objekten abgeleitet wurden undefiniert ist - die könnten ja in zwei unterschiedlichen Adressräumen liegen, für die keine Ordnungsrelation existiert.

  • Meines Wissens gibt es diese Festlegung nicht. Dagegen spricht beispielsweise, dass Grösser-/Kleinervergleich zweier Pointer nur in ausgewählten Situationen definiert ist und z.B. der >/<-Vergleich von Pointern, die von zwei unterschiedlichen Objekten abgeleitet wurden undefiniert ist - die könnten ja in zwei unterschiedlichen Adressräumen liegen, für die keine Ordnungsrelation existiert.

    Hmm, nein, das erlaubt nur einen beliebig geformten Adressraum (nur durch diese Restriktion sind z.B. Überlappungen innerhalb des Adressraums abbildbar -- der Adressraum muss nicht linear sein). Eine Konvertierung eines Integer Typs in einen Pointer ist wohldefiniert (mit implementierungsspezifischem Ergebnis), und das ist nur möglich, wenn man sich auf einen Adressraum beschränkt oder den Adressraum zum Teil des Pointer-Typs macht.


    Man kann auch noch etwas weiter ausholen: Bei Architekturen mit mehreren Adressräumen wird das in der Hardware normalerweise über unterschiedliche Instruktionen realisiert (z.B. in / out für I/O-Ports vs load / store für Memory - ein in 0xaffe lädt einen völlig anderen Wert als ein load 0xaffe). Um das korrekt zu kompilieren muss zur Kompilierzeit also bekannt sein, um was für eine Art Adresse es sich handelt, damit die richtigen Instruktionen generiert werden -- das geht nur über "qualifier", der C Standard sieht aber keine qualifier für verschiedene Adressräume vor. Genau da setzen entsprechende Extensions an und definieren eigene Qualifier (z.B. bei AVR PROGMEM für den Zugriff auf Programmspeicher).

  • Hmm, nein, das erlaubt nur einen beliebig geformten Adressraum (nur durch diese Restriktion sind z.B. Überlappungen innerhalb des Adressraums abbildbar -- der Adressraum muss nicht linear sein). Eine Konvertierung eines Integer Typs in einen Pointer ist wohldefiniert (mit implementierungsspezifischem Ergebnis), und das ist nur möglich, wenn man sich auf einen Adressraum beschränkt oder den Adressraum zum Teil des Pointer-Typs macht.

    Getaggte Pointer sind aber auch nicht so ungewöhnlich - meines Wissens benutzt Keil das auf dem 8051, um dessen Sammlung unterschiedlicher Adressräume in einem Pointertyp darstellen zu können.


    Zitat

    das geht nur über "qualifier", der C Standard sieht aber keine qualifier für verschiedene Adressräume vor. Genau da setzen entsprechende Extensions an und definieren eigene Qualifier (z.B. bei AVR PROGMEM für den Zugriff auf Programmspeicher).

    PROGMEM ist veraltet, inzwischen kann GCC auch mit explizit benannten Adressräumen umgehen. Es gibt zu dem Thema wohl eine Standarderweiterung speziell für eingebettete Systeme, die das normiert hat.