5. Tip's in Verbindung mit dem Inline-Assembler (Teil 2)
Tip's in Verbindung mit dem Inline-Assembler (Teil 1)
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
gestattet 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
Codesegment, 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, bewirkt
ein Zugriff über den Inline-Assembler sofort eine direkte Manipulierung
der Prozessorregister. Der REG-Befehl übergibt die REG-Werte
erst beim Aufruf von CALL INTERRUPT. Bitte beachten Sie diesen Unterschied
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. Entfernen
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.