Retro video games delivered to your door every month!
Click above to get retro games delivered to your door ever month!
X-Hacker.org- Watcom C/C++ User's Guide - the feature that allows us to place the results of c expressions into http://www.X-Hacker.org [<<Previous Entry] [^^Up^^] [Next Entry>>] [Menu] [About The Guide]
the feature that allows us to place the results of C expressions into
specific registers as part of the "setup" for the sequence of in-line code.
To illustrate this, let us look at another example.
Example:

     extern void BIOSSetCurPos( unsigned short __rowcol,
                                unsigned char __page );
     #pragma aux BIOSSetCurPos =     \
             "push bp"               \
             "mov ah,2"              \
             "int 10h"               \
             "pop bp"                \
             parm   [dx] [bh]        \
             modify [ah];

The "parm" attribute specifies the list of registers into which values are
to be placed as part of the prologue to the in-line code sequence.  In the
above example, the "set cursor position" function requires three pieces of
information.  It requires that the cursor row value be placed in the DH
register, that the cursor column value be placed in the DL register, and
that the screen page number be placed in the BH register.  In this example,
we have decided to combine the row and column information into a single
"argument" to the function.  Note that the function prototype for
BIOSSetCurPos is important.  It describes the types and number of arguments
to be set up for the in-line code.  It also describes the type of the return
value (in this case there is none).

Once again, having defined our in-line assembly code, let us see how it is
used in actual C code.

Example:

     #include <stdio.h>

     extern void BIOSSetCurPos( unsigned short __rowcol,
                                unsigned char __page );
     #pragma aux BIOSSetCurPos =     \
             "push bp"               \
             "mov ah,2"              \
             "int 10h"               \
             "pop bp"                \
             parm   [dx] [bh]        \
             modify [ah];


     void main()
     {
         BIOSSetCurPos( (5 << 8) | 20, 0 );
         printf( "Hello world\n" );
     }

To see how the code generator set up the register values for the in-line
code, let us take a look at the disassembled code.


         BIOSSetCurPos( (5 << 8) | 20, 0 );
      0008  ba 14 05                          mov     dx,0514H
      000b  30 ff                             xor     bh,bh
      000d  55                                push    bp
      000e  b4 02                             mov     ah,02H
      0010  cd 10                             int     10H
      0012  5d                                pop     bp

As we expected, the result of the expression for the row and column is
placed in the DX register and the page number is placed in the BH register.
The remaining instructions are our in-line code sequence.

Although our examples have been simple, you should be able to generalize
them to your situation.

To review, the "parm", "value" and "modify" attributes are used to:

 1. convey information to the code generator about the way data values are
    to be placed in registers in preparation for the code burst (parm),

 2. convey information to the code generator about the result, if any, from
    the code burst (value), and

 3. convey information to the code generator about any side effects to the
    registers after the code burst has executed (modify).  It is important
    to let the code generator know all of the side effects on registers when
    the in-line code is executed; otherwise it assumes that all registers,
    other than those used for parameters, are preserved.  In our examples,
    we chose to push/pop some of the registers that are modified by the code
    burst.

Online resources provided by: http://www.X-Hacker.org --- NG 2 HTML conversion by Dave Pearson