Programmiersprache Pascal

Byte-Anordnung

Bei Variablen der Integer-Typfamilie kann unterschieden werden, in welcher Form die Werte auf dem zugeordneten Speicherplatz abgelegt werden.

Beispiel:

  VAR s : SHORTINT;
      l : LONGINT;

  s := 16#0102;          { Hexadezimalwert nach Extended Pascal }
  l := 16#01020304;
SHORTINT bzw. LONGINT seien Integer-Varianten mit 2 bzw. 4 Byte Speicherplatzbedarf, die auf einer Reihe von Pascal-Systemen zur Verfügung stehen (jedoch nicht im Standard vorgesehen sind).

Im zugeordneten Speicherbereich können die Werte in folgender Weise angeordnet werden:

  SHORTINT
    01 02                     M68xxx, Z8000, Sparc   big endian
    02 01                     intel 80x86, VAX       little endian

  LONGINT
    01 02 03 04               M68xxx, Z8000, Sparc   big endian
    04 03 02 01               intel 80x86, VAX       little endian
    02 01 04 03               PDP-11
Oder anders ausgedrückt:
Die Zuweisung
  l := 1;
führt dazu, daß der l zugeordnete Speicherbereich mit genau einer binären Eins gefüllt wird, alle anderen Bits werden auf Null gesetzt.
Bei "little endian" landet die Eins im 1. Byte, bei "big endian" im 4. Byte.

Programm zur Demonstration der Byte-Anordnung (Pascal++):

  PROGRAM bytord(OUTPUT);
  TYPE typ = ( one, two, four );
       rec = RECORD
               CASE typ OF
                 one  : ( l : LONGINT );
                 two  : ( s : ARRAY[1..2] OF SHORTINT );
                 four : ( b : ARRAY[1..4] OF BYTE );
             END;
  
  PROCEDURE write_rec(r: rec);
  VAR i : INTEGER;
  BEGIN
    WITH r DO BEGIN
      Write(l:12); Write(' | ');
      FOR i:=1 TO 2 DO Write(s[i]:7); Write(' | ');
      FOR i:=1 TO 4 DO Write(b[i]:5); Writeln;
    END;
  END;
  
  VAR r : rec;
  
  BEGIN
    r.b[1] := 16#01;         write_rec(r);
    r.s[1] := 16#0102;       write_rec(r);
    r.l := 16#01020304;      write_rec(r);
    r.l := 1;                write_rec(r);
  END.
Ergebnis mit Pascal++ unter DOS auf PC mit 80x86:
           1 |       1      0 |     1    0    0    0 |
         258 |     258      0 |     2    1    0    0 |
    16909060 |     772    258 |     4    3    2    1 | 
           1 |       1      0 |     1    0    0    0 |
Ergebnis mit Pascal++ unter Solaris auf Sparc Workstation
    16777216 |     256      0 |     1    0    0    0 | 
    16908288 |     258      0 |     1    2    0    0 | 
    16909060 |     258    772 |     1    2    3    4 | 
           1 |       0      1 |     0    0    0    1 |
Das obige Demonstrationsprogramm nutzt Extended Pascal, systemabhängig sind die verwendeten Datentypen LONGINT, SHORTINT und BYTE, die gegebenenfalls bei Verwendung anderer Pascal-Systeme ersetzt werden müssen.
Bemerkung:
Um das Programm an Turbo Pascal anzupassen, müßten folgende Änderungen vorgenommen werden: Es sind die Datentypen LONGINT, INTEGER und SHORTINT zu verwenden, Hexadezimalwerte sind z.B. durch $FF anstelle von 16#FF anzugeben.


Die Operatoren und Funktionen eines Pascal-Systems sind so implementiert, daß für den Programmierer die Byte-Anordnung keine Rolle spielt - die Portabilität der Programme wird durch sie nicht berührt.
Portabilitätsprobleme entstehen nur dann, wenn der Programmierer systemnahe Operationen vornimmt, die auf einer bestimmten Byte-Anordnung beruhen !
Werden aus irgendwelchen Gründen solche Operationen benötigt, dann ist Sorge zu tragen, daß von der jeweils richtigen Byte-Anordnung ausgegangen wird.
Im einfachsten Fall kann das durch bedingte Compilation erfolgen: Beim Compilieren sind entsprechende Optionen zu setzen. Dies sollte aber nach Möglichkeit automatisiert werden !
(Es sollte nicht erwartet werden, daß jeder Nutzer jederzeit weiß, welche Byte-Anordnung sein Rechner verwendet.)

Das folgende Programm demonstriert, wie die Byte-Anordnung ermittelt werden kann:

  PROGRAM bytcheck(OUTPUT);
  
  TYPE typ = (one, four);
       rec = RECORD
               CASE typ OF
                 one  : ( l : LONGINT );
                 four : ( b : ARRAY[1..4] OF BYTE );
               END;
  
  VAR r : rec;
  
  BEGIN
    WITH r DO BEGIN
      l := 1;
      IF b[1] = 1 THEN
        Writeln('Little Endian')
      ELSE IF b[4] = 1 THEN
        Writeln('Big Endian')
      ELSE
        Writeln('???');
    END;
  END.
Bei einer Portierung des Programms sind gegebenenfalls die verwendeten Datentypen anzupassen.
Das Programm ist in dieser Form unter Pascal++ und Turbo Pascal lauffähig.

Das folgende (Scherz-)Programm zeigt, daß die Beachtung der Byte-Anordnung wichtig sein kann:

  PROGRAM secret(OUTPUT);
  TYPE typ = ( int, ch );
       rec = RECORD
               CASE typ OF
                 int : ( i : ARRAY[1..4] OF LONGINT );
                 ch  : ( c : ARRAY[1..16] OF CHAR );
             END;
  VAR r : rec;
      k, l : INTEGER;
  BEGIN
    WITH r DO BEGIN
      i[1] := 16#48656c6c;
      i[2] := 16#6f2c2057;
      i[3] := 16#6f726c64;
      i[4] := 16#20210a00;
      IF Ord(c[1]) = 16#48 THEN
        FOR k:=1 TO 16 DO
          Write(c[k])
      ELSE
        FOR k:=0 TO 3 DO
        FOR l:=4 DOWNTO 1 DO
          Write(c[4*k+l]);
      Writeln;
    END;
  END.
Das Programm sollte auf "little endian" und "big endian" Maschinen funktionieren, gegebenenfalls müssen, wie schon oben erläutert, Anpassungen an das jeweilige Pascal-System vorgenommen werden.
Das Programm liefert
  Hello, World !


P. Böhme, 22.08.1996