Talk About Network



Register and Login
Nick
Password
Register create new account Sign up is FREE and you can post replies, new topics, bookmark posts and more!
Recover lost password


Programming > Basic Powerbasic > PowerBASIC-FAQ,...
Latest [ Topics | Posts ] Archive Post A New Topic Post a Reply
<< Topic < Post Post 1 of 1 Topic 195 of 266
Post > Topic >>

PowerBASIC-FAQ, deutsche Ausgabe

by Thomas Gohel <gohel@[EMAIL PROTECTED] > Jul 2, 2006 at 04:15 PM

=============================================================================

        PowerBASIC.GER-FAQ für die Versionen 3.00, 3.10, 3.20 & 3.50
                            deutsche Version (DOS)

           (c) 1995/2005 von Thomas Gohel, Alle Rechte vorbehalten
                       Stand: 29.09.2005 - Version 1.00

       Tips, Tricks, Bugs und andere mehr oder weniger wichtige Sachen

=============================================================================


    =====================
    Vorwort zu dieser FAQ
    =====================

    Die in dieser FAQ aufgeführten Hinweise erfolgen ohne Berücksichtigung
    eventueller Copyright-Verletzung und ohne Rücksichtname eventuell
einge-
    tragener Warenzeichen.
    Des weiteren garantiert der Autor nicht für Richtigkeit der hier ange-
    führten Probleme, Tips & Bugs etc. Sollten Sie Anregungen oder Ver-
    besserungsvorschläge haben, so stehe ich diesen Sachen offen gegenüber
    und werde dies in zukünftigen Versionen der FAQ mit einfliessen
lassen.
        Ich möchte weiter darauf hinweisen, das einige der hier unter dem
    Abschnitt 'Fehler' aufgeführten Probleme im weiteren Sinne keine Bugs
    darstellen. Diese Ungereimtheiten bzw. verschwiegenen Einschränkungen
    gilt es hier für die Allgemeinheit zu dokumentieren (das es in Zukunft
    ein besseres PowerBASIC gibt).


    =======================
    Verbesserungsvorschläge
    =======================

    Verbesserungsvorschläge können Sie jederzeit an den Autor dieser FAQ
    richten, die aktuellen Netmail-Adressen lauten:

        Thomas Gohel@[EMAIL PROTECTED]
  (FidoNet)
        pbfaq@[EMAIL PROTECTED]
     (InterNet und Unternetze)

    Des weiteren besteht die Möglichkeit sich OnLine in eine Mailbox
einzu-
    loggen, in der der Autor dieser FAQ erreichbar ist:

        Port 1: (030) 473 00 910 (PBSOUND HQ, Berlin - 64.0, ISDN, X75,
V42B)
        Port 2: (030) 473 00 910 (PBSOUND HQ, Berlin - 33.6, VFC, V34,
FAX)

    Hier können Sie Ihre Vorschläge und Probleme los werden. Bitte
schreiben
    Sie dazu Ihre Nachricht in der PBSOUND-Nachrichten-Area. Eine Antwort
    sollten Sie spätestens nach 48 Stunden erhalten.


    ======================================
    Bezug der aktuellen PowerBASIC.GER-FAQ
    ======================================

    Die aktuelle PowerBASIC.GER-FAQ können Sie jederzeit aus meiner
Stammbox
    Online downloaden. Die Telefonnummern lauten:

        Port 1: (030) 473 00 910 (PBSOUND HQ, Berlin - 64.0, ISDN, X75,
V42B)
        Port 2: (030) 473 00 910 (PBSOUND HQ, Berlin - 33.6, VFC, V34,
FAX)

    Wechseln Sie nach dem Login in die 'PowerBASIC: FAQ'-Filearea.
    Des weiteren finden Sie hier noch 16 weitere 'PowerBASIC-Fileareas'

        PowerBASIC: PBSOUND
        PowerBASIC: Sound Blaster
        PowerBASIC: FAQ
        PowerBASIC: Sourcen (allgemein)
        PowerBASIC: Sourcen (Deutschland)
        PowerBASIC: Sourcen (Netherlands)
        PowerBASIC: Toolkits (allgemein)
        PowerBASIC: Toolkits (Deutschland)
        PowerBASIC: Toolkits (Netherlands)
        PowerBASIC: Grafik (allgemein)
        PowerBASIC: Grafik (Deutschland)
        PowerBASIC: Grafik (Netherlands)
        PowerBASIC: DFÜ, BBS und FidoNet Sourcen
        PowerBASIC: allgemeine Pakete und Info's
        PowerBASIC: Demos
        PowerBASIC: User Uploads / Incoming

    Viele in dieser FAQ erwähnten Sourcen und Toolboxen können Sie hier
    Online oder auch per FidoNet downloaden.

    InterNet-Teilnehmer können die PowerBASIC.GER-FAQ jederzeit via World
    Wide Web (WWW) unter:

        - http://www.gohel.de

    erreichen.

    Ein Request der FAQ über das FidoNet ist unter dem Magic 'PBFAQ'
    möglich!

        Port 1: (030) 473 00 910 (PBSOUND HQ, Berlin - 64.0, ISDN, X75,
V42B)
        Port 2: (030) 473 00 910 (PBSOUND HQ, Berlin - 33.6, VFC, V34,
FAX)

    Weiter PowerBASIC-Magics sind: PBSOUND und PBFILES.


    ============
    Gesamtinhalt
    ============

    1.  Bezug, Toolboxen, Preise und Info's zu PowerBASIC
    2.  Fehler/Ungereimheiten in den PowerBASIC-Versionen 3.0, 3.1 & 3.2
    3.  PowerBASIC und der CoProzessor
    4.  Standard-Probleme
    5.  Tip's in Verbindung mit dem InLine-Assembler
    6.  Tip's in Verbindung mit Pointern
    7.  Tip's in Verbindung mit Turbo-C bzw. Borland C++
    8.  Tip's bei der Konvertierung von Sourcen von PDS nach PowerBASIC
3.x
    9.  vorhandene Shareware & Public Domain-Lösungen
    10. Die PowerBASIC-Leute



    ====================================================
    1. Bezug, Toolboxen, Preise und Info's zu PowerBASIC
    ====================================================

    1.1. Die aktuelle Version von PowerBASIC
    1.2. Der Originalhersteller von PowerBASIC
    1.3. Deutschsprachiger Raum
    1.4. deutsche PowerBASIC-Preise
    1.5. Dänemark, Norwegen, Schweden und Finnland
    1.6. Neuigkeiten in der PowerBASIC 3.1 Version
    1.7. Neuigkeiten in der PowerBASIC 3.2 Version
    1.8. Neuigkeiten in der PowerBASIC 3.5 Version
    1.9. PowerBASIC 4.0 - The next Generation / Wishlist


    1.1. Die aktuelle Version von PowerBASIC
    ----------------------------------------
    Die aktuelle Version von PowerBASIC in Deutschland (seit Januar 1998)
    ist die Version 3.50. In den USA und in anderen Staaten ist diese
    Version bereits seit Dezember 1997 verfügbar.


    1.2. Der Originalhersteller von PowerBASIC
    ------------------------------------------
    PowerBASIC wird und wurde in den USA entwickelt und es befinden sich
    natürlich auch diverse Möglichkeiten mit diesen Leuten in Kontakt zu
    treten. Hier die aktuell bekannte Kontaktadresse von PowerBASIC Inc.:

    Addresse:
            PowerBASIC, Inc.
            1978 Tamiami Trail S.#200
            Venice, FL  34293

            Bestellung    : +1 (800) 780-7707
            Kundendienst  : +1 (941) 408-8700
            Fax           : +1 (941) 408-8820

    InterNet:
            World Wide Web                : www.powerbasic.com
            Liste der InterNet Addressen  : info@[EMAIL PROTECTED]
            Bestellung                    : order@[EMAIL PROTECTED]
            Verkauf und Marketing         : sales@[EMAIL PROTECTED]
            Technischer Support           : support@[EMAIL PROTECTED]
            Anregungen für zukünftige
            PowerBASIC Versionen          : suggest@[EMAIL PROTECTED]
    FTP- & WWW-Sites:
            http://pbsound.basicguru.com
            http://www.gohel.de
            http://www.xlsior.org
            http://www.basicguru.com
            http://www.uni-jena.de/~p6sepa/rshp.html
            http://home/t-online.de/home/mstadler/homepage.htm
           
http://www.leo.org/pub/comp/platforms/pc/msdos/programming/pbasic/
            http://www.fys.ruu.nl/~bergmann/basic.html
            http://www.zephyrsoftware.com
            http://www.blarg.net/~future/shareware.html
            http://www.cdrom.com/simtel.net/msdos/basic.html
            http://www.cyberbox.north.de/FILES/DOS/dos106.html
            ftp.global2000.net/pub/pbasic
    Newsgroups (englisch):
            alt.lang.powerbasic
            comp.lang.powerbasic
|   Newsgroups (deutsch):
|           news.kannofant.de/de.comp.lang.powerbasic
|           Hinweis: Nur nach Authentifizierung mit User/Password!
|                    (jeweils "basic")


    1.3. Deutschsprachiger Raum
    ---------------------------
    In Deutschland wird PowerBASIC vom deutschen Distributor: "Kirschbaum
    Software GmbH" vertrieben. Die aktuelle Adresse lautet:

            Kirschbaum Software GmbH
            Kronau 15
            83550 Emmering
            Tel.: 08067/9038-0
            Fax.: 08067/903898

    Die derzeit aktuelle Version von PowerBASIC ist die Version 3.50. Als
    aktuelle Toolboxen bietet Kirschbaum für PowerBASIC folgende Pakete
an:

        PB/DLL      - PowerBASIC DLL-Compiler für Windows
        PowerGRAPH  - für grafische Menüoberflächen (PCX, Fonts, etc.)
        PowerISAM   - Datenbanken (ebenfalls verfügbar in Englisch bei
                      PowerBASIC Inc.)
        PowerTOOLS  - SAA-Oberfläche, Hilfesystem, nützliche Routinen
        PB/xtra     - Sammlung von Sharewareprogrammen und Sourcecode

    Kirschbaum besitzt keine Mailbox bzw. offizielle EMailadressen!
Allerdings
    existieren für die Mitarbeiter bzw. für die Toolbox-Entwickler eigene
    EMail-Adressen und Support-Foren bzw. nicht öffentliche Newsgroup etc.
    In diesem Fall sehen Sie bitte in dem Handbuch der betreffenden
Toolbox
    nach.


    1.4. deutsche PowerBASIC-Preise
    -------------------------------
    Alle hier genannten Preise sind nicht verbindlich! Änderungen oder Ab-
    weichungen können jederzeit auftreten! Eine aktuelle und gültige
Preis-
    liste kann jederzeit bei Kirschbaum Software per FAX angefordert
werden.

    Vollversion: 199,-DM
    Vollversion 3.5 für Studenten, Schüler: 150,-DM
    Update von VOBIS-Basisversion 2.10f auf V3.2: 149,-DM
    Update von V2.10 auf V3.5: 149,-DM
    Update einer 3.x-Version auf V3.5: 36,80DM


|   1.5. Dänemark, Norwegen, Schweden und Finnland
|   ----------------------------------------------
|   In einigen europäischen Ländern (incl. Deutschland und Östereich)
|   wird PowerBASIC von:
|
|            Berggreen Service
|            Lodsgaarden A 111
|            DK-2791 Dragoer
|            DENMARK
|            info@[EMAIL PROTECTED]
|            http://www.berggreen.dk
|
|            vertrieben.


    1.6. Neuigkeiten in der PowerBASIC 3.1 Version
    ----------------------------------------------
    - Benutzerdefinierte TYPE- und UNION-Variablen können nun direkt
      verglichen werden.
    - Konstanten im Binaer-, Hex- oder Oktalformat (&B, &H, &O) können
      einem bestimmten Datentyp zugeordnet werden, indem man den ent-
      sprechenden Identifier anhängt.

      Beispiel:
              A?? = &HFFFF??   '= 65535
              B%  = &HFFFF%    '= -1

    - Konstanten (%Test) können ab dieser PowerBASIC-Version Werte im
      64-Bit-Wertebereich (vorzeichenbehaftet) annehmen.

      Beispiele :
              %MaxAnzahl = 500000
              %Konst1    = &HFFFF   '= -1 (Integer)
              %Konst2    = &H0FFFF  '= 65535 (Long)

      Bei Angaben Binaer-, Hexadezimal oder Oktalformat kann man durch
      Angeben oder Weglassen einer führenden Null festlegen, ob der
      erzeugte Wert vorzeichenbehaftet ist oder nicht.

    - BIN$, HEX$ und OCT$ können jetzt Werte bis zu 32bit Long-Integer
      ausgeben.

    - Ab PB 3.10 können Sie alternative Namen für SUBs oder FUNCTIONs
      vergeben, unter denen Sie dann diese Unterroutinen aus OBJ-Routinen
      (mit Assenbler oder C erzeugt) aufrufen koennen.

      Beispiel:
              SUB MySub ALIAS "_my_sub" (Var1%,Var2$) PUBLIC
                      PRINT "Hallo", Var1%, Var2$
              END SUB

    - Das Schlüsselwort ANY in einer Prozedurdefinition erlaubt die
      Übergabe eines Parameters beliebigen Typs. Der Parameter wird
      per REFERENCE als 32bit-Adresse übergeben. Damit das aufgerufene
      Programm weiss um welchen Typ es sich handelt sollten Sie einen
      Typecode als ersten Parameter mit übergeben. Wird die Routine
      in PowerBASIC codiert so muss zur Übernahme des Parameters der
      Inline-Assembler genutzt werden.

      Beispiel:
              i% = 11
              CALL TestAny(0,i%)      'die freien Parameter müssen
                                      'Variablen sein
              s$ = "Hallo"
              CALL TestAny(1,s$)

              SUB TestAny(ParamType AS INTEGER, ANY)
                  DIM Int.Param    AS INTEGER
                  DIM String.Param AS STRING
                  SELECT CASE ParamType
                      CASE 0                  'Integer
                          ! les bx, [bp+6]    :Offset der Var. in BX laden
                          ! mov ax, es:[bx]   ;Wert der Var. in AX laden
                          ! mov Int.Param, ax ;Variable mit AX (Wert)
laden
                          PRINT Int.Param
                      CASE 1                  'String
                                              ;Offset der  Stringkennung
                          ! les bx, [bp+6]    ;in BX laden
                          ! mov ax, es:[bx]   ;Stringkennung in AX laden
                          ! mov String.Param,AX
                          PRINT String.Param
                  END SELECT
              END SUB

    - Rückgabewerte von FUNCTIONs die mit dem Inline-Assembler geschrieben
      wurden, können jetzt auch ohne eine Zwischenvariable mit einem Wert
      belegt werden. Dazu dient das Schlüsselwort FUNCTION.

      Beispiel:

              PRINT AsmTest(2)
              FUNCTION AsmTest(BYVAL int.param AS INTEGER) AS INTEGER
                      ! mov ax, int.param
                      ! inc ax
                      ! mov FUNCTION, ax  ;der Wert wird zurückgeliefert
              END FUNCTION

      (siehe auch Tips mit dem Inline-Assembler)

    - Die Verwendung von FUNCTION anstelle des Funktions-Namens ist auch
      bei BASIC-Codierten FUNCTIONs möglich.

      Beispiel:
              PRINT FuTest(2)
              FUNCTION FuTest(BYVAL int.param AS INTEGER) AS INTEGER
                     FUNCTION = int.param + 1
              END FUNCTION

    - Die Funktion FRE() wurde erweitert :
      FRE(-3) gibt den freien Speicherplatz für den Stack zurück
      FRE(-4) gibt die maximale Länge für dynamische Strings zurück, die
              mit $STRING gesetzt wurde
      FRE(-5) gibt die Anzahl der belegten Stringsegmente zurück
      FRE(-6) gibt die Anzahl der unbenutzten Blöcke im aktuellen String-
              segment zurück
      FRE(-7) gibt die Größe des unbenutzten Speichers im aktuellen
              Stringsegment zurück


    1.7. Neuigkeiten in der PowerBASIC 3.2 Version
    ----------------------------------------------
    - Data Pointers
    - Code Pointers
      Es können nun folgende Sprünge direkt in Basic ausgeführt werden:
      "CALL DWORD x", "GOTO DWORD x" und "GOSUB DWORD x" . "x" ist in
      diesem Fall der 32bit Zeiger auf die SUB/FUNCTION oder das Label.
      (Zu den neuen Pointer-Funktionen existiert ein DIR$-Demo)

    - 32-Bit Umsetzung von:
      STRPTR32, VARPTR32 und CODEPTR32

    - Zeiger/Pointer auf Strukturen können an eine SUB/FUNCTION mit dem
      Schlüsselwort "BYVAL" übergeben werden.

      Beispiel:
              DECLARE SUB MySUB(x AS INTEGER)
              DIM z AS INTEGER PTR
              z = &HB8000000
              CALL MySUB(BYVAL z)

    - 16550 UART Unterstützung

    - Die LEN() Funktion liefert nun auch die Länge von User-definierten
      Strukturen zurück.

    - Label und Variablen können nun zur besseren Unterscheidung auch so-
      genannte Underlines '_' enthalten.



    1.8. Neuigkeiten in der PowerBASIC 3.5 Version
    ----------------------------------------------
    - einige wichtige Bugfixes.
    - ASCIIZ Strings: DIM xyz as ASCIIZ * 100.
    - Arrays als dürfen als Benutzertyp nun 1 oder 2 statische Dimensionen
      enthalten.
    - & Operator wird erkannt als STRING Verbindung.
    - STRING PTR ist jetzt eine legale Strutur in TYPE/UNION
    - $ELSEIF metastatement.
    - ASC(x$,n) Funktion und Befehl bieten eine optionale Anfangsposition.
    - REDIM PRESERVE nur an den äußeren Grenzen von dynamischen und HUGE
      Arrays.
    - RND() ist ein zuläßiger Ersatz fuer RND.
    - RND(x,y) liefert ein LONG INTEGER im Bereich x -> y zurück.
    - TRIM$() ist eine Kombination aus LTRIM$() und RTRIM$().
    - Indexed pointers:   @[EMAIL PROTECTED]
    - DIM VIRTUAL x(1000000) reserviert Arrayspeicher im EMS, darf aber
nicht
      als dynamischer String oder als BYREF Parameter benutzt werden.
    - HUGE und VIRTUAL Arrays dürfen LONG INTEGER Indexe verwenden. Mit
      dieser Erweiterung kann man einen leichten Anstieg bei der Größe
      des generierten Codes bemerken. Wenn ein Segment nun sehr nahe zum
      64k Limit ist, benötigt es evtl. das $SEGMENT Metastatement um
      verschoben zu werden.
    - ERRCLEAR Befehl setzt das Errorflag auf Null.
    - ERRCLEAR Funktion gibt ERR zurück, und setzt dann das Errorflag auf
      Null.
    - ERRCLEAR ist ein synonym fuer die alte Funktion ERRTEST.
    - CVI(x$[,n]), CVL... bieten eine optionale Startposition innerhalb
      des Strings.
          - CVL(X$,3) extrahiert das dritte bis sechste Byte von x$ und
            konvertiert die 4 Byte in die entsprechende LONG INTEGER
            Zahl. In diesem Fall muss x$ mindestens 6 Byte lang sein.
    - SIZEOF(var) Funktion gibt die physikalische Größe einer Variable
      zurück,
          - besonders nützlich beim Feststellen der maximalen Länge
            eines fixed-length String, ASCIIZ String oder einer User
            definierten TYPE Struktur
          - Gibt immer 2 für einen dynamischen String zurück.
    - STDIN x, y$ liest bis zu x Zeichen vom Standard Eingabegerät,
(welches
      umgeleitet werden kann), und weist sie der Stringvariable zu. Wenn
      weniger als x Zeichen sofort bereit sind, dann wird ein String
kürzer
      als x Byte zurück gegeben.
    - STDIN LINE, y$ liest eine Zeile Text direkt vom Standard
Eingabegerät,
      (welches umgeleitet werden kann) und weist sie der Stringvariable
zu.
      Wenn EOF erreicht wird, wird ein 1 Byte langer String mit CHR$(26)
      zurück gegeben.
    - STDOUT x$ [;] gibt den Stringausdruck x$ auf dem Standard
Ausgabegerät
      aus, (welches umgeleitet werden kann), gefolgt von einem CR/LF. Wenn
      das optionale angehängte Semikolon hinzugefügt wurde, dann wird das
      CR/LF unterdrückt.
    - SETEOF #1 Befehl wurde hinzu gefügt, um eine offene Datei an ihrer
      momentanen Position abzuschneiden.
    - FRE(-11) gibt die Anzahl der nicht allokierten Bytes im EMS Speicher
      zurück.


    1.9. PowerBASIC 4.0 - The next generation / wishlist
    ----------------------------------------------------
    So kurz nach einer aktuellen Release V3.5 des Compilers ist es
natürlich
    sehr, sehr schwer Punkte für Verbesserungen zu finden, aber es gibt
sie
    natürlich trotzdem.

    - XMS Support für VIRTUAL Arrays
    - SORT ARRAY Support für VIRTUAL Arrays
    - 32bit Inline-Assembler
    - Syntax Highlighting in der IDE
    - eine bessere IDE



    ====================================================================
    2. Fehler/Ungereimtheiten in den PowerBASIC-Versionen 3.0, 3.1 & 3.2
    ====================================================================

    Kurzübersicht:
    2.0.  PowerBASIC-Fehlerbibliotheken
    2.1.  Das NUMERIC/OVERFLOW-Problem in PowerBASIC 3.0
    2.2.  Das NUMERIC/OVERFLOW-Problem in PowerBASIC 3.1/3.2
    2.3.  Kein Overflow-Fehler beim Doubleword
    2.4.  Absturz der PowerBASIC IDE und fertiger EXE's beim Laden
    2.5.  unterschiedlich große EXE-File beim Komplieren mit PB/PBC
    2.6.  unterschiedliche EXE-Files bei gleicher Kompilation
    2.7   Probleme mit der Maus innerhalb der IDE
    2.8.  Das Fixup Overflow Syndrom
    2.9.  Die Sache mit dem ASCII-154 nach einen REMARK im Inline-ASM
    2.10. Fehler 454: END FUNCTION expected
    2.11. Noch ein REMARK-Problem bei $ALIAS
    2.12. Der Fehler CDWRD in der deutschen OnLine-Hilfe
    2.13. Der Fehler CVDWRD in der deutschen OnLine-Hilfe
    2.14. Absturz bei Betätigen von CNTRL-C
    2.15. Fehler bei Verwenden der Ausgabe über "CONS:" und CNTRL-C
    2.16. Die Sache mit dem Fehler 244 in einer Stand Alone EXE-Datei
    2.17. Probleme bei Verkettung mehrerer Zeilen Sourcecode
    2.18. Probleme mit dem WATCH-Fenster und mehrdimensionalen Arrays
    2.19. Fehlerhafte interne Funktion/Variable: pbvScrnCols
    2.20. unkorrekte interne Funktion/Variable: pbvHost
    2.21. Ein kleiner Unterschied im neuen InLine-Assembler der V3.1/3.2
    2.22. Das dd-Problem bei PowerBASIC 3.1/3.2
    2.23. undokumentierte interne Variablen in PowerBASIC 3.0/3.1/3.2
    2.24. Der PRINT-Bug in PowerBASIC 3.2
    2.25. Der Fehler "File not found" nach Verwendung von NAME
    2.26. Rechenfehler bei der Verwendung von Konstanten
    2.27. falsches "Bit schieben" bei ROTATE
    2.28. Overflow bei Verwendung von FOR/NEXT-Schleifen
    2.29. Overflow bei Verwendung von STEP -1 in FOR/NEXT-Schleifen
    2.30. Der Bug im VARPTR32-Befehl
    2.31. Der "KEY ON" Bug
    2.32. Absturz der PowerBASIC IDE im Pick-Menü
    2.33. Absturz der PowerBASIC IDE bei fehlerhaften Syntax
    2.34. falsches Vertauschen der Variablen bei Verwendung von SWAP
    2.35. Der Multiplexer Interrupt Fehler im REG-Befehl
    2.36. Inhalt eines Verzeichnis wird mit KILL gelöscht
    2.37. Die Sache mit der Zeichenkette "USR"
    2.38. Laufzeitfehler im PowerBASIC Helpcompiler
    2.39. Der Fehler Truncating im PowerBASIC Helpcompiler
    2.40. Absturz der PowerBASIC-IDE nach Aufruf der eigenen Hilfe


    2.0. PowerBASIC-Fehlerbibliotheken
    ----------------------------------
    Zur besseren Sicherheit Ihrer eigenen Programme empfehle ich
prinzipiell
    die Einbindung aller Fehlerbibliotheken. Nur so können Sie sicher
sein,
    das PowerBASIC auch den wahren Fehler anzeigt und z.B. nicht bei:

            SELECT CASE pbvrevision

    mit einem unerklärlichen Fehler aussteigt. Im fertigen Programm
könnnen
    Sie die Bibliotheken wieder entfernen, da sie eigentlich nur während
der
    Programmentwicklung wirklich benötigt werden.
    Die $ERROR-Bibliotheken können Sie innerhalb der IDE ständig einbinden
    oder direkt in Ihrem Sourcecode definieren. Die Einstellungen im
    Sourcecode haben gegenüber den Einstellungen der IDE Vorrang!

    Die $ERROR-Bibliotheken binden Sie wie folgt ein:

            $ERROR NUMERIC ON
            $ERROR OVERFLOW ON
            $ERROR BOUNDS ON
            $ERROR STACK ON

    Achtung: Einige der hier aufgezeigten Ungereimtheiten können nur mit
             diesen Bibliotheken aufgedeckt werden!




    2.1. Das NUMERIC/OVERFLOW-Problem in PowerBASIC 3.0
    ---------------------------------------------------
    Versionen: 3.0
    bekannt  : teilweise in Version 3.10 beseitigt

    Die hier aufgeführten Probleme beziehen sich nur auf die Verwendung
von
    vorzeichenlosen Variablen und werden an Variablen vom Typ WORD
    aufgeführt:

    Beispiel 1:
            Demo?? = &hA000

    führt zu einem Overflow, da PowerBASIC dies als vorzeichenbehaftete
    Variable versucht zu interpretieren. Dieser Fehler kann nur durch
Angabe
    einer Realzahl umgangen werden.
    Ähnliche Effekte lassen sich im $NUMERIC-System auch bei Verwendung
des
    REG()-Befehles nachvollziehen:

    Beispiel 2:
            Demo?? = REG(1)

    kann unter Umständen ebenfalls zu einem Überlauf führen, sofern der
    übergebene Wert als INTEGER negativ wäre. Den Fehler können Sie um-
    schiffen, sofern sie bei der Verwendung von REG() nur Variablen vom
Typ
    INTEGER verwenden, die NUMERIC-Bibliothek beim Kompilieren entfernen.
    Noch viel besser ist es allerdings, den alten BASIC-Unsinn über Bord
zu
    werfen und die Geschichte gleich im InLine-Assembler sauber zu pro-
    grammieren! ;-)

    Interessant ist auch das 'Verschleppen' von Fehlern bei
ausgeschalteter
    $ERROR NUMERIC Bibliothek. Der Fehler tritt dann etwas später im
    Programm auf, komischerweise aber ebenfalls bei Variablen vom Typ
WORD.
    Eigenartigerweise läßt sich dies am besten mit den internen
PowerBASIC-
    Variablen vom Typ WORD nachvollziehen.

    Ein weiterer Overflow-Effekt verbirgt sich in den
PowerBASIC-Funktionen
    STRSEG/STRPTR, VARSEG/VARPTR, CODESEG/CODEPTR. Im Gegensatz zum REG()
    Befehl müssen die Variablen definitiv vom Typ WORD sein, ansonsten
    droht wiederum ein Überlauf in größeren Programmen.


    2.2. Das NUMERIC/OVERFLOW-Problem in PowerBASIC 3.1/3.2
    -------------------------------------------------------
    Versionen: 3.1/3.2
    bekannt  : Nachbesserung bei PowerBASIC Inc. verlangt

    Man soll nicht denken, das eine neue Version auch die ganzen alten
Fehler
    in Vergessenheit geraten läßt ;-).

    Beispiel 1:
            Demo?? = &hA000

    kann weiterhin zu einem Überlauf führen. Leider läßt sich dieser
Fehler
    nicht mehr in einer Zeile demonstrieren, da er gelegentlich in sehr
    komplexen Programmen weiterhin auftritt. Das hat sich mit PowerBASIC
    in der Version 3.20 leider immer noch nicht geändert.
    Im Gegensatz zur Version 3.00 kann der Fehler aber durch explizente
    Unsigned-Angabe beseitigt werden:

            Demo?? = &h0A000

    Sollten Sie Toolbox-Entwickler sein und auf Nummer sicher gehen
wollen,
    dann geben Sie in folgene Zeile ein, sofern Ihre Sourcen auch unter
    PowerBASIC 3.0 laufen sollen:

            ! mov ax, &hA000
            ! mov Demo??, ax

    Beispiel 2:
            Demo?? = REG(1)

    führt meines Erachtens nicht mehr zu einem Overflow, ganz
ausschliessen
    kann ich dies aber nicht. Trotzdem sollte man bei der Verwendung von
REG
    weiterhin nur Variablen vom Typ INTEGER verwenden. Viele PowerBASIC-
    Funktionen funktionieren jetzt besser, andere bereiten trotzdem
Probleme.
    Dies betrifft wieder diverse spezielle Routinen welche nur für
Integer-
    Variablen ausgelegt sind, aber trotzdem mit Variablen vom Typ WORD
    funktionieren.

    Das Overflow-Problem bei STRSEG/STRPTR, VARSEG/VARPTR und
CODESEG/CODEPTR
    ist weiterhin existent.


    2.3.  Kein OVERFLOW-Fehler beim Doubleword
    ------------------------------------------
|   Versionen: 3.0/3.1/3.2/3.5
|   bekannt  : ja

    Für Variablen vom Typ Doubleword ist in PowerBASIC kein Overflowtest
    integriert. Dies können Sie an einem kleinen Beispiel testen.

    Beispiel:
            i??? = -1
            PRINT i???

    Die Ursache für diesen Mangel liegt in der Intel CPU selbst begründet,
    denn dort gibt es keinen Overflow den der Compiler auswerten könnte.


    2.4. Absturz der PowerBASIC IDE und fertiger EXE's beim Laden
    -------------------------------------------------------------
    Versionen: 3.0/3.1 (3.2 nicht getestet)
    bekannt  : nein (teilweise)

    Ein Absturz der IDE beim Laden tritt eigentlich recht selten auf und
ist
    im Prinzip immer auf folgende Ursachen zurückzuführen:

        - QEMM Speicherverwaltungsmanager (bis Version 7.03)
        - extrem wenig verfügbarer Arbeitsspeicher
        - Sie haben versucht die IDE mit dem Befehl LOADHIGH zu laden
        - 4DOS

    In den meisten Fällen wird die IDE während des Ladevorganges mit einem
    Grafikfehler (Cursor innerhalb der IDE) auf die Kommandozeile zurück-
    kehren.
    Ebenfalls betroffen von diesem Effekt sind alle fertigen
PowerBASIC-EXE
    Files. Wollen Sie diesen Effekt auf alle Fälle umgehen, so müssen Sie
    die PowerBASIC-EXE mit einem EXE-Packer wie PKLITE komprimieren.


    2.5. unterschiedlich große EXE-File beim Komplieren mit PB/PBC
    --------------------------------------------------------------
    Eigentlich ist dies kein Fehler, da es nur einen kleinen Unterschied
in
    der Wirkungsweise des IDE-Compilers zu dem Kommandozeilencompiler
gibt,
    welche die unterschiedlich großen EXE-File erklärt.
    Die IDE compiliert die EXE-Datei immer nach den Einstellungen in der
IDE,
    das heißt wenn Sie dort zum Beispiel die VGA-Lib nicht mit compilieren
    wollen, so geben sie das als Standard in der IDE an. Der PBC
compiliert
    dagegen die VGA-Lib immer mit, sofern sie das nicht als Metastatment
    anderweitig deklariert haben.
    Die Metastatment-Einstellung haben immer Vorrang vor den Einstellungen
    in der IDE!


    2.6.  unterschiedliche EXE-Files bei gleicher Kompilation
    ---------------------------------------------------------
    Versionen: 3.0/3.1
    bekannt  : anscheinend

    Einen netten Effekt gibt es zu berichten, sofern Sie Sourcen mehrmals
    compilieren und diese dann mit einem Filevergleich-Utility einer
genauen
    Betrachtung unterziehen. Sofern sich Ihr verfügbarer freier Speicher
    geändert hat, werden die erstellten EXE-Files unterschiedlich sein.

    Meines Erachtens speichern die beiden PowerBASIC Compiler auch
    Ursprungsinformationen mit ab, welche vom Typ Integer/Word sind und
sich
    immer an den Offset's &h9C/&hA0 befinden (PB3.1). Dieser Effekt läßt
    sich mit der PB-IDE und auch dem PBC nachvollziehen.

    Nach einigen Auskünften sollen PB-EXE-Files, welche unter einer
    PowerBASIC-SHELL mit PBC compiliert wurden zum Abstürzen neigen.

    Da ich aber selbst seit ca 2 Jahren alle meine Projekte auf ähnliche
    Weise compiliere, kann ich diesen Effekt nicht nachvollziehen oder
    bestätigen. In Version 3.0 des PowerBASIC-Compilers schien allerdings
    der SHELL-Befehl anderweitige Effekte bei großen EXE-File auszulösen.
    Die Probleme lösten sich damals mit der Verwendung eines alternativen
    PBSHELL-Befehls.


    2.7  Probleme mit der Maus innerhalb der IDE
    --------------------------------------------
    Versionen: 3.0
    bekannt  : anscheinend in Version 3.1 behoben

    Sollten Sie innerhalb der IDE mit der Maus arbeiten damit Sie
komfortabel
    Sourcecode Einfügen und Ausschneiden können, so kann dies beim
Markieren
    längerer Texte (welche den rechten Bildschirmrand überschreiten) zu
einem
    Teilabsturz führen. Des weiteren markiert der Maus-Cursor die Texte
nicht
    richtig. Sie erkennen das daran, das Sie in der Regel eine längere
Zeile
    nicht markieren können.
    Des weiteren scheint es vereinzelt Probleme mit der Mausunterstützung
zu
    geben, Sofern sie den 80*43/50'er Textmodus verwenden.


    2.8. Das Fixup Overflow Syndrom
    -------------------------------
    Versionen: 3.0/3.1/3.2
    bekannt  : Nachbesserung bei PowerBASIC Inc. verlangt

    So jetzt kommen wir zu meinem Lieblingsfehler, zumal er eigentlich
durch
    einen ernsthaften Programmierfehler seitens des PowerBASIC Anwenders
    ausgelöst wird. Die Beschreibung im Handbuch, sowie der OnLine-Hilfe,
    ist leicht irreführend dennoch prinzipiell richtig.

    Ich persönlich würde den Fehler wie folgt beschreiben:

    <neue Fehlerbeschreibung>
    PowerBASIC konnte die angegebene Sprungadresse nicht finden. Eine
    mögliche Ursache ist ein SHORT-Sprung zu einem Label der nicht im
    gültigen Bereich für einen SHORT-Sprung liegt. Bitte Überprüfen Sie
alle
    Sprungbefehle auf Ihren Gültigkeitsbereich.
    <Ende>

    Leider hat sich gerade bei dieser Fehlermeldung in beiden PowerBASIC
    Versionen ein Fehler eingeschlichen. Da die menschliche Natur
prinzipiell
    nicht so recht glauben will was da so steht, wird die Source eben
    nochmals (ohne Änderung) kompiliert. Die IDE quittiert das sofort mit
    einem Absturz.

    Eine genauere Beschreibung des Zusammenspiels der einzelnen Assembler-
    Befehle, vor allem die verschiedenen Adressierungsarten in
Abhängigkeit
    von der CPU, erspare ich mir hier. Dafür gibt es jede Menge Assembler-
    Bücher, meines Erachtens eh eine Voraussetzung zur sinnvollen
    Programmierung mit dem InLine-Assembler.


    2.9. Die Sache mit dem ASCII-154 nach einen REMARK
    --------------------------------------------------
    Versionen: 3.0/3.1/3.2
    bekannt  : Fehler in Version 3.50 beseitigt

    Eine nette Sache kann Sie zum Beispiel in Verbindung mit einer guten
    Kommentierung Ihrer InLine-Assembler Source schlichtweg zum Wahnsinn
    treiben: Die Sache mit dem Sonderzeichen ASCII-154 nach einem REMARK
    (REM bzw. ; ):

    Beispiel:
            CLS
            PRINT "1"
            ! nop                ; Ü   <- (ASCII-154)
            PRINT "2"

    PowerBASIC wird in diesem Fall die Programmausführung bis zu der Zeile
    mit dem Sonderzeichen (nach dem REM) fortsetzen und dann stoppen. Die
    hartgesottenen können diese Sache auch einmal mit dem Debuger
verfolgen.
    In diesem Fall werden Sie feststellen, das PowerBASIC nach dem REMARK
    einfach nur noch sieben ASCII-Nullen an den Code anhängt und das
weitere
    Compilieren einstellt.


    2.10.  Fehler 454: END FUNCTION expected
    ----------------------------------------
    Versionen: 3.0/3.1/3.2
    bekannt  : Fehler in Version 3.50 beseitigt

    Diese Fehler kann auftreten, sofern der kommentierte Text einer
Inline-
    Assemblerzeile das ASCII-154 Zeichen enthält. Lesen Sie sich bitte
auch
    den vorherigen Absatz durch.


    2.11. Noch ein REMARK-Problem bei $ALIAS
    ----------------------------------------
    Versionen: 3.0/3.1/3.2/3.5
    bekannt  : Fehler in Version 3.50 beseitigt

    Der Fehler ist wieder recht einfach zu beschreiben. Sie dürfen bei der
    Verwendung von $ALIAS kein ':' (ASCII 58) nach einem REMARK verwenden,
    da dies PowerBASIC mit einem Fehler 462 (nicht definierte
SUB/FUNCTION)
    interpretiert. Dieses Problem tritt nur Aufgrund der GWBASIC Abwärts-
    kompatibilität auf!

    Beispiel:
            $ALIAS DATA AS "_DATA"  ': C-Segmente an PowerBASIC anpassen
                                     ^
                                     führt zum Fehler 462


    2.12. Der Fehler CDWRD in der deutschen OnLine-Hilfe
    ----------------------------------------------------
    Versionen: 3.0 (nur deutsche Version)

    In der OnLine-Hilfe hat sich ein Tipfehler eingeschlichen, statt dem
    richtigen Befehl 'CDWD' wird der Befehl mit 'CDWRD' beschrieben. In
den
    deutschen Handbüchern ist der Syntax aber korrekt erklärt.

    Beispiel:
            i??? = 1
            PRINT CDWRD(i???)        : 'falscher  Syntax
            PRINT CDWD(i???)         : 'richtiger Syntax


    2.13. Der Fehler CVDWRD in der deutschen OnLine-Hilfe
    -----------------------------------------------------
    Versionen: 3.0 (nur deutsche Version)

    Analog wir bei dem Syntaxfehler 'CDWRD' hat sich auch hierbei ein
Fehler
    in der OnLine-Hilfe eingeschlichen, der Syntax lautet wie im deutschen
    Handbuch korrekt beschrieben 'CVDWD'.


    2.14. Absturz bei Betätigen von CNTRL-C
    ---------------------------------------
    Versionen: 3.0
    bekannt  : Fehler in Version 3.10 beseitigt

    Dieser Fehler ist im allgemeinen bekannt und tritt nur auf wenn Sie
die
    Compileroption $OPTION CNTLBREAK OFF verwenden, während das BREAK-Flag
    auf DOS-Ebene auf ON gesetzt ist (normalerweise ist dies aber von
MS-DOS
    eh auf OFF gesetzt). Betätigen Sie unter diesen Vorrausetzungen nun
die
    Tastenkombination CNTL-C, dann stürzt Ihr fertiges Programm gelinde
    gesagt ab.
    Abhilfe schafft das Sperren des BREAK-Flag's per eigener PowerBASIC-
    Funktion. Dies können Sie zum Beispiel durch folgende Routinen
erreichen:

            SHARED BreakFlag%
            FUNCTION BreakAus public
                    'Controll-Break-Interrupt sichern und abschalten
                    ! mov ax, &h3300
                    ! int &h21
                    ! mov BreakFlag%, dx
                    ! mov ax, &h3301
                    ! mov dx, 0
                    ! int &h21
            END FUNCTION

            FUNCTION BreakReset public
                    'Control-Break-Interrupt restaurieren
                    ! mov ax, &h3301
                    ! mov dx, BreakFlag%
                    ! int &h21
            END FUNCTION

    In einigen Mailboxen befindet sich auch eine Datei namens CNTL.ZIP,
    welche den offiziellen BugFixed darstellt.


    2.15. Fehler bei Verwenden der Ausgabe über "CONS:" und CNTRL-C
    ---------------------------------------------------------------
    Versionen: 3.0
    bekannt  : Fehler in Version 3.10 beseitigt

    Dieser Fehler ist ebenfalls eine Auswirkung des CNTRL-C Bugs, während
    der Ausgabe über "CONS:" kann es zu Nebeneffekten kommen. Näheres ist
    mir pesönlich nicht bekannt.


    2.16. Die Sache mit dem Fehler 244 in einer Stand Alone EXE-Datei
    -----------------------------------------------------------------
    Versionen: 3.0
    bekannt  : Fehler in Version 3.10 beseitigt

    Sollten Sie PowerBASIC 3.0 nutzen und öfters im InLine-Assembler
    programmieren, so kann es in Verbindung mit den beiden internen
    PowerBASIC-Funktionen:

            GetStrLoc
            GetStrAlloc

    zu dem oben genannten Fehler 244 (Bibliothek nicht vorhanden) kommen.
    Dieser Fehler tritt nur in einer Stand-Alone-EXE Datei auf und nicht
    innerhalb der PowerBASIC-IDE. Als Voraussetzung müssen sich die beiden
    internen PowerBASIC-Funktionen innerhalb einer PowerBASIC Unit (PBU)
    befinden. Als Abhilfe müssen Sie die beiden PowerBASIC-Funktionen
    STRSEG/STRPTR benutzen, die Werte dann zwischenspeichern und danach
auf
    die betreffenden Prozessorregister schieben.


    2.17. Probleme bei Verkettung mehrerer Zeilen Sourcecode
    --------------------------------------------------------
    Versionen: 3.0/3.1
    bekannt  : Fehler in Version 3.20 beseitigt

    Die PowerBASIC-IDE, sowie der Kommandozeilen-Compiler, haben
allgemeine
    Probleme, wenn Sie Sourcecode über mehrere Zeilen verteilen, welcher
    normalerweise in eine Zeile gehört.

    Beispiel:
            C$ = CHR$( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)+_
                 CHR$( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)

    Gerade in Verbindung mit großen Projekten hat sich gezeigt, das der
    Compiler zu einer falschen Interpretation neigt, sprich: An
irgendeiner
    Stelle im Sourcecode meldet der Compiler einen für Sie unerklärlichen
    Fehler. In vielen Fällen bleibt der Cursor aber an richtigen Stelle
    stehen.


    2.18. Probleme mit dem WATCH-Fenster und mehrdimensionalen Arrays
    -----------------------------------------------------------------
    Versionen: 3.0/3.1
    bekannt  : Fehler in Version 3.2 beseitigt

    Das WATCH-Fenster kann keine mehrdimensionalen Arrays korrekt dar-
    stellen.


    2.19. Fehlerhafte interne Funktion/Variable: pbvScrnCols
    --------------------------------------------------------
    Versionen: 3.0/3.1/3.2
    bekannt  : nein

    Diese interne Variable soll Ihnen die Anzahl der angezeigten
Bildschirm-
    spalten zurückliefern. In Verbindung mit allen Modies welche nicht die
    40'er bzw. 80'er Spaltenanzahl verwenden, wird nicht die korrekte
Anzahl
    der Bildschirmspalten zurück geliefert. Solche Modies können Sie auf
    jeder VGA-Karte einstellen und diverse Tools (u.a. Disk Command
Center)
    unterstützen dies sogar!
    Abhilfe schafft hierbei wieder eine eigene Funktion:

            DIM fixScrnCols AS BYTE
            ! mov  ah, &h0f
            ! int  &h10
            ! mov fixScrnCols, ah


    2.20. unkorrekte interne Funktion/Variable: pbvHost
    ---------------------------------------------------
    Versionen: 3.0/3.1/3.2
    bekannt  : nein

    Das Bit 8 ist unter Microsoft Windows(NT) 3.x nicht gesetzt.


    2.21. Ein kleiner Unterschied im neuen InLine-ASM der V3.1/3.2
    --------------------------------------------------------------
    Versionen: 3.1/3.2
    bekannt  : Nachbesserung bei PowerBASIC Inc. verlangt

    Dieser Fehler ist recht einfach erklärt, während PowerBASIC 3.0 im
    Inline-Assembler folgende Zeile zuläßt:

            ! mov ax, &h0A000

    verweigert PowerBASIC 3.1/3.2 an dieser Stelle die Zusammenarbeit,
    obwohl das Feature in der Version 3.1/3.2 neu ist.


    2.22. Das dd-Problem bei PowerBASIC 3.1/3.2
    -------------------------------------------
    Versionen: 3.1/3.2
    bekannt  : Feature in Version 3.5 beseitigt

    Dieser Fehler ist recht schnell beschrieben, da die neuen 32Bit
    &h...., &o.... &b Anweisungen als bekannt vorrausgesetzt werden.
    PowerBASIC Inc. hat in Verbindung mit dem InLine-Assembler einfach die
    Umsetzung vergessen!! Sie glauben mir nicht, dann probieren Sie doch
    einfach folgendes:

            ! dd &h12345678

    Diese kleine Ungereimtheit wird seitens PowerBASIC Inc. mit dem 8bit
    Inline Assembler begründet, aber der Inline-Assembler der Version 3.50
    wurde erfreulicherweise trotzdem in dieser Richtung überarbeitet.


    2.23. undokumentierte interne Variablen in PowerBASIC 3.0/3.1/3.2
    -----------------------------------------------------------------
    Folgende interne Variablen sind in PowerBASIC 3.0 bereits vorhanden,
    aber nicht dokumentiert:

    pbvBinBase
    pbvDefSeg
    pbvHost
    pbvScrnBuff
    pbvSwitch
    pbvVTxtX1
    pbvVtxtX2
    pbvVTxtY1
    pbvVtxtY2

    Folgende internen Varibalen sind ab V3.1 nicht mehr dokumentiert, aber
    noch in Version 3.2 vorhanden:

    pbvRestore

    Die Lage im Datensegment ist bei PowerBASIC 3.0 mit der Lage in
    PowerBASIC 3.1/3.2 identisch.


    2.24. Der PRINT-Bug in PowerBASIC 3.2
    -------------------------------------
    bekannt  : ????

    In der Version 3.2 werden Variablen vom Typ DWORD nicht mehr korrekt
    beim PRINT-Befehl dargestellt:

    Beispiel:
            Demo??? = 1234567890
            PRINT Demo???

    führt zu folgender Ausgabe:

    PowerBASIC 3.0/3.1: 1234567890
    PowerBASIC 3.2    : 1.234568+E

    Abhilfe schafft das Verwenden von PRINT USING ...


    2.25. Der Fehler "File not found" nach Verwendung von NAME
    ----------------------------------------------------------
    Versionen: 3.0/3.1/3.2
    bekannt  : Fehler in Version 3.50 beseitigt

    Ein sehr merkwürdiger Fehler in der Behandlung PowerBASIC-interner
    Filehandles hat sich bei der Verwendung des Befehles "NAME" einge-
    schlichen.

    Beispiel:
           OPEN "B",1,"DATEI1.TMP"       ' Öffnen der 1. Datei
           OPEN "B",2,"DATEI2.$$$"       ' Öffnen
           CLOSE 2                       ' ... und sofort schliessen
           OPEN "B",3,"DATEI3.TMP"       ' Öffnen
           CLOSE 3                       ' ... und sofort schliessen
           KILL "DATEI2.$$$"             ' 2. Datei löschen
           NAME "DATEI3.TMP" AS "DATEI2.$$$"
                                         ' 3. Datei -> 2. Datei umbenennen
           CLOSE 1                       ' ... Schliessen der 1. Datei
           END


    2.26. Rechenfehler bei der Verwendung von Konstanten
    ----------------------------------------------------
    Versionen: 3.0/3.1/3.2
    bekannt  : nein

    PowerBASIC rechnet bei der Verwendung von Konstanten gelegentlich
    nicht korrekt. Es sei natürlich die Frage in den Raum gestellt, warum
    man nicht gleich das Rechenergebnis einsetzt, da es sich hierbei um
    eine reine Formsache handelt.

    Beispiel:
           i% = -20-4   : %k= -20-4
           PRINT i%     , %k


    2.27. falsches "Bit schieben" bei ROTATE
    ----------------------------------------
    Versionen: 3.0/3.1
    bekannt  : Fehler in Version 3.20 beseitigt

    Der ROTATE-Befehl hat in PowerBASIC 3.0/3.1 einen Fehler sofern
Variablen
    vom Type QUAD verwendet werden.

    Beispiel:
           i&& = 1
           ROTATE RIGHT i&&, 1
           ROTATE LEFT i&&, 1
           PRINT i&&


    2.28. Overflow bei Verwendung von FOR/NEXT-Schleifen
    ----------------------------------------------------
    Versionen: 3.0/3.1/3.2/3.5
    bekannt  : ja

    PowerBASIC erlaubt es nicht in FOR/NEXT-Schleifen den maximal gültigen
    Wertebereich einer Variablen auszuschöpfen. Der maximal mögliche Wert
    wird intern von PowerBASIC verwendet, da PowerBASIC m.E. erst intern
    die Variable erhöht und dann abfragt. Logischerweise kommt es dabei
    zu einem Überlauf, sofern Ihr Wert bereits den maximal möglichen
    Wert erreicht hat.
    Der Fehler betrifft m.E. alle Variablentypen.

    Beispiel:
           FOR Demo? = 1 TO 255
               PRINT Demo?
           NEXT Demo?

    Sollten Sie nicht die "$ERROR NUMERIC" Bibliothek verwenden, so
befindet
    sich diese FOR/NEXT Konstruktion in einer Endlosschleife.

    Dieser Effekt ist begründet aufgrund der Abwärtskompatibilität zu
anderen
    BASIC Compilern und der Wirkungsweise der Intel CPU.


    2.29. Overflow bei Verwendung von STEP -1 in FOR/NEXT-Schleifen
    ---------------------------------------------------------------
    Versionen: 3.0/3.1/3.2/3.5
    bekannt  : ja

    In PowerBASIC müssen alle Variablen vom gleichen Typ (signed/unsigned)
    sein, sofern sie in FOR/NEXT Schleifen verwendet werden. Folgendes
Bei-
    spiel ist also nicht zuläßig:

    Beispiel:
           FOR Demo?? = 10 TO 2 STEP -1
           NEXT Demo??

    oder
           FOR Demo??? = 10 TO 2 STEP -1
               PRINT Demo???
           NEXT Demo???

    Sollten Sie nicht die "$ERROR NUMERIC" Bibliothek verwenden, so
befindet
    sich diese FOR/NEXT Konstruktion in einer Endlosschleife.


    2.30. Der Bug im VARPTR32-Befehl
    --------------------------------
    Versionen: ab 3.2
    bekannt  : Fehler in Version 3.50 beseitigt

    Im Gegensatz zu den Befehlen STRPTR32 und CODEPTR32 hat sich im
    VARPTR32-Befehl ein Bug eingeschlichen. Leider ist es mit diesem
    Befehl nicht möglich gleichzeitig eine mathematische Operation
    auszuführen.

    Beispiel:
           DIM Demo AS STRING * 10
           Wert1??? = VARPTR32(Demo) + 1
           Wert2??? = VARPTR32(Demo)
           Wert2??? = Wert2??? + 1
           PRINT  Wert1???, Wert2???


    2.31. Der 'KEY ON' Bug
    ----------------------
    Versionen: 3.0/3.1/3.2
    bekannt  : nein

    Laut PowerBASIC Benutzerhandbuch und BASIC Spezifikation des
KEY-Befehls
    stellt der 'KEY ON'-Befehl in Zeile 25 die aktuelle
KEY-Tastaturbelegung
    in 'Norton Commander' ähnlicher Form dar. Ist dieses der Fall, sollte
    PowerBASIC jeden Zugriff des Programmierers auf die Zeile 25 durch
    LOCATE mit einem 'Error 5: Illegal Function' unterbinden. Ebenso
sollte
    die Zeile 25 durch ein versehentliches Scrollen geschützt sein.
    Seit PowerBASIC V3.x (im Gegensatz zur V2.10) ist dieses nicht mehr
der
    Fall!

    Beispiel:
            KEY OFF
            FOR i% = 1 TO 10
                READ A$
                KEY i%, A$ + CHR$(13)
            NEXT i%
            KEY LIST
            COLOR 3, 0
            KEY ON
            COLOR 7, 0
            LOCATE 25, 1: PRINT " Dieser Text sollte abgefangen werden!!
";
            WHILE NOT INSTAT
            WEND
            KEY OFF
            END
            DATA "Hilfe", "Return"', "Edit", "Wechseln", "Report"
            DATA "PRINT", "Setup", "DOS", "Kopie", "Quit"

    Mir stellt sich nun die Frage ob dieses ein Fehler im
PowerBASIC-Handbuch
    oder ein Bug im Compiler ist. Auf alle Fälle können Sie diesen Effekt
    aber durch die Verwendung von:

            VIEW TEXT (1,1)-(80,24)

    umgehen.


    2.32. Absturz der PowerBASIC IDE im Pick-Menü
    ---------------------------------------------
    Versionen: 3.0/3.1/3.2/3.5
    bekannt  : nein

    Die PowerBASIC IDE stürzt ab, wenn sie zum ersten Mal nach dem Start
    der IDE im Menü "File\Pick", anstatt der RETURN-Taste die DEL-Taste
    betätigen. Sollten Sie bereits während der Sitzung das Menü "Pick"
einmal
    mit RETURN geöffnet haben, so wirkt sich der Fehler nicht mehr aus.
    Ich persönlich halte den Fehler für sehr ernsthaft, liegen doch die
    beiden Tasten auf der Tastatur eng zusammen.


    2.33. Absturz der PowerBASIC IDE bei fehlerhaften Syntax
    --------------------------------------------------------
    Versionen: 3.0/3.1/3.2
    bekannt  : Fehler in Version 3.50 beseitigt

    Die PowerBASIC IDE stürzt ab, sofern Sie versuchen folgende Zeile
    zu compilieren:

            PRINT Test1$ XOR Test2$ XOR Test3$

    Über den Sinn der Zeile möchte ich lieber nicht diskutieren. <g>


    2.34. falsches Vertauschen der Variablen bei Verwendung von SWAP
    ----------------------------------------------------------------
    Versionen: 3.0/3.1/3.2/3.5
    bekannt  : nein

    Bei Verwendung des SWAP-Befehl in Verbindung mit TYPE-Strukturen und
der
    Indizierung des Feldes über eine Variable (im Beispiel "a(c%).x")
werden
    die Felder falsch miteinander getauscht (geswappt). Wird das Feld über
    einen fest definierten Wert (z.B. "a(1).x") indiziert, dann arbeitet
der
    SWAP-Befehl korrekt.

    Beispiel:
            TYPE SwapTest                 ' Benutzerdefinierter Datentyp
                x AS INTEGER
                y AS INTEGER
            END TYPE

            DIM a(1 TO 2) AS SwapTest     ' Array anlegen

            c%     = 1
            d%     = 2
            a(1).x = 1                    ' Felder initialisieren
            a(1).y = 2
            a(2).x = 3
            a(2).y = 4
            CLS
            PRINT "vor  SWAP: "; a(c%).y, a(d%).y
            SWAP                 a(c%).y, a(d%).y
            PRINT "nach SWAP: "; a(c%).y, a(d%).y


    2.35. Der Multiplexer Interrupt Fehler im REG-Befehl
    ----------------------------------------------------
    Versionen: 2.x/3.0/3.1/3.2
    bekannt  : Fehler in Version 3.50 beseitigt

    Erstaunlicherweise gibt es selbst einige Ungereimtheiten sofern Sie
    mit dem REG-Befehl den Multiplexer-Interrupt &h2F aufrufen. In der
    Regel hat es den Anschein das der Aufruf vom System abgewiesen wird.
    Ein Gegentest beweist aber das es mit dem Inline-Assembler
funktioniert!
    Beobachtet wurde dieser Effekt bei der Programmierung des MSCDEX, der
    Abfrage der Windows-Version und der Timeslice-Funktion des
Multiplexer-
    Interrupts.
    Abhilfe schafft nur konsequentes Programmieren mit dem
Inline-Assembler.

    Beispiel:
            ! mov ax, &h1680
            ! int &h2F
            ! mov Taskfreigabe%, ax
            Taskfreigabe% = Taskfreigabe% AND 255
            SELECT CASE Taskfreigabe%
                CASE &h80 : PRINT "Taskfreigabe nicht unterstützt"
                CASE &h0  : PRINT "Taskfreigabe wird unterstützt"
                CASE ELSE : PRINT "unerwarteter Wert"
            END SELECT

            REG 1, &h1680
            CALL INTERRUPT &h2F
            Taskfreigabe% = REG(1)
            Taskfreigabe% = Taskfreigabe% AND 255
            SELECT CASE Taskfreigabe%
                CASE &h80 : PRINT "Taskfreigabe nicht unterstützt"
                CASE &h0  : PRINT "Taskfreigabe wird unterstützt"
                CASE ELSE : PRINT "unerwarteter Wert"
            END SELECT

    Die Ursache für diesen Effekt liegt in der Wirkungsweise des
REG-Befehls
    begründet, allerdings hat QuickBASIC diese Probleme nicht. <g>


    2.36. Inhalt eines Verzeichnis wird mit KILL gelöscht
    -----------------------------------------------------
    Versionen: 3.0/3.1/3.2
    bekannt  : nein

    Ein nettes Feature verbirgt sich in dem KILL-Befehl von PowerBASIC.
    Sollten Sie die Pfadangabe mit einem Backslash (ohne weitere Wildcards
    oder Dateinamen abschliessen), dann wird das komplette Verzeichnis
    gelöscht.

    Beispiel:
           KILL "C:\TEMP\"               ' löscht alle Dateien im TEMP-
                                         ' Verzeichnis


    2.37. Die Sache mit der Zeichenkette "USR"
    ------------------------------------------
    Versionen: 3.0/3.1/3.2
    bekannt  : Fehler in Version 3.50 beseitigt

    Ein völlig unerklärliches Verhalten in der PowerBASIC-IDE und dem
    Kommandzeilen-Compiler ist zu beobachten, wenn die Zeichenkette 'USR'
    in der Source vorkommt. Da der Compiler im ersten Beispiel abstürzt,
    ist definitiv von einem Bug zu sprechen.

    Beispiel:
           PRINT USR                     ' PB/PBC stürzt ab
           Test% = USR                   ' Error 477


    2.38. Der GOTO DWORD Bug
    ------------------------
    Versionen: 3.2
    bekannt  : beseitigt in Version 3.50

    PowerBASIC vergißt ganz simpel den Segmentanteil der Adresse, that's
all.

    Beispiel:
            Demo??? = CODEPTR32(TestLabel)
            GOTO DWORD c???
            $SEGMENT
            TestLabel:
            PRINT "Test"
            END


    2.39. Der 'ON LOCAL ERROR' Bug
    ------------------------------
    Versionen: 3.0/3.1/3.2
    bekannt  : beseitigt in Version 3.50

    Bei Verwendung von 'ON LOCAL ERROR' in einer PBU kann zu einem Absturz
    des Programms führen.

    Beispiel:
            'Main file
            $COMPILE EXE
            $LINK "TEST.PBU"            'oder PBL
            FileName$ = "TEST.DOC"
            CALL ResumeDemo(Demo%)
            PRINT "Error", Demo%
            END

            'Unit file
            $COMPILE UNIT
            SUB ResumeDemo (Demo%) PUBLIC
                ON LOCAL ERROR RESUME NEXT
                ' Zum Test dieses File mit Winword etc. erstellen und
einmal
                ' abspeichern
                OPEN "TEST.DOC" FOR BINARY AS #1
                Demo% = ERRTEST
            END SUB


    2.40. ... und nochmal 'ON LOCAL ERROR'
    --------------------------------------
    Versionen: 3.0/3.1/3.2/3.5
    bekannt  : nein

    PowerBASIC stürzt ab, wenn in einer SUB/FUNCTION mit "ON ERROR"
anstatt
    mit "ON LOCAL ERROR" gearbeitet wird. In diesem Fall kann es zu einem
    Stack bzw. Stringspeicher Problem kommen, sofern der erwartete Fehler
    auch eintritt.
    Natürlich ist dies ein eindeutiger Programmierfehler, aber der
Compiler
    sollte dieses bereits beim compilieren erkennen.


    2.41. Laufzeitfehler im PowerBASIC Helpcompiler
    -----------------------------------------------
    Versionen: 3.0 (Helpcompiler)
    bekannt  : nein

    Der Helpcompiler (bzw. Encoder) scheint irgendwie reichlich Fehler zu
    enthalten. Vor allem Anfängern bereit der Laufzeitfehler 9 an der
    Adresse 10095 bestimmt viel Ärger. Dies ist ein interner Fehler des
    Helpcompilers, der durch das Nichtvorhandensein des Befehls '/LOOKUP'
    ausgelöst wird.


    2.42. Der Fehler Truncating im PowerBASIC Helpcompiler
    ------------------------------------------------------
    Versionen: 3.0 (Helpcompiler)

    Der Fehler 'Truncating ... to 76 characters' wird des öfteren
irrtümlich
    angezeigt, da die Steuerzeichen nicht berücksichtigt werden.


    2.43. Absturz der PowerBASIC-IDE nach Aufruf der eigenen Hilfe
    --------------------------------------------------------------
    Versionen: 3.0 (Helpcompiler)

    Bei der Programmierung bzw. eigentlich dem Schreiben der Hilfe müssen
    Sie aufpassen, das die effektive Länge der darzustellenden Textzeile
    nicht größer als die wirklich vorhandene Zeilenbreite des PowerBASIC-
    Hilfefensters ist, da die PowerBASIC-IDE in diesem Fall mit einem
    Grafikfehler abstürzt.
    Dieser Fehler tritt nur in der Endwicklungsphase einer selber
    geschriebenen Hilfedatei (*.PBH) auf!


    =================================
    3. PowerBASIC und der CoProzessor
    =================================

    3.1. Unterstützt PowerBASIC einen CoProzessor?
    3.2. Welche Fließkommabibliothek ist für mich die optimale?
    3.3. Macht sich der CoProzessor auch bei $FLOAT PROCEDURE bemerkbar?
    3.4. Welche PowerBASIC-Funktionen sind betroffen?
    3.5. mögliche Ursachen für den CoProzessor-Effekt
    3.6. PowerBASIC-Benchmark Source


    3.1. Unterstützt PowerBASIC einen CoProzessor?
    ----------------------------------------------
    Die Antwort lautet ganz einfach JA. Bereits in den Compiler-Optionen
    haben Sie die Möglichkeit drei verschiedene Fließkommabibliotheken
    auszuwählen. Aber mit dieser Unterstützung des CoProzessors sind unter
    PowerBASIC einige Haken verbunden, die es hier aufzuzeigen geht damit
    sie schnellere und hoffentlich nur sauber funktionierende Programme
    entwickeln.


    3.2. Welche Fließkommabibliothek ist für mich die optimale?
    -----------------------------------------------------------
    PowerBASIC bietet insgesamt drei Fließkommabibliotheken an:

    a) $FLOAT EMULATE
       Dieses ist die DEFAULT-Bibiothek und dadurch in der Regel bei ca
95%
       der Anwender im Einsatz. Sie zeichnet sich durch automatische
Unter-
       stützung des i87 aus, sofern ein solcher CoProzessor gefunden
wurde.
       Der enorme Nachteil liegt aber sofort auf der Hand. PowerBASIC
       testet ständig auf einen CoProzessor und wird dadurch erheblich
       langsamer sofern wirklich kein i87 installiert ist.

    b) $FLOAT PROCEDURE
       Diese Bibliothek ist mit Abstand die schnellste, sofern kein Co-
       Prozessor installiert ist.

    c) $FLOAT NPX
       Mit Abstand liegt diese Bibliothek vorne, sofern jedenfalls ein
       i87 vorhanden ist.


    3.3. Macht sich der Coprozessor auch bei $FLOAT PROCEDURE bemerkbar?
    --------------------------------------------------------------------
    Auch hier ist die Antwort ganz klar: JA. Obwohl PowerBASIC keine
    Coprozessorunterstützende Fließkommabibliothek eingebunden hat, läßt
    sich dies anhand der beiliegenden Source sehr deutlich beweisen.
    Des Rätsels Ursache liegt in der PowerBASIC-Runtime-Bibliothek, diese
    unterstützt schon von Hause aus einen i87. Deshalb lassen sich auch
die
    Geschwindigkeitsauswirkungen der verschiedenen Fließkommabibliotheken
    nicht verallgemeinern.


    3.4. Welche PowerBASIC-Funktionen sind betroffen?
    -------------------------------------------------
    Als betroffende internen PowerBASIC-Funktionen wäre da vorallem
    SELECT CASE zu nennen. Messungen haben gezeigt das SELECT CASE mit i87
    5 Sekunden braucht. Unter den gleichen Voraussetzungen (aber ohne i87)
    bis zu 200 Sekunden benötigen kann ($FLOAT EMULATE). Enorme Ver-
    besserungen waren bereit mit $FLOAT PROCEDURE zu erreichen (jetzt
    nur noch 35 Sekunden).
    Im allgemeinen kann gesagt werden: SELECT CASE hat nichts in zeit-
    kritischen Routinen zu suchen.
    Ebenso, aber bei weitem nicht so extrem, ist die PRINT-Ausgabe von
    nummerischen Ausdrücken betroffen.


    3.5. mögliche Ursachen für den CoProzessor-Effekt
    -------------------------------------------------
    Meines Erachtens hat dieser Effekt recht natürliche Ursachen, da alle
    betroffenden Befehle mit dem neuen 80-stelligen Zahlensystem umgehen
    können müssen. Anscheinend haben die Programmierer von PowerBASIC ver-
    sucht den zusätzlichen Rechenaufwand durch Einsatz des CoProzessors
    wieder wettzumachen. Wobei Ihnen dies bei vorhandenem CoProzessor
    auch recht gut gelungen ist.
    Andererseits kann man sich fragen, warum der Compiler dies nicht
besser
    optimiert sofern nur normale 16/32bit Zahlen eingesetzt werden.


    3.6. PowerBASIC-Benchmark Source
    --------------------------------
    Die hier beigefügte Source soll Ihnen die Zusammenhänge der vorherigen
    Abschnitte besser demonstrieren. Am besten Sie compilieren die Source
    und testen einfach ein wenig herum.

    Source:
        REM
*****************************************************************
        REM
        REM   PBBENCH.EXE - Performance-Meßprogramm für PowerBASIC
        REM
        REM   Zum Feststellen der Geschwindigkeitsunterschiede einzelner
        REM   PowerBASIC-Befehle in Verbindung der verwendeten Fließkomma-
        REM   bibiothek bei vorhanden bzw. nichtvorhandensein eines
        REM   Coprozessors.
        REM
        REM   Copyright: Thomas Gohel & Andras Hoeffken         Version
2.10
        REM   Alle Rechte vorbehalten
        REM
        REM
-----------------------------------------------------------------
        REM
        REM   Wichtige Hinweise:
        REM   Für halbwegs reale Meßungen muß sich der Prozessor im REAL-
        REM   Mode befinden. Es dürfen keine TSR-Treiber installiert sein,
        REM   also kein KEYB.COM, SMARTDRV.EXE oder ähnliches.
        REM   Wichtig:
        REM   Für eine halbwegs genaue Meßung muß das Programm mehrmals
        REM   aufgerufen und dann Mittelwerte gebildet werden.
        REM
        REM   Besitzer von 486'er/586'ern bzw. 286/386'ern mit
        REM   installiertem x87'er Prozessor können den CoProzessor für
        REM   PowerBASIC mit dem in dieser Source beigefügtem Listing
        REM   Ein/Aus schalten. Das muß allerdings die IDE bzw. das
fertige
        REM   EXE-File erneut gestartet werden!
        REM
        REM  
*************************************************************
        REM
        $COMPILE EXE "PBBENCH.EXE"
        $CPU 80386
        $LIB ALL OFF
        REM $FLOAT NPX              ' für Rechner mit CoProzeßor (am
                                    ' schnellsten)
        REM $FLOAT PROCEDURE        ' für Rechner ohne CoProzeßor (von mir
                                    ' empfohlen)
        REM $FLOAT EMULATE          ' automatisch unterstützen (ohne
                                    ' Coprozessor extrem langsam!!
        REM $DEBUG MAP OFF

        PRINT
        PRINT "Performance-Messprogramm fuer PowerBASIC";:
        PRINT TAB(58); "(c) A.Hoeffken/Th.Gohel";:
        PRINT TAB(68); "Version 2.10";:
        PRINT STRING$(80,"-");
        PRINT
        a% = 1                           ' diverse Variablen
        i% = 1234                        '       -"-
        e& = 12345678                    '       -"-

        REM Zc1! für 5000000-Schleifen   ; zum Herausrechnen der Zeiten
        REM Zc2! für 2000000-Schleifen   ; für die FOR/NEXT-Schleifen
        REM Zc3! für 100000-Schleifen
        REM Zc4! für 2000-Schleifen

        IF pbvnpx > 0 THEN
            PRINT "CoProzessor " + CHR$(pbvnpx+48) + "87 gefunden!"
            PRINT
            PRINT "Soll der CoProzessor für die nächste Messung ";
            PRINT "ausgeschaltet werden (J/N)?"
            BEEP
            A$ = UCASE$(INPUT$(1))
            IF A$ = "J" THEN CoPro "AUS"
        ELSE
            PRINT "kein CoProzessor gefunden!"
            PRINT
            PRINT "Soll der CoProzessor für die nächste Messung ";
            PRINT "wieder eingeschaltet werden (J/N)?"
            PRINT
            PRINT "Hinweis: Einschalten dieses Testes bei nicht ";
            PRINT "installiertem Coprozessor führt"
            PRINT "         zum Absturz!"
            BEEP
            A$ = UCASE$(INPUT$(1))
            IF A$ = "J" THEN CoPro "EIN"
        END IF

        PRINT
        GOSUB HoleZeitKonstanten
        GOSUB MesseFORNEXT
        GOSUB MesseIFTHEN
        GOSUB MesseSELECTCASE
        GOSUB MesseMATHEMATIK
        GOSUB MesseSTRING
        GOSUB MesseNUMPRINT
        GOSUB MesseSTRPRINT
        PRINT
        END

       
'********************************************************************
        '  Holen der einzelen Zeitkonstanten für die einzelnen Messungen
       
'********************************************************************

        HoleZeitKonstanten:
        PRINT "Messung der Zeitkonstanten ";

        t1! = TIMER
        FOR i& = 1 TO 2000           ' Zeit für 2000-Schleifen ausmessen
        NEXT i&
        t2! = TIMER
        Zc4! = t2! - t1!

        PRINT ".";
        t1! = TIMER
        FOR i& = 1 TO 5000000        ' Zeit für 5-Mio-Schleifen ausmessen
        NEXT i&
        t2! = TIMER
        Zc1! = t2! - t1!

        PRINT ".";
        t1! = TIMER
        FOR i& = 1 TO 100000         ' Zeit für 100000-Schleifen ausmessen
        NEXT i&
        t2! = TIMER
        Zc3! = t2! - t1!

        PRINT "."
        t1! = TIMER
        FOR i& = 1 TO 2000000        ' Zeit für 2-Mio-Schleifen ausmessen
        NEXT i&
        t2! = TIMER
        Zc2! = t2! - t1!

        RETURN


       
'********************************************************************
        '
        ' Hier nun die einzelnen Routinen zur Zeitmessung der einzelnen
        ' Befehle. Im Prinzip ist die Messung immer abhängig vom
verwendeten
        ' Computersystem und dem installiertem Betriebssytem. Gerade aber
in
        ' Verbindung mit PowerBASIC, der verwendeten Fließkommabibiliothek
        ' und dem Vorhandensein eines CoProzessors lassen sich erhebliche
        ' Unterschiede bei der Performance einzelner Befehle ermitteln.
        '
       
'********************************************************************

        MesseFORNEXT:
            PRINT "Messe FOR/NEXT   : ";
            t1! = TIMER
            FOR i& = 1 TO 5000000        '5-Millionen-Schleife ausmessen,
            NEXT i&                      'i = long integer
            t2! = TIMER
            PRINT t2! - t1!; "sec "
            RETURN

        MesseIFTHEN:
            PRINT "Messe IF/THEN    : ";
            t1! = TIMER
            FOR i& = 1 TO 5000000
                IF a% = 0 THEN           'IF THEN Methode
                ELSEIF a% = 2 THEN
                ELSE
                END IF
            NEXT i&
            t2! = TIMER
            PRINT t2! - t1! - Zc1!; "sec "
            RETURN

        MesseSELECTCASE:
            PRINT "Messe SELECT CASE: ";
            t1! = TIMER
            FOR i& = 1 TO 2000000
                SELECT CASE A%           'SELECT CASE Methode
                    CASE 0
                    CASE 1
                    CASE ELSE
                END SELECT
            NEXT i&
            t2! = TIMER
            PRINT t2! - t1! - Zc2!; "sec "
            RETURN

        MesseMATHEMATIK:
            PRINT "Messe MATHEMATIK : ";
            t1! = TIMER
            FOR i& = 1 TO 2000000
                i% = i% + 100            'extrem einfache Aufgaben
                e& = e& * 2
                e& = e& \ 2
                i% = i% - 100
            NEXT i&
            t2! = TIMER
            PRINT t2! - t1! - Zc2!; "sec "
            RETURN

        MesseSTRING:
            PRINT "Messe STRING's   : ";
            t1! = TIMER
            FOR i& = 1 TO 2000
                A$ = STRING$(20000, 32)
                A$ = RIGHT$(A$, 10000) + "Test"
                e% = INSTR(A$, "Test")
               A$ = ""
            NEXT i&
            t2! = TIMER
            PRINT t2! - t1! - Zc4!; "sec "
            RETURN

        MesseNUMPRINT:
            PRINT "Messe NUM-PRINT's  ";
            t1! = TIMER
            FOR i& = 1 TO 100000
                LOCATE , 1
                PRINT "Messe NUM-PRINT's: "; i&;
            NEXT i&
            t2! = TIMER
            LOCATE , 20
            PRINT t2! - t1! - Zc3!; "sec "
            RETURN

        MesseSTRPRINT:
            PRINT "Messe $$$-PRINT's  ";
            t1! = TIMER
            FOR i& = 1 TO 100000
                LOCATE , 1
                PRINT "Messe $$$-PRINT's: ";
            NEXT i&
            t2! = TIMER
            LOCATE , 20
            PRINT t2! - t1! - Zc3!; "sec "
            RETURN

        '*****************************************************************
        ' Hier nun die Routine zum Ausschalten des Coprozessors
        '*****************************************************************

        SUB Copro(Switch$)
                SELECT CASE UCASE$(Switch$)
                     CASE "AUS", "OFF", "-"
                         ! mov ax, &h0040
                         ! mov es, ax
                         ! mov ax, word ptr es:[&h10]
                         ! and ax, &b1111111111111101
                         ! mov word ptr es:[&h10], ax
                     CASE "EIN", "ON", "+"
                         ! mov ax, &h0040
                         ! mov es, ax
                         ! mov ax, word ptr es:[&h10]
                         ! or  ax, &b0000000000000010
                         ! mov word ptr es:[&h10], ax
                END SELECT
        END SUB


    ====================
    4. Standard-Probleme
    ====================

    4.1.  Kompatibilität der PBU's & LIB's zwischen den 3'er Versionen
    4.2.  Zu wenig Speicherplatz innerhalb der PowerBASIC-IDE
    4.3.  Ermitteln des eigenen Dateinamens und dem Pfad zum Dateinamen
    4.4.  Kein Speicherplatz verfügbar bei ENVIRON$
    4.5.  Keine Errorcode-Zurückgabe bei SHELL
    4.6.  Kürzen von Files
    4.7.  Fehler 502/514 bei Verwendung von C-OBJ-Files
    4.8.  Warmboot über STRG-ALT-ENTF verhindern
    4.9.  Öffnen von mehr als 15 Files mit PowerBASIC und/oder mit DOS
    4.10. HEX$-DWORD Routine für PowerBASIC 3.1/3.2

    <Hier fallen mir einfach keine mehr ein>


    4.1. Kompatibilität der PBU's & LIB's zwischen den 3'er Versionen
    -----------------------------------------------------------------
    Im Gegensatz zum PowerBASIC-Update von der V2.10 auf die V3.00 sind
    die PBU/LIB's der PowerBASIC 3'er Versionen untereinander abwärt-
    kompatibel. Das heißt, sie können eine mit PowerBASIC 3.0 erstellte
    PBU/LIB unter den beiden höheren PowerBASIC Versionen weiterverwenden.
    Eine mit PowerBASIC 3.1 erstellte PBU/LIB können Sie dagegen
allerdings
    nicht mehr in der älteren Version nutzen.
    Zwischen den Versionen 3.0-3.1 gibt es aber Aufgrund des erweiterten
    Zahlensystems eventuell Unterschiede beim Austausch von Sourcen unter-
    einander. In diesem Fall lesen Sie sich bitte auch den Abschnitt
    'Fehler ...' durch.


    4.2. Zu wenig Speicherplatz innerhalb der PowerBASIC-IDE
    --------------------------------------------------------
    Für das 'ständig vorhandene' Speicherplatzproblem innerhalb der
    integrierten Entwicklungsumgebung wurde von Bob Zale selbst ein Tool
    entwickelt, welches die Bereiche des VGA-Grafik-RAM's, sowie den
Bereich
    der monochromen Herculeskarte für PowerBASIC erschliesst. Obwohl das
    Tool 'PBPLUS96' (96kByte mehr RAM) für die PowerBASIC Version 2.00
    entwickelt wurde, funktioniert es ebenso unter PowerBASIC Version
3.10.


    4.3. Ermitteln des eigenen Dateinamens und dem Pfad zum Dateinamen
    ------------------------------------------------------------------
    Oft stehen Sie vor dem Problem das Sie zwar Ihr Programm über einen
    Pfad-Befehl aufrufen können, dieses dann aber die eigenen Daten und
    INI-Files nicht mehr findet. Die Lösung ist recht einfach: DOS
    speichert diese Informationen im PSP bzw. im zum PSP gehörigen
    Environmentblock.

    --- Cut --------------------------------------------------------------
    '*********************************************************************
    '
    '   Pfad und Dateiname des aktuellen Programm ermitteln in
    '   PowerBASIC 3.0/3.2
    '
    '   von Thomas Gohel
    '
    '*********************************************************************

    $COMPILE EXE

        ! mov ax, &h6200
        ! int &h21
        ! mov es, bx
        ! mov ax, word ptr es:[&h2C]
        ! mov pbvDefSeg, ax           ; undokumentiert in PowerBASIC 3.0
        FOR i% = 0 TO 1024
            IF PEEK$(i%, 4) = CHR$(0,0,1,0) THEN EXIT FOR
        NEXT i%
        WHILE PEEK(i% + 4) <> 0
            Temp$ = Temp$ + CHR$(PEEK(i% + 4))
            i% = i% + 1
        WEND
        DEF SEG
        FOR i%=LEN(Temp$) TO 1 STEP -1
            IF RIGHT$(MID$(Temp$,1,i%),1) = "\" THEN EXIT FOR
        NEXT i%
        ExeDir$ = MID$(Temp$,1,i%)
        ExeName$ = MID$(Temp$,i%+1)
        PRINT ExeDir$; "  "; ExeName$
    --- Cut End ----------------------------------------------------------


    4.4. Kein Speicherplatz verfügbar bei ENVIRON$
    ----------------------------------------------
    Dieser Absatz ist zwar teilweise im Handbuch beschrieben, doch möchte
    ich einige weiterführende Tips geben, da dieses Thema immer wieder zu
    Mißverständnissen führt. Der Aufbau des Environmentblockes in
Verbindung
    mit dem Programm Segment Prefix wird nicht weiter beschrieben, ist
    allerdings von enormer Bedeutung zum besseren Verständnis dieses
Fehlers.

    Zusammenfassend sei gesagt, das Sie nur das vorhandene Environment
    modifizieren und nicht durch neue Einträge erweitern können!! Wollen
Sie
    nun trotzdem Einträge hinzufügen, so können Sie 3 Wege beschreiten:

    a) Teile des Environment löschen und dann den neuen Eintrag hinzufügen
       oder bereits vorher einen Dummy-Environmenteintrag anlegen und
diesen
       dann per ENVlRON-Befehl löschen bzw. modifizieren.

    b) Wenn Sie z.B. eine DOS-SHELL mit einer Information starten wollen:

           OldEnv$ = ENVIRON$("PROMPT")
           SHELL "COMMAND.COM /K SET PROMPT=PowerBASIC " + OldEnv$

       Der Trick hierbei ist, das bei einer SHELL automatisch ein neuer
PSP
       erstellt wird und somit auch der Speicher passend angefordert wird.

    c) Die Adresse des PSP ermitteln, dann den Zeiger auf den aktuellen
       Environmentblock holen und jetzt das Environment komplett in einen
       String packen wo es modifiziert werden kann. Abschliessend einen
       passenden DOS-Speicherblock per INT21 anfordern, das modifizierte
       Environment dorthin kopieren und den Zeiger zum Environmentblock
       innerhalb des Programm Segment Prefix anpassen.
       (siehe auch: bereits vorhandene PD-Lösungen)


    4.5. Keine Errorcode-Zurückgabe bei SHELL
    -----------------------------------------
    Vielfach ist es erforderlich, wenn nach einem SHELL-Aufruf der
Errorcode
    des beendeten Programms abgefragt werden kann. Dies ist in PowerBASIC
    nicht direkt möglich, da PowerBASIC das Programm immer über
COMMAND.COM
    ausführt und deshalb der Errorcode nicht zurückgeben werden kann (dies
    ist eine Eigenart von MS-DOS!!).

    Bespiel:
            SHELL "C:\DOS\COMMAND.COM /C MEINDEMO.EXE"

    Für die Lösung dieses Problems gibt es zum einen einen alternativen
    SHELL-Befehl in Form einer FUNCTION (also Sourcecode):

    --- Cut
---------------------------------------------------------------
   
'**********************************************************************
    '
    '   Errorlevel in PowerBASIC 3.0/3.2
    '
    '   von Thomas Gohel (nach einer Vorlage aus PDS, von Bernd Hohmann)
    '
   
'***********************************************************************

    $COMPILE EXE
    DECLARE FUNCTION PBShell% (FileName$)

    CLS
    PRINT
    PRINT "Fehlercode ist: "; PBShell%("c:\dos\command.com")
    END

    FUNCTION PBShell% (FileName$)
        LOCAL Dummy%

        Datei$ = FileName$                  ' Dateiname umkopieren.
        Datei$ = LTRIM$(Datei$)             ' Filename trimmen.
        i% = INSTR(Datei$, " ")             ' Kommando übergeben ?
        IF i% > 0 THEN                      '
           Cmd$ = MID$(Datei$, i%)          ' Kommando abtrennen
           Datei$ = LEFT$(Datei$, i% - 1)   ' Filename abtrennen
        END IF                              '
        Datei$ = UCASE$(Datei$)
        i% = INSTR(Datei$, ".")             ' Ist ein Punkt drin ?
        IF i% > 0 THEN                      '
           Ext$ = MID$(Datei$, i%)          ' Extension holen.
        ELSE                                '
           Ext$ = ""                        ' Extension ist leer.
        END IF                              '
        SELECT CASE Ext$                    ' Extensions abtesten.
            CASE ".BAT"                     ' Batch über COMMAND.COM
                                            ' ausführen.
                Cmd$ = "/C " + Datei$ + " " + Cmd$
                Datei$ = ENVIRON$("COMSPEC")
            CASE ".COM"                     ' Frei
            CASE ".EXE"                     ' Frei
            CASE ELSE                       ' Keine Extension,
                Datei$ = Datei$ + ".EXE"    ' .EXE anhängen.
        END SELECT                          '

        Datei$ = Datei$ + CHR$(0)           ' ASCIIZ-String erzeugen.
        dNul$ = CHR$(0) + CHR$(0)           ' Doppelnull fuer
Parameter-Block

        nul$ = SPACE$(127)                   ' 127 bytes fuer Strings
retten.
        MemFree& = SETMEM(0)                 ' Freien Speicherplatz holen.
        x& = SETMEM(-MemFree&)               ' Speicherplatz komplett
                                             ' freigeben.
        nul$ = ""                            ' 127 bytes wieder freigeben.
        IF Cmd$ > "" THEN                    ' Kommandozeile ?
            CmdLen$ = CHR$(LEN(Cmd$))        ' Länge des Cmd$ als String
            Cmd$ = CmdLen$ + Cmd$ + CHR$(13) ' Länge + Cmd$ + '13'
            segm$ = MKI$(STRSEG(Cmd$))       ' Einzeln die Teile des
                                             ' Parameter-Blocks
            Offs$ = MKI$(STRPTR(Cmd$))       ' erzeugen ( MID$(....)
                                             ' = segm$ geht nicht. )
            Param$ = dNul$ + Offs$ + segm$   ' Parameterblock machen.
        ELSE                                 '
            Cmd$ = CHR$(13)                  ' Start of Bug-Fixed
            segm$ = MKI$(STRSEG(Cmd$))       ' Segment des Terminator
(Dummy)
            Offs$ = MKI$(STRPTR(Cmd$))       ' Offset         -"-
            Param$ = dNul$ + Offs$ + segm$   ' Parameterblock machen.
        END IF                               ' End of Bugfixed
        DateiSeg% = STRSEG(Datei$)           ' Adressen holen
        DateiOff% = STRPTR(Datei$)
        ParamSeg% = STRSEG(Param$)
        ParamOff% = STRPTR(Param$)
        ! push ds                            ; DS sichern
        ! mov  ax, &h4B00                    ; EXEC-Funktion 4Bh / INT 21h
        ! mov  es, ParamSeg%                 ; Segment des Parameterblocks
        ! mov  bx, ParamOff%                 ; Offset des Parameterblocks
        ! mov  dx, DateiOff%                 ; Offset des Dateinamens
        ! mov  ds, DateiSeg%                 ; Segment des Dateinamens
        ! int  &h21                          ; Interrupt &h21
        ! pop  ds
        ! jc   ExecError
        ! jmp  ExecOk
        ExecError:
        ! mov Dummy%, ax
        SELECT CASE Dummy%                   ' Fehler auswerten.
            CASE 1   : PRINT "illegaler Funktionsaufruf!"
            CASE 2,3 : PRINT "Datei nicht gefunden: " + FileName$
            CASE 4   : PRINT "zu viele Dateien geöffnet"
            CASE 5   : PRINT "Zugriff verweigert " + Filename$
            CASE 8   : PRINT "Zuwenig freier Speicher für " + FileName$
            CASE 10  : PRINT "falscher Environmentblock"
            CASE 11  : PRINT "falsches Format"
            CASE ELSE: PRINT "Problem meim Ausführen von " + FileName$
        END SELECT
        ExecOk:

        Mem2& = SETMEM(MemFree&)             ' Speicher komplett
freigeben.
        IF MemFree& <> Mem2& THEN            ' Speicher stimmt nicht mehr
??
            PRINT "Achtung: vermutlich wurde ein TSR installiert!!"
        END IF

        ! mov  ah, &h4d                      ; Exit-Code ermitteln
        ! int &h21                           ; Interrupt &h21
        ! mov Dummy%, al
        PBShell% = Dummy%

        ! mov  ah, &h03                      ; Aktuelle Cursorposition
        ! mov  bh, &h00                      ; übergeben
        ! int &h10                           ; Interrupt &h10
        ! inc dh                             ; Umrechnen auf Basis 1
        ! inc dl
        ! mov NewZeile?, dh
        ! mov NewSpalte?, dl
        LOCATE NewZeile?, NewSpalte?         ' Cursor setzen
    END FUNCTION
    - Cut End
-------------------------------------------------------------

    Des weiteren können Sie die COMSPEC-Variable in Ihrem Environment
    modifizieren und Ihr Programm ohne Umwege über COMMAND.COM direkt
    ausführen.
    Beispiel:
            Comspec$ = ENVIRON$("COMSPEC")  'Sichern von COMSPEC
            ENVIRON "COMSPEC=MEINDEMO.EXE"
            SHELL                           'Ausführen von MEINDEMO.EXE
            ENVIRON "COMSPEC="+Comspec$     'Restaurieren von COMSPEC

    Beachten Sie allerdings, das die SHELL-Funktion immer automatisch
    den Parameter '/C' dem ausführendem Programm übergibt, sofern Sie
    zum Beispiel Kommandozeilenparameter übergeben wollen.


    4.6 Kürzen von Files
    --------------------
    Oft stehen Sie vor dem Problem das Sie Ihr Datenfile aufgeräumt haben,
    dieses aber immer noch viel zu groß ist. In diesem Fall hilft wie so
    oft ein kleiner aber effektiver Kniff:

    Beispiel:
            OPEN "DEMO.DAT" FOR BINARY AS #1
            SEEK #1, 20
            PUT$ #1, ""
            CLOSE #1

    Verkürzt die Datei 'DEMO.DAT' auf 20Bytes Länge.


    4.7. Fehler 502/514 bei Verwendung von C-OBJ-Files
    --------------------------------------------------
    Bei der Verwendung von C-OBJ-Files ist darauf zu achten, das in der
    OBJ-Datei nicht mehrere Anweisungen für das Datensegment zu finden
sind,
    da PowerBASIC nur ein Datensegment pro OBJ-File unterstützt.
    Da mir zu Zeit auch keine Lösung zu diesem Problem bekannt ist und es
    vermutlich keine seitens PowerBASIC gibt, bleibt meines Erachtens nur
    das Anpassen Ihrer C-Source übrig.


    4.8. Warmboot über STRG-ALT-ENTF verhindern
    -------------------------------------------
    Folgende Source verhindert einen möglichen Warmboot:

    Beispiel:
            KEY 15, CHR$(&h0C, &h53, &h73)
            ON KEY(15) GOSUB NoBoot
            KEY(15) ON

            DO
               IF INKEY$ <> "" THEN EXIT LOOP
            LOOP
            PRINT "Fertig"
            END

            NoBoot:
            PRINT "Warmstart nicht erwünscht!"
            RETURN


    4.9. Öffnen von mehr als 15 Files mit PowerBASIC und/oder mit DOS
    -----------------------------------------------------------------
    Oft scheint man an die Grenzen von PowerBASIC zu stoßen, sofern man
    mehr als 15 Files öffnen will. Dabei ist dieses Problem überhaupt
nicht
    ein Mangel des Compilers, sondern eher ein genetischer Geburtsfehler
    von MS-DOS.
    Um diesen Effekt zu erklären muß ich leider ein wenig in die Untiefen
    von DOS Licht bringen, denn dort finden wir auch des Rätsels Lösung.
    Vielen ist bestimmt bekannt, das nach dem Öffnen von Dateien ein
    Handel zurückgeliefert wird. Nur wo speichert DOS dieses Handle und
    die Informationen die zu diesem Handle gehören?

    Vielen ist bestimmt der Begriff PSP (Programm Segment Prefix) ein
    Begriff (bereits kurz erwähnt bei der Ermittlung des Dateinamens),
wenn
    nicht sollten Sie die folgenden Ausführungen besser überlesen und die
    Source testen.
    Dieses PSP enthält jedenfalls eine Tabelle, welche durch Microsoft
    zwar als reserviert gilt, deren Bedeutung aber längst klar ist. Diese
    Tabelle nennt sich 'Job File Table' (kurz JFT) und befindet sich ab
    DOS 2.0 am Offset 18Hex und umfasst ein 20 Felder großes BYTE-Array.
    Zieht man jetzt die ständig belegten Handles für: NUL, $CLOCK, CON
    AUX und PRN ab, so verbleiben unsere magischen verfügbaren 15 Handles.
    Die Aufgabe der JFT ist es allerdings lediglich, einen Zeiger auf die
    'System File Table' kurz SFT zu verwalten.
    Die SFT wiederum ist eine MCB (Memory Controll Block) ähnlich
verkettete
    Struktur, welche wichtige Daten wie Startcluster und Sharingattribute
    verwaltet. Eine solche SFT kann nur eine bestimmte Anzahl von Handles
    beinhalten, um diese zu Erhöhen muß in der CONFIG.SYS ein höherer Wert
bei
    FILES angegeben werden. Nach dem Neustart des System reserviert MS-DOS
    nun mehr als SFT markierte MCB's. Sie könnten also nun theoretisch
mehr
    als 20 Files öffnen, denn der Defaultwert bei FILES ist '8'.
    Leider stoßen wir hierbei wiederum auf die begrenzte Anzahl der
Einträge
    in der JFT innerhalb des PSP. Ab MS-DOS 3.3 gibt es hierbei aber
Abhilfe,
    da der INT &h21, Funktion &h67 ermöglicht die Anzahl der verfügbaren
    Handles zu erhöhen. Nur wie geht das genau, wo doch der Platz
innerhalb
    des PSP begrenzt ist??
    Dazu erinnern wir uns wieder an die undokumentierten Felder innerhalb
    des PSP. Interessant wird jetzt der Offset &h32, dieser enthät die
neue
    Größe der JFT in WORD. Darauf folgt der neue Pointer zur Extendet JFT.
    Interessant ist hierbei nur, das dieses neue Array ein Array vom Typ
    WORD ist. Es können also theoretisch 65535 Handles verwaltet werden,
    was allerdings rein Hypothetisch ist, da die SFT weiterhin nur 255
Ein-
    träge verwalten kann.
    Wichtig bei der Neuzuweisung einer JFT sind eigentlich nur zwei Dinge:
        - Die neuen JFT benötigt Speicher, das heißt sie müssen den Heap
          des aktuellen PowerBASIC Programms herunterschrauben!
        - Eine Extendet JFT wird bei SHELL/EXECUTE nicht an das Child-
          Programm vererbt! Für das Child-Programm gilt also wieder die
          15 Files Grenze.

     Ok, jetzt aber die Source:

   
'***********************************************************************
    '
    '  Erhöhen der verfügbaren Handles in PowerBASIC 3.2
    '
    '  entwickelt von Th.Gohel  Fido:      2:2410/301.12
    '                           InterNet:  support@[EMAIL PROTECTED]
    '                           Homepage:  http://www.snafu.de/~pbsound/
    '
   
'***********************************************************************

    MaxFiles% = 30                       ' entspricht FILES = 30
    PBFiles MaxFiles%                    ' anpassen der verfügbaren Files

    FOR i% = 1 TO MaxFiles%              ' Testen der verfügbaren Files
        PRINT "Öffne File:  PBFILES." + STR$(i%)
        OPEN "PBFILES." + STR$(i%) FOR BINARY AS i%
        PUT$ i%, "Testdatei" + STR$(i%) + " für PBFILES, bitte löschen!"
    NEXT i%
    FOR i% = 1 TO MaxFiles%              ' und wieder schliessen
        CLOSE i%
    NEXT i%

    SUB PBFiles(BYVAL MoreFiles%)
        x& = SETMEM(-255)                ' sollte Ausreichen für alle
Fälle
        ! mov ah, &h67                   ; Anzahl der verfügbaren Handles
        ! mov bx, MoreFiles%             ; festlegen
        ! add bx, 6                      ; die Standard-Handles für PB
        ! int &h21
        ! jnc PBFiles_Ok
        PRINT "Fehler beim Einrichten der verfügbaren Handles!!"
        PBFiles_Ok:
    END SUB


    4.10. HEX$-DWORD Routine für PowerBASIC 3.1/3.2
    -----------------------------------------------
    Nachfolgende Routine soll, den für mich unverständlicherweise
fehlenden
    HEX$-Support für Variablen vom Typ DWORD, ermöglichen.

    Beispiel:
            d??? = &h1234ABCD

            PRINT DHex$(d???)

            FUNCTION DHex(HexDWord???) AS STRING
                    DIM Lo AS WORD
                    DIM Hi AS WORD
                    ! les  bx, [bp+6]
                    ! mov  ax, es:[bx+0]
                    ! mov  Lo??, ax
                    ! mov  ax, es:[bx+2]
                    ! mov  Hi??, ax
                    DHex = RIGHT$("000" + HEX$(Hi??), 4) + RIGHT$("000" +
_
                    HEX$(Lo??), 4)
            END FUNCTION

    ===============================================
    5. Tip's in Verbindung mit dem Inline-Assembler
    ===============================================

    Kurzübersicht:
    5.1.  Funktionsprinzip des PowerBASIC Inline-Assemblers
    5.2.  Assembler Syntax Error
    5.3.  Fehlerhafte Variablenübergabe im Inline-Assembler
    5.4.  Probleme mit LDS/LES
    5.5.  Absturz nach Aufruf einiger INT-Funktionen
    5.6.  Fixup Overflow
    5.7.  Variablen zerlegen von WORD nach BYTE
    5.8.  Variablen zerlegen von DWORD nach WORD
    5.9.  Zugriff mit dem Inline-ASM auf Array's/Strukturen
    5.10. Parameterrückgabe mit dem Inline-ASM
    5.11. Variablenübergabe in Interrupt-Prozeduren
    5.12. Erstellen von 32bit-Zeigern
    5.13. Konvertierung von REG nach Inline-ASM
    5.14. Konvertierung von A86 nach Inline-ASM

    Die hier beschriebenen Tip's sollen keinen Grundlehrgang im Inline-
    Assembler darstellen, sondern nur die wichtigsten Anfängerprobleme
    umschiffen zu helfen. Auf eine genauere Beschreibung der Zusammenhänge
    wird deshalb verzichtet, es sei es gehört zum Problem selber.


    5.1. Funktionsprinzip des PowerBASIC Inline-Assemblers
    ------------------------------------------------------
    Der PowerBASIC Inline-Assembler besitzt den Funktionsumfang der Intel
    8086 CPU. Das heißt, da Sie Inline-Assembler-Code anderer
Hochsprachen-
    Compiler bzw. reinen Assembler-Code leicht an den PowerBASIC Inline-
    Assembler anpassen müssen, da diese recht oft bereits 80286'er Befehle
    enthalten. In der Regel fallen immer wieder folgende Befehle auf,
welche
    Sie wie folgt konvertieren können:
    <Listing>
        Quell-Source       - >      PowerBASIC
        shr ax, 2                   ! shr  ax, 1
                                    ! shr  ax, 1
                                    oder ähnlich wie folgt:
        -----------------------------------------------------------
        shl ax, 3                   ! push cx
                                    ! mov  cl, 3
                                    ! shl  ax, cl
                                    ! pop  cx
        -----------------------------------------------------------
        pusha                       ! push ax
                                    ! push bx
                                    und so weiter bis alle Register ge-
                                    sichert sind
        -----------------------------------------------------------
        popa                        analog, nur Register wieder
restaurieren.
    <Ende>


    5.2. Assembler Syntax Error
    ---------------------------
    Wenn wir von einem richtigen Syntaxfehler absehen, der in der Regel
auf-
    tritt wenn Sie noch nicht so recht mit den Assemblerbefehlen vertraut
    sind, kann der Inline-Assembler von PowerBASIC auch einen
'scheinbaren'
    Syntax Error erzeugen. Dies ist dann immer der Fall, wenn der Compiler
    eine Variable im Inline-Assembler nicht auflösen kann, da Sie nicht in
    irgendeiner Form definiert ist.
    PowerBASIC legt normalerweise die verwendeten Variablen innerhalb
einer
    reinen BASIC-Source selbstständig an und weist dieser Variablen Ihren
    Speicherplatz zu. Innerhalb des Inline-Assemblers müssen Sie dafür
    selber sorgen.
    Beispiel:
            ! mov ax, Demo%
    führt automatisch zu einem Syntax-Error, da der Compiler nichts mit
der
    Variablen 'Demo%' anfangen kann. Sollten Sie der Variablen vorher
einen
    Wert zuweisen:
            Demo% = 1
            ! mov ax, Demo%
    dann akzeptiert der Compiler nun die Assemblerzeile. Sie müssen aber
    nicht jedesmal die Variable speziell mit einem Wert laden, ein bloßes
    DIM oder auch SHARED, PUBLIC, LOCAL etc. reicht hierbei völlig aus und
    initialisiert 'Demo%'.


    5.3. Fehlerhafte Variablenübergabe im Inline-Assembler
    ------------------------------------------------------
    Oft haben Sie bestimmt schon geflucht, da eine funktionierende Routine
    mit REG(x) nach der Umsetzung in den Inline-Assembler nicht mehr
sauber
    funktioniert oder wenn ebenso Ihre Testroutine nicht mehr in einer
    SUB/FUNCTION ihre Arbeit verrichten will.
    Des Rätsels Lösung ist relativ einfach: Sie müssen Variablen für den
    Inline-Assembler immer BYVAL übergeben.
    Beispiel:
            Demo 1
            FUNCTION Demo(BYVAL i%) public
                    ! mov ax, i%
                    ! inc ax
                    ! mov i%, ax
                    PRINT i%
            END FUNCTION
    Dieses kleine Demo addiert per Inline-Assembler einfach den Wert '1'
    und gibt diesen dann auf den Bildschirm aus. Lassen Sei einfach das
    BYVAL in der Parameterübergabe weg und testen Sie das Demo erneut!


    5.4. Probleme mit LDS/LES
    -------------------------
    Ähnlich wie bei der Parameterübergabe für den Inline-Assembler verhält
    sich das Funktionsprinzip der Assemblerbefehle LDS/LES. Von ent-
    scheidener Bedeutung ist hierbei ebenfalls ob Sie die Variable
    'BY COPY', 'BY REFERENCE' oder auch 'BY VALUE' übergeben. Als
Faustregel
    können Sie sich merken:

    BY REFERENCE: - eigentlich als default im Hautprogramm
                  - bzw. wenn Sie die Variable als SHARED/PUBLIC etc.
                    deklariert haben.
    BY COPY:      - default immer in einer SUB/FUNCTION, sofern Sie
                    die Variable nicht BY VALUE übergeben.
    BY VALUE:     - interpretiert der Inline-Assembler immer als BY
                    REFERENCE.

    LDS/LES sollten Sie nur Variablen vom Typ BY COPY übergeben, da nur
    hierbei in DS/ES die Segmentadresse geladen wird und im anderen
Register
    dann die Offsetadresse der Variablen.
    Bei der Übergabe BY REFERENCE wird in DS/ES der höherwertige Inhalt
der
    Variablen geladen, sofern vom Typ Long/DWord, ansonsten enthält das
    DS/ES-Register einen irrelevanten Wert. Im anderen Register befindet
    sich dann der niederwertige Inhalt der Variablen.
    Beispiel:

            SHARED DemoSeg%, DemoOff%

            i& = &h12345678
            Demo1 i&
            Demo2 i&
            Demo3 i&

            FUNCTION Demo1(i&) public
                    PRINT "PB-Adresse   : ";:
                    PRINT HEX$(VARSEG(i&));":"; HEX$(VARPTR(i&))
            END FUNCTION

            FUNCTION Demo2(i&) public
                    ! les bx, i&
                    ! mov DemoSeg%, es
                    ! mov DemoOff%, bx
                    PRINT "LES /BY COPY : ";:
                    PRINT HEX$(DemoSeg%);":"; HEX$(DemoOff%)
            END FUNCTION

            FUNCTION Demo3(BYVAL i&) public
                    ! les bx, i&
                    ! mov DemoSeg%, es
                    ! mov DemoOff%, bx
                    PRINT "LES /BY VALUE: ";:
                    PRINT HEX$(DemoSeg%);":"; HEX$(DemoOff%)
            END FUNCTION


    5.5. Absturz nach Aufruf einiger INT-Funktionen
    -----------------------------------------------
    Warum dieser Abschnitt werden Sie sich fragen, hat der PowerBASIC
    Inline-Assembler irgendwelche Fehler? Die Antwort lautet definitiv:

    NEIN.

    Trotzdem sind viel Aufrufe über INT-Funktionen des BIOS/DOS mit
einiger
    Tücke verbunden, da Sie wichtige Segmente verbiegen bzw. speziell
    zuweisen müssen. Viele Buffer, die einer Funktion übergeben werden
    müssen, erwarten speziell im Datensegment-Register (DS) Ihren Zeiger.
    PowerBASIC selbst addressiert aber seine Variablen ebenfalls über DS,
    sodas hier Konflikte vorprogrammiert sein können. So sollte es zum
    Beispiel nicht sein:

            ! mov ax, &h3D90        ; Funktion Datei öffnen
            ! mov ds, FileSeg??     ; Segment des Dateinamens laden,
            ! mov dx, FileOff??     ; jetzt kommt der erste Fehler, da
                                    ; FileOff?? nicht mehr über DS
                                    ; addressiert werden kann. DS zeigt
                                    ; bereits woanders hin ...
            ! int &h21              ; INT-Aufruf
            ! mov Handle%, ax       ; da DS immernoch für PowerBASIC ins
                                    ; Nirwana zeigt, schlägt diese Zeile
                                    ; ebenfalls fehl und PowerBASIC
                                    ; stürzt über kurz oder lang ab.

    Ein sauberes Listing sollte wie folgt aussehen:

            ! push ds               ; DS sichern
            ! mov  ax, &h3D90
            ! mov  dx, FileOff??    ; Offset des Dateinamens laden
            ! mov  ds, fileSeg??    ; Segment des Dateinamens laden,
                                    ; für PowerBASIC brauchen wir es
                                    ; auch nicht mehr
            ! int &h21              ; INT-Aufruf
            ! pop ds                ; PowerBASIC Segment restaurieren
            ! mov Handle%, ax       ; Handle% (bzw. Fehlercode) zuweisen
            ! jnc ...               ; Carry-Flag abfragen


    5.6. Fixup Overflow
    -------------------
    Das Problem ist recht einfach und simpel: Die 8086'er CPU läßt nur
    bedingte Sprünge vom Typ SHORT zu, das heißt sie können direkt nur
    Labels im Bereich von -127/+128 Opcodes Entfernung anspringen.
    Folgendes Beispiel erzeugt also einen Fehler:

            DemoLabel:
            <mehr als 128 Bytes Opcode>
            ! jc DemoLabel

    Um der Sache aus dem Weg zu gehen, müssen Sie die ganze Sache nur
etwas
    anders adressieren. Das ist im Prinzip kein Problem, man muss es nur
    einmal wissen:

            DemoLabel:
            <mehr als 128 Bytes Opcode>
            ! jnc DemoWeiter
            ! jmp near DemoLabel
            DemoWeiter:

    Das steht allerdings auch in jedem Assembler-Buch ...


    5.7. Variablen zerlegen von WORD nach BYTE
    ------------------------------------------
    Sollten Sie immer noch Ihre 16bit Variablen mit mathematischen Aufwand
    in Ihre 8bit Bestandteile zerlegen, so wird es Zeit das Sie endlich
    damit aufhören. Das kann die CPU von ganz alleine erledigen:
    Beispiel:
            DIM Demo     AS WORD
            DIM DemoHigh AS BYTE
            DIM DemoLow  AS BYTE

            Demo?? = &H1234

            ! mov  ax, Demo??
            ! mov DemoLow? , al
            ! mov DemoHigh?, ah


    5.8. Variablen zerlegen von DWORD nach WORD
    -------------------------------------------
    Öfters steht man vor dem Problem, das man zwar Zeiger und Variablen
vom
    Typ DWORD in PowerBASIC hat, allerdings nicht weis wie man diese im
    Inline-Assembler übergeben kann oder je nach Bedarf auch in WORD zer-
    legen. Im Prinzip ist auch diese recht einfach (gewußt wie):
    Beispiel:

            DIM Demo     AS DWORD
            DIM DemoHigh AS WORD
            DIM DemoLow  AS WORD

            Demo??? = &H12345678

            ! mov  ax, Demo???[00]
            ! mov  bx, Demo???[02]
            ! mov DemoLow??,  ax
            ! mov DemoHigh??, bx


    5.9. Zugriff mit dem Inline-ASM auf Array's/Strukturen
    ------------------------------------------------------
    Relativ einfach ist der Zugriff mit dem Inline-Assembler auf feste
    Datenstrukturen, sofern sie bereits vorher die genauen Offsetadressen
    Adressen wissen.
    PowerBASIC erlaubt Ihnen folgenden Syntax:

    Beispiel:
            ! mov ah, byte ptr es:[di][22]

    Kopiert den Wert zum Offset 22 der Adresse ES:DI in das AH-Register.


    5.10. Parameterrückgabe mit dem Inline-ASM
    -------------------------------------------
    Im Gegensatz zum reinem Assembler läuft die Rückgabe einer Variablen
    im PowerBASIC Inline-Assembler leicht anders ab. PowerBASIC 3.0 ge-
    stattet z.B. nicht die direkte Übergabe aus dem Inline-Assembler an
    die FUNCTION, dies ist nur über einen kleinen Trick möglich.

    Beispiel:
            High% = &h1234
            Low%  = &h4578
            PRINT HEX$(Demo1&(High%, Low%))

            FUNCTION Demo1&(BYVAL High%, BYVAL Low%)
                    LOCAL Dummy&
                    ! mov dx, High%
                    ! mov ax, Low%
                    ! mov Dummy&[02], dx
                    ! mov Dummy&[00], ax
                    Demo1& = Dummy&
            END FUNCTION

    Ab PowerBASIC 3.1 können Sie den Rückgabewert aber direkt an die
    FUNCTION übergeben, nur bei 32bit (und größeren) Werten müssen Sie
    wieder einen kleinen Kniff anwenden:

    Beispiel:
            High% = &h1234
            Low%  = &h4578
            PRINT HEX$(Demo2&(High%, Low%))

            FUNCTION Demo2&(BYVAL High%, BYVAL Low%)
                    ! mov dx, High%
                    ! mov ax, Low%
                    ! mov FUNCTION[02], dx
                    ! mov FUNCTION[00], ax
            END FUNCTION


    5.11. Variablenübergabe in Interrupt-Prozeduren
    ------------------------------------------------
    Sehr schwierig ist die Übergabe von Variablen innerhalb einer eigenen
    Interruptroutine, da sie davon ausgehen können, das das Datensegment
    mit hoher Sicherheit nicht dem benötigtem Datensegment von PowerBASIC
    entspricht. Allerdings auch hier haben uns die Entwickler von
PowerBASIC
    eine große Hintertür offen gelassen. Die Adressierung über das Code-
    segment, welches in der Regel immer gleich ist! Allerdings klappt
dieser
    Trick nur im Inline-Assembler, zur Übergabe von/zu reinen PowerBASIC
    Routinen müssen sie diese Variable umkopieren.

    Beispiel:
            ! mov ax, &h1234
            ! mov Demo, ax
            ! mov bx, Demo
            ! retn

            Demo:
            ! dw 0

    Sollten Sie sich diese Sache unter einem Debuger ansehen, so werden
sie
    feststellen das PowerBASIC vor dem Variablenzugriff das Präfix &h2E
    (Adressierung über das Codesegment) voranstellt und das '! dw 0'-Feld
    den Wert &h1234 angenommen hat.


    5.12. Erstellen von 32bit-Zeigern
    ----------------------------------
    Oft werden 32bit Zeiger benötigt um eigene Interrupt-Prozeduren, alte
    Interrupt-Handler oder auch Gerätetreiber wie CTVDSK/CT-VOICE und
    HIMEM/MSCDEX aufzurufen. Da die Erstellung des 32bit Zeigers in einem
    der vorangegangenden Absätze beschrieben wurde, hier nur noch der
    eigentliche Syntax:

    Beispiel:
            ! jmp dword Demo&
            ! jmp dword ptr Demo&
            ! call dword Demo&
            ! call dword ptr Demo&

    Die Zeiger können ebenfalls dem Codesegment entnommen werden!


    5.13. Konvertierung von REG nach Inline-ASM
    -------------------------------------------
    Ebenfalls recht einfach läuft die Umsetzung von REG- nach Inline-
    Assemblersourcen ab. Im Gegensatz zum REG-Befehl, welcher die Inhalte
    der Prozessorregister in einem internen REG-Array zwischenpuffert, be-
    wirkt ein Zugriff über den Inline-Assembler sofort eine direkte Mani-
    pulierung der Prozessorregister. Der REG-Befehl übergibt die REG-Werte
    erst beim Aufruf von CALL INTERRUPT. Bitte beachten Sie diesen Unter-
    schied und Sie werden weniger Probleme haben.
    Ansonsten können Sie zum Beispiel folgende Befehle 1:1 umsetzen:

    Beispiele:
            REG 1, &h12345           -> ! mov ax, &h1234
            REG 2, &hFF              -> ! mov bl, &hFF
            REG 3, &h22 * 256        -> ! mov ch, &h22
            REG 4, &hAABB            -> ! mov dh, &hAA
                                        ! mov dl, &hBB
            REG 9, Demo%             -> ! mov es, Demo%
            CALL INTERRUPT &h21      -> ! int &h21
            Low?? = REG(1) AND 255   -> ! mov low??, al
            High?? = REG(1) \ 256    -> ! mov High??, ah


    5.14. Konvertierung von A86 nach Inline-ASM
    -------------------------------------------
    Prinzipiell ohne Probleme läuft eine Umsetzung von A86-Sourcen ab.
Ent-
    fernen Sie einfach den Stackrahmen und binden Sie die Assemblerzeilen
    einfach in Ihren Inline-Assembler ein. Am besten ist es, wenn Sie dazu
    einen Funktionsaufruf erstellen, der die Variablen immer BYVAL
übergibt,
    den Rest erledigt PowerBASIC.


    ======================================================
    6. Tip's in Verbindung mit Pointern und PowerBASIC 3.2
    ======================================================

    Kürzübersicht:
    6.1. Allgemeines über Pointer
    6.2. Was sind Pointer und was können sie leisten?
    6.3. PowerBASIC-Pointer und dynamische Strings
    6.4. PowerBASIC-Pointer und feste Strings
    6.5. PowerBASIC-Pointer und Flex Strings
    6.6. PowerBASIC-Pointer und Type Strukturen
    6.7. Demonstrations-Source


    6.1. Allgemeines über PowerBASIC-Pointer
    ----------------------------------------
    Pointer in Verbindung BASIC haben bereits zahlreiche Diskussionen ent-
    facht, die dynamische Speicherverwaltung von PowerBASIC wird hierbei
    immer als 'Geburtsfehler' ins Feld geführt.
    Das sich dieser elementare Vorteil der BASIC-Programmiersprache auch
    ohne Probleme beim Einsatz von Pointern ausspielen läßt, soll Ihnen
    dieser Abschnitt erläutern, denn der Einsatz von Pointern in
PowerBASIC
    ist mit keinerlei Einschränkungen verbunden!
    Allerdings sollten Sie für das Lesen folgender Artikel bereits Wissen
    über die interne Wirkungsweise von BASIC und auch DOS haben.


    6.2. Was sind Pointer und was können sie leisten?
    -------------------------------------------------
    Pointer (auch Zeiger genannt) bieten die Möglichkeit, Datenstrukturen
    an einer beliebigen Stelle des DOS-Speichers zu interpretieren. Dazu
    müssen Sie dem Pointer nur eine beliebige Adresse übergeben.
    Pointer dienen vor allem dazu Speicherbereiche zu nutzen, welche
außer-
    halb der dynamischen Speicherverwaltung von PowerBASIC liegen. Sie
    können mit Pointern z.B. direkt Strukturen interpretieren, auf die von
    DOS-Funktionen Zeiger zurückgeliefert werden, wie z.B.:
        - Directory Table Area
        - Drive Parameter Block
        - DOS Info Block
        - PSP
        - Environment Block
        - und und und ...
    Das bisher notwendige Umkopieren mit DEF SEG/POKE/PEEK entfällt ab
sofort
    und auch das leidige DEF SEG = PEEKI(...) sollten Sie in einem solchem
    Falle sofort vergessen.


    6.3. PowerBASIC-Pointer und dynamische Strings
    ----------------------------------------------
    String-Pointer auf feste Strings müssen in PowerBASIC wie folgt
definiert
    werden:

        DIM Pointer AS STRING PTR

     Der Pointer selber ist wie folgt zu initialisieren:

        Pointer = VARPTR32(Demo1$)

    Beispiel:
           
'***************************************************************
            '
            ' Demo zum korrekten Umgang mit Pointern und dynamische
Strings
            '
           
'***************************************************************

            DIM Pointer1 AS STRING PTR   ' String Pointer für dynamische
                                         ' Strings definieren
            Pointer1 = VARPTR32(Demo1$)  ' Zeiger auf Stringhandle holen

            CLS
            PRINT "Adresse:      Demo1$:       Pointer1:"

            Demo1$ = "123456"
            PRINT HEX$(VARPTR32(Demo1$)), Demo1$, @[EMAIL PROTECTED]
            Demo1$ = "654321"
            PRINT HEX$(VARPTR32(Demo1$)), Demo1$, @[EMAIL PROTECTED]
            Demo1$ = "!Test!"
            PRINT HEX$(VARPTR32(Demo1$)), Demo1$, @[EMAIL PROTECTED]
    6.4. PowerBASIC-Pointer und feste Strings
    -----------------------------------------
    String-Pointer auf feste Strings müssen in PowerBASIC wie folgt
definiert
    werden:

        DIM Demo AS STRING * 6
        DIM Pointer AS STRING PTR * 6

    Der Pointer selber ist wie folgt zu initialisieren:

        Pointer = VARPTR32(Demo$)

    Beispiel:
           
'***************************************************************
            '
            ' Demo zum korrekten Umgang mit Pointern und festen Strings
            '
           
'***************************************************************

            DIM Demo2 AS STRING * 6      ' String mit konstanter Länge
                                         ' definieren!
            DIM Pointer2 AS STRING PTR * 6
                                         ' String Pointer definieren
            Pointer2 = VARPTR32(Demo2$)  ' Zeiger auf String holen

            PRINT
            PRINT
            PRINT "Adresse:      Demo2$:       Pointer2:"

            Demo2$ = "123456"
            PRINT HEX$(VARPTR32(Demo2$)), Demo2$, @[EMAIL PROTECTED]
            Demo2$ = "654321"
            PRINT HEX$(VARPTR32(Demo2$)), Demo2$, @[EMAIL PROTECTED]
            Demo2$ = "!Test!"
            PRINT HEX$(VARPTR32(Demo2$)), Demo2$, @[EMAIL PROTECTED]
    6.5. PowerBASIC-Pointer und FLEX-Strings
    ----------------------------------------
    Pointer auf FLEX-Strings müssen in PowerBASIC wie folgt definiert
    werden:

        DIM Demo AS FLEX
        DIM Pointer AS FLEX PTR

    Der Pointer selber ist wie folgt zu initialisieren:

        Pointer1 = VARPTR32(Demo1$)

    Um mit FLEX-Strings korrekt arbeiten zu können, müssen diese vor dem
    Erstellen des Pointers mit MAP gebildet werden!

    Beispiel:
           
'***************************************************************
            '
            ' Demo zum korrekten Umgang mit Pointern und FLEX Strings
            '
           
'***************************************************************

            DIM Demo3 AS FLEX            ' String als FLEX definieren!
            DIM Pointer AS FLEX PTR
            MAP Demo3$$ * 10             '
            FLEXCHR$ = "."

            Pointer = VARPTR32(Demo3$$)  ' Zeiger auf FLEX$-Handle holen

            PRINT
            PRINT
            PRINT "Adresse:      Demo3$$:      Pointer:"

            Demo3$$ = "123456"
            PRINT HEX$(VARPTR32(Demo3$$)), Demo3$$, @[EMAIL PROTECTED]
            Demo3$$ = "654321"
            PRINT HEX$(VARPTR32(Demo3$$)), Demo3$$, @[EMAIL PROTECTED]
            Demo3$$ = "!Test!"
            PRINT HEX$(VARPTR32(Demo3$$)), Demo3$$, @[EMAIL PROTECTED]
    6.6. PowerBASIC-Pointer und TYPE Strukturen
    -------------------------------------------
    Pointer auf TYPE Strukturen müssen in PowerBASIC wie folgt definiert
    werden:

    TYPE Demo4_Struc                          ' TYPE definieren
            Demo5  AS BYTE
            Demo6 AS BYTE
    END TYPE

    Der Pointer selber ist wie folgt zu initialisieren:

    DIM TypeDemo AS SHARED Demo4_Struc PTR

    Ein Beispiel zu Pointern und TYPE Strukturen finden sie eine Source
    im folgenden Abschnitt.


    6.7. Demonstrations-Source
    --------------------------
   
'************************************************************************
    '
    ' Zugriff auf den Videoram über Pointer in PowerBASIC 3.2
    '
    ' (c) Thomas Gohel
    '
    ' Eine kleine Demonstration, das Pointer wirklich nichts (!!) mit der
    ' internen Speicherverwaltung zu tun haben und der erfolgreiche
Einsatz
    ' von Pointern sehr gute interne Kenntnisse von PowerBASIC
vorraussetzt.
    '
    ' In diesem Demo wird der Videoram als Speicher mißbraucht und
gezeigt,
    ' wie PRINT-Ausgaben den Inhalt der beiden Pointer VIDEORAM und
ZEICHEN
    ' modifizieren.
    '
    ' Als sinnvolle Erweiterung könnte man diese Routine zum schnellen
    ' Sichern und Restaurieren des kompletten Videorams nutzen:
    '
    '         @[EMAIL PROTECTED]
 = @[EMAIL PROTECTED]
    '
    ' würde den kompletten Inhalt der ersten Page in die zweite Seite
retten
    ' um später wieder restauriert werden zu können
    '
   
'************************************************************************

    TYPE Zeichen_Struc                       ' Aufbau eines einzelnen
Zeichens
            Wert  AS BYTE
            Farbe AS BYTE
    END TYPE

    TYPE Screen_Struc                        ' Aufbau der Seiten im
Videoram
            Page1 AS STRING * 4096           ' Seite 1
            Page2 AS STRING * 4096           ' Seite 2
            Page3 AS STRING * 4096           ' Seite 3
            Page4 AS STRING * 4096           ' Seite 4
    END TYPE

    DIM Zeichen AS SHARED Zeichen_Struc PTR
    DIM Videoram AS SHARED Screen_Struc PTR  ' TYPE-Strukturen erzeugen

    Videoram = pbvScrnBuff                   ' Type-Struktur auf den
Anfang
                                             ' des aktuellen Video-Ram
                                             ' schieben,
                                             ' PowerBASIC nutzt und
verwaltet
                                             ' den Videoram ab sofort als
                                             ' festen Stringspeicher! 
:-)))
    Zeichen  = pbvScrnBuff                   ' TYPE-Struktur soll gleichen
                                             ' Speicherbereich wie PRINT
und
                                             ' VIDEORAM nutzen

    SCREEN 0                                 ' Screen-Mode setzen
    CLS                                      ' alles löschen

    PRINT "Dies ist ein Test"                ' normales PRINT auf den
                                             ' Bildschirm
    A$=INPUT$(1)

    PRINT LEFT$(@[EMAIL PROTECTED]
)          ' Anzeigen der PRINT-Befehl
                                             ' automatisch auch unsere
                                             ' Struktur gefüllt wird
    A$=INPUT$(1)

    @[EMAIL PROTECTED]
 = @[EMAIL PROTECTED]
        ' Videoram in Page 2 retten

    @[EMAIL PROTECTED]
  = 76                      ' Jetzt wird die Zeichen-
                                             ' Struktur mit einem Wert
    @[EMAIL PROTECTED]
 = 14                      ' gefüllt. Hierbei erfolgt
                                             ' gleichzeitig die Ausgabe
                                             ' auf den Bildschirm und das
                                             ' aktualiseren von der Video-
                                             ' RAM-Struktur
    PRINT LEFT$(@[EMAIL PROTECTED]
)
    A$=INPUT$(1)

    @[EMAIL PROTECTED]
 = @[EMAIL PROTECTED]
        ' Videoram von Page 1
                                             ' restaurieren

    Pointer_Speed_Test:

            PRINT STRING$(25*80,178);        ' Bildschirm füllen
            LOCATE 1, 9
            COLOR 11, 1
            PRINT "  -= STRING-Manipulation innerhalb des";
            PRINT " Bildschirmspeichers! =-  "
            @[EMAIL PROTECTED]
 = @[EMAIL PROTECTED]
            COLOR 14, 1
            LOCATE 8,20: PRINT
"+----------------------------------------+"
            FOR i% = 9 TO 18
                LOCATE i%, 20
                PRINT          "|                                       
|"
            NEXT i%
            LOCATE 10, 22: PRINT "Bildschirmspeicher wird als STRING"
            LOCATE 11, 22: PRINT "verwaltet!"
            LOCATE 13, 22: PRINT "  -= Ein Demo zur PowerBASIC-FAQ =- "
            LOCATE 19, 20
            PRINT             
"+----------------------------------------+"

            @[EMAIL PROTECTED]
 = @[EMAIL PROTECTED]
            FOR i% = 1 to 1000
                @[EMAIL PROTECTED]
 = @[EMAIL PROTECTED]
                @[EMAIL PROTECTED]
 = @[EMAIL PROTECTED]
            NEXT i%

            FOR i% = 1 TO 10
                FOR Durchlauf% = 1 TO 256
                    Zeichen = pbvScrnBuff
                    FOR Offset% = 1 TO 2048
                        IF @[EMAIL PROTECTED]
 > 32 THEN
                            DECR @[EMAIL PROTECTED]
                        END IF
                        Zeichen = Zeichen + 2
                    NEXT Offset%
                NEXT Druchlauf%
                @[EMAIL PROTECTED]
 = @[EMAIL PROTECTED]
            NEXT i%
   
'************************************************************************


    ===================================================
    7. Tip's in Verbindung mit Turbo-C bzw. Borland C++
    ===================================================

    Kurzübersicht:
    7.1.  Autor
    7.2.  Warum externe Routinen für PB3 in C schreiben/verwenden
    7.3.  Speicher-Modell angleichen
    7.4.  Einschränkungen durch den PowerBASIC 3.x Compiler/-Linker
    7.5.  Parameterübergabe
    7.6.  PowerBasic-Beispiel
    7.7.  Zugehöriger C-Modul
    7.8.  Der zur C-Routine gehörige Assembler-Code
    7.9.  Verwendung von Routinen fremder C-Bibliotheken
    7.10. Massnahmen bei Verwendung von PB V2.1


    7.1. Autor
    ----------
    Die Tip's für PowerBASIC in Verbindung mit C-Compilern wie Turbo-C
bzw.
    Borland C++ wurden freundlicherweise von:

                Andras Hoeffken <ah@[EMAIL PROTECTED]
>
                Andras Hoeffken <2:2480/13.34 @[EMAIL PROTECTED]
 fidonet>
                Andras Hoeffken <130:1316/103 @[EMAIL PROTECTED]
 basnet-Germany>

    für diese FAQ zur Verfügung gestellt.

    Sehr nützliche Hinweise sind auch in der Datei CTOPB.FAQ enthalten,
diese
    gehört zum Lieferumfang von PB Vs. 3.2.


    7.2. Warum externe Routinen für PB3 in C schreiben/verwenden
    ------------------------------------------------------------
    - C-Routinen ergeben schnell laufenden Code
    - für extrem schnellen Code: C-Source schreiben und in ASM-Source
      übersetzen lassen (geht VIEL schneller als ASM-Source direkt
      zu schreiben), dann den ASM-Quellcode optimieren (Beispiel: s.u.)
    - Routinen fremder C-Bibliothen können mit PB verwendet werden


    7.3. Speicher-Modell angleichen
    -------------------------------
    Für das Linken von *.EXE-Files können (z.B. bei MASM oder C)
verschiedene
    Speichermodelle vorgegeben werden, z.B. Tiny, Small, Medium, Compact,
    Large, Huge, ...

    Für die von PowerBASIC erzeugten *.EXE gilt nur:
            PowerBASIC 3.x - Speichermodell = LARGE
            (PB benutzt für Code- und Datensegmente 32-bit FAR Pointer)

    Der C-Compiler muß daher in seinem Menü:
            Options / Compiler / Code Generation / Model
    auf das Modell LARGE eingestellt werden.


    7.4. Einschraenkungen durch den PowerBASIC 3.x Compiler/-Linker
    ---------------------------------------------------------------
    a) Der PB3-Linker kann nur .OBJ-Module mit EINEM Datensegment
einbinden,
       bei einem 2. Datensegment oder einer DGROUP streikt der PB3-Linker
       und erzeugt Errors. - C-Compiler verwenden in der Grundeinstellung
       zunaechst immer mehrere Datensegmentnamen, die in der Datengruppe
       DGROUP zusammengefasst sind (das hat bestimmte Vorteile). Die IDE
       des C-Compilers muss daher in ihrem Menü:
                   Options / Compiler / Names
       wie folgt eingestellt werden:

           Code Segment: _TEXT          Bss Segment:      _DATA
           Code Group:                  Bss Group:
           Code Class:   TEXT           Bss Class:        DATA
           Data Segment: _DATA          Far Data Segment:
           Data Group:                  Far Data Group:
           Data Class:   DATA           Far Data Class:
           (die noch vorhandenen Sternchen MUESSEN gelöscht werden)

       Jetzt erzeugt der C-Compiler nur noch EINEN Daten-Segmentnamen
           und keine DGROUP mehr!

    b) Der PB3-Linker (< Vs. 3.2) akzeptiert keine "_" bei Segmentnamen
(ist
       bei C ein Standard), daher: In der $LINK-Zeile "$ALIAS" verwenden
       (s.u.)!

    c) Der PB3-Compiler (< Vs. 3.2) akzeptiert keine "_" in Namen von
       Funktionen und SUB's (ist bei C ein Standard), daher: In den
DECLARE-
       Zeilen "$ALIAS" verwenden (s.u.)!

    d) Der PB3-Compiler übergibt bei Funktionen und Subs die Parameter in
der
       Reihenfolge "von rechts nach links" (Pascal Konvention) und er-
       wartet, daß die externe Routine den Stack selbst aufräumt, C-
       Compiler arbeiten umgekehrt. Daher: In den DECLARE-Zeilen "CDECL"
       verwenden (s.u.)!


    7.5. Parameterübergabe
    -----------------------
    PB3 uebergibt Parameter an externe Routinen auf 2 Arten:
        - mit 'far pointern' ('by reference' bzw. 'by copy')
        - direkt auf dem Stack (BYVAL)

    Entsprechend müssen die Deklarationen in den C-Routinen angepaßt
werden.


    7.6. PowerBASIC-Beispiel
    ------------------------
    Im nachfolgenden .BAS-Programm zeigen 2 Routinen die Mechanismen:
    - A: in der Addier-Funktion "addab" (integer) wird "c=a+b" berechnet,
der
         Funktionswert wird mit "x=c+1" zurückgegeben.
    - B: in der String-Routine "chst" wird das erste Zeichen eines Strings
         durch "*" ersetzt.

    --- Cut ------------------------------------------------------------
    'PB3_TBC.BAS - Turbo-C-Routinen in PB3.x einlinken

    $ALIAS DATA AS "_DATA"  'Zuordnung eines(!) Segmentnamens
    $LINK "pb3_tbc.obj"     'C-Spezialeinstellung ohne