PS 440

PS 440
Paradigmen:Strukturierte Programmierung
Erscheinungsjahr:1970
Entwickler:Gerhard Goos, Klaus Lagally, Gerd Sapper
Typisierung:explizit, statisch
Beeinflusst von:PL360, Algol 68
Betriebssystem:BS 3, BSM[1]

PS 440 ist eine Systemprogrammiersprache für den TR 440. Sie vereint die Vorteile höherer Programmiersprachen gegenüber Assemblersprachen, wie größere Übersichtlichkeit, verminderte Fehleranfälligkeit, höheren Dokumentationswert des Quellprogramms und größere Bequemlichkeit beim Programmieren, mit der Möglichkeit, die Hardware des TR 440 in allen Einzelheiten zu nutzen.

PS 440 wurde an der TU München entwickelt als Hilfsmittel für die Programmierung eines Betriebssystems. Der Hersteller des TR 440 hat den PS‑440-Compiler nicht selbst eingesetzt und auch nicht als Standard-Software vertrieben, aber die Dokumentation in der Schriftenreihe System TR 440 veröffentlicht. Der Compiler wurde von der STARG verbreitet und weiterentwickelt.

Geschichte

PS 440 wurde von der Arbeitsgruppe für Betriebssysteme der TU München entwickelt als Hilfsmittel zur Programmierung eines Betriebssystems für den TR 440.[1]

Gerhard Goos schrieb die Syntax-Analyse des PS‑440-Compilers mit Hilfe des von ihm entwickelten Parsergenerators SMG (Syntax-Maschinen-Generator). Klaus Lagally[2] schrieb die Codegenerierung. Gerd Sapper[3] brachte den Compiler auf den Betriebssystemen zum Ablauf. Das Ergebnis ist in Bericht 7002 (I. Teil des PS‑440-Handbuchs) dokumentiert.

Helgrit Wich erstellte ein Skriptum zu einem Programmierkurs von Klaus Lagally und Gerd Sapper, daraus ist dann Bericht 7106 (II. Teil des PS‑440-Handbuchs) entstanden.

In der Software-Entwicklung für Großrechner bei AEG-Telefunken wurde PS 440 nicht eingesetzt, da hier schon frühzeitig die Verwendung der höheren Programmiersprache BCPL an Stelle einer Assemblersprache verfolgt wurde.[4] 1972 erschien das PS‑440-Handbuch in der Serie System TR 440 bei Telefunken Computer. Der Compiler wurde über den Arbeitskreis Programmaustausch der STARG verbreitet.

1976 wurde in Stuttgart im Rahmen einer studentischen Semesterarbeit die Testhilfe Trace für PS 440 ergänzt, wie von anderen Compilern des TR 440 gewohnt.

Mit der Ausmusterung der letzten TR 440 Mitte bis Ende der 80er-Jahre endete naturgemäß die Anwendung der Sprache PS 440.

Programmstruktur

Der Compiler bildet die PS‑440-Quelle auf die Telefunken-Assemblersprache TAS[5] ab; die nicht durch die Sprachmittel von PS 440 abgedeckten Systemfunktionen[A 1] können durch Einschübe von TAS-Sequenzen genutzt werden. Die erzeugte TAS-Quelle kann anschließend in der üblichen Weise assembliert und montiert werden. Der PS‑440-Compiler ist ein Single-Pass-Compiler; der TAS-Assembler fungiert als zweiter Durchlauf der Compilation. Diese Konstruktion hat folgende Konsequenzen:

  • Ein PS‑440-Programm besteht aus einem oder mehreren, an einander gereihten (nicht geschachtelten), Segmenten. Bezeichner sind lokal in einem Segment gültig; Bezeichner, die als global gekennzeichnet sind, gelten im gesamten Quellprogramm. Bezeichner aus anderen Programmmoduln können per Extern-Vereinbarung erreicht werden, selbständige globale Bezeichner können als Eingang gekennzeichnet und so für andere Programmmoduln erreichbar gemacht werden; die Externbezüge werden den Eingangsbezeichnern beim Montieren zugeordnet.
  • Anweisungen, Deklarationen und Spezifikationen können, getrennt durch Semikolon, in gemischter Reihenfolge niedergeschrieben werden.[A 2][6]
  • Alle Bezeichner müssen vor ihrer ersten Verwendung deklariert oder wenigstens spezifiziert sein, sofern ihre Art nicht aus der Verwendung hervorgeht. Beispiele: eine Marke braucht nicht vorab spezifiziert zu werden, wenn sie in einer Sprung-Anweisung verwendet wird; eine Variable, die in einer konstanten Referenz verwendet wird, kann auch weiter hinten im Programm deklariert sein.
  • Selbständige Bezeichner aus PS‑440-Deklarationen können in den TAS-Einschüben verwendet werden. In TAS deklarierte Bezeichner sind dagegen außerhalb der TAS-Einschübe unbekannt. Am besten deklariert man alle benötigten Bezeichner mit PS‑440-Sprachmitteln (außerhalb von TAS-Einschüben).
  • Als quellsprachbezogener Dump kann der TAS-Dump verwendet werden.

In PS 440 gibt es 97 reservierte Schlüsselwörter, die als Delimiter, Deklaratoren, Operatoren und Bezeichnungen der Hardware-Register fungieren. Die Syntax in der Tradition der Algol-ähnlichen Sprachen macht insbesondere Anleihen bei Algol 68 und umfasst die üblichen Bausteine der strukturierten Programmierung.

Datentypen

Entsprechend der Datenstruktur des TR 440 kennt PS 440 nur drei Datentypen:

  • SHORT Halbwort mit 24 Bit Länge,
  • FULL Ganzwort mit 48+2 Bit Länge,
  • LONG Doppelwort mit 2×(48+2) Bit Länge.

Größen dieser Typen können in einem passenden Register oder im Hauptspeicher liegen; im Speicher haben die Halbwörter fortlaufende, die Ganz- und Doppelwörter gerade Adressen. Für alle Operatoren ist festgelegt, auf welche dieser Typen sie anwendbar sind und welchen dieser Typen sie als Ergebnis liefern. Für Zwischenergebnisse in komplexen Ausdrücken wählt der Compiler Register oder Speicherzellen passender Länge aus.

Weitere Datentypen differenzieren anhand des Zugriffsmechanismus:

  • INDEX wird zur Deklaration von Halbwörtern im Index-Speicher benutzt: In Ausdrücken verhalten sie sich wie SHORT-Größen, der Speicherzugriff erfolgt jedoch über spezielle Befehle.
  • PART ist ein beliebiger, durch eine Bitmaske gesteuerter, Ausschnitt aus einer FULL-Größe; in Ausdrücken wird eine PART-Größe als Ganzwort (wie eine FULL-Größe) weiter verarbeitet.
  • LABEL, PROC und PROCSFB beziehen sich auf Halbwort-Adressen in der Befehlszone; sie können Ziel eines Sprunges oder eines Prozeduraufrufs sein.

Den Datentypen im Sinne höherer Programmiersprachen, wie bool, int, real und bytes in Algol 68, sind in PS 440 keine unterschiedlichen Datentypen zugeordnet; vielmehr wird die Interpretation der Daten teils anhand ihres aktuellen Wertes (nämlich ihrer Typenkennung) bestimmt, teils anhand der Operationen, die man auf sie anwendet.

Typenkennung

Jedes Ganzwort enthält neben den 48 Bit der eigentlichen Information noch 2 Bit als Typenkennung mit folgender Bedeutung:

  • Gleitkommazahlen haben im Ganzwort TK=0 (im Doppelwort TK=0 im ersten, TK=1 im zweiten Teil);
  • Festkommazahlen haben TK=1 (im Doppelwort zweimal);
  • Befehle belegen Halbwörter innerhalb von Ganzwörtern mit TK=2;
  • je sechs Textzeichen belegen normalerweise ein Ganzwort mit TK=3.

Literale legen durch ihre Form die Typenkennung implizit fest, so erzeugen etwa die Literale 1.618 und 6.022⏨23 Ganzwörter mit TK=0, die Literale 5 und -2 Ganzwörter mit TK=1 und das Literal "PS 440" ein Ganzwort mit TK=3; Bits-Angaben wie '2H 0003 AFFE' enthalten (links vom H) die gewünschte Typenkennung.[A 3]

Typenkennungen können mit den Operationen TK0, TK1, TK2 und TK3 gesetzt und mit der Operation TK abgefragt werden.

Operationen und Operanden

Einige Operationen verhalten sich unterschiedlich, je nach der Typenkennung ihrer Operanden. So vergleichen etwa die Vergleichs-Operationen >, =, , und < zwei Operanden mit TK=0 als Gleitkommazahlen (mit Berücksichtigung von Exponent und Vorzeichen), zwei Operanden mit TK=1 als Festkommazahlen (mit Berücksichtigung des Vorzeichens) und zwei Operanden mit TK=2 oder TK=3 als positive Festkommazahlen.[A 4] Auch die Wirkung der Verschiebe-Operationen LEFT, RIGHT, LEFTC und RIGHTC hängt von der Typenkennung ihres linken Operanden ab.

Bei anderen Operationen entscheidet die Wahl des Operator-Zeichens, welche Variante gewünscht ist. So gibt es beispielsweise unterschiedliche Operatoren für die arithmetischen Operationen, etwa * für die Festkomma-Multiplikation und ** für die Gleitkomma-Multiplikation. Diese Operationen lösen eine Programmunterbrechung, den TK-Alarm, aus, wenn ihre Operanden die falsche Typenkennung haben.[A 5] Die Operatoren ET, VEL und AUT verknüpfen ihre Operanden bitweise.

Die Wertoperatoren SVAL, FVAL und LVAL fassen ihren (einzigen) Operanden als Adresse eines Halb-, Ganz- bzw. Doppelworts im Speicher auf und liefern dessen aktuellen Inhalt; entsprechend liefert IVAL den Inhalt einer Indexspeicherzelle (ein Halbwort). Umgekehrt liefert der Referenz-Operator REF, der nur auf einen Operanden im Speicher angewandt werden kann, dessen Adresse.

Ausdrücke

Formeln beschreiben die Berechnung von Werten aus einfachen Operanden. Sie folgen der üblichen Syntax mit Infixnotation für binäre und Präfixnotation für unäre Operatoren mit den üblichen Prioritäten und mit runden Klammern, wo die normalen Operator-Prioriäten nicht passen. Alle Ausgangs-, Zwischen- und Resultatwerte haben eine inhärente Länge gemäß einem der drei Datentypen und werden bei Bedarf verlängert oder verkürzt.[A 6]

Da PS 440 keinen booleschen Datentyp kennt, kann ein Vergleich keine Formel sein, sondern ist eine Bedingung: Bedingungen steuern Fallunterscheidungen und Wiederholungen, liefern aber im Gegensatz zu Formeln keinen Wert, der gespeichert oder mit dem weitergerechnet werden kann. Die Grundbausteine der Bedingungen sind Vergleiche und Tests. Die Alarmtests TKAL und ARAL haben keinen Operanden, die Typenkennungs- und Bit-Tests haben zwischen dem Operatorsymbol und dem Operanden noch eine TK- bzw. Bit-Nummer, zum Beispiel: IF TK 1 RA THEN RA := −RA FI; diese Nummer muss explizit (nicht als Formel) angegeben werden. Vergleiche und Tests können mit den logischen Operatoren ¬, und zu komplexen Bedingungen verknüpft werden.

Deklarationen und Spezifikationen

Selbständige Vereinbarung

Die mit selbständigen Vereinbarungen definierten Bezeichner können auch in TAS-Einschüben verwendet werden und erscheinen gegebenenfalls im Trace und im TAS-Dump.

Eine Typvereinbarung bestimmt Typ und Speicherort von Variablen oder Konstanten; für Variable kann ein Anfangswert, für Konstanten muss der Wert angegeben werden. Eine Indexspeicher-Vereinbarung bestimmt nur den Speicherort von Indizes; die sind immer ein Halbwort lang, immer variabel und haben keinen definierten Anfangswert. Eine Typ- oder Indexspeicher-Vereinbarung kann mit einer Wertzuweisung kombiniert werden, die dann – im Gegensatz zum statischen Anfangswert – zur Laufzeit des Programms ausgeführt wird.

Eine Prozedurvereinbarung definiert ein Unterprogramm. PS 440 kennt weder Prozedur-Parameter noch Funktionswerte: Wie in maschinennaher Programmierung üblich, muss die Informationsübergabe zwischen rufendem Programm und Prozedur über den Hauptspeicher oder die Register organisiert werden. Falls eine Prozedur rekursiv aufgerufen werden soll, muss sie auch den Keller für ihre lokalen Variablen explizit organisieren.[7] Entsprechend den beiden Aufrufmechanismen unterscheidet PS 440 auch PROC- und PROCSFB-Vereinbarungen.

Marken werden dadurch vereinbart, dass sie an der entsprechenden Stelle im Programm gesetzt sind (mit nachfolgendem Doppelpunkt).

Beispiele:

  TYPVEREINBARUNGEN:
  ; LONG L1, L2, L3         CO drei LONG-Variable ohne bestimmten Anfangswert;
  ; SHORT S1 PRESET 5       CO eine SHORT-Variable mit Anfangswert 5;
  ; SHORT S2 IS REF L3      CO eine SHORT-Konstante, deren Wert die Adresse von L3 ist;
  ; SHORT S3 := BB          CO eine SHORT-Variable,
                               der der momentane Inhalt von BB als Wert zugewiesen wird;
  ; [0:3]FULL F41           CO ein Aggregat aus zwei FULL-Variablen;[A 7]
  ; [0:5]FULL VB616         CO ein Aggregat aus drei FULL-Konstanten;
    IS ( REF S&SRF, SHORT 3 CO deren Wert auch halbwortweise angegeben werden kann;[A 8]
       , REF TXT  , SHORT 2
       , '2H 0'             CO aber natürlich auch ganzwortweise;
       )
 
; INDEXSPEICHERVEREINBARUNGEN:
  ; INDEX I, J, K             CO drei Indizes;
  ; [0:2]INDEX X3             CO ein Aggregat aus drei weiteren Indizes;
 
; PROZEDURVEREINBARUNGEN:
  ; PROC FAK                  CO Fakultät (iterativ);
    IS BEGIN
      INDEX F; FULL P
    ; F := RA; P := 1         CO Argument in RA (muss TK=1 haben);
    ; FOR F FROM F BY −1 TO 2
      DO P := P * F           CO Arithmetischer Alarm möglich! ;
    ; RA := P                 CO Resultat in RA;
    END FAK
  ; PROCSFB INCRTAG           CO Prozedur für CALLSFB;
    IS IF TAG = 6 THEN TAG := 0 ELSE TAG +:= 1 FI

Äquivalenz-Vereinbarung

Mit einer Äquivalenz-Deklaration wird einem neuen (unselbständigen) Bezeichner eine Bedeutung, bestehend aus Typ und Zugriffsmechanismus, zugewiesen, indem er einer bereits deklarierten Größe (oder einer Komponente davon) gleichgesetzt wird. Beim Zugriffsmechanismus können indirekte Adressierung, Indizierung und Teilwortzugriffe verwendet werden; diese Mechanismen werden dynamisch ausgewertet.[A 9] Eine Äquivalenz-Deklaration kann auf bereits deklarierte selbständige oder unselbständige Größen Bezug nehmen; letztlich muss eine Kette von Äquivalenzen immer auf eine selbständige Größe führen. Die folgenden Beispiele beziehen sich auf die oben deklarierten selbständigen Größen:

  INDIZIERUNG:
  ; SHORT FADR = VB616[0]  CO FADR bezeichnet das erste Halbwort des Aggregats VB616;
  ; FULL  F41I = F41[I]    CO F41I bezeichnet ein Ganzwort aus F41,
                              abhängig vom aktuellen Wert von I;
 
; INDIREKTADRESSIERUNG:
  ; [0:9]FULL FK = FVAL K  CO FK bezeichnet dasjenige Aggregat, dessen Adresse aktuell in K steht;
  ; FULL FK2     = FK[2]   CO FK2 ist das zweite Ganzwort aus FK – wo das ist, hängt von K ab;
  ; FULL FKJ     = FK[J]   CO indirekte Adressierung und Indizierung können kombiniert werden;
 
; TEILWORTZUGRIFF:
  ; PART E  = '2H FFFFFF FFFFFB' OF VB616[0] CO E bezeichnet ein Bit aus dem 1. Ganzwort von VB616;
    ,    KA = '2H FFFFFF FFFFFC' OF VB616[0] CO KA bezeichnet ein Feld aus zwei weiteren Bits;[8]

Selbstverständlich können auch Teilwort-Zugriffe mit Indizierung und indirekter Adressierung kombiniert werden. Diese Äquivalenzvereinbarungen erleichtern das Programmieren des TR 440 erheblich, wie das unten stehende Unterprogramm für Fortran-Programm illustriert.

Spezifikation

Eine Spezifikation macht die Eigenschaften einer selbständigen Größe bekannt, deren Speicherplatz an anderer Stelle deklariert wird: Eine eigentliche Spezifikation kündigt eine Vereinbarung im selben Programm an und ermöglicht damit die Compilation in einem Durchlauf; eine Extern-Vereinbarung hat (trotz des abweichenden Namens) dieselbe Funktion für eine selbständige Größe, die in einem anderen Programmodul vereinbart ist. Eine Eingangs-Spezifikation ermöglicht einem anderen Programmodul, sich auf eine selbständige Größe des vorliegenden Programms zu beziehen. Extern-Vereinbarungen und Eingangs-Spezifikationen für Indizes oder Register sind nicht möglich. Die folgenden Beispiele beziehen sich auf die oben deklarierten selbständigen Größen:

  SPEZIFIKATION:
  ; SPEC [0:5]FULL VB616          CO VB616 kann weiter unten im Programm deklariert werden;
  ; SPEC INDEX     F              CO Das ist auch für Indizes erlaubt;
 
; EXTERNVEREINBARUNG:
  ; SPEC WUNDERPGM LABEL MIRAKEL  CO MIRAKEL ist eine Marke im Programmodul WUNDERPGM;
  ; SPEC FAK       FULL  XYZ      CO FAK ist ein Programmmodul, kein lokaler Bezeichner;
  ; SPEC S&SRF     LABEL S&SRF    CO Namensgleichheit mit Bezeichnern stört also nicht;
 
; EINGANGSSPEZIFIKATION:
  ; ENTRY FAK, VB616    CO anderen Programmoduln sind die lokalen Größen FAK und VB616 zugänglich;

Anweisungen

Einfache Anweisungen

Wertzuweisung und Tausch

Die Wertzuweisung weist einer Variablen einen neuen Wert zu; im Gegensatz zur statischen Vorbelegung mit PRESET wird die Wertzuweisung zur Laufzeit des Programms ausgeführt. Wie in Algol 68 gilt die Wertzuweisung als Ausdruck, kann also Teil einer Formel oder rechter Teil einer weiteren Wertzuweisung sein. Erhöhungen und Erniedrigungen (siehe Beispiele) ergeben besonders effizienten Maschinencode.

Der Tausch vertauscht die aktuellen Werte zweier Variablen. Beide Variable müssen dieselbe Länge haben; Indizes können nur mit anderen Indizes oder dem Register BB getauscht werden. Der Tausch gilt nicht als Ausdruck, kann also – im Gegensatz zur Wertzuweisung – nicht Teil einer Formel sein.

Beispiele:

  WERTZUWEISUNG:
    RAQ := L3            CO kopiert den Inhalt des Doppelworts L3 ins Register RAQ;
  ; L1  := L2            CO das geht natürlich auch mit Variablen im Speicher;
  ; J   := FADR          CO oder mit Indizes;
  ; RA  := L3            CO die Kopie in RA ist kürzer, die linken 48+2 Bit fallen weg;
  ; BB +:= 1             CO BB wird um 1 erhöht (kurz für "BB:=BB+1");
  ; P −−:= 1.0⏨0         CO Erhöhung und Erniedrigung gibt's auch für Gleitkommazahlen;
  ; RAQ := RH := F41     CO RH erhält den Wert von F41,
                            RAQ denselben Wert auf doppelte Länge mit 0-Bits aufgefüllt;
  ; RAQ := RA * (RH+:=1) CO RH wird um 1 erhöht,
                            mit dem neuen Wert wird RA*RH berechnet und RAQ zugewiesen;
 
; TAUSCH:
    RA  :=: RH           CO vertauscht die Inhalte der beiden Register;
  ; BB  :=: J            CO vertauscht die Inhalte des Registers BB und des Index J;
  ; J   :=: K            CO vertauscht die Inhalte zweier Indizes;
  ; FK2 :=: FKJ          CO vertauscht die Inhalte zweier Ganzwörter im Speicher;

TAS-Einschub

Ein TAS-Einschub fügt die angegebenen Informationseinheiten[9] in die erzeugte TAS-Quelle ein. Damit können Assembler- oder Hardware-Funktionen genutzt werden, für die keine eigenen PS‑440-Sprachmittel vorgesehen sind.

Beispiele:

  */START LOS, ALARM CIAO/*  CO zwei Deklarationen (TAS-Pseudobefehle);
; */SSR 1 12/*               CO ein Befehl, für den es kein PS-440-Sprachmittel gibt;

Ausnahmen von der fortlaufenden Befehlsausführung

Ein Prozeduraufruf führt ein Unterprogramm aus. PS 440 unterscheidet zwei unterschiedliche Mechanismen zum Prozeduraufruf, entsprechend den Befehlen SU[10] und SFB.[11] Der SU-Befehl und die entsprechende Rückkehr ins rufende Programm[12] führen automatisch einen Keller der Rücksprung-Adressen im Index-Speicher; deshalb können CALL-Prozeduren, die keine lokalen Variablen benutzen, auch ohne explizite Keller-Organisation rekursiv aufgerufen werden.

Die EXEC-Anweisung führt einen Maschinenbefehl aus, der in einem Halbwort steht. Dies wird u. a. zur Parameterversorgung von Unterprogrammen genutzt.

Sprung und Rückkehr setzen den Programmlauf an anderer Stelle fort und sollten daher nur für Sonderfälle eingesetzt werden.[13] Normalerweise erfolgt die Rückkehr aus einer Prozedur an deren Ende ohne explizite Rückkehr-Anweisung.

Die Leere Anweisung ist unsichtbar und wirkungslos, etwa wenn in einem Zweig einer Fallunterscheidung nichts zu tun ist.

Beispiele:

; SPRUNG:
    GOTO LEERANWEISUNG   CO Fortsetzung bei Marke LEERANWEISUNG;
  ; RETURN               CO Rückkehranweisung, darf nur innerhalb einer Prozedurvereinbarung stehen;
 
; PROZEDURAUFRUF:
    RA := 7              CO Argument bereitstellen;
  ; CALL FAK             CO Prozeduraufruf – es gibt keine formalen Parameter;
  ; F41 := RA            CO Ergebnis abholen;
 
; EXECANWEISUNG:
    EXEC HV              CO siehe Anwendung im Unterprogramm für Fortran-Programm;
 
; LEERANWEISUNG:
  ;                      CO man sieht's hier nur am Extra-Semikolon;

Strukturierte Anweisungen

Die Anweisungen einer Sequenz werden durch Semikolon getrennt und können bei Bedarf mit BEGIN und END eingeklammert werden. Nach dem END darf ein Bezeichner als Kommentar geschrieben werden, um auf den Anfang der Sequenz hinzuweisen.

Die Fallunterscheidung gibt es als IF- und als CASE-Anweisung. Die IF-Anweisung muss mit FI abgeschlossen werden; so wird das Dangling Else vermieden und Sequenzen in THEN- oder ELSE-Zweig müssen nicht eingeklammert werden. Die CASE-Anweisung unterscheidet Fälle aufgrund eines ganzzahligen Ausdrucks; hier müssen gegebenenfalls Sequenzen, die einzelnen Fällen zugeordnet sind, eingeklammert werden.

Die Wiederholung kann durch eine Zählung oder durch eine Bedingung gesteuert werden; soll eine Sequenz wiederholt werden, muss sie mit BEGIN und END eingeklammert werden. Alle Wiederholungen sind vorprüfende Schleifen.

Beispiele:

  SEQUENZ:
    BEGIN RA := 9; CALL FAK; F41 := RA END SEQUENZ
 
; FALLUNTERSCHEIDUNG:
    IF P ≤ 16               CO Die Bedingung bei IF wählt THEN- oder ELSE-Zweig aus;
    THEN RA := P; CALL FAK  CO Hier ist keine BEGIN-END-Klammer notwendig;
    ELSE RA := 0
    FI
  ; IF   RA = 0             CO das könnte auch die negative Null sein;
    THEN RA := 0            CO jetzt ist's definitiv die positive Null;
    FI                      CO ELSE-Zweig kann fehlen;
  ; CASE MONAT−1            CO MONAT muss im Bereich 1:12 liegen;
    FROM MLAENGE := 31      CO Januar;
       , IF TK 2 JAHR       CO Februar;
         THEN MLAENGE := 29
         ELSE MLAENGE := 28
         FI
       , MLAENGE := 31      CO März;
       , MLAENGE := 30      CO April;
       , MLAENGE := 31      CO Mai;
       , MLAENGE := 30      CO Juni;
       , MLAENGE := 31      CO Juli;
       , MLAENGE := 31      CO August;
       , MLAENGE := 30      CO September;
       , MLAENGE := 31      CO Oktober;
       , MLAENGE := 30      CO November;
       , MLAENGE := 31      CO Dezember;
    ESAC
 
; WIEDERHOLUNG:
    FOR I FROM 1 TO 16      CO Zählschleife;
    DO BEGIN RA := I; CALL FAK; FF[I] := RA END I
  ; WHILE ODD               CO Schleife mit Bedingung;
    DO RA := RA RIGHT 1     CO Schleife endet mit einer geraden Zahl in RA;
  ; TO 99                   CO 100-mal (Zählung beginnt bei 0);
    DO BEGIN BB := VB616; */SSR 6 16/* END

Vollständige Beispiele

Die folgenden Beispiele zeigen die PS‑440-Sprachmittel im Zusammenhang aus Benutzersicht (keine Systemprogramme). Da es derzeit keine Möglichkeit gibt, PS‑440-Programme zu testen, könnten sie Fehler enthalten.

Das PS‑440-Handbuch enthält als Anhang 2 ein ausführliches Beispiel für ein vollständiges Programm.[14]

Selbständiges Benutzerprogramm

Das aus der folgenden Quelle erzeugte Programm kann im Benutzer-Auftrag mit dem normalen STARTE-Kommando aktiviert werden und schreibt dann den Text „Grüß Gott!“ ins Ablaufprotokoll (und im Dialogbetrieb an die Konsole des jeweiligen Benutzers).

SEGMENT HALLOWELT
; */START VIA, ALARM CIAO/*               CO Start- und Alarm-Adresse;
; [0:255]FULL INDIZES; */XBASIS INDIZES/* CO Platz für Indizes;
; */VORBES (1,0), UNTPR 7/*               CO Vorbesetzung Arbeitsspeicher und BU-Register;
 
; [0:5]FULL VB616               CO Versorgungsblock für Systemdienst SSR 6 16;[8]
  IS ( REF CIAO                 CO Fehler-Ausgang;
     , SHORT 3                  CO Ausgabe ins Ablaufprotokoll und an Konsole;
     , REF "*021Grüß Gott!"     CO 1 Zeile Text (mit Vorschubzeichen NL);
     , SHORT 2                  CO 2 Ganzwörter (12 Zeichen) ausgeben;
     , FULL 0                   CO bedeutungslos, da keine Konsoleingabe verlangt;
     )
; FULL VB012 = VB616            CO VB616[0:1] taugt auch als Versorgung für SSR 0 12;[15]
 
; VIA:  BB := REF VB616; */SSR 6 16/* CO Text ausgeben;
; CIAO: BB := REF VB012; */SSR 0 12/* CO Programmlauf beenden;
FINIS

Die fünf Angaben, die das Betriebssystem zum Start eines Programms im Benutzer-Auftrag benötigt, müssen in TAS-Einschüben gemacht werden. Auch die Systemdienste (SSR-Befehle) werden in TAS-Einschüben aufgerufen. Im Falle eines SSR-Fehlers oder eines Alarms (mit denen hier nicht zu rechnen ist) würde das Programm bei der Marke CIAO fortgesetzt, also ohne Weiteres beendet werden.

SSR-Befehle erwarten die Adresse eines Versorgungsblocks im Register BB. Die Art der gewünschten Systemleistung wird durch die beiden Adressteile des SSR-Befehls bestimmt, die Einzelheiten durch den Inhalt des Versorgungsblocks.[16]

Alle Variablen, Konstanten und Befehls-Adressen werden mit PS‑440-Sprachmitteln deklariert; die deklarierten Namen können in TAS-Einschüben verwendet werden (hier: VIA, CIAO und INDIZES).

Die Äquivalenz-Vereinbarung in Zeile 13 erklärt VB012 als Alias für das erste Ganzwort aus VB616. Eine Spezifikation LABEL CIAO ist unnötig, da CIAO nur in einem TAS-Einschub und in einer konstanten Referenz verwendet wird; da genügt es, dass die Marke CIAO irgendwo im Segment gesetzt ist.

Unterprogramm für Fortran-Programm

Das folgende Unterprogramm kann aus einem Fortran-Programm mit der Anweisung CALL JETZT (JAHR, MONAT, TAG, STUNDE, MINUTE, SEKUNDE) aufgerufen werden.[A 10] Als aktuelle Parameter sind 1 bis 6 INTEGER-Variable (oder Feldelemente) anzugeben, in die JETZT das aktuelle Datum samt Uhrzeit einträgt. Überzählige Parameter werden ignoriert. Das Unterprogramm lässt INTEGER*2- und INTEGER*4-Parameter zu und veranlasst bei falscher Versorgung den Abbruch des Programmlaufs mit einer Fehlermeldung.

SEGMENT PROCSFB JETZT
IS BEGIN */STRUKT (1, KB)/*   CO Daten für den Rückverfolger;
; [0:3]FULL KB                CO Kontrollblock;
  PRESET ( SHORT '2H 0'       CO Platz für Rückkehr-Adresse;
         , SHORT 1            CO Code-Prozedur;
         , SHORT '2H 81 0A0A' CO Fortran-Anschluss;
         , REF TE             CO Meldungstext im Fehlerfall;
         )
; SHORT RADR  = KB[0]         CO Rückkehr-Adresse;
      , FTADR = KB[3]         CO Fehlertext-Adresse;
; SHORT KBADR IS REF KB
; FULL  TE    IS "*037"       CO kein Text (nur Text-Ende);
; RADR        := BB           CO Rückkehradresse retten;
 
; INDEX PADR  := RA           CO Adresse der Parameterversorgung retten;
; FULL PARAMETER = FVAL PADR
; SHORT FADR     = HW                 OF PARAMETER[0] CO Fehleradresse;
; LABEL FEHLER   = SVAL FADR                          CO Fehlerroutine;
; PART SPRACHE   = '3H FFFFFF 0FFFFF' OF PARAMETER[0] CO Sprachschlüssel;
     , AUFRUF    = '3H FFFFFF FFFCFF' OF PARAMETER[0] CO Aufrufart;
     , PARZAHL   = '3H FFFFFF FFFF00' OF PARAMETER[0] CO Anzahl Parameter;
; IF  SPRACHE ≠ 1 THEN FTADR := REF "JETZT muss als FORTRAN-Unterprogramm aufgerufen werden*037"
  ELSF AUFRUF = 2 THEN FTADR := REF "JETZT muss mit CALL aufgerufen werden*037"
  FI
; IF FTADR ≠ REF TE THEN RH := REF KBADR; GOTO FEHLER FI
 
; SPEC S&SRF LABEL S&SRF  CO Unterprogramm zur Behandlung von SSR-Fehlern;
; [0:1]FULL VB432         CO Versorgungsblock für SSR 4 32;
  IS (REF S&SRF, SHORT 1) CO Ergebnis in 12 Dezimalziffern zu je 4 Bit mit TK=3 gewünscht;
; BB := REF VB432; */SSR 4 32/*; FULL UHR := RA CO Datum und Uhrzeit holen;
 
; INDEX P, PMAX, TYP, FBX
; FULL  PP = PARAMETER[P][P]
; SHORT HV = HW OF PP[0]              CO Zugriff auf den aktuellen Parameter;
; PART SCHL= '3H FFFFFF 3FFFFF' OF PP CO Beschreibung des aktuellen Parameters;
     , ART = '3H FFFFFF 3FFF00' OF PP CO Beschreibung & Art des aktuellen Parameters;
     , VTYP= '3H FFFFFF C000FF' OF PP CO Typ des aktuellen Parameters;
     , FBA = '3H FFFFFF C00000' OF PP CO gegebenenfalls Adresse der Feldbeschreibung;
; FULL FB  = FVAL FBX                 CO gegebenenfalls Feldbeschreibung;
; PART FTYP= '3H FFFFFF FF00FF' OF FB CO Typ aus Feldbeschreibung;
; IF PARZAHL > 6 THEN PMAX := 6 ELSE PMAX := PARZAHL FI
; FOR P FROM 1 TO PMAX
  DO BEGIN
    IF   SCHL = 2 THEN FBX := FBA; TYP := FTYP CO Feld-Element;
    ELSF ART  = 2 THEN             TYP := VTYP CO einfache Variable;
    ELSE FTADR := REF "Parameter muss Variable oder Feld-Element sein*037"
    FI
  ; RAQ := (RAQ := UHR) LEFT 8; SHORT WERT := RA; UHR := RQ       CO nächsten Teilwert isolieren;
  ; FULL IWERT := 10 * TK1 (WERT RIGHT 4) + TK1 (WERT ET '3HF')   CO Teilwert nach INTEGER wandeln;
  ; IF P = 1
    THEN IF IWERT > 69 THEN IWERT +:= 1900 ELSE IWERT +:= 2000 FI CO Jahr vierstellig;
    FI
  ; IF FTADR ≠ REF TE THEN CO inkompatibler Aktualparameter, nix tun;
    ELSF TYP = 1      THEN EXEC HV; SVAL BB := IWERT
    ELSF TYP = 2      THEN EXEC HV; FVAL BB := IWERT
    ELSE FTADR := REF "Parameter muss INTEGER*2 oder INTEGER*4 sein*037"
    FI
  ; IF FTADR ≠ REF TE THEN RH := REF KBADR; GOTO FEHLER FI
  END P
 
; BB := RADR
END JETZT
 
FINIS

Der Vorteil von PS 440 gegenüber TAS: Man übersetzt die Struktur der diversen Versorgungs- und Kontrollblöcke aus der Dokumentation[17] als Äquivalenz-Deklarationen ins PS‑440-Programm und muss sich dann beim Zugriff auf die so deklarierten Größen keine Gedanken um indirekte Adressierung, Indizierung und Teilwort-Zugriffe machen, da das alles der Compiler berücksichtigt. Entscheidend dabei ist, dass sich die Äquivalenzen auf veränderliche Adressen beziehen können, die erst zur Laufzeit des Programms ausgewertet werden.

Da das Unterprogramm mehrfach vom selben Programm aufgerufen werden kann, sind Vorbelegungen mit PRESET nur soweit verlässlich, wie sie durch das Unterprogramm selbst nicht verändert werden. Andernfalls muss es den Variablen ihren Anfangswert dynamisch zuweisen – ausgenommen FTADR, das nur für eine Fehlermeldung verändert wird, von der es keine Rückkehr ins rufende Programm gibt.

Das Unterprogramm JETZT wird gemäß Programmiersystem-Konvention mit dem SFB-Befehl[11] aufgerufen, der die Rückkehradresse ins BB-Register bringt; der PS‑440-Compiler erwartet, dass beim Verlassen der Prozedur die Rückkehradresse wieder in BB steht. Also muss am Anfang BB gerettet und am Ende wiederhergestellt werden. Der STRUKT-Pseudobefehl ist ein Hinweis für die Rückverfolgung; aufgrund dieser Angabe erwartet der Rückverfolger im Alarm- oder Fehlerfall die Rückkehradresse im Kontrollblock. Der sonstige Inhalt des Kontrollblocks wird von dem Fehler-Unterprogramm ausgewertet, dessen Adresse im Parameterblock übergeben wurde; diesem Unterprogramm muss im RH-Register die Adresse eines Halbworts, das rechtsbündig die Adresse des Kontrollblocks enthält, übergeben werden.

Beim Aufruf eines Unterprogramms aus höheren Programmiersprachen steht die Adresse des Parameter-Blocks im RA-Register; diese muss als Nächstes gerettet werden. Der Parameter-Block besteht aus einem Kopfwort mit allgemeinen Angaben, gefolgt von je zwei Halbwörtern (Haupt- und Zusatzversorgung) pro Parameter. Die Zusatzversorgung beschreibt Typ und Art des jeweiligen Parameters und damit auch implizit die Wirkung der Hauptversorgung; im Falle eines Feldelements oder einer einfachen Variablen ist die Hauptversorgung ein Befehl, der dessen bzw. deren Adresse ins BB-Register bringt.

Ein Unterprogramm, das aus höheren Programmiersprachen aufgerufen wird, kann die Indizes 0 bis 7 für eigene Zwecke benutzen, sofern es nicht seinerseits andere Unterprogramme aufruft, die diese Indizes verändern. JETZT benutzt insgesamt fünf dieser acht Indizes.

Literatur

  • Gerd Sapper: The Programming Language PS440 as a Tool for Implementing a Time-Sharing-System. In: Hans Langmaack u. Manfred Paul (Hrsg.): 1. Fachtagung über Programmiersprachen (= Lecture notes in economics and mathematical systems. Nr. 75). Springer Verlag, Berlin · Heidelberg · New York 1972, ISBN 3-540-06051-0, S. 43–49 (englisch).
  • Gerhard Goos, Klaus Lagally, Gerd Sapper, Helgrit Wich: PS 440. In: System TR 440. N31.ZZ.10. Telefunken Computer GmbH, Konstanz Mai 1972 (Scan [PDF; 12,9 MB; abgerufen am 6. August 2020]).
  • Gerd R. Sapper: Maschinenorientierte Sprachen (= Albert Endres, Hermann Krallmann, Peter Schnupp [Hrsg.]: Handbuch der Informatik. Band 3.1). R. Oldenbourg Verlag, München, Wien 1989, ISBN 3-486-20662-1.

Anmerkungen

  1. Hardwarebefehle; Steuerung von Assembler-, Montierer- und Überwacherfunktionen
  2. Der TAS-Assembler legt Konstanten, Variable und Befehle jeweils in eigenen Adresszonen ab, die dann beim Montieren mit gleichartigen Adresszonen aus anderen Programmmoduln jeweils zu Gebieten zusammengefasst werden. Mit anderen Worten: Auch wenn in der PS‑440-Quelle zwischen den Anweisungen Variablen- oder Konstanten-Deklarationen eingestreut sind, landen die den Anweisungen entsprechenden Befehle schließlich fortlaufend im Maschinenprogramm und werden – abgesehen von Sprungbefehlen und Prozeduraufrufen – fortlaufend ausgeführt. Dies gilt natürlich nur, soweit dieser Mechanismus nicht durch einen STARR- oder ABLAGE-Pseudobefehl in einem TAS-Einschub unterdrückt ist.
  3. Literale können auch mit einer Längen-Angabe versehen werden, etwa SHORT 42 oder LONG 3.14159265358979323846264338.
  4. Der Programmierer muss dafür Sorge tragen, dass möglichst nur Operanden mit gleicher Typenkennung verglichen werden. Bei Operanden unterschiedlicher Typenkennungen geht die Transitivität der Vergleichsoperatoren verloren; so ergibt sich beispielsweise die widersprüchliche Situation, dass −1<1, 1<"1" und "1"<−1 alle gleichermaßen zutreffen!
  5. Vorsicht ist auch geboten bei den Operatoren + und : Die führen stets eine Festkomma-Addition bzw. ‑Subtraktion durch (jeweils mit Berücksichtigung des Vorzeichens), auch wenn ein Operand eine andere Typenkennung als 1 hat. So wird beispielsweise 1.618 bei der (versehentlichen) Festkomma-Addition als 7116039255041 aufgefasst und "PS 440" als −52971178773327.
  6. Beim Verkürzen eines Wertes auf FULL oder SHORT wird das rechte Ganz- bzw. Halbwort des Ausgangswerts weiter verwendet. Beim Verlängern von SHORT auf FULL wird links mit Vorzeichen-gleichen Bits aufgefüllt, auch bei TK=2 oder TK=3. Beim Verlängern auf LONG wird links ein Ganzwort mit der Festkommazahl 0 ergänzt. Auch das kann zu Überraschungen führen: nach LONG L := −FULL 1 ist L positiv, nach LONG L := −LONG 1 negativ.
  7. Die Indizierung erfolgt für alle Aggregate, unabhängig vom Typ, ab 0 in Halbwort-Schritten.
  8. Eine Adresse wie REF S&SRF belegt ein Halbwort.
  9. Die Äquivalenzvereinbarung von PS 440 ist noch eine Spur dynamischer als die von Algol 68, wie der Vergleich von FULL F41I = F41[I] mit ref int f41i = f41[i] zeigt: In Algol  wird i einmalig beim Durchlaufen der Äquivalenzvereinbarung ausgewertet, bei PS 440 wird dagegen I bei jedem Zugriff auf F41I erneut ausgewertet.
  10. JETZT kann auch aus einem Algol‑60-Programm aufgerufen werden, wenn es dort als externe Fortran-Prozedur deklariert ist (Algol-Spracherweiterung). Der Algol-Typ integer entspricht dem Fortran-Typ INTEGER*4.

Einzelnachweise

  1. a b G. Goos, J. Jürgens, K. Lagally: The Operating System BSM Viewed as a Community of Parallel Processes. In: Technischer Bericht. Nr. 7208. TU München, München 1972 (englisch).
  2. Klaus Lagally, em. Prof. Dr. rer. nat., Leiter der Abteilung Betriebssoftware. Institutsverbund Informatik der Universität Stuttgart, 8. April 2014, abgerufen am 17. November 2020.
  3. DC2HC: DARC OV E34: Berufliches. OV E34, Funkamateure des Ortsverbandes Lüneburg-Ilmenau, 18. September 2015, abgerufen am 17. November 2020.
  4. Hans-Jürgen Siegert: AEG-Telefunken TR 440:Software und Software-Entwicklung. In: Informatik – Forschung und Entwicklung. Band 22. Springer-Verlag, Oktober 2008, ISSN 0949-2925, BCPL als Systemimplementierungssprache, S. 255, doi:10.1007/s00450-008-0046-4 (Online [abgerufen am 22. August 2020]).
  5. TAS : Telefunken-Assembler-Sprache. Änderungsstand 1. Telefunken Computer, Konstanz November 1972 (Scan [PDF; 2,6 MB; abgerufen am 8. September 2020]).
  6. TAS : Telefunken-Assembler-Sprache. Änderungsstand 1. Telefunken Computer, Konstanz November 1972, Kap. C‑6 Anordnung von Informationseinheiten, Adressenzonen und Gebieten (Scan [PDF; 2,6 MB; abgerufen am 18. April 2021]).
  7. Ein Beispiel ist der Algol-60-Keller, siehe TR 440 : TAS-Handbuch : Telefunken-Assembler-Sprache. Änderungsstand 19. Telefunken Computer, Konstanz Juni 1972, S. D9‑1–D9‑2 (Scan [PDF; 14,9 MB; abgerufen am 8. September 2020]).
  8. a b Systemdienste. Änderungsstand 9. CGK, Konstanz Januar 1975, S. SSR 6 16 (Scan [PDF; 6,0 MB; abgerufen am 8. September 2020]).
  9. TAS : Telefunken-Assembler-Sprache. Änderungsstand 1. Telefunken Computer, Konstanz November 1972, S. B‑7 (Scan [PDF; 2,6 MB; abgerufen am 8. September 2020]).
  10. TR 440 : Befehls-Lexikon. AEG-Telefunken, Konstanz, S. SU–SUE (Scan [PDF; 5,3 MB; abgerufen am 8. September 2020]).
  11. a b TR 440 : Befehls-Lexikon. AEG-Telefunken, Konstanz, S. SFB–SFBE (Scan [PDF; 5,3 MB; abgerufen am 8. September 2020]).
  12. TR 440 : Befehls-Lexikon. AEG-Telefunken, Konstanz, S. MU (Scan [PDF; 5,3 MB; abgerufen am 20. Oktober 2020]).
  13. Edsger W. Dijkstra: Letters to the editor: Go To Statement Considered Harmful. In: Communications of the ACM. Band 11, Nr. 3. ACM, März 1968, S. 147–148, doi:10.1145/362929.362947 (englisch).
  14. PS 440. Anhang 2. S. 163–191 (Scan [PDF; 12,9 MB; abgerufen am 6. August 2020]).
  15. Systemdienste. Änderungsstand 9. CGK, Konstanz Januar 1975, S. SSR 0 12 (Scan [PDF; 6,0 MB; abgerufen am 8. September 2020]).
  16. Systemdienste. Änderungsstand 9. CGK, Konstanz Januar 1975, S. 4 (Scan [PDF; 6,0 MB; abgerufen am 8. September 2020]).
  17. TR 440 – TAS-Handbuch – Telefunken-Assemblersprache. S. D8‑1–D8‑8 (Scan [PDF]).