ZX Review #7-8-9-10
08 ноября 1997

Ретро - 40 лучших процедур: Поиск подстроки.

<b>Ретро</b> - 40 лучших процедур: Поиск подстроки.

      8.8. Поиск подстроки

  Длина: 168
  Количество переменных: 0
  Контрольная сумма: 19875
  Назначение: эта программа воз-
вращает позицию подстроки (B$) в
главной строке (A$) или 0 в слу-
чае ошибки.
  Вызов программы:
     LET P = USR адрес
  Контроль ошибок:  если  строка
не  существует, или  если  длина
подстроки равна  нулю, или  если
длина подстроки больше, чем дли-
на   главной  строки,  программа
возвращает значение 0. Если оши-
бки нет, но подстрока не найдена
в главной строке, программа так-
же дает 0.
  Комментарий: после  выхода  из
программы в машинных кодах пере-
менная P (может быть использова-
на любая другая переменная)  бу-
дет  хранить  искомое  значение.
Строки, к которым делается обра-
щение, не могут  быть  массивами
данных. Для изменения используе-
мых строк числа, отмеченные  "*"

должны быть изменены.  66* - это
подстрока, 65* - главная строка.
Для изменения эти числа  необхо-
димо заменить  кодами  требуемых
символов. Например, если вы  хо-
тите найти позицию  H$ в G$, то,
соответственно, надо будет ввес-
ти 71 (код G) и 72 (код H).

   ЛИСТИНГ МАШИННЫХ КОДОВ
МЕТКА  АССЕМБЛЕР      ЧИСЛА ДЛЯ ВВОДА147.

       SUB A         151
       LD B,A         71
       LD C,A         79
       LD D,A         87
       LD E,A         95
       LD HL,(23627)  42  75  92
NEXT_V LD A,(HL)     126
       CP 128        254 128
       JR Z,NOT_FD    40  95
       BIT 7,A       203 127
       JR NZ,FOR_NX   32  41
       CP 96         254  96
       JR NC,NUMBER   48  29
       CP 65         254  65*
       JR NZ,SUBSTR   32   2
       LD D,H         84
       LD E,L         93
SUBSTR CP 66         254  66*
       JR NZ,CHECK    32   2
       LD B,H         68
       LD C,L         77
CHECK  LD A,D        122
       OR E          179
       JR Z,STRING    40   4
       LD A,B        120
       OR C          177
       JR NZ,FOUND    32  38
STRING PUSH DE       213
       INC HL         35
       LD E,(HL)      94
       INC HL         35
       LD D,(HL)      86
ADD    ADD HL,DE      25
       POP DE        209
       JR INCRS       24   5
NUMBER INC HL         35
       INC HL         35
       INC HL         35
       INC HL         35
       INC HL         35
INCRS  INC HL         35
       JR NEXT_V      24 206
FOR_NX CP 224        254 224
       JR C,N_BIT     56   6
       PUSH DE       213
       LD DE,18       17  18   0
       JR ADD         24 234
N_BIT  BIT 5,A       203 111
       JR Z,STRING    40 225
NEXT_B INC HL         35
       BIT 7,(HL)    203 126
       JR Z,NEXT_B    40 251
       JR NUMBER      24 227
FOUND  EX DE,HL      235
       INC HL         35
       INC HL         35
       PUSH HL       229
       PUSH HL       229
       INC BC          3
       PUSH BC       197
       LD A,(BC)      10
       LD E,A         95
       INC BC          3
       LD A,(BC)      10
       LD D,A         87
       OR E          179
       JR Z,ZERO      40  11
       PUSH DE       213
       LD A,(HL)     126
       DEC HL         43
       LD L,(HL)     110
       LD H,A        103
       AND A         167
       SBC HL,DE     237  82
       JR NC,CONTIN   48   8
       POP BC        193
ZERO   POP BC        193
       POP BC        193
ERROR  POP BC        193
NOT_FD LD BC,0         1   0   0
       RET           201
CONTIN POP IX        221 225
       POP BC        193
       EX DE,HL      235
       POP HL        225
       INC BC          3
       INC BC          3
SAVE   INC HL         35
       PUSH HL       229
       PUSH BC       197
       PUSH IX       221 229
       PUSH DE       213
COMPAR LD A,(BC)      10
       CP (HL)       190
       JR Z,MATCH     40  12
       POP DE        209
       POP IX        221 225
       POP BC        193
       POP HL        225
       LD A,D        122
       OR E          179
       JR Z,ERROR     40 225
       DEC DE         27
       JR SAVE        24 234
MATCH  INC HL         35
       INC BC          3
       PUSH HL       229
       DEC IX        221  43
       PUSH IX       221 229
       POP HL        225
       LD A,H        124
       OR L          181
       POP HL        225
       JR NZ,COMPAR   32 227
       POP DE        209
       POP DE        209
       AND A         167
       SBC HL,DE     237  82
       POP DE        209
       POP DE        209
       POP DE        209
       AND A         167
       SBC HL,DE     237  82
       LD B,H         68
       LD C,L         77
       RET           201
2
  Как она работает:
  В аккумулятор, пару  регистров
BC и пару  регистров  DE  загру-
жается 0. Позднее в программе  в
BC будет установлен адрес  B$, а
в DE будет установлен адрес  A$.
В HL  загружается  адрес  начала
области программных переменных.
  В аккумулятор загружается байт
из  адреса, находящегося  в  HL.
Если аккумулятор  содержит  чис-
ло  128, программа  переходит  к
NOT_FD, т.к. достигнут конец об-
ласти  программных   переменных.
Если  бит  7  аккумулятора уста-
новлен в 1, делается  переход  к
FOR_NX, т.к. найденная  перемен-
ная - не строковая и  не  число,
имя которого состоит  только  из
одной литеры.  Если  аккумулятор
содержит число большее, чем  95,
делается переход к NUMBER.
  Для  достижения  этого   этапа
строка должна быть найдена. Если
в аккумуляторе содержится  число
65,  определяется  местонахожде-
ние строки A$, а  содержимое  HL
копируется в DE. Если  аккумуля-
тор содержит  число  66, опреде-
ляется строка B$, а HL копирует-
ся в BC. Если DE не равно 0 и BC
не равно 0, определяется  место-
нахождение обеих строк, и  прог-
рамма переходит к FOUND.
  Если программа достигает  про-
цедуры STRING, DE сохраняется  в
стека и загружается длиной  най-
денной строки. Это значение при-
бавляется к адресу старшего бай-
та указателей  строки  и  сохра-
няется в HL. DE восстанавливает-
ся из стека и делается переход к
INCRS.
  В процедуре NUMBER HL увеличи-
вается в 5 раз, указывая на пос-
ледний байт найденного числа. HL
затем увеличивается, указывая на
следующую переменную, и происхо-
дит переход к NEXT_V.
  В процедуре FOR_NX, если акку-
мулятор содержит  число  меньше,
чем  224,  делается  переход   к
N_BIT, т.к. встретившаяся  пере-
менная не  является  управляющей
переменной цикла FOR-NEXT.  Если
значение  аккумулятора   больше,
чем 223, то число 18 прибавляет-
ся к HL, указывая  на  последний
байт переменной  цикла, и  прог-
рамма возвращается к INCRS.
  Если программа достигает N_BIT
и бит 5 аккумулятора  установлен
в 0, делается переход к  STRING,
чтобы загрузить в HL адрес  сле-
дующей  переменной, т.к.  найден
массив.
  Если программа достигает NEXT_
B, найдено  число, имя  которого
больше одного символа по  длине.
Таким образом, HL  увеличивается
до тех пор, пока  не  укажет  на
последний символ имени  перемен-
ной, а затем  делается переход к
NUMBER.
  В процедуре FOUND в HL  загру-
жается адрес  строки  A$, и  это
значение  увеличивается  дважды,
чтобы  получить  адрес  старшего
байта указателей.  Это  значение
затем сохраняется в стеке  дваж-
ды.  BC  увеличивается, указывая
на младший байт указателей  под-
строки B$. Адрес в BC затем сох-
раняется в стеке.  В  DE  загру-
жается длина строки  B$  и  если
это значение  равно  0, делается
переход к ZERO. Затем  DE  поме-
щается в стек. В HL  загружается
длина строки A$ и если это  зна-
чение не меньше чем DE, програм-
ма переходит  к  CONTIN.  Указа-
тель  стека  затем  восстанавли-
вается, в  BC  загружается  0  и
программа возвращается в BASIC.
  В процедуре CONTIN в IX  уста-
навливается длина строки B$, а в
BC  помещается  адрес   младшего
байта указателей  для  подстроки
B$. В  DE  загружается  разность
длин строк A$ и B$, а в HL  заг-
ружается  адрес  старшего  байта
указателей для A$. BC затем уве-
личивается  дважды, чтобы  полу-
чить  адрес  первого  символа  в
подстроке B$. HL  увеличивается,
указывая  на  следующий   символ
строки A$. HL, BC, IX и  DE  за-
тем сохраняются на стеке. В  ак-
кумулятор  загружается  байт  по
адресу в BC и, если  это  значе-
ние равно значению байта по  ад-
ресу в  HL, делается  переход  к
MATCH.  DE, IX, BC  и  HL  затем
восстанавливаются из стека. Если
DE содержит 0, делается  переход
к ERROR, т.к. подстроки B$ нет в
строке A$. Счетчик DE уменьшает-
ся и  программа  возвращается  к
SAVE.
  Если программа достигает  про-
цедуры MATCH, HL и  BC  увеличи-
ваются,  указывая  на  следующий
символ A$ и  B$  соответственно.
HL затем  сохраняется  в  стеке.
IX, счетчик, уменьшается и  пос-
ле восстановления HL  из  стека,
если IX не содержит  0, програм-
ма возвращается к COMPAR.
  Для  достижения  этого   этапа
местонахождение подстроки  B$  в
строке A$ уже должно быть  опре-
делено. Длина подстроки B$ вычи-
тается  из  HL,  а  затем  адрес
страршего байта  указателей  для
строки A$ вычитается из HL.  Ре-
зультат - это позиция  подстроки
B$ в строке A$. Это значение ко-
пируется в пару регистров  BC  и
программа возвращается в BASIC.

           *   *   *

  Заканчивая печать книги Дж.Ха-
рдмана и  Э.Хьюзона  "40  лучших
процедур", нам  хотелось бы дать
небольшой  комментарий,  который
касается формата программных пе-
ременных  в  Спектруме.  Дело  в
том, что процедуры, представлен-
ные  в  этом  последнем заключи-
тельном блоке, широко  оперируют
с ними. Те, кто не имеет фирмен-
ной  инструкции   по   Спектруму
(книга Виккерса), могут  быть  с
этим форматом и  незнакомы, а мы
в своих работах до сих пор  как-
то к этому  вопросу  не  обраща-
лись. Те, кому этот вопрос инте-
ресен, могут прочитать коммента-
рий.

   Формат данных в Спектруме

  Данные в Спектруме хранятся  в
виде  переменных  и  массивов  в
специально выделенной для  этого
области памяти. Эта область  на-
чинается непосредственно за  об-
ластью,  в  которой  размещается
текст БЕЙСИК-программы.
  На начало области  программных
переменных  указывает   двухбай-
тная системная переменная  VARS.
Она расположена по адресу  23267
(5AE3H).
  Конец области программных  пе-
ременных задан специальным  мар-
кером - это байт, значение кото-
рого равно 80H (128).
  Спектрум  различает  несколько
разных типов переменных. Это:
  - обычная числовая переменная,
имя  которой  состоит  из  одной
буквы, например x;
  - числовая переменная, имя ко-
торой состоит из более, чем  од-
ной буквы, например, row;
  - числовой  массив,  например,
a(5) или b(3,3,40);
  - переменные, управляющие цик-
лами FOR...NEXT, например, 1;
  - строковые переменные, напри-
мер, a$;
  - строковые массивы, например,
b$(10,40).

      Числовая переменная
    с именем из одной буквы

  Занимает 6  байтов.  В  первом
байте хранится ее имя, в  после-
дующих пяти - ее значение в  ин-
тегральной  форме. Об интеграль-
ном представлении действительных
чисел  см.  "Программирование  в
машинных  кодах".  Первый   байт
имеет следующую раскладку:

   ┌──┬──┬──┬──┬──┬──┬──┬──┐
   │0 │1 │1 │б │у │к │в │а │
   └──┴──┴──┴──┴──┴──┴──┴──┘

  На то, что это  простая  пере-
менная, указывает  специфическое
расположение первых трех битов.

  Числовая переменная с именем
    более чем из одной буквы

  Ее первый байт  имеет  следую-
щий формат:

   ┌──┬──┬──┬──┬──┬──┬──┬──┐
   │1 │0 │1 │б │у │к │в │а │
   └──┴──┴──┴──┴──┴──┴──┴──┘

  Прочие байты имени (кроме пос-
леднего) имеют следующий формат:

   ┌──┬──┬──┬──┬──┬──┬──┬──┐
   │0 │б │у │к │в │а │. │. │
   └──┴──┴──┴──┴──┴──┴──┴──┘

  Последний байт имени:

   ┌──┬──┬──┬──┬──┬──┬──┬──┐
   │1 │б │у │к │в │а │. │. │
   └──┴──┴──┴──┴──┴──┴──┴──┘

  За именем следуют 5 байтов для
выражения самого числа в  интег-
ральной форме.

        Числовой массив

  Первый байт:

   ┌──┬──┬──┬──┬──┬──┬──┬──┐
   │1 │0 │0 │б │у │к │в │а │
   └──┴──┴──┴──┴──┴──┴──┴──┘

  Байты  2,  3  содержат  полную
длину всех элементов (по 5  бай-
тов на каждый  элемент  массива)
плюс по 2 байта на  каждую  раз-
мерность массива, плюс один байт
на указание  количества  размер-
ностей,  т.е.  здесь  содержится
указание на конец массива.
  Байт  4  содержит  размерность
массива.
  Байты 5, 6  содержат  количес-
тво элементов в  первом  измере-
нии.  Если  размерность  массива
более, чем 1, то:
  Байты 7, 8  содержат  количес-
тво элементов во втором  измере-
нии; и т.д. После этого идут са-
ми  элементы  массива:  по  пять
байтов на  каждый  элемент.  Для
многомерных  массивов    порядок
следования   данных   следующий:
b(1,1),b(1,2), b(1,3), b(2,1)...
b(3,3).

        Переменные цикла

  Первый байт:

   ┌──┬──┬──┬──┬──┬──┬──┬──┐
   │1 │1 │1 │б │у │к │в │а │
   └──┴──┴──┴──┴──┴──┴──┴──┘

  Далее:
  5 байтов - текущее значение;
  5 байтов - конечное значение;
  5 байтов - шаг;
  2 байта - номер строки возвра-
            та;
  1  байт - номер  оператора   в
строке, к  которому  выполняется
возврат.

     Символьная переменная

  Первый байт:

   ┌──┬──┬──┬──┬──┬──┬──┬──┐
   │0 │1 │0 │б │у │к │в │а │
   └──┴──┴──┴──┴──┴──┴──┴──┘

  Далее:
  2 байта - длина строки;
  x байтов - текст строки.

       Символьный массив

  Первый байт:

   ┌──┬──┬──┬──┬──┬──┬──┬──┐
   │1 │1 │0 │б │у │к │в │а │
   └──┴──┴──┴──┴──┴──┴──┴──┘

  Далее:
  2  байта - указание  на  конец
массива;
  1 байт - размерность;
  2 байта - длина в первом изме-
рении;
  ..............................
  2  байта - длина  в  последнем
измерении.
  Далее: по одному байту на каж-
дый элемент.




Другие статьи номера:

TR-DOS для начинающих - Окончание.

Компьютерная новелла - Prince of Persia.

Компьютерная новелла - Лазерная бригада (по игре Laser Squad).

Перекресток драконов - Игра Rapscallion.

Перекресток драконов - Игра The Runes of Zendos.

Перекресток драконов - Игра The Saga.

Перекресток драконов - Игра Witch's Cauldron.

Перекресток драконов - Создаём Адвентюру. Обзор редакторов.

Перекресток драконов - Создаём словарь к Адвентюрной игре.

Программы, которые мы выбираем - Возможные последствия использования недокументированных команд.

Программы, которые мы выбираем - О замеченных шероховатостях в работе некоторых программ и пожелания к следующим версиям.

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

Программы, которые мы выбираем - Несколько предложений по усовершенствованию ассемблера.

Программы, которые мы выбираем - Предложения по доработке ZX Word v2.5.

Программы, которые мы выбираем - Программа "Эмулятор Спектрума" v1.2.

Программы, которые мы выбираем - Что хотелось бы иметь в идеальном ассемблере.

Ретро - 40 лучших процедур: Копирование данных в памяти.

Ретро - 40 лучших процедур: Обмен токена.

Ретро - 40 лучших процедур: Определение адреса БЕЙСИК-строки.

Ретро - 40 лучших процедур: Определение длины БЕЙСИК-программы.

Ретро - 40 лучших процедур: Определение размера свободной памяти.

Ретро - 40 лучших процедур: Поиск и замещение строки.

Ретро - 40 лучших процедур: Поиск подстроки.

Ретро - 40 лучших процедур: Поиск строки.

Ретро - 40 лучших процедур: Составление списка переменных.

Ретро - 40 лучших процедур: увеличение и копирование экрана.

Ретро - 40 лучших процедур: Удаление REM-строк.

Ретро - 40 лучших процедур: Удаление блока программы.

Советы экспертов - Игра Fredloader.

Советы экспертов - Игра Robin of Sherwood: The Touchstones of Rhianon.

Советы экспертов - Игра Scorpions: Die Machines.

Советы экспертов - Игра Terropods.

Страничка iS-DOS - Описание рестартов системы IS DOS.

Форум - Алгоритм распознавания символов.

Форум - Время выполнения недокументированных команд процессора Z80.

Форум - Концепция экрана высокого цветового разрешения.

Форум - Несколько Pokes к играм. Программа Hacman96.

Форум - По поводу новых DOS и BIOS для Спектрума.

Форум - Программа Multicolor на любой модели компьютера. Использование 2-го экрана для Multicolor'а. Демонстрация текста. Электронные журналы.

Форум - Проект ZX Config.

Форум - Усовершенствование Art Studio. Идеи относительно компрессии файлов.

Форум - Эмулятор ZX Spectrum на IBM. По поводу шестнадцатеричной системы счисления. Программа ZX-Stars. Странности в Elita

Форум - Эффекты на бордюре и Multicolor.

Читатель-читателю - ZX Spectrum 128 - новые возможности, новые проблемы.

Читатель-читателю - Группа 'Light'. Спектрум и экспертная система.

Читатель-читателю - Драйвер принтера для Scorpion'а.

Читатель-читателю - Печать чисел в различных системах счисления.

Читатель-читателю - Программирование аркадной игры со скроллингом экрана.

Читатель-читателю - Процедура печати меток ассемблера XAS для монитора-отладчика STS 4.3.

Этюды - Атрибутная бегущая строка. "Гасилка" экрана. Упрощенный вариант процедуры "Занавес". Процедура гащения картинки. Процедура проявления картинки по точкам.

Этюды - Графический эффект "цветные полосы".

Этюды - Драйвер экрана для печати по 64 символа в строке.

Этюды - Комплект защит загрузчиков.

Этюды - Обращение к диску в режиме IM 2. Работа с диском нестандартного формата.

Этюды - Печать символа, увеличенного в 8 раз. Программа "наливания" экрана. Процедура гашения экрана по точкам. Очистка экрана как в Terminator'е. Поиск последовательности символов в памяти. Система перекодировки символьного набора.

Этюды - Программа - каталогизатор дисков.

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

Этюды - Программа вывода картинки.

Этюды - Программа зажигания спрайта.

Этюды - Программа очистки заданного окна экрана.

Этюды - Программа сортировки массива по возрастанию. Процедура заполнения экрана заданным атрибутом. Процедура проявления картинки. Эффект летящих навстречу звезд. "Душ", идущий из верхнего левого угла экрана. Процедура "осыпания" картинки по пиксельным линиям. Программа "вытягивания" картинки под углом в 45 градусов. Три процедуры "Scroll".

Этюды - Процедура печати чисел.

Этюды - Процедура прорисовки символа с помощью атрибутов.

Этюды - Процедура проявления картинки. Fade-OUT эффект (картинка уходит за края экрана). Графический эффект "Фонтан". Fade-OUT эффект, имитирующий выключение телевизора. Процедура "зажигания" картинки. Программа плавной прорисовки картинки.

Этюды - Процедура рисования линии.

Этюды - Процедура составления оптимальной таблицы символов.

Этюды - Скроллинг строк текста в заданном окне. Атрибутный скроллер. Диагональный скроллинг.

Этюды - Спрайтовый скроллер. Процедуры проявления экрана.

Этюды - Укороченная процедура индикации амплитуды каналов муз. сопроцессора. Способ вычитания константы из регистровой пары HL.

Этюды - Формула для вычисления дня недели.


Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Обратная связь - контакты редакции.
Party - новая пати в Дзержинске: DiHalt 1999.
AD&D - описания монстров AD&D (часть первая).
Железо - доpаботка Scorpiona, после котоpой будут pаботать все пpогpаммы, с пеpеключением стpаниц по #FD.
Свиток - описание игры Empire 128.

В этот день...   23 апреля