ZX-Ревю 1992 №1-2 1991 г.

40 лучших процедур - внутренняя структура ZX Spectrum.


2. ВНУТРЕННЯЯ СТРУКТУРА ZX SPECTRUM

Компьютер - это машина, которая способна запомнить последовательность команд и затем выполнить их. Конечно, чтобы сделать так, требуется память, в которой команды могут быть сохранены. ZX SPECTRUM имеет два типа памяти. Первый тип - ПЗУ (ROM), в котором содержится фиксированная последовательность инструкций, введенных в машину ее изготовителем.

Второй тип - ОЗУ (RAM). RAM - это "блокнот для записей" компьютера. Когда компьютер выполняет задачу, он непрерывно просматривает, что находится в RAM ("чтение" из памяти) и обновляет содержимое RAM ("запись" в память). SPECTRUM не использует свой "блокнот" для записей случайно. Различные части RAM используются для хранения различных видов информации. Программа BASICa, введенная пользователем, например, хранится в одной части RAM, в то время как переменные, используемые этой программой, хранятся в другом месте. Размер "блокнота" для записей ограничен, и потому машина точна при распределении пространства для информации, которую она хранит. Свободное пространство собрано в одном месте, и, если пользователь хочет добавить строку в свою программу, информация в RAM должна быть "перетасована" по всей длине, используя некоторую свободную область для вставки дополнительной строки.

В значительной степени эта глава посвящена объяснению организации RAM SPECTRUMa, так как многие программы раздела B предназначены для манипуляций с RAM. Глава содержит в себе описание дисплейного файла, атрибутов, буфера принтера, системных переменных, программной области и области программных переменных. В конце раздела описываются стандартные подпрограммы из ROM, к которым ссылаются программы в Разделе В.

Карта памяти

RAM имеет 49152 ячейки памяти. Каждая ячейка может хранить одиночное целое число от 0 до 255 включительно и задается адресом, который является положительным целым числом от 0 до 65535. Адреса от 0 до 16383 зафиксированы для постоянной памяти -ROM. Первый адрес RAM (ОЗУ) - 16384. Табл. 2. 1. - упрощенная карта памяти SPECTRUMa, которая показывает, как используется RAM с адреса 16384.

Дисплейный файл, который хранит отображаемую на экране информацию, занимает ячейки от 16384 до 22527. Атрибуты, которые определяют цвет, яркость и т.д. для каждого знакоместа экрана следуют непосредственно дальше: в ячейках 22528 - 23295.

Первые 5 адресов в колонке Таблицы 2.1. являются фиксированными, т.к. дисплейный файл, атрибуты и т.д. занимают фиксированное положение. Пятая область назначена для карты памяти микродрайва. Это небольшое периферийное устройство представляет собой нечто среднее между магнитофоном и дисководом. Грубо говоря - это дешевая альтернатива дисководу. Скорость его работы достигаете за счет того, что, с одной стороны, лента движется с очень высокой скоростью, а с другой - за счет организации прямого доступ к файлам, как на диске, а не последовательного, как на магнитофонной кассете. Вот для того чтобы иметь в некоем месте хранилище с данными о том, что записано на каждом секторе микродрайва в памяти компьютера и выделен область карты памяти микродрайва. Если микродрайв (а точнее INTERFACE-1, через который он подключается), подсоединен к SPECTRUMy, эта область содержит информацию о его секторах. Если же не подсоединен, эта область не нужна и в этом случае шестая область (информация о каналах) размещена непосредственно за четвертой областью, системными переменными, т.е. стартовый адрес области информации о каналах и всех последующих областей не фиксирован, а может "плавать" вверх-вниз в RAM. SPECTRUM хранит стартовый адрес всех этих областей в системных переменных. Область системных переменных находится перед картой микродрайва в ячейках 23552-23733 включительно. Эти адреса являются все время строго фиксированными.

Стартовый адрес или имя

Ячейка системной

Содержимое памяти

системной переменной

переменной

16384

-

Дисплейный файл

22528

-

Атрибуты

23296

-

Буфер принтера

23552

-

Системные переменные

23734

-

Карта микродрайва

CHANS

23631

Область информации о каналах

PROG

23635

Адрес начала программы на БЕЙСИКе

VARS

23627

Адрес начала области программных переменных.

E-LINE

23641

Адрес области редактирования

WORKSP

23649

Буфер INPUT

STKBOT

23651

Стек калькулятора

STKEND

23653

Свободная область

SP

-

Машинный стек и стек GO SUB

RAMTOP

23730

Пользовательские подпрограммы в машинном коде.

UDG

23675

Графика пользователя.

P-AMT

23732

Физическая вершина ОЗУ.

Таблица 2.1. Карта памяти. Указатель стека SP хранится не в RAM, а в SP -регистре

микропроцессора Z80A.

Адреса ячеек, которые хранят стартовые адреса всех "плавающих" областей, даны в колонке 2 таблицы 2.1. Адрес области начала программы BASICa, например, хранится в ячейках 23635 и 23636 в области системных переменных.

Примечание: Ссылка к системной переменной с помощью адреса, по которому она хранится, довольно неудобна. По этой причине в Таблице 2.1. в 1-ой колонке даны условные имена системных переменных. Эти имена удобны только для пользователей, в то время как SPECTRUMOM они, естественно, не распознаются. Например, введенная строка: PRINT PROG

даст сообщение об ошибке

"2: variable not found" ("Переменная не найдена").

PEEK и POKE

Карта памяти - это ключ для понимания того, как компьютером используется RAM-память. Для непосредственного управления RAM используются ключевые слова BASICa -РЕЕК и POKE, которые позволяют просмотреть и изменить содержимое любой ячейки памяти. РЕЕК - функция вида:

РЕЕК <адрес>

Адрес - это целое положительное число от 0 до 65535 или арифметическое выражение, которое, выполняясь, дает положительное число. Важно заключить арифметическое выражение в скобки, т.к. РЕЕК 16384 + 2 интерпретируется, как (2 + результат РЕЕК 16384), тогда как РЕЕК (16384 + 2) интерпретируется, как РЕЕК 16386

Значение, выдаваемое функцией РЕЕК - это число, хранящееся по данному адресу в текущий момент. Оно всегда будет положительным от 0 до 255.

Выше объяснялось, что системная переменная PROG хранится по адресу 23635, но значение PROG (т.е. адрес в RAM) всегда больше числа 255. Следовательно, для его хранения необходимы две смежных ячейки с адресами 23635 и 23636. Значение PROG может быть получено с помощью командной строки: PRINT "PROG="; PEEK 23635 + 256 * РЕЕК 23636

Все адреса хранятся в 2-х смежных ячейках в такой форме и могут быть получены вводом: PRINT РЕЕК 1-я ячейка + 256 * РЕЕК 2-я ячейка

Например, если SPECTRUM используется без подсоединенного микродрайва, область карты микродрайва не будет существовать, и информация о каналах будет располагаться непосредственно после области системных переменных, т.о. системная переменная CHANS должна быть такой же, как стартовый адрес карты микродрайва, когда он существует, т.е. 23734. CHANS хранится в 23631 и 23632 и, следовательно, после ввода: PRINT РЕЕК 23631 + 256 * РЕЕК 23632 будет получено значение 23734.

Функция РЕЕК может быть использована также для просмотра содержимого любой из ячеек ПЗУ. Это очень полезно. Просмотр любой ячейки не приводит к разрушению или искажению программы или переменных. Иногда результаты РЕЕК могут быть обманчивыми, т.к. содержимое ячейки, которая просматривалась, может изменяться в течение или непосредственно после выполнения команды просмотра.

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

Команда POKE более рискованная, чем функция РЕЕК, т.к. задавая ее, пользователь вмешивается в функционирование компьютера. Использование этой команды может быть причиной сбоя машины или ее останова.

Формат команды:

POKE <адрес>,<число>

Адрес - это положительное целое число от 0 до 65535 включительно или арифметическое выражение, которое дает такое число. В этом случае нет необходимости заключать арифметическое выражение в скобки, т.к. РОКЕ - это команда, а не функция (хотя есть негласная заповедь, что лишними скобками программу не испортишь). Число, помещаемое в ячейку, может быть от 0 до 255 включительно.

Дисплейный файл

Обычно дисплей содержит 24 строки по 32 символа. Дисплейный файл занимает ячейки от 16384 до 22527, т.е. 6144 ячейки в общей сложности. Следовательно, количество ячеек, используемое для символа:

6144/(24*32)=8.

Эти 8 ячеек формируют изображение символа экране, называемое знакоместом.

Наиболее легкий путь получения общего впечатления о том, как организован дисплейный файл - это печать (PRINT) картинки на экране, сброс (SAVE) экрана на ленту, очистка экрана (CLS) и загрузка (LOAD) картинки экрана вновь. Программа P2.1 сохраняет (SAVE) и загружает (LOAD) экран, используя графический символ на клавише 5 для создания оригинальной картинки.

Программа P2.1.

100 FOR I=0 ТО 703

110 PRINT " "; : REM символ, находящийся на клавише "5" в G-режиме 120 NEXT I

130 SAVE "Picture" SCREEN$ 140 CLS

150 INPUT "Перемотайте ленту и включите воспроизведение"; z$ 160 LOAD "Picture" SCREEN$

Когда картинка загружается с ленты, видно, что дисплей разделен на три зоны по 8 символьных строк в каждой, а каждая строка разделяется на восемь пиксельных линий. SPECTRUM загружает сначала верхние пиксельные линии для первых восьми строк, затем следующие пиксельные линии тех же восьми строк и т.д. Таким же образом формируются средняя и нижняя части дисплея.

Другой путь понимания формирования дисплея - это рассмотреть, где хранятся 8 байтов, которые используются для формирования символа в верхнем левом углу экрана. Первый байт формирует самую верхнюю 1/8 часть символа и размещается в начале дисплейного файла по адресу 16384.

Команда РОКЕ 16364,0 очистит верхнюю линию пикселей самого верхнего левого знакоместа, в то время, как РОКЕ 16384,255 закрасит всю эту линию. При помещении в эту ячейку числа от 0 до 255 мы получим в этом месте экрана различные штрихи. Вторая сверху линия в первом знакоместе на экране не сформирована числом, хранящимся в ячейке 16385, - эта ячейка используется для верхней линии пикселей в соседнем символе. Вторая линия сверху в первом знакоместе формируется числом, хранящимся в ячейке 16384+32*8=16640.

Подобным же образом вычисляются адреса оставшихся шести линий этого знакоместа.

Следовательно, образ символа в верхнем левом углу экрана определяется содержимым адресов 16384, 16640, 16896, 17152, 17408, 17664, 17920, 18176.

Программа P2.2. позволяет Вам экспериментировать, помещая различные числа в эти восемь ячеек.

Программа P2.2. Программа для создания символа в верхнем левом углу экрана.

10 REM подпрограмма установки символа в верхнем углу экрана

20 INPUT "Символ состоит из восьми байтов, каждый из которых - число в диапазоне от 0 до

255. Введите номер байта (от 0 до 7)";n 30 IF n<0 OR n>7 OR n<>INT n THEN BEEP 0.2,24: GO TO 20 40 INPUT "Ввести содержимое байта"^

50 IF m<0 OR m>255 OR m<>INT m THEN BEEP 0.2,24: GO TO 40 60 POKE 16384+8*32*n,m

Программа P2.3. Программа декодирования атрибута.

10 REM декодер атрибутов

20 DATA "Black", "Blue", "Red", "Magenta", "Green", "Cyan", "Yellow", "White", "Bright",

"Flash" 30 DIM C$(8,7) 40 FOR I=1 TO 8 50 READ C$(I) 60 NEXT I

100 REM Декодер атрибутов

110 INPUT "Ввести число от 0 до 255. Эта программа декодирования интерпретирует его в файл атрибутов"^

120 IF n<0 OR n>255 OR n<>INT n THEN BEEP .2,24: GO TO 110

200 PRINT "Цвет символа - "; c$(1+n-8*INT(n/8))

210 PRINT "Цвет фона - "; C$(1+INT(n/8)-8*INT(n/64))

220 IF INT(n/64)=1 OR INT(n/64)=3 THEN PRINT "СИМВОЛ - BRIGHT"

230 IF n>127 THEN PRINT "Символ будет мерцать (FLASH)"

300 PRINT AT 6,0; "::::::::::::::::::::::::::::::::"

310 FOR i=22720 TO 22751

320 POKE i,n

330 NEXT i

500 INPUT "Для повторения - ENTER";z$

510 CLS

520 GO TO 110

Каждая ячейка в дисплейном файле определяет восемь пикселей на экране. При этом число, которое хранится в данной ячейке, преобразуется в двоичную форму и затем устанавливаются восемь пикселей, соответственно двоичным цифрам. Например, 240 после преобразования в двоичное число дает:

11110000

Следовательно, если ячейка содержит число 240, четыре из восьми пикселей, соответствующие единицам, будут высвечены, а оставшиеся нет. Следовательно, дисплейный файл состоит из 6144 ячеек памяти по 8 ячеек для одного знакоместа.

Каждая ячейка определяет горизонтальную полосу из восьми пикселей. Ячейки, относящиеся к данному знакоместу, не расположены последовательно одна за другой.

Атрибуты

Содержимое дисплейного файла определяет, какие пиксели высвечиваются на экране, цвет фона (PAPER), символа (INK), яркость (BRIGHT) и мерцание (FLASH) определяются с помощью атрибутов. Область атрибутов занимает ячейки 22528 - 23295 - по одной ячейке для каждого из 768 знакомест.

Соответствие между содержимым ячеек памяти файла атрибутов и самими атрибутами - следующее:

Значение атрибута = 128*FLASH + 64*BRIGHT + 8*PAPER + INK

FLASH и BRIGHT принимают значение 1, если соответствующее условие установлено, а PAPER и INK принимают значение требуемого цвета, как показано на клавиатуре (красный, например 2).

Программа P2.3. декодирует атрибуты, т.е. данное значение атрибута распечатывает с соответствующим цветом PAPER и INK.

Буфер принтера

256 ячеек ОЗУ, следующие за областью атрибутов, используются, как буфер для хранения строки символов, которая должна быть передана на принтер.

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

Единственно важное ограничение в этом случае - не использовать команды BASICa, которые требуют работы с принтером - LLIST, LPRINT, COPY.

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

Область программ на BASICe

Обычно эта область начинается с адреса 23755 и на нее указывает содержимое системной переменной PROG (23635,23636), но есть и исключения за счет некоторых видов периферийных устройств.

Если, например, к компьютеру подсоединен микродрайв, то начало этой области сдвигается, в этом самом общем случае начало области программ на BASICe и определяют с помощью системной переменной PROG. Ниже предполагается, что такая периферия не подсоединена.

Программа P2.4. распечатывает содержимое 18-ти ячеек в начале программной области, как показано на рис. 2.1. В этих 18 ячейках хранится первая строка данной программы.

10 REM Реек program

20 FOR i=23755 ТО 23772 30 PRINT i,PEEK i 40 NEXT i

Программа P2.4. Программа для просмотра содержимого первых 18-ти ячеек в программной области.

23755

0

23756

10

23757

14

23758

0

23759

234

23760

80

23761

101

23762

101

23763

107

23764

32

23765

112

23766

114

23767

111

23768

103

23769

114

23770

97

23771

109

23772

13

Рис.2.1. Форма, в которой строка 10 REM реек program хранится в программной

области.

Номер строки (10) хранится в первых двух ячейках в форме: Номер строки = 256*РЕЕК первый адрес + РЕЕК 2-й адрес.

Следующие 2 ячейки: 23757 и 23758 хранят длину оставшейся части строки, начинающейся в ячейке 23759. В нашем случае: 14+256*0=14 Т.о. следующая строка начинается с ячейки: 23759+14=23773

Ячейка 23759 хранит в себе число 234, которое является кодом ключевого слова (токена) REM. Следующие 12 ячеек хранят коды символов одиннадцати букв и пробела, составляющих фразу Peek program. Последняя ячейка хранит число 13, которое является кодом для ENTER, определяющим конец строки

Таблица 2.2. показывает метод кодирования программы в программной области.

Ячейки

Номер строки

1 и 2

Номер строки

3 и 4

Длина строки, исключая первые 4 ячейки

5

Код команды

Конец

Символ ENTER, число 13

Табл. 2.2. Этот метод используется для кодирования строк программы.

Момент, который опущен в таблице - это описание метода хранения числовых

значений, имеющих место в программе. Этот метод может быть исследован на примере строки:

10 LET а=1443

Введите ее в программу P2.4. На рис.2.2 показан результат работы программы в этом случае.

23755

0

23756

10

23757

14

23758

0

23759

241

23760

97

23761

61

23762

49

23763

52

23764

52

23765

51

23766

54

23767

0

23768

0

23769

163

23770

5

23771

0

23772

13

Рис. 2.2. Формат, в котором строка 10 LET a=1443 хранится в программной области.

Ячейки 23755-23758 такие же, как в прошлом примере. Затем следуют коды для LET, a, =, и четыре кода цифр, которые вместе формируют число 1443. Следующий элемент, находящийся в ячейке 23766, - это код 14. Этот код указывает, что следующие 5 ячеек хранят число в специальном пятибайтном формате. Линия заканчивается в ячейке 23772 вводом символа ENTER, как и ранее.

* * *

Примечание ИНФОРКОМа. Получается так, что в одной строке число как бы записано дважды. Первый раз своими символами, а второй раз - в пятибайтной форме после кода 14. Зачем это нужно?

Дело в том, что первое представление используется для того, чтобы БЕЙСИК-интерпретатор знал, что вам показать на экране, а второе - используется для расчетов во внутреннем калькуляторе компьютера. (О калькуляторе читайте в т. 1 и 2 нашего трехтомника).

Самое интересное, что они могут и не совпадать. В этом случае Вы на экране будете видеть одно, а программа будет обрабатывать совсем другое число, и этим нередко пользуются в защите программ. Например, Вы видите на экране LET а=1257: GO TO а и пытаетесь проследить работу программы, а на самом деле там было записано нечто совсем другое и компьютер делает переход не к строке 1257, а туда, куда надо.

Желающие могут посмотреть загрузчик программы BOMBJACK. В череде относительно несложных вывертов этот там стоит одним из первых. Но если на него

"клюнуть", атака на программу никак не получится.

* * *

Цифровой пятибайтный формат

Пять ячеек памяти используются для хранения чисел в программе на BASICe (исключая номера строк). Целые числа в диапазоне от -65535 до +65535 хранятся таким же образом, как в формате Z80A. Для этих чисел первые две ячейки и последняя содержат 0, а третья и четвертая хранят число в двухбайтной форме:

Число = РЕЕК 3-я ячейка + 256* РЕЕК четвертая ячейка

Таким образом 16533 хранится в пяти ячейках как

0 0 169 64 0

потому, что

169+256*64=16553

Дробные числа хранятся в формате с плавающей запятой таким образом: экспонента в первой ячейке, а мантисса в следующих четырех ячейках, т.е.:

число = мантисса * 2Лэкспонента

Первая ячейка мантиссы используется также для определения знака числа. Если ячейка содержит значение в пределах от 0 до 127, число положительное, если нет -отрицательное.

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

10 PRINT "Ввести экспоненту и четыре байта мантиссы. Все числа должны находиться между 0 и 255 включительно."

20 INPUT e,a,b,c,d

30 PRINT ,, " Exponent= ";e

40 PRINT "Mantissa= "; a,,b,,c,,d

50 PRINT ,,"The number= "; (2*(a<128)-1)*2~(e-160)* (((256*(a+128*(a<128))+b)*256+c)*256+d)

Программа P2.5. Эта программа восстанавливает дробное число.

Область переменных

Область переменных начинается в ячейке, адрес которой хранится в системной переменной VARS (ячейка 23627). Как бы ни была объявлена новая переменная, т.е. в программе или непосредственным вводом с клавиатуры, для нее резервируется соответствующее количество свободного пространства в этой области.

Все имена переменных начинаются с буквы. Различий между верхним и нижним регистром нет. Эти ограничения позволяют SPECTRUMy манипулировать с кодом первого символа каждой переменной и, таким образом, он может различить шесть типов переменных просмотром диапазона, в котором находится код.

Все цифровые переменные с односимвольными именами, например, имеют коды в пределах от 97 до 122; буква a - 97; b - 98; c - 99 и т.д. Подобным же образом цифровые массивы имеют коды в пределах 129 - 153, т.е. a - 129; b - 130; c - 131 и т.д. Диапазоны кодов представлены в таблице 2.3.

Длина каждого типа переменной также показана в таблице 2.3.

Тип переменной

Диапазон символьного кода

Длина в области переменных

Цифровой

97 - 122

6

(односимвольное имя)

Цифровой

161 - 186

5 + длина имени

(многосимвольное имя)

Цифровой массив

129 - 154

4 + 2 * размерность + 5 * общее

количество элементов.

Управляющая

225 - 250

18

переменная цикла FOR-

NEXT

Символьная строка

65 - 90

3 + длина строки

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

193 - 218

4 + 2 * размерность + общее число

элементов.

Таблица 2.3. Переменные. Диапазон кодов и длина переменных.

Подпрограммы ПЗУ

Некоторые из представленных в книге программ (раздел В) используют стандартные подпрограммы ПЗУ:

RST 16 - распечатывает содержимое аккумулятора.

CALL 3976 - вставляет символ, хранящийся в аккумуляторе, по адресу, хранящемуся в паре регистров HL.

CALL 6326 - если аккумулятор хранит код 14, устанавливается нулевой флаг и

увеличивается пара регистров HL в пять раз.

CALL 6510 - возврат в HL адреса в ОЗУ той строки, номер которой был передан в эту подпрограмму через HL.




СОДЕРЖАНИЕ:


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

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



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

Похожие статьи:
Винтостроение - Как самому собрать винт на PC.
Japan wild cross - Ото, коли тогда, шо тодi, то воно конечно же не тогда, а тодi...
Вступление - Вот и лето позади, опять на ноcу учеба, так по тиху cнова до cеccии доживем...
Игрушки - десятка наиболее продаваемых в С.-Петербурге.
ASM vs SNS - Просьба к издателям поместить это письмо во все спектрумистские газеты и во все эхи.

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