5. Hints in connection with the Inline-Assembler (Part 2)
Hints in connection with the Inline-Assembler (Part 1)
5.10. Parameter return with the Inline-Assembler
In opposite to true Assembler the return of a variable works slightly
different in the PowerBASIC Inline-Assemble. PowerBASIC 3.0 for
example does not allow the direct return from the Inline-Assembler to
the FUNCTION, this is only possible with a little trick.
Example:
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
From PowerBASIC 3.1 on you can directly pass the return value to the
FUNCTION, only with 32bit (and bigger) values have to be passed using
a little trick:
Example:
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
Very hard is the passing of variables from within an own
Interruptroutine, because you can guess that the Datasegment isn't the
same as the one used by PowerBASIC. But the developers of PowerBASIC
have left us a big back door here. The addressing using the
Codesegment, which is usually the same! Yet this trick only works with
the Inline-Assembler, to pass from/ to true PowerBASIC-Routines you
will have to recopy this variable.
Example:
! mov ax, &h1234
! mov Demo, ax
! mov bx, Demo
! retn
Demo:
! dw 0
Should you look at this thing with a Debugger, you will notice that
PowerBASIC will add the Prefix &h2E (addressing using the Codesegment)
in front of the access to the variable and the '!dw 0' field will hold
the value &h1234.
5.12. Creating 32Bit-Pointers
Often 32Bit Pointers are needed for some Interrupt-Procedures to call
old Interrupt-Handlers or Devicedrivers like CTVDSK/CT-VOICE and HIMEM/
MSCDEX. Because the creation of a 32Bit Pointer was described in a
previous Chapter, here is the actual Syntax:
Example:
! jmp dword Demo&
! jmp dword ptr Demo&
! call dword Demo&
! call dword ptr Demo&
The pointers can also be taken from the Codesegment!
5.13. Converting from REG to Inline-Assembler
The conversion from REG- to Inline-Assemblersources is also relatively
simple. Instrad of the REG-Command, which buffers the Contents of the
Processorregisters in an internal REG-Array, an access over the Inline-
Assembler causes a direct manipulation of the Processorregister. The
REG-Command passes the REG-Values when CALL INTERRUPT is executed.
Please not this difference and you will have not as many problems.
You can translate all other commands 1:1:
Example:
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. Converting from A86 to Inline-Assembler
Usually a translation of A86-Sources can be done without problems.
Remove the Stackborder and include the Assemblerlines into the Inline-
Assembler. It will be best ig you create a FUNCTION call that passes
the variables BYVAL, the rest is done by PowerBASIC.