-c1E
+\/d
Г Л А В А X. УПРАВЛЕНИЕ РЕСУРСАМИ ПАМЯТИ MSX-КОМПЬЮТЕРОВ
-
-
+\/d-
Мозг, хорошо устроенный, стоит больше,
чем мозг, хорошо наполненный.
- Мишель Монтень
+ М.Монтень
X.1. К а р т а п а м я т и (д л я к о м п ь ю т е р о в MSX-1)
-
Персональный MSX-компьютер имеет небольшой объем памяти - 96 Кбайтов
для MSX-1 и 242 Кбайта для MSX-2. Поэтому полезной для пользователя оказы-
-вается информация о распределении ресурсов памяти и сведения о наличии и
+ваются информация о распределении ресурсов памяти и сведения о наличии и
объеме в ней свободных мест в любой момент времени.
Общий объем памяти у компьютеров серии MSX-1 равен 96 Кбайтам. Здесь и
далее мы будем рассматривать только 64 Кбайта, с которыми обычно и работа-
ет основная масса пользователей.
- Взгляните на приведенный ниже рис.1 ...
+ Взгляните на приведенный ниже рис.12 ...
Вся память разбита на две основные части:
┌─────────────────────────────────────────────────────────────────────┐
мы BIOS расположены по одним и тем же адресам ROM независимо от версии
MSX-BASIC и осуществляют переход к другим подпрограммам, положение кото-
рых может быть изменено.
- В противоположность ROM, RAM не сохраняет информацию при выключении
-компьютера. Поговорим теперь о его структуре.
+ В противоположность ROM RAM не сохраняет информацию при выключении ком-
+пьютера. Сейчас мы расскажем Вам о структуре RAM.
"Верхушка" памяти (она изображена в н и ж н е й части таблицы) за-
нята р а б о ч е й о б л а с т ь ю, которая состоит из:
α) таблицы системных переменных,
2) таблицей переменных ("Variable Table", VT). VT содержит все перемен-
ные, создаваемые в ходе выполнения программы;
3) таблицей массивов ("Array Variable Table").
- Между "верхней" и "нижней" областью памяти располагаются:
+ Между "верхней" и "нижней" областями памяти располагаются:
α) свободная область ("Free Area");
β) с т е к ("Stack Area"); стек содержит всю информацию, необходимую
для выполнения программы. Например, именно здесь хранится адрес тех бай-
он задает максимальное количество одновременно открытых файлов), то для
каждого файла автоматически резервируется 267-байтное пространство для
осуществления обмена информацией с файловыми устройствами.
-
&H0000 ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
∗▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧▧∗
∗▧▧▧▧▧▧▧▧▧ ROM (Интерпретатор MSX-BASIC) ▧▧▧▧▧▧▧∗
│ Таблица ловушек ("Hooks Table") │
&HFFFF │ │
─ ─ ─ ─ └────────────────────────────────────────────────┘
- Р и с. 1
+ Р и с. 12
Приведенная карта памяти справедлива и для компьютеров серии MSX-2. Но
в отличие от компьютеров серии MSX-1 с объемом ROM в 32 Кбайта и RAM в 64
Кбайта, компьютеры серии MSX-2 имеют гораздо больший объем памяти (108
-Кбайтов ROM и 134 Кбайта RAM). Спрашивается, где размещаются эта память?
+Кбайтов ROM и 134 Кбайта RAM). Спрашивается, где размещается эта память?
┌────────────────────────────────────────────────────┐
│ Оказывается, вся память ПЭВМ разбита на блоки │
│ объемом по 64 Кбайта, называемые с л о т а м и ! │
└────────────────────────────────────────────────────┘
Однако рассмотрение этого вопроса потребует от читателя дополнительных
-знаний, и поэтому мы рассмотрим его позднее (см. раздел XI.1.9.).
+знаний, и поэтому мы рассмотрим его позднее (см. Приложение 1.8.2).
Память разделена на ячейки (б а й т ы), каждая из которых имеет адрес,
закодированный д в у м я байтами:
-
А д р е с я ч е й к и (байта)
┌─────────────────┬─────────────────┐
│ 1 1 0 1 1 0 1 1 │ 1 0 1 1 1 1 0 1 │
└────────▲────────┴────────▲────────┘
└── Б а й т ы ──┘
-
Поэтому максимально большой адрес байта равен
256·&B11111111+&B11111111+1 = 256·&hFF+&HFF+1 = 65535+1 = 65536 ,
-а следовательно, и обратиться можно не более, чем к 65536 ячейкам памяти
+а следовательно, и обратиться можно не более чем к 65536 ячейкам памяти
(подумайте, почему производится умножение именно на 256?).
- Говорят, что "объем непосредственно адресуемой памяти - 65536 байта".
-
+ Говорят, что "объем непосредственно адресуемой памяти - 65536 байтов".
X.2. Ф у н к ц и я PEEK и о п е р а т о р POKE
тацию можно дать по контексту, однако, если должной уверенности нет, надо
а н а л и з и р о в а т ь не только содержимое одной ячейки, но и содер-
жимое ячеек, находящихся в ее "окрестности"!
-
П р и м е р 1. 10 X=&H8000'"Заглянем" в память,начиная с адреса &H8001!
───────────── 20 X=X+1:Y=PEEK(X)
30 IF Y<32 THEN ?"│";:GOTO 20 ELSE ?CHR$(Y);" ";:GOTO20
Наличие условия Y<32 в строке 26 связано с тем, что существуют "непеча-
таемые" символы, имеющие код ASCII, меньший 32.
+
+
Поговорим теперь об очень полезном операторе POKE.
Общий вид оператора: ┌───────────┐
│ POKE A,D │
ние на то, что значение А может оказаться о т р и ц а т е л ь н ы м!
Если значение А не удовлетворяет ограничениям, то компьютер сообщит об
ошибке: "Overflow" ("П е р е п о л н е н и е"),
-а если значение D, то "Illegal function call"
+а если значение D, - то "Illegal function call"
("Н е п р а в и л ь н ы й в ы з о в ф у н к ц и и").
Вы можете использовать оператор POKE для:
α) модификации текста Вашей программы;
Более того, этот оператор позволяет Вам экспериментировать с "подвалом"
компьютера (рабочей областью). Но делайте так только в том случае, если
Вы понимаете, что за этим последует!
-
П р и м е р 2. Сравните результаты работы двух программ:
───────────── 10 SCREEN 1:PRINT"A" 10 SCREEN 1:PRINT"A"
20 WIDTH 10 20 POKE &HF3B0,10
-
X.3. Т а б л и ц а п р о г р а м м н ы х к о м а н д (PIT)
Таблица PIT обычно начинается по адресу &H8000. Однако ее можно "сдви-
нуть", изменив значение системной переменной TXTTAB в таблице системных
переменных.
-
- П р и м е р 1. Для помещения PIT с адреса &HА000,достаточно выполнить
+ П р и м е р 1. Для помещения PIT с адреса &HА000 достаточно выполнить
───────────── следующую программу:
- NEW
- Ok
5 'Адрес &HА001,находящийся в двух ячейках с номерами,начиная с &hF676
(слове TXTTAB (&HF676)),определяет место,с которого начнется текст про-
граммы
40 NEW 'Стираем данную программу!
Напомним Вам, что адрес &HА001 (как и любой другой!) размещается в
двух байтах так:
-
Адрес ──▶ &HF676 &HF677 ◀── Адрес
младшего байта │ │ старшего байта
┌─────│─────────│────┐
байта │ └──────┘ └──────┘ │ байта
└────────────────────┘
Слово TXTTAB
-
Очевидно, что в результате этих "манипуляций" размер свободной области
уменьшится на &H2000 байтов (&HA000-&H8000=&H2000), и область, расположен-
ная между &H8000 и началом PIT, будет защищена от "вторжения" программ на
-MSX-BASIC, и следовательно, "б е з о п а с н а" для программ на машинном
+MSX-BASIC и, следовательно, "б е з о п а с н а" для программ на машинном
языке.
Ясно, что величина PIT зависит от размера текста программы.
После выполнения данной программы нажмите кнопку сброса "RESET".
│ нем коде (один или два байта на слово, цифру) │
│ Для остального текста используется код ASCII. │
└───────────────────────────────────────────────────────────────────────┘
-
П р и м е р 2. Введем в память следующую короткую программу:
───────────── 10 B=5
20 END
Попробуйте выполнить следующее:
POKE &H8005,&H41 '41 - шестнадцатеричный код ASCII буквы "A"
POKE &H8007,&H17 '17 ─ внутренний код цифры "6"
+
А теперь наберите команду LIST, затем нажмите клавишу◀─┘ и ...:
10 A=6
20 END
-
П р и м е р 3. Теперь Вам ясно,что "инструкции" PEEK и POKE таят в се-
───────────── бе поистине безграничные возможности. По существу, они
позволяют нам распоряжаться памятью компьютера по своему усмотрению.
80 9
Ok
Таким образом, указатель следующей (с номером 20) строки располагается
-в ячейках с адресами &H8009 и &H800A, а следовательно, номер второй стро-
+в ячейках с адресами &H8009 и &H800A, а, следовательно, номер второй стро-
ки находится в ячейках с адресами &H800B и &H800C .
Проверим этот факт:
PRINT HEX$(PEEK(&H800C));" ";HEX$(PEEK(&H800B)) ┌──▶ PRINT &H14
Ok
Программа действует, но строку с номером 1 нельзя ни стереть, ни испра-
вить. Вы можете написать еще одну 1-ю строку и даже новую 20-ю строку!
-
П р и м е р 4. Введем в память короткую программу:
───────────── 10 FOR AB=-2.23227 TO 7 STEP 32.671533782376#
Теперь "просмотрим" содержимое PIT, используя в непосредственном режи-
│ 8020 │ 0 │ Конец строки │
│ 8021 │ 0 │ Конец программы │
└───────────┴─────────────┴─────────────────────────────────────────────┘
-
Однако не пытайтесь изменять с помощью оператора POKE длину строки или
путать указатели: результат будет к а т a с т р о ф и ч е с к и м!
Если Вы хотите защитить свою программу от "постороннего взгляда" (ко-
Ну а если Вы нечаянно нажали RESET, - не спешите отчаиваться! Вашу про-
грамму еще можно спасти. Это очень легко сделать, набрав ту же команду
POKE &H8001,1
-а затем auto
+а затем auto .
На экране появятся строки: 10*
20* и так далее ...
Строки с "*" - спасенные. Теперь достаточно "скомандовать": LIST и ...,
переменных (см. Приложение 2). Ее длина зависит от количества используе-
мых переменных (скалярных и массивов) и их типов.
Отметим, что переменные и массивы хранятся в порядке их создания.
+
Будем говорить, что один программный объект "располагается в памяти
в ы ш е другого", если адрес, с которого он расположен, больше.
┌───────────────────────────────────────────┐
располагается значение переменной γ.
Если переменная не существует, то выдается сообщение:
"Illegal function call" .
-
П р и м е р. Будьте бдительны!
───────────
10 INPUT Z
X.4.1. Х р а н е н и е п р о с т ы х п е р е м е н н ы х
-
Ты славно роешь землю, старый крот!
Годишься в рудокопы.
- В.Шекспир. Гамлет
-
-
+ У.Шекспир. Гамлет
Как уже неоднократно упоминалось, ц е л о е число кодируется в двух
байтах. Меньший по адресу байт называется с т а р ш и м , больший по ад-
ресу байт - м л а д ш и м.
- Однако, напомним Вам, что
+ Однако напомним Вам, что
┌─────────────────────────────────────────────────────────┐
│ процессор Z80 "хранит" младший байт "перед" старшим │.
└─────────────────────────────────────────────────────────┘
4) младший байт значения;
5) старший байт значения.
+
+
┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐
│ 1-й байт │ │ 2-й байт │ │ 3-й байт │ │ 4-й байт │ │ 5-й байт │
└─────▲─────┘ └─────▲─────┘ └─────▲─────┘ └─────▲─────┘ └─────▲─────┘
│ Код ASCII Код ASCII Младший байт Старший байт
VALTYPE первого символа второго символа значения значения
имени переменной имени переменной
-
Оказывается, что адрес четвертого байта (младшего байта значения число-
вой переменной) возвращает как раз переменная VARPTR! Кроме того,напомним,
что "содержимое" байта с известным адресом может быть "прочитано"функцией
Перед тем как работать с нижеприведенным примером, во избежание расхож-
дений в результатах не забудьте "почистить" память компьютера оператором
CLEAR.
-
П р и м е р 1. A%=356:PRINT HEX$(VARPTR(A%))
───────────── 8006
Ok
│ │ Вы, конечно же, получите число 1. │
└───────────────┴────────────────────────────────────────────────────────┘
Перепишем два последних значения в двоичной системе счисления:
-
100 = 0110 0100 1=0000 0001
² ²
А теперь примем во внимание инверсию порядка байтов:
-
0000 0001 0110 0100 ──▶ 356
────▲──── ────▲──── 10
│ │
1 100
-
И перед выполнением следующего примера не забудьте ввести в память ком-
пьютера оператор CLEAR !
П р и м е р 2. A%=-356:PRINT HEX$(VARPTR(A%))
───────────── 8006
Ok
-
Полученный результат - это шестнадцатеричный адрес младшего байта.
┌───────────────┬────────────────────────────────────────────────────────┐
│ ? РЕЕК(&Н8003)│ Вы должны получить 2. │
└───────────────┴────────────────────────────────────────────────────────┘
Перепишем два последних значения в двоичной системе счисления:
-
156 = 1001 1100 254=1111 1110
² ²
Принимая во внимание инверсию порядка байтов, запишем их содержимое:
-
1111 1110 1001 1100
────▲──── ────▲────
│ │
254 156
-
А теперь учитывая, что двоичное число 1111111010011100 записано в до-
полнительном коде, получим ²
-
1111 1110 1001 1100 ──▶ 0000 0001 0110 0011 ──▶ 0000 0001 0110 0011+
² ²
+1 = 0000 0001 0110 0100 = 101100100 = 356. Ура!
² ²
Приведем схему расположения информации в памяти для простой числовой
переменной о д и н а р н о й и д в о й н о й точности:
-
Байт, адрес которого возвращает функция VARPTR()
│
┌───┬───┬───┬─▼─┬───┬───┬───┬───┐
│ │ Знак и порядок
│ Идентификатор
Тип переменной
-
Прежде чем проверить работу ниже приведенной командной строки,наберите
команду CLEAR.
-
П р и м е р 3. AR!=22.3210E+4:PRINT HEX$(VARPTR(AR!))
───────────── 8006
Ok
-
Если Вы прочитаете адреса с &H8006-&H3=&H8003 по &H8006+&H3=&H8009, то
обнаружите:
&H8003 4 VALTYPE п е р е м е н н о й о д и н а р н о й точ-
├──────────────────┼────────────────────┼──────────┤
│ 01 000000 │ 64 │ 0 │
│ 01 000001 │ 65 │ 1 │
- │ 01 000010 │ 66 │ 2 │
│ ··· │ ··· │ ··· │
──▶ 01 000110 │ 70 │ 6 ◀──
│ ··· │ ··· │ ··· │
- │ 01 111110 │ 126 │ 62 │
│ 01 111111 │ 127 │ 63 │
│ 00 111111 │ 63 │ - 1 │
│ 00 111110 │ 62 │ - 2 │
- │ 00 111101 │ 61 │ - 3 │
│ ··· │ ··· │ ··· │
- │ 00 000010 │ 2 │ -62 │
│ 00 000001 │ 1 │ -63 │
│ 00 000000 │ 0 │ -64 │
└────▲─────────────┴────────────────────┴──────────┘
└── Бит знака мантиссы
-
Величина порядка задается формулой:
┌───────────────────────────────────────────────────────┐
│ Порядок = Двоичное значение 7 младших битов - 64 │
└──────────────────────────────────────────────────────────────┘
Перед тем как выполнить предлагаемые в примере действия,наберите и вве-
дите в память компьютера оператор CLEAR.
-
П р и м е р 4. AR#=-22.321054981117E-4:PRINT HEX$(VARPTR(AR#))
───────────── 8006
Ok
&H8006 190 = &B 1011 1110
▲
└── Знак мантиссы отрицательный!
-
Подсчитаем теперь величину порядка:
-
print &B0111110-64
-2
Ok
-
"Продолжим наши игры!":
&H8007 34 = &B 0010 0010 = 22 в двоично-десятичной системе
&H8008 50 = &B 0011 0010 = 32 в двоично-десятичной системе
&H800B 152 = &B 1001 1000 = 98 в двоично-десятичной системе
&H800C 17 = &B 0001 0001 = 11 в двоично-десятичной системе
&H800D 23 = &B 0001 0111 = 17 в двоично-десятичной системе
-
В семи последних байтах "узнается" число 0.22321054981117.
┌─────────────────────────────────────────────────────────────────┐
│ Мантисса числа двойной точности занимает 7 байтов, которые │
│ позволяют закодировать 14 разрядов в двоично-десятичном виде │
└─────────────────────────────────────────────────────────────────┘
-
Подведем и т о г и всему сказанному о хранении числовых переменных.
┌─────────┬───────┬──────┬──────┬───────────────────────────────────────┐
│ Т и п │Значен.│Колич.│Номера│ Значение (система счисления) │
│ "Содержимое" этого ├──────┼───────────────────────────────────────┤
│ байта возвращает ───▶│ 0 │ Порядок и знак (знак в первом бите) │
│ функция VARPTR() │ │ (двоичная) │
-│ │ │ │ │ Величина порядка = двоичное значение │
+│ │ │ │ │ Величина порядка = двоичному значению │
│ │ │ │ │ семи последних битов - 64 │
│ │ │ ├──────┼───────────────────────────────────────┤
│ │ │ │ 1÷3 │ М а н т и с с а (двоично-десятичная) │
│ "Содержимое" этого ├──────┼───────────────────────────────────────┤
│ байта возвращает ───▶│ 0 │ Порядок и знак (знак в первом бите) │
│ функция VARPTR() │ │ (двоичная) │
-│ │ │ │ │ Величина порядка = двоичное значение │
+│ │ │ │ │ Величина порядка = двоичному значению │
│ │ │ │ │ семи последних битов - 64 │
│ │ │ ├──────┼───────────────────────────────────────┤
│ │ │ │ 1÷7 │ М а н т и с с а (двоично-десятичная) │
П р и м е р 5. Попробуйте самостоятельно в нем разобраться!
─────────────
- NEW
- Ok
10 INPUT"Введите число";A:PRINT"Попробуем 'собрать' его из памяти"
30 B=VARPTR(A):K$=RIGHT$("00000000"+BIN$(PEEK(B)),8)
50 IF MID$(K$,1,1)="1" THEN Z$="-." ELSE Z$="+."
X.4.2. Х р а н е н и е э л е м е н т о в ч и с л о в ы х
м а с с и в о в
-
Что имеем - не храним; потерявши - плачем.
Козьма Прутков
-
Вначале мы расскажем Вам о том, как хранится в памяти ц е л о ч и с-
л е н н ы й массив.
Приведем схемы расположения информации в памяти для целочисленных чис-
ловых массивов:
α) о д н о м е р н ы й массив.
-
Байт, адрес которого возвращает функция VARPTR()──┐
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─▼─┬───┬───┬───┬─
│ │ │ │ │ │ &H1 │ │ │███│███│███│███│···
│ Идентификатор Для одномерного │ элемента элемента
Тип массива массива Количество
элементов в массиве
-
β) д в у х м е р н ы й массив.
-
Байт, адрес которого возвращает функция VARPTR()──┐
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─▼─┬───┬─
│ │ │ │ │ │ &H2 │ │ │ │ │███│███│···
│ │ Служебная инф. │ Количество Количество элемента
│ Идентификатор Для двухмерного столбцов строк (0,0)
Тип массива массива
-
γ) для э л е м е н т о в целочисленных числовых массивов.
-
┌─── Байт, адрес которого возвращает функция VARPTR()
┌─▼─┬───┬───┬───┐
│███│███│···│███│
└───────▲───────┘
│
Значение
-
Не забыли ли Вы набрать и ввести в память компьютера оператор CLEAR?
-
П р и м е р 4. DIM C5%(2):C5%(0)=32000:C5%(1)=13:C5%(2)=-4
───────────── Ok
print HEX$(VARPTR(C5%(0))-8)
²
Теперь можно найти количество элементов в массиве:00000000 00000011 =3
²
+
? PEEK(&H800B) 0 = 00000000
? PEEK(&H800C) 125 = 01111101 ²
²
²
? PEEK(&H800D) 13 = 00001101
? PEEK(&H800E) 0 ²
-
Добрались до первого элемента массива: 00000000 00001101 = 13
²
? PEEK(&H800F) 252 = 11111100
²
Далее 11111111 11111100 ──▶00000000 00000011 +1 ──▶00000000 00000100 =4
² ² ²
+
+
Приведем схемы расположения информации в памяти для нецелочисленных
числовых массивов:
α) о д н о м е р н ы й массив.
-
Байт, адрес которого возвращает функция VARPTR() ──┐
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬──▼──┬───┬───┬───┬──
│ │ │ │ │ │ &H1 │ │ │ ∗∗∗ │███│···│███│···
Количество элементов в массиве
β) д в у х м е р н ы й массив.
-
Байт, адрес которого возвращает функция VARPTR() ──┐
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬──▼──┬─
│ │ │ │ │ │ &H2 │ │ │ │ │ ∗∗∗ │···
Тип массива массива Количество строк
γ) для э л е м е н т о в нецелочисленных числовых массивов.
-
┌─── Байт, адрес которого возвращает функция VARPTR()
┌─▼─┬───┬───┬───┬───┐
│∗∗∗│███│███│···│███│
▲ │
│ Значение
Знак и порядок
-
Думаем, что теперь Вы в состоянии самостоятельно разобраться с вопроса-
ми, касающимися "хранения" в RAM многомерных (двухмерных, трехмерных и
т.д.) вещественных числовых массивов!
- X.5. С т е к
+ X.5. С т е к
+
А люди все роптали и роптали,
А люди справедливости хотят:
- Мы в очереди первые стояли,
А те, кто сзади нас,- уже едят.
В.Высоцкий
-
-
С т е к (от англ. "stack" - "стог", "груда") - структура данных или
устройство памяти для хранения наращиваемой и сокращаемой последователь-
ности значений, в которой в любой момент доступен только последний член
Ok
Адрес значения AB% в VT
-
Адреса байтов │ ┌─ FF◀── для отрицательного шага
│ ┌────┬─────▼─────┬──▼─┬────┬─────┬─────┬─────┬─────┬─────┬─────┬───┬─
│ │&H82│ &H1B│ &H80│ &H1│&HFF│ ··· │ &HF │ &H0 │ &H7 │ &H0 │ &HA │&H0│
│ │ │
Мантисса верхнего предела │ Адрес конца программной строки
Номер строки оператора FOR
-
Не забудьте о команде CLEAR!
γ) 10 FOR AB!=2.7 TO 7 STEP-32.6715
─────▲───── ▲
│ └── "Вершина" стека
Адрес конца программной строки
-
Отметим, что для версии MSX-Disk BASIC с отключенным дисководом B при
нулевой длине строковой области максимальное число вложенных циклов равно
576.
А теперь настала очередь оператора GOSUB...
- Тем не менее, о команде CLEAR забывать не стоит!
-
+ Тем не менее о команде CLEAR забывать не стоит!
П р и м е р 2. 10 GOSUB 30:INPUT A
───────────── 20 'Просто комментарий!
30 'Еще один комментарий!
│ │ │ └─ Вершина стека
Код GOSUB │ Адрес следующего оператора
Номер текущей строки
-
-
- П р и м е р 3.
- ─────────────
- Работу этих двух программ Вы должны проверить на ученическом дисплее.
- α) Ok β) Ok
- 10 GOSUB 30:PRINT 1:END 10 GOSUB 30:PRINT 1:END
+ П р и м е р 3. Работу этих двух программ Вы должны проверить на учени-
+ ───────────── ческом компьютере.
+ α) 10 GOSUB 30:PRINT 1:END β) 10 GOSUB 30:PRINT 1:END
20 PRINT 2:END 20 PRINT 2:END
30 'POKE (&HF0A0-4),&H10 30 POKE (&HF0A0-4),&H10'Адрес перехода
40 RETURN 40 RETURN 'изменен с адреса &H800A на
1 2
Ok Ok
-
-
X.6. Х р а н е н и е с т р о к о в ы х в е л и ч и н
Функция VARPTR указывает адрес расположения строковых данных в опера-
3 позиции правее той, с которой располагается информация о переменной γ.
Пусть γ - простая строковая переменная. Изобразим "кусочек" памяти в
окрестности байта с адресом X:
-
┌── Байт, адрес которого возвращает функция
┌───┬───┬───┬─▼─┬───┬───┐ VARPTR(γ)
│▧▧▧│▧▧▧│▧▧▧│∗∗∗│▧▧▧│▧▧▧│
│ │ │ └─ Ссылка на адрес в PIT или на адрес
Тип переменной │ └── Байт длины в строковой области
Идентификатор
-
Напомним Вам, что в программировании с с ы л к а - содержимое ячейки
памяти, воспринимаемое как адрес некоторой другой ячейки.
Указатели строковых переменных хранятся в VT. Они занимают 6 байтов,
MSX
Ok
+
+
П р и м е р 2. 10 A$="ABCD"
───────────── run
Ok
²
1000 0000 0000 1001 = &H8009
²
- Итак, строка помещается в PIT по адресу &H8009.
- Все остальное очевидно!
+ Итак, строка помещается в PIT по адресу &H8009.Все остальное очевидно!
? PEEK(&H8009) ? PEEK(&H800A) ? PEEK(&H800B) ? PEEK(&H800C)
65 66 67 68 ◀── Код ASCII "D"
Ok Ok Ok Ok
-
П р и м е р 3. А теперь измените строку 10 и выполните программу.
───────────── 10 A$="ABCD"+""
run
PRINT PEEK(&H8017) ──▶ 4 Длина строки
PRINT PEEK(&H8018) ──▶ 101 = &H65 ──▶ Новый адрес (млaдший байт)
PRINT PEEK(&H8019) ──▶ 241 = &HF1 ──▶ Новый адрес (старший байт)
-
Операция, выполненная над строкой, явилась причиной пересылки ее по ад-
ресу &HF165 (без изменения). Вы можете убедиться в этом, используя "в ок-
рестности" этого адреса функцию PEEK.
65 66 67 68
Ok Ok Ok Ok
Забегая несколько вперед, отметим, что функция FRE("") возвратила бы
-число 200 в первом случае, однако, во втором случае возвращает число 196.
+число 200 в первом случае, однако во втором случае возвращает число 196.
Приведем схемы расположения информации в памяти для строковых массивов:
α) о д н о м е р н ы й строковый массив.
-
VARPTR(B$(0))───┐ ┌── VARPTR(B$(1))
┌───┬───┬───┬───┬───┬───┬───┬───┬─▼─┬───┬───┬─▼─┬───┬───┬───
│ │ │ │ │ │ 1 │ │ │∗∗∗│ │ │∗∗∗│ │ │∗∗∗
│ │ │ Адрес 0-го элемента
Размерность массива │ Длина значения 0-го элемента
Число элементов в массиве
-
П р и м е р 4. Обязательно разберите пример "с компьютером в руках"!
─────────────
10 DIM SM$(2):SM$(0)="рог"+"":SM$(1)="Inform"+"":SM$(2)="1989 г."+""
Адреса ──▶ X X+1 X+2
▲ ───▲───
Байт длины ──┘ └── Ссылка на адрес в строковой области
-
Продолжим наш пример:
PRINT HEX$(VARPTR(SM$(0)))
804F
г ◀─┘
Ok
- β) д в у х м е р н ы й строковый массив.
+
+
+
+ β) д в у х м е р н ы й строковый массив.
Значение, возвращаемое функцией VARPTR() ───┐
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬──▼──┐
│ │ │ │ │ │ &H2 │ │ │ │ │ ∗∗∗ │
Тип массива массива │ │
Количество столбцов Количество строк
-
-
X.7. О п е р а т о р CLEAR
-
Чтобы вычистить одно, приходится выпачкать
что-нибудь другое; но можно испачкать все,
что угодно, и ничего при этом не вычистить.
- Принцип Накопления Грязи по Питеру
-
+ Принцип накопления грязи по Питеру
Оператор CLEAR в общем виде записывается так:
- CLEAR [[n][,A]]
+ CLEAR [[n][,A]] ,
где: CLEAR ("очистить") - служебное слово;
n - арифметическое выражение, целая часть значения которого ука-
зывает количество байтов, резервируемых под строковое пространство; значе-
Вам данные.
Другими словами, значение А "переопределяет верхний предел пространст-
ва, используемого MSX-BASIC".
- Например, команда CLEAR 1000,&HF000 отводит 1000 байт для значений
+ Например, команда CLEAR 1000,&HF000 отводит 1000 байтов для значений
строковых констант в строковой области и RAM с адреса &HF000 для размеще-
ния машинной подпрограммы.
М а к с и м а л ь н ы м значением выражения A , конечно же, является
&HF69B. Этот адрес занимает 2 байта памяти;
VARTAB - имя слова, расположенного в рабочей области по адресу
&HF6C2. Этот адрес занимает 2 байта памяти.
-
П р и м е р 3. Нажмите кнопку "RESET" Вашего компьютера.
- ─────────────
- А теперь:
+ ───────────── А теперь:
print hex$(peek(&HF69C));" ";hex$(peek(&HF69B))
DC 5F ◀───── Вы узнали адрес FRETOP ?
Ok
print &HDC5F-&H8003-145-16
23483 ◀───── 0≤n≤23483
Ok
-
П р и м е р 4. 10 CLEAR200:T$=SPACE$(198):B$=STRING$(2,"#"):?B$:X$=
───────────── STRING$(1,"L"):?X$
run
run
## 0
Ok
-
X.8. Ф у н к ц и я FRE
-
Garbage collection ("чистка памяти","сборка мусора") - действия
системы динамического распределения памяти для обнаружения неис-
пользуемых программой блоков памяти и присоединения их к списку
свободной памяти для повторного использования.
Англо-русский словарь по программированию и информатике
-
-
Информацию о размере свободной области ("Free Area") в RAM можно полу-
чить с помощью функции FRE, обращение к которой имеет вид:
- FRE(A)
+ FRE(A) ,
где: FRE ("FREe"-"свободный") - служебное слово;
A - арифметическое или строковое выражение, причем для интерпретато-
ра важным является лишь тип выражения, а не его значение.
FRE(0) или FRE("") .
Функция FRE(0) возвращает количество байтов, оставленных для расшире-
ния PIT, VT, стека, строковой области и блока управления файлами.
-
П р и м е р 1.
─────────────
10 ? FRE(0):X=451:? FRE(0):Z#=7.5:? FRE(0)
20 Y!=555:? FRE(0):W%=111:? FRE(0)
run
28739
- 28728 ◀──т.к. переменная Х по умолчанию - двойной точности, а,следова-
+ 28728 ◀──т.к. переменная Х по умолчанию - двойной точности, а следова-
тельно, занимает в памяти 11 байтов;
28717 ◀──т.к. переменная Z - двойной точности (занимает в памяти так-
же 11 байтов);
байтов);
28705 ◀──т.к. переменная W - целого типа (занимает в памяти 5 байтов).
Ok
-
Функция FRE(0) выдает сообщение:
"Out of memory" ("Н е х в а т а е т п а м я т и")
при достижении значения, меньшего 145 байтов, минимально допустимого для
го типа, перед вычислением объема свободной памяти функция выполняет
"с б о р к у м у с о р а", т.е. удаление всех неиспользуемых данных и
освобождение занимаемых ими областей.
-
П р и м е р 2. Оказывается,что если у Вас в начале программы встречает-
- ───────────── ся оператор A$="ABCD"+"EF", а затем-оператор A$="X"+"Y",
+ ───────────── ся оператор A$="ABCD"+"EF", а затем оператор A$="X"+"Y",
то Вы сразу же создадите 6-байтовое пространство, заполненное "мусором"!
Покажем это:
print HEX$(PEEK(&HF69C)); HEX$(PEEK(&HF69B));
Ok
a$="X"+"Y"
Ok
+
+
+
for t=0 to 7:print chr$(peek(&hF168-t));:next
FEDCBAYX
└──▲─┘
YXXCBAYX
└──▲─┘
Ok └─── "м у с о р"
-
Из примера следует, что строки хранятся в строковом пространстве в том
порядке, в каком они были определены.
Таким образом, функция FRE("") изменила положение значения строковой
определено много символьных переменных, время "сборки мусора" может соста-
вить несколько минут. При выполнении этой операции компьютер полностью
"застывает". Посмотрите...
-
П р и м е р 3.
─────────────
10 CLEAR 5000 'Объявлен размер строковой области - 5000 байтов
Перед работой со следующим примером выключите, а затем снова включите
Ваш компьютер.
-
П р и м е р 5.
─────────────
A$="полет"
ли на значения строковых переменных. Обычный же оператор присваивания, ра-
зумеется, указатели изменяет! Покажем это на примере (не забудьте о коман-
де CLEAR !).
-
П р и м е р 6.
─────────────
a$="полет"
Ok
Как видим, значение указателя в последнем случае не изменилось!
γ) при необходимости используйте оператор SWAP A$,В$ , который не меня-
-ет расположение значений переменных, а лишь меняет местами указатели на
+ет расположения значений переменных, а лишь меняет местами указатели на
эти значения. Проиллюстрируем этот факт на примере...
+
П р и м е р 7.
─────────────
clear
for t=0 to len(a$)+len(b$):print chr$(peek(&hF168-t));:next
течаЗтамотвАА
Ok
+
+
И наконец, функция FRE() может помочь Вам также в з а щ и т е Вашей
программы. Например, в "укромном" месте программы, работающей со строко-
вой информацией, поместите оператор X$=SPACE$(FRE(""))- конечно,Вы должны
Ok
+
+
+
+
X.9. Р а б о ч а я о б л а с т ь
В рабочей области содержатся системные подпрограммы, системные перемен-
│ нимает 2 байта, расположенных с адреса &HFC4A . │
└─────────────────────────────────────────────────────────────────┘
Еще раз напомним Вам, что адреса, занимающие два байта, всегда записы-
-ваются так: вначале записывается содержимое младшего байта, а затем - со-
-держимое старшего байта!
+ваются так: вначале записывается содержимое младшего байта, а затем содер-
+жимое старшего байта!
Отметим, что значением выражения HEX$(PEEK(&HFC4A)+256*PEEK(&HFC4B))
является а д р е с н а ч а л а р а б о ч е й области.
Поскольку рабочая область расположена в RAM, ее переменные могут изме-
X.9.1. М а т р и ц а к л а в и а т у р ы
М а т р и ц е й клавиатуры для MSX-компьютеров назовем таблицу вида:
-
0-й 1-й 2-й 3-й 4-й 5-й 6-й 7-й
бит бит бит бит бит бит бит бит
┌──────┬─────┬─────┬─────┬─────┬─────┬─────┬──────┬──────┐
- │Адреса│ │ │ │ │ │ │ │ │
- │байтов│ 254 │ 253 │ 251 │ 247 │ 239 │ 223 │ 191 │ 127 │
+ │Адреса│ &hFE│ &hFD│ &hFB│ &hF7│ &hEF│ &hDF│ &hBF │ &h7F │
+ │байтов│(254)│(253)│(251)│(247)│(239)│(223)│ (191)│ (127)│
├──────┼─────┼─────┼─────┼─────┼─────┼─────┼──────┼──────┤
0-я строка │ FBE5 │ 9 │ ; │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │
├──────┼─────┼─────┼─────┼─────┼─────┼─────┼──────┼──────┤
├──────┼─────┼─────┼─────┼─────┼─────┼─────┼──────┼──────┤
10-я строка │ FBEF │ 5 │ 6 │ 7 │ 8 │ 9 │ - │ , │ . │
└──────┴─────┴─────┴─────┴─────┴─────┴─────┴──────┴──────┘
-
Последние две строки соответствуют цифровой (правой) зоне клавиатуры
учительского компьютера серии MSX-2.
Ответим теперь на Ваш очевидный вопрос:
┌───────────────────────────────────────┐
│ Как воспользоваться этой таблицей? │
└───────────────────────────────────────┘
-
П р и м е р 1. Ниже приведены программа, останавливаемая нажатием кла-
───────────── виши "GRAPH":
10 Z=PEEK(&HFBEB):IF Z<>251 THEN 10
60 PRINT"X=";8-INSTR(Z$,"0"):PRINT
80 NEXT:GOTO 10 '──▶
-
-
X.9.2. Д и н а м и ч е с к а я к л а в и а т у р а [46]
-
Промедление с легким делом превращает его в
трудное, промедление же с трудным делом пре-
вращает его в невозможное.
Д.Лоример
-
-
Исследуем один подход к разработке учебных программ, работающих под
управлением интерпретатора MSX-BASIC. Существенная особенность этого под-
хода состоит в том, что программа в процессе выполнения модифицируется
приведенной ниже программе - строка 10);
2) символьная строка дополняется впереди номером, а в конце - кодом ко-
манды "RETURN" (строки 15 и 1890): F$="номер строки 1"+F$+CHR$(13) ;
+
+
3) строка побайтно переписывается в БК, начиная с aдреса &HFBF0, при
помощи оператора POKE и функции PEEK (подпрограмма, начинающаяся со стро-
ки 1880);
Таким образом, указанный алгоритм решает задачу автоматической модифи-
кации программы в соответствии с текстом запроса, вводимого пользователем
с клавиатуры, и запуска ее с указанного номера строки.
-
П р и м е р.
───────────
1 GOTO 10
2450 W$=INKEY$:IF W$="" THEN 2450 ELSE GOTO 10
2460 RETURN'──▶
- X.10. П о р т ы в в о д а - в ы в о д а
-
- И я надеюсь, что наши потомки будут благодарны мне
- не только за то, что я здесь разъяснил, но и за то,
- что мною было добровольно опущено с целью предоста-
- вить им удовольствие самим найти это.
- Pене Декарт. Геометрия
+ X.10. П о р т ы в в о д а - в ы в о д а
+ И я надеюсь, что наши потомки будут благодарны
+ мне не только за то, что я здесь разъяснил, но
+ и за то, что мною было добровольно опущено с
+ целью предоставить им удовольствие самим найти
+ это.
+ P.Декарт. Геометрия
П о р т ввода-вывода - многоразрядный вход или выход компьютера,через
который процессор обменивается данными с внешними устройствами (клавиату-
1) порты с адресами &H00÷&H7F. Вы не можете и з м е н и т ь их содер-
жимоe (сравните с ROM!);
2) порты с адресами &H80÷&HFF. Их содержимое изменять можно (сравните
-с RAM!);
- 3) порты с адресами &H100÷&HFFFF зарезервированы(пока не используются).
+с RAM!).
Некоторые порты, их функции и адреса перечислены ниже:
┌────────────────┬───────────────┬─────────────────────────────────────┐
│ А д р е с │ Чтение(Запись)│ Н а з н а ч е н и е │
│────────────────┴───────────────┴─────────────────────────────────────┤
│ Порты, отвечающие за работу с локальной сетью КУВТ YAMAHA MSX-1 │
├────────────────┬───────────────┬─────────────────────────────────────┤
-│ &h00 │ Чтение(Запись)│ Посылаемые данные │
-│ &h01 │ Чтение │ Статус │
+│ &H00 │ Чтение(Запись)│ Посылаемые данные │
+│ &H01 │ Чтение │ Статус │
├────────────────┼───────────────┼─────────────────────────────────────┤
│ &H02 │ Чтение │ Номер компьютера в локальной сети │
│ │ │ (только для компьютеров MSX-1) │
│ &HA0 │ Запись │ Ввод в порт номера регистра │
│ &HA1 │ Запись │ Ввод в порт информации для установ- │
│ │ │ ленного регистра │
-│ &HA2 │ Чтение │ Последнее число, записанное в PSG │
+│ &HA2 │ Чтение │ Чтение числа из регистра PSG │
├────────────────┴───────────────┴─────────────────────────────────────┤
│ Программируемый п а р а л л е л ь н ы й и н т е р ф е й с (PPI) │
├────────────────┬───────────────┬─────────────────────────────────────┤
│ &HA9 │ Чтение(Запись)│ Запись (чтение) данных в порт B │
│ &HAA │ Чтение(Запись)│ Запись (чтение) данных в порт C │
│ &HAB │ Чтение(Запись)│ Запись (чтение) режимов PPI │
+├────────────────┼───────────────┼─────────────────────────────────────┤
+│ &HB0 │ │ Внешняя память (SONY) (через &HB3) │
├────────────────┴───────────────┴─────────────────────────────────────┤
-│ Порты, отвечающие за работу с д и с к о в о д о м │
+│ Порты, отвечающие за работу с т а й м е р о м │
├────────────────┬───────────────┬─────────────────────────────────────┤
-│ &HB4 │ Запись │ ? │
-│ &HB5 │ Чтение(Запись)│ ? │
+│ &HB4 │ Запись │ Номер столбца ОЗУ таймера │
+│ &HB5 │ Чтение(Запись)│ Чтение/запись данных в ОЗУ таймера │
+├────────────────┼───────────────┼─────────────────────────────────────┤
+│ &HB8 │ │ Световое перо (Sanyo) (через &HBB) │
├────────────────┼───────────────┼─────────────────────────────────────┤
+│ │ │ Управление Audio/Video │
+│ │ ├─────┬───────────────────────────────┤
+│ │ │Номер│ Назначение бита │
+│ │ │бита │ │
+│ &HF7 │ Запись ├─────┼───────────────────────────────┤
+│ │ │ 4 │ Управление AV (0 - TV) │
+│ │ │ 5 │ Управление Ym (0 - TV) │
+│ │ │ 6 │ Управление Ys (0 - Super) │
+│ │ │ 7 │ Выбор Video (0 - TV) │
+├────────────────┼───────────────┼─────┴───────────────────────────────┤
│ &HFC │ Чтение(Запись)│ Регистры распределения │
│ &HFD │ Чтение(Запись)│ с л о т о в │
│ &HFE │ Чтение(Запись)│ (расширений памяти) │
│ Для работы с портами ввода-вывода используются: │
│ функция INP и операторы OUT и WAIT │
└─────────────────────────────────────────────────────────┘
+
+
Формат оператора OUT:
┌──────────────────────────────────┐
│ OUT а д р е с, д а н н о е │,
го принадлежит отрезку [0,255].
Оператор OUT "посылает" заданное операндом д а н н о е значение в порт,
номер которого задан значением параметра а д р е с .
-В н и м а н и е !
- На компьютерах серии MSX-2 прежде, чем использовать оператор
- OUT, необходимо в непосредственном режиме выполнить команду
- CALL NETEND
- (отключить Ваш компьютер от локальной сети)
+В н и м а н и е ! На компьютерах серии MSX-2 прежде, чем использовать опе-
+ратор OUT, необходимо в непосредственном режиме выполнить команду
+ CALL NETEND (т.е. отключить Ваш компьютер от локальной сети).
Опишем синтаксис функции INP:
┌────────────────────────┐
│ INP (а д р е с) │,
1. │ Порт А используется для выбора с л о т о в, осуществляющих │
│ управление расширенной памятью компьютера. │
└───────────────────────────────────────────────────────────────┘
+ За подробностями мы отсылаем Вас к Приложению 1 (раздел 1.8.2).
┌───────────────────────────────────────────────────────────────┐
- │ Порты PPI B и C применяются для "работы" с матрицей клавиа- │
- │ туры, причем номер строки матрицы клавиатуры "посылается" в │
+ │ Порты B и C применяются для "работы" с матрицей клавиатуры, │
+ │ причем номер строки матрицы клавиатуры "посылается" в порт │
│ порт C, а номер столбца "читается" в порту B . │
└───────────────────────────────────────────────────────────────┘
П р и м е р 1. О б н а р у ж е н и е нажатия клавиши "GRAPH".
───────────── Отметим, что клавиша "GRAPH" находится в строке 6 и
-столбце 2 матрицы клавиатуры (и строки, и столбцы матрицы нумеруются, на-
+столбце 2 матрицы клавиатуры (и строки и столбцы матрицы нумеруются, на-
чиная с 0). Тогда:
1) номер строки матрицы клавиатуры "посылаем" в порт C :
OUT &HAA,6
Взгляните на приведенную ниже таблицу, в которой описаны назначения би-
тов порта C:
┌──────────┬──────────────────────────────────────────┐
- │ Биты 0÷3 │ Строка клавиатуры │
- │ Бит 4 │ Если 0, то запускается кассетная лента │
- │ Бит 5 │ Сигнал записи на ленту │
+ │ Биты 0÷3 │ Строка матрицы клавиатуры │
+ │ Бит 4 │ Если 0, то запускается магнитная лента │
+ │ Бит 5 │ Сигнал записи на магнитную ленту │
│ Бит 6 │ Если 0, то включается индикатор "CAPS" │
│ Бит 7 │ Управление звуковым сигналом │
└──────────┴──────────────────────────────────────────┘
&B00000110 OR (&B∗1∗∗∗∗∗∗ AND &B11110000) = &B∗1∗∗ 0110
(символом "∗" отмечены биты, состояние которых в данном случае роли не иг-
рает).
-
П р и м е р 2. Включение индикатора "CAPS" (если он выключен!) можно
───────────── осуществить следующей командой:
OUT &HAA, INP(&HAA) XOR &B01000000
│ │ ┌─ !!!
▼ ▼ ▼
&B∗1∗∗∗∗∗∗ XOR &B01000000 = &B∗0∗∗∗∗∗∗
-
П р и м е р 3.
─────────────
10 OUT &HAA,6 OR (INP(&HAA) AND &HF0):B=INP(&HA9)
40 IF (B AND 4)=0 THEN PRINT "Нажата клавиша GRAPH":GOTO 10 ELSE 10
В ходе работы программы индикатор "CAPS" сохранит состояние, в котором
он находился до пуска программы!
-
П р и м е р 4. Получим матрицу клавиатуры при помощи оператора OUT!
───────────── ┌────────────────────────────────────────────┐
│ 10 INPUT "Номер строки";N │
│ 50 IF B THEN PRINT "Клавиша нажата":END │
│ 60 GOTO 30 │
└────────────────────────────────────────────┘
-
П р и м е р 5. Включение и выключение кассетной ленты. Операторы MOTOR
───────────── ON и MOTOR OFF могут быть имитированы с помощью команды:
OUT &HAA, INP(&HAA) XOR &B00010000
+
X.10.2. П р о г р а м м и р у е м ы й з в у к о в о й
г е н е р а т о р (PSG)
Вначале приведем два примера записи информации в PSG при помощи портов
ввода-вывода.
-
П р и м е р 6.
─────────────
10 SOUND 7,8 'Шум из канала A 10 OUT &HA0,7:OUT &HA1,8: A=INP(&HA2)
run
8 15 26
Ok
-
П р и м е р 7. Представьте, что Вы находитесь на берегу Черного моря
───────────── в районе Ялты. Закройте глаза и ...
10 FOR I=0 TO 13:READ V
│ PLAY "O4B" │ 227 │ 0 │
│ PLAY "O5C" │ 214 │ 0 │
└─────────────┴───────────────────┴──────────────────┘
-
+ Вы можете проверить эту таблицу при помощи следующей программы:
+ 10 PLAY "O4C"
+ 20 OUT &hA0,0: PRINT INP(&hA2) 'Читаем данные
+ 30 OUT &hA0,1: PRINT INP(&hA2) 'из регистров PSG
+ А теперь слушайте ...
П р и м е р 8. Гамма "до-мажор".
─────────────
10 DATA 1,172,1,125,1,83,1,64,1,29,0,254,0,227,0,214
50 NEXT
60 OUT &HA0,8:OUT &HA1,0 'Сбросим громкость канала A
- П р и м е р 10. "В траве сидел кузнечик!"
- ──────────────
- 10 'DEFINTA-Z:BEEP
- 20 OUT &HA0,8:OUT&HA1,15:OUT &HA0,1:OUT &HA1,0:OUT &HA0,0:OUT &HA1,254
- 30 RESTORE 240:S=S+1:IF S=1 THEN K=14 ELSE K=12
- 40 FOR I=1 TO K:READ S1,S0,T1
- 50 OUT &HA0,8:OUT &HA1,15
- 60 OUT &HA0,1:OUT &HA1,S1:OUT &HA0,0:OUT &HA1,S0
- 70 TIME=0
- 80 T=TIME:IF T<T1 THEN 80
- 90 SOUND 8,0 'OUT &HA0,8:OUT &HA1,0:FOR J=1 TO 10:NEXT
- 100 NEXT
- 110 IF S=1 THEN 30
- 120 RESTORE 260:S=0
- 130 S=S+1:IF S=1 THEN K=20 ELSE K=14
- 140 FOR I=1 TO K:READ S1,S0,T1
- 150 OUT &HA0,8:OUT &HA1,15
- 160 OUT &HA0,1:OUT &HA1,S1:OUT &HA0,0:OUT &HA1,S0
- 170 TIME=0
- 180 T=TIME:IFT<T1 THEN 180
- 190 OUT &HA0,0:OUT &HA1,0:OUT &HA0,1:OUT &HA0,0:FOR J=1 TO 10:NEXT:NEXT
- 200 IF S=1 THEN RESTORE 270:GOTO 130
- 210 OUT &HA0,8:OUT &HA1,15
- 220 OUT &HA0,1:OUT &HA1,0:OUT &HA0,0:OUT &HA1,254
- 230 RUN
- 240 DATA 0,254,15,1,83,15,0,254,15,1,83,15,0,254,15,1,13,15,1,13,30
- 250 DATA 1,13,15,1,83,15,1,13,15,1,83,15,1,13,15,0,254,15,0,254,30
- 260 DATA 0,254,15,0,0,15,0,254,30
- 270 DATA 0,227,15,0,227,7.5,0,227,7.5,0,227,15,0,227,15
- 280 DATA 0,215,15,0,215,7.5,0,215,7.5,0,215,15,0,215,15
- 290 DATA 0,215,15,0,227,15,0,254,15,1,13,15,0,254,15,0,254,30
- 300 DATA 0,254,15
-
-
X.10.3. Д р у г и е п о р т ы. О п е р а т о р WAIT
Приведем примеры использования "содержимого" других портов.
-
П р и м е р 1. Использование портов с адресами &H90 и &H91 для вывода
───────────── символа на принтер.
Вначале о "роли" первого бита порта с номером &H90:
-
7-й бит 6-й бит 5-й бит 4-й бит 3-й бит 2-й бит 1-й бит 0-й бит
┌───────┬────────┬────────┬────────┬───────┬───────┬───────┬───────┐
│ ∗ │ ∗ │ ∗ │ ∗ │ ∗ │ ∗ │ │ ∗ │
└───────┴────────┴────────┴────────└───────┴───────┴───▲───┴───────┘
Принтер в режиме ON LINE (подключен к ПЭВМ): 0 ───────│
Принтер в режиме OFF LINE (отключен от ПЭВМ): 1 ───────┘
-
A теперь: включите принтер и вставьте бумагу...
5 CLEAR 300
10 INPUT"Слово";A$
40 B=ASC(MID$(A$,I,1))
50 OUT &H91,B
60 NEXT I
-
П р и м е р 2. Считывание кода выведенного на экран символа:
───────────── 10 K$=INKEY$:IF K$="" THEN 10 ELSE PRINT K$;
20 PRINT INP(&H98):GOTO 10
(при этом Вы вернетесь в командный режим).
Содержимое порта с указанным адресом заносится в некоторый регистр про-
цессора Z-80, который мы назовем X. Далее содержимое регистра X комбиниру-
-ется со значениями параметров M и С, по формуле:
+ется со значениями параметров M и С по формуле:
X = (X XOR C) AND M
Если после этого содержимое регистра X окажется равным 0, то происхо-
дит "выход из оператора WAIT". В противном случае порт вновь "опрашивает-
├─────────────────┼───────────────────────────────┤
│ (X XOR C) AND M │ 0 0 0 1 0 1 0 0 │
└─────────────────┴───────────────────────────────┘
-Вопрос к читателю: Какой вид будет иметь таблица-"подсказка" при отсутст-
-вии параметра C ?
-
+ Вопрос к читателю: Какой вид будет иметь таблица-"подсказка" при отсут-
+ствии параметра C ?
П р и м е р 3. 10 WAIT &HAA,64,255
─────────────
(&B∗1∗∗∗∗∗∗ XOR &B11111111) AND &B01000000 = &B00000000 = 0 !
Эта программа закончит свою работу, если загорится индикатор "CAPS".
-
П р и м е р 4.
─────────────
α) WAIT &H90,2,255 'Ожидается в к л ю ч е н и е принтера
β) WAIT &H90,2,0 'Ожидается о т к л ю ч е н и е принтера
- Д о п о л н е н и е. Работа с портом ввода-вывода с адресом &h0C
- ───────────────────
- Предварительно кратко опишем структуру порта &h0C...
+ X.11. Д о п о л н е н и е
+
+ Р а б о т а с п о р т о м в в о д а - в ы в о д а
+ с а д р е с о м &h0C
+ Предварительно кратко опишем структуру данного порта.
Старший ┌───┬───┬───┬───┬───┬───┬───┬───┐ Младший
бит │ ∗ │ ∗ │ ∗ │ ∗ │ ∗ │ ∗ │ ∗ │ ∗ │ бит
└─▲─┴─▲─┴─▲─┴─▲─┴─▲─┴─▲─┴─▲─┴─▲─┘
│ └── Бит направления поступления информации (1: от учителя)
└────── Бит направления поступления информации (1: от ученика)
- А теперь два примера использования данного порта...
-
+ А теперь два примера его использования.
+ В н и м а н и е ! Слабонервых просим не смотреть: примеры написаны на
+Макроассемблере M80!
П р и м е р 1. П о с ы л к а байта по сети
──────────────
OUT_BYTE:: ; На входе в регистре A - д а н н о е
EI ;
RET ;
+
+ К а р т а а д р е с о в п о р т о в в в о д а - в ы в о д а
+ д л я к о м п ь ю т е р о в MSX-1 [30]
+
+FF·┌──────────────────────────────┐ B4·┌──────────────────────────────┐
+ │ │ │ Внешняя память │
+F8·├──────────────────────────────┤ B0·├──────────────────────────────┤
+ │ Порты управления Audio/Video │ │ PPI (8255) │
+F7·├──────────────────────────────┤ A8·├──────────────────────────────┤
+ │ │ │ PSG (AY-3-8910) │
+F0·├──────────────────────────────┤ A0·├──────────────────────────────┤
+ │ │ │ VDP (9918A) │
+E0·├──────────────────────────────┤ 98·├──────────────────────────────┤
+ │ ROM для китайских иероглифов │ │ Принтер │
+D8·├──────────────────────────────┤ 90·├──────────────────────────────┤
+ │ Контроллер Floppy Disk │ │ │
+D0·├──────────────────────────────┤ 88·├──────────────────────────────┤
+ │ │ │ RS-232C │
+C0·├──────────────────────────────┤ 80·├──────────────────────────────┤
+ │ Световое перо │ │ Зарезервированы │
+B8·├──────────────────────────────┤ 40·├──────────────────────────────┤
+ │ │ │ Не определены │
+B5·├──────────────────────────────┤ 00·└──────────────────────────────┘
+ │ Календарь. Часы │
+B4·└──────────────────────────────┘
+
+