📄 tsm_util.txt
字号:
/*************************************************************************/
TSM_UTIL.TXT
TURBO ASSEMBLER
This file documents H2ASH and H2ASH32, utilities that can be used with
TASM.
1) Online Documentation for H2ASH and H2ASH32
==============================================
C/C++ modules within a program typically share definitions of types and data
structures among themselves. They do this by including small files called
header files, which contain type definitions and data structure definitions
used by more than one module. A C/C++ header file usually has a name ending
in H. Similarly, assembly modules use header files with names that end in
.ASH (or .INC).
Programs containing modules written in both C or C++ and modules written
using Turbo Assembler must be able to share definitions of types and data
structures. The H2ASH converter utility lets this happen.
The converter has the following limitations:
-- All executable statements are ignored; no code output is generated.
-- #INCLUDEs are fully expanded in the output.
-- Name conflicts can occur in the assembly output since C++ scoping
rules differ greatly from assembly rules; using Ideal mode output
can help.
-- Multiple Inheritance, Virtual Base Classes, and Templates are not
supported in this version of H2ASH.
The H2ASH converter not only smooths the interface between C/C++ and assembly
language, it also lets you write C++ base classes directly in assembly
language (for maximum performance). H2ASH automatically converts base class
declarations in C++ into equivalent assembly object definitions, and defines
method names. We recommend that you use the following procedure for writing
base classes in assembly language:
1) Write the class declaration in a C/C++ header file.
2) Include the C header file in all descendant classes, and in the C/C++
modules that use the base class.
3) Use the H2ASH converter on the header file to produce an assembly
object header file; you can automate this by setting up a makefile.
4) Include the assembly object header file in the module where the
assembly language methods are written.
Command Line Interface for H2ASH
--------------------------------
You can invoke H2ASH by typing the following command on the command line:
H2ASH [[switches] <filename> [<filename> ... ]]
H2ASH triggers the printing of a help screen. By default, H2ASH accepts a
C/C++ header file, and produces a Turbo Assembler (TASM) 3.0 compatible
assembly include file with extension .ASH. The resulting file is
not a self-contained assembly language program; rather, it contains TASM
type declarations and EQU statements that correspond to declarations in
the original C/C++ header file. H2ASH recognizes wild cards for filename
matching.
All H2ASH-specific command line switches are a submode of the -q switch,
that is they all have the following form:
-q[<character>] [-]
H2ASH also recognizes a majority of the Borland C++ command-line switches.
In particular, word-alignment (-a), force C++ compile (-P), set output file
name (-o), define symbol (-D), and the compilation model directives (-mt,
-ms, -ml, ...), are all supported. For a definitive description of the BCC
command-line interface, see the Borland C++ User's Guide.
H2ASH allows the following switches:
-q- turn off the H2ASH converter
<default is on>
-qc pass c/c++ comments into the .ASH file
<default is off>
-qn enable name-mangling
<default is on>
-qf a 'strict' mode that strips out all untranslatable source
code (as opposed to the default behavior of issuing a warning
and partially translating the declaration in question)
<default is off>
-qi generate Ideal mode code, as opposed to Masm mode code
<default is off>
-qd generate EQUs for #DEFINE statements which appear on the
command-line, in project configuration file, or in the
original source program
<default is on>
-qb generate EQUs for #DEFINE statements which are normally
generated automatically by the compiler
<default is off>
-qt generate TASM directives as needed (H2ASH will emit .DATA
and .MODEL directives whenever static declarations appear
in the original C/C++ header file. The IDEAL directive is
generated whenever Ideal mode is used)
<default is on>
-qs pass original source code into the .ASH file
<default is off>
Processing #DEFINE directives and macros
----------------------------------------
H2ASH accepts C preprocessor #DEFINE directives and generates a corresponding
EQU directive containing the symbol name and its associated value.
Hexadecimal and octal constants force H2ASH to append an 'h' or 'q' radix
specifier onto the end of the constant value. Decimal constants are passed
directly to the output stream, while floating point numbers are treated as
text literals. Here's an example of input and output:
---- H2ASH input ----
#define ONE 1
#define NEG_ONE -1
#define OCTAL_ONE 01
#define HEX_ONE 0x1
#define FLOAT_ONE 1.000
---- H2ASH output ----
ONE EQU 1
NEG_ONE EQU <-1>
OCTAL_ONE EQU 01q
HEX_ONE EQU 01h
FLOAT_ONE EQU <1.000>
All other macro #DEFINEs generate text EQUs into the H2ASH output
stream. However, if the #DEFINE contains any macro arguments, a warning is
issued and the macro in question is not processed. For example,
---- H2ASH input ----
#define PI 22/7
#define LOOP_FOREVER while(1) {
#define seq(s,t) strcmp(s,t)
---- H2ASH output ----
PI EQU <22/7>
LOOP_FOREVER EQU <while(1) {>
H2ASH does not directly translate C preprocessor conditional #IF/#ELSE/#ENDIF
directives into their TASM equivalents. Rather, it evaluates the constant-
expression that is the argument to the conditional directive, and then passes
the appropriate clause of the conditional into the output stream, as follows:
---- H2ASH input ----
#if 0
#define PI 3.14159
#else
#define PI 22/7
#endif
---- H2ASH output ----
ZOO PI <22/7>
Processing Simple Declarations
------------------------------
H2ASH does not process declarations that have storage class 'auto'; that
is, any C/C++ declarations contained in compound-blocks are ignored. However,
declarations that have static linkage are translated into TASM 'DB', 'DW',
'DD', .... statements, depending on the size or type of the variable.
Furthermore, declarations that have external linkage are translated
into TASM 'GLOBAL' statements with an appropriate type specifier that is
dependent on the size of the C/C++ variable. H2ASH ignores all initializes
for declarations if the initializer expression is not a constant expression.
If this situation occurs, H2ASH issues a warning message. For example,
---- H2ASH input ----
char a_char;
unsigned char unsigned_char;
signed char signed_char;
int a_integer;
unsigned int unsigned_integer;
signed int signed_integer;
long a_long;
unsigned long unsigned_long;
signed long signed_long;
float a_float;
double a_double;
long double long_double;
---- H2ASH output ----
GLOBAL C a_char :BYTE
GLOBAL C unsigned_char :BYTE
GLOBAL C signed_char :BYTE
GLOBAL C a_integer :WORD
GLOBAL C unsigned_integer :WORD
GLOBAL C signed_integer :WORD
GLOBAL C a_long :DWORD
GLOBAL C unsigned_long :DWORD
GLOBAL C signed_long :DWORD
GLOBAL C a_float :PWORD
GLOBAL C a_double :QWORD
GLOBAL C long_double :TBYTE
H2ASH ignores the type modifiers 'const' and 'volatile'. However, the
linkage specifiers 'pascal' and 'cdecl', do generate the corresponding TASM
equivalents. Static variables, as required by the ANSI C standard, generate
a default zero initializer expression of the appropriate width for the data
type in question.
---- H2ASH input ----
const int const_int;
volatile int volatile_int;
static int static_int;
static double static_double;
extern int extern_int;
int pascal int_pascal;
int cdecl int_cdecl;
---- H2ASH output ----
GLOBAL C const_int :WORD
GLOBAL C volatile_int :WORD
.MODEL SMALL
.DATA
static_int DW 0
static_double DQ 0.0
GLOBAL C extern_int :WORD
GLOBAL PASCAL int_pascal :WORD
GLOBAL C int_cdecl :WORD
Processing Pointer/Array Declarations
-------------------------------------
Pointer declarations are handled in a similar manner to basic variable
declarations, except that the 'PTR' type specifier is introduced for each
level of pointer/reference indirection. Note that any initializer that
requires the creation of a temporary variable, or is not a constant
expression is ignored. For example,
---- H2ASH input ----
char *v1;
int **v2;
char far *v3;
char near *v4;
---- H2ASH output ----
GLOBAL C v1 :NEAR PTR BYTE
GLOBAL C v2 :NEAR PTR NEAR PTR WORD
GLOBAL C v3 :FAR PTR BYTE
GLOBAL C v4 :NEAR PTR BYTE
Arrays are treated like basic variable declarations, where the type
specifier consists of the element type of the array, followed by an optional
repetition field that contains the dimension of the array. If the array is an
incomplete declaration, (that is, if it's dimension is not fully specified)
the repetition field is not passed into the output stream. For example,
---- H2ASH input ----
extern char a1[];
extern char a2[10];
extern char a3[][10];
extern char a4[10][20];
---- H2ASH output ----
GLOBAL C a1: BYTE
GLOBAL C a2: BYTE : 10
GLOBAL C a3: BYTE
GLOBAL C a4: BYTE : 200
Processing TYPEDEF Declarations
-------------------------------
C/C++ TYPEDEF declarations are mapped directly onto their equivalent TASM
counterpart. When the typedef alias (the name of the typedef) is used as the
type specifier in another declaration, the actual type of the typedef, as op-
posed to the typedef alias itself, is emitted into the output stream. For
example,
---- H2ASH input ----
typedef unsigned long ul;
typedef ul alias_ul;
alias_ul ul_object;
---- H2ASH output ----
ul TYPEDEF DWORD
alias_ul TYPEDEF DWORD
GLOBAL C ul_object :DWORD
Processing ENUM Declarations
----------------------------
C/C++ enumeration types are converted directly into TASM 'ENUM' defini-
tions. Each enumerator is given an explicit initializer if the value of the
enumerator changes by more than one unit from the previously processed enum-
erator, or if the enumerator already has an explicit initializer in the
C/C++ source code. As usual, this initializer must contain a constant-
expression.
H2ASH automatically synthesizes a tag name if the enumeration does not
contain a tag. This generated name is always unique within the compilation
unit it occurs in, and can be in subsequent variable declarations. For
example,
---- H2ASH input ----
enum FOO { a, b, c = -1, d = sizeof(enum FOO)};
enum { north, east, south, west };
---- H2ASH output ----
FOO ENUM {
a,
b,
c=-1,
d=2,
pad$0=256}
tag$0 ENUM {
north,
east,
south,
west,
pad$1=256}
Finally, if the enumeration is not representable within a declaration
of size BYTE, H2ASH generates an extra enumerator (which has a unique name),
and appends it to the end of the enumeration list. This enumerator is used
to induce TASM to pack the enumeration within a data type of size WORD. This
situation can occur whenever you use the -b option, or whenever the value
of an enumerator exceeds a value representable within a BYTE. For example,
---- H2ASH input ----
enum direction { north, east = 254, south, west };
enum color { red, green = 256, blue };
---- H2ASH output ----
direction ENUM {
north,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -