TIP: Click on subject to list as thread! ANSI
echo: power_bas
to: ALLE
from: THOMAS GOHEL
date: 1997-07-01 00:00:00
subject: FAQ: PowerBASIC 09/16 (Assembler Part 1)00:00:0007/01/97

    ================================================
    5. Hints in connection with the InLine-Assembler
    ================================================
    Shortindex:
    5.1.  Principles of the function of the InLine-Assembler
    5.2.  Assembler Syntax Error
    5.3.  Faulty passing of Variables in the InLine-Assembler
    5.4.  Problems with LDS/LES
    5.5.  Crash after calling own INT-Functions
    5.6.  Fixup Overflow
    5.7.  Dividing Variables from WORD to BYTE
    5.8.  Dividing Variables from DWORD to WORD
    5.9.  Access to Arrays / Structures with the InLine-Assembler
    5.10. Parameter return with the InLine-Assembler
    5.11. Parameter return in Interrupt-Procedures
    5.12. Creating 32bit-Pointers
    5.13. Converting from REG to InLine-ASM
    5.14. Converting from A86 to InLine-ASM
    The tips shown here are not a tutorial in InLine-Assembler, but may
    help solve many beginner mistakes. A more detailes description of the
    interactions will not be written here, if it does not belong to the
    problem itself.
    5.1. Principles of the function of the InLine-Assembler
    -------------------------------------------------------
    The PowerBASIC InLine-Assembler contains the functions of the Intel
    8086 CPU. This means that you may have to adapt the InLine-Assembler-
    Code of other High-Language-Compilers or true Assembler-Code to the
    PowerBASIC InLine-Assembler, because they quite often contain 80286
    commands. Usually the following commands have to be converted:
    
        Source             - >      PowerBASIC
        shr ax, 2                   ! shr  ax, 1
                                    ! shr  ax, 1
                                    or like this:
        -----------------------------------------------------------
        shl ax, 3                   ! push cx
                                    ! mov  cl, 3
                                    ! shl  ax, cl
                                    ! pop  cx
        -----------------------------------------------------------
        pusha                       ! push ax
                                    ! push bx
                                    and so on until all registers are
                                    saved
        -----------------------------------------------------------
        popa                        analog, only restore registers
    
    5.2. Assembler Syntax Error
    ---------------------------
    When we forget the 'true' Syntax Errors, which usually occurs when you
    are not quite used to Assemblercommands, there still is an 'obvious'
    Syntax Error which can be marked by the InLine-Assembler of
    PowerBASIC. This is the case when the Compiler can't use a Variable in
    the InLine-Assembler because it isn't defined in any way.
    PowerBASIC usually creates used Variables within true BASIC-Source by
    itself and allocates memory for it. You have to do that yourself
    within the InLine-Assembler.
    Example:
            ! mov ax, Demo%
    This causes a Syntax Error because the Compiler can't do anything with
    the Variable 'Demo%'. You should first set the Variable to a value:
            Demo% = 1
            ! mov ax, Demo%
    Now the Compiler accepts the Assemblerline. You don't have to assign a
    value to a Variable every time, a simple DIM or SHARED, PUBLIC, LOCAL
    etc. is enough and initialises 'Demo%'.
    5.3. Faulty passing of Variables in the InLine-Assembler
    --------------------------------------------------------
    You probably often swore around because a working routine with REG(x)
    didn't work crrectly after conversion to the InLine-Assembler or when
    your Testroutine wouldn't do its job in a SUB/FUNCTION.
    The solution is relatively simple: You have to pass the variables to
    the InLine-Assembler BYVAL.
    Example:
            Demo 1
            FUNCTION Demo(BYVAL i%) public
                    ! mov ax, i%
                    ! inc ax
                    ! mov i%, ax
                    PRINT i%
            END FUNCTION
    This little Demo simply adds the value '1' using the InLine-Assembler
    and then prints it on the screen. Simply leave out the BYVAL and then
    test the Demo again!
    5.4. Problems with LDS/LES
    --------------------------
    Compareable to the passing of the parameters is the function of the
    commands LDS/LES. It is also essential whether a variable  is passed
    'BY COPY', 'BY REFERENCE' or 'BY VALUE'. The followingcan be taken as
    rule of thumb:
    BY REFERENCE: - default in the main program
                  - or when a variable is declared SHARED/PUBILC etc.
    BY COPY:      - default in a SUB/FUNCTION, if the variables aren't
                    passed BY VALUE.
    BY VALUE:     - always interpreted by the InLine-Assembler as BY VALUE
    You should only pass variables of type BY COPY to LDS/LES, because
    only then the DS/ES Segmentaddresses will be loaded and the
    Offsetaddresses into the other Registers.
    When passing BY REFERENCE DS/ES will be loaded with the high value
    contents of the variable, if of type Long/DWord, else the DS/ES
    Register will contain an irrelevant value. The other Registers will
    contain the low value of the variable.
    Example:
            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. Crash after calling own INT-Functions
    ------------------------------------------
    You will ask yourself: Why this section in the FAQ? Does the
    PowerBASIC InLine-Assembler have any Bugs? The answer is definetly:
    NO.
    But many calls using INT-Functions of the BIOS/DOS are connected to
    some trouble, because they change important Segments or specially
    address them. Many buffers that have to be passed to a function look
    for their pointer in the Datasegment-Register (DS). PowerBASIC also
    addresses its variables using DS, so that conflicts are 'programmed'
    here. It should not be like this, for example:
            ! mov ax, &h3D90        ; Function File open
            ! mov ds, FileSeg??     ; Load segment of Filename,
            ! mov dx, FileOff??     ; First error, because FileOff??
                                    ; can't be addressed using DS. DS
                                    ; is already pointing somewhere else.
            ! int &h21              ; INT-Call
            ! mov Handle%, ax       ; Because DS still points to nowhere
                                    ; for PowerBASIC, this is wrong, too,
                                    ; and PowerBASIC will crash sooner or
                                    ; later.
    A clean listing should look like this:
            ! push ds               ; Save DS
            ! mov  ax, &h3D90
            ! mov  dx, FileOff??    ; Load Offset of Filename
            ! mov  ds, fileSeg??    ; Load Segment of Filename, not needed
                                    ; by PowerBASIC anymore
            ! int &h21              ; INT-Call
            ! pop ds                ; Restore PowerBASIC Segment
            ! mov Handle%, ax       ; Save Handle% (Or Errorcode)
            ! jnc ...               ; Check Carry-Flag
    5.6. Fixup Overflow
    -------------------
    The problem is relatively easy and simple: The 8086 CPU only allows
    jumps of type SHORT, meaning that you can only jump to labels within
    -127/+128 OpCodes directly.
    The following example also creates such an error:
            DemoLabel:
            
            ! jc DemoLabel
    To get around this, you'll just have to address the whole thing a
    little different. This is principally no problem once you know it:
            DemoLabel:
            
            ! jnc DemoWeiter
            ! jmp near DemoLabel
            DemoWeiter:
    But this can be found in any good Assembler book...
    5.7. Dividing variables from WORD to BYTE
    -----------------------------------------
    Should you still turn your 16bit variables into its 8bit parts with
    mathematical work, it is time to finally stop it! The CPU can do it by
    itsself:
    Example:
            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. Dividing variables frob DWORD to WORD
    ------------------------------------------
    More often you have the problem that you have pointers of type DWORD
    in PowerBASIC, but you don't know how to pass them to the InLine-
    Assembler or turn them into WORD. Principally this is quite simple
    (When you know how):
    Example:
            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.  Access to Arrays / Structures with the InLine-Assembler
    -------------------------------------------------------------
    Access to static Datastructures is relatively easy with the InLine-
    Assembler if you already know the correct Offsetaddresses.
    PowerBASIC allows the following Syntax:
    Example:
            ! mov ah, byte ptr es:[di][22]
    This copies the value to Offset 22 of the address ES:DI into the AH-
    Register.
--- CrossPoint v3.11 R
2:2410/330.1)
---------------
* Origin: PBSOUND, PBFILES (27MB), PBFAQ, PBRULES, PBHIVGA at:

SOURCE: echomail via exec-pc

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.