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

Рис. 1.13. Подключение устройств компьютера к системной шине(A - адреса; D - данные; M/IO - один из сигналов управления)

Системная шина представляет собой, в сущности, набор линий - проводов, к которым единообразно подключаются все устройства компьютера. В более широком плане в понятие системной шины следует включить электрические и логические характеристики сигналов, действующих на линиях шины, их назначение, а также правила взаимодействия этих сигналов при выполнении тех или иных операций на шине - то, что обычно называют протоколами обмена информацией. Сигналы, распространяющиеся по шине, доступны всем подключенным к ней устройствам, и в задачу каждого устройства входит выбор предназначенных ему сигналов и обеспечение реакции на них, соответствующей протоколу обмена.
Процессор связан с системной шиной большим количеством линий (практически всеми своими выводами), из которых нас будут интересовать только линии трех категорий: набор линий адресов, набор линий данных и один из сигналов управления, носящий название М / IO' (М - "IO с отрицанием"). Последний сигнал, строго говоря, имеется только среди выходных сигналов микропроцессора, а на системную шину приходят производные от этого сигнала, образованные, как комбинации сигнала М / IO' с управляющими сигналами записи и чтения. Однако суть дела от этого не изменяется, и для простоты мы опустили эти подробности.
Процессор, желая записать данное по некоторому адресу в памяти, выставляет на линии адресов требуемый адрес, а на линии данных - данное. Устройство управления памятью расшифровывает поступивший адрес и, если этот адрес принадлежит памяти, принимает с линий данных поступившее данное и заносит его в соответствующую ячейку памяти. Описанная процедура отражает выполнение процессором команды типа

 

mov mem,AX

где mem - символическое обозначение ячейки памяти, принадлежащей сегменту данных программы.
Если процессор, выполняя команду типа

mov AX, mem

должен прочитать данное из памяти, он выставляет на линии адресов требуемый адрес и ожидает поступления данных. Устройство управления памятью, расшифровав поступивший адрес и убедившись в наличии такого адреса в памяти, отыскивает в памяти требуемую ячейку, считывает из нее данное и выставляет его на линии данных. Процессор снимает данное с шины и отправляет его в указанный в команде операнд (в данном случае в регистр АХ).
Описанные процедуры записи и чтения справедливы не только по отношении к памяти; для всех остальных устройств компьютера они выглядят точно так же. За каждым устройством закреплена определенная группа адресов, на которые оно должно отзываться. Обнаружив свой адрес на магистрали, устройство, в зависимости от заданного процессором направления передачи данных, либо считывает с магистрали поступившие данные, либо, наоборот, устанавливает имеющиеся в нем данные на магистраль.
Из рис. 1.13 видно, что все устройства компьютера можно разбить на две категории. Представителем одной категории является видеобуфер, входящий в видеосистему компьютера. Устройство управления видеобуфером настроено на две группы адресов, которые как бы продолжают адреса, относящиеся к оперативной памяти. Действительно, адрес последнего байта оперативной памяти составляет 9FFFFh, а уже следующий адрес A0000h является адресом первого байта графического видеобуфера. Графический видеобуфер занимает 64 Кбайт адресного пространства до адреса AFFFFh (реально немного меньше, но в плане рассматриваемого вопроса это не имеет значения). Текстовый видеобуфер расположен на некотором расстоянии от графического и занимает 32 Кбайт, начиная с адреса B8000h. Таким образом, адреса оперативной памяти и памяти видеобуфера разнесены и не перекрываются.
Ко второй категории устройств можно отнести все устройства, адреса которых перекрываются с адресами оперативной памяти. Например, за контроллером клавиатуры закреплены два адреса: 60h и 61h. По адресу 60h выполняется чтение кода нажатой клавиши, а адрес 61h используется для управления работой контроллера. И тот, и другой адрес имеются в оперативной памяти и, таким образом, возникает проблема распознавания устройства, к которому происходит обращение. Аналогичная ситуация наблюдается и со многими другими устройствами компьютера. Например, контроллер прерываний, служащий для объединения сигналов прерываний от всех устройств компьютера и направления их на единственный вход прерывания микропроцессора, управляется через два адреса Поскольку -в состав машины всегда включают два контроллера, для них выделяются две пары адресов. Во всех компьютерах типа IBM PC контроллерам прерываний назначаются адреса 20h-21h и A0h-Alh, которые так же отвечают и некоторым байтам оперативной памяти.
Проблема идентификации устройств с перекрывающимися адресами имеет два аспекта: аппаратный и программный. Идентификация устройств на системной шине осуществляется с помощью сигнала М / IO', которой генерируется процессором в любой операции записи или чтения. Однако значение этого сигнала зависит от категории адресуемого устройства. При обращении к памяти или видеобуферу процессор устанавливает значение сигнала М / IO' = 1 (М обозначает memory, память). При обращении к остальным устройствам этот сигнал устанавливается в О (IO обозначает in-out, ввод-вывод, и если IO с отрицанием равно 0, то IO равно 1, и это олицетворяет не операцию с памятью, а операцию ввода-вывода). В то же время все устройства, подключенные к шине, анализируют значение сигнала М / IO1. При этом память и видеобуфер отзываются на операции чтения-записи на шине, только если они сопровождаются значением М / IO' = 1, а остальные устройства воспринимают сигналы магистрали только при значении М / IO' = 0. Таким образом осуществляется аппаратное разделение устройств "типа памяти" и устройств "ввода-вывода".
Программное разделение устройств реализуется с помощью двух наборов команд процессора - для памяти и для устройств ввода-вывода. В первую группу команд входят практически все команды процессора, с помощью которых можно обратиться по тому или иному адресу - команды пересылки mov и movs, арифметических действий add, mul и div, сдвигов rol, ror, sal и sar, анализа содержимого байта или слова test и многие другие. Фактически в эту группу команды входит большинство команд процессора. Вторую группу команд образуют специфические команды ввода-вывода. В МП 86 их всего две - команда ввода in и команда вывода out. При выполнении команд первой группы процессор автоматически генерирует М / IO' = 1; при выполнении команд in и out процессор устанавливает сигнал М / IO' = 0.
Таким образом, при обращении к памяти и к видеобуферу программист может использовать все подходящие по смыслу команды процессора, при этом, работая, например, с видеобуфером, можно не только засылать в него (или получать из него) данные, но и выполнять прямо в видеобуфере любые арифметические, логические и прочие операции.
Обращаться же к контроллерам тех или иных устройств (и, между прочим, к видеоадаптеру), допустимо только с помощью двух команд - in и out. Арифметические операции или анализ данных в устройстве невозможен. Необходимо сначала прочитать в процессор данное из внешнего устройства, и лишь затем выполнять над ним требуемую операцию.
Наличие двух категорий адресов устройств дает основание говорить о существовании двух адресных пространств - пространства памяти, куда входит сама память, а также видеобуферы и ПЗУ, и пространства ввода-вывода (пространства портов), куда входят адреса остальной аппаратуры компьютера. При этом, если объем адресного пространства памяти составляет 1 Мбайт (а в защищенном режиме 4 Гбайт), то адресное пространство портов гораздо меньше - его размер составляет всего 64 Кбайт. Эта величина определяется форматом команд ввода-вывода. Адрес адресуемого порта должен быть записан в регистр DX (и ни в какой другой) и, таким образом, максимальное значение этого адреса составляет величину FFFFh. Реально из 64 Кбайт адресного пространства портов используется лишь очень малая часть. Практические вопросы программирования через общее с памятью адресное пространства и через пространство портов будут рассмотрены в следующих главах.