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  0026 bytes

     #pragma off (check_stack);

     extern void MyRtn( void );

     int i = { 1033 };


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

         while( i < 10000 ) {
      0005  81 fa 10 27       L1              cmp     DX,2710H
      0009  7d 06                             jge     L2

             i += 383;
         }
      000b  81 c2 7f 01                       add     DX,017fH
      000f  eb f4                             jmp     L1


         MyRtn();
      0011  89 16 00 00       L2              mov     _i,DX
      0015  e8 00 00                          call    MyRtn_
      0018  8b 16 00 00                       mov     DX,_i

         i += 13143;
      001c  81 c2 57 33                       add     DX,3357H
      0020  89 16 00 00                       mov     _i,DX

       };
      0024  5a                                pop     DX
      0025  c3                                ret


     No disassembly errors

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

     Segment: '_DATA' WORD  0002 bytes
      0000  09 04                   _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  0022 bytes

     #pragma off (check_stack);

     extern void MyRtn( void );
     #pragma aux MyRtn modify nomemory;

     int i = { 1033 };


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

         while( i < 10000 ) {
      0005  81 fa 10 27       L1              cmp     DX,2710H
      0009  7d 06                             jge     L2

             i += 383;
         }
      000b  81 c2 7f 01                       add     DX,017fH
      000f  eb f4                             jmp     L1


         MyRtn();
      0011  89 16 00 00       L2              mov     _i,DX
      0015  e8 00 00                          call    MyRtn_

         i += 13143;
      0018  81 c2 57 33                       add     DX,3357H
      001c  89 16 00 00                       mov     _i,DX

       };
      0020  5a                                pop     DX
      0021  c3                                ret


     No disassembly errors

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

     Segment: '_DATA' WORD  0002 bytes
      0000  09 04                   _i              - ..

     No disassembly errors

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

Notice that the value of i is in register DX 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 DX
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  001e bytes

     #pragma off (check_stack);

     extern void MyRtn( void );
     #pragma aux MyRtn parm nomemory modify nomemory;

     int i = { 1033 };


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

         while( i < 10000 ) {
      0005  81 fa 10 27       L1              cmp     DX,2710H
      0009  7d 06                             jge     L2

             i += 383;
         }
      000b  81 c2 7f 01                       add     DX,017fH
      000f  eb f4                             jmp     L1


         MyRtn();
      0011  e8 00 00          L2              call    MyRtn_

         i += 13143;
      0014  81 c2 57 33                       add     DX,3357H
      0018  89 16 00 00                       mov     _i,DX

       };
      001c  5a                                pop     DX
      001d  c3                                ret


     No disassembly errors

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

     Segment: '_DATA' WORD  0002 bytes
      0000  09 04                   _i              - ..

     No disassembly errors

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

Notice that after completion of the "while" loop we did not have to update i
with the value in register DX 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