home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Tools / TASM V5 / TASMDOC.PAK / TSM_UTIL.TXT < prev   
Encoding:
Text File  |  1996-02-21  |  23.8 KB  |  678 lines

  1. /*************************************************************************/
  2.                            TSM_UTIL.TXT
  3.                           TURBO ASSEMBLER
  4.  
  5. This file documents H2ASH and H2ASH32, utilities that can be used with 
  6. TASM.
  7.  
  8. 1)  Online Documentation for H2ASH and H2ASH32
  9. ==============================================
  10. C/C++ modules within a program typically share definitions of types and data
  11. structures among themselves. They do this by including small files called
  12. header files, which contain type definitions and data structure definitions
  13. used by more than one module. A C/C++ header file usually has a name ending
  14. in H.  Similarly, assembly modules use header files with names that end in
  15. .ASH (or .INC).
  16.  
  17. Programs containing modules written in both C or C++ and modules written
  18. using Turbo Assembler must be able to share definitions of types and data
  19. structures.  The H2ASH converter utility lets this happen.
  20.  
  21. The converter has the following limitations:
  22.  
  23.   -- All executable statements are ignored; no code output is generated.
  24.  
  25.   -- #INCLUDEs are fully expanded in the output.
  26.  
  27.   -- Name conflicts can occur in the assembly output since C++ scoping
  28.      rules differ greatly from assembly rules; using Ideal mode output
  29.      can help.
  30.  
  31.   -- Multiple Inheritance, Virtual Base Classes, and Templates are not
  32.      supported in this version of H2ASH.
  33.  
  34. The H2ASH converter not only smooths the interface between C/C++ and assembly
  35. language, it also lets you write C++ base classes directly in assembly
  36. language (for maximum performance). H2ASH automatically converts base class
  37. declarations in C++ into equivalent assembly object definitions, and defines
  38. method names. We recommend that you use the following procedure for writing
  39. base classes in assembly language:
  40.  
  41.   1) Write the class declaration in a C/C++ header file.
  42.  
  43.   2) Include the C header file in all descendant classes, and in the C/C++
  44.      modules that use the base class.
  45.  
  46.   3) Use the H2ASH converter on the header file to produce an assembly
  47.      object header file; you can automate this by setting up a makefile.
  48.  
  49.   4) Include the assembly object header file in the module where the
  50.      assembly language methods are written.
  51.  
  52.  
  53. Command Line Interface for H2ASH
  54. --------------------------------
  55. You can invoke H2ASH by typing the following command on the command line:
  56.  
  57.       H2ASH [[switches] <filename> [<filename> ... ]]
  58.  
  59. H2ASH triggers the printing of a help screen. By default, H2ASH accepts a
  60. C/C++ header file, and produces a Turbo Assembler (TASM) 3.0 compatible
  61. assembly include file with extension .ASH.  The resulting file is
  62. not a self-contained assembly language program; rather, it contains TASM
  63. type declarations and EQU statements that correspond to declarations in
  64. the original C/C++ header file.  H2ASH recognizes wild cards for filename
  65. matching.
  66.  
  67. All H2ASH-specific command line switches are a submode of the -q switch,
  68. that is they all have the following form:
  69.  
  70.      -q[<character>] [-]
  71.  
  72. H2ASH also recognizes a majority of the Borland C++ command-line switches.
  73. In particular, word-alignment (-a), force C++ compile (-P), set output file
  74. name (-o), define symbol (-D), and the compilation model directives (-mt,
  75. -ms, -ml, ...), are all supported.  For a definitive description of the BCC
  76. command-line interface, see the Borland C++ User's Guide.
  77.  
  78. H2ASH allows the following switches:
  79.  
  80.   -q-           turn off the H2ASH converter
  81.                 <default is on>
  82.  
  83.   -qc        pass c/c++ comments into the .ASH file
  84.                 <default is off>
  85.   
  86.   -qn           enable name-mangling
  87.                 <default is on>
  88.  
  89.   -qf           a 'strict' mode that strips out all untranslatable source
  90.                 code (as opposed to the default behavior of issuing a warning
  91.                 and partially translating the declaration in question)
  92.                 <default is off>
  93.  
  94.   -qi           generate Ideal mode code, as opposed to Masm mode code
  95.                 <default is off>
  96.  
  97.   -qd           generate EQUs for #DEFINE statements which appear on the
  98.                 command-line, in project configuration file, or in the
  99.                 original source program
  100.                 <default is on>
  101.  
  102.   -qb           generate EQUs for #DEFINE statements which are normally
  103.                 generated automatically by the compiler
  104.                 <default is off>
  105.  
  106.   -qt           generate TASM directives as needed (H2ASH will emit .DATA
  107.                 and .MODEL directives whenever static declarations appear
  108.                 in the original C/C++ header file.  The IDEAL directive is
  109.                 generated whenever Ideal mode is used)
  110.                 <default is on>
  111.  
  112.   -qs           pass original source code into the .ASH file
  113.                 <default is off>
  114.  
  115.  
  116. Processing #DEFINE directives and macros
  117. ----------------------------------------
  118. H2ASH accepts C preprocessor #DEFINE directives and generates a corresponding
  119. EQU directive containing the symbol name and its associated value.
  120. Hexadecimal and octal constants force H2ASH to append an 'h' or 'q' radix
  121. specifier onto the end of the constant value.  Decimal constants are passed
  122. directly to the output stream, while floating point numbers are treated as
  123. text literals. Here's an example of input and output:
  124.  
  125.                ---- H2ASH input ----
  126. #define        ONE         1
  127. #define        NEG_ONE           -1
  128. #define        OCTAL_ONE       01
  129. #define        HEX_ONE         0x1
  130. #define           FLOAT_ONE       1.000
  131.  
  132.                ---- H2ASH output ----
  133. ONE                 EQU     1
  134. NEG_ONE             EQU     <-1>
  135. OCTAL_ONE           EQU     01q
  136. HEX_ONE             EQU     01h
  137. FLOAT_ONE           EQU     <1.000>
  138.  
  139. All other macro #DEFINEs generate text EQUs into the H2ASH output
  140. stream.  However, if the #DEFINE contains any macro arguments, a warning is
  141. issued and the macro in question is not processed.  For example,
  142.  
  143.                ---- H2ASH input ----
  144. #define        PI              22/7
  145. #define        LOOP_FOREVER    while(1) {
  146. #define        seq(s,t)           strcmp(s,t)
  147.  
  148.                ---- H2ASH output ----
  149. PI             EQU             <22/7>
  150. LOOP_FOREVER   EQU           <while(1) {>
  151.  
  152. H2ASH does not directly translate C preprocessor conditional #IF/#ELSE/#ENDIF
  153. directives into their TASM equivalents. Rather, it evaluates the constant-
  154. expression that is the argument to the conditional directive, and then passes
  155. the appropriate clause of the conditional into the output stream, as follows:
  156.  
  157.                ---- H2ASH input ----
  158. #if 0
  159. #define     PI         3.14159
  160. #else
  161. #define     PI         22/7
  162. #endif
  163.  
  164.                ---- H2ASH output ----
  165. ZOO        PI        <22/7>
  166.  
  167.  
  168. Processing Simple Declarations
  169. ------------------------------
  170. H2ASH does not process declarations that have storage class 'auto'; that
  171. is, any C/C++ declarations contained in compound-blocks are ignored. However,
  172. declarations that have static linkage are translated into TASM 'DB', 'DW',
  173. 'DD', .... statements, depending on the size or type of the variable.
  174. Furthermore, declarations that have external linkage are translated
  175. into TASM 'GLOBAL' statements with an appropriate type specifier that is
  176. dependent on the size of the C/C++ variable. H2ASH ignores all initializes
  177. for declarations if the initializer expression is not a constant expression.
  178. If this situation occurs, H2ASH issues a warning message. For example,
  179.  
  180.                ---- H2ASH input ----
  181. char                a_char;
  182. unsigned char            unsigned_char;
  183. signed char            signed_char;
  184. int                a_integer;
  185. unsigned int            unsigned_integer;
  186. signed int            signed_integer;
  187. long                a_long;
  188. unsigned long            unsigned_long;
  189. signed long            signed_long;
  190. float                a_float;
  191. double                a_double;
  192. long double            long_double;
  193.  
  194.                ---- H2ASH output ----
  195. GLOBAL C          a_char              :BYTE
  196. GLOBAL C          unsigned_char       :BYTE
  197. GLOBAL C          signed_char         :BYTE
  198. GLOBAL C          a_integer           :WORD
  199. GLOBAL C          unsigned_integer    :WORD
  200. GLOBAL C          signed_integer      :WORD
  201. GLOBAL C          a_long              :DWORD
  202. GLOBAL C          unsigned_long       :DWORD
  203. GLOBAL C          signed_long         :DWORD
  204. GLOBAL C          a_float             :PWORD
  205. GLOBAL C          a_double            :QWORD
  206. GLOBAL C          long_double         :TBYTE
  207.  
  208. H2ASH ignores the type modifiers 'const' and 'volatile'.  However, the
  209. linkage specifiers 'pascal' and 'cdecl', do generate the corresponding TASM
  210. equivalents. Static variables, as required by the ANSI C standard, generate
  211. a default zero initializer expression of the appropriate width for the data
  212. type in question.
  213.  
  214.                ---- H2ASH input ----
  215. const int const_int;
  216. volatile int volatile_int;
  217. static int static_int;
  218. static double static_double;
  219. extern int extern_int;
  220. int pascal int_pascal;
  221. int cdecl  int_cdecl;
  222.  
  223.                ---- H2ASH output ----
  224. GLOBAL C            const_int           :WORD
  225. GLOBAL C            volatile_int        :WORD
  226. .MODEL SMALL
  227. .DATA
  228. static_int          DW      0
  229. static_double       DQ      0.0
  230. GLOBAL C            extern_int          :WORD
  231. GLOBAL PASCAL       int_pascal          :WORD
  232. GLOBAL C            int_cdecl           :WORD
  233.  
  234.  
  235. Processing Pointer/Array Declarations
  236. -------------------------------------
  237. Pointer declarations are handled in a similar manner to basic variable
  238. declarations, except that the 'PTR' type specifier is introduced for each
  239. level of pointer/reference indirection.  Note that any initializer that
  240. requires the creation of a temporary variable, or is not a constant
  241. expression is ignored.  For example,
  242.  
  243.                ---- H2ASH input ----
  244. char      *v1;
  245. int      **v2;
  246. char far  *v3;
  247. char near *v4;
  248.  
  249.                ---- H2ASH output ----
  250. GLOBAL C            v1                  :NEAR PTR BYTE
  251. GLOBAL C            v2                  :NEAR PTR NEAR PTR WORD
  252. GLOBAL C            v3                  :FAR PTR BYTE
  253. GLOBAL C            v4                  :NEAR PTR BYTE
  254.  
  255. Arrays are treated like basic variable declarations, where the type
  256. specifier consists of the element type of the array, followed by an optional
  257. repetition field that contains the dimension of the array. If the array is an
  258. incomplete declaration, (that is, if it's dimension is not fully specified)
  259. the repetition field is not passed into the output stream.  For example,
  260.  
  261.                ---- H2ASH input ----
  262. extern char a1[];
  263. extern char a2[10];
  264. extern char a3[][10];
  265. extern char a4[10][20];
  266.  
  267.                ---- H2ASH output ----
  268. GLOBAL        C    a1:    BYTE
  269. GLOBAL        C    a2:    BYTE : 10
  270. GLOBAL        C       a3:    BYTE
  271. GLOBAL        C    a4:    BYTE : 200
  272.  
  273.  
  274. Processing TYPEDEF Declarations
  275. -------------------------------
  276. C/C++ TYPEDEF declarations are mapped directly onto their equivalent TASM
  277. counterpart.  When the typedef alias (the name of the typedef) is used as the
  278. type specifier in another declaration, the actual type of the typedef, as op-
  279. posed to the typedef alias itself, is emitted into the output stream. For
  280. example,
  281.  
  282.                ---- H2ASH input ----
  283. typedef     unsigned long     ul;
  284. typedef     ul         alias_ul;
  285. alias_ul             ul_object;
  286.  
  287.                ---- H2ASH output ----
  288. ul        TYPEDEF        DWORD
  289. alias_ul    TYPEDEF        DWORD
  290. GLOBAL    C    ul_object      :DWORD
  291.  
  292.  
  293. Processing ENUM Declarations
  294. ----------------------------
  295. C/C++ enumeration types are converted directly into TASM 'ENUM' defini-
  296. tions. Each enumerator is given an explicit initializer if the value of the
  297. enumerator changes by more than one unit from the previously processed enum-
  298. erator, or if the enumerator already has an explicit initializer in the
  299. C/C++ source code.  As usual, this initializer must contain a constant-
  300. expression.
  301.  
  302. H2ASH automatically synthesizes a tag name if the enumeration does not
  303. contain a tag.  This generated name is always unique within the compilation
  304. unit it occurs in, and can be in subsequent variable declarations. For
  305. example,
  306.  
  307.                ---- H2ASH input ----
  308.  enum FOO    { a, b, c = -1, d = sizeof(enum FOO)};
  309.  enum           { north, east, south, west };
  310.  
  311.                ---- H2ASH output ---- 
  312. FOO                 ENUM    {
  313.                     a,
  314.                     b,
  315.                     c=-1,
  316.                     d=2,
  317.                     pad$0=256}
  318.  
  319. tag$0               ENUM    {
  320.                     north,
  321.                     east,
  322.                     south,
  323.                     west,
  324.                     pad$1=256}
  325.  
  326. Finally, if the enumeration is not representable within a declaration
  327. of size BYTE, H2ASH generates an extra enumerator (which has a unique name),
  328. and appends it to the end of the enumeration list.  This enumerator is used
  329. to induce TASM to pack the enumeration within a data type of size WORD. This
  330. situation can occur whenever you use the -b option, or whenever the value
  331. of an enumerator exceeds a value representable within a BYTE. For example,
  332.  
  333.                ---- H2ASH input ----
  334.  enum direction  { north, east = 254, south, west };
  335.  enum color      { red, green = 256, blue };
  336.  
  337.                ---- H2ASH output ----
  338. direction           ENUM    {
  339.                     north,
  340.                     east=254,
  341.                     south,
  342.                     west,
  343.                     pad$0=256}
  344.  
  345. color               ENUM    {
  346.                     red,
  347.                     green=256,
  348.                     blue}
  349.  
  350.  
  351. Processing Simple Aggregate Declarations
  352. ----------------------------------------
  353. Structures and unions are mapped by H2ASH onto their direct TASM STRUC
  354. and UNION counterparts. If a tag is not present in the aggregate declaration,
  355. H2ASH automatically generates one.  The GLOBAL directive is used to represent
  356. an instance of the structure, where the type-field contains that tag name of
  357. the structure or union in question.  For example,
  358.  
  359.                ---- H2ASH input ----
  360.  struct S1 {
  361.    int field1;
  362.    int field2;
  363.    } S1_object;
  364.  
  365.  union U1 {
  366.    int field1;
  367.    int field2;
  368.    int (*field3)(void);
  369.    } U1_object;
  370.  
  371.                ---- H2ASH output ----
  372. S1                  STRUC
  373. @S1@field1          DW      ?
  374. @S1@field2          DW      ?
  375. S1                  ENDS
  376.  
  377. GLOBAL C            S1_object           :S1
  378.  
  379. U1                  UNION
  380. @U1@field1          DW      ?
  381. @U1@field2          DW      ?
  382. @U1@field3          DW      NEAR PTR ?
  383. U1                  ENDS
  384.  
  385. GLOBAL C            U1_object           :U1
  386.  
  387. Using the word-alignment (-a) option lets H2ASH explicitly output
  388. appropriate padding.  For the exact structure-alignment rules, see the
  389. C++ Programmer's Guide.  For example,
  390.  
  391.                ---- H2ASH input ----
  392. struct S2 {
  393.    char field1;
  394.    int  field2;
  395.    };
  396.  
  397.                ---- H2ASH output ----
  398. S2                  STRUC
  399. @S2@field1          DB      ?
  400.                     DB      0
  401. @S2@field2          DW      ?
  402. S2                  ENDS
  403.  
  404. H2ASH treats nested structures as separate TASM STRUC declarations, and
  405. gives the nested structures specially mangled names. This is done because
  406. nested structures are not true members; they are merely in the lexical scope
  407. of the structure in which they are contained.  However, if a nested structure
  408. is instantiated (for example, an object of the type of that structure is
  409. declared), the appropriate space is reserved in the enclosing structure as
  410. in the following example:
  411.  
  412.                ---- H2ASH input ----
  413. struct a {
  414.     int i;
  415.     struct b {
  416.         int j;
  417.     };
  418.         int k;
  419.         struct c {
  420.                 int l;
  421.     } c_instance;
  422. };
  423.  
  424.                ---- H2ASH output ----
  425. @a@b                STRUC
  426. @a@b@j              DW      ?
  427. @a@b                ENDS
  428.  
  429. @a@c                STRUC
  430. @a@c@l              DW      ?
  431. @a@c                ENDS
  432.  
  433. a                   STRUC
  434. @a@i                DW      ?
  435. @a@k                DW      ?
  436. @a@c_instance       @a@c    <>
  437. a                   ENDS
  438.  
  439.  
  440. Processing Bitfield Declarations
  441. --------------------------------
  442. Bitfields are represented by H2ASH as TASM RECORD declarations. In
  443. general, it generates two kinds of RECORDS. First, if a STRUCT contains
  444. only bitfield declarations and if each of the bitfields are of the same type,
  445. and if this type is sufficiently large to contain all of the fields, H2ASH
  446. generates a global RECORD declaration. H2ASH inserts a uniquely named padding
  447. field at the top of the RECORD so that proper alignment is achieved. For
  448. example,
  449.  
  450.                ---- H2ASH input ----
  451. struct S1 {
  452.    int field1: 1;
  453.    int field2: 4;
  454.    };
  455.  
  456.                ---- H2ASH output ----
  457. S1                  RECORD    {
  458. pad$0               :11
  459. field2              :4
  460. field1              :1
  461. }
  462.  
  463. If H2ASH is unable to generate a global RECORD declaration, a local one
  464. is emitted within the STRUC in which the original bitfield is declared.
  465. Furthermore, a member with the type of the tag of the local RECORD
  466. declaration is declared to reserve the appropriate amount of storage. H2ASH
  467. attempts to pack adjacent bitfields within a single record when adjacent
  468. bitfields are of the same type, and whenever the type of the bitfield is
  469. large enough to contain the adjacent fields. For example,
  470.  
  471.                 ---- H2ASH input ----
  472. struct S1 {
  473.     int  field1;
  474.     char field2: 1;
  475.     char field3: 8; // NOTE: cannot be packed with field2
  476.     };
  477.  
  478.                 ---- H2ASH output ----
  479. S1                  STRUC
  480. @S1@field1          DW      ?
  481. S1                  RECORD    {
  482. pad$0               :7
  483. field2              :1
  484. }            
  485. $bit$0              S1      <>
  486. S1                  RECORD    {
  487. field3              :8
  488. }
  489. $bit$1              S1      <>
  490. S1                  ENDS
  491.  
  492.  
  493. Processing Function/Operator Declarations
  494. -----------------------------------------
  495. File scope function declarations are emitted as GLOBAL declarations with
  496. type NEAR or FAR, depending on the model settings.  Prototypes for func-
  497. tions are ignored, because TASM does not support typed CALLs or typed PROTO
  498. statements. However, the prototype is encrypted by the mangled name of the
  499. function.  For example,
  500.  
  501.                ---- H2ASH input ----
  502.  void   fvv(void);
  503.  extern efvv(void);
  504.  int    fiii(int, int);
  505.  
  506.                ---- H2ASH output ----
  507.  GLOBAL     C     @fvv$qv     :NEAR  ;or far, depending on model
  508.  GLOBAL  C    @efvv$qv    :NEAR  ;or far, depending on model
  509.  GLOBAL  C    @fiii$qii    :NEAR  ;or far, depending on model
  510.  
  511. H2ASH ignores default arguments, as well as all function bodies. In both
  512. cases, H2ASH issues a warning and processes that declaration as if the
  513. default arguments and function bodies were not present.  H2ASH also ignores
  514. static function declarations. In this case, the declaration is not emitted
  515. into the output stream. Here's an example:
  516.  
  517.                ---- H2ASH input ----
  518.  static sfvv(void);
  519.  void   dfii(int i = 0, int = sizeof(foo));
  520.  int    fvv(int i) { return ++i; }
  521.  
  522.                ---- H2ASH output ----
  523. ; warning, declaration of static function 'sfvv(...)' ignored
  524.  
  525.  void   C       @dfii$qii      :NEAR   ; warning, default arguments ignored
  526.  void   C       @fvv$qi        :NEAR   ; warning, function body ignored
  527.  
  528. H2ASH supports function and operator overloading by encoding function
  529. prototypes and operator names. Otherwise, H2ASH treats these declarations
  530. in exactly the same manner as ordinary functions. For example,
  531.  
  532.                ---- H2ASH input ----
  533.  int abs(int,  int);
  534.  int abs(int);
  535.  
  536.  struct alpha;
  537.  
  538.  int operator+(alpha, int);
  539.  int operator+(int, alpha);
  540.  
  541.                ---- H2ASH output ----
  542. GLOBAL C            @abs$qii            :NEAR
  543. GLOBAL C            @abs$qi             :NEAR
  544. GLOBAL C            @$badd$q5alphai     :NEAR
  545. GLOBAL C            @$badd$qi5alpha     :NEAR
  546.  
  547.  
  548. Processing Classes
  549. ------------------
  550. C++ classes are mapped onto TASM STRUC declarations, just as C STRUCTS
  551. are.  Nonstatic class data members are treated as ordinary STRUCT fields.
  552. Static class data members are treated as GLOBAL declarations, and are emitted
  553. after the class declaration in which they are declared. Nonvirtual function
  554. members are treated exactly like ordinary function definitions, except, that
  555. they receive a mangled name that encodes the tagname of class in which they
  556. are contained. Virtual function members are treated exactly like nonvirtual
  557. functions, except that they force H2ASH to allocate space for a virtual-
  558. function-table-pointer.  This pointer has a mangled name containing the
  559. suffix 'vptr$', which is always unique throughout a single compilation unit.
  560. Finally, all 'special' member functions (constructors, copy constructors,
  561. assignment operators), are treated as ordinary function declarations.
  562. However, if they are compiler-synthesized members, H2ASH does not emit them.
  563. For example,
  564.  
  565.                ---- H2ASH input ----
  566.  class c {
  567.  
  568.      static int static_member;
  569.              int normal_member;
  570.  
  571.  public:
  572.  
  573.      virtual void f1_virtual(void);
  574.      virtual void f2_virtual(void);
  575.              void f3_normal(void);
  576.  
  577.      void *operator ++();
  578.  
  579.      c();
  580.      c(int&);
  581.      ~c(); 
  582.  
  583.    };
  584.  
  585.                ---- H2ASH output ----
  586. c                   STRUC
  587. @c@vptr$0           DW      NEAR PTR ?
  588. @c@normal_member    DW      ?
  589. c                   ENDS
  590.  
  591. GLOBAL C            @c@static_member    :WORD
  592. GLOBAL C            @c@f1_virtual$qv    :NEAR
  593. GLOBAL C            @c@f2_virtual$qv    :NEAR
  594. GLOBAL C            @c@f3_normal$qv     :NEAR
  595. GLOBAL C            @c@$binc$qv         :NEAR
  596. GLOBAL C            @c@$bctr$qv         :NEAR
  597. GLOBAL C            @c@$bctr$qri        :NEAR
  598. GLOBAL C            @c@$bdtr$qv         :NEAR
  599.  
  600. H2ASH supports single inheritance. If a program using multiple inheri-
  601. tance is presented as input, or if virtual bases are present, H2ASH
  602. terminates and gives an appropriate error message. Within a derived class, a
  603. base class is represented as a member subobject, and is treated by H2ASH as
  604. if it were an ordinary member with a specially synthesized name: 'subobject$'
  605. which has the type of the base class in question.  Again, this name is always
  606. unique. Virtual function table pointers are shared between the base and
  607. derived class; hence, no further space is allocated for the virtual-pointer
  608. within the derived class.  For example, adding a derived class to the
  609. previous example:
  610.  
  611.                ---- H2ASH input ----
  612. // previous definition for class c goes here.
  613.  
  614.  class d : c {
  615.  
  616.      int derived_member;
  617.  
  618.      virtual void f1_virtual(void); // virtual override of c::f1_virtual()
  619.  
  620.      d();
  621.     ~d();
  622.  
  623.  };
  624.  
  625.                ---- H2ASH output ----
  626. d                   STRUC
  627. subobject$0         c       <>
  628. @d@derived_member   DW      ?
  629. d                   ENDS
  630.  
  631. GLOBAL C            @d@f1_virtual$qv    :NEAR
  632. GLOBAL C            @d@$bctr$qv         :NEAR
  633. GLOBAL C            @d@$bdtr$qv         :NEAR
  634.  
  635. Pointers to class members are also supported, both pointers to data
  636. members and pointers to function members. Here's a simple example:
  637.  
  638.                ---- H2ASH input ----
  639. class f{
  640. public:
  641.    int x;
  642.    int * px;
  643.    int foo( char * ) { return px }
  644. };
  645.  
  646. int  f::*pointer_to_data_member;
  647. int (f::*pointer_to_function)(char *);
  648.  
  649.                ---- H2ASH output ----
  650. f                   STRUC
  651. @f@x                DW      ?
  652. @f@px               DW      NEAR PTR ?
  653. f                   ENDS
  654.  
  655. GLOBAL C            @f@foo$qpzc         :NEAR
  656.  
  657. vb_data$mptr        STRUC
  658. vb_data$member_offset                   DW      0
  659. vb_data$vbcptr_offset                   DW      0
  660. vb_data$mptr        ENDS
  661.  
  662. GLOBAL C            pointer_to_data_member               :vb_data$mptr
  663.  
  664. vb_near_func$mptr   STRUC
  665. vb_near_func$func_addr                  DW      0
  666. vb_near_func$member_offset              DW      0
  667. vb_near_func$vbcptr_offset              DW      0
  668. vb_near_func$mptr   ENDS
  669.  
  670. GLOBAL C            pointer_to_function :vb_near_func$mptr
  671.  
  672. C++ Templates are not supported in this version of H2ASH. If a program
  673. containing templates is given as input, H2ASH outputs an error and terminates
  674. execution.
  675.  
  676. /**************************** END OF FILE ********************************/
  677.  
  678.