Страница 8 из 21
Приложение Г. Включение ассемблерных процедур в программы на Бейсике. Процедуры на языке ассемблера состоят из строк байтов машинно- го кода. При выполнении этой процедуры Бейсик передает управление из последовательности инструкций, составляющих программу на Бей- сике, в то место, где хранятся инструкции, которые могут быть декодированы в последовательность инструкций языка ассемблера. При завершении ассемблерной процедуры управление возвращается в то место бейсиковской программы, откуда была вызвана процедура. В этой книге ассемблерные процедуры, используемые в программах на Бейсике, приведены в двух видах. В обоих видах процедуры вклю- чены в программу, а не хранятся в виде отдельного дискового фай- ла. При первом способе требуется, чтобы коды процедуры находились в отдельном месте в памяти, а при втором, менее принятом, этого не требуется. В первом способе процедура помещается в операторы 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 не могут быть введены таким образом для наших целей.
|