diff --git a/programs/cmm/c--/c--.ini b/programs/cmm/c--/c--.ini new file mode 100644 index 0000000000..f7dcbd6631 --- /dev/null +++ b/programs/cmm/c--/c--.ini @@ -0,0 +1,27 @@ +; В этом файле можно изменить настройки компилятора по умолчанию. + +J0 ; не делать начальный jump на main() + +8 ; оптимизация для Pentium II процессора. + +r- ; запретить изменение доступной памяти в *.com файлах + +X ; запретить включение в выходной файл надписи SPHINXC-- + +oc ; опримизация по размеру кода + +w ; выдавать предупреждения + +wf=warning.txt ; предупреждения выводить в файл warning + +nw=1 ; не показывать кое-какие ошибки в warning.txt + +nw=2 ; не показывать кое-какие ошибки в warning.txt + +;de ; использовать временное расширение типа при делении + +;ON ; включить оптимизацию чисел + +;ost ; оптимизировать текстовые константы + +IP=D:\Kolibri\SVN\programs\cmm\lib \ No newline at end of file diff --git a/programs/cmm/c--/cmm.exe b/programs/cmm/c--/cmm.exe new file mode 100644 index 0000000000..893be9e2f7 Binary files /dev/null and b/programs/cmm/c--/cmm.exe differ diff --git a/programs/cmm/c--/cmm.kex b/programs/cmm/c--/cmm.kex new file mode 100644 index 0000000000..afff638ea8 Binary files /dev/null and b/programs/cmm/c--/cmm.kex differ diff --git a/programs/cmm/c--/manual_c--.htm b/programs/cmm/c--/manual_c--.htm new file mode 100644 index 0000000000..0bf1367f7a --- /dev/null +++ b/programs/cmm/c--/manual_c--.htm @@ -0,0 +1,5697 @@ + +Документация на C-- + + + + + + + +
+
+
+ + + + + + + + + +
+ + Документация на C--. +
+ + + +

+Содержание. +

+
+
+
+1      Введение.
+1.1    История создания и развития.
+1.2    Что такое C--?
+1.3    Как установить C--.
+
+2.     Управление компиляцией.
+2.1    Параметры командной строки компилятора C--.
+2.1.1  /ON - Оптимизация числовых выражений.
+2.1.2  /DE - Временное расширение разрядности переменной.
+2.1.3  /ARGC - Альтернативный обработчик командной строки.
+2.1.4  /OST - слияние одинаковых строковых констант.
+2.1.5  /D - установка идентификатора в TRUE из командной строки.
+2.1.6  /IA - упрощенный ввод ассемблерных инструкций.
+2.1.7  /CRI - пропуск повторно включаемого файла.
+2.1.8  /IND - импорт имен процедур из DLL.
+2.1.9  /WS - задать имя stub файла для программ под windows.
+2.1.10 /WBSS - разместить не инициализированные данные в отдельной секции.
+2.1.11 /DBG - создание отладочной информации.
+2.1.12 /J0 /J1 /J2.
+2.1.13 /LST - Создание ассемблерного листинга.
+2.1.14 /ENV - Сохранение адреса переменных окружения.
+2.1.15 /CPA - Очистка post-области данных.
+2.1.16 /W - вывод предупреждений.
+2.1.17 /NW - Выборочное отключение типов предупреждений.
+2.1.18 /WSI - короткая таблица импорта.
+2.2    Директивы транслятора.
+2.2.1  ?ifdef/?ifndef
+2.2.2  ?initallvar
+2.2.3  ?usestartup
+2.2.4  ?startusevar
+2.2.5  ?atexit
+2.2.6  ?startuptomain
+2.2.7  ?undef
+2.2.8  ?align и ?aligncode
+2.2.9  ?pragma
+
+3.     Константы.
+3.1    Числовые константы.
+3.2    Символьные константы.
+3.3    Строковые константы.
+3.4    Постоянные выражения.
+
+4.     Выражения.
+4.1    Типы выражений.
+4.2    Выражения типа EAX/AX/AL.
+4.3    Выражения использующие получатель при вычислении выражения.
+4.4    Не - EAX/AX/AL выражения.
+4.5    Условные выражения.
+4.5.1  Простые условные выражения.
+4.5.2  Сложные условные выражения.
+4.6    Изменение типа выражения при присваивании.
+4.7    Вычисление в регистры EAX/AX/AL со знаком.
+
+5.     Идентификаторы.
+5.1    Формат идентификатора.
+5.2    Зарезервированные идентификаторы.
+5.3    Универсальные регистры для 16 и 32-битного режима.
+5.4    Предопределенные идентификаторы.
+
+6.     Переменные.
+6.1    Типы переменных.
+6.2    Объявление переменных.
+6.3    Глобальные переменные.
+6.4    Локальные переменные.
+6.5    Динамические переменные и структуры.
+6.6    Присваивание одного значения нескольким переменным.
+6.7    Переменные типа float.
+6.7.1  Формат переменных типа float.
+6.7.2  Константы с плавающей точкой.
+6.7.3  Диапазон допустимых значений.
+6.7.4  Математические операции.
+6.7.5  Преобразования типов.
+6.7.6  Операции сравнения.
+6.7.7  Сравнение переменных типа float с 32-битным регистром.
+6.8    Указатели.
+
+7.     Адресация.
+7.1    Относительная адресация.
+7.2    Абсолютная адресация.
+
+8.     Работа с блоками данных.
+8.1    Структуры.
+8.1.1  Что такое структуры.
+8.1.2  Синтаксис.
+8.1.3  Инициализация структур при объявлении.
+8.1.4  Инициализация структуры при выполнении программы.
+8.1.5  Операции с элементами структур.
+8.1.6  Вложенные структуры.
+8.1.7  Отображение тега структуры на блок памяти.
+8.1.8  Битовые поля структур.
+8.2    Объединения.
+8.3    Команды FROM и EXTRACT.
+
+9.     Операторы.
+9.1    Условные инструкции.
+9.2    Циклы do{} while.
+9.3    Циклы loop, LOOPNZ, loopnz.
+9.4    Цикл while, WHILE.
+9.5    Цикл for, FOR.
+9.6    Оператор переключатель switch.
+9.7    Оператор перехода goto, GOTO.
+9.8    Оператор разрыва break, BREAK.
+9.9    Оператор продолжения continue, CONTINUE.
+9.10   Логическое объединение условий.
+9.11   Переход через циклы.
+9.12   Инвертирование флага проверки условий.
+9.13   Вычисление выражения, а затем проверка условия.
+9.14   Проверка битов при операции сравнения.
+9.15   Оператор перестановки.
+9.16   Оператор отрицания.
+9.17   Оператор инверсии.
+9.18   Специальные условные выражения.
+9.19   Символ $ - вставляет текущий адрес программы.
+9.20   Ключевое слово static и оператор ::.
+9.21   Оператор sizeof.
+9.22   Метки перехода.
+
+10.    Ассемблер.
+10.1   Поддержка команд ассемблера.
+10.2   Ключевое слово asm.
+10.3   Префикс dup - повторение инструкций DB/DW/DD.
+10.4   Инструкции процессора Pentium III.
+
+11.    Процедуры.
+11.1   Типы процедур, функций и макрокоманд.
+11.2   Стековые процедуры.
+11.3   Регистровые процедуры.
+11.4   Динамические процедуры.
+11.4.1 Установка динамической процедуры в определенное место программы.
+11.5   inline-процедуры.
+11.5.1 Другое применение inline.
+11.6   Процедуры обработки прерываний.
+11.7   Замена return на goto.
+11.8   Возвращаемые значения.
+11.9   Объявление параметров в регистровых процедурах.
+11.10  Объявление параметров в стековых процедурах.
+11.11  Использование макрокоманд.
+11.12  Передача параметров в стековые процедуры через регистры.
+11.13  Вызов процедур с адресом в регистре.
+11.14  Встоенные в компилятор процедуры.
+11.14.1 Процедуры ABORT, ATEXIT и EXIT.
+11.14.2 Процедуры inp/inportb, inport, inportd, outp/outportb, outport и
+        outportd.
+11.14.3 Процедуры для работы с вещественными числами.
+11.15  Классы.
+11.15.1 Объявление процедур в структурах.
+11.15.2 Наследование.
+11.15.3 Наследование процедур.
+
+12.    Типы выходных файлов.
+12.1   Выходные файлы типа COM.
+12.2   Выходные файлы типа EXE.
+12.3   Выходной файл *.EXE с моделью памяти tiny.
+12.4   Объектный выходной файл OBJ.
+12.5   COM файл symbiosis.
+12.5.1 СИМБИОЗ - что это такое?
+12.5.2 Как это делать.
+12.5.3 Использование.
+12.5.4 Злоупотребления.
+12.6   SYS - драйверы устройств.
+12.7   Компиляция кода расширителей ROM-BIOS.
+12.8   32-битные файлы.
+12.8.1 32-битный код под DOS.
+12.8.2 32-битный код под Windows.
+12.8.3 Вызов API процедур по ординалам.
+12.8.4 Создание DLL под Windows.
+12.8.5 Инициализация DLL при загрузке.
+12.8.6 Компиляция ресурсов.
+12.9   Выходные файлы для MeOS.
+
+13.    Приложения.
+13.1   Поиск включаемых файлов.
+13.2   Регистры, которые должны быть сохранены.
+13.3   C--.ini файл.
+13.4   startup.h-- файл.
+13.5   mainlib.ldp файл.
+13.6   C-- символы.
+
+
+
+1. Вступление.
+
+  1.1 История создания и развития.
+
+
+      Автором языка SPHINX C-- является Peter Cellik (CANADA). Последняя
+  авторская версия SPHINX C-- v0.203 от 28.Oct.96. К сожалению автор
+  отказался от дальнейшего развития языка. С 1998 года, уже почти умерший
+  проект, подхватил Михаил Шекер (Россия). Изначально компилятор был freeware
+  (и даже greenware, как его называл Peter Cellik). Таким статус компилятора
+  остался и поныне.
+
+      Первоначально компилятор мог создавать только *.com файлы и был
+  рассчитан на создание небольших demo-программ и резидентов (TSR). В
+  дальнейшем возможности компилятора расширялись, так как этого требовало
+  наше бурное время.
+
+      При развитии компилятора, было стремление придерживаться следующих
+  принципов:
+
+      1. Максимально возможная совместимость синтаксиса с последней версией
+  компилятора написанного Peter Cellik. Это давало возможность с минимальными
+  затратами (а чаще всего без всяких затрат) адаптировать программы,
+  написанные для 0.203 версии компилятора, к последней на этот момент версии
+  компилятора.
+
+      2. Сблизить синтаксис компилятора со стандартным языком C. Это могло
+  значительно облегчить перенос программ написанных на C.
+
+      3. Также прилагались усилия, для того, чтобы человек знающий только
+  ассемблер мог бы с минимальными затратами освоить C--.
+
+      Вот эти, зачастую противоречащие друг другу принципы, влияли на выбор
+  реализации возможностей компилятора. Насколько это удалось - судить Вам.
+
+      Если у Вас есть предложения и идеи по улучшению компилятора - пишите.
+  Мой e-mail sheker@mail.ru . Я с удовольствием выслушаю Ваши предложения, но
+  не гарантирую, что все они будут реализованы. Если реализовывать все
+  поступающие предложения, то компилятор превратится в свалку. Но если Ваше
+  предложение будет ценным (на мой взгляд, так что Вам придется свое
+  предложение хорошо аргументировать) и его будет возможным реализовать, оно
+  без сомнения найдет место в компиляторе.
+Return to contents.
+
+
+
+  1.2 Что такое C--?
+
+
+      C-- был разработан, для того чтобы строить маленькие и быстрые
+  программы. Это наиболее подходит для создания резидентных программ (TSR),
+  программ, требующих обработку прерываний или программ у которых ограничены
+  ресурсы.
+
+      C-- занимает промежуточное положение между си и ассемблером. В связи с
+  этим промежуточным положением, Вам, для того чтобы писать программы на C--,
+  необходимо знать и ассемблер и си. Если Вам надоело возиться с огромными
+  ассемблерными листингами, а излишняя строгость языка C Вас угнетает, то этот
+  язык для ВАС.
+
+      Сейчас компилятор C-- может создавать 32-битные программы под Windows
+  (EXE-файлы формата PE) и 32-битные программы под DOS (LE-формат). Имеет
+  встроенный компилятор ресурсов и дизассемблер для генерации листинга
+  откомпилированного файла. Поддерживает ассемблерные инструкции процессора
+  Pentium III и ассемблерные инструкции FPU. Компилятор может генерировать
+  отладочную информацию совместимую с отладчиками фирмы Borland. Компилятор
+  может создавать объектные файлы (obj), но только для DOS программ.
+
+      C-- разработан только для использования на компьютерах с процессорами
+  совместимыми с семейством 80x86. Компилятор может работать только с
+  операционными системами DOS и семейством Windows.
+Return to contents.
+
+
+
+  1.3 Как установить C--.
+
+
+      Компилятору C-- для работы нужны совсем незначительные ресурсы:
+  процессор 386 или лучше, чуть более 1 Мб дискового пространства и 4Мб
+  оперативной памяти. Компилятор может быть установлен на компьютеры с
+  операционной системой Windows 95 или лучше. Компилятор также может работать
+  в среде чистого DOS. В основном пакете компилятора находится 32-битная DOS
+  версия компилятора. На сайте http://sheker.chat.ru или
+  http://c--sphinx.narod.ru можно найти и консольную версию компилятора.
+  Консольная версия компилятора может работать только в среде Windows, но
+  она, в отличие от DOS версии, может работать с длинными именами исходных
+  файлов.
+
+      Установить компилятор C-- на Ваш компьютер очень просто. Предположим,
+  что Вы решили установить C-- на диск C. Создайте на диске C директорию
+  (папку) с именем C-- или с другим, удобным и понятным для Вас именем
+  (например, ДОСовской командой: MD C-- или другим доступным Вам способом).
+  Затем с сайта http://sheker.chat.ru или http://c--sphinx.narod.ru скачайте
+  файлы full_c--.zip и ful_c--2.zip и разархивируйте их в этой директории.
+  Затем в файле autoexec.bat можно прописать путь к директории с
+  компилятором. И все. Компилятор готов к работе. Если Вы добавляли путь к
+  компилятору в файл autoexec.bat, то Вам придется перегрузить операционную
+  систему.
+
+      Переменная окружения для компилятора C-- задается либо из командной
+  строки либо из командного файла (лучше всего ее прописать в autoexec.bat).
+  Эта переменная должна указывать компилятору, где находятся его библиотечные
+  файлы. Пример:
+
+    set C--=c:\c--\lib
+
+  Большой необходимости в переменной окружения для сегодняшней версии
+  компилятора нет. Существует несколько других способов, указать компилятору
+  место расположения библиотек. Поэтому определять или не определять
+  переменную окружения дело вашего вкуса и привычек.
+Return to contents.
+
+
+
+2. Управление компиляцией.
+
+  2.1 Параметры командной строки компилятора C--.
+
+
+      Формат командной строки вызова компилятора C--:
+
+  C-- [Параметры] [ИМЯ INI ФАЙЛА] [ИМЯ ИСХОДНОГО ФАЙЛА]
+
+      Имя исходного файла можно задавать без расширения. Компилятор ищет
+  файл с расширением c--, cmm, c.
+
+      Параметры выделяются предшествующим символом / или -.
+  Инвертировать функцию опции можно завершающим символом -.
+
+  Список поддерживаемых параметров:
+
+  /0          использовать только команды 8086/8088 процессора (установлено
+              по умолчанию при компиляции 16-битных программ).
+  /1          использовать команды 80186 процессора.
+  /2          использовать команды и оптимизацию для 80286 процессора.
+  /3          использовать команды и оптимизацию для 80386 процессора.
+              (установлено по умолчанию для 32-битных программ).
+  /4          использовать команды и оптимизацию для 80486 процессора.
+  /5          использовать команды и оптимизацию для Pentium процессора.
+  /6          использовать команды и оптимизацию для Pentium MMX процессора.
+  /7          использовать команды и оптимизацию для Pentium Pro процессора.
+  /8          использовать команды и оптимизацию для Pentium II процессора.
+  /9          использовать команды и оптимизацию для Pentium III процессора
+              (пока не реализовано из-за отсутствии информации).
+  /A          выравнивание данных на четный адрес
+              по умолчанию разрешено, поддерживает инверсию
+  /AC         выравнивание адреса начала циклов
+              по умолчанию отключено, поддерживает инверсию
+              имеет смысл только на процессорах Pentium+
+  /AL=##      установить значение байта заполнения при выравнивании данных
+              по умолчанию 0.
+  /AP         выравнивание адреса начала процедур.
+              по умолчанию отключено, поддерживает инверсию
+              имеет смысл только на процессорах Pentium и лучше
+  /ARGC       вставить блок разбора командной строки
+              по умолчанию отключено, поддерживает инверсию
+  /AS         выравнивание в структурах.
+              по умолчанию отключено, поддерживает инверсию
+  /AT         вставить блок поддержки ATEXIT процедуры
+              по умолчанию отключено, поддерживает инверсию
+  /C          вставить блок игнорирования CTRL-C
+              по умолчанию отключен, поддерживает инверсию
+              имеет смысл только под DOS программы
+  /CRI        проверять включаемые файлы на повторную загрузку
+              по умолчанию включено, поддерживает инверсию
+  /CPA        очистка post-области данных
+  /D32        создать EXE файл (32 битный код под DOS)
+              по умолчанию COM
+  /D=idname   определить идентификатор для условной компиляции
+              по умолчанию нет
+  /DBG        генерировать отладочную информацию
+              по умолчанию нет
+  /DE         временное расширение разрядности после умножения
+              по умолчанию отключено, поддерживает инверсию
+  /DLL        создать DLL для Windows32
+              по умолчанию COM
+  /ENV        сохранение адреса переменных окружения
+  /EXE        создать EXE файл для DOS (модель SMALL)
+              по умолчанию COM
+  /HELP /H /? справка, эта информация
+  /IA         имена ассемблерных инструкций являются идентификаторами
+              по умолчанию отключено, поддерживает инверсию
+  /IND=name   импорт имен из файла name.
+  /IP=path    задать путь поиска включаемых файлов
+              по умолчанию нет
+  /IV         инициализировать все переменные
+              по умолчанию отключено, поддерживает инверсию
+  /J0         не делать начальный jump на main()
+              по умолчанию отключено, поддерживает инверсию
+              В COM-файлах не создает jmp на main. В остальных не создается
+              блок начальной инициализации программы, а управление
+              передается сразу на main.
+  /J1         делать короткий jump на main()
+              по умолчанию нет
+              имеет смысл только в COM-файлах
+  /J2         делать jump на main()
+              по умолчанию да, поддерживает инверсию
+              имеет смысл только в COM-файлах
+  /LAI        список поддерживаемых ассемблерных инструкций
+  /LRS        загружать числовые константы через стек.
+              по умолчанию да, поддерживает инверсию
+  /LST        создать ассемблерный листинг
+  /ME         показать мой адрес и имя
+  /MEOS       создать исполняемый файл для MeOS
+              по умолчанию COM
+  /MER=##     установить максимальное число ошибок
+              по умолчанию 16
+  /MIF=file   определить имя главного компилируемого файла
+  /NS         запретить подключать stub файлов
+              по умолчанию нет, поддерживает инверсию
+  /NW=##      выборочное отключение предупреждений
+  /OBJ        создать OBJ файл
+              только 16 битный код.
+              по умолчанию COM
+  /OC         оптимизировать по размеру кода
+              по умолчанию нет, поддерживает инверсию
+  /ON         оптимизация чисел
+              по умолчанию нет, поддерживает инверсию
+  /OS         оптимизация по скорости выполнения
+              по умолчанию да, поддерживает инверсию
+  /OST        оптимизация строковых идентификаторов
+              по умолчанию отключено, поддерживает инверсию
+  /P          вставить блок разборки командной строки
+              по умолчанию нет, поддерживает инверсию
+  /R          вставить блок уменьшающий размер доступной памяти.
+              по умолчанию да, поддерживает инверсию
+              имеет смысл только в DOS-файлах
+  /S=#####    установить размер стека
+              по умолчанию 2048
+  /SA=####    начальное смещение адреса запуска программы
+              имеет смысл только в COM-файлах, по умолчанию 0x100
+  /SOBJ       создать ведомый OBJ файл
+              по умолчанию COM
+  /STM        перенести блок startup кода в процедуру main
+              по умолчанию нет, поддерживает инверсию
+              имеет смысл только в COM-файлах
+  /SUV=####   начальный адрес не инициализированных переменных, при
+              использовании ими startup кода.
+              имеет смысл только в COM-файлах, по умолчанию равен /SA
+  /SYM        надстройка для COM файла
+              по умолчанию COM
+  /SYS        создать драйвер устройств (SYS)
+              по умолчанию COM
+  /TEXE       создать EXE файл для DOS (модель TINY)
+              по умолчанию COM
+  /UL         использовать lea при оптимизации сложения регистров.
+              по умолчанию да, поддерживает инверсию
+  /UST        использовать startup код для переменных.
+              имеет смысл только в COM-файлах
+              по умолчанию нет, поддерживает инверсию
+  /W          разрешить предупреждения
+              по умолчанию нет, поддерживает инверсию
+  /W32        создать EXE файл для Windows32 GUI
+              по умолчанию COM
+  /W32C       создать EXE файл для Windows32 console
+              по умолчанию COM
+  /WBSS       помещать не инициализированные данные в отдельную секцию.
+              по умолчанию для /w32 разрешено, для остальных запрещено.
+              поддерживает инверсию
+  /WF=file    перенаправить вывод предупреждений в файл.
+              по умолчанию нет
+  /WFA        использовать быстрые вызовы API процедур
+              по умолчанию да, поддерживает инверсию
+              только под windows
+  /WFU        создавать таблицу перемещений (для Windows32)
+              по умолчанию нет, поддерживает инверсию
+              только под windows
+              для DLL устанавливается в да
+  /WIB=#####  установить адрес image base
+              по умолчанию 0x400000
+  /WMB        создавать Windows-файл с единым блоком
+              по умолчанию да, поддерживает инверсию
+              только под windows
+              для DLL устанавливается в нет
+  /WORDS      выдать список зарезервированных идентификаторов
+  /WS=name    указывает имя файла используемого в качестве stub под windows.
+  /X          запретить вставлять в код SPHINXC-- сигнатуру
+              по умолчанию разрешено, поддерживает инверсию
+              отключается если есть J0
+
+      Примечание: выражение поддерживает инверсию означает, что для данной
+  опции можно использовать и противоположное значение с помощью символа -
+  после опции. Пример:
+
+  /WFA-
+
+       Параметры командной строки можно писать как большими, так и
+  маленькими буквами.
+Return to contents.
+
+
+
+    2.1.1 /ON - Оптимизация числовых выражений.
+
+
+        При включении в командную строку опции /ON или в файл C--.INI строчки
+    ON, компилятор будет анализировать операции над числами и где это
+    можно, сокращать число операций. Например:
+
+     Строка до оптимизации  | После оптимизации
+    -----------------------------------------------
+      AX = var + 7 - 3;     | AX = var + 4;
+      AX = var * 2 * 5;     | AX = var * 10;
+      AX = var * 2 / 4;     | AX = var / 2;
+      AX = var * 10 / 2;    | AX = var * 5;
+      AX = var / 2 / 3;     | AX = var / 6;
+      AX = var / 4 * 8;     | AX = var * 2;
+      AX = var / 16 * 16;   | AX = var;
+
+        Возможные отрицательные последствия:
+        Применение этой оптимизации может иметь и негативные последствия.
+    Например, если Вам нужно выровнять значение переменной на границу
+    параграфа, Вы напишите строку:
+
+    var = var / 16 * 16;
+
+    но после оптимизации будет
+
+    var = var;
+
+    т.е. выравнивание не будет  произведено. Этого можно избежать, если
+    разбить это выражение на два:
+
+    var = var / 16;
+    var = var * 16;
+
+    тогда оптимизация не будет произведена. Но для получения более
+    компактного кода лучше будет записать так:
+
+    AX = var;
+    AX = AX / 16;
+    AX = AX * 16;
+    var = AX;
+Return to contents.
+
+
+
+    2.1.2 /DE - Временное расширение разрядности переменной.
+
+
+        Как известно, после умножения может произойти переполнение, т.е
+    разрядность результата может превысить разрядность исходных операндов и
+    произойдет искажение результата. Частично решить эту проблему Вам поможет
+    опция командной строки /DE или строка DE в файле C--.INI. После команды
+    умножения компилятор будет просматривать остаток строки и если обнаружит,
+    что расширение разрядности может быть востребовано (востребовать
+    расширенную разрядность могут операции деления и вычисления остатка), то
+    будут приняты меры по ее сохранению. Например:
+
+      a = b*c+d/e; //здесь будет включена поддержка расширения разрядности
+      a = b*c+d*e; //здесь поддержки расширения разрядности не будет.
+
+        Однако применение этой опции может иметь и негативные последствия.
+    Покажу это на примере:
+
+    пусть имеется выражение
+
+      a = b * c / d;
+
+    если значения переменных b = 0xC000, c = 0x1000, d=0x10, после запуска
+    такая программа зависнет с сообщением о том, что произошло переполнение
+    при делении.
+Return to contents.
+
+
+
+    2.1.3 /ARGC - Альтернативный обработчик командной строки.
+
+
+        Отличие этого обработчика командной строки от parsecommandline
+    заключается в том, что при вызове PARAMSTR(0); Вы получите адрес строки в
+    которой указан путь и имя запущенной программы. Следующие вызовы этой
+    процедуры с увеличивающимся параметром будут возвращать адреса слов
+    командной строки. А вызов процедуры PARAMCOUNT вернет Вам число слов в
+    командной строке плюс один.
+
+        Альтернативный обработчик командной строки включается директивой
+    ?argc TRUE или из командной строки компилятора ключом /argc или
+    строчкой argc в файле C--.INI.
+Return to contents.
+
+
+
+    2.1.4 /OST - слияние одинаковых строковых констант.
+
+
+        Если этот режим оптимизации будет активизирован, то компилятор будет
+    запоминать все строковые константы и при обнаружении одинаковых в код
+    файла не будет вставлена повторная строковая константа, а будет сделана
+    ссылка на первую, обнаруженную ранее строковую константу. В оптимизации
+    участвуют только неименованные строковые константы. Т.е. если массив или
+    структура будет инициализированы строкой, то такая строка не будет
+    участвовать в процессе инициализации, так эта строка может быть изменена
+    в процессе работы программы. Пример:
+
+      char var="test";  //эта строка не будет участвовать в процессе
+                        //оптимизации.
+
+      void proc(){
+        WRITESTR("test");	// эта строка будет участвовать в оптимизации.
+        AX="test";          // переменной AX будет присвоен адрес строки,
+                            // которая была вставлена в код программы в
+                            // предыдущей строке.
+      }
+
+        Обо всех случаях обнаружения повторной строки компилятор будет
+    выдавать предупреждения.
+
+        Включается этот режим оптимизации либо с командной строки /ost, либо
+    директивой #pragma option ost, либо строкой в файле c--.ini - ost.
+    Отключить, включенный ранее, этот режим можно директивой #pragma option ost-.
+Return to contents.
+
+
+
+    2.1.5 /D - установка идентификатора в TRUE из командной строки.
+
+
+        Если Вы написали программу, которая может компилироваться по разному,
+    в зависимости от состояния некоторых идентификаторов (используется режим
+    условной компиляции), то Вам очень может пригодится эта опция.
+    Устанавливая с командной строки различные идентификаторы, Вы можете
+    получать различные варианты программы, не редактируя исходный текст
+    программы.
+
+        Идентификатор вводится с командной строки ключом /d=idname.
+Return to contents.
+
+
+
+    2.1.6 /IA - упрощенный ввод ассемблерных инструкций.
+
+
+        Стало возможным использовать ассемблерные инструкции без префикса $
+    и вне блока asm. Этот режим включается: с командной строки опцией /ia;
+    в файле конфигурации строкой ia или директивой #pragma option ia.
+
+        Когда этот режим включен, все имена ассемблерных инструкций становятся
+    зарезервированными словами, т.е. Вы не сможете эти имена использовать в
+    качестве имен переменных или процедур. Ассемблерные инструкции компилятор
+    распознает независимо от того, написаны они маленькими или большими
+    буквами.
+Return to contents.
+
+
+
+    2.1.7 /CRI - пропуск повторно включаемого файла.
+
+
+        Чаще всего, повторно включать файл в компилируемый проект, нет
+    необходимости, но это иногда происходит из-за того, что некоторые
+    включаемые файлы сами включают другие файлы. Чтобы этого не происходило
+    приходится делать проверку на повторную загрузку файла. Теперь эту
+    функцию берет на себя компилятор и у Вас отпадает необходимость делать
+    эту проверку.
+
+        Но иногда (очень редко) возникает потребность сделать повторное
+    включение файла. Для этого в компиляторе есть опция командной строки
+    /cri-, которая запрещает компилятору делать проверку на повторное
+    включение. Соответственно, для c--.ini файла, это можно сделать строкой
+    cri- или директивой в компилируемом файле - #pragma option cri-.
+Return to contents.
+
+
+
+    2.1.8 /IND - импорт имен процедур из DLL.
+
+
+        Если Вы хотите в своей программе использовать DLL, для которой нет
+    заголовочного файла с описанием процедур, то компилятор может
+    импортировать имена из этой DLL. Для этого Вам надо указать имя этой
+    библиотеки либо через опцию командной строки /ind=name.dll, либо в
+    файле INI строкой 'ind=name.dll', либо через директиву '#pragma option
+    ind=name.dll'.
+
+        К недостатком такого способа получения имен можно отнести то, что при
+    компиляции программы библиотека, из которой импортируются имена,
+    обязательно должна присутствовать в компьютере. Также, если имена в
+    библиотеке написаны без суффикса '@number', компилятор не будет
+    контролировать число параметров передаваемых процедуре. И, к сожалению,
+    компилятор умеет импортировать имена из библиотек имеющих только формат
+    PE-файла.
+Return to contents.
+
+
+
+    2.1.9 /WS - задать имя stub файла для программ под windows.
+
+
+        Как известно, в программах под windows есть DOS заглушка, называемая
+    stub, которой передается управление при запуске такой программы в чистом
+    DOS-е. Обычно такая заглушка выводит на экран сообщение о том, что эту
+    программу надо запускать в среде windows.
+
+        Вы можете вместо стандартного stub использовать свой. Для этого Вам
+    необходимо указать имя 16-битного EXE-файла либо через опцию командной
+    строки /ws=filename, либо строкой в INI-файле ws=filename, либо
+    директивой #pragma option ws=filename.
+
+        Таким образом, у Вас появилась возможность создавать программы,
+    работающие и под DOS и под windows.
+Return to contents.
+
+
+
+    2.1.10 /WBSS - разместить не инициализированные данные в отдельной секции.
+
+
+        Секция .bss создается автоматически при компиляции программ с ключом
+    /w32. Если Вы хотите иметь эту секцию и при компиляции программ с
+    ключами /w32c или /dll Вам необходимо добавить либо в командной
+    строке опцию /wbss, либо строку wbss в INI-файле, либо директиву
+    #pragma option wbss.
+
+        Использование секции .bss практически не влияет на размер получаемого
+    файла. Теоретически, для процессоров, у которых есть отдельный кэш для
+    данных, использование секции .bss, должно повышать скорость работы
+    программы.
+Return to contents.
+
+
+
+    2.1.11 /DBG - создание отладочной информации.
+
+
+        Если при компиляции программы в командную строку добавить ключ /dbg,
+    или в файл конфигурации c--.ini добавить строку dbg, то компилятор после
+    окончания компиляции создаст файл с отладочной информацией. Этот файл
+    имеет имя главного модуля и имеет расширение *.tds.
+
+        Отладочная информация создаваемая компилятором C-- совместима с
+    отладочной информацией создаваемой компиляторами фирмы Borland. Но, пока,
+    эта информация реализована еще не в полном объеме. Создаваемой сейчас
+    отладочной информации достаточно для проведения простейшей отладки
+    программы.
+
+        Для 16-битных программ под DOS для отладки надо использовать Turbo
+    Debugger из пакета Borland C v4.5 или лучше (файл td.exe).
+
+        Для программ под Windows надо использовать 32-битный отладчик из этого
+    же пакета (файл td32.exe).
+
+        Для 32-битных программ, использующих расширитель DOS применять для
+    отладки Turbo Debugger невозможно. Но, может быть я не знаю, как это
+    делать. Если Вы знаете, как создавать 32-битные программы с
+    DOS-расширителем компиляторами фирмы Borland с включением в них отладочной
+    информации, то расскажите мне. А я попробую применить это для C--.
+Return to contents.
+
+
+
+    2.1.12 /J0 /J1 /J2
+
+
+        Синонимом ключей /J0 /J1 /J2 является директива #jumptomain с
+    параметрами NONE, SHORT и NEAR соответственно.
+
+        Директива #jumptomain выполняет немного различные функции в
+    зависимости от типа выходного файла.
+
+        Компиляция файла типа *.com и *.exe модель памяти tiny:
+
+      #jumptomain NONE (-j0) - в этом случае по окончании кода начальной
+    инициализации программы не генерируется jmp на процедуру main. Эту
+    директиву следует использовать в случае, если до процедуры main нет других
+    не динамических процедур и инициализированных переменных.
+
+      #jumptomain SHORT (-j1) - в этом случае по окончании кода начальной
+    инициализации генерируется короткий jmp на процедуру main. Эту директиву
+    следует использовать, если до процедуры main находится не более 128 байт
+    кода и данных.
+
+      #jumptomain NEAR (-j2) - это состояние устанавливается по умолчанию. При
+    этом генерируется близкий jmp на процедуру main.
+
+        Компиляция файлов *.exe (ключи -exe -d32 -w32 -w32c):
+
+      #jumptomain NONE (-j0) - в этом случае код начальной инициализации
+    программы не генерируется и управление при запуске передается сразу на
+    процедуру main.
+
+      Во всех остальных случаях генерируется код начальной инициализации и
+    управление на процедуру main передается инструкцией call.
+
+        Компиляция файлов *.dll:
+
+      #jumptomain NONE (-j0) - в этом случае код начальной инициализации
+    программы не генерируется и управление при запуске передается сразу на
+    процедуру main.
+
+      Во всех остальных случаях генерируется код заглушки и управление на
+    процедуру main не передается. Фактически процедура main в этом случае не
+    нужна.
+
+      Процедура main при создании файлов DLL должна выглядеть немного иначе,
+    чем в других случаях:
+
+    dword main ( dword hInstDLL, reason, reserv )
+    {
+      ...
+    }
+Return to contents.
+
+
+
+    2.1.13 /LST - Создание ассемблерного листинга.
+
+
+        С помощью дополнительной опции командной строки -lst Вы можете
+    получить вместе с исполнительным файлом и его ассемблерный листинг.
+    Листинг будет помещен в файл одноименный с исполнительным файлом и
+    имеющим расширение *.lst.
+
+        Ассемблерный листинг создается независимой от компилятора частью кода
+    с использованием информации накапливаемой при компиляции программы.
+Return to contents.
+
+
+
+    2.1.14 /ENV - Сохранение адреса переменных окружения.
+
+
+        Если при компиляции программы Вы в командную строку добавите опцию
+    -ENV или в файл c--.ini строка ENV, то компилятор добавит в вашу
+    программу переменную environ, в которой при загрузке будет сохранятся
+    адрес переменных окружения запускаемой программы. Для программ под
+    Windows это будет полный адрес, а для остальных в этой переменной будет
+    сохраняться только адрес сегмента.
+Return to contents.
+
+
+
+    2.1.15 /CPA - Очистка post-области данных.
+
+
+        Переменные, которым в теле программы не было присвоено никакое
+    значение, не включаются в тело скомпилированной программы. Для них
+    резервируется память за пределами программы. Но эта память может быть
+    заполнена произвольной информацией.
+
+        Если Вам необходимо, чтобы неинициализированные переменные при
+    загрузке программы всегда содержали одно и тоже значение (ноль) -
+    включите в командную строку опцию -CPA.
+Return to contents.
+
+
+
+    2.1.16 /W - вывод предупреждений.
+
+
+        По умолчанию компилятор не выводит предупреждения и многие даже не
+    подозревают о существовании такой полезной опции. В C-- предупреждения
+    фактически являются подсказками для создания оптимальных программ и
+    зачастую облегчают отладку программ. В предупреждениях компилятор может
+    сообщить Вам о том, в каком месте можно использовать короткие формы
+    операторов IF, WHILE, FOR... О том, какие процедуры, переменные и
+    структуры определенные в вашей программе не были использованы. О том
+    какие регистры компилятор использовал без вашего ведома и много другой
+    полезной информации.
+
+        По умолчанию предупреждения выводятся на экран. Но их бывает так
+    много, что они могут не поместиться на экране. Поэтому в компиляторе есть
+    опция, по которой все предупреждения выводятся в файл. Имя этого файла
+    задается в той же опции. Поместив в свой c--.ini файл пару вот этих строк:
+
+    w
+    wf=warning
+
+        Вы будете получать в файле warning предупреждения.
+Return to contents.
+
+
+
+    2.1.17 /NW - Выборочное отключение типов предупреждений.
+
+
+        Сейчас компилятор может выдавать 12 типов предупреждений и, иногда их
+    бывает так много, что становится трудно в них ориентироваться. Теперь
+    можно выборочно запрещать выдачу предупреждений. Для этого в командной
+    строке (или в файле C--.INI) можно установить опцию /nw=number, где
+    number - число от 1 до 12. Этим цифрам соответствуют следующие типы
+    предупреждений:
+
+      1 - Optimize numerical expressions
+      2 - Compiler used register ..."
+      3 - Short operator '...' may be used
+      4 - String '...' repeated
+      5 - Expansion variable
+      6 - Signed value returned
+      7 - '...' defined above, therefore skipped.
+      8 - Variable/structure/procedure '...' possible not used
+      9 - Non-initialized variable may have been used
+     10 - Return flag was destroyed
+     11 - Code may not be executable
+     12 - Don't use local/parametric values in inline procedures
+Return to contents.
+
+
+
+    2.1.18 /WSI - короткая таблица импорта.
+
+
+        Таблица импорта обычно состоит в свою очередь из четырех таблиц. Две
+    таблицы LookUp Table и Import Address Table абсолютно одинаковы.
+
+        Опцией командной строки /WSI Вы можете заставить компилятор
+    генерировать только одну из этих двух одинаковых таблиц (генерируется
+    только Import Address Table). Тем самым у Вас получится более компактная
+    таблица импорта, что приведет, в некоторых случаях, к созданию более
+    компактного выходного файла.
+Return to contents.
+
+
+
+  2.2 Директивы транслятора.
+
+
+      C-- не содержит препроцессор. Тем не менее, есть несколько функций
+  очень похожих на функции C препроцессора.
+
+      Они даются как директивы транслятора. Все директивы транслятора
+  начинаются с вопросительного знака ? либо с символа #. Вот список имеющихся
+  директив и их назначение:
+
+  ? align [val]                  Выровнять данные программы на четный по
+                                 умолчанию или на адрес кратный величине val.
+
+  ? aligncode [val]              Выровнять код программы на четный по
+                                 умолчанию или на адрес кратный величине val.
+			         Заполнение производится кодом 0x90.
+
+  ? aligner (aligner value)      определить значение байта вставки.
+
+  ? alignword (TRUE or FALSE)    разрешает или запрещает выравнивание на
+                                 четный адрес переменных типа word и int,
+                                 значение по умолчанию TRUE.
+
+  ? argc (TRUE or FALSE)         Включить или отключить альтернативный
+                                 обработчик командной строки.
+
+  ? atexit                       Вставляет в startup код поддержки процедуры
+                                 ATEXIT().
+
+  ? code32 (TRUE/FALSE)          разрешает/запрещает генерацию 32-битного
+                                 кода.
+
+  ? codesize                     оптимизация размера кода (в ущерб скорости).
+
+  ? compilerversion min-vers     указывает, компилятор какой версии необходим
+                                 для компиляции данной программы.
+
+  ? ctrl_c (TRUE or FALSE )      разрешает или запрещает игнорирование
+                                 нажатия CTRL-C.
+
+  ? dataseg (value)              указывает компилятору сегментный адрес ОЗУ
+                                 для переменных при компиляции ROM-BIOS.
+
+  ? define (identifier) (token)  определяет идентификатор.
+
+  ? DOSrequired (номер)          устанавливает минимальную требуемую версию
+                                 DOS:  старший байт - номер версии,
+                                 младший байт - номер модификации:
+                                  0x0101 для версии 1.1 DOS
+                                  0x0315 для версии 3.21 DOS
+                                  0x0303 для версии 3.3 DOS
+                                  0x0600 для версии 6.0 DOS
+                                  0x0602 для версии 6.2 DOS и т.д.
+
+  ? dosstring (TRUE/FALSE)       указывает компилятору, что в качестве
+                                 терминатора строки надо использовать символ $
+
+  ? else                         генерирует альтернативный код если ?ifdef или
+                                 ?ifndef принимают значение FALSE (пример
+                                 использования смотрите в файле FPU.H--)
+
+  ? endif                        указывает на конец действия директив ifdef и
+                                 ifndef
+
+  ? fastcallapi (FALSE/TRUE)     запретить/разрешить генерацию быстрого вызова
+                                 API-процедур (по умолчанию разрешено).
+                                 Директива работает при компиляции программ
+                                 под Windows.
+
+  ? fixuptable (TRUE/FALSE)      разрешить/запретить создание FixUp таблицы
+                                 (по умолчанию запрещено). Директива работает
+                                 при компиляции программ под Windows.
+
+  ? ifdef (identifier)           если идентификатор определен, то возвращает
+                                 TRUE иначе FALSE
+
+  ? imagebase value              задает адрес Image Base. По умолчанию этот
+                                 адрес  равен 0x400000. Директива работает при
+                                 компиляции программ под Windows.
+
+  ? ifndef (identifier)          если идентификатор определен, то возвращает
+                                 FALSE иначе TRUE
+
+  ? include ("filename")         включает другой файл.
+
+  ? includepath ("path")         указание компилятору, в какой директории надо
+                                 искать включаемые файлы
+
+  ? initallvar                   инициализирует 0 все неинициализированные
+                                 переменные.
+
+  ? jumptomain (NONE, SHORT, NEAR or FALSE)
+                                 устанавливает тип перехода к main(),
+                                 значение по умолчанию - NEAR.
+
+  ? maxerrors (number)           максимальное количество найденных ошибок,
+                                 превысив которое транслятор прекращает
+                                 работу, значение по умолчанию - 16.
+
+  ? movedatarom  (TRUE/FALSE)    указывает компилятору о необходимости
+                                 переноса данных из ПЗУ в ОЗУ.
+
+  ? parsecommandline (TRUE or FALSE)
+                                 включает в программу блок кода для
+                                 синтаксического анализа командной строки
+                                 значение по умолчанию FALSE.
+
+  ? pragma                       может объявлять несколько других директив
+
+  ? print (number or string)     выводит на экран строку или число.
+
+  ? printhex (number)            выводит на экран число в шестнадцатеричном
+                                 коде.
+
+  ? randombyte                   вставляет в код программы байт случайного
+                                 значения.
+
+  ? resize (TRUE or FALSE)       включает функцию изменения после запуска
+                                 размера выделенного программе блока памяти
+                                 на минимально требуемый объем,
+                                 значение по умолчанию TRUE.
+
+  ? resizemessage (string)       сообщение, выводимое на экран перед
+                                 аварийным прерыванием выполнения программы,
+                                 если изменение размера выделенного программе
+                                 блока памяти не выполнено.
+
+  ? setdinproc                   по этой директиве компилятор немедленно
+                                 вставляет в код компилируемой программы все
+                                 вызывавшиеся ранее динамические процедуры.
+
+  ? sizerom  (value)             указывает компилятору размер ПЗУ.
+
+  ? speed                        оптимизация быстродействия (значение
+                                 по умолчанию) в ущерб размеру кода.
+
+  ? stack (number)               определяет размер стека программы в байтах.
+
+  ? startaddress (number)        устанавливает стартовый адрес начала кода,
+                                 значение по умолчанию 0x100.
+
+  ? startuptomain                в com-файлах размещает startup-код в
+                                 процедуре main().
+
+  ? startusevar (number)         указывает адрес, с которого разрешено
+                                 использовать ячейки памяти под
+                                 неинициализированные переменные.
+
+  ? sysattribute (значение)      эта директива передает компилятору атрибут
+                                 создаваемого драйвера. По умолчанию
+                                 устанавливается значение 0x2000.
+                                 Действует только с ключом /SYS.
+
+  ? sysname <текстовая строка>   эта директива передает компилятору имя
+                                 будущего драйвера. По умолчанию
+                                 присваивается имя NO_NAME. Длина имени не
+                                 более 8 символов.  Действует только с ключом
+                                 /SYS.
+
+  ? syscommand ,, ...; - эта директива
+                                 является обязательной при создании
+                                 драйверов. По этой директиве компилятору
+                                 передается список имен процедур обработки
+                                 команд драйвера. Действует только с ключом
+                                 /SYS.
+
+  ? warning (TRUE or FALSE)      эта директива разрешает или запрещает выдачу
+                                 предупреждений. Директива действует только в
+                                 пределах текущего файла и не влияет на
+                                 включаемые файлы.
+
+  ? winmonoblock FALSE           запрещает размещение таблиц файла формата PE
+                                 в одну секцию.
+
+  ? undef                        уничтожает константы объявленные директивой
+                                 ? define
+
+  ? use8086                      ограничивается при генерации объектного кода
+                                 командами 8088/8086 (значение по умолчанию).
+
+  ? use8088                      ограничивается при генерации объектного кода
+                                 командами 8088/8086 (значение по умолчанию).
+
+  ? use80186                     допускает при генерации объектного кода
+                                 команды и оптимизацию для процессора 80186.
+
+  ? use80286                     допускает при генерации объектного кода
+                                 команды и оптимизацию для процессора 80286.
+
+  ? use80386                     допускает при генерации объектного кода
+                                 команды и оптимизацию для процессора 80386.
+
+  ? use80486                     допускает при генерации объектного кода
+                                 команды и оптимизацию для процессора 80486.
+
+  ? usePentium                   допускает при генерации объектного кода
+                                 команды и оптимизацию для процессора Pentium.
+
+  ? useMMX                       допускает при генерации объектного кода
+                                 команды и оптимизацию для процессора Pentium
+                                 MMX.
+
+  ? usestartup                   разрешает компилятору использовать ячейки
+                                 памяти, занимаемые кодом начальной
+                                 инициализации программы.
+Return to contents.
+
+
+
+    2.2.1 ?ifdef/?ifndef
+
+
+         Ранее директива ?ifdef срабатывала на наличие константы независимо
+    от значения ее величины, а директива ?ifndef срабатывала на отсутствие
+    константы в компилируемом файле. Теперь ?indef срабатывает лишь на
+    константу отличную от FALSE, а ?ifndef срабатывает как на отсутствие
+    константы в компилируемом файле, так и на константу имеющую значение
+    FALSE.
+
+        Для директив ?ifdef/?ifndef зарезервированы константы codesize и
+    speed, которые принимают значение TRUE или FALSE в зависимости от режима
+    оптимизации. Это будет полезным для создания более гибких библиотек.
+
+        Есть возможность проверки типа CPU для которого ведется компиляция.
+    Допустимые варианты синтаксиса:
+
+    ?ifdef cpu > 1	 //если программа компилируется для CPU выше 80186
+    ?ifndef cpu >= 2 // -------//------------- не больше или равно 80286
+    ?ifdef cpu == 3  // -------//------------- равно 80386
+    ?ifdef cpu != 0  // -------//------------- не равен 8086
+    ?ifdef cpu < 3   // -------//------------- хуже 80386
+    ?ifdef cpu <= 2  // -------//------------- хуже или равен 80286
+
+        Эта директива позволит Вам писать одну процедуру для различных типов
+    CPU.
+Return to contents.
+
+
+
+    2.2.2 ?initallvar
+
+
+        Директивой ?initallvar TRUE включается режим при котором всем
+    неинициализированным переменным будет присвоено нулевое значение и они
+    будут располагаться в том месте, где были объявлены. Т.е. практически
+    исчезнут неинициализированные переменные. Это может быть полезным при
+    написании драйверов и резидентных программ.
+
+        Параметр FALSE этой директивы отключает этот режим.
+        По умолчанию эта директива установлена в FALSE.
+Return to contents.
+
+
+
+    2.2.3 ?usestartup
+
+
+        Директива ?usestartup разрешает компилятору использовать ячейки кода
+    начальной инициализации программы (startup) для последующего размещения в
+    них неинициализированных переменных. Это может быть полезным для получения
+    более компактного кода, как обычных программ, так и в особенности
+    резидентных.
+
+        Эту директиву применяют только для генерации *.COM файлов.
+Return to contents.
+
+
+
+    2.2.4 ?startusevar
+
+
+        Директивой ?startusevar можно указать начальный адрес с которого
+    компилятор будет распределять память для неинициализированных переменных.
+    Например, получив директиву ?startusevar 0x53 компилятор будет
+    располагать неинициализированные переменные, начиная с адреса 0x53. Это
+    может быть полезным для получения более компактного кода как для
+    резидентных, так и для обычных программ.
+
+        Эту директиву применяют только для генерации *.COM файлов.
+Return to contents.
+
+
+
+    2.2.5 ?atexit
+
+
+        Директива ?atexit добавляет в startup программы код поддержки
+    процедуры ATEXIT, резервирует место для хранения 16 адресов процедур и
+    изменяет код процедур ABORT и EXIT.
+
+        Процедура ATEXIT регистрирует процедуру, адрес которой передается ей в
+    качестве параметра, как процедуру завершения программы. Эта процедура
+    будет вызвана в момент завершения программы процедурами ABORT или EXIT
+    или инструкцией RET из main.
+
+        Всего можно зарегистрировать до 16 процедур. Процедуры вызываются в
+    порядке обратном порядку их регистрации.
+Return to contents.
+
+
+
+    2.2.6 ?startuptomain
+
+
+        По этой директиве компилятор в начале файла делает jmp на начало
+    процедуры main(). Перед началом компиляции этой процедуры компилятор
+    начнет компиляцию startup кода и лишь затем будет продолжена компиляция
+    процедуры main(). Тем самым startup код окажется не в начале файла, как
+    это происходит обычно, а в теле процедуры main(). Это будет полезным при
+    компиляции резидентных программ (TSR).
+
+        Директива ?startuptomain работает только при компиляции com-файлов.
+Return to contents.
+
+
+
+    2.2.7 ?undef
+
+
+        Эта директива уничтожает константы объявленные директивой ?define. Ее
+    можно применять для изменения в процессе компиляции значения какой-нибудь
+    константы.
+Return to contents.
+
+
+
+    2.2.8 ?align и ?aligncode
+
+
+        В C-- существует директива ?align, которая делает однократное
+    выравнивание данных на четный адрес. Но если к этой директиве добавить
+    число, то выравнивание будет произведено на адрес кратный этому числу.
+    Например директива ?align 4 дополнит сегмент данных до адреса кратного
+    4. При выравнивании будут вставляться байты, значения которых определяются
+    директивой ?aligner, по умолчанию это значение равно нулю. Директива
+    ?align производит выравнивание только в сегменте данных. В тех моделях
+    памяти, в которых сегмент данных и кода совпадают эту директиву можно
+    применять и для выравнивания начала процедур.
+
+        Директива ?aligncode [value] делает выравнивание в сегменте кода на
+    адрес кратный значению value, по умолчанию на четный адрес. Значение байта
+    заполнения в этой директиве является число 0x90 - код инструкции NOP.
+    Значение байта заполнения для этой директивы изменить нельзя. Т.о. эту
+    директиву можно применять и внутри исполняемого кода. Например, если Вы
+    хотите получить быстрый код на 486 процессоре, то рекомендуется делать
+    выравнивание начала процедур и циклов на адрес кратный 16.
+Return to contents.
+
+
+
+    2.2.9 ?pragma
+
+
+        Директива #pragma это многофункциональнальная директива, которая в
+    свою очередь имеет свои директивы:
+
+      option
+        Директива option позволяет включить в Ваш код опции командной строки
+    компилятора. Некоторые опции не могут быть использованы в этой директиве;
+    другие должны помещаться в самом начале исходного текста. Пример:
+
+      #pragma option w32c
+
+        Эта директива объявляет компилятору, что надо создать консольный
+    32-битный файл под windows.
+
+      startup
+       Директивой startup можно указать функцию, которая будет выполнена перед
+    запуском процедуры main. Эта директива имеет такой формат:
+
+      #pragma startup procname
+
+        Количество раз, которое можно применять эту директиву в одной
+    программе не ограничено, но реально можно использовать лишь несколько
+    тысяч раз.
+
+      line
+        Директива line выводит на экран номер текущей строки и имя файла.
+    Дополнительно может выводиться содержимое строки находящееся после слова
+    line. Пример:
+
+      #pragma line information
+
+        Встретив эту директиву, компилятор выведет на экран номер строки и имя
+    файла. Также будет выведено сообщение справа от слова line, если оно
+    есть.
+
+      resource
+        Эта директива может принимать значения start и end. Эти два
+    значения выделяют начало и конец блока ресурсов, если вы используете его
+    непосредственно в исходном коде файла, а не в отдельном файле. Пример:
+
+    #pragma resource start
+
+    MyMenu MENU DISCARDABLE
+    BEGIN    POPUP "Files",HELP
+        BEGIN
+            MENUITEM "Open",                        ID_OPEN
+            MENUITEM "Save",                        ID_SAVE
+            MENUITEM SEPARATOR
+            MENUITEM "Exit",                        ID_EXIT
+        END
+        MENUITEM "Other",                           65535
+    END
+
+    #pragma resource end
+Return to contents.
+
+
+
+3. Константы.
+
+  3.1 Числовые константы.
+
+
+      Представление числовых констант в виде десятичных чисел (чисел с
+  основанием 10) и шестнадцатеричных чисел (основание счисления 16) полностью
+  аналогично языку C.
+
+      При двоичном представлении чисел (основание 2) число должно начинаться
+  с символов 0b, за которыми без пробела идет последовательность нулей и
+  единиц.
+
+      При восьмеричном представлении чисел (основание 8) число должно
+  начинаться с символов 0o, за которыми без пробела идет последовательность
+  цифр.
+
+      Вещественное число отличается от целого по наличию в нем точки.
+  Начинаться вещественное число должно либо цифрой от 0 до 9, либо знаком
+  минус. Необязательной частью вещественного числа является показатель
+  степени. Показатель степени отделяется от числа символом e или E.
+  Пробелы недопустимы.
+
+  Примеры:
+    0b11111111 // двоичное представление числа 255
+    0x00F // шестнадцатеричное представление числа 15
+    0o10 // восьмеричное представление числа 8
+    1.234567E-20 // вещественное число
+
+      C-- вместе с традиционным C-стилем шестнадцатеричных чисел понимает и
+  числа записанные в стиле ассемблера. Для тех, кто вдруг не знает, сообщаю,
+  что шестнадцатеричные числа в ассемблере имеют на конце символ h или H.
+  Если первый символ шестнадцатеричного числа больше 9, то перед ним
+  обязательно должен быть записан символ 0. Примеры:
+
+    1234h
+    0A000H
+
+      К числовым константам можно писать суффиксы L, U и F. Фактически
+  эти суффиксы в C-- не играют никакой роли, компилятор их просто
+  проглатывает. Пример:
+
+  #define DEF  1L
+  #define DEF2 2Lu
+  #define DEF3 3.0F
+
+      Эти суффиксы не зависят от регистра, т.е. их можно писать как
+  маленькими, так и большими буквами.
+Return to contents.
+
+
+
+  3.2 Символьные константы.
+
+
+      Одиночные символьные константы, как и в C, должны заключаться в
+  одиночные кавычки '.
+
+      Также как и в C, для обозначения специальных символов служит обратная
+  наклонная черта вправо \ с последующим за ней ключевым символом (или
+  несколькими символами). Поддерживаются следующие специальные символы:
+
+    \a  /* звуковой сигнал */
+    \b  /* забой */
+    \f  /* перевод  страницы */
+    \l  /* перевод строки */
+    \n  /* возврат каретки*/
+    \r  /* возврат каретки*/
+    \t  /* табуляция */
+    \x??  /* символ ASCII, соответствующий байтовому представлению,
+               состоящему из двух шестнадцатеричных цифр, расположенных
+               на месте знаков вопроса */
+     \???  /* символ ASCII, соответствующий байтовому представлению,
+               состоящему из трех десятичных цифр, расположенных
+               на месте знаков вопроса */
+
+      Любой другой символ после обратной наклонной черты вправо будет принят
+  как простой символ.
+
+      Символ "Одиночная кавычка" ' может быть введен при помощи конструкции
+  \'
+
+      Символ NULL может быть введен как ''
+
+      В C-- поддерживаются и многобуквенные символьные константы. Примеры
+  многобуквенных символьных констант:
+
+         'ab'
+         'the'
+         'this is large'
+
+      Никакого ограничения на число символов в символьной константе не
+  накладывается, но различаются только последние 4 символа. Это - максимум,
+  который может быть сохранен в 32-разрядной переменной. Например, константы
+  this is large и arge - одинаковы.
+
+      C-- обрабатывает все символьные константы как числовые значения ASCII
+  символов. Для многобуквенных символьных констант первый символ
+  соответствует старшим разрядам, таким образом, значение для ab будет
+  закодировано как a*256+b.
+Return to contents.
+
+
+
+  3.3 Строковые константы.
+
+
+      Строковые константы, как и в C, заключаются в двойные кавычки (").
+  Специальные символы внутри строк обозначаются так же, как и в символьных
+  константах. Все специальные символы имеют то же значение, что и в
+  символьных константах за исключением \n, который имеет значение новая
+  строка и заменяет собой пару символов возврат каретки и перевод
+  строки.
+
+      В настоящее время наибольшая длина строковой константы - 2048 символов,
+  включая символ-ограничитель 0, таким образом, максимум 2047 значащих
+  символов.
+Return to contents.
+
+
+
+  3.4 Постоянные выражения.
+
+
+      Постоянное выражение - одиночная числовая константа или несколько
+  числовых констант, связанных между собой операторами. Числовое значение
+  выражения вычисляется один раз во время компиляции и далее используется
+  только его постоянное значение.
+
+      Подобно всем выражениям в C--, постоянные выражения всегда вычисляются
+  слева направо, невзирая на правила арифметики! Это совершенно отлично от
+  других языков, и при написании выражений надо быть осторожным и помнить,
+  что 2+3*2=10 а не 8.
+
+      Некоторые примеры постоянных выражений:
+  45 & 1 + 3 // равняется 4
+  14 - 1 / 2 // равняется 6 (помните целочисленные значения)
+  1 * 2 * 3 / 2 + 4 // равняется 7
+      Примеры с применением вещественных чисел:
+  3.23*1.53+2.0E2 // равняется 204.9419
+Return to contents.
+
+
+
+4. Выражения.
+
+  4.1 Типы выражений.
+
+
+      Имеются три типа выражений в C--, не считая постоянных выражений. Это
+  выражения типа EAX/AX/AL, выражения типа неEAX/AX/AL и условные выражения.
+  Все C-- выражения вычисляются слева направо, независимо от старшинства
+  входящих в выражение математических операций.
+Return to contents.
+
+
+
+  4.2 Выражения типа EAX/AX/AL.
+
+
+      Этот тип выражений применяется в случае, когда его результат может быть
+  сохранен в переменной в памяти или в регистре EAX или AX или AL.
+
+      Если результат может быть сохранен в переменных типа byte или char,
+  используется нотация AL.
+
+      Если результат может быть сохранен в переменных типа word или int,
+  используется нотация AX.
+
+      Если результат может быть сохранен в переменных типа dword, long или
+  float, используется нотация EAX.
+Return to contents.
+
+
+
+  4.3 Выражения использующие получатель при вычислении выражения.
+
+
+      Если в правой части выражения используется переменная являющаяся
+  одновременно и приемником, то такие выражения дают различные результаты в
+  зависимости от того является приемник регистром или переменной памяти. Это
+  связано с тем, что при вычислении выражения в переменную памяти, вычисление
+  производится сначала в регистр EAX/AX/AL, и лишь после окончания вычисления
+  результат будет записан в приемник. Если же приемником является регистр, то
+  его значение будет меняться после каждой операции вычисления. Пример:
+
+  int var;
+    var = BX = 2;
+    var = 3 + var; // результатом будет 5
+    BX = 3 + BX;   // результатом будет 6
+Return to contents.
+
+
+
+  4.4 Не - EAX/AX/AL выражения.
+
+
+      Этот тип выражений применяется в случае, когда его результат должен
+  быть сохранен в любом другом регистре, отличном от аккумулятора EAX, AX
+  или AL. В процессе вычисления выражения этого типа меняется только
+  содержимое указанного регистра-получателя, все другие регистры будут
+  сохранены. Если регистром-получателем служит байтовый регистр, а при
+  вычислении используются величины размером в слово, одновременно с записью в
+  младший байт может быть разрушено содержимое старшего байта
+  регистра-получателя.
+
+      Это обстоятельство накладывает некоторые ограничения на операции и
+  операнды, допустимые в выражениях типа не EAX/AX/AL. Внутри выражений
+  байтового типа не допускается:
+
+      - делать вызовы МАКРОКОМАНД,
+      - делать вызовы РЕГИСТРОВЫХ процедур
+      - делать вызовы СТЕКОВЫХ процедур
+
+      Ранее в не-EAX/AX/AL выражениях было можно использовать лишь
+  операции: сложения, вычитания, XOR, OR, AND. Теперь для 16 и 32 битных
+  регистров почти все ограничения сняты. Но есть еще ограничения на регистры.
+  Например, если в выражении используется сдвиг на значение переменной, а
+  приемником являются регистры CX/ECX, то такое выражение компилятор не будет
+  компилировать:
+
+     CX = var * SI * 3 * var >> 3;  //вызовет сообщение об ошибке
+
+      Примечание:  для 8 битных не-AL выражений умножать можно только на
+  числа: 0, 1, 2, 4, 8, 16, 32, 64 и 128. Все эти ограничения связаны со
+  стремлением не разрушать другие регистры при использовании не-EAX/AX/AL
+  выражений.
+Return to contents.
+
+
+
+  4.5 Условные выражения.
+
+
+      Условные выражения - выражения, результатом вычисления которых является
+  логическое значение да или нет, используемое в операторе if и циклах do {}
+  while, while, for.
+
+      Имеются два типа условных выражений, простые и сложные.
+
+      Возможно логическое объединение условий.
+Return to contents.
+
+
+
+    4.5.1 Простые условные выражения.
+
+
+        Простые условные выражения - одиночная лексема или выражение, которое
+    примет значение да, если расчетное значение отлично от нуля, или значение
+    нет, если расчетное значение равно нулю.
+Return to contents.
+
+
+
+    4.5.2 Сложные условные выражения.
+
+
+    Сложные условные выражения имеют следующую форму:
+
+         (левая_часть оператор_отношения правая_часть)
+
+    Где:
+       левая_часть - любое выражение типа AL/AX/EAX или постоянное выражение.
+                     Тип выражения определяется по типу первой лексемы
+                     (регистра или переменной); значение типа по умолчанию -
+                     word для 16-битных программ и dword для 32-битных. Если
+                     желателен другой тип, перед выражением ставится
+                     соответствующее ключевое слово, определяющее его тип:
+                     byte, char, int, long, dword или float
+
+       оператор_отношения - любой из операторов отношения:
+                     ==, !=, <>, <, >, <=, или >=.
+
+       правая_часть - любой одиночный регистр, одиночная переменная или
+                     постоянное выражение.
+
+    Примеры правильных сложных условных выражений:
+
+         (X + y > z)
+         (int CX*DX < = 12*3)
+         (byte first*second+hold == cnumber)
+
+    Примеры недопустимых сложных условных выражений:
+
+         (x+y >= x-y) // правая часть не является одиночной лексемой или
+                         постоянным выражением.
+         (Z = y) // вместо == ошибочно поставлен =
+Return to contents.
+
+
+
+  4.6 Изменение типа выражения при присваивании.
+
+
+      Если после знака равенства написать тип отличный от типа вычисляемой
+  переменной, то все переменные участвующие в процессе вычисления, будут
+  преобразовываться к этому новому типу, и лишь конечный результат будет
+  преобразован к типу вычисляемой переменной. Пример:
+
+  int i, a;
+  long b;
+  char c;
+
+    i = a * b + c ;
+
+      Значения переменных a, b, и c в этом примере перед вычислением будут
+  преобразованы к типу int (типу переменной i). Но если записать это
+  выражение вот так:
+
+    i = long a * b + c ;
+
+      то  переменные  a,  b,  и  c  в  этом  примере  перед  вычислением будут
+  преобразованы к типу  long, а конечный  результат будет преобразован  к типу
+  переменной i - int.
+Return to contents.
+
+
+
+  4.7 Вычисление в регистры EAX/AX/AL со знаком.
+
+
+      По умолчанию все вычисления в регистры производятся как с без знаковыми
+  величинами.
+
+  Например:
+
+    int a,b,c;
+    AX = a * b / c ;
+
+  При этом компилятор генерировал без знаковые инструкции div и mul, так как
+  регистры считаются без знаковыми переменными. Если написать вот так:
+
+    AX = int a * b / c ;
+
+  то компилятор сгенерирует инструкции idiv и imul.
+
+       Обращаю ваше внимание, что для регистра AL можно использовать только
+  модификатор char, для AX соответственно только int, а для EAX - long. Для
+  остальных регистров подобное делать нельзя.
+Return to contents.
+
+
+
+5. Идентификаторы.
+
+  5.1 Формат идентификатора.
+
+
+      Идентификаторы в C-- должны начинаться или с символа подчеркивания _
+  или заглавных или строчных букв. Следующие символы могут быть любой
+  комбинацией символов подчеркивания, заглавных или строчных букв или чисел
+  (от 0 до 9). Общая длина идентификатора не может превышать 64 символа.
+  Символы с кодом больше 0x7A (код символа z) недопустимы.
+
+  Примеры допустимых идентификаторов:
+
+  _DOG
+  Loony12
+  HowdYBoys_AND_Girls
+  WOW___
+  X
+
+  Примеры недопустимых идентификаторов:
+
+  12bogus                                 /* не может начинаться с числа */
+  WowisthisalongidentifieryupitsureisnotOyoulengthismorethat64chars
+   /*длина идентификатора превышает 64 */
+  Y_es sir                                /* пробелы недопустимы */
+  The-end                                 /* дефисы недопустимы */
+Return to contents.
+
+
+
+  5.2 Зарезервированные идентификаторы.
+
+
+      Список зарезервированных в C-- идентификаторов, которые не могут
+  использоваться как общие идентификаторы, поскольку они уже были определены
+  или зарезервированы для других целей:
+
+  BREAK  CASE    CONTINUE  ELSE    EXTRACT  FALSE  FOR
+  FROM   GOTO    IF        LOOPNZ  RETURN   SWITCH TRUE
+  WHILE
+
+  CARRYFLAG    MINUSFLAG  NOTCARRYFLAG  NOTOVERFLOW
+  NOTZEROFLAG  OVERFLOW   PLUSFLAG      ZEROFLAG
+
+  __CODEPTR__ __COMPILER__ __DATAPTR__ __DATESTR__ __DATE__    __DAY__
+  __HOUR__    __LINE__     __MINUTE__  __MONTH__   __POSTPTR__ __SECOND__
+  __TIME__    __VER1__     __VER2__    __WEEKDAY__ __YEAR__
+
+  _export  asm     break   byte      case     cdecl   char       continue
+  default  do      dword   else      enum     extern  far        fastcall
+  float    for     goto    if        inline   int     interrupt  long
+  loop     loopnz  pascal  return    short    signed  sizeof     static
+  stdcall  struct  switch  union     unsigned void    while      word
+
+  ESCHAR  ESBYTE  ESINT  ESWORD  ESLONG  ESDWORD  ESFLOAT
+  CSCHAR  CSBYTE  CSINT  CSWORD  CSLONG  CSDWORD  CSFLOAT
+  SSCHAR  SSBYTE  SSINT  SSWORD  SSLONG  SSDWORD  SSFLOAT
+  DSCHAR  DSBYTE  DSINT  DSWORD  DSLONG  DSDWORD  DSFLOAT
+  FSCHAR  FSBYTE  FSINT  FSWORD  FSLONG  FSDWORD  FSFLOAT
+  GSCHAR  GSBYTE  GSINT  GSWORD  GSLONG  GSDWORD  GSFLOAT
+
+  AX   CX   DX   BX   SP   BP   SI   DI
+  EAX  ECX  EDX  EBX  ESP  EBP  ESI  EDI
+  AL   CL   DL   BL   AH   CH   DH   BH
+  ES   CS   SS   DS   FS   GS
+
+  ST(0)  ST(1)  ST(2)  ST(3)  ST(4)  ST(5)  ST(6)  ST(7)  ST
+  st(0)  st(1)  st(2)  st(3)  st(4)  st(5)  st(6)  st(7)  st
+
+      Этот список может быть получен из C-- транслятора в любое время,
+  запуском его с опцией /WORDS из командной строки.
+
+      Если Вы пользуетесь при компиляции опцией командной строки /ia, которая
+  позволяет использовать ассемблерные инструкции не заключая их в блоки asm и
+  без префикса $, то все имена ассемблерных инструкций становятся
+  зарезервированными словами. Причем имена ассемблерных инструкций компилятор
+  различает независимо от того, написаны они маленькими или большими буквами.
+
+     Список имен поддерживаемых компилятором ассемблерных инструкции можно
+  получить запустив компилятор с опцией /LAI.
+
+     Кроме этого в ассемблерных инструкциях становятся зарезервированными
+  следующие идентификаторы:
+
+  ax   cx   dx   bx   sp   bp   si   di
+  eax  ecx  edx  ebx  esp  ebp  esi  edi
+  al   cl   dl   bl   ah   ch   dh   bh
+  es   cs   ss   ds   fs   gs
+
+  DR0   DR1   DR2   DR3   DR4   DR5   DR6   DR7
+  CR0   CR1   CR2   CR3   CR4   CR5   CR6   CR7
+  TR0   TR1   TR2   TR3   TR4   TR5   TR6   TR7
+  MM0   MM1   MM2   MM3   MM4   MM5   MM6   MM7
+  XMM0  XMM1  XMM2  XMM3  XMM4  XMM5  XMM6  XMM7
+
+  dr0   dr1   dr2   dr3   dr4   dr5   dr6   dr7
+  cr0   cr1   cr2   cr3   cr4   cr5   cr6   cr7
+  tr0   tr1   tr2   tr3   tr4   tr5   tr6   tr7
+  mm0   mm1   mm2   mm3   mm4   mm5   mm6   mm7
+  xmm0  xmm1  xmm2  xmm3  xmm4  xmm5  xmm6  xmm7
+Return to contents.
+
+
+
+  5.3 Универсальные регистры для 16 и 32-битного режима.
+
+
+      При создании библиотечных процедур очень часто приходится писать
+  варианты процедуры для работы в 16-битном и 32-битном режимах, которые
+  отличаются друг от друга лишь использованием в них либо 16-битных либо
+  32-битных регистров соответственно. Но можно писать лишь одну процедуру,
+  используя в ней новый синтаксис регистров. Если компилятор встретит вот
+  такой синтаксис:
+
+    (E)AX=0;
+
+      то компилятор будет использовать при компиляции 16-битного кода регистр
+  AX, а при компиляции 32-битного кода регистр EAX.
+
+      Использование автоматических регистров позволит упростить библиотечные
+  файлы и сделать их более понятными.
+Return to contents.
+
+
+
+  5.4 Предопределенные идентификаторы.
+
+
+      Идентификаторы, определяемые компилятором в зависимости от режима
+  компиляции:
+
+  __TLS__     идет компиляция под windows (w32, w32c, dll).
+  __DLL__     идет компиляция dll.
+  __CONSOLE__ идет компиляция консольного приложения windows
+  __WIN32__   идет компиляция GUI-шного приложения
+  __FLAT__    компилируется 32-битный код.
+  __MSDOS__   компилируется 16-битный код.
+  __TINY__    используется модель памяти tiny в 16-битном режиме
+  __SMALL__   используется модель памяти small в 16-битном режиме
+  __DOS32__   компилируется 32-битный код под DOS (d32)
+  __COM__     компилируется com-файл
+  __SYS__     компилируется sys-файл
+  __ROM__     компилируется rom-файл
+  __OBJ__     компилируется obj-файл
+  __TEXE__    компилируется exe-файл модели tiny
+  __EXE__     компилируется exe-файл модели small
+  __MEOS__    компилируется исполняемый файл для MenuetOS
+  codesize    компиляция ведется с оптимизацией на размер кода
+  speed       компиляция ведется с оптимизацией на быстродействие кода
+  cpu         определяет тип процессора для которого ведется компиляция:
+  	    0 - 8086
+  	    1 - 80186
+  	    2 - 80286
+  	    3 - 80386
+  	    4 - 80486
+  	    5 - Pentium
+  	    6 - Pentium MMX
+  	    7 - Pentium II
+
+      Эти идентификаторы могут быть проверены директивами #ifdef или #ifndef.
+  Идентификатор cpu может быть использован лишь с операторами проверки
+  условий:
+
+  #ifdef cpu > 3  //если тип процессора больше 80386
+Return to contents.
+
+
+
+6. Переменные.
+
+  6.1 Типы переменных.
+
+
+      В C-- имеется семь типов переменных (именованных областей памяти), это:
+  byte, word, dword, char, int, long, float.
+
+      Следующая таблица  показывает размер  и диапазон  представляемых величин
+  каждого из типов переменной:
+
+   NAME   | SIZE  |        VALUE RANGE          |        VALUE RANGE
+   тип    |размер |   диапазон представления    |   диапазон представления
+          |в байт.|    в десятичной системе     | в шестнадцатеричной системе
+  ---------------------------------------------------------------------------
+  byte    |   1   |           0 to 255          |        0x00 to 0xFF
+  word    |   2   |           0 to 65535        |      0x0000 to 0xFFFF
+  dword   |   4   |           0 to 4294967295   |  0x00000000 to 0xFFFFFFFF
+  char    |   1   |        -128 to 127          |        0x80 to 0x7F
+  int     |   2   |      -32768 to 32767        |      0x8000 to 0x7FFF
+  long    |   4   | -2147483648 to 2147483647   |  0x80000000 to 0x7FFFFFFF
+  float   |   4   |    -3,37E38 to +3,37E38     |  0xFF7FFFFF to 0x7FFFFFFF
+
+      Примечание:  для работы с типами float, dword и long используются
+  32-разрядные целочисленные команды, следовательно, для их выполнения нужно
+  иметь процессор не хуже 80386, что сейчас не является большой проблемой.
+
+      Для совместимости со стандартом, принятом в языке C, введены
+  новые зарезервированные слова: short, signed, unsigned. Для типа int
+  в 32-битном режиме изменена разрядность. Вот таблица всех вариантов новых
+  типов данных:
+
+  ---------------------------------------------------------
+  |   полный тип     |допустимые сокращения|старые аналоги|
+  ---------------------------------------------------------
+  |signed char       |char                 |  char        |
+  |signed int        |signed, int          |  int/long    |
+  |signed short int  |short, signed short  |  int         |
+  |signed long int   |long, signed long    |  long        |
+  |unsigned char     |---                  |  byte        |
+  |unsigned int      |unsigned             |  word/dword  |
+  |unsigned short int|unsigned short       |  word        |
+  |unsigned long int |unsigned long        |  dword       |
+  ---------------------------------------------------------
+
+      Старые типы byte, word и dword поддерживаются по прежнему и имеют
+  функционально прежнее значение. Изменения коснулись лишь типа int. Он в
+  16-битном режиме, также как и тип unsigned int, имеет 16-битный размер, а
+  в 32-битном режиме эти оба типа имеют размер в 32-бита. На первый взгляд
+  такие свойства типа int вносят некоторую путаницу, но это дает большой
+  выигрыш при использовании этого типа в библиотечных файлах, которые могут
+  быть использованы при компиляции 16-битных и 32-битных программ.
+Return to contents.
+
+
+
+  6.2 Объявление переменных.
+
+
+      Синтаксис для объявления переменных следующий:
+
+  variable-type identifier;
+
+  где variable-type - char, byte, int, word, long, dword или float.
+
+      Одновременно могут быть объявлены несколько идентификаторов одного типа:
+
+  variable-type identifier1, identifier2, ... , identifierN;
+
+      Одномерные массивы могут быть объявлены следующим образом:
+
+  variable-type identifier[elements];
+
+  где elements -  постоянное выражение для  количества переменных этого  типа,
+  объединенных в массив.
+
+      Инициализированные массивы можно объявлять без указания числа
+  элементов. При этом будет создан массив по фактическому числу элементов.
+
+  variable-type identifier[] = { const1, const2 };
+
+      Переменные при объявлении могут быть проинициализированы следующим
+  образом:
+
+  variable-type identifier = value;
+
+      Некоторые примеры глобальных объявлений:
+  byte i,j;    /* объявляет две переменные типа byte с именами i и j */
+  word see[10] /* объявляет массив с именем see, состоящий из 10
+                  элементов типа word */
+  int h,x[27]  /* объявляет, переменную типа int с именем h,
+                  и массив с именем x, состоящий из 27 элементов типа int */
+  long size=0; /* объявлена переменная типа long с именем size и ей присвоено
+                  значение 0. */
+Return to contents.
+
+
+
+  6.3 Глобальные переменные.
+
+
+      Глобальные переменные - это переменные, область действия которых
+  распространяется на всю программу. В C-- использовать глобальные переменные
+  можно в процедурах, расположенных ниже места ее объявления. Т.е. если Вы
+  пишите процедуру, в которой используете переменную var, а саму переменную
+  объявляете ниже текста процедуры, то компилятор выдаст ошибку. Это связано
+  с тем, что компилятор может знать тип переменной только после их
+  объявления.  Но для таких переменных можно использовать взятие их адреса,
+  так как адрес переменной не зависит от его типа. Пример:
+
+  void Proc(){
+    gvar = 0; /* компилятор выдаст сообщение об ошибке, т.к. он еще не знает
+                 типа переменной gvar */
+    AX = #gvar; /* несмотря на то, что компилятор не знает и адреса этой
+                   переменной такое выражение будет откомпилировано */
+  }
+  int gvar;
+
+      Но все же ситуация не безнадежна и нам удастся добиться того, чего мы
+  задумали. В этом нам поможет альтернативный синтаксис обращения к
+  переменным:
+
+  void Proc(){
+    DSINT[#gvar] = 0; /* компилятор успешно откомпилирует это выражение т.к.
+                         ему теперь известен тип переменной gvar */
+  }
+  int gvar;
+
+      Память под глобальные переменные выделяется в сегменте данных. Если
+  переменная при объявлении инициализируется (т.е. ей присвоено какое-то
+  значение), то переменная будет включена в код компилируемого файла. Если
+  переменная не инициализируется, то место для переменной будет
+  зарезервировано сразу же за последним байтом скомпилированной программы.
+Return to contents.
+
+
+
+  6.4 Локальные переменные.
+
+
+      Локальные переменные - это переменные область действия которых
+  распространяется лишь в пределах одной процедуры. Объявлять локальные
+  переменные, в отличии от современных версий C, можно между именем процедуры
+  и первой открывающейся фигурной скобкой. Пример:
+
+  void PROC ()
+  int i;  //объявлена локальная переменная типа int с именем i
+  {
+      for ( i=0; i<10; i++ ) WRITE(1);
+  }
+
+      Память под локальные переменные отводится в сегменте стека.
+
+      К локальным переменным можно отнести и параметры стековых процедур. Под
+  них также отводится память в стеке.
+
+      Можно инициализировать локальные переменные при их объявлении. Но есть
+  некоторые ограничения. Нельзя инициализировать массивы и многомерные
+  структуры. Инициализировать можно одним значением, т.е нельзя при
+  инициализации локальных переменных пользоваться перечислением заключенным в
+  фигурные скобки и операторами FROM и EXTRACT.
+
+      Имена локальных переменных могут совпадать с именами глобальных
+  переменных или процедур, но тогда Вы не сможете обратиться к глобальной
+  переменной или вызвать одноименную процедуру.
+
+      Локальные переменные можно объявлять и в начале блока процедуры. Но
+  только до начала тела процедуры. Пример:
+
+  void proc(){
+  int locproc;  // объявление локальной процедуры
+    locproc=0;  // а теперь пошло тело процедуры
+  int locproc;  // а на это объявление переменной компилятор выдаст сообщение
+                // об ошибке, т.к. уже началось тело процедуры
+  }
+Return to contents.
+
+
+
+  6.5 Динамические переменные и структуры.
+
+
+      Наряду с уже известными Вам динамическими процедурами в C-- есть
+  возможность использовать динамически и переменные и структуры. Динамические
+  переменные и структуры обозначаются также как и динамические процедуры -
+  символом двоеточия перед началом их объявления. И также как и динамическая
+  процедура, динамическая переменная или структура будет вставлена в код,
+  лишь в том случае, если она будет использована в программе.
+
+      Динамические переменные и структуры найдут применение в библиотеках.
+  Использовать их непосредственно в программах нет смысла.
+
+      У динамических переменных, структур также как и у процедур, есть один
+  недостаток - Вы не сможете знать, в каком месте откомпилированного кода они
+  будут расположены, и в каком порядке. Но необходимость это знать бывает
+  очень редко.
+
+      Динамические инициализированные переменные и структуры в файле будут
+  расположены в его самом конце, после динамических процедур. Эту их
+  особенность можно использовать, если Вам будет необходимо, чтобы данные не
+  были разбросаны среди кода, а были сгруппированы в одном месте.
+Return to contents.
+
+
+
+  6.6 Присваивание одного значения нескольким переменным.
+
+
+      Если Вам необходимо присвоить нескольким переменным одинаковые значения:
+
+    var1=0;
+    var2=0;
+    var3=0;
+
+      то теперь это можно записать более коротко:
+
+    var1=var2=var3=0;
+
+      При использовании такой записи генерируется более компактный и более
+  быстрый код.
+Return to contents.
+
+
+
+  6.7 Переменные типа float.
+
+    6.7.1 Формат переменных типа float.
+
+
+        Для представления значений с плавающей точкой в язык C-- введен тип
+    float. Этому типу соответствует действительное число одинарной точности
+    FPU.
+
+        Формат представления данных с плавающей точкой включает три поля:
+    знака, мантиссы и порядка. Знак определяется старшим значащим разрядом.
+    Поле мантиссы содержит значащие биты числа, а поле порядка содержит
+    степень 2 и определяет масштабирующий множитель для мантиссы.
+
+    31 30.....23 22........0
+    |  |      |  |         |
+    |  |      |  -------------- - поле мантиссы
+    |  ------------------------ - поле порядка
+    --------------------------- - бит знака
+Return to contents.
+
+
+
+    6.7.2 Константы с плавающей точкой.
+
+
+        Компилятор отличает вещественное число от целого по наличию в нем
+    точки. Начинаться вещественное число должно либо цифрой от 0 до 9, либо
+    знаком минус. Необязательной частью вещественного числа является
+    показатель степени. Показатель степени отделяется от числа символом e или
+    E. Пробелы недопустимы. Вот примеры допустимого синтаксиса:
+
+     0.98
+     -15.75
+     3.14e2
+     1.234567E-20
+Return to contents.
+
+
+
+    6.7.3 Диапазон допустимых значений.
+
+
+        Вещественное число типа float может находиться в диапазоне от 3.37E38
+    до -3.37E38. Минимально близкое к нулю значение равняется 1.17E-38 и
+    -1.17E-38. Записывать вещественное число одинарной точности более чем 8
+    цифрами не имеет смысла. Показатель степени может принимать значения от
+    +38 до -38.
+Return to contents.
+
+
+
+    6.7.4 Математические операции.
+
+
+        Компилятор поддерживает 4 основных действия над переменными типа
+    float: сложение, вычитание, умножение и деление. Поддерживается также
+    инкремент (var++ - увеличение на 1), декремент (var-- - уменьшение на 1),
+    смена знака (-var) и обмен значениями (var1 >< var2). Остальные
+    математические операции будут реализованы либо уже реализованы во внешних
+    библиотеках. При вычислении значения переменной float можно использовать
+    и переменные других типов, они будут автоматически преобразованы в тип
+    float.
+
+        ВНИМАНИЕ! Составные математические  операции выполняются в том
+    порядке, в котором они записаны, невзирая на правила арифметики.
+Return to contents.
+
+
+
+    6.7.5 Преобразования типов.
+
+
+        При математических операциях конечным итогом которых является
+    переменная типа float, все операнды других типов перед вычислением будут
+    преобразованы в тип float. При присваивании переменной типа float значения
+    переменной другого типа оно также будет преобразовано в тип float.
+
+        Если при целочисленных вычислениях одним из операндов будет переменная
+    типа float, то из него будет выделена целая часть, которая и примет
+    участие в вычислениях. При присваивании целочисленной переменной значения
+    переменной типа float, из нее также будет выделена целая часть, которая и
+    будет присвоена целочисленной переменной.
+Return to contents.
+
+
+
+    6.7.6 Операции сравнения.
+
+
+        Если при операции сравнения левым операндом является переменная или
+    выражение типа float, а правым является целочисленное значение, то
+    целочисленное значение будет преобразовано в вещественный тип. Если же
+    левым операндом является целочисленное выражение или переменная, а правым
+    операндом значение типа float, то из правого операнда будет выделена целая
+    часть, которая и примет участие в сравнении.
+Return to contents.
+
+
+
+    6.7.7 Сравнение переменных типа float с 32-битным регистром.
+
+
+        В регистрах могут содержаться знаковые, без знаковые и вещественные
+    данные. По умолчанию считается, что в регистре находится без знаковое целое
+    число. При сравнении переменных типа float с 32-битным регистром можно
+    указывать тип данных содержащихся в регистре.  Для этой цели можно
+    использовать модификаторы: signed, unsigned, float. Примеры:
+
+    float f=1.0;
+
+    void PROC()
+    {
+      IF( f < signed ECX)	//в регистре ECX находится знаковое число
+      IF( unsigned EBX > f) //в регистре EBX находится без знаковое число
+      IF( f == float EAX )  //в EAX находится число формата float
+    }
+
+        ВНИМАНИЕ!  При операции сравнения с участием переменой типа float,
+    содержимое регистра AX будет разрушено.
+Return to contents.
+
+
+
+  6.8 Указатели.
+
+
+      В C-- сейчас указатели реализованы не в полном объеме. Поэтому многие
+  вещи, которые возможны в обычных языках C, здесь будут недоступны.
+
+      Пример применения указателей в C--:
+
+  char *string[4]={"string1", "string2", "string3", 0}; //массив указателей
+  char *str="string4";
+
+  main()
+  int i;
+  char *tstr;
+  {
+	FOR(i=0; string[i]!=0; i++){
+		WRITESTR(string[i]);
+		WRITELN();
+	}
+	FOR(tstr=str;byte *tstr!=0; tstr++){
+		WRITE(byte *tstr);
+	}
+  }
+
+      Указатели можно использовать при передаче параметров процедурам, а в
+  самих процедурах в качестве как локальных, так и параметрических
+  переменных. Указатели можно также использовать в структурах. Можно
+  использовать указатели на указатели. Введена поддержка указателей на
+  процедуры:
+
+  void (*proc)();  //объявление указателя на процедуру
+
+      По умолчанию указатели на процедуру являются указателями на процедуру в
+  стиле pascal, независимо от регистра, в котором написано имя процедуры и
+  режима компиляции. Если Вам необходимо, чтобы был использован другой тип
+  вызова, то его необходимо указать при объявлении указателя на процедуру.
+
+      При инициализации указателей компилятор не контролирует то, чем
+  инициализируется указатель. Т.е. Вы можете указателю на char присвоить
+  указатель на int или указателю на процедуру присвоить адрес переменной.
+  Это может вызвать ошибку в работе программы.
+Return to contents.
+
+
+
+7. Адресация.
+
+  7.1 Относительная адресация.
+
+
+      Изначально индексный доступ к элементам в массивах любого типа в
+  компиляторе осуществлялся побайтно, независимо от объявленного типа данных.
+  Индексы ограничены форматом поля RM процессора 8086, таким образом,
+  доступны только следующие форматы индексов (где индекс - значение
+  16-разрядной константы или постоянного выражения):
+
+        variable[index]
+        variable[index+BX+SI]
+        variable[index+BX+DI]
+        variable[index+BP+SI]
+        variable[index+BP+DI]
+        variable[index+SI]
+        variable[index+DI]
+        variable[index+BP]
+        variable[index+BX]
+
+      Начиная с версии 0.210, появилась возможность использовать в качестве
+  индекса переменных типа char byte int word long dword. При этом
+  доступ к элементам массива осуществляется в зависимости от объявленного типа
+  массива.
+
+      Также начиная с версии 0.210 появилась возможность использовать в
+  качестве индексных и базовых регистров при относительной адресации любые
+  32-битные регистры.
+
+      Если Вы для адресации к элементам массива будете использовать регистры и
+  числовые константы, из которых можно получить поле RM для инструкций 8086
+  процессора или комбинацию полей RM BASE и SIB для 80386 процессора, то
+  компилятор будет использовать эти регистры для генерации инструкции с этими
+  полями. В результате Вы получите относительную побайтную адресацию к
+  элементам массива.
+
+      Если же из этих регистров невозможно получить поля RM, BASE, SIB,
+  или для адресации будет использована переменная, то компилятор сначала
+  вычислит это выражение в регистр (E)SI или другой, подходящий регистр, а
+  затем умножит содержимое этого регистра на разрядность Вашего массива. Таким
+  образом, в этом случае вы будете иметь поэлементную адресацию в массиве.
+  Пример:
+
+    AX = var [ 5 ];
+    AX = var [ BX + 5 ];
+    AX = var [ BX + CX ];
+    AX = var [ i ];
+
+      Компилятор сгенерирует следующий код:
+  test.c-- 7: AX=var[5];
+  0100 A12501                   mov     ax,[125h]
+
+  test.c-- 8: AX=var[BX+5];
+  0103 8B872501                 mov     ax,[bx+125h]
+
+  test.c-- 9: AX=var[BX+CX];
+  0107 89DE                     mov     si,bx
+  0109 01CE                     add     si,cx
+  010B 01F6                     add     si,si
+  010D 8B842001                 mov     ax,[si+120h]
+
+  test.c-- 10: AX=var[i];
+  0111 8B362201                 mov     si,[122h]
+  0115 01F6                     add     si,si
+  0117 8B842001                 mov     ax,[si+120h]
+
+      Как Вы видите, первые два выражения были преобразованы в одну
+  ассемблерную инструкцию, и получилась побайтная адресация. В двух следующих
+  выражениях получить одну ассемблерную инструкцию не удалось и компилятор
+  применил для этих выражений поэлементную адресацию.
+
+      Такой двойственный подход реализован с целью сохранения совместимости
+  новых возможностей с предыдущими.
+
+      Несмотря на кажущуюся для неискушенного пользователя путаницу, этот
+  механизм легко понять и запомнить по следующему простому правилу: если Вы
+  используете в качестве индекса только цифровое значение или регистр BX, SI,
+  DI, BP или любой 32-битный регистр, то компилятор сгенерирует код с
+  побайтной адресацией. Если же в качестве индекса будет использована
+  переменная, то компилятор сгенерирует код с поэлементной адресацией. Если
+  же Вы хорошо знакомы с ассемблером, то Вам не составит большого труда
+  понять в каких случаях Вы получите побайтную, а в каких поэлементную
+  адресацию.
+
+      Иногда требуется иметь побайтный доступ к элементам массива используя в
+  качестве индекса переменную. Например
+
+    AX=var[i];
+
+      Для этого выражения будет сгенерирована поэлементная адресация, а нам
+  нужна побайтовая. Для этого можно написать так:
+
+    SI=i;
+    AX=var[SI];
+
+      Но можно это записать короче:
+
+    AX=DSWORD[#var+i];
+
+      В обоих этих случаях Вы получите побайтную адресацию к элементам массива
+  var. В первом варианте Вы сможете контролировать какой регистр будет
+  использован в качестве индекса, а во втором варианте компилятор будет сам
+  выбирать регистр для использования в качестве индекса.
+
+      Важно всегда помнить о двойственном подходе компилятора к вычислению
+  адреса в массиве. Еще раз кратко:  если Вы в массиве адресуетесь используя
+  числовую константу или регистры BX,DI,SI,BP компилятор использует эти
+  значения без изменения.  Во всех других случаях будет коррекция значения в
+  зависимости от типа массива.
+Return to contents.
+
+
+
+  7.2 Абсолютная адресация.
+
+
+      Абсолютная адресация также возможна.  Действуют те же самые ограничения
+  на индексы, что и при относительной адресации.
+
+      Вычисленный индекс будет абсолютен в сегменте, регистр которого указан.
+  Можно указывать любой из регистров DS, CS, SS и ES. На процессорах 80386 и
+  более новых можно указывать также регистры FS и GS.
+
+      Синтаксис - точно такой же, как и в относительной адресации, за
+  исключением того, что указывается не переменная, а сегмент и тип данных.
+  Могут применяться следующие указатели:
+
+             // адресация в сегменте данных
+         DSBYTE  [смещение] // адресует байт в сегменте DS
+         DSWORD  [смещение] // адресует слово в сегменте DS
+         DSCHAR  [смещение] // адресует char в сегменте DS
+         DSINT   [смещение] // адресует int в сегменте DS
+         DSDWORD [смещение] // адресует dword в сегменте DS
+         DSLONG  [смещение] // адресует long в сегменте DS
+         DSFLOAT [смещение] // адресует float в сегменте DS
+
+             // адресация в сегменте кода
+         CSBYTE  [смещение] // адресует байт в сегменте CS
+         CSWORD  [смещение] // адресует слово в сегменте CS
+         CSCHAR  [смещение] // адресует char в сегменте CS
+         CSINT   [смещение] // адресует int в сегменте CS
+         CSDWORD [смещение] // адресует dword в сегменте CS
+         CSLONG  [смещение] // адресует long в сегменте CS
+         CSFLOAT [смещение] // адресует float в сегменте CS
+
+             // адресация в сегменте стека
+         SSBYTE  [смещение] // адресует байт в сегменте SS
+         SSWORD  [смещение] // адресует слово в сегменте SS
+         SSCHAR  [смещение] // адресует char в сегменте SS
+         SSINT   [смещение] // адресует int в сегменте SS
+         SSDWORD [смещение] // адресует dword в сегменте SS
+         SSLONG  [смещение] // адресует long в сегменте SS
+         SSFLOAT [смещение] // адресует float в сегменте SS
+
+             // адресация в дополнительном сегменте данных
+         ESBYTE  [смещение] // адресует байт в сегменте ES
+         ESWORD  [смещение] // адресует слово в сегменте ES
+         ESCHAR  [смещение] // адресует char в сегменте ES
+         ESINT   [смещение] // адресует int в сегменте ES
+         ESDWORD [смещение] // адресует dword в сегменте ES
+         ESLONG  [смещение] // адресует long в сегменте ES
+         ESFLOAT [смещение] // адресует float в сегменте ES
+
+             // адресация в дополнительном сегменте 2 (80386) +
+         FSBYTE  [смещение] // адресует байт в сегменте FS
+         FSWORD  [смещение] // адресует слово в сегменте FS
+         FSCHAR  [смещение] // адресует char в сегменте FS
+         FSINT   [смещение] // адресует int в сегменте FS
+         FSDWORD [смещение] // адресует dword в сегменте FS
+         FSLONG  [смещение] // адресует long в сегменте FS
+         FSFLOAT [смещение] // адресует float в сегменте FS
+
+             // адресация в дополнительном сегменте 3 (80386) +
+         GSBYTE  [смещение] // адресуют байт в сегменте GS
+         GSWORD  [смещение] // адресуют слово в сегменте GS
+         GSCHAR  [смещение] // адресуют char в сегменте GS
+         GSINT   [смещение] // адресуют int в сегменте GS
+         GSDWORD [смещение] // адресуют dword в сегменте GS
+         GSLONG  [смещение] // адресуют long в сегменте GS
+         GSFLOAT [смещение] // адресует float в сегменте GS
+
+  Примеры:
+     Загрузить в AL байт из ячейки с шестнадцатеричным адресом 0000:0417
+                 ES = 0x0000;
+                 AL = ESBYTE [0x417];
+
+     Переместить слово из ячейки с шестнадцатеричным адресом 2233:4455
+     в ячейку с шестнадцатеричным адресом A000:0002
+                 $PUSH DS
+                 DS = 0x2233;
+                 ES = 0xA000;
+                 ESWORD [0x0002] = DSWORD [0x4455];
+                 $POP DS
+
+     Сохранить вычисленное значение выражения X + 2, имеющее
+     тип int в ячейке с шестнадцатеричным адресом FFFF:1234
+                 ES = 0xFFFF;
+                 ESINT [0x1234] = X + 2;
+
+     Сохранить BX в сегменте стека по смещению 42:
+                 SSWORD [42] = BX;
+Return to contents.
+
+
+
+8. Работа с блоками данных.
+
+  8.1 Структуры.
+
+    8.1.1 Что такое структуры.
+
+
+        Структура позволяет объединить в одном объекте совокупность значений,
+    которые могут иметь различные типы.
+Return to contents.
+
+
+
+    8.1.2 Синтаксис.
+
+
+    struct [<тег>] { <список-объявлений-элементов> }
+      <описатель>[,<описатель>...];
+    struct <тег> <описатель> [,<описатель>];
+
+        Объявление структуры начинается с ключевого слова struct и имеет две
+    формы записи.
+
+        В первой форме типы и имена элементов структуры специфицируются в
+    списке-объявлений-элементов. Необязательный в данном случае тег - это
+    идентификатор, который именует структурный тип, определенный данным
+    списком объявлений элементов. описатель специфицирует либо переменную
+    структурного типа, либо массив структур данного типа.
+
+        Вторая синтаксическая форма объявления использует тег структуры для
+    ссылки на структурный тип, определенный где-то в другом месте программы.
+
+        Список объявлений элементов представляет собой последовательность из
+    одной или более объявлений переменных. Каждая переменная, объявленная в
+    этом списке, называется элементом структуры.
+
+        Элементы структуры запоминаются в памяти последовательно в том
+    порядке, в котором они объявляются. Выравнивание элементов внутри
+    структуры по умолчанию не производится. Но существует опция, включение
+    которой в командную строку позволяет иметь выравнивание и внутри
+    структуры. Сама структура выравнивается на четный адрес если включено
+    выравнивание.
+
+      Примеры объявлений структур:
+
+    struct test
+    {
+      int a;
+      char b[8];
+      long c;
+    } rr, ff[4];
+
+        В этом примере объявлены структура с именем rr и массив из 4 структур
+    с именем ff. Всему набору переменных присвоено название (тег) test. Этот
+    тег можно использовать для объявления других структур. Например:
+
+   struct test dd;
+
+        Здесь объявлена структура с именем dd, имеющая набор элементов
+    описанных в теге test.
+
+        При объявлении структур с ранее объявленным тегом ключевое слово
+   struct можно не писать. Т.е можно написать вот так:
+
+      test dd;
+Return to contents.
+
+
+
+    8.1.3 Инициализация структур при объявлении.
+
+
+        После объявления структуры ее элементы могут принимать произвольные
+    значения. Что бы этого не было надо структуры проинициализировать.
+    Инициализировать структуры при их объявлении можно только глобальные. C--
+    поддерживает несколько способов инициализации структур при их объявлении:
+
+      1. Одним значением:
+
+       struct test dd=2;
+
+    В этом примере всем элементам структуры dd присваивается значение 2.
+
+      2. Массивом значений:
+
+       struct test dd={1,2,,6};
+
+    В этом примере первому элементу структуры dd присваивается значение 1,
+    второму - 2, четвертому - 6. Пропущенным и не доинициализированным
+    значениям будет присвоено 0 значение.
+
+      3. Командой FROM:
+
+       struct test dd=FROM "file.dat";
+
+    В этом примере на место где расположена структура dd при компиляции будет
+    загружено содержимое файла . Если размер файла больше чем размер
+    структуры, то лишние байты будут загружены в код программы, но они не
+    будут востребованы. Если размер файла меньше чем размер структуры, то
+    недостающие байты структуры будут заполнены нулями.
+
+      4. Командой EXTRACT:
+
+       struct test dd=EXTRACT "file.dat", 24, 10;
+
+    В этом примере на место где расположена структура dd при компиляции будет
+    загружен фрагмент из файла file.dat длиной 10 байт со смещения 24.
+    Недостающие байты будут заполнены нулями.
+Return to contents.
+
+
+
+    8.1.4 Инициализация структуры при выполнении программы.
+
+
+        При выполнении программы, кроме присвоения каждому элементу структуры
+    значения, можно проинициализировать всю структуру присвоением ей числа или
+    переменной. Примеры:
+
+    void proc()
+    struct test aa[5],rr;
+    int i;
+    {
+      aa[0]=0x12345678;
+      aa[i]=int 0x12345678;
+      aa=long 0x12345678;
+      rr=i;
+
+    В первом примере память, занимаемая первой структурой массива из 5
+    структур, будет заполнена байтом 0x78 (по умолчанию).
+
+    Во втором примере память, занимаемая (i+1)-вой структурой массива из 5
+    структур, будет заполнена словом 0x5678.
+
+    В третьем примере память, занимаемая всем массивом из 5 структур, будет
+    заполнена длинным словом 0x12345678.
+
+    В четвертом примере память, занимаемая структурой rr, будет заполнена
+    содержимым переменной i.
+
+        Можно также копировать содержимое одной структуры в другую. Например:
+
+      rr=aa[2];
+
+    Будет скопировано содержимое третьей структуры массива структур aa в
+    структуру rr.
+Return to contents.
+
+
+
+    8.1.5 Операции с элементами структур.
+
+
+        С элементами структур можно выполнять все те операции, которые
+    доступны для переменных соответствующего типа. Например:  Объявлена
+    структура:
+
+    struct test
+    {
+      int a;
+      char b[8];
+      long c;
+    } rr[3];
+    Пример допустимого синтаксиса:
+        rr.a = rr.b[i] * rr[1].c + i ;
+
+    Примечание:
+        При операциях с элементами массива структур и с индексированными
+    элементами, в которых в качестве индекса или номера структуры используется
+    переменная, компилятор может использовать регистры SI и DI, а в некоторых
+    ситуациях (например:  rr[i].b[j] >< rr[i+1].b[j+2] ) будет задействован и
+    регистр DX.
+
+        Для отдельных элементов структуры, можно получать их адрес, размер
+    и смещение в теге структуры. Вот пример:
+
+    struct AA       //объявление тега структуры
+    {
+      word a[3];    // первый элемент структуры
+      char b;       // второй элемент структуры
+      long c;       // третий элемент структуры
+    };
+
+    struct BB	//тег второй структуры
+    {
+      word aa;	// первый элемент
+      AA bb;	// второй элемент - вложенная структура
+    }ss;		// объявляем структуру с тегом BB
+
+    void proc()
+    {
+      AX=#ss.bb.b; // получить адрес элемента b структуры bb в структуре ss
+      AX=#BB.bb.b; // получить смещение этого же элемента в теге BB
+      AX=sizeof(ss.bb);	// получить размер элемента bb в структуре ss
+      AX=sizeof(BB.bb);	// получить размер элемента bb в теге BB
+    }
+Return to contents.
+
+
+
+    8.1.6 Вложенные структуры.
+
+
+        При объявлении тегов структур можно использовать теги других,
+    объявленных ранее структур. Пример вложенных структур:
+
+    struct RGB
+    {
+      byte Red;
+      byte Green;
+      byte Blue;
+      byte Reserved;
+    };
+
+    struct BMPINFO
+    {
+      struct BMPHEADER header; //описание этой структуры пропущено
+      struct RGB color[256];
+    }info;
+
+        Предположим Вам нужно получить содержимое переменной Red десятого
+    элемента color. Это можно будет записать так:
+
+      AL=info.color[10].Red;
+
+        Но существует одно ограничение использования вложенных структур в C--.
+    Это невозможность использования переменной в качестве индекса более одного
+    раза при обращении к многоэкземплярным структурам. Поясним это на примере:
+
+    struct ABC
+    {
+      int a;
+      int b;
+      int c;
+    };
+
+    struct
+    {
+      struct ABC first[4];  //4 экземпляра структуры ABC
+      int d;
+    }second[4];
+
+    int i,j;
+
+    void proc()
+    {
+      AX=second[i].first[j].a; //такая запись вызовет сообщение об ошибка, так
+                               //как переменная использовалась в двух местах
+      AX=second[2].first[j].a; //а этот синтаксис допустим.
+      AX=second[i].first[3].a;
+    }
+Return to contents.
+
+
+
+    8.1.7 Отображение тега структуры на блок памяти.
+
+
+        Отображение тега структуры на блок памяти является альтернативой
+    указателям на структуры.
+
+        Альтернативный способ использования указателей на структуры позволит
+    Вам самим выбрать регистр, в котором будет хранится адрес структуры и
+    самим следить за его сохранностью и по мере необходимости восстанавливать
+    его содержимое.
+
+        Объяснить, как использовать отображение тега структуры на память,
+    наверное, будет проще на примере:
+
+    struct AA       //объявление тега структуры
+    {
+      word a[3];    // первый элемент структуры
+      char b;       // второй элемент структуры
+      long c;       // третий элемент структуры
+    };
+
+    byte buf[256];  //блок памяти, на который будет отображен тег структуры
+
+    void proc1()
+    {
+     ...
+     proc2 ( #buf );  // вызов процедуры с передачей ей в качестве параметра
+                      // адреса блока памяти
+     ...
+    }
+
+    long proc2 (unsigned int pointer_to_mem)
+    {
+    int i;
+      BX=pointer_to_mem;  // в BX загрузим адрес блока памяти
+      FOR(i=0; i<3; i++){ // в массив элемента a записать -1
+        BX.AA.a[i]=-1;
+      }
+      BX.AA.b=0;
+      ES:BX.AA.c=EAX;
+      return BX.AA.c;  // вернуть содержимое элемента c
+    }
+
+        В 16-битном режиме для хранения адреса структуры можно использовать
+    регистры: BX,DI,SI,BP. Но лучше для этого использовать регистр BX.
+    Регистры DI и SI может использовать компилятор при вычислении адреса
+    многоэлементных объектов. Регистр BP компилятор использует для работы с
+    локальными и параметрическими переменными. В 32-битном режиме можно
+    использовать любой кроме ESP и EBP регистр, а регистры EDI и ESI надо
+    использовать осторожно.
+Return to contents.
+
+
+
+    8.1.8 Битовые поля структур.
+
+
+        Битовые поля структур используются для экономии памяти, поскольку
+    позволяют плотно упаковать значения, и для организации удобного доступа к
+    регистрам внешних устройств, в которых различные биты могут иметь
+    самостоятельное функциональное назначение.
+
+        Объявление битового поля имеет следующий синтаксис:
+
+    <тип> [<идентификатор>]:<константа>;
+
+    или на примере:
+
+    int var:5;  //объявление битового поля размером 5 бит с именем var
+
+        Битовое поле состоит из некоторого числа битов, которое задается
+    числовым выражением константа. Его значение должно быть целым
+    положительным числом и его значение не должно превышать числа разрядов,
+    соответствующие типу определяемого битового поля. В C-- битовые поля
+    могут содержать только без знаковые значения. Нельзя использовать массивы
+    битовых полей, указатели на битовые поля.
+
+        идентификатор именует битовое поле. Его наличие необязательно.
+    Неименованное битовое поле означает пропуск соответствующего числа битов
+    перед размещением следующего элемента структуры. Неименованное битовое
+    поле, для которого указан нулевой размер, имеет специальное назначение:
+    оно гарантирует, что память для следующего битового поля будет начинаться
+    на границе того типа, который задан для неименованного битового поля.
+    Т.е.  будет произведено выравнивание битового поля на 8/16/32 бита.
+
+        В C-- все битовые поля упаковываются одно за другим независимо от
+    границ типа идентификаторов. Если последующее поле не является битовым
+    полем, то оставшиеся до границы байта биты не будут использованы.
+    Максимальный размер битового поля равен 32 бита для типа dword/long, 16
+    бит для типа word/int и 8 бит для типа byte/char. Битовые поля можно
+    объединять, т.е. использовать их в операторе union. sizeof
+    примененный к битовому полю вернет размер этого поля в битах. При
+    использовании битового поля, его содержимое будет расширятся в регистр
+    как без знаковое целое число.
+Return to contents.
+
+
+
+  8.2 Объединения.
+
+
+      Объединения позволяют в разные моменты времени хранить в одном объекте
+  значения различного типа.
+
+      Память, которая выделяется под объединение, определяется размером
+  наиболее длинного из элементов объединения. Все элементы объединения
+  размещаются в одной и той же области памяти с одного и того же адреса.
+  Значение текущего элемента объединения теряется, когда другому элементу
+  объединения присваивается значение.
+
+      В C-- реализованы так называемые анонимные объединения. Т.е.
+  объединениям не присваивается имя, а обращение к элементам объединения
+  происходит как к обычной переменной. Пример:
+
+  union
+  {
+    dword regEAX;
+    word  regAX;
+    byte  regAL;
+  };  // объявили, что 3 переменные расположены по одному и тому же
+      // физическому адресу
+
+  void test()
+  {
+  	regEAX = 0x2C;
+  	BL = regAL;	//в регистре BL окажется значение 0x2C
+  }
+
+      Объединять можно переменные различных типов, массивы, строковые
+  переменные и структуры. Объединения могут быть глобальными и локальными, а
+  также располагаться внутри структур (пока в объединениях внутри структур
+  нельзя использовать структуры). Глобальные объединения могут быть
+  инициализированными и неинициализированными. Чтобы получить
+  инициализированное объединение достаточно проинициализировать лишь первый
+  элемент объединения. Если же первый элемент объединения не инициализирован,
+  а следующие элементы инициализированы, то это вызовет сообщение компилятора
+  об ошибке.
+Return to contents.
+
+
+
+  8.3 Команды 'FROM' и 'EXTRACT'.
+
+
+      В C-- есть очень оригинальные команды, которых нет в других языках. Это
+  FROM и EXTRACT.
+
+      Команда FROM имеет синтаксис:
+
+  <тип_переменной> <имя_переменной> = FROM <имя_файла>;
+
+      Встретив эту команду при компиляции, компилятор загрузит в выходной
+  файл содержимое файла имя_файла, а имя_переменной будет идентификатором
+  начала загруженного кода. Вот пример использования этой команды из файла
+  tinydraw.c--:
+
+  byte palette[PALSIZE] = FROM "TINYDRAW.PAL";  // buffer for palette
+
+     Команда EXTRACT имеет синтаксис:
+
+  <тип_переменной> <имя_переменной> = EXTRACT <имя_файла>, <начало>, <длина>;
+
+      Встретив эту команду при компиляции, компилятор загрузит в выходной
+  файл из файла имя_файла число байт равное длина со смещения начало, а
+  имя_переменной будет идентификатором начала загруженного кода. Вот пример
+  использования этой команды:
+
+  byte LIT128 = EXTRACT "8X16.FNT", 16*128, 16;
+  byte LIT130 = EXTRACT "8X16.FNT", 16*130, 16;
+Return to contents.
+
+
+
+9. Операторы.
+
+  9.1 Условные инструкции.
+
+
+      Условные инструкции, при помощи которых осуществляется ветвление, такие
+  же как в C.
+
+      C-- имеет две инструкции ветвления. if и IF.
+
+      if делает близкий условный переход, а IF делает короткий
+  (8-разрядный) условный переход. IF выполняется быстрее и может экономить
+  до 3 байт в размере кода, но может осуществлять переходы только в пределах
+  127 байтов кода.
+
+      Условные инструкции, как и в C, могут сопровождаться, как одиночной
+  командой, так и блоком из нескольких команд, заключенных в фигурные скобки
+  { и }. Условные инструкции имеют те же ограничения, что и условные
+  выражения.
+
+      Если за инструкцией IF следует больше чем 127 байтов кода, транслятор
+  выдаст следующее сообщение об ошибке:
+
+          IF jump distance too far, use if.
+
+  Это можно просто исправить, заменив в этом месте инструкцию IF на if.
+
+      Команды else и ELSE используются точно так же, как в языке C.
+  Отличие их в том, что ELSE имеет ограничение адреса перехода 127 байт,
+  такое же как IF. else генерирует код на 1 байт длиннее, чем ELSE.
+
+      Команды IF и else, а также if и ELSE могут свободно смешиваться
+  как в следующем примере:
+
+          if( x == 2 )
+              WRITESTR("Two");
+          ELSE{ WRITESTR("not two.");
+                printmorestuff();
+              }
+
+      Если за инструкцией ELSE следует больше чем 127 байтов кода,
+  транслятор выдаст следующее сообщение об ошибке:
+
+          ELSE jump distance too far, use else.
+
+      Это можно просто исправить, заменив в этом месте инструкцию ELSE на
+  else.
+Return to contents.
+
+
+
+  9.2 Циклы do{} while.
+
+
+      В таком цикле блок кода, составляющий тело цикла, будет повторяться,
+  пока условное выражение имеет значение истинно.
+
+      Истинность условного выражения проверяется после выполнения тела  цикла,
+  поэтому блок кода будет выполнен, по крайней мере, один раз.
+
+   Пример do {} while цикла, в котором тело будет исполнено пять раз:
+
+           count = 0;
+           do {
+              count++;
+              WRITEWORD(count);
+              WRITELN();
+              } while (count < 5);
+
+  Условное выражение в do {} while инструкции должно соответствовать тем же
+  правилам, что и в инструкциях IF и if.
+Return to contents.
+
+
+
+  9.3 Циклы loop, LOOPNZ, loopnz.
+
+
+      Циклы loop повторяют блок кода, пока определенная переменная или
+  регистр, выполняющие роль счетчика цикла, содержат значение, отличное от
+  нуля. В конце выполнения блока кода, составляющего тело цикла, указанная
+  переменная или регистр - уменьшается на 1, а затем проверяется на равенство
+  нулю. Если переменная (или регистр) не равна нулю, тело цикла будет
+  выполнено снова, и процесс повторится.
+
+      Пример использования цикла loop в котором в качестве счетчика цикла
+  использована переменная:
+
+          count = 5;
+          loop( count )
+              {WRITEWORD(count);
+              WRITELN();
+              }
+
+      Наибольший эффект дает использование регистра CX для циклов с небольшим
+  телом, поскольку в этом случае компилятором генерируется цикл с применением
+  машинной команды LOOP.
+
+      Если перед стартом счетчик циклов содержит нулевое значение, команды
+  тела цикла будут выполнены максимальное число раз для диапазона переменной
+  (256 раз для 8-битного счетчика (переменной типа byte или char), 65536 для
+  16-битного счетчика (переменной типа word или int), и 4294967296 для
+  32-битного счетчика (переменной типа dword или long).
+
+   В следующем примере цикл будет выполнен 256 раз:
+
+           BH = 0;
+           loop (BH)
+              {
+              }
+
+      Если в команде не указано никакого счетчика цикла, цикл будет
+  продолжаться бесконечно.
+
+      Следующий пример будет непрерывно выводить символ звездочки (*) на
+  экран:
+
+          loop()
+              WRITE('*');
+
+      Программист, если хочет, может использовать или изменять значение
+  переменной счетчика цикла внутри цикла.
+
+      Например, следующий цикл выполнится только 3 раза:
+
+           CX = 1000;
+           loop( CX )
+              {
+              IF( CX > 3 )
+                  CX = 3;
+              }
+
+      Цикл можно также прервать оператором разрыва BREAK или break. Вот
+  тот же пример с использованием BREAK:
+
+           CX = 1000;
+           loop( CX )
+              {
+              IF( CX > 3 )
+                  BREAK;
+              }
+
+      Циклы LOOPNZ/loopnz отличаются от цикла loop, тем, что перед входом
+  в цикл проверяется равенство нулю аргумента цикла. Если аргумент равен
+  нулю, то тело цикла ни разу не выполнится (в цикле loop в этом случае
+  тело цикла выполнится максимальное число раз). Цикл LOOPNZ получается
+  максимально эффективным при оптимизации на размер кода, если в качестве
+  параметра-счетчика используется регистр CX/ECX. При этом компилятор
+  использует ассемблерные инструкции JCXZ/JECXZ и LOOP.
+Return to contents.
+
+
+
+  9.4 Цикл while, WHILE.
+
+
+       Синтаксис:
+    while(<выражение>)
+         <оператор>
+
+      Цикл выполняется до тех пор, пока значение выражения не станет
+  ложным. Вначале вычисляется выражение. Если выражение изначально ложно,
+  то тело оператора while вообще не выполняется и управление сразу
+  передается на следующий оператор программы.
+
+      Цикл WHILE аналогичен циклу while, но при этом генерируется код на
+  3 байта короче. Размер сгенерированного кода в цикле WHILE должен быть
+  меньше 127 байт.
+
+    Примеры:
+  	while ( i < 20 ){
+  		WRITEWORD(i);
+  		i++;
+  	}
+
+  	WHILE (i < 20 ) @WRITEWORD(i);	//цикл либо будет бесконечным либо не
+                                          //выполнится ни разу
+Return to contents.
+
+
+
+  9.5 Цикл for, FOR.
+
+
+       Синтаксис:
+    for ([<начальное выражение>]; [<условие>]; [<приращение>])
+      <оператор>
+
+      Цикл for выполняется до тех пор, пока значение условия не станет
+  ложным. Если условие изначально ложно, то тело оператора for вообще не
+  выполняется и управление сразу передается на следующий оператор программы.
+  Начальное выражение и приращение обычно используются для инициализации
+  и модификации параметров цикла.
+
+      Первым шагом при выполнении for является вычисление начального
+  выражения, если оно имеется. Затем вычисляется условие и производится
+  его оценка следующим образом:
+
+      1) Если условие истинно, то выполняется тело оператора. Затем
+  вычисляется приращение (если оно есть), и процесс повторяется.
+
+      2) Если условие опущено, то его значение принимается за истину. В
+  этом случае цикл for представляет бесконечный цикл, который может
+  завершиться только при выполнении в его теле операторов break, goto,
+  return.
+
+      3) Если условие ложно, то выполнение цикла for заканчивается и
+  управление передается следующему оператору.
+
+      Цикл FOR аналогичен циклу for, но при этом генерируется код на 3
+  байта короче. Размер сгенерированного кода в цикле FOR должен быть меньше
+  127 байт.
+
+    Примеры:
+  	for(i=0;i<5;i++){
+  		WRITESTR("СТРОКА ");
+  		WRITEWORD(i);
+  		WRITELN();
+  	}
+
+      Число начальных выражений и число приращений не ограничено. Каждый
+  оператор в начальных выражениях и приращениях должен разделяться
+  запятой. Пример:
+
+        for ( a=1, b=2 ; a<5 ; a++, b+=a ) {...
+
+      Также есть возможность логического объединения условий. Объединять
+  можно до 32 условий. Каждое объединяемое условие должно быть заключено в
+  скобки. Пример:
+
+        for ( a=0 ; (a>=0) && (a<10) ; a++ ){...
+Return to contents.
+
+
+
+  9.6 Оператор переключатель switch.
+
+
+      Синтаксис:
+    switch(<выражение>){
+      case <константа>:
+        <оператор>
+  	...
+      case <константа>:
+        <оператор>
+  	...
+      ...
+      default:
+        <оператор>
+    }
+      Оператор переключатель switch предназначен для выбора одного из
+  нескольких альтернативных путей выполнения программы. Выполнение начинается
+  с вычисления значения выражения. После этого управление передается одному
+  из операторов тела переключателя. В теле переключателя содержатся
+  конструкции: case константа:, которые синтаксически представляют собой
+  метки операторов. Оператор, получающий управление, - это тот оператор,
+  значение константы которого совпадают со значением выражения
+  переключателя. Значение константы должно быть уникальным.
+
+      Выполнение тела оператора-переключателя switch начинается с выбранного
+  таким образом оператора, и продолжается до конца тела или до тех пор, пока
+  какой-либо оператор не передаст управление за пределы тела.
+
+    Оператор, следующий за ключевым словом default, выполняется, если ни
+  одна из констант не равна значению выражения. Если default опущено, то
+  ни один оператор в теле переключателя не выполняется, и управление
+  передается на оператор, следующий за switch.
+
+      Для выхода из тела переключателя обычно используется оператор разрыва
+  break (BREAK).
+
+    Пример:
+    switch (i){
+      case 'A':
+        WRITE(i);
+        i++;
+        BREAK;
+      case 32:
+        WRITE('_');
+        i++;
+        BREAK;
+      default:
+        WRITE('i');
+    }
+
+      Оператор switch сейчас в компиляторе может реализовываться трем
+  способами: двухтабличным, табличным и методом последовательных проверок.
+
+      Табличный метод является самым быстрым, а при большом числе операторов
+  case и при незначительной разнице между максимальным и минимальным
+  значениями case он еще может быть и более компактным. Но у него есть и
+  недостатки: в 16-битном режиме компилятор всегда использует регистр BX, а в
+  32-битном режиме, если операндом switch является регистр, то его значение
+  будет разрушено.
+
+      В методе последовательных проверок блок сравнений находится в начале
+  тела оператора switch, это позволяет избавиться от 1-2 лишних jmp. Но
+  компилятор не может определить, какой тип перехода использовать при
+  проверке значений case. Это будет Вашей заботой. Если размер кода от
+  начала тела оператора switch до места расположения оператора case
+  меньше 128 байт, можно использовать короткий переход. В этом случае Вы
+  можете указать оператор CASE, что приведет к генерации более компактного
+  кода. Компилятор в предупреждениях будет Вам подсказывать о возможности
+  использования операторов CASE. Использование оператора CASE в случаях,
+  когда размер блока кода более 128 байт приведет к выдаче компилятором
+  сообщения об ошибке.
+
+     При двухтабличном методе создаются две таблицы - таблица адресов входа в
+  тело оператора switch/SWITCH и таблица значений case. Генерируется
+  процедура сравнения входного значения со значениями во второй таблице. Если
+  есть совпадение, то делается переход по адресу из второй таблицы. Этот
+  метод является самым медленным, но при большом числе значений case (более
+  15) он становится самым компактным.
+
+      При оптимизации кода на размер, компилятор предварительно вычисляет
+  размер кода, который может быть получен всеми методами и реализует самый
+  компактный. При оптимизации на скорость преимущество отдается табличному
+  методу, если размер таблицы получается не слишком большим.
+
+      Для оператора switch введена также и короткая его форма - SWITCH.
+  Ее можно применять в случае, если размер блока кода между началом тела
+  оператора и оператором default (если он отсутствует, то концом тела
+  оператора switch) меньше 128 байт. О возможности использования короткой
+  формы компилятор будет сообщать в предупреждениях.
+
+      Для оператора case/CASE, который может использоваться только в теле
+  блока оператора switch/SWITCH, можно указывать диапазон значений. Сначала
+  надо указывать меньшее значение, затем после многоточия большее. Пример:
+
+  switch(AX){
+    case 1...5:
+      WRITESTR("Range AX from 1 to 5");
+      BREAK;
+  };
+
+      Раньше Вам бы пришлось писать более громоздкую конструкцию:
+
+  switch(AX){
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+      WRITESTR("Range AX from 1 to 5");
+      BREAK;
+  };
+
+      Кроме того, что новый формат записи более компактен и более читабелен,
+  но еще при этом компилятор создает более компактный и быстрый код.
+Return to contents.
+
+
+
+  9.7 Оператор перехода goto, GOTO.
+
+
+       Синтаксис:
+       goto <метка>;
+  	.
+  	.
+  	.
+  <метка>:
+
+      Оператор перехода goto передает управление на оператор помеченный
+  меткой. Аналогом в ассемблере оператору goto является команда jmp near.
+  Аналогом в ассемблере оператору GOTO является команда jmp short.
+Return to contents.
+
+
+
+  9.8 Оператор разрыва break, BREAK.
+
+
+      Оператор разрыва break прерывает выполнение операторов do-while,
+  for, switch, while, loop, loopnz, LOOPNZ. Он может содержаться
+  только в теле этих операторов. Управление передается оператору, следующему
+  за прерванным циклом.
+
+      Оператор BREAK аналогичен break, но при этом генерируется код на 1
+  байт короче. Размер сгенерированного кода от места где применяется BREAK
+  до конца цикла должен быть меньше 127 байт.
+
+    Примеры:
+  	FOR (i=0; ; i++){
+  		FOR(j=0; j < WIDTH; j++){
+  			IF(i==5)BREAK;
+  		}
+  		IF(i==10)BREAK;
+  	}
+Return to contents.
+
+
+
+  9.9 Оператор продолжения continue, CONTINUE.
+
+
+      Оператор продолжения continue передает управление на следующую
+  итерацию в циклах do-while, for, while, loop, loopnz. В циклах
+  do-while, while, loop следующая итерация начинается с вычисления
+  условного выражения. Для цикла for следующая итерация начинается с
+  вычисления выражения приращения, а затем происходит вычисление условного
+  выражения.
+
+    Оператор CONTINUE аналогичен continue, но при этом генерируется код на
+  1 байт короче. Размер сгенерированного кода от места где применяется
+  CONTINUE до начала итерации должен быть меньше 127 байт.
+Return to contents.
+
+
+
+  9.10 Логическое объединение условий.
+
+
+      Существует возможность логического объединения сравнений в условиях
+  IF и if, циклах do{}while, while{}, WHILE{}, for{} и FOR{}.
+  Каждое сравнение при их логическом объединении должно быть заключено в
+  скобки.  Объединять можно не более 32 сравнений.
+
+      В отличие от C в C-- анализ логических объединений происходит слева
+  направо и все лишние скобки будут восприняты компилятором как ошибочные.
+  Это несколько снижает гибкость и возможности применения этих объединений,
+  но такова традиция и философия, заложенная в C--.
+
+      Пример:
+
+  	   if ( (a>3) && (b>4) || (c<8) ){
+
+  Т.е. если произвести расшифровку этого условия, то получится следующее:
+  условие выполнится если a>3 и b>4 или a>3 и c<8.
+Return to contents.
+
+
+
+  9.11 Переход через циклы.
+
+
+     Для операторов BREAK, break, CONTINUE, continue введена
+  поддержка числового параметра, определяющего, сколько циклов надо
+  пропустить, прежде чем будет выполнен этот оператор. Например, мы имеем три
+  вложенных цикла:
+
+  do{
+     loop(CX){
+        for(BX=0;BX<10;BX++){
+  	 break;	  //стандартный оператор
+  	 break 0; //break с параметром - пропустить 0 циклов
+  	 break 1; //break с параметром - пропустить 1 цикл
+  	 break 2; //break с параметром - пропустить 2 цикла
+        }
+  LABL0:
+     }
+  LABL1:
+  }while (DX!=0);
+  LABL2:
+
+      В третьем цикле находится группа различных вариантов оператора break.
+  Первым стоит стандартный оператор break, при выполнении которого
+  управление будет передаваться за пределы третьего цикла - на метку LABL0.
+  Вторым идет оператор break 0, при выполнении которого будет пропущено 0
+  циклов и управление будет передано опять же на метку LABL0. Таким
+  образом, запись break и break 0 являются синонимами. Третьим идет
+  оператор break 1, при выполнении которого будет пропущен один цикл и
+  управление будет передано за пределы второго цикла на метку LABL1. Ну и
+  наконец, последним идет оператор break 2, при выполнении которого
+  компилятор пропустит два цикла и передаст управление за пределы третьего,
+  на метку LABL2. Метки в этом примере проставлены для удобства объяснения.
+  Ну и я надеюсь, Вам понятно, что значение параметра не может превышать
+  числа циклов находящихся перед текущим. Так для одиночного цикла этот
+  параметр может принимать максимальное и единственное значение - 0.
+Return to contents.
+
+
+
+  9.12 Инвертирование флага проверки условий.
+
+
+      Инвертирование флага проверки условий в операциях сравнения if/IF
+  for/FOR while/WHILE происходит с помощью символа ! - not.
+
+     Выражени
+
+    IF ( NOTCARRYFLAG )...   и  IF ( ! CARRYFLAG )...
+    IF ( proc() == 0 )...    и IF ( ! proc() ) ...
+
+  являются синонимами.
+Return to contents.
+
+
+
+  9.13 Вычисление выражения, а затем проверка условия.
+
+
+      В операциях сравнения в левом операнде теперь допустимо использовать
+  вычисления выражения с присваиванием и операции инкремента, декремента.
+  Например:
+
+    IF (i=a+2 != 0 )...
+    IF ( i++ )...
+    IF ( a-- )...
+    IF ( i+=4 == 0 )...
+
+      Во всех этих примерах сначала произойдет вычисление выражения в левой
+  части операции сравнения, а потом будет произведено сравнение результата с
+  правой частью выражения сравнения.
+Return to contents.
+
+
+
+  9.14 Проверка битов при операции сравнения.
+
+
+      Если в левой части выражения сравнения написано: BX & 5, то при
+  вычислении выражения содержимое регистра BX будет изменено инструкцией
+  and. Но иногда возникает необходимость в проверке битов без изменения
+  содержимого регистра BX. Для этих целей надо использовать инструкцию
+  test. Как же указать компилятору, в каких ситуациях использовать
+  инструкцию and, а в каких test? В стандартных языках C для этого
+  используется механизм приоритетов - если выражение заключено в скобки, то
+  производится его вычисление, если нет, то производится проверка. Но C-- не
+  поддерживает приоритетов. Для разрешения этой проблемы в C-- решено
+  использовать непосредственно саму инструкцию test. Вот допустимые
+  варианты синтаксиса:
+
+  IF ( $test AX,5 )
+  IF ( ! $test AX,5)
+  IF ( asm test AX,5)
+  IF ( ! asm { test AX,5 } )
+Return to contents.
+
+
+
+  9.15 Оператор перестановки.
+
+
+      В C-- есть оператор, который не встречается в других языках, это
+  оператор перестановки. Оператор перестановки меняет местами содержимое двух
+  переменных. Символьное обозначение этого оператора ><. Переменные с обеих
+  сторон оператора перестановки должны иметь одинаковый размер, 8 бит и 8
+  бит, 16 бит и 16 бит, или 32 бита и 32 бита.
+
+    Вот некоторые примеры:
+
+      AX >< BX; // сохраняет значение BX в AX и значение AX в BX
+      CH >< BL; // меняет местами содержимое регистров CH и BL
+      dog >< cat; /* меняет местами значения переменной dog и переменной cat*/
+      counter >< CX; // меняет местами значения переменной counter
+                     // и содержимое регистра CX
+
+      Если перестановка осуществляется между двумя 8-разрядными переменными в
+  памяти, будет разрушено содержимое регистра AL. Если перестановка - между
+  двумя 16-разрядными переменными в памяти, будет разрушено содержимое
+  регистра AX. Если перестановка - между двумя 32-разрядными переменными в
+  памяти, будет разрушено содержимое EAX. В любом другом случае, например,
+  между переменной в памяти и регистром, значения всех регистров будут
+  сохранены.
+Return to contents.
+
+
+
+  9.16 Оператор отрицания.
+
+
+      C-- поддерживает быстрый синтаксис смены знака переменной - оператор
+  отрицания. Поставив - (знак минус) перед идентификатором переменной памяти
+  или регистра и ; (точку с запятой) после идентификатора, вы смените знак
+  переменной памяти или регистра.
+
+  Вот некоторые примеры:
+
+           -AX; // результат тот же, что и при 'AX = -AX;' ,но быстрее.
+           -tree; // то же самое, что 'tree = -tree;' ,но быстрее.
+           -BH; // меняет знак BH.
+Return to contents.
+
+
+
+  9.17 Оператор инверсии.
+
+
+      C-- поддерживает быстрый синтаксис выполнения логической инверсии
+  значения переменной - оператор инверсии. Поставив ! (восклицательный знак)
+  перед идентификатором переменной памяти или регистром и ; (точку с
+  запятой) после идентификатора, вы выполните логическую (выполнится
+  ассемблерная команда NOT) инверсию текущего значения переменной. Вот
+  некоторые примеры:
+
+          !AX; // то же самое, что ' AX ^ = 0xFFFF; ' но быстрее.
+          !node; // заменяет значение 'node' его логической инверсией.
+          !CL; // то же самое, что ' CL ^ = 0xFF ' но быстрее.
+Return to contents.
+
+
+
+  9.18 Специальные условные выражения.
+
+
+      C-- поддерживает восемь специальных условных выражений:
+
+           CARRYFLAG
+           NOTCARRYFLAG
+           OVERFLOW
+           NOTOVERFLOW
+           ZEROFLAG
+           NOTZEROFLAG
+           MINUSFLAG
+           PLUSFLAG
+
+      Они могут использоваться вместо любых нормальных условных выражений.
+  Если Вы желаете, например, выполнить блок кода только если установлен флаг
+  переноса, Вам следует использовать следующую последовательность команд:
+
+           IF( CARRYFLAG )
+           {
+           // здесь вы чего-то делаете
+           }
+
+      Если Вы желаете непрерывно выполнять блок кода до тех пор, пока не
+  установится флаг переполнения, Вам следует использовать нечто подобное
+  следующему куску кода:
+
+          do {
+              // здесь вы опять чего-то делаете
+              } while( NOTOVERFLOW );
+Return to contents.
+
+
+
+  9.19 Символ $ - вставляет текущий адрес программы.
+
+
+      Символ $, кроме того, что является признаком последующей ассемблерной
+  инструкции, в языке C--, как и в языке Assembler может указывать текущий
+  адрес (смещение) компилируемой программы. Но в C-- он имел ограниченные
+  возможности. Он мог быть использован лишь как аргумент в операторах
+  GOTO/goto и ассемблерных инструкциях DW/DD/JMP.
+
+      Этот символ может находиться в любом месте вычисляемого числового
+  выражения и может быть применен в любом месте совместно с другими числовыми
+  выражениями.
+
+  Примеры применения:
+
+  DW #main-$	//записать расстояние от процедуры main до текущего места
+  GOTO $+2;	//перейти по адресу на 2 больше, чем текущий адрес
+Return to contents.
+
+
+
+  9.20 Ключевое слово static и оператор ::.
+
+
+      Если перед объявлением глобальной переменной, структуры или процедуры
+  указать слово static, то эти переменная, структура или процедура будут
+  доступны только в том файле, в котором они были объявлены. Т.е. если Вы
+  включите этот файл в другой директивой include, то переменные объявленные
+  во включаемом файле со словом static не будут доступны в основном файле,
+  и Вы можете в основном файле объявить другие переменные с такими же
+  именами.
+
+      Если Вы примените слово static при объявлении локальной переменной в
+  процедуре, то память для этой переменной будет выделена не в стеке, а в
+  области данных процедуры. Но эта переменная будет доступна только внутри
+  процедуры, в которой она была объявлена. Применение static к локальным
+  переменным дает возможность сохранять значение переменной для следующего
+  входа в процедуру.
+
+      Слово static можно применять к любому глобальному объекту
+  (переменной, структуре, процедуре). Для локального использования это слово
+  можно применять только к переменным.
+
+      Если в Вашей программе есть глобальная и локальная переменная с
+  одинаковыми именами, то в процедуре, в которой объявлена эта локальная
+  переменная, Вы не имели доступа к одноименной глобальной переменной.
+  Применив перед именем переменной оператор ::, Вы получите доступ к
+  глобальной переменной.  Пример:
+
+  int var;  //объявляем глобальную переменную
+
+  void proc()
+  int var;  //объявляем локальную переменную с именем уже существующей
+            //глобальной переменной
+  {
+    (E)AX=var;	//имеем доступ только к локальной переменной
+    (E)AX=::var;  //а так можно получить доступ к глобальной переменной
+  }
+Return to contents.
+
+
+
+  9.21 Оператор sizeof.
+
+
+      Операция sizeof определяет размер памяти, который соответствует объекту
+  или типу. Операция sizeof имеет следующий вид:
+
+   sizeof (<имя типа>)
+
+      Результатом операции sizeof является размер памяти в байтах,
+  соответствующий заданному объекту или типу.
+
+      В C-- оператор sizeof можно применять к переменным, регистрам, типам
+  переменных, структурам, процедурам, текстовым строкам и файлам.
+
+      Если операция sizeof применяется к типу структуры, то результатом
+  является размер тега данной структуры.
+
+      Если операция sizeof применяется к текстовой строке, то результатом
+  операции является размер строки плюс завершающий нуль. Например:
+
+   sizeof ("Test")
+
+  результатом этой операции будет число 5. Если Вы напишите такую
+  конструкцию:
+
+  char a="Test";
+
+   sizeof(a)
+
+  то результатом будет 5 - размер памяти, отведенный для переменной a.
+
+      При использовании оператора sizeof с именем структуры вставляет
+  фактический размер памяти, занимаемый структурой. Это особенно важно, если
+  Вы объявили массив структур.
+
+      Оператор sizeof можно применять и к имени определенной ранее
+  процедуры. Результатом будет размер этой процедуры. Но для динамических
+  процедур всегда будет ноль.
+
+      Операцию sizeof можно применять и к файлам. Это бывает очень полезным
+  при использовании оператора FROM, но может применяться и в других случаях.
+  Пример применения оператора sizeof к файлам:
+
+   sizeof ( file "filename.dat" )
+
+  Результатом этой операции будет размер файла "filename.dat".
+Return to contents.
+
+
+
+  9.22 Метки перехода.
+
+
+      Метки перехода применяются для указания начальных точек участков кода,
+  используемых командами перехода встроенного ассемблера и операторами
+  goto/GOTO.
+
+      Имеются два типа меток перехода: глобальные и локальные. Глобальные
+  метки, как следует из названия, это метки, которые видимы из любого места в
+  программе. Локальные метки видны только в пределах своего процедурного
+  блока, и не определены за его пределами.
+
+      Метки определяются идентификатором, оканчивающимися двоеточием. Если
+  идентификатор содержит хотя бы один символ строчных букв (букв нижнего
+  регистра, маленьких букв), это глобальная метка перехода, в противном
+  случае, это локальная метка перехода.
+
+      Глобальные метки перехода не должны использоваться внутри динамических
+  процедур; там можно использовать только локальные метки. Это важно помнить,
+  поскольку, из-за применения такого средства как макрокоманды, динамическая
+  процедура может присутствовать в нескольких местах кода, что будет
+  означать, что метке соответствует больше чем один адрес.
+
+      Метки вне процедур фактически располагаются в области данных программы.
+  Если данные и код находятся в одном сегменте (а именно так организованна
+  программа, написанная на C--), то метки вне процедур становятся простым и
+  эффективным методом для получения расстояний между частями программы. В
+  качестве имен для меток вне процедур могут быть использованы уникальные
+  идентификаторы, в которых можно использовать большие, маленькие и смесь
+  больших и маленьких букв.
+Return to contents.
+
+
+
+10. Ассемблер.
+
+  10.1 Поддержка команд ассемблера.
+
+
+      Встроенный в C-- ассемблер поддерживает все инструкции 8088/8086,
+  80286, 80386, 80486, Pentium, Pentium II и Pentium III процессоров.
+
+      Все инструкции встроенного ассемблера должны начинаться с символа
+  доллара $. Поддерживается также ключевое слово asm, которое являясь
+  синонимом к символу доллара, еще и поддерживает объединение ассемблерных
+  инструкций в блоки.
+Return to contents.
+
+
+
+  10.2 Ключевое слово asm.
+
+
+      Ключевое слово asm является синонимом к $ - префикс ассемблерной
+  команды. После слова asm можно писать блок ассемблерных команд.  Пример:
+
+  	asm {
+  		.
+  		.
+  		push AX
+  labl:
+  		push BX
+  		mov AX,0x1234
+  		jmp short labl
+  		.
+  		.
+  		.
+  	}
+
+    Метки внутри блока ассемблерных команд допустимы.
+Return to contents.
+
+
+
+  10.3 Префикс dup - повторение инструкций DB/DW/DD.
+
+
+      Для ассемблерных инструкции DB, DW, DD введена возможность использовать
+  префикс повторений dup. Применение этого префикса имеет следующий
+  синтаксис:
+
+    $DW NUMREP dup VALTOREP
+
+  NUMREP - число повторов инструкции DW.
+  VALTOREP - величина, которая будет повторена NUMREP раз.
+
+      В отличие от аналога этого префикса из ассемблера повторяемую величину
+  заключать в скобки нельзя.
+Return to contents.
+
+
+
+  10.4 Инструкции процессора Pentium III.
+
+
+      В компилятор добавлена поддержка 19 новых инструкций MMX расширения
+
+  MASKMOVQ   mmx,mmx
+  MOVNTQ     m64,mmx
+  PAVGB      mmx,mmx/m64
+  PAVGW      mmx,mmx/m64
+  PEXTRW     r32,mmx,i8
+  PINSRW     mmx,r32/m16,i8
+  PMAXUB     mmx,mmx/m64
+  PMAXSW     mmx,mmx/m64
+  PMINUB     mmx,mmx/m64
+  PMINSW     mmx,mmx/m64
+  PMOVMSKB   r32,mmx
+  PMULHUW    mmx,mmx/m64
+  PREFETCHT0 mem
+  PREFETCHT1 mem
+  PREFETCHT2 mem
+  PREFETCHNTA mem
+  SFENCE
+  PSADBW     mmx,mmx/m64
+  PSHUFW     mmx,mmx/m64,i8
+
+      и 46 инструкций SSE расширения.
+
+  ADDPS      xmm,m128/xmm
+  ADDSS      xmm,xmm/m32
+  ANDNPS     xmm,xmm/m128
+  ANDPS      xmm,xmm/m128
+  COMISS     xmm,xmm/m32
+  DIVPS      xmm,m128/xmm
+  DIVSS      xmm,xmm/m32
+  MAXPS      xmm,m128/xmm
+  MAXSS      xmm,xmm/m32
+  MINPS      xmm,m128/xmm
+  MINSS      xmm,xmm/m32
+  MULPS      xmm,m128/xmm
+  MULSS      xmm,xmm/m32
+  ORPS       xmm,xmm/m128
+  RCPPS      xmm,xmm/m128
+  RCPSS      xmm,xmm/m32
+  RSQRTPS    xmm,xmm/m128
+  RSQRTSS    xmm,xmm/m32
+  SQRTPS     xmm,m128/xmm
+  SQRTSS     xmm,xmm/m32
+  SUBPS      xmm,m128/xmm
+  SUBSS      xmm,xmm/m32
+  UCOMISS    xmm,xmm/m32
+  UNPCKHPS   xmm,xmm/m128
+  UNPCKLPS   xmm,xmm/m128
+  XORPS      xmm,xmm/m128
+  CMPPS      xmm,xmm/m128,i8
+  CMPSS      xmm,xmm/m32,i8
+  SHUFPS     xmm,xmm/m128,i8
+  CVTPI2PS   xmm,m64/mmx
+  CVTSI2SS   xmm,m32/r32
+  CVTPS2PI   mmx,m128/xmm
+  CVTTPS2PI  mmx,xmm/m128
+  CVTSS2SI   r32,xmm/m128
+  CVTTSS2SI  r32,xmm/m128
+  LDMXCSR    m32
+  STMXCSR    m32
+  MOVHLPS    xmm,xmm
+  MOVLHPS    xmm,xmm
+  MOVMSKPS   r32,xmm
+  MOVNTPS    m128,xmm
+  MOVAPS     m128/xmm,xmm/m128
+  MOVSS      xmm/m32,xmm/m32
+  MOVUPS     xmm/m128,m128/xmm
+  MOVHPS     xmm/m64,m64/xmm
+  MOVLPS     xmm/m64,m64/xmm
+
+      Многие из этих инструкций могут использовать в качестве операнда
+  64-битные и 128-битные ячейки памяти. Компилятор C-- сейчас может работать
+  только с 32-битными переменными. Поэтому для инструкций использующих в
+  качестве операнда ячейки памяти размером больше 32-бит можно использовать
+  переменные любых типов. Компилятор не будет выдавать на это сообщений об
+  ошибке, будет использован адрес этой переменной, а сама инструкция будет
+  использовать нужное ей число битов памяти, начиная с адреса указанной
+  переменной. Например:
+
+      Для инструкции movaps один из операндов может быть 128-битной
+  ячейкой памяти. Для этой инструкции допустимы следующий синтаксис:
+
+  byte  var8_128[16];
+  word  var16_128[8];
+  dword var32_128[4];
+
+  void proc()
+  {
+  asm{
+    movaps var8_128,xmm0 //в массив из 16 байт будет записано содержимое XMM0
+    movaps xmm1,var16_128	//в XMM1 будет записано содержимое 8 слов
+    movaps var32_128,xmm1 //в массив из 4 двойных слов будет записано XMM1
+  }
+  }
+Return to contents.
+
+
+
+11. Процедуры.
+
+  11.1 Типы процедур, функций и макрокоманд.
+
+
+      Сейчас C-- поддерживает 4 типа вызова процедур: cdecl, pascal, stdcall
+  и fastcall. Вот краткие характеристики этих типов вызовов процедур:
+
+  cdecl  Этот тип вызова процедур является по умолчанию для языка С. Он
+  характеризуется тем, что параметры процедуры передаются в порядке обратном
+  их записи. Очистка стека от параметров производится после завершения работы
+  процедуры. Этот способ вызова процедур очень удобен для процедур с
+  переменным числом параметров.
+
+  pascal  Этот тип вызова предполагает, что параметры передаются в том
+  порядке, в котором они записаны в программе. Освобождение стека от
+  параметров производит сама вызываемая процедура. Этот тип вызова является
+  более компактным, чем cdecl.
+
+  stdcall  Этот тип вызова является гибридом первых двух. Параметры
+  передаются процедуре в порядке обратном, тому в котором они записаны в
+  программе. Освобождение стека от параметров производится в самой вызываемой
+  процедуре.
+
+  fastcall  Этот тип вызова процедур предполагает что передача параметров
+  процедуре производится через регистры, тем самым отпадает необходимость
+  освобождения стека от параметров. Для этого типа вызова процедуры
+  существуют ограничения по числу передаваемых параметров. Для C это три
+  параметра, а для C-- шесть. В C-- параметры передаются по умолчанию в
+  следующем порядке: 1-й - AX/EAX, 2-й - BX/EBX, 3 - CX/ECX, 4 - DX/EDX, 5 -
+  DI/EDI, 6 - SI/ESI. Параметры типов char или byte могут передаваться в
+  количестве не более 4 или только в первых 4 регистрах: 1 - AL, 2 - BL, 3 -
+  CL, 4 - DL. Этот порядок регистров может быть изменен, если явно указать
+  его либо при объявлении процедуры, либо при ее определении. Процедуры типа
+  fastcall иногда еще называют регистровыми.
+
+      В C-- по умолчанию, если имя процедуры написано большими буквами, то
+  считается, что эта процедура имеет тип вызова fastcall. Если же в имени
+  процедуры есть хотя бы одна маленькая буква, то по умолчанию считается, что
+  эта процедура имеет тип вызова pascal, за исключением программ
+  компилируемых с ключом /w32 /w32c или /DLL. В них по умолчанию применяется
+  тип вызова процедур stdcall. Если же Вы хотите изменить тип вызова процедур
+  из по умолчанию на любой другой, то эту процедуру надо обязательно объявить
+  с указанием типа желаемого вызова.
+
+      Объявление процедур введено для того, чтобы сообщать компилятору о
+  типе возврата из процедур, способе передачи параметров процедуре и их числе.
+Return to contents.
+
+
+
+  11.2 Стековые процедуры.
+
+
+      Стековые процедуры по умолчанию объявляются при помощи идентификатора,
+  который содержит, по крайней мере, один символ строчных букв (букв нижнего
+  регистра, маленьких букв). Таким образом, стековые процедуры легко отличимы
+  от регистровых процедур, поскольку для имен регистровых процедур символы
+  строчных букв запрещены.
+
+      Параметры для стековых процедур, если они есть, могут иметь любой тип
+  byte, char, word, int, dword, long или float.
+
+      Параметры передаются в соответствии с правилами, принятыми для данного
+  типа процедур. Если процедура не имеет объявления, то компилятор не следит
+  за числом и типом передаваемых параметров. В этом случае у Вас появляется
+  свобода в их использовании, но Вы должны осознавать и последстви
+  неправильного их использования.
+
+      В списке параметров для каждого параметра указывается его тип.
+  Параметры одного типа, идущие подряд, разделяются запятыми. Формальные
+  параметры разного типа в объявлении функции разделяются символом ;.
+
+      В следующем примере стековая процедура возвращает сумму всех своих
+  параметров (имеющих различные типы) как величину типа word:
+
+  	word add_them_all (int a,b,c; byte d,e; word x,y)
+  	{
+  	return( a+b+c+d+e+x+y );
+  	}
+
+      Ранее C-- делал вызовы стековых процедур лишь в стиле pascal.
+  Преимуществом этого способа вызова процедур является компактность и более
+  простой механизм генерации кода. К недостаткам, а соответственно и
+  преимуществам С-стиля, можно отнести жесткую привязанность паскалевских
+  процедур к числу и типу передаваемых параметров (попробуйте при вызове
+  процедуры в стиле pascal опустить один параметр и получите 100% зависание).
+  Напомню некоторые технические детали обоих типов вызовов процедур.
+
+  Кадр стека C-- для близких процедур стека в стиле pascal:
+       АДРЕС
+        ...
+      BP + FFFE предпоследний байта локальных переменных
+      BP + FFFF последний байт локальных переменных
+      BP + 0000 Сохраненный BP
+      BP + 0002 RET адрес
+      BP + 0004 последнее слово передаваемых процедуре параметров (если они
+                есть)
+      BP + 0006 предпоследнее слово передаваемых процедуре параметров
+       ...
+      BP + nnnn первое слово передаваемых процедуре параметров
+
+      Освобождение стека от переданных процедуре параметров происходит прямо
+  в самой процедуре командой RET nnnn - где nnnn является размером переданных
+  в стек параметров.
+
+  Кадр стека C-- для близких процедур стека в стиле си:
+       АДРЕС
+        ...
+      BP + FFFE предпоследний байта локальных переменных
+      BP + FFFF последний байт локальных переменных
+      BP + 0000 Сохраненный BP
+      BP + 0002 RET адрес
+      BP + 0004 первое слово передаваемых процедуре параметров (если они
+                есть)
+      BP + 0006 второе слово передаваемых процедуре параметров
+       ...
+      BP + nnnn последнее слово передаваемых процедуре параметров
+
+      Процедуры в стиле С заканчиваются командой RET. Освобождение стека от
+  параметров происходит в том месте откуда была вызвана процедура. Обычно это
+  делается командой ADD SP,nnnn. Т.е. компилятор может точно знать сколько и
+  каких параметров Вы передаете в данном случае процедуре и соответственно
+  освобождает стек после завершения процедуры. Это очень удобно для процедур,
+  которые могут обрабатывать переменное число параметров (например, процедуры
+  типа printf).
+
+      Объявление процедуры имеет следующий вид:
+
+    rettype modif procname();
+
+      Первым идет необязательный тип возврата из процедур. По умолчанию он
+  для 16-битных программ равен word, а для 32-битных dword. Затем должен идти
+  также необязательный модификатор. По умолчанию все стековые процедуры в C--
+  (за исключением режима компиляции программ под Windows, где по умолчанию
+  действует стиль вызова процедур stdcall) имеют стиль pascal. Далее идет им
+  процедуры со скобками, которые являются признаком того что Вы объявляете
+  процедуру, а не переменную. Завершает объявление символ точка с запятой.
+
+      При объявлении процедур в C-- прописывать параметры процедуры
+  необязательно (тогда компилятор не будет контролировать число и тип
+  передаваемых параметров), но если Вы их вставите, то включится механизм
+  контроля за числом и типом параметров.
+Return to contents.
+
+
+
+  11.3 Регистровые процедуры.
+
+
+      Регистровые процедуры определяются, по умолчанию, при помощи
+  идентификатора, который не содержит символов строчных букв. Или же явным
+  указанием что это регистровая процедура с помощью ключевого слова fastcall.
+
+      Как уже было сказано, параметры (если они есть) для регистровой
+  процедуры передаются через регистры. Регистровые процедуры могут иметь не
+  более 6 параметров. Если параметры имеют тип int или word, регистры по
+  умолчанию используются в следующем порядке: AX, BX, CX, DX, DI, и SI.
+  Первые четыре параметра могут также иметь тип char или byte, в этом случае
+  задействуются регистры AL, BL, CL и DL соответственно. Любой из шести
+  параметров может иметь тип long, dword или float, тогда для него
+  используется регистр EAX, EBX, ECX, EDX, EDI, или ESI.
+
+      В следующем примере регистровая процедура с именем TOGETHER возвращает
+  значение типа word как результат умножения первого параметра, имеющего тип
+  word, на второй параметр того же типа:
+
+           word TOGETHER() /* AX = первый параметр, BX = второй параметр */
+           {
+           return (AX * BX);
+           }
+
+      В следующем примере регистровая процедура с именем SHOW_NUM, которая не
+  возвращает никакого значения, зато выводит на экран первый параметр
+  (имеющий тип int), затем разделительный знак в виде двоеточия :, а затем
+  второй параметр (имеющий тип byte) :
+
+           void SHOW_NUM () /* AX = первое число, BL = второе число */
+           {
+           $ PUSH BX
+           WRITEINT (int AX);
+           WRITE (':');
+           $ POP BX
+           WRITEWORD (BL);
+           }
+
+      Но если в процедуре сделать объявление порядка и типов используемых
+  регистров, то возможно произвольное использование регистров. Более подробно
+  об этом можно почитать в разделе об объявлениях параметров в регистровых
+  процедурах.
+
+      Для того, чтобы использовать регистровую процедуру как макрокоманду,
+  она должна быть объявлена как динамическая процедура. Динамические
+  процедуры описаны в следующем подразделе.
+Return to contents.
+
+
+
+  11.4 Динамические процедуры.
+
+
+      Динамические процедуры - процедуры, которые определены, но вставляются
+  в код программы, только если есть вызов. Динамические процедуры могут
+  использоваться как макрокоманды.
+
+      Определение динамической процедуры начинается с символа двоеточия ':'.
+
+  Пример динамической процедуры стека:
+
+          : void setvideomode (byte mode)
+          {
+          AL = mode;
+          AH = 0;
+          $ INT 0x10
+          }
+
+  Пример динамической регистровой процедуры:
+
+          : int ABS () /* AX = число, абсолютное значение которого ищется*/
+          {
+          IF (int AX < 0)
+               -AX;
+          }
+Return to contents.
+
+
+
+    11.4.1 Установка динамической процедуры в определенное место программы.
+
+
+        Динамические процедуры, если они не используются как макросы и если
+    они были востребованы в программе, вставляются в код программы в самом
+    конце компиляции. В каком точно месте Вашей программы они окажутся узнать
+    невозможно. Если же Вам необходимо, чтобы какая-то динамическая процедура
+    находилась в конкретном месте программы, то это можно сделать таким
+    образом:
+
+    :void proc ( int par1, par2)
+    {
+       ...
+    }
+
+        Мы имеем динамическую процедуру, код которой был бы расположен ранее
+    кода обычной процедуры нашей программы. Для этого перед определением этой
+    процедуры надо написать такую строку:
+
+    @ void proc ();
+
+	В итоге динамическая процедура будет вставлена в код программы не в
+    конце ее, как обычно, а в месте, где будет расположена эта строка. Если
+    динамическая процедура имеет параметры, то прописывать эти параметры
+    необязательно.
+
+	В компиляторе есть еще более мощное средство, позволяющее все
+    динамические объекты ( процедуры, переменные, структуры ) расположить в
+    указанном месте, а не в конце программы, как обычно. Это директива
+    #setdinproc. Встретив эту директиву, компилятор немедленно расположит все
+    известные ему на этот момент динамические объекты в месте объявления этой
+    директивы. Последующие динамические объекты будут располагаться как
+    обычно, в конце программы, если конечно, не будет повторно применена
+    директива #setdinproc.
+
+	Это может быть применено и быть полезным при создании резидентных
+    программ (TSR) и драйверов устройств.
+Return to contents.
+
+
+
+  11.5 inline-процедуры.
+
+
+      inline-процедурами могут быть динамические процедуры, которые можно
+  использовать как макросы. Но в отличие от макросов, inline-процедуры, при
+  включенной оптимизации на скорость, автоматически вставляются в код, а при
+  оптимизации кода на размер, делается вызов их, как динамических процедур.
+
+      Но иногда бывает нужно при включенной оптимизации на размер кода, чтобы
+  процедуры вставлялись в код, а не делался их вызов. Для этих целей введена
+  директива #inline TRUE. Этой же директивой ( #inline FALSE ), можно при
+  оптимизации на скорость делать вызовы процедур, вместо их вставки.
+
+      Важно помнить, что статус директивы #inline автоматически меняется при
+  смене режима оптимизации. При установке оптимизации на скорость статус
+  директивы #inline устанавливается в TRUE, а при смене режима оптимизации по
+  размеру кода, устанавливается в FALSE. Поэтому применяйте директиву #inline
+  лишь после смены режима оптимизации.
+
+      Директивы меняющие режим оптимизации #codesize, #speed и директива
+  #inline, объявленные внутри процедуры распространяются только на оставшуюся
+  часть процедуры, т.е. они становятся локальными. Для того чтобы изменения
+  были глобальными эти директивы надо объявлять вне тела процедуры.
+
+      Для того чтобы определить inline-процедуру, надо в первой строке с
+  именем процедуры вместо символа динамической процедуры (:) написать
+  ключевое слово inline. Пример определения inline-процедуры:
+
+  inline int fastcall abs(AX)
+  {
+      IF ( int AX < 0 ) -AX ;
+  }
+Return to contents.
+
+
+
+    11.5.1 Другое применение inline.
+
+
+	Ключевое слово inline имеет в процедурах и другое применение. Если
+    это слово расположено перед началом блока процедуры, то для такой
+    процедуры не создается кадр стека и не генерируется завершающий процедуру
+    ret. Пример:
+
+    void PROC ()
+    inline
+    {
+      ...
+    }
+
+	Такие процедуры не должны содержать локальных переменных. Если
+    процедура является регистровой (тип fastcall), то с передачей ей
+    параметров нет проблем. Если же процедура является стековой, то передать
+    в такую процедуру параметры Вы можете, но воспользоваться этими
+    параметрами используя их имена, Вы уже не сможете. Это происходит потому,
+    что в этих процедурах кадр стека не формируется. Пример:
+
+    void proc (int par1, par2)
+    inline
+    {
+      AX=par1; /* компилятор обратится с параметру 'par1' через регистр BP.
+		  Но так как кадр стека не был создан, при выполнении этого
+                  кода программа будет работать не правильно. */
+       ...
+    }
+
+	Встретив такое определение процедуры, компилятор выдаст предупреждение
+    о том, что в таких процедурах использовать локальные и параметрические
+    переменные нельзя.
+Return to contents.
+
+
+
+  11.6 Процедуры обработки прерываний.
+
+
+      Процедуры обработки прерываний определяются следующим способом:
+
+          interrupt procedure_name ()
+          {
+          // put code here (здесь должен быть код обработки)
+          }
+
+      Процедуры обработки прерываний не сохраняют никаких регистров
+  автоматически, и никакие регистры сами по себе не загружаются перед
+  передачей управления обработчику прерывания, следовательно, на Вашей
+  совести сохранение значений регистров в стеке и последующий их возврат, а
+  также загрузка регистра DS нужным значением.
+
+      Вот пример обработчика прерывания, который сохраняет значения всех
+  регистров и загружает регистр DS:
+
+       interrupt safe_handle ()
+       {
+       $ PUSH DS
+       $ PUSH ES
+       $ PUSHA   // для выполнения этой команды нужен процессор не хуже 80286
+       DS = CS;  // здесь DS загружается для работы с моделью памяти типа tiny
+
+
+       /* do your thing here (здесь вы делаете свою обработку)*/
+
+       $ POPA   // для выполнения этой команды нужен процессор не хуже 80286
+       $ POP ES
+       $ POP DS
+       }
+
+      При завершении процедуры прерывания будет автоматически сгенерирована
+  инструкция выхода из обработчика прерывания - IRET.
+Return to contents.
+
+
+
+  11.7 Замена return на goto.
+
+
+      В некоторых ситуациях, при компиляции программы, оператор return
+  будет заменяться на goto. Это происходит при разрешенной оптимизации по
+  размеру кода для операторов return, которые расположены внутри процедуры
+  и, естественно, если размер кода для выполнения return больше, чем размер
+  кода для реализации goto. Для динамических процедур, которые используются
+  как макросы, такая замена будет производится всегда. Оператор goto будет
+  выполнен на конец процедуры, там, где будет располагаться единственный
+  выход из процедуры. В динамических процедурах, используемых в качестве
+  макросов, return в конце процедуры будет пропущен компилятором.
+
+      Таким образом, снято последнее ограничение на использование
+  динамических процедур в качестве макросов. Любая динамическая процедура
+  может быть использована как макрос.
+
+      Для оператора goto существует его более короткий аналог - GOTO.
+  Для получения более компактного кода для оператора return введен также
+  более короткий оператор RETURN. Его можно использовать, если от места
+  его применения до конца процедуры находится не более 128 байт. Если Вы
+  будете использовать RETURN на большем расстоянии до конца процедуры, то
+  компилятор выдаст сообщение об ошибке. При использовании return на
+  расстоянии меньше 128 байт до конца кода, компилятор выдаст вам
+  предупреждение о возможном использовании RETURN.
+Return to contents.
+
+
+
+  11.8 Возвращаемые значения.
+
+
+      Возвращаемые из функций значения располагаются в регистрах. В таблице
+  показано, какой регистр используется для каждого из возвращаемых типов:
+
+      --------------------------------------------
+      | возвращаемый тип |  используемый регистр |
+      --------------------------------------------
+      |        byte      |        AL             |
+      |        word      |        AX             |
+      |        dword     |        EAX            |
+      |        char      |        AL             |
+      |        int       |        AX             |
+      |        long      |        EAX            |
+      |        float     |        EAX            |
+      --------------------------------------------
+
+      Самый простой способ вернуть значение из функции состоит в том, чтобы
+  использовать команду return(), но вместо этого можно напрямую загрузить
+  возвращаемое значение в соответствующий регистр. Например, следующие две
+  функции возвращают одно и то же значение:
+
+           byte proc_one ()
+           {
+           return (42);
+           }
+
+           byte proc_two ()
+           {
+           AL = 42;
+           }
+
+      Многие DOS функции 0x21 прерывания в качестве индикатора успешного
+  выполнения используют установку или сброс carry флага. Использовать флаги
+  процессора при возврате из процедур можно и в других случаях, когда надо
+  иметь статус успешного или не успешного выполнения процедуры. Это позволит
+  более полно использовать возможности процессора и соответственно уменьшит
+  размер кода и повысит быстродействие программы.
+
+      Наряду с флагами, при возврате из процедур, по прежнему остается
+  возврат различных типов и через регистр AL/AX/EAX. Если для процедуры
+  объявлено, что она имеет тип возврата int и CARRYFLAG, то при использовании
+  такой процедуры в операциях сравнения IF, WHILE... будет делаться проверка
+  carry флага, а не сравнение регистра AX. Пример использования возврата
+  флагов из процедур:
+
+  int CARRYFLAG FOPEN();	// объявление процедуры
+
+  void proc()
+  {
+    IF ( FOPEN(name,0) ) Error ( "Not open file" );
+  }
+
+      Варианты допустимого синтаксиса для использования возврата флага:
+
+  IF ( ! FOPEN() )...
+  IF ( @ FOPEN() )...
+  IF ( ! @ FOPEN() )...
+  IF ( handl = FOPEN() )...
+  IF ( handl = @ FOPEN() )...
+  IF ( ! handl = FOPEN() )...
+  IF ( ! handl = @ FOPEN() )...
+
+      А вот варианты, в которых, несмотря на то, что для процедуры объявлен
+  возврат флага, будет производиться сравнение регистра AX:
+
+  IF ( FOPEN() == 5 )...	// производится сравнение
+  IF ( FOPEN() + 2 )...   // результат процедуры подвергается дальнейшему
+                          // вычислению, в результате которого флаги будут
+  			// изменены.
+Return to contents.
+
+
+
+  11.9 Объявление параметров в регистровых процедурах.
+
+
+      Ранее каждому параметру регистровой процедуры соответствовал строго
+  определенный регистр. Например, для переменных типа int или word первый
+  параметр передавался через регистр AX, 2-й - BX, 3-й - CX, 4-й - DX, 5-й -
+  DI, 6-й - SI. Поэтому, если Вам было необходимо передать только один
+  параметр через регистр SI, то приходилось перед ним писать пять запятых.
+  Вот как, например, выглядит вызов процедуры STRCPY:
+
+  void main ()
+  {
+    STRCPY ( , , , , #dest, #sourc ) ;
+  }
+
+      Теперь регистры могут располагаться при передаче параметров
+  произвольным образом. Надо только объявить компилятору о том, какой регистр
+  закреплен за каким параметром данной процедуры. После такого объявления
+  компилятор будет сам следить за тем, через какой регистр передавать
+  параметр процедуре, его размерностью и числом передаваемых параметров. Вот
+  как будет выглядеть объявление и использование процедуры STRCPY:
+
+  void STRCPY ( DI, SI ) ;	//это объявление процедуры
+
+  void main ()
+  {
+    STRCPY ( #dest, #sourc ) ;	//а это вызов процедуры
+  }
+
+      Можно не делать объявления процедуры, а указать расположение регистров
+  в заголовке процедуры. Но тогда такая процедура должна вызываться только
+  после ее определения. Вот пример процедуры выводящей на экран несколько
+  одинаковых символов:
+
+  void PUTNCHAR(AL,CX,BL,BH)
+  /* 1 параметр в AL - код символа, который будет выведен
+     2 параметр в CX - число выводимых символов
+     3 параметр в BL - цветовой атрибут
+     4 параметр в BH - номер видеостраницы
+  */
+  {
+    AH=9;
+    $INT 0x10
+  }
+
+      При объявлении регистровой процедуры можно также указывать какой тип
+  переменной ожидает процедура (знаковый/без знаковый или вещественный). По
+  умолчанию считается без знаковый тип. Однако знаковый тип указывать есть
+  смысл только если параметр передается через регистр AL/AX/EAX. Через другие
+  регистры переменная всегда передается как без знаковая. Пример объявления
+  регистровой процедуры с указанием типов:
+
+  int fastcall Exampl( word CX, int AX, DX, float ESI ) ;
+   |    |        |        |         |   |   |
+   |    |        |        |         |   |   |---- 4-й парам. имеет тип float и
+   |    |        |        |         |   |         перед. через регистр ESI.
+   |    |        |        |         |   |-------- 3-й парам. имеет по умолч.
+   |    |        |        |         |             тип word и перед. через DX.
+   |    |        |        |         |------------ 2-й парам. имеет тип int и
+   |    |        |        |                       передается через регистр AX.
+   |    |        |        |---------------------- 1-й парам. имеет тип word и
+   |    |        |                                передается через регистр CX.
+   |    |        |------------------------------- Имя объявляемой процедуры.
+   |    |---------------------------------------- Модификатор, указывающий, что
+   |                                              эта проц. явл. регистровой.
+   |--------------------------------------------- Процедура возвращает перемен.
+  						                          типа int.
+
+      Если Вы сделали объявление регистров процедуры, то компилятор будет
+  строго следить за количеством указанных параметров при вызове этой
+  процедуры и выдавать сообщения об ошибке, если их будет меньше или больше.
+  С одной стороны это хорошо - есть контроль за тем, что Вы ничего не забыли
+  или не добавили лишнего при вызове процедуры. С другой стороны иногда
+  бывают необязательные параметры, а их теперь придется прописывать. Но если
+  Вы при вызове процедуры не укажете ни одного параметра, то компилятор не
+  будет Вам выдавать сообщение об ошибке.  Это дает Вам возможность
+  проинициализировать регистры, через которые Вы передаете параметры, вне
+  вызова процедуры.  Но если Вы укажете, хоть один параметр, то Вам придется
+  указывать и остальные, иначе компилятор будет считать, что Вы их случайно
+  пропустили и выдаст сообщение об ошибке.
+
+      Если Вы не объявили регистры ни при объявлении регистровой процедуры,
+  ни в заголовке самой процедуры, то компилятор будет считать, что параметры
+  в эту процедуру передаются старым способом. Таким образом, достигается
+  полная совместимость с предыдущими версиями компилятора.
+Return to contents.
+
+
+
+  11.10 Объявление параметров в стековых процедурах.
+
+
+      Как известно, ранее в C-- контроль за числом и типом передаваемых
+  процедуре параметров возлагался на программиста. Поэтому возникла непростая
+  задача, совместить одновременно отсутствие контроля за параметрами (для
+  совместимости с предыдущими версиями) и ее наличие. В результате
+  компромиссов появился вариант немного отличающийся от традиционно принятого
+  в языках C.
+
+      Главное отличие - это то, что параметры, определяемые при определении
+  процедуры, не будут восприниматься компилятором для контроля за ними. Во
+  всех языках C допускается совмещение прототипа процедуры и ее объявления.
+  В C-- для того, чтобы включился контроль за параметрами стековой процедуры,
+  надо эту процедуру обязательно объявить. Но не всякое объявление процедуры
+  будет сигналом компилятору о включении контроля за параметрами этой
+  процедуры. Если при объявлении в круглых скобках ничего не будет, то
+  компилятор не будет отслеживать параметры, передаваемые этой процедуре. В
+  C++ такое объявление означает, что процедуре не передаются никакие
+  параметры. В C-- для этого надо при объявлении процедуры в круглых скобках
+  обязательно написать void. Например:
+
+  int proc ( void ) ;
+
+      Встретив такое объявление процедуры, компилятор будет следить за тем,
+  чтобы этой процедуре не были переданы параметры.
+
+      При объявлении процедуры имена параметров можно опускать. Как известно,
+  в C-- параметры процедуры одного типа записываются через запятую. Для смены
+  типа используют точку с запятой. При объявлении смену типа можно
+  производить и после запятой:
+
+  void ptoc ( int a, b, c; word d );
+  void proc ( int, int, int, word );
+  void proc ( int, int, int; word );
+
+      Все эти примеры объявлений являются идентичными и допустимыми.
+
+      Для контроля за процедурами с переменным числом параметров был введен
+  новый для C-- элемент синтаксиса - многоточие или его еще называют эллипс.
+  Вот как будет выглядеть объявление процедуры printf:
+
+  void cdecl printf ( word, ... );
+Return to contents.
+
+
+
+  11.11 Использование макрокоманд.
+
+
+      Теперь любая динамическая процедура может быть использована как макрос.
+  Если перед вызовом динамической процедуры поставить символ @, то код этой
+  процедуры будет вставлен, а не вызван инструкцией CALL.
+
+      При использовании стековых динамических процедур в качестве макросов
+  очистка стека от переданных параметров производится ассемблерной
+  инструкцией ADD SP,SIZE_PARAMETRS сразу после окончания кода вставленного
+  макроса. Поэтому, если эта процедура использовала флаги в качестве
+  возврата, то они будут разрушены.
+Return to contents.
+
+
+
+  11.12 Передача параметров в стековые процедуры через регистры.
+
+
+      При передаче параметров через регистры, чаще всего получается более
+  компактный и быстрый код. Но содержимое регистров может быть легко
+  разрушено. Если в Вашей процедуре, какой-то из параметров используется
+  однократно для того, чтобы в начале процедуры инициализировать какой-то
+  регистр, то Вы можете передать это значение в процедуру сразу через
+  регистр, минуя стадию засовывания и извлечения содержимого в стек. Пример:
+
+  int proc (int param1, param2, param3)
+  {
+    (E)BX = param3;
+    (E)BX.TEG_STRUCT.var = proc2 (param1,papra2);
+    proc3 (param1,param2);
+  }
+
+      В этом примере параметр param3 используется лишь для того, чтобы
+  инициализировать регистр (E)BX, поэтому его можно сразу передать через
+  регистр:
+
+  int proc (int param1, param2, (E)BX)
+  {
+    (E)BX.TEG_STRUCT.var = proc2 (param1,papra2);
+    proc3 (param1,param2);
+  }
+
+      Как Вы видите, процедура немного упростилась.
+
+      В принципе, порядок расположения стековых и регистровых параметров не
+  принципиален. Но надо помнить, что содержимое регистров может быть легко
+  разрушено, и поэтому лучше всего регистровые параметры инициализировать
+  лишь после того, как были засунуты в стек все стековые параметры. Для
+  процедур типа pascal регистровые параметры лучше располагать после
+  стековых параметров. Для процедур типа cdecl и stdcall сначала лучше
+  располагать регистровые параметры.
+Return to contents.
+
+
+
+  11.13 Вызов процедур с адресом в регистре.
+
+
+      В C-- допустимо делать вызов процедуры, адрес которой находится в
+  регистре. Параметры для такого вызова передаются только через стек. Тип
+  вызова процедуры для программ под Windows stdcall, для остальных pascal.
+  Адрес процедуры для 32-битных программ должен находится в 32-битном
+  регистре, а для 16-битных программ в 16-битном регистре. Считается, что
+  такой вызов имеет возврат типа unsigned int. Пример:
+
+    BX = # proc;
+    BX (a);
+    IF ( BX(b) == 0 ) AX=2;
+
+    Вы получите следующий код:
+
+  test.c-- 8: BX=#proc;
+  0104 BB1A01                   mov     bx,11Ah
+
+  test.c-- 9: BX(a);
+  0107 FF76FC                   push    word ptr [bp-4]
+  010A FFD3                     call    near bx
+
+  test.c-- 10: IF (BX(b) == 0)AX=2;
+  010C FF76FE                   push    word ptr [bp-2]
+  010F FFD3                     call    near bx
+  0111 85C0                     test    ax,ax
+  0113 7503                     jne     118h
+  0115 B80200                   mov     ax,2
+Return to contents.
+
+
+
+  11.14 Встроенные в компилятор процедуры.
+
+
+      Для некоторых процедур Вы не найдете их исходные тексты в библиотеках
+  компилятора. Код этих процедур генерирует компилятор. Вот список этих
+  процедур:
+
+  ABORT             Прекращение выполнения программы
+  atan              Вычислить арктангенс числа
+  atan2             Вычислить арктангенс числа
+  ATEXIT            Зарегистрировать функцию выполняющуюся при выходе.
+  cos               Возвращает косинус угла
+  EXIT              Закончить программу с кодом ошибки
+  exp               Возвращает экспоненту числа
+  inp/inportb       Считать один байт из порта
+  inport            Считать слово из порта
+  inportd           Считать двойное слово из порта
+  fabs              Возвращает абсолютное значение числа
+  log               Вычисляет натуральный логарифм числа
+  log10             Вычисляет десятичный логарифм числа
+  outp/outportb     Записать один байт в порт
+  outport           Записать слово в порт
+  outportd          Записать двойное слово в порт
+  sin               Возвращает синус угла
+  sqrt              Извлечь квадратный корень через FPU.
+  tan               Возвращает тангенс угла
+
+      Размещение этих процедур непосредственно в компиляторе, связано с тем,
+  что в настоящий момент компилятор может таким образом генерировать более
+  эффективный код, чем если бы эти процедуры располагались в библиотеках.
+  В будущем, по мере развития компилятора, эти процедуры постепенно будут
+  выносится из компилятора в библиотеки.
+
+      Но ничто не мешает Вам уже сейчас написать свои одноименные
+  библиотечные процедуры. Встретив определение такой процедуры, компилятор не
+  будет выдавать никаких сообщение, он просто будет применять Ваш вариант
+  процедуры.
+Return to contents.
+
+
+
+    11.14.1 Процедуры ABORT, ATEXIT и EXIT.
+
+
+        Процедуры ABORT и EXIT связаны с работой директивы #atexit и
+    процедурой ATEXIT. Наиболее оптимальную их реализацию и взаимную
+    интеграцию может сделать только компилятор. Именно поэтому эти процедуры
+    поддерживаются компилятором.
+
+        Процедура ATEXIT - регистровая процедура, которая регистрирует
+    функцию, адрес которой передается ей в качестве параметра, т.е. через
+    регистр (E)AX, как функцию завершения программы. При успешной регистрации
+    ATEXIT возвращает 0. Всего можно зарегистрировать до 16 функций.
+
+        Завершающие функции не должны иметь параметров и возврата. Эти
+    функции будут выполняться в порядке обратном очередности регистрации в
+    случае, если Вы будете завершать работу программы через вызовы процедур
+    ABORT или EXIT или закончится работа процедуры main. Если Вы
+    завершите работу программы вызовом процедуры ExitProcess под Windows или
+    вызовом AH=0x4C; $int 0x21 под DOS, выход из программы произойдет без
+    запуска зарегистрированных функций.
+
+        Процедура ABORT и EXIT, если не включена директива #atexit делают
+    вызов процедуры ExitProcess под Windows и вызов AH=0x4C; $int 0x21 под
+    DOS.  Процедуре ABORT не передаются никакие параметры, и она завершает
+    работу программы с кодом возврата 0. Процедуре EXIT передается в
+    качестве параметра код возврата, с которым она и завершает работу
+    программы.
+Return to contents.
+
+
+
+    11.14.2 Процедуры inp/inportb, inport, inportd, outp/outportb, outport и
+                                                                    outportd
+
+
+        Эти процедуры всегда вставляются в код как макросы, т.е. для этих
+    процедур никогда не генерируется вызов процедуры. В зависимости от
+    значения порта, с которым работают эти процедуры, генерируется разный
+    код. Все это позволяет получать более компактный код.
+
+        Процедуры чтения из порта имеют такой прототип:
+
+    byte inp ( word port );
+    word inport ( word port );
+    dword inportd ( word port );
+
+        Процедуры записи в порт имеют такой прототип:
+
+    void outp ( byte val; word port );
+    void outport ( word val; word port );
+    void outportd ( dword val; word port );
+
+        Имена процедур inp и inportb, также как и имена outp и outportb
+    являются синонимами.
+Return to contents.
+
+
+
+    11.14.3 Процедуры для работы с вещественными числами.
+
+
+        Эти процедуры реализуются компилятором и всегда вставляются в код как
+    макросы, т.е. для них никогда не генерируется вызов процедуры. Кроме
+    этого, если параметром одной процедуры является вызов другой, то
+    результат работы второй процедуры остается в стеке FPU, а первая
+    процедура использует этот результат непосредственно из стека. Таким
+    образом получаются более компактный код. Вот вымышленный пример:
+
+    test.c-- 7: f = sin( sqrt(1) );
+    0100 D9061C01                 fld     [11Ch]
+    0104 D9FA                     fsqrt
+    0106 D9FE                     fsin
+    0108 D91E2001                 fstp    [120h]
+    010C 9B                       fwait
+
+        Эти процедуры имеют следующий прототип:
+
+    float atan ( float val );
+    float atan ( float val, val2 );
+    float cos ( float val );
+    float exp ( float val );
+    float fabs ( float val );
+    float log ( float val );
+    float log10 ( float val );
+    float sin ( float val );
+    float sqrt ( float val );
+    float tan ( float val );
+Return to contents.
+
+
+
+  11.15 Классы.
+
+    11.15.1 Объявление процедур в структурах.
+
+
+        С введение поддержки объявления процедур в структурах, структура
+    становится подобной классу в C++. Т.е. такая процедура становится методом
+    класса. Пример:
+
+    struct Point  // объявление класса
+    {
+    	int x; // элементы данных
+    	int y; // класса типа Point
+    	void SetX(int);  // объявление методов
+    	void SetY(int);  // класса Point
+    };
+
+    void Point::SetX(int _x)  //определение процедуры класса Point
+    {
+    	IF((_x>=0)&&(_x<=MAX_X)) x=_x;
+    // переменные x, y являются членами этого класса и поэтому доступ к ним из
+    // процедур этого же класса осуществляется напрямую.
+     }
+
+    void main()
+    Point p;  //определяем структуру в стеке
+    {
+      p.y = p.x = 0;
+      p.SetX(1);
+    }
+
+        При вызове процедуры являющейся методом класса ей неявным образом
+    передается адрес этого класса (структуры). В самой процедуре этот адрес
+    доступен через имя параметрической переменной this. Эту переменную
+    автоматически генерирует компилятор. Если в объявление процедуры в
+    структуре указать ключевое слово static, то такой процедуре адрес
+    класса не передается и переменная this не генерируется.
+
+        Процедура объявленная в структуре может быть динамической. Для этого,
+    при ее определении, в самом ее начале, надо написать символ двоеточия :
+    (также как и для обычных динамических процедур). Но такая динамическая
+    процедура не может быть использована как макрос.
+Return to contents.
+
+
+
+    11.15.2 Наследование.
+
+
+        В C-- поддерживаются простые и множественные наследования. Объявление
+    структуры с наследованием имеет следующий синтаксис:
+
+    struct Derived : Base1, Base2, ... Basen
+    {
+      int x0;
+    };
+
+        Число базовых структур в производном не ограничено. При множественном
+    наследовании структура может наследовать два и более экземпляра базовой
+    структуры. При этом возникает неоднозначность. Пример:
+
+    struct A
+    {
+      int x,y;
+      . . .
+    };
+
+    struct B : A  //структура B наследует A
+    {
+      . . .
+
+    };
+
+    struct C : A  //структура C наследует A
+    {
+      . . .
+    };
+
+    struct D : B, C //структура D наследует B и C
+    {
+      . . .
+    };
+
+    void main()
+    D d;  //выделяем для структуры D память в стеке и присваиваем ей имя d
+    {
+      d.x0=0;
+
+        В этом примере структура D наследует два экземпляра структуры A и
+    в ней находятся два элемента с именем x0. Компиляторы C++ при записи
+    типа d.x0=0 выдают сообщение об ошибке. C-- эту запись обрабатывает,
+    присваивание производится по умолчанию в элемент из последней базовой
+    структуры, имеющей элемент x0. Для того чтобы получить доступ ко
+    второму элементу x0 (физически этот элемент находится в структуре
+    первым), необходимо применить операцию разрешения видимости:
+
+      d.B::x0=0;
+
+        Из всего этого следует, что записи:
+
+      d.x0=0;
+    и
+      d.C::x0=0;
+
+         являются равнозначными.
+Return to contents.
+
+
+
+    11.15.3 Наследование процедур.
+
+
+	Если в базовом классе есть процедура, а в производном классе Вы эту
+    процедуру переопределили, то эта процедура будет переопределена и в
+    базовом классе. Таким образом процедура определенная в базовом классе
+    будет потеряна. Пример:
+
+    struct Point  // базовый класс
+    {
+    	int x; // элементы данных
+    	int y; // класса типа Point
+    	void SetX(int);  // объявление методов
+    	void SetY(int);  // класса Point
+    };
+
+    void Point::SetX(int _x)  // определение процедуры класса Point
+    {
+    	IF((_x>=0)&&(_x<=MAX_X)) x=_x;
+    }
+
+    struct Point2 : Point  // производный класс
+    {
+      int x2;
+    }
+
+    struct Point3 : Point  // еще один производный класс
+    {
+      int z;
+    }
+
+    void Point3::SetX(int _x)  // в этом производном классе переопределяем
+    {                          // процедуру SetX
+    	IF((_x>=80)&&(_x<=MAX_X)) x=_x;
+    }
+
+	Процедура SetX, определенная в базовом классе Point, теперь будет
+    недоступна. Вместо кода определенного в этом классе, будет вызываться код
+    процедуры, определенный в наследуемом классе Point3. При вызове процедуры
+    SetX из другого производного класса Point2 будет также вызываться код
+    процедуры, определенный в производном классе Point3. Переопределяя
+    процедуру таким образом, Вы замените код этой процедуры в базовом классе и
+    во всех его наследуемых классах.
+
+	Если Вам необходимо, чтобы код новой процедуры был доступен
+    одновременно с кодом старой процедуры, то в производном классе Вам
+    необходимо сделать еще одно объявление этой процедуры. Пример:
+
+    struct Point  // базовый класс
+    {
+    	int x; // элементы данных
+    	int y; // класса типа Point
+    	void SetX(int);  // объявление методов
+    	void SetY(int);  // класса Point
+    };
+
+    void Point::SetX(int _x)  // определение процедуры класса Point
+    {
+    	IF((_x>=0)&&(_x<=MAX_X)) x=_x;
+    }
+
+    struct Point2 : Point  // производный класс
+    {
+      int x2;
+    }
+
+    struct Point3 : Point  // еще один производный класс
+    {
+      int z;
+      void SetX(int);  // в наследуемом классе делаем еще одно объявление
+                       // процедуры SetX
+    }
+
+    void Point3::SetX(int _x)  // в этом производном классе переопределяем
+    {                          // процедуру SetX
+    	IF((_x>=80)&&(_x<=MAX_X)) x=_x;
+	EDI=this;
+	EDI.Point.SetX(_x);  // делаем вызов одноименной процедуры из
+			     // базового класса
+    }
+
+	Теперь из производного класса Point3 Вам доступны две различные
+    процедуры с одним именем SetX. А из базового класса Point и из другого
+    производного класса Point2 будет по прежнему доступен только базовый
+    вариант процедуры SetX.
+Return to contents.
+
+
+
+12. Типы выходных файлов.
+
+  12.1 Выходные файлы типа COM.
+
+
+      Этот тип выходного файла получается автоматически по умолчанию.
+
+      Изначально C-- мог делать только файлы формата типа COM. В настоящее
+  время появилась возможность получать файла типа EXE с моделями памяти tiny
+  и small для 16-битного кода, а также 32-битные для DOS и Windows. Также
+  есть возможность получения выходного файла в формате OBJ, что позволяет
+  связывать программы на C-- с программами на других языках.
+Return to contents.
+
+
+
+  12.2 Выходные файлы типа EXE.
+
+
+      Этот формат файла можно получить, если компилировать с ключом командной
+  строки /exe или /e.
+
+      Возможно также поддержка EXE-формата через выходной файл формата OBJ,
+  который можно затем обработать линковщиком, не входящим в пакет C--.
+Return to contents.
+
+
+
+  12.3 Выходной файл *.EXE с моделью памяти tiny.
+
+
+      Фактически код файла *.exe модели tiny ничем не отличается от кода
+  *.com. В сущности, это тот же com-файл, к которому добавлен 32-байтный
+  заголовок exe-файла. Единственное отличие возникает, когда Вы компилируете
+  файл с директивой ?resize TRUE. В com-файле, по этой директиве, в код
+  программы добавляется соответствующий код, изменяющий размер доступной
+  памяти. В exe-файле для этих целей будет скорректирован заголовок
+  exe-файла.
+
+      Чтобы получить exe-файл с моделью памяти tiny, надо запустить
+  компилятор с ключом в командной строке /TEXE.
+Return to contents.
+
+
+
+  12.4 Объектный выходной файл OBJ.
+
+
+      В настоящее время C-- может только создавать OBJ-файлы, но не может их
+  компоновать.
+
+      Ранее C-- создавал obj-файлы, которые могли быть подключены к проектам
+  созданным на других языках, т.е. ведомые (slave) модули. Причем из C--
+  модулей для основного проекта были доступны только процедуры и эти
+  процедуры не должны были использовать глобальные переменные.
+
+      Теперь же C-- может создавать основной модуль (master), который может
+  быть слинкован в самостоятельный файл.
+
+      Для obj-файлов появилась возможность использовать внешние (extern)
+  процедуры, переменные или структуры. Для этого достаточно их объявить как
+  extern. Причем ключевое слово extern должно быть всегда первым. Пример
+  объявления внешних объектов:
+
+  extern void cdecl _printf(); // объявление внешней процедуры _printf имеющей
+                               // тип cdecl  и тип возврата void
+  extern int buts,cubs;        // объявление двух внешних переменных типа int
+  extern struct IPXL ipxl;     // объявление внешней структуры ipxl имеющей тег
+  			     // IPXL,  причем тег этой структуры должен быть
+  			     // описан ранее.
+
+      Появление возможности объявлять внешние объекты позволяет подключать к
+  obj-модулю на C-- модули написанные на других языках или подключать к
+  программе на C-- процедуры из библиотек на других языках. При объявлении
+  внешних объектов очень важно правильно указать тип процедуры и ее имя. Если
+  Вы будете использовать внешние процедуры, написанные на C то чаще всего,
+  Вам нужно будет указывать модификатор cdecl, а к имени процедуры или
+  переменной добавлять префикс _.
+
+      Из основного (master) obj-файла написанного на C-- для других
+  obj-модулей доступны все процедуры, глобальные переменные и глобальные
+  структуры.
+
+      Чтобы получить ведомый obj-модуль при компиляции надо использовать ключ
+  /sobj.
+
+      C-- может создавать obj-файлы с моделью памяти tiny и small. По
+  умолчанию создаются модули с моделью tiny. Чтобы получить obj-файл с
+  моделью памяти small надо запустить компилятор с ключами /obj и /exe.
+
+      Для создания obj-файлов для 32-битного DOS в командной строке Вам
+  необходимо указать ключи /d32 и /obj. Использовать полученный obj-файл мне
+  удалось лишь с помощью wlink и расширителя zrdx.exe.
+
+      Создание obj-файлов под windows не предусмотрено.
+Return to contents.
+
+
+
+  12.5 COM файл symbiosis.
+
+    12.5.1 СИМБИОЗ - что это такое?
+
+
+        Транслятор C-- имеет ключ, позволяющий добавлять компилируемую
+    программу к концу уже имеющегося COM файла. Это называют COM-файл
+    Symbiosis. Когда такая программа запускается, управление сначала получает
+    добавленный код C--, и только после выполнения его процедуры main()
+    управление получит первоначальный код COM-файла.
+
+        Если добавленный вами код завершается EXIT() или ABORT(), программа
+    прекратится, и первоначальный код COM-файла не будет выполнен. Это
+    позволяет программе, добавленной к COM файлу, определять, будет ли
+    управление передано на первоначальный код.
+Return to contents.
+
+
+
+    12.5.2 Как это делать.
+
+
+        Чтобы сделать это, Вы должны использовать ключ /SYM в командной
+    строке компилятора, в которой указывается полное имя COM-файла, к
+    которому что-то добавляется. При этом оригинал COM-файла не меняется, а
+    новый файл содержит его в себе. Например, чтобы откомпилировать программу
+    HELLO.C-- к концу копии C:\command.сом используют следующую команду:
+
+             C-- /SYM C:\COMMAND.COM HELLO.C--
+
+    Будет создан выходной файл HELLO.COM .
+Return to contents.
+
+
+
+    12.5.3 Использование.
+
+
+        Вы можете, вероятно, придумать большое количество путей использования
+    этой функции, типа:
+
+             - Добавление защиты с использованием пароля к некоторым
+	       специальным COM файлам.
+             - Уменьшение памяти, доступной COM файлу при запуске.
+             - Инициализация режима видео для COM файла.
+Return to contents.
+
+
+
+    12.5.4 Злоупотребления.
+
+
+        Любой злоумышленник может придумать и вредные применения для этой
+    функции. Наиболее очевидное из них - создание троянских коней. Я хотел бы
+    указать, что это неконструктивное использование C--, и любое
+    разрушительное использование симбиозов COM-файлов запрещено.
+Return to contents.
+
+
+
+  12.6 SYS - драйверы устройств.
+
+
+      Компилятор значительно облегчит Ваш труд при написании драйверов.
+  Компилятор сам создаст заголовок драйвера и процедуры СТРАТЕГИЯ и
+  ПРЕРЫВАНИЕ. Вам остается лишь написать код обработки команд.
+
+      Что бы откомпилировать файл драйвера устройства, надо добавить в
+  командную строку ключ /SYS. Кроме того, появились новые директивы
+  компилятору, которые действуют только с этим ключом. Вот они:
+
+      ?sysattribute значение  - эта  директива передает  компилятору
+  атрибут создаваемого драйвера. По умолчанию устанавливается значение
+  0x2000.
+
+      ?sysname <текстовая  строка> -  эта директива  передает компилятору
+  имя будущего драйвера. По умолчанию присваивается имя "NO_NAME". Длина
+  имени  не более 8 символов.
+
+      ?syscommand command_0,command_1, ... command_n; - эта директива
+  является обязательной. По этой директиве компилятору передается список имен
+  процедур обработки команд драйвера. Имена разделены запятыми. Список должен
+  заканчиваться символом точка-с-запятой. Можно передать не более 25 команд.
+  Если какая-то команда не имеет кода поддержки, то в список надо записать
+  слово NONE.
+
+      По умолчанию компилятор для драйвера не создает стек. Драйвер может
+  пользоваться системным стеком. Но, говорят, что он имеет маленькую глубину.
+  Если Ваши процедуры активно используют стек, и Вы не надеетесь на системный,
+  то директивой ?stack <величина> можно заставить драйвер пользоваться своим
+  стеком.
+
+      Вашим процедурам обработки команд при передаче управления в регистрах
+  ES:BX будет передан адрес заголовка запроса. Регистр DS равен CS. При
+  возврате управления ваши процедуры должны сохранить регистр DS. В регистре
+  AX должен находиться код возврата. Остальные регистры могут быть
+  использованы произвольным образом.
+
+      Процедуру обработки команды инициализации желательно располагать
+  последней (чтобы иметь возможность отдать адресное пространство занимаемое
+  этой процедурой операционной системе). Перед этой процедурой, если Вы в
+  других процедурах обработки команд используете динамические процедуры,
+  обязательно должна быть директива ?setdinproc. Глобальные переменные должны
+  быть обязательно проинициализированы.
+Return to contents.
+
+
+
+  12.7 Компиляция кода расширителей ROM-BIOS.
+
+
+      Расширители ROM-BIOS (BIOS видеоконтроллеров, сетевых карт...) имеют
+  определенную структуру и требования. C-- теперь может облегчить Вам процесс
+  создания кода ROM-BIOS. Если запустить компилятор на компиляцию с ключом
+  командной строки /ROM, то компилятор создаст сигнатуру (заголовок)
+  ROM-BIOS, заполнит оставшееся свободное место до указанного размера ПЗУ
+  кодом заполнения, подсчитает и скорректирует контрольную сумму ПЗУ.
+
+      Для этого режима компиляции есть несколько специфических директив:
+
+    1.  ?sizerom value - эта директива сообщает компилятору размер ПЗУ в
+  байтах. Если эта директива не указана, то компилятор сам выберет
+  минимальный подходящий размер ПЗУ из ряда: 1024, 2048, 4096, 8192, 16384,
+  32762 или 65536. Свободное от кода и данных место будут заполнены до конца
+  размера ПЗУ байтом заполнения определяемого директивой ?aligner. По
+  умолчанию он равен нулю, для РПЗУ типа 27ххх этот байт имеет смысл сделать
+  равным 0xFF. Последний байт ПЗУ будет скорректирован компилятором таким
+  образом, чтобы контрольная сумма равнялась нулю.
+
+    2.  ?movedatarom TRUE/FALSE - эта директива сообщает компилятору есть ли
+  необходимость копировать данные из ПЗУ в ОЗУ. По умолчанию она установлена
+  в FALSE. Если эту директиву определить TRUE, то компилятор вставит в
+  область инициализации код перемещающий данные из ПЗУ в ОЗУ. При этом
+  регистр DS будет установлен на сегмент ОЗУ. Стек также будет переустановлен
+  на этот сегмент. Таким образом, процедура main получит управление с
+  регистрами AX = ES = DS = SS = сегменту ОЗУ с перенесенными в него данными.
+  Если эту директиву установить в FALSE, регистр DS все равно будет
+  переустановлен на адрес сегмента ОЗУ, так как Ваш код будет использовать
+  этот сегмент для неинициализированных глобальных переменных.
+  Инициализированные переменные останутся в ПЗУ и все обращения к ним будут
+  производиться через регистр CS. Так же останется не тронутым (таким, каким
+  его установил главный BIOS) и стек.
+
+    3.  ?dataseg value - этой директивой компилятору сообщается сегментный
+  адрес ОЗУ, который может быть использован вашим кодом. По умолчанию он
+  равен 0x70. Этот адрес вы можете узнать в любой момент, считав его из вашего
+  кода по смещению 4. Например: DS = CSWORD[4];
+
+      Некоторые замечания:
+
+    1.  Не забывайте, что в момент инициализации ROM-BIOS, DOS еще не
+  загружен, и соответственно все процедуры использующие вызовы DOS работать
+  не будут.
+
+    2. Нельзя завершать работу программы процедурами ABORT() или EXIT() и им
+  подобным. Работа расширителя ROM-BIOS должна завершаться только выходом из
+  процедуры main().
+
+    3. Если директива ?movedatarom установлена в FALSE, то будьте внимательны
+  при работе с инициализированными переменными. Они в этом режиме доступны
+  только для чтения, и адресуются через регистр CS.
+Return to contents.
+
+
+
+  12.8 32-битные файлы.
+
+    12.8.1 32-битный код под DOS.
+
+
+        Для того чтобы откомпилировать 32-битную программу под DOS надо
+    запустить компилятор с ключом командной строки /d32. Но работа 32-битной
+    программы под DOS-ом невозможна без расширителя DOS. Для C-- можно
+    использовать DOS4GW или zrdx.exe или любой другой расширитель DOS. Чтобы
+    компилятор знал, где искать stub файл и его имя, надо в файл c--.ini
+    прописать строку stub=path_name_to_stub_file.  Пример:
+
+        stub=c:\c--\zrdx.exe
+
+        Если не добавлять в c--.ini эту строку, то компилятор сгенерирует
+    32-битный exe-файл, но без расширителя DOS. Если в командной строке
+    вместе с ключом /d32 указать и ключ /ns, то строка с переменной stub из
+    файла c--.ini будет аннулирована, и вы получите файл без расширителя DOS.
+
+        Для 32-битного DOS-файла можно использовать директивы компилятора
+    ?parsecommandline TRUE/FALSE или его расширенный вариант ?argc
+    TRUE/FALSE.  Реализована и поддержка директивы ?atexit TRUE/FALSE.
+
+        Сейчас для 32-битных DOS-файлов используется LE-формат. Так как LE
+    формат является стандартным, то теперь можно использовать почти любой
+    stub, понимающий этот формат. Файлы LE формата можно сжимать программами
+    типа UPX.EXE и ей подобными.
+
+        Если Вы используете stub, который затем загружает DOS4GW.EXE, то
+    начало Вашей программы должно иметь специальную сигнатуру. Компилятор
+    автоматически сформирует ее, если Вы в командной строке или в c--.ini
+    файле укажете ключ /DOS4GW. Такой ключ Вам необходимо будет применять,
+    если Вы будете использовать в качестве stub 4gs.exe.
+
+        Существует также поддержка блока кода использующего для перехода и
+    работы в 32-битном режиме возможности DPMI сервиса. Исходный текст этого
+    блока находится в файле startup.h-- и компилируется, если в командной
+    строке указана опция /stub=dpmi или в файле c--.ini написать строку
+    stub=dpmi.  Недостатком этого способа перехода и работы в 32-битном
+    режиме являются необходимость обязательного функционирования на
+    запускаемом компьютере DPMI сервиса. Так как, программа загружается как
+    обычная DOS программа, и лишь в процессе работы переходит в 32-битный
+    режим работы, размер программы ограничен размером свободной DOS памяти.
+    Ну а преимуществом его является компактный размер исполняемого файла.
+Return to contents.
+
+
+
+    12.8.2 32-битный код под Windows.
+
+
+        Для того чтобы откомпилировать программу, написанную под Windows надо
+    запустить компилятор с ключом командной строки /w32.
+
+        Если Вы в своей программе используете вызовы API-процедур, то эти
+    процедуры надо предварительно обязательно объявить. Объявление процедур
+    имеет следующую форму:
+
+    extern WINAPI "DLL_name"
+    {
+        returncode procname1();
+        returncode procname2();
+        procname3();
+    }
+
+      где:
+           DLL_name - имя и расширение dll-библиотеки, в которой находятся эти
+                      процедуры.
+         returncode - тип возврата из api-процедур. По умолчанию он равен dword.
+
+        Программы, написанные под Windows, имеют одну немаловажную
+    особенность - все параметры в стековые процедуры передаются в обратном
+    порядке (так называемый C-стиль), но очистка стека от параметров
+    происходит в самих процедурах. Получается своеобразный гибрид C и pascal
+    стилей - stdcall.
+
+        С помощю ключа /W32C компилятор создает консольный файл под Windows.
+
+	Если при компиляции указывали опцию командной строки /j0 или
+    директиву #jumptomain NONE, то Ваша программа будет компилироваться без
+    использования кода начальной инициализации, описание которого находится в
+    файле startup.h--.
+
+	Код начальной инициализации для программ под Windows имеет следующий
+    вид:
+
+	hThisInst=GetModuleHandleA(0);
+      #ifdef __CONSOLE__
+	hStdOut=GetStdHandle(-11);
+      #endif
+        lpszArgs=GetCommandLineA();
+      #ifdef __environ;
+	environ=GetEnvironmentStringsA();
+      #endif
+	main();
+	ExitProcess(EAX);
+
+	Таким образом, в глобальных переменных hThisInst будет находится
+    handl запущенного файла, а в lpszArgs адрес командной строки Вашего
+    файла. Если Вы в командной строке указали опции /p или /argc или в
+    начале вашего файла есть директивы #parsecommandline TRUE или argc TRUE,
+	то компилятор создаст дополнительный код сделающий разборку этой
+    командной строки на части. Если Вы компилируете консольную программу, то
+    в вашей программе будет еще одна глобальная переменная - hStdOut. В этой
+    переменной хранится handl стандартного вывода (экрана). Если Вы при
+    компиляции программы указали опцию /env, то в глобальной переменной
+    environ хранится адрес переменной окружения программы.
+
+	После завершения работы процедуры main выполнятся процедура
+    ExitProcess, которой в качестве параметра передается регистр EAX. Т.о.
+    Вам для завершения работы программы будет достаточно сделать выход из
+    процедуры main, предварительно загрузив в регистр EAX нужный Вам код
+    возврата.
+
+        Некоторые компиляторы создают DLL, в которых имена экспортируемых
+    процедур имеют такой формат:
+
+       ProcName@8
+
+        В этом имени после символа @ указывается размер стека с
+    параметрами, передаваемых процедуре.
+
+        Объявлять такие процедуры нужно так:
+
+    extern WINAPI "name.dll"
+    {
+       ProcName@8 ;
+    }
+
+    т.е. без круглых скобок. В программе, при обращении к такой процедуре, ее
+    имя надо писать без суффикса @8, т.е. вот так - ProcName(param1,param2);
+Return to contents.
+
+
+
+    12.8.3 Вызов API процедур по ординалам.
+
+
+        В динамически подключаемых библиотеках (DLL) каждой процедуре, кроме
+    ее имени, соответствует уникальное число, которое называется ординалом. И
+    поэтому, кроме общепринятого вызова API-процедуры по имени, можно делать
+    вызов и по ординалу. Теоретически, при использовании вызова по ординалу,
+    загрузка файла должна происходить быстрее. Так как в выходной файл не
+    будут включены списки имен процедур, вызов которых производится по
+    ординалам, то выходной файл может получиться немного меньшим по размеру.
+
+        Чтобы компилятор создал файл, использующий вызов API-процедур по
+    ординалам, надо сделать две вещи:
+
+     1. Разрешить компилятору это делать. Для этого надо в опциях командной
+    строки (или в файле C--.INI) указать ключ WO.
+
+     2. Сообщить компилятору - какой номер ординала соответствует какому
+    имени процедуры. Процедуры, для которых не был указан ординал, будет
+    создан вызов по имени. Установить соответствие имен процедур ординалу
+    можно двумя способами:
+
+        a). Автоматически, с помощью опции командной строки IND=name.dll,
+	по которой компилятор просканирует эту библиотеку и импортирует из
+	нее все имена и ординалы процедур. (Импорт возможет только из
+	библиотек имеющих формат PE).
+
+        b). В ручную указать в объявлении API-процедур и ее ординал. Делается
+	это так: после имени процедуры ставится точка, а за ней указывается
+	номер ординала. Вот пример объявления API-процедуры с указанием ее
+	ординала:
+
+    extern WINAPI "user32.dll"
+    {
+      ............
+      long  MessageBoxA.429();
+      ............
+    }
+
+        В библиотеках (DLL), иногда существуют процедуры, для которых не
+    указано их имя, но указан номер ординала. Вызов таких процедур по имени
+    не возможен, но можно это сделать по ординалу (если, конечно Вы знаете,
+    для чего эта процедура и что она делает). Для этого в объявлении
+    API-процедуры Вам надо придумать для этой процедуры уникальное имя и
+    указать реальный ординал. Затем в программе Вы будете обращаться к этой
+    процедуре по вымышленному имени. Но если Вы случайно откомпилируете такой
+    файл без ключа WO, то при запуске этой программы Вы получите сообщение,
+    о том, что данного имени в библиотеке нет.
+
+        К сожалению, нет никаких гарантий того, что номер ординала для данной
+    процедуры не изменится при смене версии динамической библиотеки. Поэтому
+    использовать ординалы надо осторожно.
+Return to contents.
+
+
+
+    12.8.4 Создание DLL под Windows.
+
+
+        Динамически подключаемые библиотеки позволят получать более
+    компактные программы и ускорить процесс компиляции. К минусам
+    использования DLL можно отнести необходимость наличия самих файлов DLL на
+    запускаемом компьютере и немного увеличивается время запуска программы.
+
+        Для того чтобы процедура стала доступной для других программ надо в
+    исходном тексте перед именем процедуры прописать ключевое слово - _export.
+    Пример:
+
+      void _export testproc()
+      {
+        ....
+      }
+
+        Для того чтобы создать DLL, нужно написать файл, в котором будут
+    процедуры с ключевыми словами _export. Вспомогательные процедуры, которые
+    могут понадобиться для работы основных экспортируемых процедур, объявлять
+    как _export необязательно. Затем этот файл нужно откомпилировать с ключом
+    /dll.  В результате Вы получите готовую динамически подключаемую
+    библиотеку.
+Return to contents.
+
+
+
+    12.8.5 Инициализация DLL при загрузке.
+
+
+        Иногда, для работы процедур из динамических библиотек (DLL), бывает
+    необходимым инициализировать некоторые переменные значениями, зависящими
+    от текущего состояния операционной системы, например, получить дескриптор
+    этой библиотеки.
+
+      Директивой #jumptomain NONE (-j0) управление при запуске передается
+    сразу на процедуру main.
+
+      Во всех остальных случаях генерируется код заглушки и управление на
+    процедуру main не передается. Фактически процедура main в этом случае не
+    нужна.
+
+      Процедура main при создании файлов DLL должна выглядеть немного иначе,
+    чем в других случаях:
+
+    dword main ( dword hInstDLL, reason, reserv )
+    {
+      ...
+    }
+Return to contents.
+
+
+
+    12.8.6 Компиляция ресурсов.
+
+
+        Встроенный в C-- компилятор ресурсов по своим возможностям уступает
+    специализированным компиляторам ресурсов, но этих возможностей, как мне
+    кажется, будет достаточно для большинства Ваших задач.
+
+        Будет проще перечислить то, что встроенный в C-- компилятор ресурсов
+    не умеет делать. Не обрабатываются операторы ресурсов: VERSION,
+    VERSIONINFO и определяемые пользователем ресурсы. При необходимости,
+    данные, вводимые с помощью этих операторов, можно ввести с помощью
+    оператора RCDATA. У многих операторов ресурсов есть необязательные
+    параметры loading и 'memory'.  Поддержка этих параметров не
+    реализована. Встретив эти параметры, компилятор их просто пропустит.
+
+        Заставить компилятор C-- обрабатывать ресурсы можно двумя способами:
+
+        1. Включить в свой проект директивой #include файл с расширением
+    .rc.  Файлы с таким расширением компилятор считает файлом с ресурсами.
+    Файл ресурсов необходимо включать в Ваш проект лишь после включения
+    заголовочных файлов Windows.
+
+        2. Ресурсы можно располагать в теле исходного текста программы в
+    произвольном месте. Текст ресурсов должен начинаться с директивы #pragma
+    resource start, а заканчиваться директивой #pragma resoutce end.
+    Ресурсы могут быть разделенными на части и эти части можно располагать в
+    любом удобном для Вас месте (глупо располагать ресурсы в блоке
+    комментариев и потом удивляться, почему они не были откомпилированы).
+    Компилятор соберет эти части и откомпилирует.
+
+        Имена операторов можно писать как большими, так и маленькими буквами,
+    но имена идентификаторов чувствительны к регистру.  В тексте ресурсов
+    можно использовать директивы и комментарии.
+
+        Ничто не мешает Вам использовать компиляторы ресурсов от других
+    языков.  Главное, чтобы синтаксис файла ресурсов соответствовал выбранному
+    компилятору.
+Return to contents.
+
+
+
+  12.9 Выходные файлы для MeOS.
+
+
+      Исполняемые файлы для операционной системы MenuetOS поддерживаются
+  компилятором совсем недавно. Для того, чтобы откомпилировать файл для
+  MenuetOS, нужно в опциях компилятору указать /meos. Вы получите файл без
+  расширения, который потом можно будет выполнить в среде операционной
+  системы MenuetOS.
+
+      Если при компиляции файла Вы не указывали опцию /j0 или не
+  использовали директиву #jumptomain NONE, то компилятор будет использовать
+  файл начальной инициализации startup.h--, в котором для операционной
+  системы MenuetOS создан блок инициализации и завершения программы.
+  Завершать выполнение таких программ можно просто выйдя из процедуры main.
+Return to contents.
+
+
+
+13. Приложения.
+
+  13.1 Поиск включаемых файлов.
+
+
+      Поиск включаемого в вашу программу файла, имя которого объявляется
+  директивой include и заключено в двойные кавычки "", производится
+  компилятором по такой схеме:
+
+  сначала делается попытка открыть файл в текущей директории. Если файла там
+  нет, то далее делается попытка открыть файл в директории указанной
+  директивой #includepath. Если директива не была задана или файла в этой
+  директории не оказалось, то делается попытка открыть файл в директории
+  указанной в командной строке командой /ip=path. Если эта команда не была
+  задана или файла в указанной директории не оказалось, то делается попытка
+  открыть файл в директории указанной в файле C--.INI командой ip=. Если эта
+  команда не была задана или файла в указанной директории не оказалось, то
+  делается попытка открыть файл в директории, на которую указывает переменная
+  окружения C--. Если переменная окружения не была задана или файла в этой
+  директории не оказалось, то делается последняя попытка открыть файл в
+  директории, откуда был запущен компилятор.
+
+      Если имя включаемого файла заключено в угловые скобки < >, то поиск
+  этого файла производится в противоположном направлении, за исключением
+  того, что поиск в текущей директории не производится.
+
+      Для консольной версии компилятора имена главного модуля и включаемых
+  файлов могут иметь длину более 8 символов.
+Return to contents.
+
+
+
+  13.2 Регистры, которые должны быть сохранены.
+
+
+      Регистры, которые должны сохраняться - BP, DI, SI, DS, SS, SP, CS и IP.
+
+      BP используется как указатель на локальные и параметрические
+  переменные в стеке, что и требует его сохранения.
+
+      DI и SI сохранять не обязательно, если программист осознает
+  последствия. DI и SI часто используются для индексации массивов, как
+  например в формуле:
+
+        dog = firehydrant(1,red) + legs[DI];
+
+      Если DI не сохранялся в процедуре firehydrant, значение, присвоенное
+  переменной dog, скорее всего, будет неправильным, поскольку индекс для
+  массива legs был изменен. В сущности, для точного согласования все
+  процедуры должны иметь специальное указание в комментарии на то, что в них
+  не сохраняется содержимое регистров DI и/или SI.
+
+      DS указывает на сегмент данных, и все операции с глобальными
+  переменными пользуются этим значением.
+
+      SS хранит сегмент стека и должен сохраняться. SP указывает на текущую
+  позицию в стеке и тоже должен сохраняться.
+
+      CS хранит сегмент кода программы.  Все команды выбираются с
+  использованием CS и IP, следовательно их значения должны сохраняться. IP,
+  как известно, указатель адреса команды, и CS и IP непосредственно не могут
+  изменяться в процессорах 8086, 8088, 80286, 80386, 80486,...
+Return to contents.
+
+
+
+  13.3 C--.ini файл.
+
+
+      C--.ini файл предназначен для предустановки по умолчанию параметров
+  компилятора.
+
+      Сейчас компилятор поддерживает огромное число параметров командной
+  строки. Правильное их использование позволит Вам получать более компактный
+  код и может значительно облегчить Вам отладку программы. Но так как этих
+  параметров очень много набирать их каждый раз в командной строке бывает
+  утомительно и не исключена возможность пропустить какой-нибудь параметр.
+  Чтобы избавить Вас от всех этих напастей и был введен c--.ini файл.
+
+       Параметры командной строки прописываются в этом файле построчно.
+  Синтаксис тот же, что и в командной строке, но без ведущего обратного слэша
+  или минуса. Если файл расположен в директории, на которую указывает
+  переменная окружения set c--= или если эта переменная не определена,
+  то в той же директории где и файл c--.exe, то эти параметры
+  распространяются на все компилируемые программы. Если же файл c--.ini
+  расположен в текущей директории, то параметры считываются только из этого
+  файла и действуют только для текущего проекта.
+
+      Допустимо использование комментариев. Признаком начала комментария
+  является символ ;. Все последующие символы после ; и до конца строки
+  считаются комментарием.
+
+      Пример C--.ini файла:
+
+  r-
+  X
+  3     ;это комментарий
+  os
+
+      ini-файл может иметь любое имя (но расширение должно быть обязательно
+  ini). Имя этого файла с расширением должно быть передано компилятору в
+  командной строке. Файл c--.ini загружается и обрабатывается автоматически
+  до загрузки файла указанного в командной строке.
+
+      Таким образом, файл *.ini можно использовать подобно make-файлу - в нем
+  Вы можете указать и имя главного компилируемого модуля, и все необходимые
+  для его компиляции настройки.
+
+      Как альтернативу c--.ini файлу, параметры командной строки можно
+  прописывать непосредственно в начале главного файла компилируемого проекта,
+  используя директиву pragma option. С одной стороны это обеспечит Вашему
+  проекту независимость от настроек компилятора, если Ваш проект будет
+  компилироваться на другом компьютере. Но с другой стороны некоторые
+  настройки являются индивидуальными для данного компьютера (это расположение
+  библиотек, имена и расположение stub-файлов). Какой вариант использовать
+  решать Вам, но как говорят, и я с этим согласен, лучше пользоваться золотой
+  серединой - Часть параметров прописать в c--.ini файле, а другую
+  непосредственно в компилируемом файле.
+Return to contents.
+
+
+
+  13.4 startup.h-- файл.
+
+
+      В этом файле находятся исходные тексты, которые компилируются
+  компилятором в код начальной инициализации файла, для всех поддерживаемых
+  компилятором типов выходных файлов. Этот файл должен находится либо в
+  директории вместе с компилятором, либо в директории с библиотечными файлами.
+  Этот файл включается компилятором в проект автоматически, а включение его
+  директивой include может привести к нежелательным результатам.
+
+      В блоке начальной инициализации программы может производится (если Вы
+  это укажете с помощью опций командной строки или используя директивы),
+  разбор командной строки на параметры, сохранение переменой окружения,
+  поддержка работы процедуры ATEXIT, изменение размера доступной памяти для
+  *.com файлов и многие другие подготовительные операции. Если Вы
+  откомпилируете свой файл не используя никаких опций командной строки и у
+  Вас будет отсутствовать c--.ini файл, а в самом компилируемом файле у Вас
+  будут отсутствовать директивы, то при компиляции *.com файла в него будет
+  включен блок изменяющий размер доступной памяти и сигнатура SPHINXC--.
+
+      Если Вы компилируете файл типа *.exe (кроме файла модели tiny для DOS)
+  и используете директиву jumptomain NONE или ключ командной строки /j0,
+  то для этого проекта файл startup.h-- компилятором не используется. Не
+  используется этот файл также при компиляции *.com файлов если, кроме /j0,
+  в этом проекте не используется разбор командной строки (/p /argc), не
+  применяется процедура ATEXIT (/at), не используется адрес переменной
+  окружения (/env), не используется очистка области post-адресов (/cpa), не
+  используется уменьшение доступной программе памяти (/r) и не используется
+  заглушка нажатий CTRL-C (/c).
+
+      Кроме блока начальной инициализации программы в файле startup.h--
+  находятся динамические процедуры:
+
+  void CLEARPOSTAREA( (E)AX );  - очистка post-области данных.
+  unsigned int PARAMSTR( ECX ); - получить адрес элемента командной строки
+  unsigned int PARAMCOUNT();    - получить число элементов в командной строке
+
+      При разборе командной строки на составляющие ее элементы для 32-битных
+  программ реализована поддержка длинных имен. Для 16-битных программ
+  поддержка разбора командной строки с учетом длинных имен подключается, если
+  Вы в начале свой программы укажете директиву:
+
+  #define _USELONGNAME TRUE
+
+      либо в c--.ini файле или в командной строке компилятора укажете опцию
+  d=_USELONGNAME.
+Return to contents.
+
+
+
+  13.5 mainlib.ldp файл.
+
+
+      В этом файле находится большое число процедур из основной библиотеки
+  компилятора в уже откомпилированном виде. Все процедуры откомпилированы в
+  4-х различных режимах оптимизации. В этот файл также вынесены многие
+  процедуры, которые ранее были внутри компилятора. Использование ранее
+  откомпилированных процедур повышает скорость компиляции.
+
+      Эти процедуры откомпилированы только для 16-битного режима работы
+  программы. Если Вы будете использовать эти процедуры в 32-битной программе,
+  то компилятор на это не выдаст никаких сообщений и включит эту процедуру в
+  Ваш код. Но при запуске такой программы она неизбежно потерпит крах.
+
+      Использовать эту библиотеку очень просто. Все что нужно, это
+  расположить эту библиотеку в одной с компилятором директории. Тогда
+  компилятор, если встретит в вашей программе вызов процедуры, которая не
+  была определена ни во включаемых в программу библиотечных файлах, ни в
+  вашей программе, будет искать эту процедуру в файле mainlib.ldp. Если эта
+  процедура будет найдена в этом файле, то ее код будет перенесен в Ваш файл,
+  иначе будет выдано сообщение о неизвестной процедуре. Таким образом, чтобы
+  процедура была вставлена в вашу программу из библиотеки mainlib.ldp Вам
+  нужно в свою программу не включать библиотечный файл, содержащий процедуру с
+  таким же именем.
+
+      Список процедур находящихся в этой библиотеке можно получить с помощью
+  специальной программы cmmlib.exe. Эту программу можно найти в архиве
+  cmmlib.rar. Извлеките программу cmmlib.exe из этого архива и расположите ее
+  в одной с компилятором директории. Затем запустите эту программу с ключом
+  /L и Вы получите список процедур находящихся в этой библиотеке.
+Return to contents.
+
+
+
+  13.6 C-- символы.
+
+
+  SYMBOL|FUNCTION                  |EXAMPLE
+  --------------------------------------------------------------------
+    /*  |начинают блок комментария |/* комментарий */
+    */  |завершают блок комментария|/* комментарий */
+        |                          |
+    //  |комментарий до конца линии|// комментарий
+        |                          |
+     =  |присвоение                |AX = 12;
+     +  |сложение                  |AX = BX + 12;
+     -  |вычитание                 |house = dog - church;
+     *  |умножение или указатель   |x = y * z; AL = * var;
+     /  |деление                   |x1 = dog / legs;
+     &  |поразрядное логическое И  |polution = stupid & pointless;
+     |  |поразрядное логическое ИЛИ|yes = i | mabe;
+     ^  |поразрядн. исключающее ИЛИ|snap = got ^ power;
+    <<  |битовый сдвиг влево       |x = y << z;
+    >>  |битовый сдвиг вправо      |x = y >> z;
+        |                          |
+    +=  |сложение                  |fox += 12;   // fox = fox +12;
+    -=  |вычитание                 |cow -= BX;   // cow = cow - BX;
+    *=  |умножение                 |a *= b;      // a = a * b;
+    /=  |деление                   |a /= b;      // a = a / b;
+    &=  |поразрядное логическое И  |p &= q;      // p = p & q;
+    |=  |поразрядное логическое ИЛИ|p |= z;      // p = p | z;
+    ^=  |поразрядн. исключающее ИЛИ|u ^= s;      // u = u ^ s;
+    <<= |битовый сдвиг влево       |x <<= z;     // x = x << z
+    >>= |битовый сдвиг вправо      |x >>= z;     // x = x >> z
+        |                          |
+    ><  |обмен значениями          |x >< y; /* меняет местами значения x и y */
+        |                          |
+    ==  |проверка на равенство     |IF(AX == 12)
+     >  |проверка на больше чем    |IF(junk > BOGUS)
+     <  |проверка на меньше чем    |if( x < y )
+    >=  |проверка больше или равно |if(AX >= 12)
+    <=  |проверка меньше или равно |IF(BL >= CH)
+   !=   |проверка на неравенство   |IF(girl != boy)
+    <>  |проверка на отличие       |if (cat<>dog) /* та же функция что != */
+        |                          |
+    @   |вставка кода              |@ COLDBOOT(); /* вставляет COLDBOOT код */
+    :   |динамическая процедура    |: functionname () //объявляет functionname
+    $   |ассемблерная команда      |$ PUSH AX   /* заносит AX в стек */
+    #   |получение адреса(смещения)|loc = #cow;    /* loc = address of cow */
+        |или директива             | #resize FALSE
+    !   |оператор NOT или смена    |!x_var;  if(!proc())
+        |флага операции сравнения. |
+   ...  |любое число параметров в  | void proc(...);
+   ::   |разрешение видимости      | ::var=0;
+Return to contents.
+
+                
+

+ +

+ +
+ +
+
+
+ + + + + +
+ +