Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Boroda_2

.doc
Скачиваний:
7
Добавлен:
20.03.2015
Размер:
1.67 Mб
Скачать

Команды ввода-вывода

Ни одна другая группа команд не различается в разных машинах так сильно, как команды ввода-вывода. В современных персональных компьютерах используют­ся три разные схемы ввода-вывода:

+ программируемый ввод-вывод с активным ожиданием;

+ ввод-вывод с управлением по прерываниям;

+ ввод-вывод с прямым доступом к памяти.

Мы рассмотрим каждую из этих схем по очереди.

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

В качестве примера рассмотрим терминал с четырьмя 1-байтными регистра­ми, как показано на рис. 5.20. Два регистра используются для ввода: регистр со­стояния устройства и регистр данных. Два регистра используются для вывода: тоже регистр состояния устройства и регистр данных. Каждый из них имеет уни­кальный адрес. Если имеет место ввод-вывод с отображением на память, все 4 регистра являются частью адресного пространства и могут считываться и запи­сываться с помощью обычных команд, предназначенных для работы с памятью. В противном случае для чтения и записи регистров требуются специальные ко­манды ввода-вывода, например IN и OUT. В обоих случаях ввод-вывод осуществ­ляется путем передачи данных и информации о состоянии устройства между центральным процессором и указанными регистрами.

Рис. 5.20. Регистры устройств в простом терминале

В регистре состояния клавиатуры из 8 бит используются только 2. Самый левый бит аппаратно устанавливается всякий раз, когда в буфере клавиатуры появляется символ. Если предварительно программно был установлен бит 6, вы­полняется прерывание. В противном случае прерывания не происходит. При программируемом вводе-выводе для получения входных данных центральный процессор обычно периодически в цикле считывает регистр состояния клавиату­ры, пока бит 7 не получит значение 1. Когда это случается, программно считыва­ется буферный регистр клавиатуры, чтобы получить символ. Считывание реги­стра данных вызывает сброс бита наличия символа.

Вывод осуществляется аналогично. Чтобы вывести символ на экран, сначала программно считывается регистр состояния дисплея, чтобы узнать, установлен ли бит готовности. Если он не установлен, цикл выполняется снова и снова до тех пор, пока бит готовности не станет равным единице. Это будет означать, что устройство готово принять символ. Как только терминал приходит в состояние готовности, символ программно записывается в буферный регистр дисплея, ко­торый выводит символ на экран и дает сигнал устройству сбросить бит готовно­сти в регистре состояния дисплея. Когда символ появляется на экране, а тер­минал подготавливается к обработке следующего символа, контроллер снова устанавливает бит готовности.

В качестве примера программируемого ввода-вывода рассмотрим Java-npo- цедуру (листинг 5.5). Эта процедура вызывается с двумя параметрами: массивом символов, которые нужно вывести, и количеством символов, имеющимся в мас­сиве (до килобита). Тело процедуры представляет собой цикл, в котором вы­водится по одному символу. Сначала центральный процессор ждет готовности устройства и только после этого выводит символ, и эта последовательность дей­ствий повторяется для каждого символа. Процедуры in и out — это типичные процедуры ассемблера для чтения и записи регистров устройств, которые опре­деляются по первому параметру. Переменная, из которой выполняется чтение или в которую производится запись, определяется по второму параметру. Деле­ние на 128 (путем сдвига вправо на 7 разрядов) ликвидирует младшие 7 бит, при этом бит готовности оказывается в нулевом разряде.

Листинг 5.5. Пример программируемого ввода-вывода

public static void output_buffer(int buf[], int count) {

// Вывод блока данных на устройство int status, i, ready;

for (i = 0; i<count; i++) { do {

status = in(display_status_reg); // получение информации

// о состоянии устройства ready = (status » 7) & 0x01; // выделение бита

// готовности

} while (ready == 1); out(display_buffer_reg, buf[i]);

}

}

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

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

Во многих компьютерах сигнал прерывания порождается путем логического умножения (И) бита разрешения прерываний и бита готовности устройства. Ес­ли в первую очередь (перед запуском устройства ввода-вывода) программно раз­решить прерывания, прерывание произойдет сразу же, поскольку бит готовности уже установлен. То есть вероятно сначала нужно запустить устройство, а уже по­сле этого разрешить прерывания. Запись байта в регистр состояния устройства не меняет бита готовности, который может только считываться.

Ввод-вывод с управлением по прерываниям — это большой шаг вперед по сравнению с программируемым вводом-выводом, но все же он далеко не со­вершенен. Дело в том, что прерывание приходится генерировать для каждого пе­редаваемого символа и нужно каким-то образом избавляться от слишком боль­шого числа прерываний.

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

Микросхема ПДП имеет по крайней мере 4 регистра. Все они могут загру­жаться программно центральным процессором. Первый регистр содержит адрес памяти, который нужно считать или записать. Второй регистр содержит количе­ство передаваемых байтов или слов. Третий регистр содержит номер устройства ввода-вывода или адрес в адресном пространстве ввода-вывода, задавая требуе­мое устройство. Четвертый регистр сообщает, должны ли данные считываться с устройства или записываться на него.

Чтобы записать блок из 32 байт с адреса памяти 100 на терминал (например, устройство 4), центральный процессор записывает числа 32, 100 и 4 в первые три регистра ПДП, а код записи (например, 1) — в четвертый регистр, как показано на рис. 5.21. Контроллер ПДП, инициализированный таким образом, делает за­прос на доступ к шине, чтобы считать байт 100 из памяти, точно так же, как если бы этот байт считывал центральный процессор. Получив нужный байт, контрол­лер ПДП посылает устройству 4 запрос на ввод-вывод, чтобы записать на него байт. После завершения этих двух операций контроллер ПДП увеличивает зна­чение регистра адреса на 1 и уменьшает значение регистра счетчика на 1. Если значение счетчика остается положительным, следующий байт считывается из памяти и записывается на устройство ввода-вывода.

Когда значение счетчика доходит до 0, контроллер ПДП останавливает пере­дачу данных и нагружает линию прерывания на микросхеме процессора. При наличии ПДП центральному процессору остается только инициализировать не­сколько регистров, после чего он может заниматься чем-нибудь другим, пока пе­редача данных не завершится. При завершении передачи центральный процес­сор получает сигнал прерывания от контроллера ПДП. Некоторые контроллеры ПДП содержат 2, 3 и более наборов регистров, так что они могут управлять не­сколькими процессами передачи одновременно.

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

Команды процессора Pentium 4

В этом и следующих двух подразделах мы рассмотрим наборы команд трех ма­шин: Pentium 4, UltraSPARC III и 8051. Каждая из них поддерживает базовые команды, обычно получаемые в результате работы компиляторов, а также допол­нительные команды, которые используются редко или используются исключи­тельно операционной системой. Начнем с Pentium 4.

Команды Pentium 4 представляют собой причудливую смесь 32-разрядных команд, а также команд, появившихся еще в процессоре 8088. В табл. 5.9 приве­дены наиболее распространенные целочисленные команды, при этом использу­ются следующие обозначения:

  • SRC — источник данных;

  • DST — приемник данных;

  • # — количество битов, на которое происходит сдвиг;

  • LV — количество локальных переменных.

Перечень далеко не полный, поскольку в него не вошли команды с плаваю­щей точкой, команды управления, а также некоторые нечасто встречающиеся це­лочисленные команды (например, использование 8-разрядного байта для выпол­нения поиска по таблице). Тем не менее таблица дает представление о том, какие действия может выполнять Pentium 4.

Многие команды Pentium 4 обращаются к одному или к двум операндам, ко­торые находятся в регистрах или памяти. Например, бинарная команда ADD складывает два операнда, а унарная команда INC увеличивает значение одного операнда на 1. Некоторые команды имеют несколько похожих вариантов. На­пример, команды сдвига могут сдвигать слово либо вправо, либо влево, с уче­том знакового бита или без учета. Большинство команд имеют несколько раз­личных кодировок в зависимости от природы операндов.

Таблица 5.9. Наиболее распространенные целочисленные команды процессора Pentium 4

Команда

Описание

Команды перемещения

MOV DST, SRC

Перемещение из SRC в DST

PUSH SRC

Помещение из SRC в стек

POP DST

Выталкивание слова из стека и помещение его в DST

XCHG DS1, DS2

Смена мест DS1 и DS2

LEA DST, SRC

Загрузка действительного адреса SRC в DST

CMOV DST, SRC

Условное перемещение

Арифметические команды

ADD DST, SRC

Сложение SRC и DST

SUB DST, SRC

Вычитание SRC из DST

MUL SRC

Умножение ЕАХ на SRC (без учета знака)

IMUL SRC

Умножение ЕАХ на SRC (с учетом знака)

DIV SRC

Деление EDXiEAX на SRC (без учета знака)

IDV SRC

Деление EDX:EAX на SRC (с учетом знака)

ADC DST, SRC

Сложение SRC с DST и прибавление бита переноса

SBB DST, SRC

Вычитание DST и перенос из SRC

INC DST

Инкремент (прибавление 1) DST

DEC DST

Декремент (вычитание 1) DST

NEG DST

Отрицание DST (вычитание DST из 0)

Двоично-десятичные команды

DAA

Десятичная коррекция

AAA

Коррекция ASCII-кода для сложения

AAS

Коррекция ASCII-кода для вычитания

AAM

Коррекция ASCII-кода для умножения

AAD

Коррекция ASCII-кода для деления

Логические команды

AND DST, SRC

Логическая операция И над SRC и DST

OR DST, SRC

Логическая операция ИЛИ над SRC и DST

XOR DST, SRC

Логическая операция ИСКЛЮЧАЮЩЕЕ ИЛИ над SRC и DST

NOT DST

Замещение DST дополнением до 1

Команды обычного и циклического сдвига

SAL/SAR DST, #

Сдвиг DST влево/вправо на # бит

SHL/SHR DST, #

Логический сдвиг DST влево/вправо на # бит

ROL/ROR DST, #

Циклический сдвиг DST влево/вправо на # бит

ROL/ROR DST, #

Циклический сдвиг DST по переносу на # бит

Команды тестирования и сравнения

TST SRC1, SRC2

Операнды логической операции И, установка флагов

Команда

Описание

CMPSRC1, SRC2

Установка флагов на основе разности SRC1 - SRC2

Команды передачи управления

JMP ADDR

Переход к адресу

Jxx ADDR

Условные переходы на основе флагов

CALL ADDR

Вызов процедуры по адресу

RET

Выход из процедуры

IRET

Выход из прерывания

LOOPxx

Продолжение цикла до выполнения определенного условия

INT ADDR

Программное прерывание

INTO

Прерывание, если установлен бит переполнения

Команды обработки строк

LODS

Загрузка строки

STOS

Сохранение строки

MOVS

Перемещение строки

CMPS

Сравнение двух строк

SCAS

Сканирование строки

Команды для работы с кодами условий

STC

Установка бита переноса в регистре EFLAGS

CLC

Сброс бита переноса в регистре EFLAGS

СМС

Дополнение бита переноса в регистре EFLAGS

STD

Установка бита направления в регистре EFLAGS

CLD

Сброс бита направления в регистре EFLAGS

STI

Установка бита прерывания в регистре EFLAGS

CLI

Сброс бита прерывания в регистре EFLAGS

PUSHFD

Помещение значения из регистра EFLAGS в стек

POPFD

Выталкивание значения из стека в регистр EFLAGS

LAHF

Загрузка АН из регистра EFLAGS

SAHF

Сохранение АН в регистре EFLAGS

Прочие команды

SWAP DST

Изменение порядка следования байтов в DST

CWQ

Расширение ЕАХ до EDX:EAX для деления

SWDE

Расширение 16-разрядного числа в АХ до ЕАХ

ENTER SIZE, LV

Создание стекового фрейма с байтами размера

LEAVE

Удаление стекового фрейма, созданного командой ENTER

NOP

Пустая операция

HLT

Останов

IN AL, PORT

Перенос байта из порта в АЛУ

OUT PORT, AL

Перенос байта из АЛУ в порт

WAIT

Ожидание прерывания

При выполнении команд источники данных (SRC) не изменяются, а прием­ники (DST) обычно изменяются. Существуют определенные правила, опреде­ляющие, что может быть источником, а что приемником, но здесь мы не будем о них говорить. Многие команды имеют три варианта: для 8-, 16- и 32-разрядных операндов соответственно. Они различаются по коду операции и/или по одному биту в команде. В табл. 5.9 приведены в основном 32-разрядные команды.

Для удобства мы разделили команды на несколько групп. Первая группа со­держит команды, которые перемещают данные между компонентами машины: регистрами, памятью и стеком. Вторая группа содержит арифметические коман­ды для операций со знаком и без знака. При умножении и делении 64-разрядное произведение или делимое хранится в двух регистрах: ЕАХ (младшие биты) и EDX (старшие биты).

Третья группа включает двоично-десятичную арифметику. Здесь каждый байт рассматривается как два 4-разрядных полубайта. Каждый полубайт содер­жит 1 десятичный разряд (от 0 до 9). Комбинации битов от 1010 до 1111 не ис­пользуются. Таким образом, 16-разрядное целое число может содержать деся­тичное число от 0 до 9999. Хотя такая форма хранения неэффективна, она устраняет необходимость преобразования десятичных входных данных в двоич­ные, а затем обратно в десятичные для вывода. Эти команды служат для выпол­нения арифметических действий над двоично-десятичными числами. Они широ­ко используются в программах на языке COBOL.

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

Следующие две группы связаны с проверкой, сравнением и осуществлением перехода в зависимости от полученного результата. Результаты проверки и срав­нения хранятся в различных битах регистра EFLAGS. Символами Jxx обозначе­на группа команд, выполняющих условный переход в зависимости от результа­тов предыдущего сравнения (то есть в зависимости от битов в регистре EFLAGS).

В Pentium 4 есть несколько команд для загрузки, сохранения, перемещения, сравнения и сканирования символьных строк или слов. Перед этими командами может стоять специальный префиксный байт REP (repetition — повторение), ко­торый заставляет команду повторяться до тех пор, пока не будет выполнено оп­ределенное условие (например, пока регистр ЕСХ, значение которого уменьша­ется на 1 после каждого повторения, не станет равным 0). Таким образом, различные действия (перемещение, сравнение и т. д.) могут производиться над произвольными блоками данных. Следующая группа команд управляет кодами условий.

В последнюю группу входят команды, которые не вошли ни в одну из преды­дущих групп. Это команды перекодирования, управления, ввода-вывода и оста­новки процессора.

Команды Pentium 4 имеют ряд префиксов. Один из них (REP) мы уже упомя­нули. Префикс — это специальный байт, который может ставиться практически перед любой командой (подобно WIDE в IJVM). Как уже отмечалось, префикс REP заставляет команду, идущую за ним, повторяться до тех пор, пока регистр ЕСХ не примет значение 0. Префиксы REPZ и REPNZ заставляют команду выполняться снова и снова, пока код выполнения условия Z не примет значение 1 или 0 соот­ветственно. Префикс LOCK резервирует шину для всей команды, чтобы можно бы­ло осуществлять межпроцессорную синхронизацию. Другие префиксы исполь­зуются для того, чтобы команда работала в 16- или 32-разрядном формате. При этом меняется не только длина операндов, но и полностью переопределяются ре­жимы адресации. Наконец, в Pentium 4 реализована сложная схема сегментации, в которой задействованы код, данные, стек и дополнительные сегменты (насле­дие 8088). Префиксы позволяют регламентировать применение тех или иных сегментов при обращении к памяти. К счастью, эта проблема для нас не слишком актуальна.

Команды UltraSPARC III

Все целочисленные команды пользовательского режима UltraSPARC III пере­числены в табл. 5.10, при этом используются следующие обозначения:

  • SRC — регистр-источник;

  • DST — регистр-приемник;

  • R1 — регистр-источник;

  • S2 — источник (регистр или непосредственно данные);

  • ADDR — адрес памяти;

  • TRAP# — номер системного прерывания;

  • FCN — код функции;

  • MASK — тип операции;

  • CON — константа;

  • V — обозначение регистра;

  • СС — набор кодов условия;

4 R — регистр-приемник;

  • сс — условие;

  • г — LZ, LEZ, Z, NZ, GZ или GEZ.

В таблице не представлены команды с плавающей точкой, команды управле­ния (например, команды управления кэш-памятью, команды перезагрузки сис­темы), команды, включающие отличные от пользовательских адресные про­странства, устаревшие команды. Набор команд удивительно мал. Оно и понятно, ведь UltraSPARC III — это RISC-процессор.

Структура команд LOAD и STORE очень проста. Эти команды имеют варианты для 1, 2, 4 и 8 байт. Если в 64-разрядный регистр загружается число размером меньше 64 бит, это число может быть либо расширено по знаку, либо дополнено нулями. Существуют команды для обоих вариантов.

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]