Шаг 13.
Оптимизация с помощью ассемблера.
Написание встраиваемого кода BASM. Использование утилиты H2ASH

    На этом шаге мы рассмотрим использование утилиты H2ASH.

    Наиболее трудоемкий процесс в написании внешних ассемблерных модулей - разработка интерфейса с внутренней структурой данных программы. Ассемблер не предназначен для выполнения операций над структурами, массивами, строками C, а также классами C++, однако вы можете воспользоваться несколькими "трюками" для доступа к объектов этих и других типов из операторов ассемблера.

    Утилита H2ASH.EXE, поставляемая вместе с TASM, может помочь вам сократить время поиска ответа на вопрос: "Как мне получить доступ к программным данным с помощью ассемблерных инструкций и директив?" H2ASH преобразует объявления, содержащиеся в заголовочных файлах C и C++ в эквивалентные объявления TASM, хранимые в файлах с расширением .ash (заголовочный файл ассемблера). Вы можете воспользоваться этими объявлениями для доступа к вашим программным данным или же, руководствуясь ими, написать свои собственные директивы.

    Утилита H2ASH поддерживает большинство конструкций C и классов C++. Она обрабатывает файлы #include и может пользоваться преимуществами идеального режима - расширенный MASM - подобный синтаксис TASM. К сожалению, H2ASH не распознает множественного наследования, виртуальных базовых классов и шаблонов. Она также выдает предупреждения для элементов, подобных макросам, которые не транслируются так просто в директивы TASM. Следует рассматривать H2ASH как рекомендацию, а не последнее слово в преобразовании объявлений C и C++ в ассемблерный код. Для 32-битного кода следует пользоваться утилитой H2ASH32.


    Замечание. Прочитайте текстовый файл TSM-UTIL.TXT, содержащийся в каталоге \BC45\DOC, для того, чтобы узнать больше об утилите H2ASH.

    Продемонстрируем работу утилиты H2ASH, обработав с ее помощью несколько образцов заголовочных файлов. Например, найдите заголовочный файл Db.h (листинг 1) Скопируйте этот файл и h2ash.exe в папку \BC45\BIN, и введите команду h2ash db.h для создания нового файла Db.ash с эквивалентными директивами TASM. Поскольку в Db.h включается заголовочный файл STDIO.H, утилита H2ASH преобразует содержащиеся в нем объявлении так же, как в Db.h. (Во время выполнения H2ASH может предупреждать вас время от времени о макросах и других элементах, которые нельзя преобразовать.)

    Листинг 1. db.h (Создание заголовочного файла образца базы данных)

#include <stdio.h>
#include <limits.h>

#define FALSE 0
#define TRUE 1
#define NAMELEN 30
#define ADDRLEN 30
#define CSZLEN 30
#define PHONELEN 13

typedef struct record {
  union {
        long numrecs;
        long custnum;
  } info;
  char name[NAMELEN];
  char addr[ADDRLEN];
  char csz[CSZLEN];
  char phone[PHONELEN];
  double balance;
} Record;

#define MAXREC (LONG_MAX/sizeof(Record))

int CreateBD(const char *path);
FILE *OpenBD(const char *path, Record *header);
int ReadRecord(FILE *f, long recnum, Record *recp);
int WriteRecord(FILE *f, long recnum, Record *recp);
int AppendRecord(FILE *f, long recnum, Record *recp);
void InputLong(const char *label, long *lp);
void InputChar(const char *label, char*cp, int len);
void InputDouble(const char *label, double *db);
Тексты этих объявлений можно взять здесь.

    Несмотря на несовершенство результатов, утилита H2ASH мастерски справляется с преобразованием большинства объявлений. Например, в Db.h определяются следующие константы:

#define FALSE 0
#define TRUE 1
#define NAMELEN 30
#define ADDRLEN 30
#define CSZLEN 30
#define PHONELEN 13

    Утилита H2ASH переводит их в эквивалентные директивы TASM:

FALSE EQU 0
TRUE EQU 1
NAMELEN EQU 30
ADDRLEN EQU 30
CSZLEN EQU 30
PHONELEN EQU 13

    Утилите H2ASH "по зубам" и более заковыристые объявления:

typedef  struct record {
   union {
             long numrecs;
             long custnum;
             } info;
   char name[NAMELEN];
   char addr[ADDRLEN];
   char csz[CSZLEN];
   char phone[PHONELEN];
   double balance;
} Record;

    Эта структура легко преобразуется утилитой H2ASH, которая выдаст следующие эквивалентные директивы TASM:

tag$1UNION
numrecs  DD  ?
custnum  DD  ?
tag$1ENDS

record                              struct
info   tag$1                         <>
name   DB                        30 DUP ( ? )
addr   DB                        30 DUP ( ? )
csz    DB                        30 DUP ( ? )
phone  DB                        30 DUP ( ? )
balance                             DQ    ? 
record  ENDS                 

   В дополнение к преобразованию существующих имен, таких, как numrecs и phone, утилита H2ASH создает все необходимые имена, подобные tag$1. Она также создает объявления, необходимые для вызова функций C или C++, для которых в программе есть прототипы:

GLOBAL C CreateDB       :NEAR
GLOBAL C OpenDB         :NEAR
GLOBAL C ReadRecord   :NEAR
GLOBAL C WriteRecord  :NEAR

    На следующем шаге мы рассмотрим написание внешних модулей TASM.




Предыдущий шаг Содержание Следующий шаг