Справочник программиста на персональном компьютере фирмы IBM. Приложения - Включение ассемблерных процедур в программы  на Бейсике

ОГЛАВЛЕНИЕ

Приложение Г.  Включение ассемблерных процедур в программы  на Бейсике.


   Процедуры на языке ассемблера состоят из строк байтов машинно-
го кода. При выполнении этой процедуры Бейсик передает управление
из  последовательности инструкций, составляющих программу на Бей-
сике, в то место, где  хранятся  инструкции,  которые  могут быть
декодированы  в  последовательность инструкций языка  ассемблера.
При завершении ассемблерной  процедуры  управление возвращается в
то место бейсиковской программы, откуда была вызвана процедура.
   В этой книге ассемблерные процедуры, используемые в программах
на Бейсике, приведены в двух видах. В обоих видах процедуры вклю-
чены  в программу, а не хранятся в виде отдельного дискового фай-
ла. При первом способе требуется, чтобы коды процедуры находились
в  отдельном месте в памяти, а при втором, менее принятом,  этого
не требуется.
   В первом способе процедура помещается в операторы DATA и прог-
рамма  пересылается в неиспользуемую часть памяти, а затем  вызы-
вается оператором CALL. Надо позаботиться о том, чтобы код проце-
дуры  не  накладывался на какие-либо данные и наоборот.   Обычное
решение этой проблемы состоит в  том,  что процедура помещается в
те  адреса  памяти,  к которым Бейсик не может  получить  доступ.
Поскольку интерпретатор Бейсика не  может иметь доступ за пределы
64K,  то  для системы, скажем, с памятью  256K,  нужно  поместить
процедуру в старшие  64K.  Для  систем  с  памятью 128K Вы должны
вычислить  сколько памяти требуется операционной системе, Бейсику
и драйверам  устройств.   Допустимо,  чтобы они занимали 25K плюс
64K,  используемых  Бейсиком.  В системах с 64K  используйте  при
старте команду CLEAR, которая ограничивает объем памяти доступный
для Бейсика. CLEAR,n ограничивает Бейсик n байтами.  Затем помес-
тите процедуру в самые верхние адреса памяти.
   Для указания начала  области,  куда  будет помещена процедура,
используйте  оператор  DEF SEG, а затем с помощью оператора  READ
считываются байты процедуры  и  помещаются  в  память до тех пор,
пока вся процедура не будет помещена на место. Например:

100 DATA &Hxx, &Hxx, &Hxx, &Hxx, &Hxx  '10-байтная процедура
110 DATA &Hxx, &Hxx, &Hxx, &Hxx, &Hxx
 .
 .
300 '''помещаем процедуру в память
310 DEF SEG = &H3000   'указываем на область памяти
320 FOR N = 0 TO 9     'для каждого из 10 байтов
330 READ Q             'читаем байт данных
340 POKE N,Q           'помещаем его в память
350 NEXT

   После  того  как процедура загружена в память и Вы  хотите  ее
использовать, необходимо чтобы  последний оператор DEF SEG указы-
вал на начало процедуры.  Затем присвойте целой переменной значе-
ние 0 и напишите оператор  CALL  с  именем  этой переменной. Если
процедуре  передаются  параметры,  то они должны быть  указаны  в
скобках в конце оператора CALL. Например:

500 DEF SEG = &H3000   'указываем на начало процедуры
510 DOGS = 12          'у нее 3 параметра
520 CATS = 44          '
530 POSSUMS = 1        '
540 CASUALTIES = 0     'начинаем выполнение с 1-го байта
550 CALL CASUALTIES(DOGS,CATS,POSSUMS)  'выполняем процедуру

   Имеется  намного  более простой и экономичный способ  создания
ассемблерных процедур, который  избегает  проблемы  распределения
памяти. Надо просто создать процедуру в виде строковой переменной
внутри программы.  Каждый байт  может  быть закодирован с помощью
CHR$.  Затем используйте функцию VARPTR для определения положения
этой строки в памяти. Смещение по которому находится эта перемен-
ная  хранится в двух байтах, которые идут за тем, на который ука-
жет VARPTR (в первом байте  содержится  длина строки). Затем этот
адрес используется для вызова процедуры.  Отметим способ, которым
используется оператор DEF  SEG,  для  указания  на сегмент данных
Бейсика, с тем чтобы полученное смещение указывало на адрес стро-
ки для оператора CALL. Например:

100 DEF SEG         'устанавливаем сегмент на данные Бейсика
110 X$ = "CHR$(B4)+..."  'код процедуры
120 Y = VARPTR(X$)       'получаем дескриптор строки
130 Z = PEEK(Y+1)+PEEK(Y+2)*256  'вычисляем ее адрес
140 CALL Z

Многие значения, выражаемые  через CHR$() могут быть представлены
и в виде символов ASCII.  Вы можете писать ROUT = CHR$(12) + "AB"
вместо ROUT = CHR$(12) + CHR$(65) + CHR$(66). На самом деле боль-
шинство символов ASCII могут вводиться путем нажатия клавиши Alt,
наборе номера кода на дополнительной клавиатуре, а затем отпуска-
ния  клавиши  Alt.  Однако коды от 0 до 31 не могут быть  введены
таким образом для наших целей.