Справочник программиста на персональном компьютере фирмы 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 не могут быть введены
таким образом для наших целей.