Главная » Basic » ПРОЦЕДУРЫ И ВСТАВКИ

0

Не во многих  системах  предлагаются настоящие процедуры, представляющие собой совокупности команд, в известной  мере похожие на блочные функции, однако в большинстве версий Бейсика для микроЭВМ предусматриваются определенные команды для вызова   и исполнения  из программы на Бейсике вставок на машинном коде.

6.4.3.  ПРИМЕНЕНИЕ МАШИННОГО КОДА

В принципе применение в программах на Бейсике вставок, написанных на машинном коде, является не  такой уж трудной задачей, так как во  многих системах предусмотрен, по крайней мере, один способ вызова таких вставок. Однако на практике  при этом приходится сталкиваться с множеством мелких деталей, например с адресом ячеек памяти и  списками числовых  значений, которые надо правильным образом устанавливать при каждом вызове вставки. Этого и следовало ожидать, так как машинный код имеет дело с физической  реальностью ЭВМ; поэтому и  приходится отыскивать и

использовать  фактические  адреса ячеек памяти, загружать значения в  арифметические  регистры,

проверять и изменять указатели стека.

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

Команды РЕЕК и РОКЕ

Общая форма записи: POKE I, J (оператор) и переменная = РЕЕК (I) (функция) где

I содержит десятичный (или шестнадцатеричный, если указан соответствующий символ)  адрес байта памяти ЭВМ в диапазоне 0… 65 535;

J содержат десятичное (или шестнадцатеричное) значение, которое надо поместить в байт  с адресом I. Значение J должно лежать в пределах 0. .. 255.

Учтите, что в Бейсике ВВС этих функций нет.

Таким образом, оператор 10  РОКЕ 16251,22

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

100   А=62000

110   В=33

120   РОКЕ А,В

Некоторые системы позволяют пользоваться  шестнадцатеричными значениями, перед которыми для отличия  других величин  указываются символы  &  или  &Н.  Например, &FF  представляет собой шестнадцатеричный эквивалент  числа 255, а & 1А — шестнадцатеричный эквивалент  26. Таким образом, оператор

10   РОКЕ & 5A00,&FF

поместит 255 в ячейку с адресом 23040.

Команда РЕЕК покажет Вам значение любого байта (8 бит) памяти. Ее применение иллюстрируется следующей программой:

10 RЕМ ЧТЕНИЕ СОДЕРЖИМОГО ПАМЯТИ

20 INPUT "ВВЕДИТЕ НАЧАЛЬНЫЙ АДРЕС"; I%

30 INPUT "ВВЕДИТЕ ЧИСЛО БАЙТОВ";В%

40 FOR N%=0 TO B%-1

50   PRINT " " ;РЕЕК (I%+N%);

60 NEXT N%

70 PRINT

80 END

После ввода начального адреса и  требуемого числа байтов программа распечатывает в  десятичном виде   (в   диапазоне 0  …  255)  значения байтов памяти. Используя  оператор  PRINT  "  ";  CHR$ (PEEK(1%+N%)); можно получить символьное представление  значения каждого байта. В версии Бейсика Microsoft  предусмотрена  функция НЕХ$  (X),  которая  возвращает шестнадцатеричный эквивалент  десятичного значения X, и  ею можно воспользоваться вместо CHR$. Таким образом, заполненные    значения   можно    очень    легко    изобразить  в      десятичном,   символьном     и шестнадцатеричном виде.

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

10   REM ДЕМОНСТРАЦИЯ ДЕЙСТВИЯ РОКЕ

20   DATA  31,167,208,165,179.166

30   DATA 180,133,180,134,179,162

40   DATA   0,161.179,168,138, 76

50   DATA 120,210

60   FOR I%=0 TO 19 70  READ N% 80   POKE I%+826,N%

90   NEXT I%

100   END

занесет законченную вставку на машинном коде в область памяти с адресами от 826-го до 845-го для последующего вызова.

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

CALL   адрес,   входные  параметры   (входные  параметры   могут   отсутствовать), например:  10

CALL&FF10

В версии Бейсика Microsoft для микроЭВМ с микропроцессором 6502 вызов вставки имеет несколько другую форму:

10   START=&FF10

20   CALL%START (10,20,30)

Исполнение команд передается Бейсиком вставке  на машинном коде, начинающейся с заданного адреса. Если ей требуется передать какие-либо значения, то они могут быть загружены в некоторые из регистров,  или в регистры могут быть занесены ссылки на эти значения,  или эти значения  могут быть  переписаны в   определенную  область  памяти, на  которую  будет  иметься ссылка  в   паре регистров. Детали процесса передачи  значений  зависят от того, на каком именно микропроцессоре выполнена Ваша система. Если необходимо,  Ваша вставка на машинном коде должна будет первым делом  сохранить текущие значения регистров и    указателей  стека,  а  непосредственно  перед возвращением в Бейсик восстановить эти значения  с тем, чтобы Бейсик мог нормально продолжить свою работу с того места, откуда была вызвана вставка.

Другой  способ вызова вставки  на  машинном коде состоит в  том, что вставка используется как простая  функция с  единственным  входным значением (аргументом) и   единственным  выходным значением (результатом). Обращение к ней осуществляется с помощью функции USR(X), например:

10   A=USR (2*B+3)

Иногда  требуется,  чтобы  входное значение было  целым.  Тогда  в   случае  вещественного X  оно округляется до ближайшего целого числа. В некоторых системах и  результат должен быть целым числом. Так  как  заранее  не  известно,  где  располагается  вставка, то  перед  вызовом вставки  ее начальный адрес должен быть занесен в определенное место (какое именно,  зависит от конкретной системы) с помощью команды POKE, например:

100   РОКЕ 1,58 110   РОКЕ 2,4 120   A=USR(B)

Для занесения 16-битового адреса в память с помощью команды PОКЕ приходится расщеплять его на два 8-битовых байта, помещая обычно младшие адреса в первый  из байтов.  В приведенном выше примере в байт с номером 1 заносилось значение 58, что равно 3*16+10 или ЗА в шестнадцатеричной 201

записи, а  в    байт  с  номером  2  —  значение 4,  что  равно  4  в    шестнадцатеричной записи.

Шестнадцатеричные значения ЗА и 4 в байтах 1 и 2 соответственно дают адрес

4*256 + 3*16+ 10=1082

После того как USR передает управление вставке, начинающейся  с этого адреса, последняя извлекает значение входного параметра (переменной В в приведенном выше примере) из определенной области памяти, на которую указывает пара резисторов.  В версии  Бейсика Microsoft дополнительно предусмотрено простое средство для передачи адреса: если указан оператор

10   DEF USR0 = 2400

то при любом последующем обращении к USR0 (X) используется десятичный адрес, указанный в DEF  USR0.  (После  USR  можно  указывать одну  цифру, так  что  доступно  до  десяти различных вставок.)

В системе ВВС также предусмотрена функция USR, но последняя берет адрес вставки  из входного параметра, указанного при вызове USR, например:

20   A=USR(Z%) и

50   PRINT USR (& 1000)

При  вызове   USR   значения  специальных  переменных  А%,   Х%,   Y%   и    С%   копируются  в микропроцессорные  регистры А, X, Y и однобитовый флаг (регистр) переноса С для последующего использования  во вставке.  Оператор CALL в  Бейсике ВВС имеет форму, похожую на описанную выше, но дополнительно допускает возможность такой же передачи параметров через регистры и флаг переноса, как в случае USR. Детали процесса передачи параметров  вставке см. в руководстве по Бейсику ВВС.

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

120  INPUT SUM

130   [.SHIFT ROR A

140      INT

150      CPY 8

160      BNE SHIFT ]

170  PRINT SUM

Предусмотренные в Бейсике ВВС операции косвенной  адресации (?, ! и $) являются более гибкими,

чем команды РЕЕК и РОКЕ, но выполняют аналогичные действия, например:

А=?В эквивалентно А=РЕЕК (В)

?А=В эквивалентно РОКЕ А,В

Операция ? применяется к одному байту, операция ! к одному слову, состоящему из  четырех байтов, операция $ — к строке символов.

6.4.4.  ПРОЦЕДУРЫ

Подпрограммы, для работы с которыми используются операторы GOSUB и  RETURN, имеют дело исключительно с глобальными переменными, доступными в любом месте программы. Перед входом в подпрограмму определенные переменные должны содержать соответствующие входные значения. Однострочные  функции могут  пользоваться как  значениями,  указанными в   списке параметров функции, так и значениями глобальных переменных. Формальные переменные из списка параметров  в действительности являются локальными по отношению к функции   и отличаются от одноименных

глобальных  переменных.  Блочные  функции расширяют  возможности применения локальных переменных,   допуская   определение  ряда   локальных   переменных,   обладающих  аналогичным свойством. Но однострочные функции возвращают одно и  только одно значение в то место, откуда их вызывают. В принципе также могут "поступать" и блочные функции, хотя они могут иметь доступ и к глобальным переменным и изменять  их, если требуется возвращать несколько значений. Процедуры  доступны в  нескольких системах с Бейсиком для больших ЭВМ, но среди микроЭВМ только   система ВВС  дает  возможность пользоваться процедурами, что  выглядит следующим образом: вызов процедуры осуществляется по имени, например

100   PROCPICTURE (9,27,6, BIG)

Процедуре можно передавать любое число входных параметров. Соответствующие  им (по типу и номеру) формальные переменные являются локальными по отношению к процедуре, и, кроме того, можно   определить  дополнительные  локальные   переменные   оператором   LOCAL.   Процедуре доступны и   глобальные переменные, но  пользоваться ими  надо осторожно, так  как  желательно сохранить существенную независимость  процедуры.  Значения, указанные  в   списке  параметров, копируются в локальные параметры для последующего использования. Процедура имеет следующий вид:

500   DEF PROCPICTURE (A,B,C$)

510   LOCAL I%,S

520   PRINT B,C$

530   FOR I%=A TO B

800   END PROC

Она начинается оператором DEF  PROC  имя  и  завершается оператором ENDPROC. Как и блочные функции, процедуры могут быть рекурсивными. Процедуры служат идеальным средством реализации модульного програм203

мирования, проповедуемого в этой и других книгах. Их следует предпочитать подпрограммам. Как и функции  в Бейсике ВВС, процедуры надо помещать за концом основной программы.

Параметры процедуры можно использовать  для передачи ей входных значений; все те значения, которые должны служить результатом вызова процедуры, необходимо передавать через глобальные переменные  (т.  е.  переменные,  используемые в   основной части программы).  Если результатом является единственное  значение, то  вместо процедуры следует использовать  блочную функцию. Ниже приведен  пример процедуры PROCNUM, вычисляющей два значения (сумму двух  чисел и максимальное число) и возвращающей их через глобальные переменные С и D соответственно:

10 INPUT A,B

20 PROCNUM(А,В)

30 PRINT C,D

40 END

50 DEF PROCNUM(X.Y)

60   C=X+Y                      :REM С ИСПОЛЬЗУЕТСЯ ДЛЯ ВОЗВРАТА ЗНАЧЕНИЯ

70   IF X>Y THEN D=X ELSE D=Y   :REM И D ТОЖЕ

80 ENDPROC

Приведем  пример другой процедуры, которая ждет до тех пор, пока не будет нажата клавиша  с символом, заданным в А$:

250   DEF PROCWAIT (А$)

260   PRINT "НАЖМИТЕ КЛАВИШУ"; А$; "ДЛЯ ПРОДОЛЖЕНИЯ"

270   REPEAT UNTIL GETS =A$

280   ENDPROC

Источник: Уолш Б.    Программирование на Бейсике: Пер. с англ. М.: Радио и связь, 1988. 336 с: ил.

По теме:

  • Комментарии