Как работает периферия компьютера: от клавиатуры до дисплея и прерываний

Завершение контрольной секции процессора

На этом этапе мы завершили проектирование контрольной секции нашего процессора. Теперь у нас есть возможность загружать инструкции в оперативную память (ОЗУ), а внутренние компоненты процессора смогут их выполнять. Давайте взглянем на итоговую схему этой секции:

На первый взгляд схема может показаться сложной, но на самом деле мы уже разобрали все её составные части. Основное новшество в полной версии — это несколько дополнительных логических элементов ИЛИ, необходимых для подключения нескольких сигнальных проводов к большинству управляющих битов ‘e’ и ‘s’.

Когда байт инструкции попадает в регистр команд (IR), он активирует определённую последовательность действий внутри схемы. Каждый из 256 возможных паттернов байта вызывает уникальную активность. Таким образом, мы получаем машинный код — набор из 256 различных команд, которые процессор способен понимать и выполнять. Именно с помощью этого кода мы можем заставить компьютер производить полезные вычисления.

Как бы удивительно это ни звучало, но всё, что вы когда-либо видели на экране компьютера — результат выполнения процессором именно таких простых инструкций.

Дополнительные арифметические операции

До сих пор мы рассматривали только операцию сложения. Хотя глубоко погружаться в арифметику не будем, стоит понять базовые принципы других действий. Например, вычитание можно реализовать с помощью сумматора и инвертора. Чтобы вычесть значение регистра R1 из R0, нужно: инвертировать R1, прибавить к результату единицу, а затем сложить полученное число с R0. Рассмотрим на примере 37 - 21:

Последний шаг — сложение 37 и 235. Теоретически результат 272, но наш регистр 8-битный, поэтому сумматор активирует бит переноса, а оставшиеся 8 бит будут равны 00010000, что в десятичной системе и есть 16. Нам не обязательно досконально понимать, почему вычитание в двоичной системе работает именно так; главное, что этот метод эффективен.

Умножение в двоичной системе ещё проще: 1 × 1 = 1, а во всех остальных случаях результат 0. Вот пример умножения 5 на 5:

Алгоритм следующий: если младший бит множимого равен 1, мы добавляем множитель к результату. Затем сдвигаем множитель влево и повторяем проверку для следующего бита множимого. Проще понять это, взглянув на программный код, где R0 — верхнее число, R1 — нижнее, R2 — результат, а R3 используется для управления циклом:

Проследим за состоянием регистров в первые три итерации цикла:

Из-за небольших множителей умножение завершается быстро: R1 был добавлен к R2 дважды (на первой и третьей итерации, когда флаг переноса C был равен 1). В итоге R2 содержит 00011001, что равно 25 (16+8+1) — правильный ответ для 5 × 5. Цикл выполнится ещё 5 раз, но сложения больше не произойдёт, так как в R0 не останется единиц. Вся программа занимает восемь проходов.

Если результат умножения превышает 255, потребуется более сложная программа с использованием нескольких регистров и флага переноса. Однако наша цель — не научить программированию, а объяснить принципы работы компьютера, поэтому углубляться в сложные алгоритмы не будем.

Деление, например 15 / 3, можно представить как количество раз, которое можно вычесть 3 из 15, пока не получится 0. На каждом шаге мы вычитаем делитель из делимого, увеличиваем счётчик (например, в регистре R2) и проверяем, не стал ли результат нулём (флаг Z). После пяти таких шагов программа завершится, и в R2 будет записано 5.

Существуют и методы работы с отрицательными числами, но в рамках этого обзора мы их рассматривать не будем.

Взаимодействие с периферийными устройствами

Работа компьютера была бы бессмысленной, если бы результаты вычислений оставались только в регистрах и ОЗУ. Для обмена информацией с внешним миром используются периферийные устройства, обеспечивающие ввод и вывод данных (I/O). Человек вводит данные (например, с клавиатуры), а компьютер выводит результат (например, на монитор). Для организации этого обмена нужны дополнительные провода и новые инструкции.

Сначала мы выводим шину центрального процессора (ЦП) за его пределы вместе с несколькими управляющими проводами. Эти 12 проводов образуют «шину ввода/вывода» (I/O Bus). Устройства, подключённые к ней, называются периферийными. Поскольку одновременно может работать только одно устройство, каждому из них присваивается уникальный адрес ввода/вывода — число, по которому устройство понимает, что данные предназначены именно ему. Вот как выглядит шина ввода/вывода ЦП:

На схеме ниже показаны провода шины ввода/вывода. CPU Bus — это та же шина данных ЦП.

Провод input/output определяет направление передачи данных.

Провод Data/Address указывает, передаются ли данные или адрес устройства.

I/O Address — это номер конкретного периферийного устройства.

I/O clk e и I/O clk s — сигналы для активации и установки регистров при передаче данных.

Теперь нужно доработать контрольную секцию, добавив поддержку операций ввода-вывода:

Биты 4 и 5 регистра IR постоянно подключены к шине ввода/вывода. Операция ввода-вывода выполняется за один шаг. Для вывода на 4-м шаге степпера активируется сигнал ‘e’ регистра Reg B и сигнал ‘s’ I/O clk s. Для ввода на 5-м шаге активируется ‘e’ I/O clk e и ‘s’ Reg B.

Рассмотрим код инструкции ввода/вывода:

В зависимости от комбинации битов 4 и 5 регистра IR, эта инструкция может использоваться четырьмя разными способами, что даёт нам четыре новые команды машинного языка:

Каждое периферийное устройство имеет уникальные характеристики и требует специального интерфейса для подключения к шине I/O — так называемого «адаптера устройства» (например, адаптер клавиатуры или диска). Адаптер остаётся неактивным, пока на шине не появится его адрес. По команде «OUT Addr» компьютер устанавливает на шину адрес устройства, с которым хочет общаться. Соответствующий адаптер «просыпается», в то время как остальные устройства игнорируют передачу.

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

Устройство ввода: клавиатура

Клавиатура — одно из простейших устройств ввода. Её задача — передавать процессору один байт (код ASCII) при нажатии клавиши. Внутри клавиатуры есть собственная 8-проводная шина, которая формирует соответствующий код при замыкании контакта клавиши.

При нажатии клавиши код ASCII появляется в регистре «Keycode». Логический элемент №1 на схеме активируется только тогда, когда на шине ЦП появляется адрес 00001111, соответствующий этому адаптеру клавиатуры. Элемент №2 срабатывает при одновременной активации сигналов Clk s, Address и команды OUT, что включает бит памяти «М» и активирует адаптер. Элемент №3 активируется при наличии сигналов Clk e, DATA и команды IN, позволяя передать данные из регистра Keycode в регистр Reg B процессора.

Каждый адаптер, подключённый к шине I/O, должен иметь схему, аналогичную описанной, с уникальной комбинацией проводов для выбора устройства.

Рассмотрим пример программы, которая записывает код нажатой клавиши в регистр R3:

Эта программа постоянно опрашивает состояние клавиатуры. Если клавиша не нажата, в R3 будет 0. Если нажата — в R3 запишется соответствующий код ASCII, и программа может выполнить действия, связанные с этой клавишей. Так работает базовое взаимодействие с устройствами ввода.

Устройство вывода: дисплей

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

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

Дисплей — это периферийное устройство, которое самостоятельно занимается отрисовкой изображения на основе данных, полученных от ЦП. Если бы процессор контролировал каждый пиксель в реальном времени, у него не оставалось бы ресурсов на другие задачи. Решение заключается в том, что ЦП передаёт дисплею информацию о следующем кадре в промежутках между отрисовкой. Для хранения этого кадра дисплею требуется собственная память (видеопамять).

Обратите внимание: США делают ставку на квантовые компьютеры.

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

Рассмотрим упрощённый пример: монохромный дисплей с разрешением 320×200 пикселей (всего 64 000 точек). Каждый пиксель может быть либо включён, либо выключен. Для хранения одного кадра потребуется 64 000 бит, или 8 000 байт (по 8 пикселей в байте). Частота обновления 30 кадров в секунду требует тактового генератора с частотой около 1,92 МГц.

Адаптер дисплея содержит регистры, отслеживающие текущие координаты пикселя (по горизонтали и вертикали). С каждым тактом горизонтальная координата увеличивается. Достигнув 319, она сбрасывается в 0, а вертикальная координата увеличивается на 1. Достигнув 199, вертикальная координата также сбрасывается, и начинается отрисовка нового кадра. Таким образом, за один кадр последовательно выбираются все пиксели от (0,0) до (319,199).

Поскольку 8 пикселей хранятся в одном байте видеопамяти, адрес в памяти увеличивается каждые 8 тактов. Сначала считывается байт по адресу 0, и отрисовываются пиксели (0,0)…(7,0). Затем адрес увеличивается до 1, и отрисовываются пиксели (8,0)…(15,0), и так далее.

Большую часть времени адаптер дисплея занят отрисовкой. В паузах между кадрами ЦП может отправлять новые данные в видеопамять с помощью команды I/O OUT, указывая адрес адаптера дисплея, а затем адреса и байты для записи. Видеопамять устроена так, что для чтения (отрисовки) и записи (обновления) используются разные схемы управления адресами (MAR).

Но просто записать код символа ASCII (например, 01000001 для буквы «А») в видеопамять недостаточно — на экране появятся лишь восемь точек. Чтобы отобразить узнаваемый символ, нужен дополнительный шаг — преобразование кода в графическое изображение.

Преобразование кодов в изображения: шрифты

Мы выяснили, что для отображения символов на экране недостаточно просто записать их ASCII-коды в видеопамять. Необходим механизм преобразования этих кодов в читаемые изображения букв и цифр. Допустим, мы хотим отображать символы в виде матрицы 8×8 пикселей. Для хранения изображения одного символа потребуется 8 байт. Например, буква «Е» (код ASCII 69) может выглядеть так:

Набор таких изображений для всех символов называется «шрифтом». Для отображения текста из 100 символов потребуется 800 байт шрифта. Наш учебный компьютер имеет только 256 байт ОЗУ, но в реальности 8-битные процессоры часто используют 16-битную адресную шину, позволяющую адресовать до 64 КБ памяти, что вполне достаточно для хранения шрифтов и программ.

Если изображения символов в шрифте расположены последовательно, то адрес начала картинки для символа можно найти, умножив его ASCII-код на 8. Для буквы «Е» (код 69) это будет адрес 552 (69 × 8). По этому адресу в памяти начинаются 8 байтов, описывающих изображение буквы.

Чтобы нарисовать эту букву в левом верхнем углу экрана, нужно скопировать эти 8 байтов в определённые адреса видеопамяти. Первая строка символа (первый байт шрифта) копируется в байт видеопамяти с адресом 0 (он управляет первыми 8 пикселями первой строки экрана). Вторая строка символа копируется по адресу 40 (так как в строке экрана 320 пикселей, что соответствует 40 байтам). Третья — по адресу 80, и так далее. Для отображения следующего символа (например, «Х») справа от «Е», его байты нужно будет записать по адресам 1, 41, 81 и т.д.

Вывод одной буквы на экран — довольно трудоёмкий для процессора процесс, требующий выполнения множества инструкций для вычисления адресов и копирования данных. Для отображения 1000 символов может потребоваться около 400 000 машинных циклов. Хотя это звучит как большое число, для современного процессора такая задача составляет лишь малую долю его вычислительной мощности, что и позволяет компьютерам быстро работать с графикой.

Накопитель данных: жёсткий диск

Жёсткий диск — это устройство для долговременного хранения данных. Его ключевые преимущества — большой объём и энергонезависимость (данные не теряются при отключении питания, в отличие от ОЗУ).

Внутри диска находятся один или несколько магнитных «блинов» с концентрическими дорожками. Дорожки разбиты на секторы. Запись и чтение осуществляются магнитными головками, закреплёнными на подвижных рычагах. Организация данных на диске отличается от ОЗУ: информация хранится блоками (кластерами) размером в несколько тысяч байт. Нельзя прочитать или записать отдельный байт — только целый кластер. Для доступа к данным нужно указать номер головки (блина), дорожки и сектора.

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

Механизм прерываний

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

Для реализации прерываний к шине I/O добавляется специальный провод. Устройство, которому требуется внимание процессора (например, клавиатура), активирует этот провод. Получив сигнал прерывания, процессор на следующем такте выполняет не очередную инструкцию основной программы, а специальную последовательность действий:

В результате текущие значения счётчика команд (IAR) и регистра флагов (Flags) сохраняются в ячейки ОЗУ 0 и 1. Затем в IAR и Flags загружаются значения из ячеек 2 и 3 ОЗУ, которые обычно содержат адрес начала программы-обработчика прерывания. Процессор начинает выполнять эту программу. По её завершении специальная инструкция восстанавливает исходные значения IAR и Flags из ячеек 0 и 1, и выполнение основной программы продолжается с того места, где оно было прервано.

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

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

Заключение

На этом мы завершаем обзор основных принципов работы компьютера. Безусловно, в устройстве этой «волшебной коробки» есть ещё множество нюансов. Существуют разные наборы инструкций процессоров, которые могут быть не только 8-битными, но и 16-, 32-, 64- и даже 128-битными. Многообразие периферийных устройств и способов их подключения огромно. А область программирования и вовсе представляет собой необъятное поле для изучения.

Главной задачей этой серии статей было познакомить вас с внутренним устройством и фундаментальными принципами работы центрального процессора и оперативной памяти. Теперь, будь вы начинающий радиолюбитель, программист или просто любознательный человек, компьютер перестал быть для вас «волшебной машиной» и стал понятным механизмом, работающим по логичным и изучаемым законам. Надеемся, это путешествие в мир компьютерной логики было для вас интересным и полезным. Спасибо за внимание и время, потраченное на чтение! Удачи в учёбе и новых начинаниях!

Часть 9 - Назад

#компьютеры #наука и техника #образование #начинающим радиолюбителям #электроника начинающим #процессоры #программирование

Еще по теме здесь: Новости науки и техники.

Источник: Как устроен компьютер? Часть 10 (Как работат периферия).