Глава 5. Операционная система Commodore-64 на языке ассемблера

Glava 5 Operacionnaa Sistema Commodore 64 Na Azyke Assemblera



5.1 Введение

Операционная система для компьютера Commodore-64 поставляется с компьютером в постоянном запоминающем устройстве (ПЗУ). Количество ячеек памяти для Commodore-64 варьируется от $0000 до $FFFF (т. е. от 000016 до FFFF16, что составляет от 010 до 65,53510). Операционная система стоит от $E000 до $FFFF (т. е. от 57,34410 до 65,53610).

Зачем изучать операционную систему Commodore-64
Зачем изучать операционную систему Commodore-64 сегодня, если это была операционная система компьютера, выпущенная в 1982 году? Итак, компьютер Commodore-64 использует центральный процессор 6510, который является модернизацией (хотя и не большой модернизацией) 6502 µP.







6502 µP до сих пор производится в больших количествах; это уже не домашние или офисные компьютеры, а электрические и электронные приборы (устройства). 6502 µP также прост в понимании и эксплуатации по сравнению с другими микропроцессорами того времени. В результате это один из лучших (если не лучший) микропроцессор, используемый для обучения ассемблеру.



65C02 µP, по-прежнему относящийся к классу микропроцессоров 6502, имеет 66 инструкций на языке ассемблера, каждую из которых можно даже выучить наизусть. Современные микропроцессоры имеют множество инструкций на языке ассемблера, и их невозможно выучить наизусть. Каждый микропроцессор имеет свой собственный язык ассемблера. Любая операционная система, новая или старая, написана на языке ассемблера. При этом язык ассемблера 6502 удобен для обучения работе с операционной системой новичков. Изучив операционную систему, например, Commodore-64, можно легко освоить современную операционную систему, взяв ее за основу.



Это не только мнение автора (моего). Это растущая тенденция в мире. В Интернете пишется все больше статей об улучшении операционной системы Commodore-64, чтобы она выглядела как современная операционная система. Современные операционные системы описаны в главе, следующей за следующей.





Примечание : ОС Commodore-64 (Kernal) до сих пор хорошо работает с современными устройствами ввода и вывода (не со всеми).

Восьмибитный компьютер
В восьмибитном микрокомпьютере, таком как Commodore 64, информация хранится, передается и обрабатывается в форме восьмибитных двоичных кодов.



Карта памяти
Карта памяти — это шкала, которая делит весь диапазон памяти на более мелкие диапазоны разного размера и показывает, что (подпрограмма и/или переменная) к какому диапазону принадлежит. Переменная — это метка, соответствующая определенному адресу памяти, имеющему значение. Метки также используются для обозначения начала подпрограмм. Но в данном случае они известны как имена подпрограмм. Подпрограмму можно просто назвать подпрограммой.

Карта памяти (раскладка) в предыдущей главе недостаточно подробная. Это довольно просто. Карта памяти компьютера Commodore-64 может быть отображена с тремя уровнями детализации. На промежуточном уровне компьютер Commodore-64 имеет разные карты памяти. Карта памяти по умолчанию компьютера Commodore-64 на промежуточном уровне:


Рис. 5.11 Карта памяти Commodore-64

В те времена существовал популярный компьютерный язык под названием BASIC. Многим пользователям компьютеров необходимо было знать некоторые минимальные команды языка BASIC, такие как загрузка программы с дискеты (диска) в память, запуск (выполнение) программы в памяти и выход (закрытие) программы. Когда программа BASIC запущена, пользователь должен вводить данные построчно. Это не то, что сегодня, когда приложение (несколько программ образуют приложение) написано на языке высокого уровня с окнами, и пользователю нужно просто вписать различные данные в специализированные места в окне. В некоторых случаях мы используем мышь для выбора предварительно заказанных данных. BASIC в то время был языком высокого уровня, но довольно близок к языку ассемблера.

Обратите внимание, что большая часть памяти занята BASIC в карте памяти по умолчанию. В BASIC есть команды (инструкции), которые выполняются так называемым интерпретатором BASIC. Фактически, интерпретатор BASIC находится в ПЗУ от адреса $A000 до $BFFF (включительно), который предположительно является областью ОЗУ. Это 8 Кбайт – это довольно много по тем временам! На самом деле он находится в ПЗУ в этом месте всей памяти. Имеет тот же размер, что и операционная система от $E000 до $FFFF (включительно). Программы, написанные на BASIC, также располагаются в диапазоне от $0200 до $BFFF.

Объем оперативной памяти для пользовательской программы на ассемблере составляет от $C000 до $CFFF, всего 4 Кбайт из 64 Кбайт. Итак, почему мы используем или изучаем язык ассемблера? Новые и старые операционные системы используют языки ассемблера. Операционная система Commodore-64 находится в ПЗУ от $E000 до $FFFF. Он написан на языке ассемблера 65C02 µP (6510 µP). Состоит из подпрограмм. Пользовательской программе на языке ассемблера необходимо вызывать эти подпрограммы для взаимодействия с периферийными устройствами (устройствами ввода и вывода). Понимание операционной системы Commodore-64 на языке ассемблера позволяет учащемуся быстро и менее утомительно разобраться в операционных системах. Опять же, в те времена многие пользовательские программы для Commodore-64 были написаны на Бейсике, а не на ассемблере. Языки ассемблера в те времена больше использовались самими программистами для технических целей.

Kernal, пишется как K-e-r-n-a-l, — это операционная система Commodore-64. Он поставляется с компьютером Commodore-64 в ПЗУ, а не на диске (или дискете). Кернал состоит из подпрограмм. Чтобы получить доступ к периферийным устройствам, пользовательская программа на ассемблере (машинном языке) должна использовать эти подпрограммы. Не следует путать ядро ​​с ядром, которое в современных операционных системах пишется как K-e-r-n-e-l, хотя это почти одно и то же.

Область памяти от $C000 (49,15210) до $CFFF (6324810) размером 4 Кбайт10 памяти представляет собой либо ОЗУ, либо ПЗУ. Когда это ОЗУ, оно используется для доступа к периферийным устройствам. Когда это ПЗУ, оно используется для печати символов на экране (мониторе). Это означает, что либо символы печатаются на экране, либо осуществляется доступ к периферийным устройствам с использованием этой части памяти. В системном блоке (материнской плате) имеется банк ПЗУ (символьное ПЗУ), который для этого включается и выключается из всего пространства памяти. Пользователь может не заметить переключение.

Область памяти от 0100$ (256 10 ) до $01FF (511 10 ) — это стек. Он используется как операционной системой, так и пользовательскими программами. Роль стека была объяснена в предыдущей главе этого онлайн-курса карьеры. Область памяти от $0000 (0 10 ) до $00FF (255 10 ) используется операционной системой. Там назначено множество указателей.

Таблица переходов ядра
В ядре есть процедуры, которые вызываются пользовательской программой. По мере выхода новых версий ОС адреса этих подпрограмм менялись. Это означает, что пользовательские программы больше не смогут работать с новыми версиями ОС. Этого не произошло, потому что Commodore-64 предоставил таблицу переходов. Таблица переходов представляет собой список из 39 записей. Каждая запись в таблице имеет три адреса (кроме последних 6 байт), которые никогда не менялись даже при смене версии операционной системы.

Первый адрес записи содержит инструкцию JSR. Следующие два адреса состоят из двухбайтового указателя. Этот двухбайтовый указатель представляет собой адрес (или новый адрес) реальной процедуры, которая все еще находится в ПЗУ ОС. Содержимое указателя может измениться в новых версиях ОС, но три адреса для каждой записи таблицы переходов никогда не меняются. Например, рассмотрим адреса $FF81, $FF82 и $FF83. Эти три адреса предназначены для процедуры инициализации схем (регистров) экрана и клавиатуры материнской платы. Адрес $FF81 всегда имеет код операции (один байт) JSR. Адреса $FF82 и $FF83 содержат старый или новый адрес подпрограммы (все еще находящейся в ПЗУ ОС) для выполнения инициализации. Одно время адреса $FF82 и $FF83 имели содержимое (адрес) $FF5B, которое могло измениться в следующей версии ОС. Однако адреса $FF81, $FF82 и $FF83 таблицы переходов никогда не изменяются.

Для каждой записи из трех адресов первый адрес с JSR имеет метку (имя). Метка $FF81 — PCINT. PCINT никогда не меняется. Итак, чтобы инициализировать регистры экрана и клавиатуры, программист может просто набрать «JSR PCINT», который работает для всех версий ОС Commodore-64. Местоположение (начальный адрес) фактической подпрограммы, например, $FF5B, может со временем меняться в разных операционных системах. Да, в пользовательской программе, использующей ROM OS, задействованы как минимум две инструкции JSR. В пользовательской программе есть инструкция JSR, которая осуществляет переход к записи в таблице переходов. За исключением последних шести адресов в таблице переходов, первый адрес записи в таблице переходов имеет инструкцию JSR. В ядре некоторые подпрограммы могут вызывать другие подпрограммы.

Таблица переходов ядра начинается с $FF81 (включительно) и идет вверх группами по три, за исключением последних шести байтов, которые представляют собой три указателя с адресами младших байтов: $FFFA, $FFFC и $FFFE. Все процедуры ПЗУ ОС представляют собой коды многократного использования. Таким образом, пользователю не придется их переписывать.

Блок-схема системного блока Commodore-64
Следующая диаграмма более подробная, чем диаграмма из предыдущей главы:


Рис. 5.12 Блок-схема системного блока Commodore_64

ПЗУ и ОЗУ здесь показаны как один блок. Здесь показан чип видеоинтерфейса (IC) для передачи информации на экран, который не был показан в предыдущей главе. Единый блок для устройств ввода/вывода, показанный в предыдущей главе, здесь показан в виде двух блоков: CIA #1 и CIA #2. ЦРУ означает «Адаптер сложного интерфейса». Каждый из них имеет два параллельных восьмибитных порта (не путать с внешними портами на вертикальной поверхности системного блока), называемых портом A и портом B. В этой ситуации CIA подключаются к пяти внешним устройствам. Устройствами являются клавиатура, джойстик, дисковод/принтер и модем. Принтер подключается с задней стороны дисковода. Также имеются схема устройства звукового интерфейса и схема программируемой логической матрицы, которые не показаны.

Тем не менее, существует ПЗУ символов, которое можно поменять местами с обоими CIA, когда персонаж отправляется на экран и не отображается на блок-схеме.

Адреса ОЗУ от $D000 до $DFFF для цепей ввода/вывода при отсутствии символьного ПЗУ имеют следующую подробную карту памяти:

Таблица 5.11
Подробная карта памяти от $D000 до $DFFF
Диапазон подадресов Схема Размер (байты)
Д000 – Д3ФФ VIC (контроллер видеоинтерфейса (чип))
Д400 – Д7ФФ SID (звуковая цепь)
Д800 – ДБФФ Цветная ОЗУ 1 тыс. закусок
ДК00 – ДКФФ ЦРУ №1 (клавиатура, джойстик) 256
ДД00 – ДДФФ ЦРУ № 2 (последовательная шина, пользовательский порт/RS-232) 256
DE00 – ДЕФ Открыть слот ввода-вывода №1 256
ДФ00 – ДФФФ Открыть слот ввода-вывода №2 256

5.2 Два сложных интерфейсных адаптера

В системном блоке Commodore-64 имеются две отдельные интегральные схемы (ИС), каждая из которых называется адаптером сложного интерфейса. Эти два чипа используются для сопряжения клавиатуры и других периферийных устройств с микропроцессором. За исключением VIC и экрана, все входные/выходные сигналы между микропроцессором и периферийными устройствами проходят через эти две микросхемы. В Commodore-64 нет прямой связи между памятью и каким-либо периферийным устройством. Связь между памятью и любым периферийным устройством осуществляется через аккумулятор микропроцессора, одним из которых являются адаптеры CIA (ИС). Микросхемы называются ЦРУ №1 и ЦРУ №2. ЦРУ означает «Адаптер сложного интерфейса».

Каждое ЦРУ имеет 16 регистров. За исключением регистров таймера/счетчика в CIA, каждый регистр имеет ширину 8 бит и имеет адрес в памяти. Адреса регистров памяти для CIA #1 взяты из $DC00 (56320 10 ) до $DC0F (56335 10 ). Адреса регистров памяти для CIA #2 взяты из $DD00 (56576 10 ) до $DD0F (56591 10 ). Хотя эти регистры не находятся в памяти микросхемы, они являются ее частью. В промежуточной карте памяти область ввода-вывода от $D000 до $DFFF включает адреса CIA от $DC00 до $DC0F и от $DD00 до $DD0F. Большую часть области памяти ввода-вывода ОЗУ от $D000 до $DFFF можно поменять местами с банком памяти символьного ПЗУ для экранных символов. Вот почему, когда символы отправляются на экран, периферийные устройства не могут работать; хотя пользователь может этого не заметить, поскольку переключение туда и обратно происходит быстро.

В CIA #1 есть два регистра, называемые портом A и портом B. Их адреса — $DC00 и $DC01 соответственно. В ЦРУ №2 также есть два регистра, называемые Порт А и Порт Б. Конечно, их адреса разные; это $DD00 и $DD01 соответственно.

Порт A или порт B в любом CIA является параллельным портом. Это означает, что он может отправлять данные на периферийное устройство в восьми битах одновременно или получать данные от микропроцессора в восьми битах одновременно.

С портом A или портом B связан регистр направления данных (DDR). Регистр направления данных для порта A CIA #1 (DDRA1) находится в ячейке байта памяти $DC02. Регистр направления данных для порта B CIA #1 (DDRB1) находится в ячейке байта памяти $DC03. Регистр направления данных для порта A CIA #2 (DDRA2) находится в ячейке байта памяти $DD02. Регистр направления данных для порта B CIA №2 (DDRB2) находится в ячейке байта памяти $DD03.

Теперь каждый бит порта A или порта B может быть установлен соответствующим регистром направления данных как входной или выходной. Ввод означает, что информация поступает от периферийного устройства к микропроцессору через ЦРУ. Выход означает, что информация поступает от микропроцессора к периферийному устройству через ЦРУ.

Если ячейка порта (регистра) должна быть введена, соответствующий бит в регистре направления данных равен 0. Если ячейка порта (регистра) должна быть выведена, соответствующий бит в регистре направления данных равен 1. В большинстве случаев все 8 бит порта запрограммированы как входные или выходные. Когда компьютер включен, порт A запрограммирован для вывода, а порт B — для ввода. Следующий код делает порт A CIA #1 выходным, а порт B CIA #1 входным:

LDA #$FF
СТА DDRA1 ; Режиссер $DC00 — $DC02.
LDA #$00
СТА DDRB1 ; $DC01, режиссер $DC03

DDRA1 — это метка (имя переменной) для местоположения байта памяти $DC02, а DDRB1 — это метка (имя переменной) для местоположения байта памяти $DC03. Первая инструкция загружает 11111111 в аккумулятор микропроцессора. Вторая инструкция копирует это в регистр направления данных порта A номера CIA. 1. Третья инструкция загружает 00000000 в аккумулятор микропроцессора. Четвертая инструкция копирует это в регистр направления данных порта B CIA №. 1. Этот код находится в одной из подпрограмм операционной системы, которая выполняет инициализацию при включении компьютера.

Каждое CIA имеет линию запроса обслуживания прерывания к микропроцессору. Тот, кто из ЦРУ №1, отправляется в прерывание вывод микропроцессора. Тот, что из ЦРУ №2, отправляется в НМИ вывод микропроцессора. Помните, что НМИ имеет более высокий приоритет, чем прерывание .

5.3 Программирование на языке ассемблера клавиатуры

Для Commodore-64 существует только три возможных прерывания: прерывание , БРК и НМИ . Указатель таблицы переходов для прерывание находится по адресам $FFFE и $FFFF в ПЗУ (операционной системе), что соответствует подпрограмме, все еще находящейся в ОС (ПЗУ). Указатель таблицы переходов для BRK находится по адресам $FFFC и $FFFD в ОС, что соответствует подпрограмме, все еще находящейся в ОС (ПЗУ). Указатель таблицы переходов для НМИ находится по адресам $FFFA и $FFFB в ОС, что соответствует подпрограмме, все еще находящейся в ОС (ПЗУ). Для прерывание , на самом деле есть две подпрограммы. Итак, программное прерывание (инструкция) BRK имеет собственный указатель таблицы переходов. Указатель таблицы переходов для прерывание приводит к коду, который решает, будет ли задействовано аппаратное прерывание или программное прерывание. Если это аппаратное прерывание, процедура для прерывание называется. Если это программное прерывание (BRK), вызывается процедура BRK. В одной из версий ОС подпрограмма для прерывание находится по адресу $EA31, а подпрограмма для BRK — по адресу $FE66. Эти адреса ниже $FF81, поэтому они не являются записями таблицы переходов и могут меняться в зависимости от версии ОС. В этой теме есть три подпрограммы, представляющие интерес: одна, которая проверяет, нажата ли это клавиша или BRK, та, которая находится в $FE43, и та, которая также может меняться в зависимости от версии ОС.

Компьютер Commodore-64 по внешнему виду похож на огромную пишущую машинку (вверх) без печатной секции (головки и бумаги). Клавиатура подключена к ЦРУ №1. ЦРУ №1 по умолчанию сканирует клавиатуру каждые 1/60 секунды самостоятельно, без какого-либо вмешательства программирования. Итак, каждую 1/60 секунды ЦРУ №1 отправляет прерывание в МКП. Здесь только один прерывание контакт на микропроцессоре, который поступает только от ЦРУ №1. Один входной контакт НМИ µP, который отличается от прерывание , поступает только от ЦРУ №2 (см. следующий рисунок). BRK на самом деле представляет собой инструкцию языка ассемблера, закодированную в пользовательской программе.

Итак, каждые 1/60 секунды прерывание Вызывается подпрограмма, на которую указывают $FFFE и $FFFF. Процедура проверяет, нажата ли клавиша или встречается инструкция BRK. Если клавиша нажата, вызывается процедура обработки нажатия клавиши. Если это инструкция BRK, вызывается процедура обработки BRK. Если ни то, ни другое, ничего не происходит. Ни того, ни другого не может быть, но ЦРУ №1 посылает прерывание к µP каждые 1/60 секунды.

Очередь клавиатуры, также известная как буфер клавиатуры, представляет собой диапазон местоположений байтов ОЗУ от $0277 до $0280 включительно; Всего 1010 байт. Это буфер «первым пришел — первым обслужен». Это означает, что персонаж, пришедший первым, уйдет первым. Западноевропейский символ занимает один байт.

Таким образом, хотя программа не потребляет никаких символов при нажатии клавиши, код клавиши попадает в этот буфер (очередь). Буфер продолжает заполняться до тех пор, пока в нем не останется десять символов. Любой символ, нажатый после десятого символа, не записывается. Он игнорируется до тех пор, пока хотя бы один символ не будет получен (израсходован) из очереди. В таблице переходов есть запись для подпрограммы, которая передает первый символ из очереди в микропроцессор. Это означает, что он берет первый символ, который попадает в очередь, и помещает его в аккумулятор µP. Подпрограмма таблицы переходов, предназначенная для этого, называется GETIN (Get-In). Первый байт трехбайтовой записи в таблице переходов помечен как GETIN (адрес $FFE4). Следующие два байта — это указатель (адрес), указывающий на реальную процедуру в ПЗУ (ОС). Ответственность за вызов этой процедуры лежит на программисте. В противном случае буфер клавиатуры останется заполненным и все недавно нажатые клавиши будут игнорироваться. Значение, которое поступает в аккумулятор, является соответствующим значением ключа ASCII.

Как коды ключей вообще попадают в очередь? Существует процедура таблицы переходов под названием SCNKEY (для ключа сканирования). Эту процедуру можно вызывать как программно, так и аппаратно. В этом случае он вызывается электронной (физической) схемой микропроцессора, когда электрический сигнал прерывание низкий. Как именно это делается, в этом онлайн-курсе карьеры не рассматривается.

Код для получения первого кода клавиши из буфера клавиатуры в аккумулятор A состоит всего из одной строки:

ЗАЛЕЗАЙ

Если буфер клавиатуры пуст, в аккумулятор помещается $00. Помните, что код ASCII для нуля — это не $00; это 30 долларов. $00 означает ноль. В программе может быть момент, когда программе придется ждать нажатия клавиши. Код для этого:

ПОДОЖДИТЕ, JSR ПОЛУЧИТСЯ
CMP #$00
ЛЯГУШКА ПОДОЖДИТЕ

В первой строке «WAIT» — это метка, идентифицирующая адрес ОЗУ, куда вставляется (вводится) инструкция JSR. GETIN также является адресом. Это адрес первого из соответствующих трех байтов в таблице переходов. Запись GETIN, как и все записи таблицы переходов (кроме трех последних), состоит из трех байтов. Первый байт записи — это инструкция JSR. Следующие два байта — это адрес тела фактической подпрограммы GETIN, которая все еще находится в ПЗУ (ОС), но ниже таблицы переходов. Итак, запись говорит о переходе к подпрограмме GETIN. Если очередь клавиатуры не пуста, GETIN помещает код клавиши ASCII очереди «первым пришел — первым обслужен» в аккумулятор. Если очередь пуста, в аккумулятор помещается значение Null ($00).

Вторая инструкция сравнивает значение аккумулятора с $00. Если это $00, это означает, что очередь клавиатуры пуста, и инструкция CMP отправляет 1 во флаг Z регистра состояния процессора (просто называемого регистром состояния). Если значение A не равно $00, инструкция CMP отправляет 0 во флаг Z регистра состояния.

Третья инструкция, «BEQ WAIT», отправляет программу обратно к первой инструкции, если флаг Z регистра состояния равен 1. Первая, вторая и третья инструкции выполняются повторно по порядку, пока не будет нажата клавиша на клавиатуре. . Если клавиша ни разу не нажата, цикл повторяется бесконечно. Подобный сегмент кода обычно записывается с сегментом временного кода, который выходит из цикла через некоторое время, если клавиша никогда не нажимается (см. следующее обсуждение).

Примечание : Клавиатура является устройством ввода по умолчанию, а экран — устройством вывода по умолчанию.

5.4 Канал, номер устройства и номер логического файла

Периферийные устройства, которые в этой главе используются для описания операционной системы Commodore-64, — это клавиатура, экран (монитор), дисковод с дискетой, принтер и модем, подключаемый через интерфейс RS-232C. Для осуществления связи между этими устройствами и системным блоком (микропроцессором и памятью) должен быть установлен канал.

Канал состоит из буфера, номера устройства, логического номера файла и, возможно, вторичного адреса. Объяснение этих терминов следующее:

Буфер
Обратите внимание из предыдущего раздела, что при нажатии клавиши ее код должен перейти в байтовую ячейку ОЗУ из серии из десяти последовательных ячеек. Эта серия из десяти мест представляет собой буфер клавиатуры. Каждое устройство ввода или вывода (периферийное) имеет в оперативной памяти ряд последовательных ячеек, называемых буфером.

Номер устройства
В Commodore-64 любому периферийному устройству присваивается номер устройства. В следующей таблице показаны различные устройства и их номера:

Таблица 5.41
Номера устройств Commodore 64 и их устройства
Число Устройство
0 Клавиатура
1 Ленточный накопитель
2 Интерфейс RS 232C, например. модем
3 Экран
4 Принтер №1
5 Принтер №2
6 Плоттер №1
7 Плоттер №2
8 Дисковод
9
¦
¦
¦
30
От 8 (включительно) до 22 дополнительных устройств хранения данных

Существует два типа портов для компьютера. Один тип – внешний, на вертикальной поверхности системного блока. Другой тип — внутренний. Этот внутренний порт является регистром. Commodore-64 имеет четыре внутренних порта: порт A и порт B для CIA 1 и порт A и порт B для CIA 2. У Commodore-64 есть один внешний порт, который называется последовательным портом. Устройства с цифрой 3 вверх подключаются к последовательному порту. Они подключаются последовательно (один сзади другого), каждый из которых идентифицируется по номеру устройства. Устройства с номером 8 вверх обычно являются устройствами хранения данных.

Примечание : Устройством ввода по умолчанию является клавиатура с номером устройства 0. Устройством вывода по умолчанию является экран с номером устройства 3.

Логический номер файла
Логический номер файла — это номер, присвоенный устройству (периферийному устройству) в том порядке, в котором они открываются для доступа. Они варьируются от 010 до 255. 10 .

Дополнительный адрес
Представьте, что на диске открыты два файла (или более одного файла). Чтобы различать эти два файла, используются вторичные адреса. Вторичные адреса — это числа, которые различаются от устройства к устройству. Значение 3 как вторичного адреса для принтера отличается от значения 3 как вторичного адреса для жесткого диска. Значение зависит от таких функций, как открытие файла для чтения или открытие файла для записи. Возможные дополнительные номера от 0 10 до 15 10 для каждого устройства. Для многих устройств номер 15 используется для отправки команд.

Примечание : Номер устройства также известен как адрес устройства, а дополнительный номер также известен как вторичный адрес.

Определение периферийной цели
Для карты памяти Commodore по умолчанию адреса памяти от $0200 до $02FF (стр. 2) используются исключительно операционной системой в ПЗУ (ядро), а не операционной системой и языком BASIC. Хотя BASIC все еще может использовать местоположения через ОС ROM.

Модем и принтер — это две разные периферийные цели. Если с диска открываются два файла, это две разные цели. При использовании карты памяти по умолчанию имеется три последовательные таблицы (списка), которые можно рассматривать как одну большую таблицу. Эти три таблицы содержат взаимосвязь между номерами логических файлов, номерами устройств и вторичными адресами. При этом становится идентифицируемым конкретный канал или цель ввода/вывода. Эти три таблицы называются таблицами файлов. Адреса ОЗУ и то, что они имеют:

$0259 — $0262: Таблица с меткой LAT, содержащая до десяти активных логических номеров файлов.
$0263–$026C: Таблица с меткой FAT, содержащая до десяти соответствующих номеров устройств.
$026D — $0276: Таблица с меткой SAT из десяти соответствующих вторичных адресов.

Здесь «—» означает «к», а число занимает один байт.

Читатель может спросить: «Почему при идентификации канала не учитывается буфер для каждого устройства?» Что ж, ответ в том, что в Commodore-64 каждое внешнее устройство (периферийное устройство) имеет фиксированную последовательность байтов в оперативной памяти (карте памяти). Без какого-либо открытого канала их позиции все еще находятся в памяти. Например, буфер для клавиатуры фиксирован от $0277 до $0280 (включительно) для карты памяти по умолчанию.

Функции ядра SETLFS и SETNAM
SETLFS и SETNAM — это процедуры ядра. Канал можно рассматривать как логический файл. Для открытия канала необходимо указать логический номер файла, номер устройства и дополнительный вторичный адрес. Также может потребоваться дополнительное имя файла (текст). Процедура SETLFS устанавливает логический номер файла, номер устройства и дополнительный вторичный адрес. Эти цифры помещены в соответствующие таблицы. Процедура SETNAM устанавливает для файла строковое имя, которое может быть обязательным для одного канала и необязательным для другого канала. Он состоит из указателя (двухбайтового адреса) в памяти. Указатель указывает на начало строки (имя), которая может находиться в другом месте памяти. Имя строки начинается с байта, имеющего длину строки, за которым следует текст (имя). Имя имеет максимальную длину шестнадцать байтов.

Чтобы вызвать процедуру SETLFS, пользовательская программа должна перейти (JSR) по адресу $FFBA таблицы переходов ОС в ПЗУ для карты памяти по умолчанию. Помните, что за исключением последних шести байтов таблицы переходов, каждая запись состоит из трех байтов. Первый байт — это инструкция JSR, которая затем переходит к подпрограмме и начинается с адреса в следующих двух байтах. Чтобы вызвать процедуру SETNAM, пользовательская программа должна перейти (JSR) по адресу $FFBD таблицы переходов ОС в ПЗУ. Использование этих двух процедур показано в следующем обсуждении.

5.5 Открытие канала, открытие логического файла, закрытие логического файла и закрытие всех каналов ввода-вывода

Канал состоит из буфера памяти, логического номера файла, номера устройства (адреса устройства) и дополнительного вторичного адреса (числа). Логический файл (абстракция), который идентифицируется логическим номером файла, может относиться к периферийному устройству, такому как принтер, модем, дисковод и т. д. Каждое из этих различных устройств должно иметь разные логические номера файлов. На диске много файлов. Логический файл также может ссылаться на определенный файл на диске. Этот конкретный файл также имеет логический номер файла, который отличается от номеров периферийных устройств, таких как принтер или модем. Логический номер файла задается программистом. Это может быть любое число от 010 ($00) до 25510 ($FF).

Процедура SETLFS ОС
Подпрограмма OS SETLFS, доступ к которой осуществляется путем перехода (JSR) к таблице переходов ПЗУ ОС в $FFBA, устанавливает канал. Ему необходимо поместить логический номер файла в таблицу файлов, то есть LAT ($0259 — $0262). Необходимо поместить соответствующий номер устройства в таблицу файлов FAT ($0263 — $026C). Если для доступа к файлу (устройству) требуется дополнительный номер, необходимо поместить соответствующий вторичный адрес (номер) в таблицу файлов, то есть SAT ($026D — $0276).

Для работы подпрограмме SETLFS необходимо получить логический номер файла из аккумулятора µP; ему необходимо получить номер устройства из регистра µP X. Если это необходимо каналу, ему необходимо получить вторичный адрес из регистра µP Y.

Логический номер файла определяется программистом. Логические номера файлов, относящиеся к разным устройствам, различны. Теперь, прежде чем вызывать процедуру SETLFS, программист должен поместить номер логического файла в аккумулятор µP. Номер устройства считывается из таблицы (документа), например, в Таблице 5.41. Программисту также необходимо будет поместить номер устройства в регистр µP X. Поставщик такого устройства, как принтер, дисковод и т. д., предоставляет возможные вторичные адреса и их значения для устройства. Если каналу необходим вторичный адрес, программисту необходимо получить его из документа, поставляемого с устройством (периферийным устройством). Если необходим вторичный адрес (номер), программист должен поместить его в регистр µP Y перед вызовом функции SETLFS. Если нет необходимости во вторичном адресе, программист должен поместить номер $FF в регистр µP Y перед вызовом функции SETLFS.

Функция SETLFS вызывается без каких-либо аргументов. Его аргументы уже находятся в трех регистрах 6502 мкП. После помещения соответствующих чисел в регистры подпрограмма вызывается в программе просто со следующей строкой:

JSR SETLFS

Процедура помещает разные числа в соответствующие таблицы файлов.

Процедура ОС SETNAM
Доступ к процедуре OS SETNAM осуществляется путем перехода (JSR) к таблице переходов ПЗУ ОС по адресу $FFBD. Не во всех местах назначения есть имена файлов. Для тех, у кого есть места назначения (например, файлы на диске), необходимо указать имя файла. Предположим, что имя файла — «mydocum», состоящее из 7 байт без кавычек. Предположим, что это имя находится в ячейках от $C101 до $C107 (включительно), а длина $07 — в ячейках $C100. Начальный адрес строковых символов — $C101. Младший байт начального адреса равен $01, а старший байт — $C1.

Перед вызовом процедуры SETNAM программист должен поместить число $07 (длина строки) в аккумулятор µP. Младший байт начального адреса строки $01 помещается в регистр µP X. Старший байт начального адреса строки $C1 помещается в регистр µP Y. Подпрограмма вызывается просто со следующей командой:

JSR СЕТНАМ

Процедура SETNAM связывает значения из трех регистров с каналом. После этого значения не обязательно должны оставаться в регистрах. Если каналу не требуется имя файла, программист должен поместить $00 в аккумулятор µP. В этом случае значения, находящиеся в регистрах X и Y, игнорируются.

Процедура открытия ОС
Доступ к подпрограмме OS OPEN осуществляется путем перехода (JSR) к таблице переходов ПЗУ ОС по адресу $FFC0. Эта процедура использует логический номер файла, номер устройства (и буфера), возможный вторичный адрес и возможное имя файла, чтобы обеспечить соединение между компьютером-коммодором и файлом во внешнем устройстве или самим внешним устройством.

Эта процедура, как и все другие процедуры ПЗУ ОС Commodore, не принимает аргументов. Хотя он использует регистры µP, ни в один из регистров не требуется предварительно загружать аргументы (значения). Чтобы закодировать его, просто введите следующее после вызова SETLFS и SETNAM:

JSR ОТКРЫТЫЙ

При выполнении процедуры OPEN могут возникнуть ошибки. Например, файл может не быть найден для чтения. При возникновении ошибки процедура завершается сбоем и помещает соответствующий номер ошибки в аккумулятор µP и устанавливает флаг переноса (в 1) регистра состояния µP. В следующей таблице представлены номера ошибок и их значения:

Таблица 5.51
Номера ошибок ядра и их значение для процедуры OS ROM OPEN
Номер ошибки Описание Пример
1 СЛИШКОМ МНОГО ФАЙЛОВ ОТКРЫТЬ, когда уже открыто десять файлов
2 ФАЙЛ ОТКРЫТ ОТКРЫТЬ 1,3: ОТКРЫТЬ 1,4
3 ФАЙЛ НЕ ОТКРЫТ ПЕЧАТЬ №5 без ОТКРЫТИЯ
4 ФАЙЛ НЕ НАЙДЕН НАГРУЗКА «НЕСУЩЕСТВУЮЩАЯ»,8
5 УСТРОЙСТВО НЕТ ОТКРЫТЬ 11,11: ПЕЧАТЬ №11
6 НЕ ВХОДНОЙ ФАЙЛ ОТКРЫТЬ «SEQ,S,W»: GET#8,X$
7 НЕ ВЫХОДНОЙ ФАЙЛ ОТКРЫТЬ 1,0: ПЕЧАТЬ №1
8 ОТСУТСТВУЕТ ИМЯ ФАЙЛА НАГРУЗКА «»,8
9 НЕЗАКОННЫЙ № УСТРОЙСТВА. ЗАГРУЗКА «ПРОГРАММА»,3

Эта таблица представлена ​​таким образом, что читатель, вероятно, увидит ее во многих других местах.

Процедура ОС CHKIN
Доступ к подпрограмме OS CHKIN осуществляется путем перехода (JSR) к таблице переходов ПЗУ ОС по адресу $FFC6. После открытия файла (логического файла) необходимо решить, предназначено ли открытие для ввода или вывода. Процедура CHKIN открывает входной канал. Эта процедура должна прочитать логический номер файла из регистра µP X. Таким образом, программист должен поместить логический номер файла в регистр X перед вызовом этой процедуры. Называется просто так:

ЖСР ЧКИН

Процедура ОС CHKOUT
Доступ к процедуре OS CHKOUT осуществляется путем перехода (JSR) к таблице переходов ПЗУ ОС по адресу $FFC9. После открытия файла (логического файла) необходимо решить, предназначено ли открытие для ввода или вывода. Процедура CHKOUT открывает выходной канал. Эта процедура должна прочитать логический номер файла из регистра µP X. Таким образом, программист должен поместить логический номер файла в регистр X перед вызовом этой процедуры. Называется просто так:

ДСР ЧКОУТ

Процедура ЗАКРЫТИЯ ОС
Доступ к процедуре OS CLOSE осуществляется путем перехода (JSR) к таблице переходов ПЗУ ОС по адресу $FFC3. После открытия логического файла и передачи байтов логический файл необходимо закрыть. Закрытие логического файла освобождает буфер в системном блоке для использования другим логическим файлом, который еще предстоит открыть. Соответствующие параметры в трех таблицах файлов также удаляются. Местоположение ОЗУ для количества открытых файлов уменьшается на 1.

При включении питания компьютера происходит аппаратный сброс микропроцессора и других основных микросхем (интегральных схем) на материнской плате. Далее следует инициализация некоторых ячеек оперативной памяти и некоторых регистров в некоторых микросхемах материнской платы. В процессе инициализации байтовая ячейка адреса $0098 на нулевой странице задается меткой NFILES или LDTND, в зависимости от версии операционной системы. Во время работы компьютера в этом однобайтовом ячейке из 8 бит хранится количество открытых логических файлов и индекс начального адреса таблиц последовательных трех файлов. Другими словами, этот байт содержит число открытых файлов, которое уменьшается на 1 при закрытии логического файла. Когда логический файл закрыт, доступ к конечному (целевому) устройству или реальному файлу на диске больше невозможен.

Чтобы закрыть логический файл, программист должен записать номер логического файла в аккумулятор µP. Это тот же логический номер файла, который используется при открытии файла. Это необходимо процедуре CLOSE, чтобы закрыть этот конкретный файл. Как и другие процедуры ПЗУ ОС, процедура CLOSE не принимает аргумент, хотя значение, используемое из аккумулятора, в некоторой степени является аргументом. Строка инструкций на ассемблере проста:

JSR ЗАКРЫТЬ

Пользовательские или предопределенные подпрограммы языка ассемблера 6502 (подпрограммы) не принимают аргументов. Однако аргументы приходят неформально путем помещения значений, которые будет использовать подпрограмма, в регистры микропроцессора.

Программа CLRCHN
Доступ к процедуре CLRCHN ОС осуществляется путем перехода (JSR) к таблице переходов ПЗУ ОС по адресу $FFCC. CLRCHN означает CLear ChanneL. Когда логический файл закрывается, его параметры: номер логического файла, номер устройства и возможный вторичный адрес удаляются. Итак, канал для логического файла очищается.

В инструкции написано, что процедура ОС CLRCHN очищает все открытые каналы и восстанавливает номера устройств по умолчанию и другие значения по умолчанию. Означает ли это, что номер устройства периферийного устройства можно изменить? Ну, не совсем. Во время инициализации операционной системы расположение байта адреса $0099 задается меткой DFLTI для хранения текущего номера устройства ввода во время работы компьютера. Commodore-64 может иметь доступ только к одному периферийному устройству одновременно. Во время инициализации операционной системы расположение байта адреса $009A задается меткой DFLTO для хранения текущего номера устройства вывода во время работы компьютера.

Когда вызывается подпрограмма CLRCHN, она устанавливает переменную DFLTI в значение 0 ($00), которое является номером устройства ввода (клавиатуры) по умолчанию. Он устанавливает для переменной DFLTO значение 3 ($03), которое является номером устройства вывода (экрана) по умолчанию. Другие переменные номера устройства сбрасываются аналогичным образом. В этом и заключается смысл сброса (или восстановления) устройств ввода/вывода в нормальное состояние (значения по умолчанию).

В руководстве Commodore-64 сказано, что после вызова процедуры CLRCHN открытые логические файлы остаются открытыми и все еще могут передавать байты (данные). Это означает, что процедура CLRCHN не удаляет соответствующие записи в таблицах файлов. Название CLRCHN довольно неоднозначно по своему смыслу.

5.6 Отправка персонажа на экран

Основная интегральная схема (ИС), обеспечивающая отображение символов и графики на экране, называется контроллером видеоинтерфейса (чипом), который в Commodore-64 обозначается аббревиатурой VIC (фактически VIC II для VIC версии 2). Чтобы информация (значения) попала на экран, она должна пройти через VIC II, прежде чем попасть на экран.

Экран состоит из 25 строк и 40 столбцов символьных ячеек. Это составляет 40 x 25 = 1000 символов, которые могут быть отображены на экране. VIC II считывает соответствующие 1000 последовательных байтов памяти RAM для символов. Эти 1000 мест вместе известны как экранная память. В эти 1000 мест входят коды символов. Коды символов Commodore-64 отличаются от кодов ASCII.

Код символа не является шаблоном символов. Существует также так называемое ПЗУ символов. ПЗУ символов состоит из всевозможных шаблонов символов, некоторые из которых соответствуют шаблонам символов на клавиатуре. Символьное ПЗУ отличается от экранной памяти. Когда символ должен быть отображен на экране, код символа отправляется в одну из 1000 позиций памяти экрана. Отсюда из ПЗУ символов выбирается соответствующий шаблон, который должен отображаться на экране. Выбор правильного шаблона в ПЗУ символов из кода символов осуществляется VIC II (аппаратно).

Многие ячейки памяти между $D000 и $DFFF имеют две цели: они используются для обработки операций ввода/вывода, отличных от экрана, или используются в качестве символьного ПЗУ для экрана. Речь идет о двух блоках памяти. Один из них — ОЗУ, а другой — ПЗУ символов. Замена банков для обработки либо ввода/вывода, либо шаблонов символов (ПЗУ символов) выполняется программным обеспечением (программа ОС в ПЗУ от $F000 до $FFFF).

Примечание : VIC имеет регистры, адресация которых осуществляется по адресам пространства памяти в диапазоне $D000 и $DFFF.

Процедура CHROUT
Доступ к процедуре OS CHROUT осуществляется путем перехода (JSR) к таблице переходов ПЗУ ОС по адресу $FFD2. Эта процедура при вызове принимает байт, который программист поместил в аккумулятор µP, и печатает на экране, где находится курсор. Например, сегмент кода для печати символа «E»:

LDA #$05
ЧРОУТ

0516 не является кодом ASCII для буквы «E». Commodore-64 имеет свои собственные коды символов для экрана, где $05 означает «E». Число #$05 помещается в память экрана до того, как VIC отправит его на экран. Эти две строки кода должны появиться после настройки канала, открытия логического файла и вызова процедуры CHKOUT для вывода. Полный код:

; Настройка канала
LDA #$40; логический номер файла
ЛДКС #$03 ; номер устройства для экрана — $03
ЛДИ #$FF ; нет вторичного адреса
JSR SETLFS ; настроить канал правильно
; нет SETNAM, поскольку экрану не нужно имя
;
; Открыть логический файл
JSR ОТКРЫТЫЙ
; Установить канал для вывода
ЛДКС #$40 ; логический номер файла
ДСР ЧКОУТ
;
; Вывод символа на экран
LDA #$05
JSR ЧРОУТ
; Закрыть логический файл
LDA № 40 долларов США
JSR ЗАКРЫТЬ

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

; Настройка канала
LDA #$40; логический номер файла
ЛДКС #$03 ; номер устройства для экрана — $03
ЛДИ #$FF ; нет вторичного адреса
JSR SETLFS ; настроить канал правильно
; нет SETNAM, поскольку экрану не нужно имя
;
; Открыть логический файл
JSR ОТКРЫТЫЙ
; Установить канал для вывода
ЛДКС #$40 ; логический номер файла
ДСР ЧКОУТ
;
; Ввод символов с клавиатуры
ПОДОЖДИТЕ JSR ПОЛУЧИТЬ; помещает $00 в A, если очередь клавиатуры пуста
CMP #$00 ; Если 00 долларов перешли в A, то Z при сравнении равен 1.
БЭК ОЖИДАНИЕ ; ПОЛУЧИТЬ из очереди снова, если 0 поступил в аккумулятор
БНЕ ПРНСКРН ; перейдите в PRNSCRN, если Z равен 0, потому что у A больше нет $00
; Вывод символа на экран
PRNSCRN JSR CHROUT ; отправить символ в A на экран
; Закрыть логический файл
LDA № 40 долларов США
JSR ЗАКРЫТЬ

Примечание : WAIT и PRNSCRN — это метки, идентифицирующие адреса. Байт с клавиатуры, поступающий в аккумулятор µP, представляет собой код ASCII. Соответствующий код, который Commodore-64 будет отправлять на экран, должен быть другим. В предыдущей программе это не учтено для простоты.

5.7 Отправка и получение байтов для диска

В системном блоке (материнской плате) Commodore-64 имеются два адаптера сложного интерфейса, которые называются VIA #1 и CIA #2. Каждый CIA имеет два параллельных порта, которые называются портом A и портом B. На вертикальной поверхности задней части системного блока Commodre-64 имеется внешний порт, который называется последовательным портом. Этот порт имеет 6 контактов, один из которых предназначен для данных. Данные поступают в системный блок или покидают его последовательно, по одному биту за раз.

Например, восемь параллельных битов из внутреннего порта А CIA #2 могут выйти из системного блока через внешний последовательный порт после преобразования в последовательные данные с помощью сдвигового регистра в CIA. Восьмибитные последовательные данные из внешнего последовательного порта могут поступать во внутренний порт A CIA №2 после преобразования в параллельные данные с помощью сдвигового регистра в CIA.

Системный блок Commodore-64 (базовый блок) использует внешний дисковод с дискетой. Принтер можно подключить к этому дисководу последовательно (подключая устройства последовательно в виде цепочки). Кабель передачи данных для дисковода подключается к внешнему последовательному порту системного блока Commodore-64. Это означает, что к тому же последовательному порту подключен шлейфовый принтер. Эти два устройства идентифицируются двумя разными номерами устройств (обычно 8 и 4 соответственно).

Отправка или получение данных на диск осуществляется той же процедурой, что описана ранее. То есть:

  • Установка имени логического файла (номера), которое совпадает с именем фактического файла на диске, с помощью процедуры SETNAM.
  • Открытие логического файла с помощью процедуры OPEN.
  • Решение о том, является ли это вводом или выводом, осуществляется с помощью подпрограммы CHKOUT или CHKIN.
  • Отправка или получение данных с использованием инструкций STA и/или LDA.
  • Закрытие логического файла с помощью процедуры CLOSE.

Логический файл должен быть закрыт. Закрытие логического файла фактически закрывает этот конкретный канал. При настройке канала для диска логический номер файла определяется программистом. Это число от $00 до $FF (включительно). Это не должен быть номер, который уже был выбран для какого-либо другого устройства (или фактического файла). Номер устройства равен 8, если имеется только один дисковод. Вторичный адрес (номер) можно получить из руководства к дисководу. Следующая программа использует 2. Программа записывает букву «E» (ASCII) в файл на диске с именем «mydoc.doc». Предполагается, что это имя начинается с адреса памяти $C101. Таким образом, перед вызовом процедуры SETNAM младший байт $01 должен находиться в регистре X, а старший байт $C1 — в регистре Y. Регистр A также должен иметь номер $09 перед вызовом процедуры SETNAM.

; Настройка канала
LDA #$40; логический номер файла
ЛДКС #$08 ; номер устройства для первого диска
ЛДИ #$02 ; дополнительный адрес
JSR SETLFS ; настроить канал правильно
;
; Файлу на диске нужно имя (уже в памяти)
LDA #$09
ЛДКС #$01
LDY#$C1
JSR СЕТНАМ
; Открыть логический файл
JSR ОТКРЫТЫЙ
; Установить канал для вывода
ЛДКС #$40 ; логический номер файла
JSR CHKOUT ;для записи
;
; Вывод символа на диск
LDA #$45
JSR ЧРОУТ
; Закрыть логический файл
LDA № 40 долларов США
JSR ЗАКРЫТЬ

Чтобы считать байт с диска в регистр µP Y, повторите предыдущую программу со следующими изменениями: Вместо «JSR CHKOUT ; для записи используйте «JSR CHKIN; для чтения'. Замените сегмент кода на «; Вывести символ на диск» со следующим:

; Ввод символа с диска
ДжСР КРИС

Доступ к подпрограмме OS CHRIN осуществляется путем перехода (JSR) к таблице переходов ПЗУ ОС по адресу $FFCF. Эта процедура при вызове получает байт из канала, который уже настроен как входной канал, и помещает его в регистр µP A. Вместо CHRIN также можно использовать процедуру ОС GETIN ROM.

Отправка байта на принтер
Отправка байта на принтер осуществляется аналогично отправке байта в файл на диске.

5.8 Процедура сохранения ОС

Доступ к процедуре OS SAVE осуществляется путем перехода (JSR) к таблице переходов ПЗУ ОС по адресу $FFD8. Процедура OS SAVE в ПЗУ сохраняет (сбрасывает) участок памяти на диск в виде файла (с именем). Начальный адрес раздела в памяти должен быть известен. Конечный адрес раздела также должен быть известен. Младший байт начального адреса помещается в нулевую страницу ОЗУ по адресу $002B. Старший байт начального адреса помещается в следующую ячейку памяти по адресу $002C. На нулевой странице метка TXTTAB относится к этим двум адресам, хотя на самом деле TXTTAB означает адрес $002B. Младший байт конечного адреса помещается в регистр µP X. Старший байт конечного адреса плюс 1 помещается в регистр µP Y. Регистр µP A принимает значение 2 млрд долларов США для TXTTAB (002 млрд долларов США). При этом процедуру SAVE можно вызвать следующим образом:

JSR СОХРАНИТЬ

Сохраняемый раздел памяти может представлять собой программу на языке ассемблера или документ. Примером документа может быть письмо или эссе. Чтобы использовать процедуру сохранения, необходимо выполнить следующую процедуру:

  • Настройте канал с помощью процедуры SETLFS.
  • Задайте имя логического файла (номер), которое совпадает с именем фактического файла на диске, с помощью процедуры SETNAM.
  • Откройте логический файл с помощью процедуры OPEN.
  • Создайте файл для вывода с помощью CHKOUT.
  • Здесь находится код для сохранения файла, который заканчивается на «JSR SAVE».
  • Закройте логический файл с помощью процедуры CLOSE.

Следующая программа сохраняет файл, который начинается с ячеек памяти от $C101 до $C200:

; Настройка канала
LDA #$40; логический номер файла
ЛДКС #$08 ; номер устройства для первого диска
ЛДИ #$02 ; дополнительный адрес
JSR SETLFS ; настроить канал правильно
;
; Имя файла на диске (уже в памяти по адресу $C301)
ЛДА #$09 ; длина имени файла
ЛДКС #$01
LDY#$C3
JSR СЕТНАМ
; Открыть логический файл
JSR ОТКРЫТЫЙ
; Установить канал для вывода
ЛДКС #$40 ; логический номер файла
JSR ЧКОУТ ; для записи
;
; Вывод файла на диск
LDA #$01
STA $2 млрд; ТХТТАБ
LDA #$C1
СТА $2C
ЛДКС #$00
ЛДИ #$C2
LDA # 2 миллиарда долларов
JSR СОХРАНИТЬ
; Закрыть логический файл
LDA № 40 долларов США
JSR ЗАКРЫТЬ

Обратите внимание, что это программа, сохраняющая на диск (дискету для Commodore-64) другой раздел памяти (не раздел программы).

5.9 Процедура загрузки ОС

Доступ к процедуре загрузки ОС осуществляется путем перехода (JSR) к таблице переходов ПЗУ ОС по адресу $FFD5. Когда раздел (большая область) памяти сохраняется на диск, он сохраняется с заголовком, имеющим начальный адрес раздела в памяти. Функция OS LOAD загружает байты файла в память. При выполнении этой операции ЗАГРУЗКИ значение аккумулятора должно быть 010 (00 долларов США). Чтобы операция ЗАГРУЗКИ прочитала начальный адрес в заголовке файла на диске и поместила байты файла в ОЗУ, начиная с этого адреса, вторичный адрес канала должен быть 1 или 2 (в следующей программе используется 2). Эта процедура возвращает адрес плюс 1 самой старшей загруженной ячейки ОЗУ. Это означает, что младший байт последнего адреса файла в ОЗУ плюс 1 помещается в регистр µP X, а старший байт последнего адреса файла в ОЗУ плюс 1 помещается в регистр µP Y.

Если загрузка не удалась, в регистре µP A сохраняется номер ошибки (возможно, 4, 5, 8 или 9). Также устанавливается флаг C регистра состояния микропроцессора (становится равным 1). Если загрузка прошла успешно, последнее значение регистра А не имеет значения.

Теперь, в предыдущей главе этого онлайн-курса карьеры, первая инструкция программы на языке ассемблера находится по адресу в оперативной памяти, где программа запускалась. Так не должно быть. Это означает, что первая инструкция программы не обязательно должна находиться в начале программы в оперативной памяти. Инструкция запуска программы может находиться в любом месте файла в оперативной памяти. Программисту рекомендуется пометить начало инструкции языка ассемблера с помощью START. При этом после загрузки программы она перезапускается (исполняется) со следующей инструкцией языка ассемблера:

JSR СТАРТ

«JSR START» находится в программе на языке ассемблера, которая загружает программу для запуска. Язык ассемблера, который загружает другой файл языка ассемблера и запускает загруженный файл, имеет следующую процедуру кода:

  • Установите канал с помощью процедуры SETLFS.
  • Задайте имя логического файла (номер), которое совпадает с именем фактического файла на диске, с помощью процедуры SETNAM.
  • Откройте логический файл с помощью процедуры OPEN.
  • Сделайте его файлом для ввода с помощью CHKIN.
  • Здесь идет код загрузки файла и заканчивается на «JSR LOAD».
  • Закройте логический файл с помощью процедуры CLOSE.

Следующая программа загружает файл с диска и запускает его:

; Настройка канала
LDA #$40; логический номер файла
ЛДКС #$08 ; номер устройства для первого диска
ЛДИ #$02 ; дополнительный адрес
JSR SETLFS ; настроить канал правильно
;
; Имя файла на диске (уже в памяти по адресу $C301)
ЛДА #$09 ; длина имени файла
ЛДКС #$01
LDY#$C3
JSR СЕТНАМ
; Открыть логический файл
JSR ОТКРЫТЫЙ
; Установить канал для входа
ЛДКС #$40 ; логический номер файла
ЖСР ЧКИН; для чтения
;
; Входной файл с диска
LDA #$00
JSR НАГРУЗКА
; Закрыть логический файл
LDA № 40 долларов США
JSR ЗАКРЫТЬ
; Запустить загруженную программу
JSR СТАРТ

5.10 Модем и стандарт RS-232

Модем — это устройство (периферийное), которое преобразует биты компьютера в соответствующие электрические аудиосигналы для передачи по телефонной линии. На принимающей стороне перед принимающим компьютером находится модем. Этот второй модем преобразует электрические аудиосигналы в биты для принимающего компьютера.

Модем необходимо подключить к компьютеру через внешний порт (на вертикальной поверхности компьютера). Стандарт RS-232 относится к определенному типу разъема, который соединяет модем с компьютером (в прошлом). Другими словами, многие компьютеры в прошлом имели внешний порт, который представлял собой разъем RS-232 или разъем, совместимый с RS-232.

Системный блок Commodore-64 (компьютер) имеет внешний порт на задней вертикальной поверхности, который называется пользовательским портом. Этот пользовательский порт совместим с RS-232. Туда можно подключить модемное устройство. Commodore-64 связывается с модемом через этот пользовательский порт. В операционной системе ПЗУ Commodore-64 есть подпрограммы для связи с модемом, называемые подпрограммами RS-232. Эти процедуры имеют записи в таблице переходов.

Скорость передачи данных
Восьмибитный байт компьютера преобразуется в серию из восьми бит перед отправкой на модем. Обратное делается от модема к компьютеру. Скорость передачи данных — это количество бит, передаваемых последовательно в секунду.

Нижняя часть памяти
Термин «нижняя часть памяти» не относится к местоположению байта памяти по адресу $0000. Это относится к самой нижней ячейке оперативной памяти, куда пользователь может начать помещать свои данные и программы. По умолчанию это 0800$. Вспомните из предыдущего обсуждения, что многие места между $0800 и $BFFF используются компьютерным языком BASIC и его программистами (пользователями). Только адреса от $C000 до $CFFF остаются для использования для программ и данных на языке ассемблера; это 4Кбайт из 64Кбайт памяти.

Верх памяти
В те времена, когда клиенты покупали компьютеры Commodore-64, в некоторых из них не было всех ячеек памяти. Такие компьютеры имели ПЗУ со своей операционной системой от $E000 до $FFFF. Оперативная память у них была от $0000 до предела, который не $DFFF, рядом с $E000. Предел был ниже $DFFF, и этот предел называется «Верх памяти». Таким образом, верхняя часть памяти не относится к местоположению $FFFF.

Буферы Commodore-64 для связи RS-232
Передающий буфер
Буфер для передачи RS-232 (выход) занимает 256 байт сверху вниз. Указатель на этот передающий буфер помечен как ROBUF. Этот указатель находится на нулевой странице с адресами $00F9, за которыми следует $00FA. ROBUF фактически идентифицирует $00F9. Таким образом, если адрес начала буфера — $BE00, младший байт $BE00, то есть $00, находится в ячейке $00F9, а старший байт $BE00, то есть $BE, находится в ячейке $00FA. расположение.

Приемный буфер
Буфер для приема байтов RS-232 (вход) занимает 256 байт снизу передающего буфера. Указатель на этот приемный буфер помечен как RIBUF. Этот указатель находится на нулевой странице с адресами $00F7, за которыми следует $00F8. RIBUF фактически идентифицирует $00F7. Таким образом, если адрес начала буфера — $BF00, младший байт $BF00, то есть $00, находится в ячейке $00F7, а старший байт $BF00, то есть $BF, находится в ячейке $00F8. расположение. Таким образом, 512 байт из верхней части памяти используются в качестве общего буфера ОЗУ RS-232.

Канал RS-232
Когда модем подключен к (внешнему) пользовательскому порту, связь с модемом осуществляется по протоколу RS-232. Процедура создания полного канала RS-232 почти такая же, как и в предыдущем обсуждении, но с одним важным отличием: имя файла представляет собой код, а не строку в памяти. Код $0610 — хороший выбор. Это означает скорость передачи данных 300 бит/сек и некоторые другие технические параметры. Кроме того, нет вторичного адреса. Обратите внимание, что номер устройства — 2. Процедура настройки полного канала RS-232:

  • Настройка канала с помощью процедуры SETLFS.
  • Установка имени логического файла, $0610.
  • Открытие логического файла с помощью процедуры OPEN.
  • Создание файла для вывода с помощью CHKOUT или файла для ввода с помощью CHKIN.
  • Отправка отдельных байтов с помощью CHROUT или получение отдельных байтов с помощью GETIN.
  • Закрытие логического файла с помощью процедуры CLOSE.

Доступ к процедуре OS GETIN осуществляется путем перехода (JSR) к таблице переходов ПЗУ ОС по адресу $FFE4. Эта процедура при вызове принимает байт, отправленный в буфер приемника, и помещает (возвращает) его в аккумулятор µP.

Следующая программа отправляет байт «E» (ASCII) модему, который подключен к пользовательскому порту, совместимому с RS-232:

; Настройка канала
LDA #$40; логический номер файла
ЛДКС #$02 ; номер устройства для RS-232
ЛДИ #$FF ; нет вторичного адреса
JSR SETLFS ; настроить канал правильно
;
; Имя для RS-232 представляет собой код, например. $0610
ЛДА #$02 ; длина кода 2 байта
ЛДКС #$10
ЛДИ #$06
JSR СЕТНАМ
;
; Открыть логический файл
JSR ОТКРЫТЫЙ
; Установить канал для вывода
ЛДКС #$40 ; логический номер файла
ДСР ЧКОУТ
;
; Вывод символа в RS-232, например. модем
LDA #$45
JSR ЧРОУТ
; Закрыть логический файл
LDA № 40 долларов США
JSR ЗАКРЫТЬ

Для получения байта код очень похож, за исключением того, что «JSR CHKOUT» заменяется на «JSR CHKIN» и:

LDA #$45
JSR ЧРОУТ

заменяется на «JSR GETIN», а результат помещается в регистр A.

Непрерывная отправка или получение байтов осуществляется с помощью цикла отправки или получения сегмента кода соответственно.

Обратите внимание, что ввод и вывод с помощью Commodore в большинстве случаев аналогичен, за исключением клавиатуры, где некоторые процедуры не вызываются программистом, а вызываются операционной системой.

5.11 Подсчет и расчет времени

Рассмотрим последовательность обратного отсчета:

2, 1, 0

Это обратный отсчет от 2 до 0. Теперь рассмотрим повторяющуюся последовательность обратного отсчета:

2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0

Это повторяющийся отсчет одной и той же последовательности. Последовательность повторяется четыре раза. Четыре раза означают, что время равно 4. Отсчет ведется в пределах одной последовательности. Повторение одной и той же последовательности — это время.

В системном блоке Commodore-64 имеется два адаптера сложного интерфейса. Каждое CIA имеет две схемы счетчика/таймера, называемые Таймер A (TA) и Таймер B (TB). Схема счета не отличается от схемы синхронизации. Счетчик или таймер в Commodore-64 означает одно и то же. Фактически, любой из них по сути относится к одному 16-битному регистру, который всегда ведет обратный отсчет до 0 в тактовых импульсах системы. В 16-битный регистр можно установить различные значения. Чем больше значение, тем больше времени требуется для обратного отсчета до нуля. Каждый раз, когда один из таймеров достигает нуля, прерывание Сигнал прерывания подается на микропроцессор. Когда счет падает за ноль, это называется недостатком.

В зависимости от того, как запрограммирована схема таймера, таймер может работать в однократном или непрерывном режиме. На предыдущем рисунке одноразовый режим означает «сделать 2, 1, 0» и остановиться, пока тактовые импульсы продолжаются. Непрерывный режим выглядит следующим образом: «2, 1, 0, 2, 1, 0, 2, 1, 0, 2, 1, 0 и т. д.». который продолжается тактовыми импульсами. Это означает, что когда он превышает ноль и не дано никаких инструкций, последовательность обратного отсчета повторяется. Самое большое число обычно намного больше 2.

Таймер А (ТА) ЦРУ №1 генерирует прерывание через регулярные промежутки времени (продолжительность) для обслуживания клавиатуры. Фактически, по умолчанию это происходит каждые 1/60 секунды. прерывание отправляется в микропроцессор каждые 1/60 секунды. Это только тогда, когда прерывание отправляется сообщение о том, что программа может прочитать значение ключа из очереди клавиатуры (буфера). Помните, что микропроцессор имеет только один вывод для прерывание сигнал. Микропроцессор также имеет только один вывод для НМИ сигнал. Сигнал ¯NMI на микропроцессор всегда поступает от ЦРУ №2.

16-битный регистр таймера имеет два адреса памяти: один для младшего байта и один для старшего байта. Каждое ЦРУ имеет две схемы таймера. Оба ЦРУ идентичны. Для CIA №1 адреса двух таймеров: DC04 и DC05 для TA и DC06 и DC07 для TB. Для CIA №2 адреса двух таймеров: DD04 и DD05 для TA и DD06 и DD07 для TB.

Предположим, что число 25510 должно быть отправлено на таймер ТА ЦРУ №2 для обратного отсчета. 25510 = 00000000111111112 состоит из шестнадцати бит. 00000000111111112 = $000FFF находится в шестнадцатеричном формате. В этом случае $FF отправляется в регистр по адресу $DD04, а $00 отправляется в регистр по адресу $DD05 — небольшой порядок байтов. Следующий сегмент кода отправляет номер в регистр:

LDA #$FF
СОСТОЯНИЕ $DD04
LDA #$00
СОСТОЯНИЕ $DD05

Хотя регистры в CIA имеют адреса ОЗУ, физически они находятся в CIA, а CIA представляет собой отдельную микросхему из ОЗУ или ПЗУ.

Это еще не все! Если таймеру присвоено число для обратного отсчета, как, например, в предыдущем коде, обратный отсчет не начинается. Обратный отсчет начинается, когда восьмибитный байт отправляется в соответствующий регистр управления таймера. Первый бит этого байта регистра управления указывает, следует ли начинать обратный отсчет. Значение 0 для этого первого бита означает прекращение обратного счета, а значение 1 означает начало обратного счета. Кроме того, байт должен указывать, ведется ли обратный отсчет в однократном (однократном) режиме или в автономном режиме (непрерывном режиме). В одноразовом режиме обратный отсчет прекращается, когда значение регистра таймера становится равным нулю. В свободном режиме обратный отсчет повторяется после достижения 0. Четвертый (индекс 3) бит байта, отправляемого в регистр управления, указывает режим: 0 означает автономный режим, а 1 означает одноразовый режим.

Подходящее число для начала подсчета в режиме одного выстрела — 000010012 = $09 в шестнадцатеричном формате. Подходящим числом для начала счета в автономном режиме является 000000012 = $01 в шестнадцатеричном формате. Каждый регистр таймера имеет свой собственный регистр управления. В CIA №1 регистр управления таймера A имеет адрес ОЗУ DC0E16, а регистр управления таймера B имеет адрес ОЗУ DC0F16. В CIA №2 регистр управления таймера A имеет адрес ОЗУ DD0E16, а регистр управления таймера B имеет адрес ОЗУ DD0F16. Чтобы начать отсчет шестнадцатибитного числа в ТА ЦРУ №2 в одноразовом режиме, используйте следующий код:

LDA #$09
СТА $DD0E

Чтобы начать отсчет шестнадцатибитного числа в ТА ЦРУ №2 в свободном режиме, используйте следующий код:

LDA #$01
СТА $DD0E

5.12. прерывание и НМИ Запросы

Микропроцессор 6502 имеет прерывание и НМИ линии (булавки). И ЦРУ №1, и ЦРУ №2 имеют прерывание контакт для микропроцессора. прерывание контакт CIA #2 подключен к НМИ вывод микропроцессора. прерывание контакт CIA #1 подключен к прерывание вывод микропроцессора. Это единственные две линии прерываний, которые соединяют микропроцессор. Итак прерывание значок ЦРУ №2 — это НМИ источник и также может рассматриваться как линия ¯NMI.

У ЦРУ №1 есть пять возможных непосредственных источников генерации информации. прерывание сигнал для µP. ЦРУ №2 по структуре такое же, как ЦРУ №1. Итак, ЦРУ №2 на этот раз имеет те же пять возможных непосредственных источников генерации сигнала прерывания, которыми является НМИ сигнал. Помните, что когда µP получает НМИ сигнал, если он обрабатывает прерывание запрос, он приостанавливает его и обрабатывает НМИ запрос. Когда он завершит обработку НМИ запроса, затем он возобновляет обработку прерывание запрос.

CIA #1 обычно подключается снаружи к клавиатуре и игровому устройству, например джойстику. Клавиатура использует больше порта A CIA №1, чем порт B. Игровое устройство использует больше порта B CIA №1, чем порта A. CIA №2 обычно подключается к дисководу снаружи (последовательное подключение к принтеру). и модем. Дисковод использует больше порта A CIA №2 (хотя и через внешний последовательный порт), чем порт B. Модем (RS-232) использует больше порта B CIA №2, чем порт A.

При всем этом, откуда системному блоку знать, что вызывает прерывание или НМИ прерывать? У ЦРУ №1 и ЦРУ №2 есть пять непосредственных источников прерывания. Если сигнал прерывания на микропроцессоре НМИ , источник - один из пяти ближайших источников ЦРУ №2. Если сигнал прерывания на микропроцессоре прерывание , источник - один из пяти ближайших источников ЦРУ №1.

Следующий вопрос: «Как системное подразделение различает пять непосредственных источников каждого ЦРУ?» Каждый CIA имеет восьмибитный регистр, который называется регистром управления прерываниями (ICR). СКР обслуживает оба порта ЦРУ. В следующей таблице показаны значения восьми бит регистра управления прерываниями, начиная с бита 0:

Таблица 5.13
Регистр управления прерываниями
Битовый индекс Значение
0 Устанавливается (сделано 1) по истечении таймера A
1 Устанавливается при переполнении таймера B
2 Установите, когда часы времени суток равны будильнику
3 Устанавливается, когда последовательный порт заполнен
4 Устанавливается внешним устройством
5 Не используется (сделано 0)
6 Не используется (сделано 0)
7 Устанавливается, когда установлен любой из первых пяти битов.

Как видно из таблицы, каждый из непосредственных источников представлен одним из первых пяти битов. Таким образом, когда сигнал прерывания поступает на микропроцессор, необходимо выполнить код для чтения содержимого регистра управления прерываниями, чтобы узнать точный источник прерывания. Адрес ОЗУ для ICR ЦРУ №1 — DC0D16. Адрес оперативной памяти ICR ЦРУ №2 — DD0D16. Чтобы прочитать (вернуть) содержимое ICR ЦРУ №1 в аккумулятор µP, введите следующую команду:

LDA $DC0D

Чтобы прочитать (вернуть) содержимое ICR ЦРУ №2 в аккумулятор µP, введите следующую команду:

ЛДА $DD0D

5.13 Фоновая программа, управляемая прерываниями

Клавиатура обычно прерывает работу микропроцессора каждые 1/60 секунды. Представьте, что программа запущена и достигает состояния ожидания нажатия клавиши с клавиатуры, прежде чем она сможет продолжить работу с приведенными ниже сегментами кода. Предположим, что если на клавиатуре не нажата ни одна клавиша, программа выполняет лишь небольшой цикл в ожидании клавиши. Представьте, что программа запущена и ожидает нажатия клавиши сразу после выдачи прерывания клавиатуры. В этот момент весь компьютер косвенно останавливается и ничего не делает, кроме цикла ожидания. Представьте, что клавиша клавиатуры нажата непосредственно перед следующим вызовом следующего прерывания клавиатуры. Это означает, что компьютер ничего не делал примерно одну шестидесятую секунды! Это очень долго, чтобы компьютер ничего не делал, даже во времена Commodore-64. В это время (длительность) компьютер мог делать что-то еще. Таких длительностей в программе много.

Вторую программу можно написать так, чтобы она работала в такие периоды простоя. Говорят, что такая программа работает на фоне основной (или первой) программы. Самый простой способ сделать это — просто принудительно включить модифицированную обработку прерываний BRK, когда ожидается нажатие клавиши на клавиатуре.

Указатель инструкции BRK
В последовательных ячейках ОЗУ адресов $0316 и $0317 находится указатель (вектор) для фактической процедуры инструкции BRK. Указатель по умолчанию помещается туда, когда компьютер включается, операционная система находится в ПЗУ. Этот указатель по умолчанию представляет собой адрес, который по-прежнему указывает на обработчик инструкций BRK по умолчанию в ПЗУ ОС. Указатель представляет собой 16-битный адрес. Младший байт указателя помещается в байтовую ячейку адреса $0306, а старший байт указателя помещается в байтовую ячейку $0317.

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

Эту проблему легко решить: каждый раз, когда компьютеру приходится ждать нажатия клавиши с клавиатуры, вставьте в код инструкцию BRK и замените указатель $0316 (и $0317) на указатель следующей подпрограммы второй ( пользовательская) программа. Таким образом, обе программы будут работать ненамного дольше, чем основная программа, работающая отдельно.

5.14 Сборка и компиляция

Ассемблер заменяет все метки адресами. Программа на языке ассемблера обычно пишется так, чтобы запускаться по определенному адресу. Результат работы ассемблера (после сборки) называется «объектным кодом», где всё в двоичном виде. Результатом является исполняемый файл, если файл является программой, а не документом. Документ не является исполняемым.

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

Компилятор необходим вместо ассемблера, когда имеется более одной программы переднего плана. Компилятор собирает каждую программу в объектный код. Однако возникнет проблема: некоторые сегменты кода будут перекрываться, поскольку программы, вероятно, написаны разными людьми. Решение компилятора состоит в том, чтобы сместить все перекрывающиеся программы, кроме первой, в область памяти, чтобы программы не перекрывались. Теперь, когда дело доходит до хранения переменных, адреса некоторых переменных все равно будут перекрываться. Решение здесь — заменить перекрывающиеся адреса новыми адресами (кроме первой программы), чтобы они больше не пересекались. Таким образом, разные программы будут помещаться в разные части (области) памяти.

При этом одна подпрограмма в одной программе может вызывать подпрограмму в другой программе. Итак, компилятор выполняет связывание. Связывание означает наличие начального адреса подпрограммы в одной программе и последующий вызов ее в другой программе; оба из которых являются частью приложения. Для этого обе программы должны использовать один и тот же адрес. Конечным результатом является один большой объектный код, все в двоичном формате (битах).

5.15 Сохранение, загрузка и запуск программы

Язык ассемблера обычно пишется в какой-либо программе-редакторе (которая может поставляться вместе с программой ассемблера). Программа-редактор указывает, где программа начинается и заканчивается в памяти (ОЗУ). Процедура Kernal SAVE ПЗУ ОС Commodore-64 может сохранить программу из памяти на диск. Он просто сбрасывает на диск раздел (блок) памяти, который может содержать вызов его инструкции. Целесообразно иметь вызывающую инструкцию SAVE отдельно от сохраняемой программы, чтобы при загрузке программы в память с диска она не сохраняла себя снова при запуске. Загрузка программы на языке ассемблера с диска представляет собой задачу другого рода, поскольку программа не может загрузить сама себя.

Программа не может загрузиться с диска туда, где она начинается и заканчивается в оперативной памяти. Commodore-64 в те времена обычно поставлялся с интерпретатором BASIC для запуска программ на языке BASIC. Когда машина (компьютер) включается, появляется командная строка: ГОТОВО. Отсюда можно вводить команды или инструкции BASIC, нажав клавишу «Enter» после ввода. Базовая команда (инструкция) для загрузки файла:

ЗАГРУЗИТЬ «имя файла», 8,1

Команда начинается с зарезервированного слова BASIC — ЗАГРУЗИТЬ. За ним следует пробел, а затем имя файла в двойных кавычках. Далее следует номер устройства 8, которому предшествует запятая. Далее следует вторичный адрес диска, равный 1, и ему предшествует запятая. В таком файле стартовый адрес программы на языке ассемблера находится в заголовке файла на диске. Когда BASIC завершает загрузку программы, возвращается последний адрес ОЗУ плюс 1 адрес программы. Слово «возвращенный» здесь означает, что младший байт последнего адреса плюс 1 помещается в регистр µP X, а старший байт последнего адреса плюс 1 помещается в регистр µP Y.

После загрузки программы ее необходимо запустить (выполнить). Пользователь программы должен знать начальный адрес выполнения в памяти. Опять же, здесь необходима еще одна программа BASIC. Это команда SYS. После выполнения команды SYS программа на ассемблере запустится (и остановится). Если во время работы требуется какой-либо ввод с клавиатуры, программа на языке ассемблера должна указать это пользователю. После того, как пользователь вводит данные на клавиатуре и нажимает клавишу «Ввод», программа на языке ассемблера продолжит работу с использованием ввода с клавиатуры без вмешательства интерпретатора BASIC.

Предполагая, что адрес начала выполнения (рабочей) оперативной памяти для программы на языке ассемблера равен C12316, C123 преобразуется в десятичное число перед использованием его с командой SYS. Преобразование C12316 в десятичную систему выглядит следующим образом:

Итак, команда BASIC SYS:

СИС 49443

5.16 Загрузка Commodore-64

Загрузка Commodore-64 состоит из двух этапов: этапа аппаратного сброса и этапа инициализации операционной системы. Операционная система — это ядро ​​в ПЗУ (а не на диске). Есть строка сброса (на самом деле ВИЭ ), который подключается к контакту на 6502 мкП и к контакту с тем же именем на всех специальных кораблях, таких как CIA 1, CIA 2 и VIC II. На этапе сброса за счет этой линии все регистры в МКП и в специальных микросхемах сбрасываются в 0 (обнуляются для каждого бита). Затем аппаратным обеспечением микропроцессора передаются указатель стека и регистр состояния процессора с их начальными значениями в микропроцессоре. Затем программному счетчику присваивается значение (адрес) в ячейках $FFFC и $FFFD. Напомним, что счетчик программ хранит адрес следующей инструкции. Содержимое (адрес), хранящееся здесь, предназначено для подпрограммы, которая начинает инициализацию программного обеспечения. До сих пор все делается микропроцессорным оборудованием. Вся память на этом этапе не затрагивается. Затем начинается следующий этап инициализации.

Инициализация выполняется некоторыми процедурами в ОС ПЗУ. Инициализация означает присвоение начальных значений или значений по умолчанию некоторым регистрам специальных микросхем. Инициализация начинается с присвоения начальных значений или значений по умолчанию некоторым регистрам специальных микросхем. прерывание , например, должен начинать выдачу каждые 1/60 секунды. Таким образом, соответствующий таймер в CIA №1 должен быть установлен на значение по умолчанию.

Далее ядро ​​выполняет тест оперативной памяти. Он проверяет каждое местоположение, отправляя туда байт и считывая его обратно. Если и есть разница, то, по крайней мере, это расположение плохое. Kernal также определяет верхнюю и нижнюю часть памяти и устанавливает соответствующие указатели на странице 2. Если верхняя часть памяти равна $DFFF, $FF помещается в ячейку $0283, а $DF помещается в байтовую ячейку $0284. И $0283, и $0284 имеют маркировку HIRAM. Если нижняя часть памяти равна $0800, $00 помещается в ячейку $0281, а $08 помещается в ячейку $0282. И $0281, и $0282 имеют маркировку LORAM. Тест ОЗУ фактически начинается с 0300 долларов США до верхней части памяти (ОЗУ).

Наконец, векторам ввода/вывода (указателям) присваиваются значения по умолчанию. Тест ОЗУ фактически начинается с 0300 долларов США до верхней части памяти (ОЗУ). Это означает, что инициализируются страница 0, страница 1 и страница 2. Страница 0, в частности, содержит множество указателей на ПЗУ ОС, а страница 2 содержит множество указателей на BASIC. Эти указатели называются переменными. Помните, что страница 1 — это стек. Указатели называются переменными, поскольку у них есть имена (метки). На этом этапе очищается экранная память экрана (монитора). Это означает отправку кода размером 20 долларов США (который совпадает с ASCII 20 долларов США) на 1000 ячеек экрана ОЗУ. Наконец, ядро ​​запускает интерпретатор BASIC для отображения командной строки BASIC, которая ГОТОВА, в верхней части монитора (экрана).

5.17 Проблемы

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

  1. Напишите код на ассемблере, который сделает все биты порта A CIA №2 выходными, а порта B CIA №2 – входными.
  2. Напишите код языка ассемблера 6502, который ожидает нажатия клавиши клавиатуры, пока она не будет нажата.
  3. Напишите программу на языке ассемблера 6502, которая отправляет символ «E» на экран Commodore-64.
  4. Напишите программу на языке ассемблера 6502, которая берет символ с клавиатуры и отправляет его на экран Commodore-64, игнорируя код клавиши и время.
  5. Напишите программу на языке ассемблера 6502, которая получает байт с дискеты Commodore-64.
  6. Напишите программу на языке ассемблера 6502, которая сохраняет файл на дискету Commodore-64.
  7. Напишите программу на языке ассемблера 6502, которая загружает программный файл с дискеты Commodore-64 и запускает его.
  8. Напишите программу на языке ассемблера 6502, которая отправляет байт «E» (ASCII) модему, который подключен к пользовательскому RS-232-совместимому порту Commodore-64.
  9. Объясните, как осуществляется подсчет и отсчет времени на компьютере Commodore-64.
  10. Объясните, как системный блок Commodore-64 может идентифицировать 10 различных источников запросов на немедленное прерывание, включая немаскируемые запросы на прерывание.
  11. Объясните, как фоновая программа может работать с программой переднего плана на компьютере Commodore-64.
  12. Кратко объясните, как программы на языке ассемблера могут быть скомпилированы в одно приложение для компьютера Commodore-64.
  13. Кратко объясните процесс загрузки компьютера Commodore-64.