Каналы и потоки
Операторы языка Бейсик, такие как PRINT, INPUT и некоторые другие,
работают несколько сложней, чем это может показаться на первый взгляд.
Выполните, например, оЦератор:PRINT #0;"Test message": PAUSE О
Сообщение будет выведено на служебный экран. Если заменить число
после символа # на 2, то вывод осуществится на основной экран, если
подставить 3 — сообщение будет напечатано на принтере.Для достижения большей гибкости при организации ввода/вывода в
ZX Spectrum нет твердо установленного соответствия между операторами
ввода/вывода и внешними устройствами» Связь между ними устанавлива-
ется с помощью системы каналов и потоков — каждый канал связан с
конкретным устройством ввода/вывода, поток же указывает на канал, через
который будут передаваться данные.| Оператор}-*»| Поток »|~Канал |—Внешнее устройство |
Информация о существующих каналах хранится в области ОЗУ, на
которую указывает системная переменная CHANS (23631/32). Каждый
канал задается так называемым описателем канала — блоком памяти, состо-
ящем не менее чем из пяти ячеек этой области. Первые два байта описателя
составляют адрес программы вывода на связанное с каналом внешнее
устройство, следующие два — адрес программы ввода, пятый байт —
символьное имя канала. Здесь же может храниться и другая информация о
каналеf но операционная система использует только упомянутые пять байт.Системная переменная CURCHL (23633/34) содержит адрес первого
байта описателя текущего канала (канала, через который осуществляется
ввод/вывод в данный момент). Записав в эту переменную адрес первого
байта описателя другого канала, можно установить его текущим.При запуске компьютера операционной системой задаются четыре
стандартных канала, которые обеспечивают:"К" — вывод на вспомогательный экран и ввод с клавиатуры;
"S" — вывод на основной экран;
"R" — запись байта в рабочую область памяти, адресуемую переменной
K_CUR (23643/44);
"Р" — вывод байта на ZX Printer.
Описатели стандартных каналов занимают первые 20 байт в области
информации о каналах. Их порядок менять не следует. Каналы "S", "R" и
"Р" работают только на вывод (при попытке ввода управление передается на
подпрограмму обработки ошибок (#15С4), выдающую при этом сообщение
J Invalid I/O device).При написании собственных процедур ввода/вывода, которые впос-
ледствии будут «подключены» к какому-нибудь каналу, следует учитывать*) Работа с принтером в Spectrum 128 организована иначе.
требования, предъявляемые к ним операционной системой ZX Spectrum.
Обмен байтами (передача/прием) между операционной системой и подпрог-
раммами ввода/вывода осуществляется через аккумулятор. Программа вво-
да, кроме того, использует некоторые флаги: при получении байта устанав-
ливает флаг переноса CY; если байт на данный момент не введен, флаг CY
сбрасывается и устанавливается флаг Z; при обнаружении конца файла или
ошибки сбрасываются флаги CY и Z, после чего системой будет выведено
сообщение 8 End of file. Заметим, что при ожидании ввода (флаг Z установлен)
система не контролирует клавишу Break, об этом нужно позаботиться в
программе ввода. Программы ввода/вывода являются подпрограммами от-
носительно операционной системы ZX Spectrum.В Бейсике не существует операторов для задания новых каналов, для
этого необходимо написать специальную программу в кодах (или на Бейсике,
используя оператор РОКЕ). Не рекомендуется «подключать» программы вво-
да/вывода к уже существующим каналам (то есть помещать в описатель
канала адреса новых программ ввода/вывода), лучше задать новый канал.
Количество каналов ограничено лишь свободным пространством ОЗУ.Для осуществления ввода/вывода недостаточно только задать канал,
необходимо еще и связать его с конкретным потоком. Только после этого, указывая
в бейсик-операторах ввода/вывода номер потока (число, записываемое после
символа #), через канал можно будет передавать и принимать информацию.В операционной системе ZX Spectrum имеется 19 потоков, которым
присвоены номера от —3 до 15. После запуска компьютера системой откры-
ваются (связываются с одним из каналов) 7 потоков с номерами от -3 до 3
— эти потоки переназначать не рекомендуется. Потоки от -3 до -1 недоступ-
ны из Бейсика (хотя поток -3 связан с тем же каналом, что и потоки 0 и 1,
а поток -2 — с тем же каналом, что и поток 2). Текущий поток устанавливается
с помощью подпрограммы, расположенной по адресу #1601 (см. «Исполь-
зование подпрограмм ПЗУ»).Информация о связи потоков с каналами хранится в области систем-
ных переменных STRMS, начиная с адреса 23568 (#5СЮ). Первые две
ячейки этой области указывают на канал, связанный с потоком -3, следую-
щие две — с потоком -2 и т. д. В этих ячейках хранятся увеличенные на
единицу смещения первого байта описателя канала, с которым связывается
поток, относительно начала области информации о каналах (системная
переменная CHANS). Если поток не связан ни с одним из каналов, ячейки
обнулены, и считается, что поток свободен (закрыт). На рис. 14 приведена
диаграмма связи потоков и стандартных каналов после запуска компьютера.![]()
Для открытия потока из Бейсика служит оператор OPEN #0/4", где п
— номер потока (0...15), at — имя канала, связываемого с потоком. Напри-
Мер, после выполнения оператораOPEN #7,"S"
при выводе в поток 7 информация будет передаваться в канал "S", то
есть на основной экран:PRINT #7;"Printing in 7th stream"
Поток n закрывается оператором CLOSE #n, например:
CLOSE #7
Если после закрытия потока Вы попытаетесь вывести в него инфор-
мацию, то получите сообщение об ошибке О Invalid stream.К сожалению, с помощью операторов OPEN и CLOSE могут быть
подключены только каналы "S", "К" и "Р". При попытке использовать другие
имена каналов выдается сообщение об ошибке*.Ввод информации осуществляется оператором INPUT #п либо функ-
цией INKEY$ #п. Используя INPUT, помните, что оператор работает точно
также, как и при вводе с клавиатуры. Например, выполнение INPUT #4;а$
приведет к тому, что перед передачей информации из потока 4 в переменную
а$ через этот поток будут выведены две кавычки.Операторы LIST и PRINT по умолчанию выводят информацию в поток
2 (на экран), a LLIST и LPRINT — в поток 3 (на принтер), хотя при явном
указании номера потока и те и другие могут использоваться для вывода на
любое устройство (например, оператор LLIST #2 будет выводить листинг
программы на экран).Формат хранения текста программы на Бейсике
Строки бейсик-программы размещаются в порядке возрастания но-
меров в области памяти, адрес начала которой задается системной перемен-
ной PROG (23635/36). Они хранятся в следующем формате:ст. байт мп.байт ст.баит
Номер строки Длина! строки Текст ^строки Байт #0Р|
t_^_/
Номер строки может принимать значения от 0 до 9999 (правда, из
Бейсика редактировать строку с номером 0 невозможно). Обратите внима-
ние также на то, что номер записан «наоборот», то есть сначала размещается
старший байт, а затем младший. Длина текста бейсик-программы рассчиты-
вается с учетом символа перевода строки (код #0D).Текст строки хранится в виде кодов ASCII-символов и токенов — кодов
операторов Бейсика (см. «Таблица символов»). Непосредственно после сим-
вольной записи числа размещается его образ во внутреннем формате: байт
#0Е и 5 байт собственно числа (1 байт порядка и 4 байта мантиссы). При
записи пользовательской функции DEF FN после каждого параметра резер-
вируются 6 байт для записи чисел в аналогичном формате.Формат хранения переменных
В именах переменных бейсик-программы допускается использовать
буквы латинского алфавита A...Z и a...z (в числовых переменных могут также*) Некоторые внешние устройства, например, Interface 1, могут перехваты-
вать это сообщение и заменять стандартное ПЗУ своим, существенно
расширяя возможности работы с каналами.использоваться цифры от 0 до 9). Интерпретатор Бейсика не делает различий
между строчными и прописными буквами. Кроме того, пробелы в именах
числовых переменных игнорируются, например, имена «Label 12» и
«LABEL 12» в программе будут указывать на одну и ту же переменную.После определения переменной в бейсик-программе она помещается
в специально отведенную область памяти, адрес начала которой задается
системной переменной VARS (23627/28). Порядок расположения перемен-
ных соответствует последовательности их определения в программе.При записи переменных их тип задается тремя старшими битами
первого байта формата:010 — символьная переменная;
011 — числовая переменная с одним символом в имени;
100 — числовой массив;
101 — числовая переменная с несколькими символами в имени;
110 — символьный массив;
111 — переменная цикла FOR...NEXT.
В остальные биты первого байта записываются младшие 5 бит имени
переменной (если переменная многосимвольная, то младшие 5 бит первой
буквы ее имени):![]()
Составленный подобным образом байт называется щенпихришпорсм
переменной.Числовые переменные (numeric variables!
Имена числовых переменных в бейсик-программе могут состоять из
неограниченного числа символов (букв или цифр), но первым символом
имени обязательно должна быть буква. Хранение в памяти переменных, имя
которых задано одним символом, и переменных с многосимвольным именем
осуществляется в различных форматах.Для записи числовых переменных с односимвольным именем исполь-
зуется 6 байт: 1 байт идентификатора и 5 байт под численное значение
переменной во внутреннем формате:![]()
Формат размещения переменной с многосимвольным именем:
Формат размещения переменной с многосимвольным именем:
![]()
Числовой массив (numeric array)
Имя числового массива может состоять только из одной буквы. Эле-
менты массива хранятся в памяти последовательно в сторону увеличения
индекса. Например, элементы массива S(2,3,4) (количество измерений — 3;![]()
первая размерность — 2; вторая — 3; третья — 4) в памяти будут распола-
гаться в такой последовательности: (1,1,1); (1,1,2); (1,1,3); (1,1,4); (1,2,1);
(1,2,2); (1,2,3); (1,2,4); (1,3,1); ...; (1,3,4); (2,1,1); (2,1,2); ...; (2,3,4).При определении массива оператором Бейсика DIM всем его элементам
присваивается нулевое значение.Управляющая переменная цикла FOR...NEXT (index variable)
Имя управляющей переменной цикла FOR...NEXT может состоять толь-
ко из одной буквы. Кроме идентификатора, начального и конечного значе-
ний, а также шага цикла, запись переменной содержит номер строки
оператора FOR и номер в строке оператора, следующего за FOR. Обратите
внимание, что номер строки в этом случае хранится «правильно» — сначала
младший, а затем старший байт.![]()
Символьная переменная {string)
Имя символьной переменной задается одной буквой, за которой
следует знак $. Количество байт, отводимых для записи символьной пере-
менной, не ограничено и равно длине строки, хранящейся в переменной в
данный момент, плюс 3 байта (идентификатор и 2 байта длины текста). Если
переменная принимает значение «пустой строки»,,под нее отводится только
три байта (байты длины равны нулю).![]()
Символьный массив (character array)
Имя символьного массива может состоять только из одной буквы. Его
элементы хранятся в таком же порядке, что и элементы численного массива.При определении массива оператором Бейсика DIM всем его элемен-
там присваивается значение 32 (#20) — код символа «пробел».![]()
Стек калькулятора
Для вычислений значения выражений интерпретатор Бейсика ис-
пользует подпрограмму калькулятора из операционной системы
ZX Spectrum, которая вызывается инструкцией RST #28. Калькулятор орга-
низован по стековому принципу — исходные значения для вычислений
сначала помещаются в стек, а затем с помощью специальных команд над
ними производятся необходимые действия. В стеке калькулятора сохраняют-
ся также промежуточные результаты вычислений._Стек операционной системы
Стек операционной системы — это стек микропроцессора Z80. Обыч-
но его величина вполне достаточна для работы как бейсик-программ, так и
подпрограмм в кодах, вызываемых из Бейсика. Размер области памяти,
отводимой под стек, не должен быть меньше 80 байт, в противном случае
будет выдано сообщение 4 Out of memory.Если в своей программе Вы переназначили указатель стека, то при
возврате в Бейсик его значение необходимо восстановить.Стек оператора GO SUB
Этот стек используется для сохранения адресов возврата при вызове
подпрограмм оператором GO SUB.При выполнении каждого оператора GO SUB в стек помещаются три
байта: номер следующего за GO SUB оператора (1 байт) и номер строки, в
которой он расположен (2 байта).Область символов, определяемых пользователем
При запуске системы область определяемых пользователем символов
размещается в самом конце ОЗУ. Изменив значения переменной UDG,
можно переместить область в любое место памяти (см. «Русификация
ZX Spectrum», «Системные переменные»).