Справочник по системным программам для компьютера ZX Spectrum 1991 г.

Описание GENS4 - принцип работы, директивы, команды условной трансляции, команды ассемблера, строчный редактор, введение в редактор, команды редактора, вставка текста, распечатка текста, редактирование текста.


60000=-5536 (60000-65536)
2.6. Макроопределения

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

Макроопределение состоит из набора инструкций ассемблера
вместе с именем макроопределения. Когда это имя в последующем
используется в поле кода операции, то оно будет заменено на все
инструкции ассемблера, составляющее это макроопределение.

Так, макроопределение NSUB может быть определено следую-
щим образом:

NSU MAC

OR А

SBC HL, DE

ADD HL, DE

ENDM

Когда бы мы в дальнейшем ни применили NSUB как код опера-
ции, оно будет генерировать три инструкции ассемблера^ A; SBC
HL, DE и ADD HL, DE.

Это спасет вас от лишнего печатания и сделает вашу программу
легче для понимания, но вы должны помнить, что при каждом появ-
лении NSUB генерируется объектный код, и, может быть, эффектив-
нее использовать CALL для вызова вместо не подпрограммы. Ниже
мы приводим формат макроопределения и его вызов вместе с некото-
рыми примерами. Изучайте их, пожалуйста, внимательно.

Макроопределение имеет следующую форму:

Имя MAC
• ♦ ♦

• • •

Тело макроопределения
• • «

• • ♦

ENDM

По имени макроопределения будет вызываться его текст, когда
это имя в последующем встретится в поле кода операции. "MAC"
показывает начало макроопределения, a "ENDM" указывает на его
конец.

Параметры макроопределения могут упоминаться внутри мак-
роопределения путем использования знака равенства, за которым
следует номер параметра (0...31) включительно. Таким образом,
макроопределение

MOVE MAC
LD HL, =0
LD DE, =1
LD ВС, =2
LDIR
ENDM

Имеет три параметра, адрес источника, адрес приемника и дли-
ну, загружает нужные значения в HL, DE, и ВС и затем выполняет
инструкцию LDIR. Для того чтобы вызвать макроопределение из тела
вашей программы, просто используйте его имя в поле команд. За
именем макроопределения должны следовать необходимые вам три
параметра:

MOVE 16384, 16385, 4096

В этом примере мы используем особенные адреса, но в действи-
тельности вы можете работать с любыми существующими выражени-
ями для определения значения параметра макроопределения:

MOVE START, START+1, LENGTH

Подумайте, являются ли вышеприведенные примеры хорошим
использованием макроопределения? Не могли ли вы использовать
подпрограмму?

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

Например:

НМС MAC
LD HL, =0*3600
LD DE, =1*60
ADD HL, DE
LD DE, =2
ADD HL, DE
ENDM

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

HOURS EQU 2

MINUTES EQU30
SECONDS EQU 12
START EQU 0

HMC HOURS, MINUTES, SECONDS

LD DE, START

ADD HL, DE ;HL - окончательное время

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

Во время ассемблирования, как только имя макроопределения
встречается в поле команды, ассемблируется его текст. Обычно этот
текст тела макроопределения не попадает в ассемблерный листинг и
печатается только для макроопределения. Однако вы можете усилить
листинг расширением макроопределения, используя команду ассем-
блера *М+, а, используя *М-, запретить распечатывать текст макро-
определения.

Если вы вышли за пределы пространства, отведенного под буфер
макро, то будет выдано сообщение и прервется ассемблирование.
Используйте команду редактора "С" для резервирования буфера
больших размеров.

2.7. Директивы ассемблера

GENS4 распознает определенные псевдокоманды - так называ-
емые директивы ассемблера. Они не влияют на процессор Z80 при
прогоне, т.е. не декодируются, а просто заставляют ассемблер выпол-
нять определенные действия во время трансляции. Эти действия оп-
ределенным образом изменяют код, генерируемый GENS4.

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

ORG <выражение> - устанавливает счетчик адресов равным
значению выражения. Если ключи 2 и 16 оба не указаны и результат
ORG попадает в область GENS4, текстового файла или таблицы
сивволов, то появляется выражение "BAD ORG!" и прекращается
трансляция. См. п.2.0. Для более детального ознакомления с тем, как
ключи 2 и 16 влияют на использование ORG см. Команду "А" в
разделе 3 для некоторых предосторожностей в использовании ORG,
когда автоматически сохраняется объектный код.

EQE <выражение> - этой директиве должна предшествовать
метка. Значению метки присваивается значение выражения. Выра-
жение не должно содержать имен, которым еще не присвоено значе-
ние. В противном случае ассемблер выдает вам сообщение об ошибке

-♦ERROR* 13.

DEFB <выражение>, <выражение>... - Каждое выражение дол-
жно оценивать 8 бит; байт, адрес которого в настоящий момент со-
держится в счетчике адресов, принимает значение выражения и счет-
чик адресов увеличивается на

1. Все вышеуказанное повторяется для каждого выражения.

DEFW <выражение>, <выражение>... - Дополняет слово (2 бай-
та) , адрес которого указан счетчиком адресов, значением выражения
и увеличивает счетчик адресов на 2. Младший байт помещается сна-
чала, за ним следует старший байт. Повторяется для каждого выра-
жения.

DEFS <выражение> - увеличивает счетчик адресов на значение
выражения. Эквивалент резервирования области памяти размером,
равным значению выражения.

DEFM "S" - определяет, что последовательность N байтов памя-
ти будет равна представлению строки "S" в коде ASCII, где N - длина
строки. Теоретически, длина строки может быть от 1 до 255 включи-
тельно, но практически она ограничена длиной строки, которую мож-
но ввести редактором. Первый символ в поле операндов (", как
показано выше) является ограничителем и строка "S" определяется
только символами, лежащими между двумя ограничителями; символ
конца строки также действует как ограничитель строки.

ENT <выражение> - эта директива никак не влияет на генери-
руемый объектный код, она просто используется для определения
адреса, на который осуществляется переход по команде редактора
"R". Выражение ENT устанавливает этот адрес равным значению
выражения. Используется совместно с командой редактора "R"
(см. Разд. 3). Для выполнимого адреса нет умолчания.

2.8. Команды условной трансляции

Команды условной трансляции обеспечивают программисту
возможность включения или не включения определенных секций
исходного текста в процесс ассемблирования. Это возможно при ис-
пользовании команд IF, ELSE, END.

IF <выражение> - эта команда оценивает выражение. Если ре-
зультат равен нулю, то прекращается ассемблирование следующих
линий до тех пор, пока не встретится ELSE или END. Если значение
выражений отлично от нуля, то ассемблирование происходит нор-
мально;

ELSE - эта команда просто переключает ассемблирование. Если
перед появлением ELSE было ассемблирование, то в последующем
оно выключается и наоборот.

END - просто включает ассемблирование.

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

2.9. Команды ассемблера

Команды ассемблера подобно директивам ассемблера не влияют
на работу ассемблера Z80, т.к. они не декодируются в объектные
коды. Однако, в отличии от директив ассемблера, они не влияют на
объектный код, производимый ассемблером команды просто модифи-
цируют формат листинга. Команда ассемблера - эта строка исходного
текста, которая начинается с символа *.

Надпись после звездочки определяет тип команды и должна
быть выполнена заглавными буквами. Ограничением строки может
быть любой текст. Исключение составляют команды L и D, предпо-
лагающие знаки "+" или после команды. В распоряжении програм-
миста имеются следующие команды:

*Е - выдает 3 пустые строки на экран или принтер, это полезно
для разделения модулей.

*HS - выдает строку "S" - заголовок, который будет печататься
после каждого вывода "*Е". *Н автоматически выполняет *Е.

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

Примечание: если *S появляется после *L-, то листинг не оста-
навливается.

*L+ - прекращает листинг и печать, начиная с данной строки.

*L- - начинает листинг и печать, начиная с данной строки.

*D+ - указывает, что значение счетчика адресов в начале каж-
дой строки должно выдаваться в десятичнбм виде вместо обычного
16-ричного.

*D- - возвращает к использованию шестнадцатеричного вида
значения счетчика адресов в начале каждой строки.

*С- - укорачивает листинг ассемблера, начиная со следующей
строки. Листинг характеризуется тем, что он не содержит объектного
кода, генерируемого текущей строкой - это укорачивает строку лис-
тинга на 9 символов и делает строку ассемблера более удобной для
дисплея с 32-мя символами в строке, что улучшает читаемость.

*С+ - возвращает к полному листингу, как описано в разделе 2.0.

*М+ - включает печать макроопределения.

*М- - выключает печать макроопределения.

*F <имя файла> - это очень мощная команда, позволяющая вам
ассемблировать текст с ленты или дисковода

- этот текст читается с ленты или дисковода в буфер, блокиру-
ется там на время и затем ассемблируется из этого буфера; это позво-
ляет создавать объектный код большого размера, только если
исходный ассемблируемый текст не занимает много места в памяти.
Имя текстового файла (до 10 символов), который вы желаете проас-
семблировать таким образом, не обязательно должно быть определе-
но и ему должен предшествовать пробел. Если файл находится на
кассете, то вы указываете это, набивая перед именем файла номер
привода с двоеточием:

*F 2:TEST - для файла на микроприводе N2;

*F TEST - для файла на ленте.

Если не указано имя файла, то с ленты считывается первый
найденный файл, но при считывании с дисковода вышеуказанное
нельзя принимать в расчет. Если вы работаете с дисководов, то файл
должен быть предварительно сохранен с помощью команды редакто-
ра "Р" обычным способом.

Если файл находится на ленте, то вы должны предварительно
загрузить его с ленты при помощи команды редактора "Т", а не "Р" -
это необходимо, так как текстовый файл, содержащийся на ленте,
должен быть преобразован в блоки с достаточным размером межблоч-
ных интервалов, что позволяет ассемблировать текущий блок перед
тем, как следующий начнет грузиться с ленты. Размер блока, исполь-
зуемого данной командой (и командой редактора "Т"), устанавлива-
ется с помощью команды редактора "С" (см. Следующий раздел).
Возможность выбора размера этого буфера позволяет вам оптимизи-
ровать отношение размер/скорость для любых выводов текстов с
ленты. Например, если вы не собираетесь использовать команду "F"
во время ассемблирования, то полезно будет определить размер бу-
фера равным 1 для минимизации пространства, занимаемого GENS4
и минимизации рабочего пространства.

Где бы ни встретил ассемблер команду "F", он определит, откуда
нужно считывать файлы, с дискеты или с ленты. Это происходит на
обоих просмотрах, так как на каждом просмотре необходимо скани-
ровать текст. Если считывается лента, то на ней ищется файл с
требуемым именем или первый файл.

Если имя файла во время его поиска на ленте не соответствует
заданному, то выдается сообщение: "FOUND FILE" и поиск продол-
жается, в другом случае выдается сообщение: "USING FILE", файл
загружается блок за блоком и обрабатывается. Подробнее ознако-
миться с "F" вам поможет пример приложения 3.

Остальные команды ассемблера обрабатываются только на вто-
ром просмотре.

Если ассемблирование было прервано одной из команд условной
трансляции, то и работа любой команды ассемблера также прерыва-
ется.

Замечание: описанные возможности не годятся для систем
DISCIPLE, OPUS и PLUS 3 DEVPAC 4. Быстрее и легче вместо ленты
использовать диск. Следствием этого является то, что в этих версиях
команда "С" не позволяет вам определить размер буфера загрузки и
команда "Т" не существуёт.

3. Строчный редактор

3.1. Введение в редактор

Редактор, поставляемый со всеми версиями GENS4, является
простым строчным редактором, разработанным для обслуживания
всех операционных систем, сделанных для Z80. Редактор прост в
использовании и дает возможность редактировать программы просто
и эффективно.

Для уменьшения размера текстового файла редактор выполняет
определенное сжатие пробелов. Это происходит по следующей схеме:
когда вводится строка с клавиатуры, она символ за символом зано-
сится во внешний, относительно ассемблера буфер и затем, в конце
строки (когда вы нажимаете клавишу <ENTER>), строка перемеща-
ется из буфера в текстовый файл. Во время этого перемещения про-
исходит определенное сжатие пробелов: если первый символ строки -
пробел, то в текстовый файл вводится символ табуляции, и все после-
дующие пробелы пропускаются. Если первый символ в строке не
пробел, то символы заносятся из буфера в текстовый файл, пока не
встретится пробел, после чего обработка ведется так же, как если бы
следующий символ был бы первым символом в строке. Это продолжа-
ется и в дальнейшем. В результате символы табуляции включаются
в начале строки или между меткой и кодом операции, а также между
кодом операции, операндами и комментариями. Конечно, если код
возврата каретки (ENTER) встречается в любое другое время, то
преобразование завершается и управление передается редактору.

Этот процесс сжатия понятен, и вы можете просто использовать
клавишу "-->" для того, чтобы получить кратко протабулированный
файл, который также экономичней для хранения. Заметим, что про-
белы не сжимаются внутри комментариев и что пробелы не должны
присутствовать в полях меток, кодов операций и операндах.

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

llv II
^ *

В ответ на подсказку вы можете ввести командную строку сле-
дующего формата:

С N1, N2, SI, S2 <ENTER> , где:

"С" - мнемоника команды, которую необходимо выполнить;

N1 - число в пределах от 1 до 32767 включительно;

N2 - число в пределах от 1 до 32767 включительно;

SI, S2 - строка не более чем из 20 символов.

Запятая используется для разделения различных аргументов,
хотя это можно изменить - см. Команду "S". Пробелы игнорируются
во всех случаях кроме тех, когда они находятся внутри строк. Ника-
кой из аргументов не является обязательным, хотя некоторые коман-
ды, например, команда "DELETE", не будут работать, если опущены
аргументы N1 и N2.

Редактор помнит ранее введенное число и строки и использует
сформированное значение для применения, если вы не определили
другие значения внутри командной строки. Первоначально значения
N1, N2 устанавливаются равными 10, а строки - пустыми.

Если вы вывели неправильную командную строку, например,
F - 1, 100, HELLO, то эта команда будет проигнорирована и появится
сообщение "PARDON?". При этом вы должны ввести командную
строку правильно, например, F1, 100 HELLO.

Это же сообщение появится, если длина строки S2 превышает 20
символов. Если более 20 символов содержит строка S1, то лишние
символы игнорируются.

Команды могут вводиться как на верхнем, так и на нижнем
регистрах.

При вводе команды определенные комбинации ключей могут
использоваться для ее редактирования. Так, клавиша "<--" использу-
ется для стирания символов в направлении начала строки, "-->" - для
продвижения курсора в следующую позицию табуляции, "CAPS
SHIFT 0" или "DELETE" - для уничтожения предыдущего символа.

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

3.2. Команды редактора

3.2.1. Вставка текста

Текст может быть введен в текстовый файл или указанием но-
мера строки, пробела и требуемого текста, или посредством команды
"Г. Заметим, что если сразу за номером строки вы введете <ENTER>,
то эта строка будет удалена из текста, если, конечно, он существует.
Где бы не вводился текст, можно применять клавиши "<—", "-->" и
<EDIT> (возврат к метке команды).

Клавиша <DELETE> будет уничтожать предыдущий символ (но
не далее начала строки текста).

Текст вводится во внешний буфер внутри GENS4 и вы должны
оградить его от переполнения использованием клавиш <DELETE>
или "<--" для освобождения свободного пространства. Если во время
ввода текста редактор определит, что конец текста перекрывает вер-
шину адресуемой памяти, то выдается сообщение <BAD MEMORY!>.
Это показывает, что далее текст вводить нельзя и что текстовый файл
или последняя его часть должна быть сохранена на кассете для даль-
нейшего восстановления.

Команда "I N, M"

Использование этой команды переводит ввод в автоматический
режим: вам подсказывают номера строк, начиная с N приращением
М на каждом шагу. После высвечивающегося номера вы вводите
нужный текст, по желанию используя нужные клавиши, и заверша-
ете строку текста вводом <ENTER>. Для выхода из этого режима
используется <EDIT>.

Если вы вводите строку с уже существующим номером, то строка
текста с этим номером удаляется и заменяется на вновь введенную
после нажатия <ENTER>.

Если автоматическое увеличение номера строки дает значение,
большее 32767, то происходит автоматический выход из режима ввода.

Если при вводе текста вы добрались до конца строки на экране,
но еще не ввели 64 символа (размер буфера), то экран сдвинется
вверх на одну строку и вы можете продолжать ввод со следующей
строки - номер строки автоматически будет соответствовать введен-
ному тексту.

3.2.2. Распечтка текста

Текст может быть проверен с помощью команды "L"; номер
строки, постоянно отображаемый при выполнении данной команды,
устанавливается заранее, но он может быть изменен с помощью ко-
манды "К".

Команда " LN, М "

Эта команда выводит листинг со строки N до строки включи-
тельно на терминал. По умолчанию N присваивается значение 1, М
- 32767, т.е. значениями по умолчанию не являются ранее введенные
аргументы.

Для листинга целого файла просто используйте команду "L" без
аргументов. Строки на экране форматируются по левой границе эк-
рана, так что номер строки отображается ясно. Строка протабулиро-
вана автоматически, в результате чего получаем четкое разделение
полей в строке. Номер отображаемой на экране строки может быть
проконтролирован с помощью команды "К" - после листинга опреде-
ленного количества строк листинг будет приостановлен (даже если
это еще не строка М). Для возврата в точку входа в редактор нажмите
клавишу <EDIT> или любую другую клавишу для продолжения.

Команда " К N "

"К" устанавливает количество экранных линий, которые долж-
ны отображаться на терминале перед паузой, как это было описано
выше (см. Команду "L"). Значение N (не более 256) хранится в
памяти. Например, если вы хотите при последующем использовании
"L" выдавать на экран по 5 строк, то введите команду "К5".

3.2.3. Редактирование текста

Однажды созданный текст неизбежно будет нуждаться в редак-
тировании некоторых строк. В GENS4 имеются команды, позволяю-
щие исправлять, стирать, перемещать и перенумеровывать строки.

Команда " D [N, М]"

Все линии от N до М включительно удаляются из текстового
файла. Если M<N или определено менее двух аргументов, то команда
игнорируется. Это сделано для предотвращения ошибок из-за не-
брежности. Одиночная строка может быть уничтожена указанием
N=M. Этого же можно достичь простым введением номера строки, за
которым следует <ENTER>.

Команда " М N, М "

Эта команда помещает текст строки с номером N в строку М,
уничтожая текст, уже существующий там. То есть эта команда по-
зволяет вам перемещать строку текста внутри текстового файла.
Если строки с номером N не существует, то команда игнорируется.

Команда " N [N, М]"

Команда "N" перенумеровывает М строк текстового файла, на-
чиная со строки N. N и М должны быть реальными и если номер линии
превышает 32767, то остается первоначальная нумерация.

Команда "F N, М, F, S "

Текст со строки N до строки М исследуется на появление строки
F. Если такая строка найдена, то она отображается на терминале и
включается режим "EDIT" (см. ниже).

Вы можете использовать команды внутри режима EDIT для
нахождения последующих появлений строки F в пределах опреде-
ленной области строк или для замещения строкой S текущего появ-
ления строки F и затем продолжить поиск строки F. Отметим, что
диапазоны строк F и S могут быть установлены ранее другой коман-
дой, так что возможно вводить только F для инициализации поиска
(см. Пример в разделе 3. 3).

Команда "EN"

Редактирует строку с номером N. Если строки N не существует,
то команда игнорируется; в противном случае строка копируется в
буфер и отображается на терминале вместе с номером строки. Номер
строки вновь отображается под строкой и включается режим редак-
тирования. Все последующее редактирование происходит внутри бу-
фера, а не внутри самого текста, так что первоначальная строка
может быть получена в любой момент.

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

<SPACE> - перемещает курсор на одну позицию к следующему
символу в строке. Вы не можете шагнуть на конец строки.

<DELETE> - возвращает курсор на предыдущий символ в стро-
ке. Невозможно шагнуть левее первого символа строки.

<—> > - перемещает курсор на следующую позицию табуляции
в каждой экранной строке.

<ENTER> - конец редактирования данной строки. Сохраняет
все сделанные изменения.

<Q> - выход из режима редактирования данной строки, т.е.
покидание редактируемой строки с игнорированием всех сделанных
изменений. Строка остается такой же как она и была до редактиро-
вания.

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

<L> - распечатывает остаток строки, который должен быть отре-
дактирован, т.е. остаток строки за текущей позицией курсора. Вы
остаетесь в режиме редактирования с указателем, перепозициониро-
ванным в начало строки.

<К> - уничтожает символ в указываемой курсором позиции.

<Z> - уничтожает все символы, начиная с указанного курсором
и до конца строки.

<F> - ищет следующее появление строки "F", ранее определен-
ной в командной строке (см. Команду "F" выше).

Эта подкоманда будет автоматически выводить систему из ре-
жима редактирования текущей строки (сохраняя все изменения) да-
же если цепь символов "F" в текущей строке не встретилась. Если
цепочка "F" встретилась в последующих строках текста внутри пер-
воначально определенного диапазона, то будет включен режим ре-
дактирования для строки, в которой найдена заданная
последовательность символов "F". Отметим, что курсор всегда уста-
навливается в начало найденной строки.

<S> - замещает ранее определенной строкой "S" текущее прояв-
ление цепи символов "F" и затем выполняет подкоманду "F", т.е.
осуществляет поиск следующей строки "F". Так, вместе с вышеупо-
мянутой командой "F" она используется для пошаговой замены строк
символов "F" строками "S". См. раздел 3.3 для примера.

<1> - вводит символ в указанную курсором позицию. Вы будете
оставаться в этом режиме до тех пор, пока не нажмете <ENTER>. По
этой клавише вы возвращаетесь в основной режим редактирования с
указывающим на последний введенный символ. Используя
<DELETE> внутри этого режима, вы уничтожите символ в буфере
слева от курсора, тогда как, используя < —> >, переместите курсор в
следующую позицию табуляции, включая пробелы внутри буфера.

<Х> - перемещает курсор в конец строки и включает описанный
подрежим.

<С> - изменяет подрежим. Это позволяет перезаписать символ
в текущей позиции, затем передвигать курсор через одну позицию.
Вы останетесь в измененном подрежиме до тех пор, пока не нажмете
клавишу <ENTER>, нажатие которой возвратит вас в основной ре-
жим редактирования с курсором, указывающим на последний изме-
ненный символ. <DELETE> просто сдвигает через одну позицию
курсор влево, а < —> > не имеет эффекта.




СОДЕРЖАНИЕ:


  Оставте Ваш отзыв:

  НИК/ИМЯ
  ПОЧТА (шифруется)
  КОД



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

Похожие статьи:
Millennium 2003 - Как вы уже догадались, сегодня наша цель - Millеnnium 2ОО3.
Игры - Пару слов по этой новой игре New Dizzy про нашего любимого Диззика.
Проекты - Specnet или spectrum network: проект, призванный объединить разобщенную толпу спектрумистов.
Editorial - Sq: "никогда у меня писать не получалось, и я всегда завидовал тем, у кого это получалось очень хорошо"...
Вступление - содержание номера.

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