ПРИЛОЖЕНИЕ A
----------------------------------------------------------
                             Обсуждение работы с числами
----------------------------------------------------------

     В процессе выполнения программы ТУРБО БЕЙСИКу прихо-
дится  иногда  преобразовывать  внутренние  представления
числовых значений из одной формы в другую; например, чис-
ло с одинарной точностью в целое:

    А=14.1
    В%=А

В таких случаях ТУРБО БЕЙСИК решает, как быть с  излишней
или  недостающей  точностью.  Следующие правила управляют
преобразованием числовых типов:
    В  операторе  присваивания   число   запоминается   с
точностью, соответствующей  точности переменной,  которой
оно  присваивается  (т.е.  переменной,  стоящей  слева от
знака равенства). Например:

    В=1.1
    А%=В
    PRINT A%

    Во всех  случаях, когда значение с большей  точностью
присваивается переменной с меньшей точностью, выполняется
округление. Например:

    A%=1.5
    B=123.456789
    PRINT A%,B

Обратите,  однако,  внимание,  что   ТУРБО БЕЙСИК  особым
образом рассматривает любые числа, содержащие 5 в дробной
части:  такое  число  всегда  округляется  до  ближайшего
четного  числа.  Например,   0.5  округлится  в   сторону
меньшего  -  до  0,  9.005  также  округлится  в  сторону
меньшего - до 9.00.
    Если число  с меньшей точностью преобразуется в число
с  большей  точностью,  результирующее  значение не может
быть  более  точным,  чем  исходное.  После присваивания,
приведенного  в  следующем  примере,  значимыми  являются
только 6 цифр переменной B#:

    A=123.456
    B#=A
    PRINT B#

    При  вычислении   числового   выражения  ТУРБО БЕЙСИК
преобразует  все  операнды  выражения  в  соответствии  с
наиболее точным из них. Например:

    A=1.1: B#=1.123456
    C=A*B#
    PRINT A*B#,C

Обратите внимание, что для выражений, содержащих операнды
и с одинарной, и с двойной точностью, точность результата
будет одинарной.

    Компьютеры и множество вещественных чисел.
    ------------------------------------------
    Множество вещественных чисел  включает  и  бесконечно
большие и бесконечно малые числа.  В дополнение к минус и
плюс бесконечности,  между любыми двумя точками на число-
вой прямой  имеется бесконечное число точек (чисел). Так,
например, между 17.1  и  17.11  находятся  точки  17.101;
17.104; 17.1041 и т. д.
    Будучи конечными автоматами, компьютеры не могут точ-
но представлять это трансцендентное множество чисел,  од-
нако, они могут представлять  их  приближенные  значения.
Компромисс между качеством аппроксимации (т. е. точности)
с одной стороны,  и скоростью вычислений и потребностью в
памяти, с другой,  привели к созданию двух наиболее попу-
лярных способов представления множества вещественных  чи-
сел: числа  с  одинарной точностью и числа с двойной точ-
ностью.
    Обе эти  модели  отображают конечное,  но практически
очень большое множество дискретных значений на значитель-
ном отрезке вещественной числовой прямой.  Между смежными
значениями на ней имеются промежутки. Если при вычислении
результат  попадает  в  промежуток,  выполняется округле-
ние до ближайшей представимой точки.
    Плотность представимых значений распределена неодина-
ково   вдоль   числовой   прямой.    Равное    количество
представимых чисел находится между целыми степенями двой-
ки. Например,  между 1 и 2 столько же представимых чисел,
сколько и между 131072 и 262144.  Другими словами, проме-
жутки между представимыми  значениями  становятся  больше
при движении в любом направлении от нуля на числовой пря-
мой. Наконец,  вы заберетесь так далеко от нуля,  что там
не останется представимых точек.  Использование чисел вне
представимых значений в любом направлении числовой прямой
приводит к переполнению.

    Переполнение и потеря значимости
    - - - - - - - - - - - - - - - - -
    Переполнение числа с плавающей точкой возникает в тех
случаях, когда результат вычислений  больше максимального
представимого положительного  значения  или меньше макси-
мального отрицательного числа. В силу обширности диапазо-
на значений,  допустимых  в  ТУРБО БЕЙСИКе,  переполнение
числа с плавающей точкой является нетипичной ситуацией. В
отличие от переполнения целого числа,  переполнение числа
с плавающей точкой всегда регистрируется.
    Потеря значимости  числа с плавающей точкой возникает
в случаях,  когда результат вычислений попадает в крошеч-
ный интервал  между 0 и первым представимым отрицательным
или положительным числом на одном из лучей числовой  пря-
мой. Математические  подпрограммы ТУРБО БЕЙСИКа обрабаты-
вают подобные ситуации присвоением 0 величине,  у которой
произошла потеря   значимости,  и  продолжают  выполнение
программы без вывода сообщения об ошибке.

    Файлы произвольного доступа, содержащие данные с пла-
    вающей запятой.
    - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Поскольку     Интерпретатор     БЕЙСИК     использует
нестандартный  формат  Microsoft  для  чисел  с плавающей
запятой, в программах на ТУРБО БЕЙСИКе должны выполняться
специальные преобразования для  чтения и записи  данных в
файлы с произвольным доступом, созданные  Интерпретатором
БЕЙСИКа. Функции MKMS$  и MKMD$ (make  Microsoft) создают
числовые строки в формате Microsoft; CVMS и CVMD (convert
Microsoft)  обрабатывают   числовые  строки   в   формате
Microsoft и  возвращают числовые  данные в  формате ТУРБО
БЕЙСИКа.

    Внутреннее представление четырех типов чисел.
    ---------------------------------------------

             ---------------------
             I   I величина или  I
     Целое   I S I  дополнение   I
             I   I    до двух    I
             ---------------------
              15                0

             -------------------------------
     Длинное I   I     величина или        I
     целое   I S I      дополнение         I
             I   I        до двух          I
             -------------------------------
              31                          0

             -------------------------------
    ОдинарноеI   Iсмещенный I              I
     вещест- I S IпоказательI  мантисса    I
     венное  I   Iстепени   I              I
             -------------------------------
              31         23 I             0

             --------------------------------------------
     Двойное I   I  смещенный     I                     I
     вещест- I S I  показатель    I       мантисса      I
     венное  I   I  степени       I                     I
             --------------------------------------------
              63               52 I                    0

   S - знаковый бит
(0 - положительное число, 1 - отрицательное)

   Смещенный показатель степени ( нормализованное значение )
Короткое вещественное: 127 (7FH)
Длинное  вещественное: 1023 (3FFH)

                 Рисунок А-1. Форматы данных

    Целые  числа
    - - - - - - -
    Целые  числа представляются в виде 16-битовых (2-бай-
товых) чисел  со знаками.  Отрицательные числа хранятся в
дополнительном коде. Дополнительный код в двоичной систе-
ме означает,  что все  биты меняют значения на противопо-
ложные и к результату добавляется 1.

                   -----------------T-------------------¬
                   ¦    байт  0     ¦      байт  1      ¦
------------------T+----------------+-------------------+
¦Шестнадцатеричное¦       13        ¦        02         ¦
+-----------------+-----------------+-------------------+
¦Двоичное         ¦    00010011     ¦     00000010      ¦
L-----------------¦-----------------+--------------------

    Длинные целые
    - - - - - - -
    Длинные целые  представляются   в   виде   32-битовых
(4-байтовых) чисел  со знаками.  Отрицательные числа хра-
нятся в дополнительном коде.  Наименее значимое слово за-
писывается первым (по младшему адресу), а наименее значи-
мый байт  каждого слова располагается до более значимого.
Например, десятичное   число   79033  равно  000134B9h  и
записывается в виде последовательности байтов B9h 34h 01h
и 00h:
                   -----------------T-------------------¬
                   ¦байт 0 I байт 1 ¦  байт 2 I байт 3  ¦
------------------T+----------------+-------------------+
¦Шестнадцатеричное¦   B9   I   34   ¦    01   I   00    ¦
+-----------------+-----------------+-------------------+
¦Двоичное         ¦10111001 00110100¦ 00000001 00000000 ¦
L-----------------¦-----------------+--------------------

А десятичное число -79033 равно дополнению к  000134B9h -
FFFECB47h и  хранится в виде последовательности байтов 47
CB FE FF.

    Числа с плавающей запятой одинарной точности
    - - - - - - - - - - - - - - - - - - - - - - -
    Числа с одинарной точностью в ТУРБО БЕЙСИКе соответс-
твуют коротким  вещественным значениям,  принятым в стан-
дарте IEEE.  В этом формате число записывается в 4 байтах
памяти с  точностью  от  6 до 7 десятичных знаков и может
иметь значение в приближенном диапазоне:

    8.43e-37 <= abs(X) <= 3.37e+38

    Числа с одинарной  точностью  состоят  из  23-битовой
нормализованной мантиссы,  8-битового  показателя степени
со смещением 7FH и знакового бита,  размещенных так,  как
показано на  рисунке А-1.  (Смещение относится к разности
между беззнаковым целым,  записываемым в поле  показателя
степени числа с плавающей точкой, и непосредственно пока-
зателем степени, который это целое представляет.)

    Далее приводится программа,демонстрирующая внутренний
формат представления числа с одинарной точностью  в ТУРБО
БЕЙСИКе:

    а1=167.25
    address=VARPTR(a)
    FOR n=0 TO 3
      byteval=PEEK(address+n)
      PRINT HEX$(byteval)
    NEXT n

    Давайте расшифруем полученные четыре  байтовых значе-
ния,  представляющие число 167.25  с одинарной точностью.
Сначала перезапишем так, что наиболее значимый байт будет
следовать первым: 43 27 40 00

    Теперь представим в двоичном виде:

         -------------------------------------------
     hex I  4    3    2    7    4    0    0    0   I
         -------------------------------------------
     bin I 0100 0011 0010 0111 0100 0000 0000 0000 I
         -------------------------------------------

    Выделим знаковый бит, показатель степени и мантиссу:

         ------------------------------------------------
     bin I  0  I  10000110  I  01001110100000000000000  I
         ------------------------------------------------

    Вычтем смещение 7FH из показателя степени:
    86h - 7Fh = 7  -  получим истинное  двоичное значение
показателя степени.
    Нормализованная  мантисса  имеет  подразумеваемые 1 и
двоичную точку с левого края,  так что в действительности
значение мантиссы равно:

    1.010 011 101 000 000 000 000 00

    Перемещение  двоичной  точки  на семь знаков с учетом
показателя степени приводит к результату:

    10 100 111. 010 000 000 000 000 0=167.25

    Числа с плавающей запятой с двойной точностью
    - - - - - - - - - - - - - - - - - - - - - - -
    Вещественные числа с двойной точностью,  используемые
в ТУРБО БЕЙСИКе,  соответствуют длинным вещественным чис-
лам в стандарте IEEE. В этом формате число записывается в
8 байтах памяти с точностью от 15 до 16 десятичных цифр и
может иметь значение в приближенном диапазоне:

    4.19e-307 <= abs(X) <= 1.67e+308

    Значения  с  двойной  точностью состоят из 52-битовой
нормализованной мантиссы, 11-битового показателя  степени
со смещением 3FFH и знакового бита, размещенных как пока-
зано на рисунке А-1.


                        ПРИЛОЖЕНИЕ В
-----------------------------------------------------------------
                                         Прерывания по событиям
-----------------------------------------------------------------

    ТУРБО БЕЙСИК  поддерживает возможность фоновой обработки, из-
вестной как прерывания при возникновении событий,  которые  могут
одновременно  и упростить и ускорить отдельные операции. Прерыва-
ние по событию означает, что проверку  различных  событий,  таких
как  нажатие  определенной клавиши, выполняет сам ТУРБО БЕЙСИК, и
нет необходимости писать операторы, чтобы  делать  это  самостоя-
тельно. ТУРБО БЕЙСИК может выполнять такую проверку между каждыми
двумя операторами вашей программы и гарантирует при этом наиболее
быстрый  возможный  ответ. Когда событие наступает, автоматически
вызывается подпрограмма, которую вы задали для обработки прерыва-
ния.
    Проверяться могут следующие типы событий:
    - Клавишные: была ли нажата клавиша F10? Или пробел? Или кла-
виша SHIFT-ALT-K?  Можно  определить прерывания  для 20 различных
клавиш одновременно.
    - Состояние таймера, работающего  в режиме вычитания - управ-
ление передаётся подпрограмме обработки прерывания по истечении n
секунд,  например,  для  обновления  экранного времени  каждые 60
секунд.
    - Нажатие кнопки джойстика.
    - Действия светового пера.
    - Состояние буфера фоновой музыки (проверка необходимости за-
грузки в буфер дополнительного количества нот).
    Вы  можете получить краткое описание событий, вызывающих и не
вызывающих прерывание, просмотрев в главе 5 "Справочное руководс-
тво по ТУРБО БЕЙСИКУ" данного пособия разделы на букву "O". Боль-
шинство операторов "ON что-либо  GOSUB"  управляют  прерываниями,
связанными с событиями.
    Нет  нужды специальным образом сообщать ТУРБО БЕЙСИКУ о необ-
ходимости генерации кода обработки прерывания  по  событиям.  Его
автоматически  генерирует  компилятор всякий раз, когда встречает
любые инструкции, связанные с прерываниями.

    Пример
    - - - -
    Представьте программу ведения учета с дюжиной меню для выбора
варианта  работы с большим количеством выводимых экранов. Как ав-
тор столь сложной прикладной системы, вы можете пожелать  включе-
ния  вспомогательных экранов, содержащих основную информацию о еe
использовании, такую, как например, описание  комбинаций  клавиш,
необходимых  для  редактирования полей данных или преждевременной
отмены выбранного пункта меню. Для  простоты  рассмотрим  систему
вызова вспомогательной информации,  не являющейся контекстнозави-
симой, т.е.  независимо от того, в каком месте программы в момент
запроса вспомогательной информации находится  пользователь, выво-
дится всегда один и тот же текст.
    Пусть F1 - клавиша вызова вспомогательной информации. Другими
словами,  когда бы ни была нажата клавиша F1, независимо от теку-
щего контекста на экран будет выведена  вспомогательная  информа-
ция.
    Возможность прерывания при возникновении событий в ТУРБО БЕЙ-
СИКЕ  позволяет  кодировать  "вывод вспомогательной информации" в
одном месте программы, а затем вызывать его без лишних  усилий  в
любом  ее  месте.  Если бы возможности обработки событий не было,
приходилось бы проверять состояние клавиши F1 (с помощью перехода
GOSUB на вспомогательную подпрограмму) в каждом месте  программы,
где пользователь может на некоторое время задержаться.
    Во-первых,  поскольку дело  касается клавишного прерывания (а
не прерывания по джойстику или световому перу), следует с помощью
оператора ON KEY(n) определить подпрограмму, которая получит  уп-
равление при нажатии клавиши F1:

    ON KEY(1) GOSUB DispHelpText

    В  этой  строке определяется, что когда прерывание по клавише
включено, между каждыми двумя операторами  выполняется  проверка:
была  ли  нажата  клавиша  F1. Если была, вызывается подпрограмма
DispHelpText; если не была, выполняется следующий оператор.
    Подпрограмма DispHelpText есть ни что  иное,  как  последова-
тельность операторов PRINT. Поскольку выполнение прерванной прог-
раммы  при  этом  не должно быть нарушено, подпрограмма сохраняет
текущую позицию курсора, а затем после завершения вывода  на  эк-
ран,  восстанавливает  её. Вспомогательная информация воспроизво-
дится в шести  нижних  строках экрана, где  по  соглашению  ничто
больше не выводится.

    DispHelpText:
      oldcsrx=POS(0): oldcsry=CSRLIN
      LOCATE 20,1
      PRINT "Эта программа была выпущена в эксплуатацию вместе с"
      PRINT "замечательным дорогостоящим руководством, тщательно"
      PRINT "подготовленным профессиональными писателями. Оно   "
      PRINT "содержит больше информации, чем вам когда-либо     "
      PRINT "понадобится. Используйте его. Нажмите пробел, чтобы"
      INPUT "продолжить.", dummy$
      LOCATE 22,1: PRINT SPACE$(320)
      LOCATE oldcsrx, oldcsry
    RETURN

    Теперь,  когда подпрограмма обработки прерывания (код, на ко-
торый будет передано управление при нажатии клавиши F1)  объявле-
на, включите обработку прерывания с помощью оператора KEY(n)

    KEY(1) ON

    После  выполнения  этого  оператора, ТУРБО БЕЙСИК переходит в
режим проверки событий. Перед выполнением каждого следующего  опе-
ратора, он производит быструю проверку того, была ли нажата клави-
ша  F1. Если не была, выполняется следующий оператор. Если клавиша
F1 была нажата, вызывается подпрограмма DispHelpText. После  возв-
рата из неe с помощью оператора RETURN, управление передается сле-
дующему оператору в прерванной последовательности.
    Когда возникает прерывание, связанное с наступлением заданного
события  выполняется  неявный  оператор "остановки прерываний" для
того, чтобы избежать повторных вызовов подпрограммы обработки пре-
рываний из нее самой (и переполнения таким образом стека).  Завер-
шающий  подпрограмму оператор RETURN автоматически выполняет неяв-
ный оператор "включения прерывания", если  только  в  подпрограмме
явно  не содержится оператор "отключить прерывание". Вы можете за-
менить слова PEN, PLAY, KEY, STRIG, TIMER и COM  словом  "прерыва-
ние".

    Настройка прерываний при наступлении события.
    ---------------------------------------------

средство, но оно имеет цену. Поскольку между выполнением  каждых
двух  операторов  вашей  программы производится проверка события
(или событий), ее работа замедляется, что, в зависимости от кон-
кретных приложений, может привести к недопустимо маленькой  ско-
рости. Кроме того, компилятор для программы, связанной с преры-
ваниями  по  событиям,  генерирует более длинный код (1 дополни-
тельный байт на каждый оператор), чем для программы, не  связан-
ной с ними.
    Для  управления  генерацией  кода  проверки событий в ТУРБО
БЕЙСИКе служит метаоператор $EVENT. В программах, которые  обра-
батывают  прерывания  по  событиям в отдельных частях программы,
следует использовать метаоператор $EVENT.  $EVENT  OFF  отменяет
генерацию кода проверки событий до тех пор, пока не будет выпол-
нен метаоператор $EVENT ON.
    Для иллюстрации, рассмотрим подпрограмму сортировки в прог-
рамме  ведения учета, упомянутой ранее. Сортировки работают мед-
ленно, даже без остановки после  выполнения  каждого  оператора,
чтобы  проверить, была ли нажата клавиша F1. Более того, так как
сортировка не требует ввода от пользователя, какой смысл в выво-
де на экран вспомогательной информации?
    Решение состоит в том, чтобы заключить  подпрограмму  между
метаоператорами $EVENT:

     ON KEY(1) GOSUB DispHelpText
     KEY(1) ON
     .
     .   тело основной программы...
     .
     $EVENT OFF
     Sortroutine:
     .
     .   здесь код проверки событий не генерируется;
     .   это экономит время и память.
     .
     EndSortroutine:
     $EVENT ON
     .
     .   остальная часть программы
     .
     END

     Существует  значительная разница между $EVENT и отключением
прерывания с помощью оператора KEY(10) OFF, обычно  используемым
в  Интерпретаторе БЕЙСИКа. Дело в том, что KEY(10) OFF - это ди-
намический оператор (т.е. он выполняется во время прогона  прог-
раммы),  который  отключает реакцию на нажатие клавишы F1, но не
отключает выполнения проверок, с соответствующими затратами вре-
мени. Они участвуют в ходе работы программы, так как код провер-
ки вставляется между каждыми двумя операторами. Тогда как $EVENT
- оператор, выполняющийся на этапе компиляции, который управляет
тем, будет ли компилятор генерировать код проверки события.
     Для отмены генерации кода проверки событий в части програм-
мы используется метаоператор $EVENT OFF. В этом случае  выполне-
ние оператора KEY(1) ON не вызывает никакого действия.


                        ПРИЛОЖЕНИЕ C
---------------------------------------------------------------
                                Интерфейс с языком ассемблера
---------------------------------------------------------------

     При  разработке  некоторых  прикладных систем может возник-
нуть задача, которая либо слишком долго решается в  ТУРБО БЕЙСИ-
Ке,  либо  по каким-то причинам вообще не может быть реализована
на нем. Для того, чтобы обеспечить потребность в большей скорос-
ти и гибкости, ТУРБО БЕЙСИК позволяет программе  вызывать  подп-
рограммы, написанные на ассемблере и обращаться к функциям DOS и
BIOS.
     В ТУРБО БЕЙСИКе имеются три формы оператора CALL:
     1) Вызов процедуры (CALL). Процедура может быть написана на
на  ТУРБО БЕЙСИКе  или  является встроенной (INLINE) процедурой,
написанной на языке  ассемблера. Встроенное ассемблирование  яв-
ляется наиболее мощной формой интерфейса с ассемблером.
     2)   Вызов   подпрограммы   по   абсолютному  адресу  (CALL
ABSOLUTE). Подпрограмма, написанная на  ассемблере,  уже  должна
быть загружена в память. Эта возможность реализована для обеспе-
чения максимальной совместимости с Интерпретатором БЕЙСИКа.
     3)  Вызов  подпрограммы  обработки  программного прерывания
CALL INTERRUPT, в соответствии со значением вектора  программных
прерываний.  Вызывает  подпрограмму и обычно применяется для ис-
пользования служебных операций DOS и DIOS.
     В главе 5 "Справочное руководство по ТУРБО БЕЙСИКУ" описаны
в деталях операторы ТУРБО БЕЙСИКа CALL и SUB. В этом приложении,
мы рассмотрим аспекты CALL и SUB, касающиеся ассемблера.
     Обратите внимание, что средства интерфейса с подпрограммами
на ассемблере трудны для понимания в силу сложности самого  про-
цесса связи. Прежде, чем приступить к изучению того  что изложе-
но в данном приложении, следует ознакомиться с основными положе-
ниями языка ассемблер.

     Оператор CALL ABSOLUTE
     ----------------------
     Выполнение  оператора  CALL  ABSOLUTE  в программе на ТУРБО
БЕЙСИКе вызывает подпрограмму на ассемблере, предварительно заг-
руженную оператором BLOAD  или  являющуюся  частью  пространства
данных программы.
     В примере:

     DEF SEG=$H5000
     MyAsmSub%=&H4000
     CALL ABSOLUTE MyAsmSub%

вызывается ассемблерная процедура, расположенная в сегменте 5000H
со   смещением   4000H.   Адрес   обычнo   указывается   в   виде
сегмент:смещение, т. е. 5000:4000.

Синтаксис оператора CALL ABSOLUTE:

    CALL ABSOLUTE <числовой-идентификатор>[,(список-параметров)]

где  числовой-идентификатор - это числовая скалярная переменная,
которая находится в диапазоне от -32768 до 65535. Если  числовой
идентификатор отрицателен, он преобразуется в положительное чис-
ло  путем  дополнения  до 2. Он задает смещение и используется в
совокупности с адресом сегмента, установленным в последнем  опе-
раторе  DEF SEG, для  задания  вызываемого  абсолютного  адреса.
Если вы хотите использовать  выражение для задания  адреса,  вам
следует присвоить его числовому идентификатору,  а затем указать
идентификатор в операторе CALL.
     В качестве необязательных параметров могут задаваться толь-
ко короткие целые скалярные переменные.  Параметры передаются по
адресу  с помощью  16-битовых  указателей,  размещенных  в стеке
слева направо.  Сами параметры  располагаются в главном сегменте
данных (DS).
     Эта форма оператора CALL  допускает  минимальную  совмести-
мость  с интерпретатором БEЙСИКА. ТУРБО БЕЙСИК располагает более
мощной возможностью вызова встроенных процедур (SUB INLINE)  для
обеспечения полного доступа к хранилищам данных.
     После завершения требуемых действий, ассемблерные процедуры
должны  выполнить  межсегментный  (дальний)  возврат (RETURN)  в
ТУРБО БЕЙСИК. Выполнение программы затем продолжается с операто-
ра, следующего за вызовом CALL.
     Заботиться о сохранении  регистров  сегмента  данных  (DS),
указателя  базы (BP), сегмента стека (SS) и указателя стека (SP)
должен сам программист.

     Оператор CALL INTERRUPT
     -----------------------
     Оператор CALL INTERRUPT использует значения вектора  преры-
ваний  для входа  в подпрограмму на ассемблере. Обычно эта форма
CALL используется для вызова  подпрограмм  обработки  прерываний
DOS  и  BIOS,  но  может употребляться и для вызова определенных
пользователем программных обработчиков прерываний.

Синтаксис оператора CALL INTERRUPT:

     CALL INTERRUPT <целое-выражение>

где целое выражение должно быть в пределах от 0 до 255.
     Перед вызовом подпрограммы  обработки  прерывания  следует,
пользуясь  оператором  REG,  установить значения соответствующих
регистров. Доступ к результатам, записанным в регистрах и сохра-
няемых компилятором, может быть осуществлен  с  помощью  функции
REG.
     После  выполнения  нужной  операции  ассемблерная процедура
должна выполнить  возврат из прерывания (IRET)  в  ТУРБО БЕЙСИК.
Затем продолжается выполнение следующего  за вызовом CALL опера-
тора.
     Заботиться о сохранении  регистров  сегмента  данных  (DS),
указателя  базы (BP), сегмента стека (SS) и указателя стека (SP)
должен сам программист.

     Регистровый буфер
     - - - - - - - - -
     Оператор  CALL  INTERRUPT  использует  для  передачи из и в
программу на ассемблере регистровый буфер. Он представляет собой
последовательность  16-битовых целых чисел, соответствующих зна-
чениям процессорных регистров непосредственно до и после  выпол-
нения оператора CALL INTERRUPT.
     Оператор REG сохраняет содержимое 16-битовой целой перемен-
ной в указанном регистре, в соответствии с заданным числовым ар-
гументом (от 0 до 9).
     Функция  REG возвращает 16-битовое содержимое заданного ре-
гистра, определяемого в соответствии со значением числового  ар-
гумента  (от  0 до 9). Связь между аргументами и действительными
процессорными регистрами приведена в следующей таблице:
     -------------------------------------------
     I    Номер           I   Регистр          I
     -------------------------------------------
     I        0           I   Флаги            I
     I        1           I   AX               I
     I        2           I   BX               I
     I        3           I   CX               I
     I        4           I   DX               I
     I        5           I   SI               I
     I        6           I   DI               I
     I        7           I   BP               I
     I        8           I   DS               I
     I        9           I   ES               I
     I------------------------------------------

     Для того, чтобы установить значение в  регистровом  буфере,
пользуйтесь оператором REG. Например:
     REG 5,&H8000
загружает 16-ричное значение 8000H в регистр SI буфера.
     Обратите  внимание,  что REG не производит непосредственной
записи или чтения процессорного регистра - REG читает или  запи-
сывает в промежуточный буфер.
     Для чтения элемента из регистрового буфера пользуйтесь фун-
кцией REG, например:
     y%=REG(1)
загружает в целую переменную y% содержимое из дубликата регистра
AX.
     И  вновь, заметьте, что значение регистрового буфера загру-
жается в процессорные регистры с  началом  выполнения  оператора
CALL INTERRUPT и копируется из процессора после возврата из выз-
ванной подпрограммы.

     О вызовах функций DOS и BIOS
     - - - - - - - - - - - - - - -
     Прерывания 10H - 1FH являются обращениями к BIOS и выполня-
ют  различные служебные функции. (Для более детальной информации
см. "Техническое справочное руководство по DOS IBM".)
     Прерывание 21H (33 десятичное) представляет особый  интерес
по сравнению с остальными номерами прерываний, так как оно явля-
ется  главным способом обращения к DOS. Запрос на прерывание по-
мещается в старший байт регистра AX (AH), а дополнительные,  при
необходимости, размещаются в других регистрах. DOS предоставляет
множество полезных функций, доступ к которым может быть осущест-
влен с помощью описанного выше способа.
     В качестве примера рассмотрим функцию FNFreeSpace,  опреде-
ляющую количество пустого дискового пространства.

     DEF FNFreeSpace (drive%) 'Функция DOS 36H возвращает число
                              'свободных кластеров на выбранном
                              'устройстве: 0=устройство по
                              'умолчанию, 1=А, 2=В и т.д.
     REG 4,drive%
     REG 1,&H3600
     CALL INTERRUPT &H21
     'своб. пространство = доступные кластеры * байт/сектор *
     'сектор/кластер = BC*CX*AX
     FNFreeSpace = CSNG(REG(2))*REG(3)*REG(1)
     END DEF

     Определенная  в  одном месте программы, функция FNFreeSpace
может быть вызвана в любом другом, также  как  и  все  остальные
функции. Ммого ли места на диске по умолчанию?

     PRINT FNFreeSpace (0)

     Использование CALL вместе с INLINE
     ----------------------------------
     Встроенные  процедуры  на ассемблере и обычные процедуры на
ТУРБО БЕЙСИКе используют одну и ту же вызывающую  последователь-
ность. Изменяется определение процедуры SUB при задании программ
на  языке ассемблера. Встроенные процедуры - наиболее мощный ре-
жим использования ассемблера в ТУРБО БЕЙСИКе.

Синтаксис:

     CALL <имя процедуры> [(список параметров)]

Синтаксис:

     SUB <имя процедуры> INLINE
       $INLINE <список-байтов>
       $INLINE <имя-файла-COM>
     END SUB

     Может  быть  задано  произвольное   количество   операторов
$INLINE  в  любом порядке. Единственное ограничение - количество
файлов COM в одной процедуре не должно быть больше 16.
     Список-байтов состоит из констант или  выражений,  значения
которых находятся в диапазоне от 0 до 255, разделенных запятыми.
Обычно   для   каждого   байта   задается   16-ричная  константа
($H4C,$H90).
     Команды возврата недопустимы ни в ассемблерном коде,  ни  в
конце  процедуры  SUB.  За этим автоматически следит компилятор.
Если необходимо выйти из процедуры до ее завершения, следует вы-
полнить переход на ассемблерную метку в конце встроенного кода.
     Обратите внимание, что в определении SUB список  параметров
не задается.
     Заботиться о сохранении  регистров  сегмента  данных  (DS),
указателя  базы (BP), сегмента стека (SS) и указателя стека (SP)
должен сам программист.

     Передача параметров встроенным процедурам
     - - - - - - - - - - - - - - - - - - - - -
Параметры в качестве 32-битовых указателей элементов данных (за
исключением массивов) помещаются в стек в порядке слева направо.

- Передача числовых переменных

     Для числовых переменных (целых и с плавающей запятой) пере-
дается 32-битовый указатель данных (см. Приложение А "Обсуждение
работы с числами" описание числовых форматов.)

- Передача символьных данных

     Для символьных параметров (за исключением массивов) переда-
ется  32-битовый  указатель  на  4-байтовый дескриптор строки. В
первых двух байтах дескриптора содержится длина строки.  Следую-
щие  два  байта  содержат  смещение символьных данных в сегменте
символьных данных.
     Замечание. Старший бит байтов,  указывающих  длину  строки,
использовать  не следует, он зарезервирован и может быть в даль-
нейшем задействован. Прежде, чем  использовать  значение  длины,
нужно  исключить  старший бит с помощью логической операции "И".
Нельзя, однако, изменять значение в памяти. Можно изменять байты
в строке символов, но не следует менять длину строки. Для  полу-
чения  указателя  символьного  сегмента используйте первое слово
сегмента данных, определенного по умолчанию.  Дескриптор  строки
имеет следующий формат:
   Байты 0,1:  Длина строки (старший бит зарезервирован)
         2,3:  Смещение данных в символьном сегменте.

- Передача массивов

     Когда  параметрами  являются  массивы,  дескриптор массива,
длина которого 60 байтов, помещается в стек.  Дескриптор массива
имеет следующий формат:

   Байты 0,1:  Адрес сегмента данных  массива.  Первый  элемент
               массива начинается со смещения 0. Для динамичес-
               ких массивов  он содержит  0 до тех пор, пока не
               установлена размерность массива.
           2:  Описывает тип элементов массива
                 0 = целый
                 2 = длинный целый
                 4 = с плавающей запятой одинарной точности
                 6 = с плавающей запятой двойной точности
                 8 = зарезервирован
                10 = символьный
           3:  Количество индексов
         4,5:  Число элементов массива
         6,7:  Длина элементов массива
                 2 байта = целый
                 4 байта = длинный целый
                 4 байта = с плавающей запятой одинарной точности
                 8 байт  = с плавающей запятой двойной точности
                 4 байта = символьный дескриптор
         8,9: Нижняя граница правого индекса массива
       10,11: Верхняя граница правого индекса массива
 Следующие 6 байтов повторяются для 8 размерностей(индексов)
 Байты 12,13: зарезервированы
       14,15: нижняя граница следующего индекса массива
       16,17: верхняя граница следующего индекса массива

    Предостережение: некоторые части массивного дескриптора
зарезервированы и являются объектами изхменения в будущих версиях
компилятора. Настоятельно рекомендуется передавать число элемен-
тов, а также первый и последний элементы массива, и пользоваться
результирующими указателями.
    Элементы массива всегда хранятся в следующих непосредственно
друг за другом ячейках памяти (главное упорядочение по ряду).

- Передача результатов выражений

     Процедурам  на ассемблере можно передавать значения выраже-
ний, однако нельзя гарантировать числовой тип результата его вы-
числения. Мы советуем присваивать значение выражения  переменной
и затем передавать переменную.

- Передача констант

     Процедурам на ассемблере можно передавать константы, но не-
обходимо  явно  указать  их  числовой тип. Используйте для этого
идентификаторы типов после значения константы.

     Создание файла INLINE.COM
     - - - - - - - - - - - - -
     Для создания файла можно использовать отладчик или макроас-
семблер. Находясь в отладчике, можно выполнить команду А (ассем-
блировать) для ввода с клавиатуры операторов, написанных на язы-
ке ассемблер, команду N (имя) для задания имени файла и  команду
W (запись) для записи файла на диск.
     При  использовании  макроассемблера необходимо четыре прог-
раммы: редактор, макроассемблер, компоновщик и программа,  назы-
ваемая  EXE2BIN.  Сначала наберите в редакторе текст вашей прог-
раммы на ассемблере. Затем запустите  макроассемблер  для  того,
чтобы  получить объектный файл вашей программы. Далее, с помощью
компоновщика создайте выполняемый файл. И, наконец,  используйте
EXE2BIN для преобразования выполняемого файла в файл типа .COM.
    Для автоматизации этой обработки можно использовать следую-
щий пакетный файл.

    MASM %1;
    LINK %1;
    EXE2BIN %1 %1 COM

    Некоторые указания для преобразования ассемблерной программы
из EXE-файла в COM-файл, подлежащий использованию ТУРБО БЕЙСИКОМ:
Не включайте стековый сегмент (компоновщик будет сообщать об
ошибке - нет стекового сегмента, но это игнорируется). Все
инструкции должны использовать только относительную адресацию как
для ссылок на коды, так и на данные. Рекомендуется держать все
локальные данные на стеке и адресоваться к ним относительно
стека. Используйте заявление ORG 100H в начале программы.
Защищайте регистры сегмента данных (DS), базового указателя (BP),
сегмента стека (SS), и стекового указателя (SP).

     Пример INLINE-сборки
     - - - - - - - - - - -
     Предположим, для нашего алгоритма требуется, чтобы некоторое
ненулевое значение, скажем, 100, быстро загружалось в каждый
элемент 200-элементного целого массива. Это можно реализовать
циклом типа

     DEFINT a-n
     DIM a(199)
     FOR n=0 TO 199
        a(n) = 100
     NEXT n

     К сожалению, для нашей конкретной области применения эта схема
"по элементу за раз" слишком тихоходна. Поэтому вы ищете ассем-
блерно-языковое решение этой проблемы, насколько можно быстрое.

     DEFINT a-z
     DIM a(199)
     CALL FillArray a(0)
     FOR n=0 TO 199
        PRINT a(n)
     NEXT n
     END

     SUB FillArray INLINE
        $INLINE &H55              'PUSH BP
                             'хранить базовый указатель
        $INLINE &H89, &HE5        'MOV  BP,SP
                             'переместить стековый указатель в BP
        $INLINE &HC4, &H7E, &H06  'LES  DI,(BP+6)
                             'адрес смещения параметров
        $INLINE &HEB, &H64, &HD0  'MOV  AX,64H
                             'константа - заполнить
        $INLINE &HB9, &HCB, &HD0  'MOV  CX,CBH
                             'длина - заполнить
        $INLINE &HFC              'OLD
                             'очистить флаг направления
        $INLINE &HF3              'REP
                             'заполнить слова
        $INLINE &HAB              'STOSW
        $INLINE &H5D              'POP  BP
                             'восстановить базовый указатель
     END SUB


   На рисунке С-1 изображен простой пример распределения памяти
во время выполнения:

 0000:0000 -------------------------------
           I            DOS              I
           -------------------------------
           I Другие резидентные          I (SideKick и т.д.)
           I          программы          I
           -------------------------------
           I ТУРБО БЕЙСИК                I
           I      Система выполнения     I
           I      Область данных         I
           I      Рабочий стек           I FRE (-2)
           -------------------------------
           I Область пользовательских    I От 16 до 64К
           I          программ           I Сегменты пользо-
           I                             I вательских кодов
           -------------------------------
           I Скалярный сегмент           I
           I      Набор констант         I
           I      Скалярные переменные   I
           I      Символьные дескрипторы I
           I      Дескрипторы массивов   I
 YYYY:FFFF -------------------------------
           I Пространство для массивов   I            переменный
           I                             I  FRE (-1)  размер
 XXXX:0000 -------------------------------
           I Символьный сегмент          I  FRE (S$)
 XXXX:FFFF -------------------------------
           I Свободное пространство      I  MEMSET
 A000:FFFF -------------------------------

          Рисунок С -1 Карта распределения памяти в
                   момент выполнения программы


                        ПРИЛОЖЕНИЕ  D
-----------------------------------------------------------------
               Сравнение ТУРБО БЕЙСИКа и Интерпретатора БЕЙСИКа
-----------------------------------------------------------------

     Между ТУРБО БЕЙСИКом и  Интерпретатором БЕЙСИКа  имеются три
основные отличия:
     1. Компилятор против интерпретатора
     2. Расширение языка БЕЙСИК в ТУРБО БЕЙСИКе
     3. Реализация компилятора
     Каждое из этих основных  отличий определяет связанные с ним
более мелкие различающиеся детали в двух реализациях БЕЙСИКа. Их
мы рассмотрим ниже.

     Компилятор против интерпретатора
     --------------------------------
     Интерпретаторы имеют  тенденцию затуманивать различия  между
командами для создания программ и командами, используемыми в про-
грамме; другими  словами, между системой сопровождения программ и
самим языком. Так, например, EDIT и AUTO не составляют часть язы-
ка в том смысле, в каком ими являются GOSUB и PRINT.
     Интерпретаторы выполняют программный код в заданном порядке.
Компиляторы,  напротив, сначала просматривают исходные операторы,
затем  генерируют выполняемый код для исходного текста. Последнее
свойство позволяет ТУРБО БЕЙСИКу, как компилятору, выявлять ошиб-
ки в ветвях программы, которые никогда не  будут  выполняться Ин-
терпретатором БЕЙСИКа. В следующем примере, выполняемом в  Интер-
претаторе,  если X не будет равно  3 перед выполнением строки 20,
операторы, следующие за THEN никогда выполняться не будут:

     10 X=5
     20 IF X=3 THEN GOTO 30: X=10: Z="ААА"

При этом синтаксическая ошибка присвоения числовой переменной сим-
вольного  значения обнаружена не будет. Кроме того, операторы Х=10
и Z="ААА" никогда не будут выполняться, так как при Х=3 будет осу-
ществлен переход GOTO на строку 30. Компилятор во время компиляции
пометит любой "тупиковый код" как ошибку.

     Неподдерживаемые команды
     - - - - - - - - - - - - -
     В  ТУРБО БЕЙСИКе  имеется  настоящий полноэкранный редактор и
команды  работы с меню для выполнения вспомогательных функций. По-
этому нет необходимости в  наличии каких-либо операторов,связанных
с загрузкой,  сохранением  и  редактированием  исходных  программ.
Таких команд в ТУРБО БЕЙСИКе нет.  Соответствующие  команды Интер-
претатора  БЕЙСИКа  обычно используются в  режиме непосредственной
работы и включают:

     AUTO , DELETE , EDIT , LIST , LOAD , NEW , RENUM , SAVE

     ТУРБО БЕЙСИК позволяет создавать и модифицировать программы с
помощью текстового редактора, то есть, нет необходимости в измене-
нии  или  стирании  строк  программы  (например,  командами EDIT и
DELETE). Если вы захотите удалить  строку,  переместите  курсор  в
нужную  строку и нажмите CTRL-Y. Аналогично, нет потребности в ко-
манде LIST - вместо этого достаточно нажать соответствующие клави-
ши и нужная часть программы будет выведена на экран.
     Команды основного меню ТУРБО БЕЙСИКа выполняют те же  (и дру-
гие)  функции,  что  и  команды  SAVE, LOAD  и  NEW Интерпретатора
БЕЙСИКа. Кроме того, так как  в ТУРБО БЕЙСИКе необязательны номера
строк, то и команды АUTO и RENUM не нужны.
     В ТУРБО БЕЙСИКе не поддерживаются также следующие команды:

     CONT
     В ТУРБО БЕЙСИКе   не  допускается повторный запуск прерванной
программы. Прерывание программы по STOP или Ctrl-Break означает то
же самое, что и выполнение оператора END.

     MERGE
     ТУРБО БЕЙСИК транслирует программу в выполняемый код, поэтому
он не предоставляет возможности сливать строки исходной  программы
в момент выполнения.

     MOTOR
     Кассетный порт обычно не встречается на PC.

     USR
     Оператор CALL выполняет те же (и другие) задачи что и USR.

     Операторы, требующие модификации
     - - - - - - - - - - - - - - - - -
     CALL ABSOLUTE
     В операторе CALL ABSOLUTE ТУРБО БЕЙСИКа допустимы только  це-
лые параметры.  Он включен  в систему для обеспечения  минимальной
совместимости с интерпретируемым БЕЙСИКом. Для программирования на
ассемблере ТУРБО БЕЙСИК располагает более мощными средствами: CALL
INTERRUPT и встроенными ассемблерными процедурами. (Для более пол-
ной информации см. приложение С "Интерфейс с языком ассемблер").

     CHAIN
     Программы типа СHAIN должны транслироваться в файлы  .EXE или
.TBC  с  помощью   выбора  в  меню  "Варианты" компилятора режимов
Compile to exe (компиляция  в  EXE) или Compile to Chain (компиля-
ция в CHAIN). В операторах  COMMON как в обычных, так и цепых про-
граммах, список  переменных  должен  содержать  общие переменные в
надлежащем порядке (хотя и необязательно с одними и теми же имена-
ми). Нельзя выполнять в среде ТУРБО БЕЙСИКа оператор CHAIN. Он мо-
жет  использоваться  только  при  работе  в  DOS.  Режимы  MERGE и
DELETE "диапазон-номеров-строк" не поддерживаются.

     DEFtype, TRON, TROFF, OPION BASE
     Реализация этих операторов в  ТУРБО БЕЙСИКе  и Интерпретаторе
БЕЙСИКа  несколько отличается. ТУРБО БЕЙСИК рассматривает физичес-
кое местоположение каждого оператора в исходной  программе,  а  не
его  появление в выполняемой ветви объектного кода программы. Дру-
гими словами, имеется в виду положение каждого оператора во  время
компиляции, а не во время выполнения. Рассмотрим на примере следу-
ющей программы оператор DEFtype:

     10 GOTO  30
     20 DEFINT X
     30 X=2.3
     40 PRINT X

     При выполнении этой программы в Интерпретаторе БЕЙСИК, опера-
тор в  строке 20 обнаружен не будет. Таким образом, при выполнении
строки 20 будет использован тип переменной Х по умолчанию (с  оди-
нарной точность), а затем выведется значение 2.3.
     В отличие  от  этого  ТУРБО БЕЙСИК устанавливает соглашения о
типах во время компиляции. Поскольку,  оператор  DEFINT  физически
предшествует первому появлению переменной Х, оператор PRINT  выве-
дет значение 2.

     DRAW и PLAY
     Оба эти оператора выполняют сложные командные строки, выводя-
щие графические изображения или воспроизводящие музыку, соответст-
венно. В Интерпретаторе БЕЙСИКа символьная информация, управляющая
выполнением команд, может включать  имена  символьных  переменных.
Например, в Интерпретаторе БЕЙСИКа операторы:

     n=50
     PLAY "T=n;C"

устанавливают  темп  в  50 четвертей в минуту и исполняет ноту до.
ТУРБО БЕЙСИК не понимает подобной конструкции, так как после  ком-
пиляции  вся информация, касающаяся переменной n,утрачивается. Од-
нако, того же эффекта можно добиться с помощью функции VARPTR$:

     n=50
     PLAY "T=" + VARPTR$(n) + "C".

     Параметры функций
     Для  определения  параметров  функции  Интерпретатор   БЕЙСИК
позволяет  использовать  те  же   имена   переменных   параметров.
ТУРБО БЕЙСИК выдает сообщение  об  ошибке,  связанной  с  наличием
дубликата локальной переменной.

     RUN
     Программа в ТУРБО БЕЙСИКе может использовать оператор RUN для
загрузки и выполнения другой программы или перезапуска себя самой,
но нет возможности запустить  текущую  программу  из  произвольной
точки кроме ее начала, задавать номер строки, с  которой  начнется
выполнение программы, в этом случае нельзя.

     Преобразование программ Интерпретатора БЕЙСИК в программы
     ТУРБО БЕЙСИК
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     Первый шаг преобразования программы Интерпретатора  БЕЙСИК  в
программу ТУРБО БЕЙСИК - сохранение ее на диске в  формате  ASCII.
Например, чтобы сохранить текущую программу, введите:

          SAVE "<имя программы>.txt",A.

     Режим ",А" заставляет  Интерпретатор  БЕЙСИКа  записывать  на
диск текстовый (ASCII)  файл,  не  снабжая  его  "опознавательными
знаками".    Такой    файл    может    непосредственно    читаться
ТУРБО БЕЙСИКом, однако,  если  он  больше  64К,  следует  выделить
основной  и  подключаемые  файлы  прежде,чем   редактировать   или
компилировать его в ТУРБО БЕЙСИКе.

     Дополнение языка БЕЙСИК
     -----------------------
     ТУРБО БЕЙСИК  предоставляет  новые  командные  возможности  и
дополнения языка БЕЙСИК. Ниже приводятся  некоторые  из  них  (см.
для более детальной информации главу 5 "Справочное руководство по
ТУРБО БЕЙСИКу).

     Структурные операторы
     - - - - - - - - - - -
     В дополнение к Интерпретатору БЕЙСИК, ТУРБО БЕЙСИК использует
для управления ходом программы и создания легко ...