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 following form of the auxiliary pragma can be used to describe a http://www.X-Hacker.org [<<Previous Entry] [^^Up^^] [Next Entry>>] [Menu] [About The Guide]
The following form of the auxiliary pragma can be used to describe a
function that does not modify any memory (i.e., global or static variables)
that is used directly or indirectly by the caller.

+--------------------------------------------------------------------------+
|      #pragma aux sym modify nomemory [;]                                 |
|                                                                          |
+--------------------------------------------------------------------------+

where
    description

sym
    is a function name.

Consider the following example.


     #pragma off (check_stack);

     extern void myrtn(void);

     int i = { 1033 };

     extern Rtn() {
         while( i < 10000 ) {
             i += 383;
         }
         myrtn();
         i += 13143;
     };

To compile the above program, "rtn.c", we issue the following command.


     C>wcc rtn /oai /d1
     C>wpp rtn /oai /d1
     C>wcc386 rtn /oai /d1
     C>wpp386 rtn /oai /d1

For illustrative purposes, we omit loop optimizations from the list of code
optimizations that we want the compiler to perform.  The "d1" compiler
option is specified so that the object file produced by Watcom C/C++
contains source line information.

We can generate a file containing a disassembly of RTN.OBJ by issuing the
following command.


     C>wdis rtn /l /s /r

The "s" option is specified so that the listing file produced by the Watcom
Disassembler contains source lines taken from RTN.C.  The listing file
RTN.LST appears as follows.


     Module: rtn.c
     Group: 'DGROUP' CONST,_DATA

     Segment: '_TEXT' BYTE USE32  00000036 bytes

     #pragma off (check_stack);

     extern void myrtn(void);

     int i = { 1033 };


     extern Rtn() {
      0000  52                Rtn_            push    EDX
      0001  8b 15 00 00 00 00                 mov     EDX,_i

         while( i < 10000 ) {
      0007  81 fa 10 27 00 00 L1              cmp     EDX,00002710H
      000d  7d 08                             jge     L2

             i += 383;
         }
      000f  81 c2 7f 01 00 00                 add     EDX,0000017fH
      0015  eb f0                             jmp     L1


         myrtn();
      0017  89 15 00 00 00 00 L2              mov     _i,EDX
      001d  e8 00 00 00 00                    call    myrtn_
      0022  8b 15 00 00 00 00                 mov     EDX,_i

         i += 13143;
      0028  81 c2 57 33 00 00                 add     EDX,00003357H
      002e  89 15 00 00 00 00                 mov     _i,EDX

     }
      0034  5a                                pop     EDX
      0035  c3                                ret


     No disassembly errors

     ------------------------------------------------------------

     Segment: '_DATA' WORD USE32  00000004 bytes
      0000  09 04 00 00             _i              - ....

     No disassembly errors

     ------------------------------------------------------------


Let us add the following auxiliary pragma to the source file.


     #pragma aux myrtn modify nomemory;

If we compile the source file with the above pragma and disassemble the
object file using the Watcom Disassembler, we get the following listing
file.


     Module: rtn.c
     Group: 'DGROUP' CONST,_DATA

     Segment: '_TEXT' BYTE USE32  00000030 bytes

     #pragma off (check_stack);
     #pragma aux myrtn modify nomemory;


     extern void myrtn(void);

     int i = { 1033 };

     extern Rtn() {
      0000  52                Rtn_            push    EDX
      0001  8b 15 00 00 00 00                 mov     EDX,_i

         while( i < 10000 ) {
      0007  81 fa 10 27 00 00 L1              cmp     EDX,00002710H
      000d  7d 08                             jge     L2

             i += 383;
         }
      000f  81 c2 7f 01 00 00                 add     EDX,0000017fH
      0015  eb f0                             jmp     L1


         myrtn();
      0017  89 15 00 00 00 00 L2              mov     _i,EDX
      001d  e8 00 00 00 00                    call    myrtn_

         i += 13143;
      0022  81 c2 57 33 00 00                 add     EDX,00003357H
      0028  89 15 00 00 00 00                 mov     _i,EDX

     }
      002e  5a                                pop     EDX
      002f  c3                                ret


     No disassembly errors

     ------------------------------------------------------------

     Segment: '_DATA' WORD USE32  00000004 bytes
      0000  09 04 00 00             _i              - ....

     No disassembly errors

     ------------------------------------------------------------


Notice that the value of i is in register EDX after completion of the
"while" loop.  After the call to myrtn, the value of i is not loaded from
memory into a register to perform the final addition.  The auxiliary pragma
informs the compiler that myrtn does not modify any memory (i.e., global or
static variables) that is used directly or indirectly by Rtn and hence
register EDX contains the correct value of i.

The preceding auxiliary pragma deals with routines that modify memory.  Let
us consider the case where routines reference memory.  The following form of
the auxiliary pragma can be used to describe a function that does not
reference any memory (i.e., global or static variables) that is used
directly or indirectly by the caller.

+--------------------------------------------------------------------------+
|      #pragma aux sym parm nomemory modify nomemory [;]                   |
|                                                                          |
+--------------------------------------------------------------------------+

where
    description

sym
    is a function name.

Notes:

 1. You must specify both "parm nomemory" and "modify nomemory".

Let us replace the auxiliary pragma in the above example with the following
auxiliary pragma.


     #pragma aux myrtn parm nomemory modify nomemory;

If you now compile our source file and disassemble the object file using
WDIS, the result is the following listing file.

     Module: rtn.c
     Group: 'DGROUP' CONST,_DATA

     Segment: '_TEXT' BYTE USE32  0000002a bytes

     #pragma off (check_stack);
     #pragma aux myrtn parm nomemory modify nomemory;


     extern void myrtn(void);

     int i = { 1033 };

     extern Rtn() {
      0000  52                Rtn_            push    EDX
      0001  8b 15 00 00 00 00                 mov     EDX,_i

         while( i < 10000 ) {
      0007  81 fa 10 27 00 00 L1              cmp     EDX,00002710H
      000d  7d 08                             jge     L2

             i += 383;
         }
      000f  81 c2 7f 01 00 00                 add     EDX,0000017fH
      0015  eb f0                             jmp     L1


         myrtn();
      0017  e8 00 00 00 00    L2              call    myrtn_

         i += 13143;
      001c  81 c2 57 33 00 00                 add     EDX,00003357H
      0022  89 15 00 00 00 00                 mov     _i,EDX

     }
      0028  5a                                pop     EDX
      0029  c3                                ret


     No disassembly errors

     ------------------------------------------------------------

     Segment: '_DATA' WORD USE32  00000004 bytes
      0000  09 04 00 00             _i              - ....

     No disassembly errors

     ------------------------------------------------------------


Notice that after completion of the "while" loop we did not have to update i
with the value in register EDX before calling myrtn.  The auxiliary pragma
informs the compiler that myrtn does not reference any memory (i.e., global
or static variables) that is used directly or indirectly by myrtn so
updating i was not necessary before calling myrtn.

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