TURBO Pascal 3.0 Projekte



TURBO Pascal und das Arbeiten mit Adressen

Bekanntlich verfügt TURBO Pascal 3.0 über drei unterschiedliche Zahlentypen:
  Typ       Bereich     Bytes im
                        Speicher
-------  -------------  --------
Byte         0..255        1
Integer  -32768..32767     2
Real      1E-38..1E38      6
Programierer, die sich z.B. mit den 16 Bit Adressen des Z80 herumschlagen, haben hier ein Problem. So ist die Adresse $FFFF deutlich grösser als die Adresse $0001. Trotzdem fällt der Vergleich mit den Standardroutinen (z.B. X<Y) falsch aus, da in TURBO die Zahl $FFFF als -1 interpretiert wird, die ja tatsächlich <1 ist.

Um vorzeichenlose 16 Bit Zahlen richtig vergleichen zu können, kann folgende Funktion eingesetzt werden:

function cmpwrd(x,y:integer):integer;
Begin
  if x=y then cmpwrd:=1
         else if ((x<y) xor ((x<0) xor (y<0))) then cmpwrd:=0
                                               else cmpwrd:=2;
End;
Diese Funktion liefert
  • 1, wenn beide Werte gleich sind
  • 0, wenn der erste Wert kleiner als der zweite ist
  • 2, wenn der erste Wert grösser als der zweite ist
Um ähnliche Vergleichsoperationen wie bei den Integeroperationen zur Verfügung zu haben, können beispielsweise folgende Funktionen eingesetzt werden:
function wEQ(x,y:integer):boolean;     function wNE(x,y:integer):boolean;
Begin                                  Begin
  wEQ:=(cmpwrd(x,y)=1);                  wNE:=(cmpwrd(x,y)<>1);
End;                                   End;
Diese beiden Funktionen lassen sich jedoch auch mit den Standardoperatoren programmieren:
    ires:=wEQ(x,y);    entspricht    bres:=x=y;
    ires:=wNE(x,y);    entspricht    bres:=x<>y;
(ires ist eine Integer, breg eine Bool'sche Variable)

Bei den anderen Vergleichen benötigt man jedoch neue Funktionen:

function wLT(x,y:integer):boolean;     function wGT(x,y:integer):boolean;
Begin                                  Begin
  wLT:=(cmpwrd(x,y)=0);                  wGT:=(cmpwrd(x,y)=2);
End;                                   End;
und
function wLTE(x,y:integer):boolean;    function wGTE(x,y:integer):boolean;
Begin                                  Begin
  wLTE:=((cmpwrd(x,y)=0) OR (x=y));      wLTE:=((cmpwrd(x,y)=2) OR (x=y));
End;                                   End;
Mit diesen Funktionen lassen sich ohne Probleme Vergleichsoperationen bei vorzeichenlosen 16 Bit Zahlen programmieren.

Ein anderes Thema ist die Ausgabe von Integers im Bereich $8000..$FFFF, weil in diesem Bereich alle Zahlen negativ dargestellt werden. Im folgenden stelle ich zwei Funktionen vor, die entweder eine Zahl hexadezimal darstellen, wie es eigentlich bei Arbeiten mit Adressen üblich ist, oder aber den oben genannten Bereich als positive Zahlen.

HEX

type
  HexStr       = string[4];

function Hex(val:integer):HexStr;
const
  HexTab       : array[0..15] of char='0123456789ABCDEF';
var
  str          : HexStr;
  i            : integer;
Begin
  str:='0000';
  for i:=4 downto 1 do
  begin
    str[i]:=HexTab[val AND $0F];
    val:=val SHR 4;
  end;
  Hex:=str;
End;
Hier wird also ein String aus vier Zeichen mit einer Zahl in Hexdarstellung zurückgegeben.

INTEGER

Um eine Integer Zahl im Bereich $8000..$FFFF positiv darstellen zu können, muß der Zahlenbereich erweitert werden, in diesem Fall mit einer Real. Folgende Funktion kann das übernehmen:
function wrd(x:integer):real;
Begin
  if x<0 then wrd:=65536.0+x
         else wrd:=x;
end;
Für die Ausgabe einer solchen Zahl bietet sich dann an:
write('Adresse=',wrd:0:0);
Nebenbei bemerkt hat TURBO Pascal 3.0 schon lange den Elchtest nicht bestanden. Wer es nicht glaubt, sollte die Funktion wrd wie folgt mal testen
program Elch(input,output);
var
  i            : integer;
  adr          : integer;

function wrd(x:integer):real;
Begin
  if x<0 then wrd:=65536.0+x
         else wrd:=x;
end;

BEGIN
  adr:=$7fff;
  for i:=1 to 3 do
  begin
    writeln(adr:6,' ist ',wrd(adr):0:0);
    adr:=succ(adr);
  end;
END.
Hier soll also der Übergang $7FFF -> $8000 -> $8001 getestet werden. Erwartet wird folgende Ausgabe:
       32767 ist 32767
      -32768 ist 32768
      -32767 ist 32769
Und das passiert:
       32767 ist 32767
      -32768 ist
Ja, und dann schwieg das Lamm, äh, der Elch. In der Tat liegt hier ein Fehler in der TURBO Run Time Library vor, undzwar exakt und nur für die Wandlung der Integer Zahl $8000 nach Real.


Abgedruckt in Klubzeitung Nr. 53. Autor: Werner Cirsovius