Предыдущая глава ЧАСТЬ 3. АВТОНОМНЫЕ ПРОГРАММЫ РЕАЛЬНОГО РЕЖИМА Следующий раздел

Автономная программа выполняется на ВС, не имеющей операционную систему. Поэтому она не может обратиться за помощью к ОС, используя для этого соответствующие системные вызовы. Следовательно, автономная программа должна выполнять управление ресурсами системы сама, возможно, используя для этого системные вызовы BIOS. Разработка автономных программ особенно актуальна для небольших встроенных систем, устанавливаемых непосредственно на объекте управления. Кроме того, в качестве автономной программы можно рассматривать и саму ОС.

В отличие от процессора i8086, современные процессоры имеют не один, а несколько режимов работы. Среди этих режимов основным является защищенный режим, выполняющий поддержку мультипрограммирования. Реальный режим – режим, в котором процессор оказывается сразу же после включения питания. Так как этот режим очень похож на работу процессора i8086, то разработку автономных программ целесообразно начать с этого режима.

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

Несмотря на то, что автономная программа выполняется без помощи ОС, разработка такай программы, то есть получение для нее исходных, объектных и загрузочного файлов, как и раньше, будет происходить в среде конкретной операционной системы. Соответствующая ВС (аппаратура + ОС) называется инструментальной системой. Естественно, что для автономной программы инструментальная и выполняющая системы не совпадают. Но для первоначальных вариантов разрабатываемых далее программ это не выполняется. Эти варианты программ не только разрабатываются, но и исполняются в среде используемой инструментальной системы (i8086 + DOS). Позднее, когда у нас появятся загрузчики автономных программ, мы «доделаем» наши программы так, чтобы они действительно были автономными. Пока лишь заметим, что такая «доделка» производится достаточно просто.

 

20.1. Управление устройствами на аппаратном уровне

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

Для работы со стандартными ПУ программа может использовать системные подпрограммы ОС и BIOS, используя для этого соответствующие системные вызовы. При этом программе предоставляется возможность работать с ПУ не только как с устройствами, но и как с файлами. Подобные системные вызовы широко использовались нами в рассмотренных ранее примерах программ, заметно сокращая время программирования.

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

Допустим, что ЭВМ имеет структуру с общей шиной (см.рис.4). С помощью одного ИУ к ОШ подсоединяются однотипные ПУ. Простейшее ИУ состоит из одного или более регистров, в состав которых обязательно входят регистр состояния и управления и буферный регистр данных. Буферный регистр данных (RD) предназначен для временного хранения одного или двух байтов данных, передаваемых на ПУ при выводе или принимаемых с ПУ при вводе.

  Регистр состояния и управления (RS) играет для ИУ и подключенных к нему ПУ ту же роль, что регистр FLAGS играет для ЦП, то есть фактически является их блоком управления. Количество регистров состояния и управления, а также назначение их битов для разных ИУ существенно отличаются. На рис.68 приведен пример типичного RS, который будет использоваться нами в дальнейшем. В этом RS b0–b3управляющие биты. Они устанавливаются программами, которые исполняются на ЦП, и предназначены:

1) если b0 = 1, то разрешается работа ПУ по вводу (выводу) единицы информации;

2) b1 – b2  используются для уточнения операции (функции), выполняемой устройством;

3) если b3 = 1, то в ЦП может быть выдан сигнал прерывания.

На рис.68 биты b4–b7биты состояния ПУ. Они устанавливаются ПУ или его ИУ. При этом b7 описывает состояние буферного регистра данныхRD. Для устройства ввода b7 = 1 означает, что RD заполнен данными, которые могут быть перенесены в ЦП. Для устройства вывода это означает, что выходной буфер данных сейчас пуст и ждет, когда ЦП загрузит в него новые данные.

Биты b4 – b6 содержат информацию о том, произошла ли ошибка при выполнении последней операции ввода-вывода. Нулевое содержимое всех этих битов сообщает об отсутствии ошибки, иначе эти биты содержат код ошибки.

 

 

Рис.68. Пример регистра состояния и управления RS

 

При использовании простейшего ИУ всю работу по управлению ПУ выполняет сам ЦП. Поэтому он отвлекается от выполнения самих программ и, таким образом, значительно снижается его фактическая производительность. Применение более сложных ИУ позволяет возложить на них значительную часть работы по управлению ПУ, которая теперь в принципе может выполняться параллельно работе ЦП. Наиболее сложным ИУ является контроллер – специализированный процессор ввода-вывода. (Как и всякое ИУ, контроллер имеет свои RS и RD.)

Регистры ИУ, непосредственно доступные из программ ЦП, называются портами. Портами являются многие RS и RD (но не все), а также служебные регистры, используемые для программного доступа к тем RS и RD, к которым нет непосредственного доступа. Каждый порт в ЭВМ имеет свой уникальный номер, называемый адресом порта. Для некоторых типов ЦП программные операции с портами (чтение и запись) выполняются точно так же, как и операции с ячейками ОП. При этом для адресации портов используется часть адресного пространства ОП, в которой каждый реальный адрес соответствует не ячейке ОП, а порту.

В i8086 используется другой подход, при котором существуют два адресных пространства – одно для ячеек ОП, а второе – для портов. При этом адрес порта – число в диапозоне от 0 до 65535, а сам порт представляет собой 8–битный регистр. Следствием наличия двух адресных пространств является использование для работы с портами специальных команд ЦП: in для ввода из порта и out – для вывода в порт.

Одной командой in можно или ввести в регистр AL один байт, или ввести в регистр AX 16-битное слово. Во втором случае  ввод осуществляется из двух портов, имеющих смежные адреса, причем порт с меньшим адресом содержит младший вводимый байт. Адрес порта в команде in можно задать двумя способами: 1) в виде константы; 2) в качестве содержимого регистра DX. Первый из этих способов позволяет использовать в команде in лишь младшие адреса портов (от 0 до 255). Второй способ позволяет задавать любые порты (от 0 до 65535). Примеры:

 

in al, 50h                           ; ALß (50h)

in      ax, 50h                     ; AX ß (51h : 50h)

in      al, dx                       ; AL ß ((DX))

in      ax, dx                      ; AX ß ((DX)+1 : (DX))

 

Одна команда out позволяет вывести (скопировать) байт из регистра AL в заданный порт или вывести слово из регистра AX в два порта со смежными адресами. Адрес порта задается аналогично команде in с той лишь разницей, что теперь порт является получателем и должен записываться в качестве первого операнда. Примеры:

 

    out    50h, al                           ; (50h) ← (AL)

    out    50h, ax                          ; (51h : 50h) ← (AX)

    out    dx, al                             ; ((DX)) ← (AL)

    out    dx, ax                            ; ((DX)+1 : (DX)) ← (AX)

 

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

1) подготовка ПУ и, возможно, самого драйвера к последующим операциям по обмену данными;

2) инициирование очередной операции ПУ по вводу (выводу) единицы информации;

3) обеспечение завершения очередной операции ввода-вывода.

Реализация перечисленных функций в значительной степени зависит от принципа ввода-вывода, принятого при разработке драйвера. Различают следующие принципы: синхронный; асинхронный с общей памятью; асинхронный с прерываниями; прямой доступ в память. Первые два из этих принципов предназначены для посимвольного обмена с ПУ без использования прерываний.

 


Предыдущая глава В начало Следующий раздел