Министерство образования Российской Федерации ОРЕНБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ Кафедра промышленной электроники и информационно-измерительной техники
В.Н.Булатов
УЧЕБНОЕ ПОСОБИЕ Архитектура микропроцессорной системы. Состав машинных команд и основы программирования микропроцессорной системы на ассемблере
Оренбург 1999
ББК 32.973.2Я7 Б 90 УДК 681.327
Введение В конце двадцатого века микропроцессорные средства вычислительной техники стали широко применяться в приборах бытовой техники, в различных контрольно-измерительных устройствах, средствах управления и тому подобное. С повышением надежности больших интегральных схем, в которых реализованы микропроцессорные устройства, микропроцессорные средства стали применяться и в технике военного и космического назначения. Это связано с тем, что они обладают функциональной гибкостью, высокой надежностью и способны реализовать сложные алгоритмы. На базе микропроцессоров разработаны вычислительные машины нового класса, как персональные компьютеры широкого применения, так и специализированные компьютеры (например, бортовая ЭВМ) и контроллеры (микропроцессорные цифровые автоматы). В связи с этим компьютерная грамотность становится обязательной для любого специалиста. Использование микропроцессорных средств, привело к существенному изменению процесса разработки вычислительной и управляющей аппаратуры. Главное внимание стало уделяться вопросам выбора структуры системы, организации подсистем ввода-вывода, создания программного обеспечения, отладки и тестирования. Особенность этого пособия заключается в том, что изложение принципов построения и программирования ЭВМ на базе микропроцессора ориентировано на широкий круг читателей, имеющих устойчивые знания основ цифровой (дискретной) техники. Принципы работы и архитектура микропроцессора рассматриваются на примере распространенного микропроцессора 80х86 фирмы Intel, являющимся базовым вариантом для одного из самых мощных направлений в развитии компьютеров. Подробное описание набора часто используемых команд 80х86, иллюстрируемое на примерах синтеза команд и составления фрагментов элементарных программ, нацелено на детальное ознакомление с особенностями программирования работы микропроцессоров. Разработка и отладка программного обеспечения является трудоемким этапом проектирования микропроцессорных систем, требующим больших затрат времени и средств. Специалистам, занимающимся вопросами проектирования микропроцессорных систем, приходится использовать либо промышленные образцы отладочных комплексов, либо простые специализированные комплексы собственного изготовления, либо их комбинацию. Методика изучения материала в рамках, изложенного в данном пособии, ориентирована на третий вариант, где: а) в качестве технического средства может быть использовано учебноотладочное устройство К-1810, разработанное на кафедре промышленной 2
электроники и информационно-измерительной техники ОГУ, или любой IBMсовместимый компьютер; б) в качестве программного средства — составленная автором данного пособия на основе DEBUG упрощенная программа редактора-отладчика MONITOR.COM. Построение подсистем ввода-вывода представляет собой не менее сложную проблему проектирования микропроцессорных систем. Подробное описание портов ввода-вывода в наиболее часто используемых режимах программируемых интерфейсов 8255 (параллельный порт) и 8250 (последовательный порт), а также ознакомление с таймером 8253 и контроллером прерываний 8259, примеры их подключения и программирования предполагают не просто ознакомиться с организацией ввода-вывода, но и научиться практически программировать ввод-вывод. Изложенный в последующих главах материал, в силу своей специфичности, не является достаточным для освоения основ микропроцессорной техники. Процесс изучения можно считать достаточным, если он будет подкреплен практическими занятиями: а) в составлении фрагментов схем микропроцессорной системы; б) в составлении фрагментов программ, демонстрирующих возможности набора изучаемых команд; в) в программировании и отладке программ инициализации и функционирования конкретного интерфейса микропроцессорной системы.
3
1 Основы микропроцессорной техники Микропроцессоры и функциональный набор, составляющий микропроцессорный комплект, скорее понятие технологическое, чем идеологическое. И связано оно, главным образом, с возможностью современных технологий выращивания в маленьком объеме (1мм x 1мм x 1мм) кристалла кремния сложнейших схем, содержащих до несколько сотен тысяч полупроводниковых элементов: транзисторов, диодов, резисторов, конденсаторов. Для того, чтобы вникнуть в существо вопроса, необходимо сделать маленький экскурс в историю создания и развития ЭВМ. На всем протяжении истории развития человеческого общества человек все время пытался создать некие автоматы (механизмы, устройства и т.п.), которые могли бы заменить часть человеческой деятельности в области производства. Особенно там, где сам человек это делает очень медленно, непроизводительно. Так в середине двадцатого века появилась ЭВМ. Необходимо сразу заметить, что было бы ошибочным считать, что ЭВМ создавалась именно как вычислитель. Совсем нет. Человек замахнулся на большее. Он захотел, чтобы она еще и умела думать как человек. И принимать решения как человек. И вот совсем в другой области — в области функциональной математики — в конце девятнадцатого века сформировалось самостоятельное направление — логическая математика. С использованием достижений в этой области ученые-математики на основе очень простых абстрактных моделей процессоров создавали системы команд (как алфавит будущего языка). И чем талантливее был придуман этот набор команд, тем большими возможностями он обладал —сначала для создания слов, а потом предложений, а потом уже и целых словесных произведений-программ. Таким образом, разработчикам физической ЭВМ оставалось только выбирать лучший на их взгляд набор команд и реализовать его аппаратно. Надо сказать, что не все разработчики ЭВМ идут этим путем. Вероятно, чтобы не иметь проблем с патентной чистотой, некоторые разработчики технических средств самостоятельно решают вопросы логической реализации процессоров. Получаемые результаты не содержат классических форм, и их, как правило, никак нельзя назвать превосходными. Так можно сказать и о некоторых процессорах Intel. Можно пояснить это с помощью примера, основанного на потенциальных возможностях национальных алфавитов. Рассмотрим русский алфавит. Он содержит 33 буквы, которые используются в строчном и заглавном написании. Чтобы освоить пользование этим алфавитом, нужно — как показывает опыт школьного обучения — совсем немного времени. Но это никак не сказывается на его потенциальных возможностях. Скорее, наоборот. 4
Показательным является сравнение русского алфавита с китайским, каждый элемент которого поглощает в себя гораздо больше, чем буква русского алфавита. Это — событие, предмет или часть его. И сразу столько проблем. Вопервых, этих иероглифов нужно тысячи, и, во-вторых, чтобы пользоваться ими, приходится все время производить выбор, так как зачастую одно слово можно обозначить несколькими комбинациями иероглифов. А любая избыточность, если говорить о технических средствах, отягощает аппаратную реализацию, делает ее громоздкой и менее надежной. При первом профессиональном знакомстве с ЭВМ необходимо рассмотреть ее основные функции, для реализации которых и создавались специализированные группы команд. Но прежде всего нужно отметить, что все они реализуются посредством логических операций И, ИЛИ, НЕ и функции запоминания.
1.1 Классификация команд и архитектура ЭВМ 1.1.1 Команды передачи данных Аналогов два: а) загрузка данных: Ставите чемодан (данные=data) в камеру хранения (приемник=dst); комментарий dst:= data («:=» — присвоить); б) пересылка данных: посылка из почтового отделения города Оренбурга (источник=src) переправляется в город Челябинск (приемник=dst); что пересылается —не знаем, может воздух — это неважно. Комментарий: dst:= <src>, где <> - содержимое (в данном случае — содержимое источника). 1.1.2 Операционные команды Операционные команды есть арифметико-логические команды. Их набор стандартен: а) команды сложения и вычитания; б) логические команды И, ИЛИ, НЕ; в) команды сравнения. 1.1.3 Команды сдвигов и приращений Выполняют: а) сдвиги влево и вправо на один или несколько разрядов; различают логические и арифметические сдвиги (об этом позднее); б) увеличение и уменьшение на единицу; используются для организации счетчиков. 1.1.4 Команды ветвлений и переходов Сразу отметим, что ветвление — это тот же переход, только если выполнилось определенное условие. Например, если результат последней операции равен нулю, то перейти на указанное место (метку). Если нет, то ничего не делать и перейти к выполнению следующей команды. Результат (ноль или не ноль) хранится в специальном месте. Совокупность всевозможных результатов называется словом состояния процессора (PSW). 1.1.5 Команды ввода-вывода Самая малочисленная группа. Вводятся данные или выводятся данные — все по отношению к процессору. Вводятся, значит, процессор принимает 5
данные от внешнего устройства. Выводятся, внешнее устройство принимает данные от процессора. 1.1.6 Команды прерывания Представьте себе, что Вы читаете захватывающий детектив. И вдруг телефонный звонок. Что вы делаете? Первый вариант: игнорируете звонок (маскируете его). Второй вариант: вы вкладываете закладку на прерванном месте (чтобы оперативно возвратится туда), берете трубку, разговариваете. Возможно, за этим последуют еще какие-то действия, вызванные этим прерыванием, но потом вы опять возвращаетесь к прерванному занятию. Основные моменты этой процедуры: — Вы должны знать, куда вернуться из прерывания; — Вы должны знать, как обслужить прерывание, то есть где находится телефонный аппарат, чтобы быстро и безошибочно подойти к нему, а не к двери, приняв за телефонный звонок — звонок в дверь, и так далее. Именно эти два момента и отражены в реализации процедуры обработки прерываний в ЭВМ. Теперь рассмотрим команды в целом. Любая команда всегда начинается с кода операции (КОП). Код операции имеет длину, равную, как правило (хотя бывают исключения), формату данных процессора, то есть 1-му байту, 2-м байтам или 4-м байтам. Код операции —это набор управляющих функций цифрового автомата процессора (ЦА), который сам основан, как правило, на базе элементарного автомата Мура. Если КОП предусматривает использование одного или двух операндов, то они должны располагаться в запоминающем устройстве (ЗУ) следом, причем в той последовательности, в какой они будут востребованы процессором. Любое сообщение в ЭВМ представляется и обрабатывается побитно. Но написание программ в двоичных кодах просто бессмысленно из-за громоздкости и непроизводительности. Поэтому для обозначения двоичных комбинаций в ЭВМ используют их свертки в шестнадцатеричном коде (Н-коде). Один разряд этого кода поглощает сразу 4 двоичных разряда. А специальные трансляторы уже в ЭВМ превращают их в двоичные комбинации. Но даже такая форма для программиста, в случае написания больших программ, неприемлема. Это сколько кодов команд надо помнить! Поэтому каждая система команд дублируется машинным языком в ассемблере — языке простых аббревиатурных обозначений. Например, MOV A,B или MOV R1,R2. Здесь сокращение от MOVE (переслать) говорит о том, что в регистр A пересылается содержимое регистра B (фирма Intel). Или для второго случая: в регистр R2 пересылается содержимое регистра R1 (фирма DEC). Таким образом, остается лишь запомнить некоторые дополнительные обозначения, но их совсем немного. Можно привести еще ряд примеров: 6
ADD B,D (add —прибавить, сложить); SUB C,A (subtract —вычесть); AND A,D (and —И, т.е. конъюнкция); OR A,D (OR —ИЛИ, т.е. дизъюнкция); и так далее. Так получилось, что основой ассемблера во всем мире стал английский язык. А в 70-х годах у нас был свой ряд отечественных ЭВМ «Минск - ХХ»с превосходной системой команд, где ассемблер выглядел так: ВЫЧ Р1,Р2. Понятно, что что-то из чего вычитается. Но теперь все отечественные разработки сразу «разговаривают» на английском, для того, чтобы российская программная продукция не была ограничена только внутренним рынком. Итак, у каждого машинного двоичного кода команды есть его отображение в виде команды на ассемблере, на котором достаточно быстро можно научиться писать программы. Но кто же (или что) будет переводить из ассемблера в двоичные коды? Для этого есть специальные трансляторы (компиляторы). В данном пособии указанная процедура демонстрируется вручную, чтобы лучше понять предмет изучения. А теперь, когда проанализированы основные функции ЭВМ, рассмотрим структурную схему того, что уже можно назвать ЭВМ (рисунок 1). Поскольку ЭВМ создавалась по образу и подобию человека, то и мы попробуем характеризовать основные компоненты ЭВМ с этой, возможно не очень корректной, точки зрения. Итак, сердцем ЭВМ является процессор, основу которого составляет цифровой автомат ЦА. Он «разгадывает» очередной код операции и в соответствии с ним производит определенные действия со всеми составляющими ЭВМ. АЛУ тоже является частью цифрового автомата, но выделено отдельно, так как оно программно доступно относительно выбора операции: сложения, вычитания, конъюнкции, дизъюнкции и тому подобное. РОНы —локальная память малой емкости — сверхбыстродействующее ОЗУ. Реализовано, как правило, на триггерах, объединенных по 8, 16 или 32 шт. в регистры. Длина регистра зависит от длины слова, которым оперирует процессор. Размер информационного слова принято считать 1 байт (1 Byte)= 8 бит (8 Bite), то есть равным 8-и разрядам. Поэтому, в отношении процессора обычно оперируют терминами «однобайтовый», «двухбайтовый» и тому подобное. Процессор подсоединяется к системной шине (магистрали) как активное устройство (командир). Системная шина имеет множество разновидностей, но любые системные шины можно объективно разделить на два вида, так называемые Q-bus и MultiBus. Q-bus —шина со совмещенной шиной данных и адреса (ШДА). Что и в какой момент находится на ШДА —можно узнать только по определенным фронтам управляющих сигналов. Кроме этого, все запросы на прерывания и их инициирование происходят по последовательному протоколу. Если вернуться к рассмотренному примеру со звонком, то представьте себе не один, а несколько телефонных аппаратов, но с общим звонком. И чтобы найти, какой телефон 7
звонит, нужно последовательно снимать трубки, пока не будет обнаружен тот единственный. Q-bus считается наиболее совершенной системой шины, так как предусматривает очень надежный протокол установления связи с любым компонентом ЭВМ. Алгоритм его приведен на рисунке 2 – на примере вывода данных (из процессора в устройство). Процессор Арифметико-логическое устройство (АЛУ)
Регистры общего назначения (РОНы)
Данные
Цифровой автомат (ЦА)
Постоянное запоминающее устройство (ПЗУ)
Управление
Оперативное
запоминающее устройство (ОЗУ)
Код команды
К внешнему устройству №1
К внешнему К внешнему устройству устройству №i №n
Интерфейсное
Интерфейсное
устройство №1 (адаптер)
устройство №n (адаптер)
Регистр кода операции (РКОП) Шина управления (ШУ) Шина адреса (ША) Шина данных (ШД)
С и с т е м н а я м а г и с т р а л ь Рисунок 1 – Архитектура ЭВМ Вывод
Выставить адрес устройства на ШДА
Есть такой адресат?
Нет
Да Выставить данные на ШДА
Данные приняты?
Да Конец
8
Нет
Подпрограмма тяжелого останова
Рисунок 2 – Протокол шины Q-bus. MultiBus —системная шина с разделенными шинами данных ШД и адреса ША (рисунок 1). Кроме этого, все запросы на прерывание в MultiBus поступают радиально (то есть, параллельно). Если, к примеру, в ЭВМ предусматривается обработка 16 запросов на прерывание, то системная шина должна иметь в составе шины управления 16 проводников для этих запросов, а не 1, как это реализовано в Q-bus. И к сему, выдача процессором адреса и данных устройства не предусматривается, как это делается в Q-bus. Не предусматриваются подтверждение обнаружения устройства с установленным адресом и подтверждение приема этим устройством данных. Можно встретить иногда MultiBus с ответом распознавания адреса, но это скорее исключение, чем правило. Все дело в том, что системные шины живут и развиваются как бы сами по себе. Наилучший пример тому — железные дороги. Ширина колеи, высота рельсов, нагрузка на единицу площади, закругления и угол наклона на поворотах, габариты тоннелей, высота троллеи — все это уже навсегда, пока существует железнодорожное сообщение. Что-то здесь будет меняться, например, вместо деревянных шпал — железобетонные, но принципиально — никогда. Замечательно, что все разработки, будь то электровоз, дрезина, грузовой или пассажирский вагон и другие виды изделий транспортировки по рельсам могут бесконечно модернизироваться и даже создаваться новые, поскольку заранее известно, что «правила игры» остаются неизменными. В этом смысле консерватизм параметров железнодорожного пути является составляющей прогресса развития транспортных средств на железных дорогах. Все сказанное совершенно адекватно и к системным шинам Q-bus и MultiBus, не смотря на некоторые их очевидные недостатки. Подводя итог, можно сказать, что системная шина является кровеносной системой ЭВМ. Обязательным элементом ЭВМ является постоянное запоминающее устройство (ПЗУ). Все дело в том, что без ЗУ ЭВМ является устройством с «пустыми мозгами», а точнее — без них. Хотя бы для того, чтоб ЭВМ могла загрузить в себя чужой интеллект, нужна программа первоначальной загрузки с какого-либо внешнего устройства, например, с жесткого диска или компакт-диска. А для этого, как минимум, нужно настроить соответствующий адаптер, потом через него привести в исходное состояние дисковод, проверить область ОЗУ, куда будет загружаться этот самый интеллект в виде операционной системы, а затем только загрузить операционную систему. Вся описанная последовательность реализуется программой, защитой в ПЗУ, и называется программой инициализации (INIT). Следовательно, ПЗУ играет роль спинного мозга, который хранит программы рефлекторных, а не сознательных действий. ОЗУ же предназначен как для хранения выполняемых программ, так и результатов их выполнения. Кроме этого ОЗУ используется операционной сисемой для регистрации состояния практически всех составляющих узлов микропроцессорной системы. ОЗУ, как правило, по объему во много раз меньше, чем объем внешних носителей информации. И что удивительно, 9
незаметно стремление развивать объем ОЗУ до объема внешних носителей. Что это? Факт, отражающий реальное положение дел в этой области? Или опять философский подход к решению проблемы? Что человеческий мозг ограничен по емкости, а размеры книжных полок и их количество ограничивать теоретически нечем? Ну и, наконец, связь с внешним миром. Для того, чтобы это интеллектуальное устройство не было бы изолировано от внешнего мира, чтобы могло «слышать» и «видеть», «говорить» и «воздействовать», необходимо, как минимум, иметь входное и выходное интерфейсные устройства. Какие функции они реализуют? Их две. Во-первых, с одной стороны они должны полностью сопрягаться с системной шиной по протоколу системной шины, и с другой стороны – по протоколу внешнего устройства сопрягаться с внешним устройством. Протоколы установления связи и обмена для внешних устройств, как правило, стандартизованы: RS-232, Centronics, IRPR и так далее. Знакомство с ними произойдет при изучении соответствующих интерфейсных схем. Таким образом, интерфейсные устройства (схемы) играют роль переводчиков. Отсюда и название: интерфейс. Во-вторых, интерфейсное устройство должно быть согласовано по электрическим параметрам с обоими «разговаривающими». А эти сигналы бывают различными и по напряжению, и по мощности, и по составляющей помехе. Поэтому, интерфейсные интегральные схемы (ИИС), как правило, «обвязываются», то есть между ИИС и внешним устройством ставятся специальные приемники и передатчики. Это схемное решение: интерфейсная ИИС плюс обвязка —и называется адаптером. Теперь, когда в общих чертах обрисована структура и функции ЭВМ минимальной конфигурации, можно перейти к понятиям: однокристальный микропроцессор, микропроцессорный модуль, микропроцессорная секция (секционный микропроцессор), однокристальная ЭВМ.
1.2 Секционный микропроцессор. Вернемся к рисунку 1. Если из состава микропроцессора извлечь цифровой автомат, то микропроцессор превратится в микропроцессорную секцию со входами управления функциями АЛУ и чтением-записью РОНов. Проигрыш — отсутствует реализация команд. Выигрыш — можно самим реализовывать любую систему команд микропроцессора и обрабатывать любую длину слова (за 1 раз), так как синтезировать цифровой автомат предоставляется самим. Для секционных микропроцессоров даже существует такой термин: «Система команд пользователя».Типичные отечественные представители этого семейства: К581 — 8р.,16р. n-МОП; К583 — 8xn р. И2П; К588 — 16&n р. КМОП; К589 — 2&n р. ТТЛШ; К1800 — 4&n р. ЭСЛ; 10
К1804 — 4&n р. ТТЛШ; К1811 — 8&n р. n-МОП; Здесь первая буква и последующие цифры означают семейство микросхем микропроцессорного комплекта; цифра после тире – число разрядов в секции; «n» – множитель (целое число), показывающий возможное увеличение размера обрабатываемого слова; «р.» - разряд; последние буквы – тип технологии (например, ЭСЛ – эмиттерно-связанная логика). Однако, как показывает опыт, производители ЭВМ на секционных микропроцессорах (ряд ЭВМ СМ: г. Киев, г. Северодонецк — в Украине) все же реализуют известные системы команд. И это вполне понятно. Консерватизм в системе команд — это тоже путь к прогрессу в области программного продукта.
1.3 Однокристальный микропроцессор. Однокристальный микропроцессор это собственно все то, что входит в процессор (рисунок 1, ПРОЦЕССОР). Типичные представители: (США) (аналог, Россия) Intel 8085 (1821BM85), n-МОП; Zilog 80 (1858BM80), n-МОП; F11/34 (DEC) (1801BM3), n-МОП; MC 6800 (Motorola) (нет), n-МОП . F11/34 —микропроцессор фирмы Digital Equipment Corporation (DEC), с одной из самых лучших системой команд. Изготавливается по специальной вентильной технологии. Системная шина: Q-bus. Аналог в России —1801ВМ3. Как самый надежный из семейства однокристальных микропроцессоров (МП) используется в военной технике. Известные родоначальники персональных ЭВМ: — на основе МП F11 —ПЭВМ PDP-11 с операционной системой RT-11; — на основе МП МС6800 —ПЭВМ «Mackintosh» .
1.4 Микропроцессорный модуль. Этот термин совершенно не принципиальный. А появился он потому, что фирме Intel на определенном этапе не удалось вырастить очередной микропроцессор в одном кристалле. Представьте себе, что некто «вытащил» из процессора генераторную часть ЦА (рисунок 1) и часть ЦА, которая управляет системной шиной, и «обрезал» эти связи, оставив выводы этих связей наружи. Таким образом, получилось три кристалла, и, как следствие, три корпуса микросхем. Для одного из семейств Intel-8080 одна из них называется генератор-формирователь (8224), другая (8228) контроллер системной шиной (CONTROL — управление) и третья (8080) — остатки процессора, которую принято называть: микропроцессор. Понятно, что процессором это все может называться только тогда, когда все эти кристаллы соединятся соответственно «обрезанными» выводами в единое логическое устройство. Вот это все: 8224 & 8228 & 8080 и есть микропроцессорный модуль (МПМ). Так выглядит 11
родоначальник, составляющий основу популярного семейства компьютеров IBM PC на основе МПМ из четырех микросхем (кристаллов или чипов): Чип
Микропроцессорная система
8284 Известный базовый 16-разрядный PC/XT 8288 фирмы IBM с операционной системой MS-DOS 8086 фирмы Microsoft. 8087
1.5 Однокристальные ЭВМ (ОЭВМ). Пояснить, что такое ОЭВМ, оказывается, достаточно просто. Все, что составляет ЭВМ (рисунок 1), выращено на одном кристалле. Понятно, что по возможностям ОЭВМ уступают таким гигантам как F-11 или 8086. Но они и создаются для «мелких» целей и используются: для управления печатающим устройством, клавиатурой, изображением дисплея и тому подобное. Здесь преуспели фирмы Intel и Motorola. Самые популярные 8-и разрядные ОЭВМ: 8048 (1816РВЕ48), 8050, 8031,8051,8052. Номенклатура ОЭВМ велика и характеризуется большим разнообразием. Связано это с разработкой специализированных ОЭВМ для аудио- и видеотехники, техники связи, систем регулирования, информационноизмерительных систем и так далее. Появился целый класс ОЭВМ со встроенными ЦАП и АЦП, с элементами регулирования для следящих динамических систем, реализующие быстрые функциональные преобразования (например, преобразование Фурье) и так далее. В заключение представляется интересным провести обзор тенденций, существующих на момент издания пособия, в области разработок и производства средств микропроцессорной техники. Судя по приведенной в настоящей главе информации по микропроцессорам, все они разработаны и изготовлены в США. Значит ли это, что США — лидер в этой области? Анализ рынка интегральных схем показывает, что в области разработок больших интегральных схем лидируют Япония, Тайвань, подтягивается Южная Корея. Сегодняшний высокий технологический уровень в этой области в США поддерживают специалисты именно из этих стран. Европейцы, из-за необходимости платить высокую зарплату производственному персоналу, вообще не конкурентоспособны и в подавляющем случае покупают (или производят на дочерних фирмах) микропроцессорные комплекты в Азии. Особым образом дело обстоит в России. Имея высокий научнотехнический потенциал, но при отсутствии конкуренции и по причине закрытости все лучшие разработки малоизвестны и связаны, главным образом, с оборонным и космическим комплексом. Что касается западных микропроцессорных средств, то российские специалисты достаточно легко проникали в технологические тонкости и фирмы Intel, и фирмы DEC, и быстро осваивали производство копий интегральных схем или их аналогов для 12
внутренних нужд. Теперь, в связи с вхождением России в мировой рынок, нашим производителям необходимо или изобретать что-то свое, или покупать лицензии на необходимые технологии, или покупать дешевые комплектующие и осваивать производство ЭВМ. Сейчас на рынке России появились различные модификации компьютера ВИСТ-1000 с микропроцессорами, которые реализуют систему команд микропроцессора Pentium (AMD, Cyrix). Компьютеры собираются в г. Зеленограде, в ведущем в России предприятииразработчике ИС. Почти все большие ИС и блочные комплектующие приобретаются в Азии. Значит ли это, что принят третий вариант. Время покажет.
2 Состав команд и архитектура микропроцессора 8086 Микропроцессор 8086 не самый лучший и не самый надежный микропроцессор. Но он один из самых дешевых, как и весь его микропроцессорный комплект ИС, разработанный для создания единой микропроцессорной системы. Именно на этом комплекте были реализованы компьютеры IBM PС/ХТ, а так же некоторые отечественные компьютеры 80-х годов, такие, как ЕС-1841, ЕС-1843, Искра-1030.11 и другие. Для изучения микропроцессорных средств неважно, какой микропроцессор будет взят в качестве изучаемого объекта. Все они – братья-близнецы. И достаточно познакомиться с одним, чтоб иметь представление о других. Тем более, что во всех последующих поколениях — вплоть до Pentium-II, можно обнаружить все основные черты процессора 8086, как по структуре, так и по составу команд. Как уже отмечалось в предыдущей главе, микропроцессор 8086 является составной частью микропроцессорного модуля, состоящего из генератора-формирователя 8284 и контроллера системной шины 8288, и только микропроцессорный модуль является единым целым, то есть, процессором. При изучении подобных устройств рассматривают не структурную, и тем более, не функциональную схему, а архитектуру устройства — новый для технических средств термин. Архитектура —это такое представление устройства, которое демонстрирует функциональные возможности аппаратных средств (процессора, ОЭВМ или вообще ЭВМ) с точки зрения воздействия на них программных средств (то есть, последовательности команд). На рисунке 3 представлена архитектура микропроцессора 8086. Изучение можно начать с элементов, которые формируют физический адрес. Из рисунка 3 видно, что адресное пространство равно 220=1Мбайт (1 мегабайт). Почему адресное пространство измеряется в байтах? Дело в том, что в качестве элемента обмена информации вообще принято считать коды ASCII (отечественные аналоги —КОИ-7, КОИ-8 —соответственно 7-разрядные и 8-разрядные двоичные коды). Восьми разрядов вполне достаточно (28=256), чтобы закодировать латинский и русский (заглавный и строчный) алфавиты, цифры, знаки препинания, математические обозначения и специальные управляющие сигналы, как перевод каретки 13
(CR или ВВОД), перевод строки, звуковой сигнал и тому подобное. Ниже приведена таблица (таблица 1) для одной из альтернативных кодировок
символов для IBM совместимых компьютеров. Рисунок 3 – Архитектура МП модуля 8086 Поэтому любые носители: древние — перфолента, менее древние – магнитная лента, современные — магнитные поверхности дисков и лазерный диск (Cdisk) — все это запоминало и запоминает (то есть, записывает на себя) восьми разрядным кодом, то есть, байтом. А поскольку ПЗУ и ОЗУ —это те же носители информации, то и размер одного слова, записываемого по одному адресу, составляет 1 байт. Шина данных системной магистрали может быть 16-разрядной, 32-разрядной, но логическое обращение к памяти (через специальную схему — контроллер динамической памяти) всегда происходит так: по одному адресу — 1 байт. Вернемся к адресу. Из рисунка 3 видно, что формируется он своеобразно. При этом используется достаточно общепринятый прием. Это касается всех типов мощных микропроцессорных систем. Дело в том, что программы пишутся монолитом не более, чем 216=64 Кбайта. Действительно, просто трудно представить себе программу примерно в 20 тысяч команд. При написании такой программы разработчику ее просто не удержать в голове. Поэтому программу разбивают на отдельные фрагменты, каждый из которых 14
без напряжения укладывается в пространство 216=64 Кбайта. А потом все связывают главной (резидентной) программой. Таблица 1 —Коды символов ПЭВМ для внешних устройств Старший разряд
М л а д ш и й р а з р я д
код
0
0
NUL
1
2
3
4
SP 0
5
6
P
'
7
8
9
А
В
С
D
Е
F
p
A
Р
а
░
└
╨
р
Ё
q
B
С
б
▒
┴
╤
с
ё /
1
DCI
!
1
A
Q a
2
DC2
"
2
В
R
b
r
B
Т
в
▓
┬
╥
т
3
DC3
#
3
S
c
s
Г
У
г
│
├
╙
у
4
DC4
$
4
С D
T
d
t
Д
Ф
д
┤
─
╘
ф
5
%
5
E
U e
u
E
Х
е
╡
┼
╒
x
6
&
6
F
V f
v
Ж
Ц
ж
╢
╞
╓ ц
'
7
G
W g
w
3
Ч
з
╖
╟
╫ ч
( ) *
8 9 :
H I J
X h Y i Z j
x y z
И Ш И Щ К Ъ
и и к
± \
Л Ы М Ь
л м
╚ ╔ ╩ ╦
╪ ш ┘ щ ┌ ъ
k l
╕ ╣ ║ ╚ ╝
╠
m n — o
\ b
Н Э О Ю
н о
╜ ╬
═
п
┐
╧
7
BEL
8 9 A
BS HT LF
В С
VT FF
+ ,
; <
К • L /
D E
CR SO
.
= >
M / N ^
F
SI
/
?
O
CAN EM ESC
DEL П
Я
█ ▄
ы ь
▌ э ▐ ю ▀
я
SP
Так вот, регистры DI, SI, BP, SP, IP — 16-и разрядные регистры и, в зависимости от типа команд, являются источниками адреса ЕА или участвуют в формировании ЕА (ЕА —эффективный адрес) фрагментов программ. Их выходы мультиплексируются на шину A15...A0 (до сумматора). Программист, когда указывает те или иные адреса ЕА, имеет ввиду именно эти регистры. Самый важный адресный регистр — регистр IP — регистр-счетчик текущего адреса программы (программный счетчик). После выборки из ЗУ очередного кода операции какой-либо команды его содержимое автоматически увеличивается на «1», подготавливая тем самым выборку следующего операнда из ОЗУ. SP —указатель стека (Stack) — тоже адресный регистр-счетчик, только для специальной — стековой памяти. С этим регистром предстоит поближе познакомиться, когда будут изучаться стековая память и ее команды. BP — просто регистр адреса стековой памяти. Используется программно для перехвата <SP> и его временного хранения. Регистры SI и DI предназначены, главным образом, для использования в специальных — цепочных (или строковых) командах, когда, например, необходимо «переместить» массив данных из одного места ОЗУ (ПЗУ) в другое место ОЗУ. В этих цепочных командах SI хранит адрес источника данных (src), 15
а DI — адрес приемника данных (dst). При этом после каждой пересылки одного операнда их содержимое автоматически увеличивается (или уменьшается — это как задано направление), подготавливая адреса транспортировки очередного операнда. Другая группа регистров называется сегментной (RS) и тоже участвует в формировании физического адреса. Обычно в других мощных микропроцессорах, где адресное пространство от 1 Мбайт до 4 Гбайт, роль сегментного регистра выполняет регистр с одним именем. И это, в общем-то, достаточно. Но фирма Intel — не как все, и в данном микропроцессоре их четыре. Главное назначение сегментных регистров — расширение адресного пространства. Сегментные регистры — те же 16-разрядные регистры, как и адресные. Но их содержимое гораздо «тяжелее»: A19...A4. Физический адрес ОЗУ/ПЗУ автоматически вычисляется в результате следующего сложения: RS: A19A18A17A16A15A14A13A12A11A10A9A8A7A6A5A40 0 0 0 + ЕА: 0 0 0 0 A15A14A13A12A11A10A9A8A7A6A5A4A3A2A1A0 ——————————————————————————————————————— Add:A19A18A17A16A15A14A13A12A11A10A9A8A7A6A5A4A3A2A1A0 Для удобства, чтобы не писать длинные двоичные числа, далее будут использоваться их шестнадцатеричные свертки. Так, например, двоичное число 1110 1111 0010 1100 есть EF2C в шестнадцатеричном коде (Н-коде). (Рекомендуется иметь постоянно под рукой таблицу перевода десятичных чисел от «0» до «15» в двоичную и шестнадцатеричную формы). Следовательно, если в сегментном регистре находится число 1CDO, а ЕА= F156, то физический адрес на шине адреса системной магистрали будет: 1CDO + F156 ————— 2BE56 На рисунке 3 видно, что выходы сегментных регистров тоже мультиплексируются. Почему их четыре и когда они используются? Для начала необходимо обратить внимание, что последняя буква у них S, что значит — сегментный. Теперь разберемся с первыми буквами. C – command —командный. CS используется при формировании только выборок команд из ЗУ совместно с IP (указывают: CS:IP); S — stack — стековый. SS используется только при формировании адреса стековой памяти (стека) совместно с SP (указывают: SS:SP) или BP (SS:BP); D – data — данные. DS по умолчанию используется в пересылках данных между микропроцессором и ЗУ совместно с адресом ЕА этих данных, указанных прямо или косвенно в команде; ES — резервный сегментный регистр. На этом пока можно закончить знакомство с сегментными регистрами. 16
Далее, на рисунке 3 видно, что сегментные и адресные регистры доступны со стороны шины данных. А поставленные рядом с именами регистров числа — это номера (или адреса), на которые они (если они указаны в коде операции) должны откликаться. Следующая группа регистров: AX, BX, CX и DX. Из рисунка 3 следует, что они подключены к ВШД — внутренней шине данных, и что они могут функционировать как 16-разрядные регистры в количестве 4 штук или как 8-разрядные в количестве 8 штук. Размер регистра полностью определяется кодом операции команды. Рядом с именем регистра в скобках указан его номер (адрес). Эти регистры в командах используются самым различным образом. Поэтому они получили название: РОНы —регистры общего назначения. Правда, есть одно небольшое примечание: ввод-вывод данных осуществляется только через регистр AL (или AX), поэтому этот регистр еще иногда называют аккумулятором. Хотя для МП 8086 это совершенно нехарактерно. Дело в том, что МП 8086 «вырос» из МП 8080, а там регистр A используется как накопитель результата всех арифметико-логических операций. Следующий элемент архитектуры: АЛУ — арифметико-логическое устройство. Все АЛУ различных типов микропроцессоров в функциональном отношении практически не отличаются друг от друга. Они реализуют, как правило, до 8 функций: сложение, вычитание и логические операции. Как следует из рисунка 3, результат АЛУ выдается на ВШД, а это значит, что приемником результата может быть практически любой регистр МП и шина данных (это для ОЗУ). Кроме этого, выход АЛУ 6-ю разрядами подключен еще к одному регистру — регистру флагов F. Слово «флаг» в данном случае жаргонное слово. По смыслу, в этом регистре хранится слово состояния процессора (PSW — processor status word), где каждый из разрядов регистра F хранит результат какой-либо операции или указание для действия определенной команды. Забегая вперед, можно привести пример: если в результате сложения получился ноль, то разряд ZF (флаг ZF) установится в «1». Или, если флаг IF установлен в «0», то будут запрещены все аппаратные прерывания. Каждый флаг (или чаще говорят: флажок), что называется, на вес золота. Если число РОНов может быть больше или меньше, то каждый флаг строго индивидуален и его появление вызвано только необходимостью запомнить нужную особенность результата, полученную при выполнении команды АЛУ. Подробнее о флаговом регистре — далее. А пока о той части флагов, которые устанавливаются результатами арифметико-логических операций. CF — устанавливается в единицу (взводится), если произошло переполнение формата. Например, складываются два байта (слова), и происходит переполнение: старший разряд суммы выпадает за пределы байта (слова). Чтобы его не потерять (как в школе учили: 8+7 — пишем 5 и один держим в уме), он автоматически попадает в СF. PF — устанавливается, если двоичное число в младшем байте состоит из четного числа единиц. Используется для контроля ввода-вывода. Дело в том, 17
что коды обмена информации в каналах связи — КОИ-7 (7 разрядов), поэтому для надежности 8-й бит (старший) дополняют до четного или нечетного (говорят: контроль по чету или нечету) числа единиц в байте. И в случае потери одного бита нарушается четность или нечетность, и эту ситуацию — по изменению флага PF — можно сразу зафиксировать. AF —флаг переполнения, но только младшей тетрады байта. Используется при сложении чисел, представленных в двоично-десятичной форме. ZF —флаг нуля, или нулевого результата. Если ZF:=1 (взвелся), то это значит, что получен результат, равный нулю. SF — флаг, а точнее бит знака. Дело в том, что если число представлено со знаком, то под его место отводится всегда старший бит. Если это байт, то D7, если слово, то — D15. Но поскольку микропроцессор не знает, что текущий результат со знаком или без знака, он («на всякий случай») автоматически запоминает старший бит байта (слова), полученного в результате арифметикологической операции. («0» - это «+», «1» - это «-»). OF — флаг арифметического переполнения; подразумевается, что число со знаком. И если мантисса полученного результата «наезжает» на знаковый бит, то OF=1. Алгоритм контроля достаточно прозрачен: если (+) + (+) = (-), то OF=1 (так как при сложении положительных чисел сумма должна быть положительной, а иначе — произошло арифметическое переполнение: мантисса числа увеличилась настолько, что «затерла» знак числа). Или: (-)+(-) = =(+), то OF=1 (то есть, наоборот). Аналогично и для вычитания. С остальными флагами: IF, DF, TF, которые устанавливаются программно, можно будет познакомиться по мере изучения соответствующих команд. Теперь можно перейти к центральному элементу микропроцессорного модуля — цифровому автомату (ЦА). Главная его функция заключается в том, чтобы выполнить алгоритм (определенную последовательность действий) согласно коду операции (который на все время выполнения команды хранится в регистре кода операции (РКОП)), и по окончании команды загрузить в РКОП код операции следующей команды. Рассмотрим кратко все управляющие сигналы, с помощью которых микропроцессорный модуль «общается» с системной шиной: — MW (-MEMWR) — строб записи; используется в системной шине в качестве строба записи информации, выводимой из МП в ОЗУ. — MR (-MEMRD) —строб чтения; используется в системной шине в качестве сигнала подключения на время длительности строба выхода какоголибо элемента ОЗУ к шине данных ШД. По заднему фронту информация на ШД фиксируется в МП. — IOW (-IOWR) — то же самое, что и -MW, только в отношении интерфейсных схем. — IOR (-IORD) — то же самое, что и -MR, только в отношении интерфейсных схем. — INT (-INTR) —запрос от внешнего устройства срочно его обслужить (запрос на прерывание). Микропроцессор, выполнив до конца текущую 18
команду, перейдет к процедуре обслуживания прерывания, если есть на то разрешение (IF=1). — INTA — строб чтения вектора прерывания (начальной метки подпрограммы обработки прерываний) из регистра векторов (контроллера прерывания). Вектора заносятся программно после того, как становится известным, где в ОЗУ/ПЗУ располагаются те или иные подпрограммы обработки прерываний. Этот строб подключает выход регистра векторов (контроллера прерываний) к шине данных. — HOLD — запрос от какого-либо устройства к микропроцессору — отдать ему на время всю системную шину (например, от второго процессора). Микропроцессор, выполнив до конца текущую команду, переходит в 3-е состояние (отключается от системной шины). — HLDA — сообщение внешнему устройству: «Я обнаружил HOLD и перешел в 3-е состояние; можешь забирать системную шину». — RDY — сигнал разрешения генерации тактовых импульсов. Необходимо отметить, что внутри цифрового автомата находится кварцевый генератор, вырабатывающий сигнал OSC с частотой 14,31818НГц. Этот генератор работает непрерывно. Сигнал с генератора делится на 3, образуя сигнал CLK с тактовой частотой 4,772727...МГц, который: а) выводится наружу на системную шину и может использоваться для различных целей (для таймера, последовательного интерфейса и так далее); б) через схему «И» подается непосредственно на тактируемые входы цифрового автомата; на второй вход схемы «И» подается RDY. Отключение этого сигнала позволяет «заморозить» на некоторое время выполнение команды в нужном месте ее выполнения (стоп-кадр). Это дает возможность сопрягать во времени «быстрый» процессор с «медленным» устройством, растянув во времени, например, строб -IOW или строб -IOR на несколько тактов, чтобы интерфейсная схема успела скоммутироваться с шиной данных. RES — сигнал сброса МП в исходное состояние. При подаче этого сигнала на вход МП последний переходит в 3-е состояние (все выводы переходят в высокоомное состояние). В момент снятия сброса происходят следующие действия: CS:=FFFF, IP:=0000. Затем происходит ввод содержимого шины данных в РКОП и начинается первое действие. Следовательно, по адресу FFFF:0000 должна располагаться первая команда самой первой программы, приводящей всю микропроцессорную систему (МПС) в исходное состояние. Поэтому, этот адрес принадлежит ПЗУ. А программа, приводящая МПС в исходное состояние, называется программой инициализации, а сам процесс — инициализацией (INIT). С элементами инициализации будет возможность познакомиться при изучении интерфейсных схем. А теперь можно перейти к форматам команд микропроцессора 8086. Размер команды зависит от функции, которая закладывается в команду. Этот размер находится в пределах от 1-го байта до 6-и байт. Сама команда разделяется на код операции (набор управляющих функций для цифрового автомата) и возможных одного или двух операндов, следующих за кодом операции. Все это в ЗУ должно располагаться последовательно с 19
нарастанием адреса (рисунок 4). В чем заключается процесс выборки? Сначала МП загружает в РКОП КОП 1-й команды, и цифровой автомат начинает выполнять алгоритм этого КОПа. По нему ЦА распознает, что прежде, чем выполнять команду, для ее выполнения надо выбрать еще 1 байт данных из ЗУ по адресу i+1. После этого ЦА подготавливает выборку следующего кода операции: IP:=
+1=i+2 —и выполняет выбранную команду. После выполнения 1-й команды МП загружает байт данных из ЗУ по адресу, хранящемуся в IP (там i+2) в регистр кода операции. И начинается выполнение следующей команды. И так далее.
Рисунок 4 —Расположение команд в ЗУ Следовательно, с нашей стороны (со стороны пользователя) требуется только быть внимательным и правильно расположить команды в ОЗУ. В заключение необходимо отметить, что при написании программ на языках высокого уровня (PL, PASCAL, FORTRAN, CИ и т.п.) программист не видит, как трансляторы этих языков превращают (транслируют) составленные программы в последовательность команд в машинных кодах (то есть, на машинном языке). Такие программы, как правило, получаются громоздкими. Дело в том, что одна команда PRINT, например, на Бейсике реализуется программой на ассемблере из 14— команд, где указываются и адреса источника выводимого массива на печать, и адреса портов, к которым подключен принтер. При этом программа реализует последовательность действий по протоколу обмена данными CENTRONCS с принтером. Программа, выполняющая то же действие и написанная на машинном языке, проще и меньше объемом. Но написание программ на машинном языке (ассемблере) требует превосходного знания не только самого языка, но и параметров микропроцессорной системы. Именно эту цель преследует данное учебное пособие, и следующие его главы позволят ознакомиться с системой команд МП 8086, некоторыми интерфейсными схемами и с примерами составления программ на ассемблере. 20
3 Команды пересылки и загрузки. Способы адресации. Перед тем, как приступить к изучению команд МП 8086, целесообразно определить границы состава команд МП 8086, которые не следует переходить. Дело в том, что МП 8086 имеет множество дублирующих друг друга команд. Это связано с тем, что МП 8086 «вырос» из МП 8080, и разработчики сохранили в 86-м процессоре до 70% состава команд 80-го процессора. А 80-й процессор — однобайтовый. Это решение фирмы Intel никак нельзя назвать удачным. Поэтому есть смысл изучить прежде всего команды 86-го процессора как 16-разрядного МП. Далее необходимо отметить еще одну проблему, которая заключается в том, что этих команд набирается свыше 4000. И если их все изучать по одной, то на это может уйти много времени. Наиболее эффективный метод изучения команд —комплексный, на основе объединения однотипных по коду операции (КОП) команд и синтеза КОП и команд в целом, как в машинных кодах так и в ассемблере. При этом полезно еще раз показать обоснованность использования дублирующего машинные команды и, на первый взгляд, искусственного языка ассемблера. Чтобы выявить разницу между машинным кодом команды и ассемблером этой же команды, рассмотрим следующий пример. Как люди общаются друг с другом? Звуком, то есть акустическими волнами, которые представляют собой сигнал со сложным спектром. Это аналог машинного кода. Со временем человечество сообразило, что таким сложным физическим процессом оперировать можно только в очень ограниченных случаях. И придумало для каждого звука его «ассемблер» (assemble - собирать, монтировать), то есть букву — графический символ. Этому «ассемблеру» нас учат сразу с детских лет, чтобы мы могли общаться и развиваться, не ограничиваясь только использованием звука. Представить трудно, сколько было бы проблем, и где бы было сегодня человечество, если бы не придумали этот удобный заменитель звуковому сообщению. Так и в ЭВМ для каждой индивидуальной и, как правило, сложной совокупности логических действий придумали простое и понятное обозначение. В чем же оно заключается? Пусть, например, необходимо из пункта А в пункт В переслать то, что хранится в пункте А. Принятое обозначение комментария в краткой форме: В:= <А>, т.е. В присвоить содержимое А. Или: <А> В, то есть содержимое А переслать в В. Итак, А и В — это, собственно, источник (src) и приемник (dst) сообщений (не физического предмета). Вопрос: а что остается в А? А то же, что и было; потому что, если один абонент передал другому сообщение, то теперь этим сообщением владеют оба. Классически на ассемблере это обозначают: MOV A,B (сокращенное от move —переместить). Именно такой ассемблер у многих микропроцессоров и ОЭВМ. Но фирма Intel (вероятно, чтобы не иметь проблем с авторскими правами), решила это сделать так: 21
MOV B,A Таким образом, у нас в команде пересылки первым будет указываться приемник, а вторым (через запятую) — источник. Но это не существенно. Главное, что таким образом гораздо удобнее и писать программу, и читать ее. Теперь вернемся к машинным кодам МП 8086. Команда (основная) состоит из кода операции (16 разрядов) и, если того требует КОП, одного или двух операндов, стоящих вслед за КОПом в последовательности, согласно их востребованию. Отсюда следует, что главное — это знать все о самом коде операции, а их два вида: 1) для двух абонентов (mov a,b); 2) для одного абонента (mov a,data). Во втором случае только один абонент, и, судя по его месту в команде, он приемник (dst). А вторым операндом являются данные, которые нужно заслать в dst. Итак, как же выглядят коды операции для этих двух случаев, но не только для команд MOV, а вообще для 16-разрядных КОП? Рассмотрим эти два типа: 1) для dst и rsc:
2) только с dst:
Из обоих форматов следует, что у них есть некая общая (универсальная) часть и совершенно индивидуальная —микрокод операции (микроКОП), который собственно и делает один тип команд отличным от других типов. Займемся пока общей частью. Видно, что она достаточно запутана.
22
3.1 Тип кода операции с dst и rsc По формату КОП видно, что расположение dst и src такое же, как и в ассемблере: слева приемник (dst), справа источник (src). В простеньких микропроцессорах фирмы Intel так и было. Но в этом микропроцессоре, чтобы придать ему такие же мощные формы адресации операндов, как у микропроцессоров фирм DEC или Motorola, к dst (разряды D7, D6) «прилепили» расширение (разряды D2..D0). А для источника (разряды D5..D3) оставили по-прежнему скромные возможности: это адрес (или номер) одного из 8-ми регистров МП. Вот с него и начнем. Посмотрим на архитектуру МП 8086 (рисунок 3), на адреса регистров. Видно, что здесь есть элементы с одинаковыми адресами. Например, регистр DI имеет адрес 1112, и регистр BH имеет тот же адрес. Единственная разница в том, что DI —16-разрядный регистр, а BH —8-разрядный. Значит, в КОП должен быть предусмотрен отличительный признак байта или слова. Это разряд D8 (W — word — слово). Для него возможны следующие случаи: а) W= 0 — значит, что все адреса касаются однобайтовых данных; б) W= 1 — значит, что все адреса имеют отношение к словам. Не помешает напомнить, что байт — 8 разрядов, а слово — это 2 байта, то есть 16 разрядов. Следовательно, для нашего примера, если D8=0 (W=0), то src есть BH; а если D8=1 (W=1), то src есть DI, то есть совсем другой и уже 16-и разрядный регистр. Теперь, что касается dst. Здесь несколько сложнее. Под адрес dst отведено 5 разрядов. Следовательно, число вариантов 25=32. Из формата видим, что основой адресации dst является mod (D7,D6) (moda — модификация). Глядя на расширение dst, обнаруживаем, что возможны принципиально только два варианта: приемник — это или регистр микропроцессора (reg), или элемент ЗУ (mem - MEMORY — память). 1-й вариант Приемником является регистр (reg); в этом случае mod=11. Выделим этот вариант в виде таблицы 2: Таблица 2 mod dst 11 reg Номера регистров в поле D2..D0 определяются точно так же, как для src. 2-й вариант Приемником является элемент ЗУ (ОЗУ или ПЗУ). Здесь возможны 24 подварианта. Их можно объединить в 7 глобальных групп (собственно, это и является главным критерием). Для mod после таблицы 2 осталось 3 комбинации: 002, 012, 102. Составим соответствующую этим комбинациям таблицу, где число столбцов будет 3, а число строк —23=8 (комбинации в D2..D0). В координатных клетках обозначим уравнение адреса EA, то есть как он складывается (EA —эффективный адрес без учета сегментного регистра). В таблице 3 выделены глобальные группы в количестве 6 штук. Они определяются комбинациями разрядов D7, D6 и D2. Кроме этого, в таблице 23
специально выделено место, которое является исключением из правил. Данный вид адресации называется прямым. Вообще, по отношению к способам адресации установилась некая терминология. Непосредственная адресация: адрес «запрятан» в коде операции. Очевидный пример: mod=11, значит dst — регистр, номер которого указывается в КОПе (в разрядах D2..D0). Прямая адресация. Следом за КОПом должен следовать адрес ячейки памяти (сначала младший байт, затем —старший). Таким образом, в машинном коде сразу виден адрес dst. В таблице 3: mod=00, seg/mem=110. Косвенная адресация. В коде операции указывается источник (хранилище) адреса ячейки памяти. Пример тому —место в таблице 3: mod=00, reg/mem=100, 101, 111. Во всех этих случаях адрес dst автоматически будет извлекаться из регистра SI, или DI, или BX. Значит, прежде чем обратиться к ячейке памяти, адрес этой ячейки надо загрузить в соответствующий регистр. Иначе получится на «деревню к дедушке». Таблица 3 —Формирование эффективного адреса dst (mod 7- 011) Reg/mem D2 D1 D0 00 0 0 0 EA=+<SI> 0 0 1 EA=+ 0 1 0 EA=+<SI> 0 1 1 EA=+ 1 0 0 EA=<SI> 1 0 1 EA= Прямая адресация 1 1 0 EA=адрес(2 байт) 1 1 1 EA=
mod (D7,D6) 01 EA=+<SI>+см.1б EA=++см.1б EA=+<SI>+см.1б EA=++см.1б EA=<SI>+см.1б EA=+см.1б
10 EA=+<SI>+см.2б EA=++см.2б EA=+<SI>+см.2б EA=++см.2б EA=<SI>+см.2б EA=+см.2б
EA=+см.1б
EA=+см.2б
EA=+см.1б
EA=+см.2б
Относительная адресация. В этом случае вместо прямого адреса следом за кодом операции располагают смещение (disp). Это смещение (в таблице 3 обозначено: см.) складывается с текущим адресом, который может храниться в IP, BP, BX, SI, DI. Причем, это смещение со знаком (старший разряд выступает в качестве знакового бита), поскольку смещение может быть как вперед, так и назад, и в дополнительном коде. Еще раз следует отметить, что положительные числа со знаком в прямом и дополнительном кодах совпадают, а отрицательное число в прямом коде преобразуют в дополнительный инверсией его (знак не меняют) и добавлением к результату единицы. Все эти четыре способа — классика. А далее возможны комбинации из этих способов со смещениями, что и следует из таблицы 3 для МП 8086. Здесь смещение может быть коротким (см. 1б. – смещение размером в один байт) со знаком в D7 и в дополнительном коде, или нормальным (см. 2б – смещение размером в два байта) со знаком в D15 и тоже в дополнительном коде. И конечный адрес в самом сложном случае может формироваться как сумма двух регистров и смещения (смотрите mod=01, mod=10, и reg/mem=000...011). 24
Ниже будет представлено несколько примеров на конкретной команде, но окончательно все способы адресации к ячейке ЗУ можно твердо освоить только после соответствующих практических занятий по синтезу кодов команд и ассемблера этих команд, и при выполнении этих команд на учебно-отладочном устройстве. Теперь последний штрих к представленному материалу. Если проанализировать представленный выше формат команд, то выходит, что если приемником (dst) может быть или регистр МП, или ячейка ЗУ, то источником (src) —только регистр. Получается, что невозможно источником сделать ячейку памяти? Вот для того, чтобы это можно было сделать, в КОПе отводится еще один разряд D9 для изменения направления пересылки (d — down — вниз, обратно). Если d=0, то направление не меняется: dst остается приемником, а src — источником. Если же d=1, то направление переворачивается в обратную сторону, то есть src — становится приемником, а dst —источником. И все равно остается проблема: как просто переслать данные из одной ячейки ЗУ в другую ячейку ЗУ? Только через регистр МП с помощью двух команд? Получается, что так. Можно только сожалеть, что столько сложностей при формировании КОП, а подобную пересылку с помощью одной команды выполнить невозможно.
3.2 Тип кода операции с dst. Группа коман MOV По формату КОП видно, что расположение dst и формирование его точно такое же, как и в первом типе формата. Поэтому все выше изложенное справедливо и для этого типа формата команд. Из-за отсутствия src три разряда D5..D3 используются в качестве расширения КОП. КОП также поглотил и разряд D9, поскольку при одном абоненте об изменении направления пересылки говорить бессмысленно. Теперь можно перейти к командам. Команда: MOV dst,src КОП команды MOV: микро КОП
Рассмотрим пару примеров по синтезу ассемблера и машинного кода. Пример 1 — Переслать содержимое регистра BL в регистр AL. Кратко: AL:=. Ответ: а) ассемблер: MOV AL,BL; б) машинный код: w=0 (1 байт); d=0 (направление не меняется); 25
src=011 (адрес регистра BL — из рисунка 3); dst=11 000 (mod =11— из таблицы 2; reg/mem=reg=000 — адрес регистра AL — из рисунка 3). Составляем КОП:
Разбиваем КОП на тетрады и переводим в H-код (шестнадцатеричный код). Получается, что вся команда состоит из одного КОПа 88D8, так как адресация src и dst —непосредственная. Пример 2 —Отправить в ячейку памяти с адресом 1FC0 содержимое регистра CL. Кратко: M1FC0:= (М —от MEMORY — память); Ответ: а) ассемблер: MOV [1FC0],CL (в квадратных скобках указывается или адрес — при прямой адресации, или источник адреса — при косвенной адресации, или источник плюс смещение, или источник плюс источник плюс смещение — при комбинационной адресации); б) машинный код: w=0; d=0; src=001; dst=[mod=00; reg/mem=110]; составляем КОП:
Разбиваем на тетрады и получаем КОП=880E. А вся команда будет выглядеть так: 88 0E CO 1F. Поскольку команда располагается в ЗУ по адрес нарастающей адреса:
то можно заметить, что многобайтовое число в ЗУ располагается таким образом: младшая часть располагается по младшему адресу, старшая часть —по старшему адресу. Это правило справедливо для всех типов микропроцессоров. 26
Следующая команда — команда загрузки данных в приемник: MOV dst,data Формат команды:
Рассмотрим пример. Пример 3 —Данные 5С отправить в ячейку памяти с адресом 1FC0. Кратко: M1FC0:=5C. Ответ: 1) длина пересылаемых данных —1 байт; 2) ассемблер: MOV BYTE [1FC0],5C (byte —байт —длина данных; обязательно нужно указывать, если dst —память); 3) машинный код: w=0, dst=00 110 (mod=00, reg/mem=110); составляем КОП:
Разбиваем на тетрады и записываем КОП в H-коде: C6 06, и команду в целом: C6 06 C0 1F 5C . адрес данные Еще один пример. Пример 4 — Необходимо переслать два байта в две ячейки памяти: M1FC0:=6D, M1FC1:=5A. Ответ: поскольку МП 8086 —16-разрядный, и учитывая, что байты отправляются в две соседние ячейки ЗУ, оформляем это следующим образом: 1) ассемблер: MOV WORD [IFC0],5A6D (word —слово, то есть 2 байта: смотрите пример 3). В команде число 5A6D пишется как единое число, и поскольку 5A располагается по адресу 1FC1, то в 16-разрядном числе оно и является старшим (как уже отмечалось выше), а 6D —младшим. А вот адрес в команде можно указывать только один. Поэтому принято во всех видах микропроцессоров для многобайтового слова указывать адрес только младшей его части. 27
Код операции C7 06, а весь машинный код: C7 06 C0 1F 6D 5A. адрес данные Это самая длинная команда в МП 8086. Ко всему, что рассмотрено, следует добавить, что обращение к каждой указанной ячейке памяти будет производиться (по умолчанию) в текущем сегменте DS. Но как быть, если надо указать непосредственно физический адрес, ну, допустим А=3B8D0? В этом случае необходимо разделить (по своему усмотрению, если нет других условий) сегмент и текущий адрес в сегменте. Пусть DS=3B00. Тогда EA = 3B8D0 3В00 08D0 — текущий адрес внутри сегмента (эффективный адрес). Если известно, как переслать данные по адресу EA внутри сегмента, то как обратится к физическому адресу? Ведь нужно еще и загрузить значение сегмента данных в DS: DS:=3B00. Для этих целей разработана специальная группа команд — сегментные команды. Обозначим сегментный регистр (их четыре) обобщенным обозначением RS. 1) MOV RS,dst; Комментарий: RS:= . Формат кода операции: 2) MOV dst,RS; Комментарий: dst:= ; Формат кода операции:
28
Из обоих форматов видно, что пересылка из RS или в RS отличается только первым байтом КОП. Рассмотрим пример. Пример 5 —Необходимо выполнить действие: M3B8D0:=. Ответ: распишем последовательность действий: 1) в любой регистр (кроме AX) загрузим данные для DS; пусть это будет CX: CX:=3B00; 2) перешлем: DS:= ; 3) перешлем: MDS:EA = M3B00:8D0 = M3B8D0 = . И пусть эта последовательность команд будет расположена с адреса 0100 (адрес — в H-коде). Адрес 0100 0101 0102 0103 0104 0105 0106 0107 0108 0109
Машинный код C7 C1 00 3B 8E D9 88 06 D0 08
Ассемблер MOV CX,3B00
Комментарий В регистр CX загрузить данные 3B00
MOV DS,CX
В сегментный регистр DS переслать содержимое CX Загрузить в ячейку памяти с адресом DS:08D0=3B8D0 содержимое AL
MOV [08D0],AL
КОП только второй команды с сегментным регистром. Собственно говоря, типы первой и третьей команды уже рассматривались, поэтому составим только его вторую часть (2-й байт). Из архитектуры МП (рисунок 3) определяем номер DS: № DS= 112.
Переводим вторую половину КОП в H-код: D9; а весь КОП=8E D9.
29
4 Организация стековой памяти Эта небольшая глава посвящена стековой памяти (или просто — стеку) и ее командам. Стек (stack) —это специально организованное оперативное запоминающее устройство. Оно, как правило, располагается в ОЗУ и там занимает то место, которое ему отводит пользователь. Стек — память безадресная. Под термином «безадресная» подразумевается, что в команде не указывается — ни прямо, ни косвенно — адрес ячейки стека. На самом деле источником адреса является SP — регистр-счетчик адреса стековой памяти, или просто — указатель стека. Его содержимое указывает всегда на адрес последней записи в стеке. Слово стековой памяти — двухбайтовое, поэтому в ОЗУ оно занимает две соседние ячейки памяти. Причем, по старшему адресу располагается старший байт слова стека. Как же она организована? Общая идея такова: это память магазинного типа (например, магазин автомата Калашникова). Если мы пишем (то есть заправляем патроны), то после записи видим только последнее записанное слово. Если читаем (разряжаем магазин), то только в обратном порядке. И ту запись, которую зарядили первой, сможем достать только последней. И если последним зашел, то первым выйдешь (LIFO). Такая память действительно быстрая — не надо искать ни улицу, ни дом, ни квартиру. Но зато пользователю всегда надо помнить, в какой последовательности он закладывал в стек данные, чтобы потом ничего не перепутать. Теперь о другой особенности стековой памяти, только уже микропроцессорных систем. Как уже отмечалось, при выполнении команды содержимое IP увеличивается, подготавливая к выборке из ОЗУ код следующей команды. Поэтому программы начинают располагаться с одного края ОЗУ, со стороны младших адресов. Как следствие, стек задумано располагать с другой стороны ОЗУ, со стороны старших адресов. А если так, то при записи в стек вершина стека (последняя запись), адрес которой хранится в SP, будет «расти» вниз. Поэтому такой стек называют стеком с отрицательной вершиной. А теперь рассмотрим динамику записи и чтения (рисунок 5). а) Запись в стек. Записанное слово расположится: старший байт — по адресу i-1, младший байт — по адресу i-2. Указатель стека SP = i-2 и указывает уже на новую вершину стека. б) Чтение из стека. После чтения содержимого ячеек с адресами i-2 и i-1 указатель стека будет иметь значение: SP = i. Если сделать еще одно чтение стека, то после чтения SP = i+2, и вершина стека передвинется на адрес i+2 (хотя там может ничего и не быть). Стековая память контролируется только самим пользователем. Рассмотрим команды стековой памяти: ассемблер и коды операций команд стека. 30
1) Запись в стек. а) Ассемблер: PUSH dst; Комментарий: Stack:=. Примечание – dst —только двухбайтовый источник, так как слова стековой памяти —двухбайтовые.
Рисунок 5 —Организация стека б) Машинный код операции:
2) Чтение из стека. а) Ассемблер: POP dst; комментарий: dst:=<Stack>. Примечание – dst —только двухбайтовый приемник. б) Машинный код операции:
31
Рассмотрим пример. Пример — Составить команду: Stack:=. Ответ: а) Ассемблер: PUSH DX. б) Машинный код:
Адресную часть dst КОПа составляем по аналогии с примерами, приведенными в главе 3. Получаем после перевода в H-код: FFF2. Существуют стековые команды и для сегментных регистров. 1) Запись в стек: Stack:=. а) Ассемблер: PUSH RS; б) Машинный код:
2) Чтение стека: RS:=<Stack>. а) Асеемблер: POP RS; б) Машинный код:
Физический адрес стека определяется, как уже отмечалось в главе 2, следующим образом: A:=SS:SP. Следовательно, основание стековой памяти (когда еще не было сделано ни одной записи) назначается так: сначала значение сегмента SS, а затем значение SP. Как это делается — было уже рассмотрено в примере с определением физического адреса для пересылки данных (глава 3, пример 5). Подводя итог, следует заметить, что далее уже не будет столько внимания уделяться синтезу КОП, а основное внимание будет уделено 32
изучению результатов действия специальных групп команд, таких как: декремент, инкремент, сдвиг, команды АЛУ, ветвлений, ввода-вывода и прерываний.
33
5 Команды сдвигов и приращений. 5.1 Команды приращений Начнем изучение указанной группы команд с наиболее простой. Это команды приращений (команды инкремента-декремента) dst. Суть действия этих команд: dsr:=+1, если была команда инкремента; dst:=-1, если была команда декремента. Эти команды существуют для перебора адресов данных, для организации счетчиков и воздействуют своими результатами на флажки, кроме CF. То, что сохраняется CF —это сделано специально. Дело в том, что счетчики функционально реализованы как генераторы кодов двоичных чисел. Сколько, например, может быть комбинаций у двухразрядного реверсивного счетчика? 22=4. Нарисуем диаграмму его
состояний (состояния представлены в двоичном коде): Рисунок 6 Суть этого автомата — организовать переход от одного состояния счетчика к последующему. Поэтому арифметического действия здесь нет, и переполнения быть не может, а значит и не может быть воздействия на флажок переполнения (CF). Он остается неизменным. В том числе, когда есть переход от 11 к 00 или наоборот. 1) Команда инкремента. а) Ассемблер: INC dst; Комментарий: dst:=+1. б) Машинный КОП:
2) Команды декремента. а) Ассемблер: DEC dst; Комментарий: dst:=-1. б) Машинный КОП: 34
Пример 1 — Пусть в ячейке ОЗУ с адресом 1FD5 находится значение FF. Эту ячейку необходимо обнулить. Ответ: Составляем команду инкремента: INC BYTE [1FD5] После выполнения этой команды в заданной ячейке памяти: FF+1=00. Пример 2 — Пусть в регистре CX все биты находятся в состоянии «0», то есть =0000. Ответ: Применим к нему команду DEC CX. После выполнения команды в CX будет FFFF, то есть все биты будут установлены в «1». Эти примеры показывают, что при выполнении команд INC dst и DEC dst у счетчика нет крайних комбинаций, так как цикл является замкнутым.
5.2 Команды сдвига МП 8086 реализует 8 типов сдвигов. Эти 8 типов делятся на 2 группы: 1) логические сдвиги; 2) арифметические сдвиги. Давайте сначала разберемся с характеристиками этих сдвигов. 1) Логический сдвиг. Главная его отличительная особенность – цикличность (неразрывность) сдвигаемого слова. Например:
2) Арифметический сдвиг. Главная отличительная собенность – заполнение освобождающихся при сдвиге разрядов нулями (правда, есть исключение, но об этом чуть ниже). Это необходимо, например, для умножения: 46 Х 32 92 35
138* 1472 Здесь второе произведение, поскольку оно умножается на 30, сдвигаем влево на 1 десятичный разряд, а на место * мы должны поставить 0. Но так как нас этому не учили, мы его и не ставим (потому что этот ноль ничего не значит в общей сумме). Но в алгоритме арифметического сдвига этот ноль должен появляться безусловно. Чтобы не рассматривать 8 форматов КОП команд, обобщим их в
один: В таблице 4 приведены ассемблеры всех команд сдвига с комментариями ввиде схем. Из формата КОП следует, что появился некий новый признак V(D9). Таблица 4 —Команды сдвига
36
Дело в том, что МП 8086 может выполнить сдвиг на один разряд или сразу на несколько. Это определяет разряд D9 в КОП. Рассмотрим случаи для различных значений V. а) V=0; сдвиг на 1 разряд (i=1). Обязательная форма ассемблера (примеры): 1) ROL BX,1; (содержимое BX сдвинуть циклически влево на 1 разряд); 2)SHL BYTE [1CD0],1 (содержимое ячейки ОЗУ с адресом 1CD0 сдвинуть арифметически влево на 1 разряд); б) V=1; сдвиг на число разрядов, где число по умолчанию берется из регистра CL (i=CL). Обязательная форма ассемблера (примеры): 1) RСL AX,CL; (Содержимое AX сдвинуть циклически влево на число разрядов, где число сдвигов n=; 2) SHL WORD [1CD0],CL (содержимое слова, хранящегося в ячейках памяти M1CD1, M1CD0 , сдвинуть арифметически влево на число разрядов, где число сдвигов n=. Сформулируем краткие характеристики к схемам (таблица 4) выполнения команд сдвига, учитывая, что указанные схемы практически полностью отражают действия команд. Команды 3-й и 4-й строчки отличаются от 1-й и 2-й тем, что в команде циклического сдвига появляется дополнительный разряд : CF. Это свойство позволяет, в случае необходимости, спрятать один бит слова в CF, произвести нужные операции над оставшейся частью слова и вернуть обратным сдвигом спрятанный бит в CF на место. В частности, это можно использовать при преобразовании отрицательного числа из прямого кода в дополнительный и наоборот. Нижние четыре строчки таблицы касаются арифметических сдвигов. Причем, тип команды: 1102 — формальный, а результаты ее выполнения — бессмысленны. А вот нижняя команда используется достаточно часто. Из схемы следует, что тип 1112 отличается от типа 1012 тем, что вместо нулей при арифметическом сдвиге вправо освобождающиеся разряды заполняются содержимым старшего бита. А учитывая, что в старшем бите у чисел со знаком находится знак (вспомним, что «+» = 0, «-» = 1), то этот тип сдвига, сохраняя знак, сдвигает само число вправо. При этом, если число положительное, то освобождающиеся разряды заполняются нулями (после знака). А если отрицательное число, то — единицами. При преобразовании числа в прямой код эти единицы превращаются в нули. Пример 3 — Пусть в регистре XD находятся данные OFFE. Сдвинуть арифметически это число влево на 3 разряда. Ответ: Составляем программу в ассемблере: MOV CL, 03; Задаем в CL число сдвигов SHL DX, CL; и сдвигаем влево. 37
После выполнения программы: DX=7FFO.
6 Арифметико-логические команды По назначению арифметико-логические команды (команды АЛУ) разделяются на две группы: а) арифметические; б) логические. По кодам операции они разделяются на (2 типа x 8 видов) = 16 команд. Схемы выполнения 2-х типов команд АЛУ приведены на
рисунке 7. Рисунок 7 — Схема выполнения команд АЛУ Рассмотрим обобщенные КОПы для этих типов команд АЛУ. а) 1-й тип: машинный код команд АЛУ для команд типа: dst:= операция <src>.
б) 2-й тип: машинный код команд АЛУ с непосредственными данными (вместо src указывают данные в качестве второго числа): dst:= операция data.
38
Здесь в разряде D9 указывают знаковый признак данных. 1) Если S=0, то data — беззнаковый операнд, и длина его соответствует: при W=0 —байт; при W=1 — слово. 2) Если S=1, то: а) data длиной только в 1 байт; б) D7 —знак; число воспринимается в дополнительном коде; в) если dst — слово, то data расширяется до слова (знак переносится в D15). Все эти тонкости, на первый взгляд, являются запутанными, но если отталкиваться от четкого представления, как в цифровой электронике представляются положительные и отрицательные числа со знаком и без знака, и как реализуются операции сложения и вычитания (последняя заменяется сложением с дополнительным кодом вычитаемого), то все встанет на свои места. В таблице 5 представлены команды в ассемблере и комментарии для всех типов команд. Коды типов команд приводятся не по порядку, а по смыслу, связанному с назначением групп родственных команд. Все команды АЛУ, приведенные в таблице 5, воздействуют на флаги. Таблица 5 —Команды АЛУ Вид Ассембле Комментарий для команд АЛУ, содержащих: № команд р а) dst и src (тип 1) б) dst и data (тип2) п/п ы 1 000 ADD dst:=+<src> dst:=+data 2 010 ADC dst:=+<src>+ dst:=+data+ 3 101 SUB dst:=-<src> dst:=-data 4 011 SBB dst:=-<src>- dst:=-data- dst:=∨<src> dst:=∨data 5 001 OR (дизъюнкция —ИЛИ) dst:=∧<src> dst:=∧data 6 100 AND (конъюнкция —И) dst:=+<src> dst:=+data 7 110 XOR (сложение по модулю 2) -<src> -data 8 111 CMP (компарация — сравнение)
Рассмотрим команды АЛУ в порядке номеров пунктов таблицы 5.
6.1 Команды сложения а) Сложение содержимым dst и src; результат — в dst. Ассемблер с комментариями (примеры): ADD AX,BX ; AX:=+ ADD SI,[1CDO] ; SI:=<SI>+<M1СD0> в) Сложение содержимого dst и данных, указанных в команде. Ассемблер c комментариями (примеры): 39
ADD CX,1350 ; CX:=+1350 ADD BYTE [1500], 2F ; M1500:=<M1500>+2F ADD WORD [1500],20 ; M1501,M1500:=<M1501,M1500>+(-02) Составим машинный код последней команды, используя таблицу 5 для определения вида команды и таблицу 3 (глава 3) для определения адреса dst: 83 06 00 15 FE КОП Адрес data FE —это не что иное, как дополнительный код отрицательного числа: 20 (H-код). Действительно, если преобразовать -02 из прямого кода в дополнительный, то и получим FE: S Мантисса -216 = 1 0000010 инверсия S —место знака 1 1111101 +0 0000001 1 1111110 = FE16 Следовательно, эту же операцию можно представить так: ADD WORD [1500],FE? Оказывается, нельзя. Поскольку не указан знак, а любой редактор ассемблера дополняет байт или слово в части старших бит нулями (то есть их можно не указывать), то в результате работы транслятора для команды ADD WORD [1500],FE получится следующий машинный код: 8306 0015 FE00 КОП Адрес data И полный ассемблер этой команды будет таков: ADD WORD [1500],OOFE А это совсем другая команда.
6.2 Команда сложения с учетом переноса Эта команда складывает не просто 2 числа, а добавляет к ним . Это замечательная команда, потому что без нее невозможно было бы достаточно просто складывать многобайтовые числа. Возьмем пример для десятичных чисел: 59 +36 85 и 1 держим в уме. Единица —это перенос: CF = 1. Естественно, что если при сложении старших чисел не учитывать перенос от предыдущей суммы, то результат будет неверным. Чтобы 2-я сумма была корректной, необходимо ее сложить с переносом: 8 40
+ от предыдущего сложения 9 Итого: 95. Рассмотрим пример сложения многобайтовых чисел. Пример 1— Пусть 1-ое слагаемое находится в M1501,M1500 (двухбайтовое число), а второе слагаемое — в BX. Сумму поместить в M1601,M1600. Ответ: Если складывать по байтам, то это будет выглядеть так: ADD BL,[1500]; Сложить младшие байты чисел MOV [1600],BL; и переслать младшую часть суммы в M1600. ADC BH,[1501]; Сложить старшие байты слагаемых и + возможMOV [1601],BH; ный перенос от предыдущей суммы и M1601.
6.3 Операция вычитания Эта команда выполняется чуть сложнее, чем команда сложения. В отличие от сложения, операция вычитания простыми логическими средствами не реализуется. Операция вычитания производится следующим образом: а) вычитаемое преобразуется в дополнительный код; б) дополнительный код вычитаемого складывается с уменьшаемым. Само собой разумеется, что все это выполняется автоматически. В отличие от сложения, перенос в этом случае направляется в CF через инвертор. Посмотрим на абстрактных примерах, что из этого выходит. Пусть A —уменьшаемое, B —вычитаемое. Случай 1: A>B. Пусть A=1000, B=0101 (двоичные числа). Преобразуем B в дополнительный код (без знака): 0101 инверсия 1010 + 0001 Bдоп=1011 — дополнительный код B. Теперь складываем: A+Bдоп: 1000 +1011 1 0011 Перенос = 1. Но этот перенос при вычитании инвертируется, и только потом попадает в CF. Значит, в этом случае CF=0. Еще раз: 1000201012= 00112 и CF=0. (Кстати, результат получили в прямом коде). Случай 2: A
+0001 Bдоп=1000 —дополнительный код B. Складываем: A+Bдоп: 0101 +1000 0 1101 Перенос=0 Переполнения нет, но флажок CF=1, так как он устанавливается переполнением через инвертор. А теперь подставим значение CF=1 в качестве старшего бита уменьшаемого и вычтем вычитаемое B: 1 0101 — 1000 1101 Получили тот же результат, что и выше. Вывод: при вычитании флаг CF имеет смысл заема! Но заем предполагает наличие старшей части числа. А если ее нет? Тогда необходимо вспомнить, что все числа в АЛУ представлены в дополнительном коде, и если после вычитания CF=1 , а занимать не у «кого», то полученный результат есть отрицательное число в дополнительном коде. Чтобы получить результат в истинном виде, необходимо полученное отрицательное число (беззнаковое) перевести в прямой код: CF=1
1101 инверсия CF=1 0010 +0001 — инкремент, чтобы «не трогать» CF=1 0011 Получили: 510 —810 = -310, где имеет смысл знака. Ассемблер команды вычитания (пример): SUB AX,BX ; AX:=-; заем (если есть) — в CF.
6.4 Команда вычитания с учетом заема Эта команда вычитания как раз и учитывает возможный заем от предыдущего вычитания. Рассмотрим следующий пример. Пример 2 — Пусть в ячейках памяти M1001 и M1000 находится уменьшаемое, а в DX-вычитаемое. Разность отправить в DX. Ответ: Составляем программу с демонстрацией использования процедуры заема на ассемблере: SUB [1000],DL ; M1000:=<M1000>-, заем (если есть) — в CF, MOV DL,[1000] ; и младшую часть разности отправить в DL. SBB [1001],DH ; M1001:=<M1001>--заем (если он есть), 42
MOV DH,[1000]
; и разность в DH.
6.5 Команда логической функции ИЛИ Основные логические функции булевой алгебры —это И, ИЛИ, НЕ. В таблице представлены только две из них: И (AND) и ИЛИ (OR). Дело в том, что операция НЕ оперирует только с одним адресатом, поэтому ее здесь нет. Ее рассмотрим в конце этой главы. А пока вернемся к команде ИЛИ (дизъюнкция). Рассмотрим следующий пример. Пусть в AL=3C (001111002), в AH=41 (010000012). Что получится после выполнения OR AH,AL? Учитывая, что с многобитовыми событиями логические операции выполняются по-битно, можем записать: 00111100 (3С) (ИЛИ) ∨ 01000001 (41) 01111101 AH = 7 D. Эта логическая операция используется достаточно часто. Например, еобходимо установить бит D5 ячейки памяти M1000 в единицу, оставив неизменными остальные биты M1000. Это делается очень просто. Составим байт, у которого бит D5=1: 001000002=2016. Выполним команду: OR BYTE [1000],20 И все.
6.6 Команда логической функции И Операция И (конъюнкция) выполняется аналогично ИЛИ (смотрите п.5 таблицы 5). Рассмотрим пример. Пусть в регистре АХ хранятся следующие события: AH=42, AL=7C. Что будет в регистре AL после выполнения команды AND AL,AH? 01111100 (7С) И) ∧ 01000010 (42) 01000000 AL= 4 0 Эта команда тоже достаточно популярна. Например, она позволяет сбрасывать в «0»один бит в байте (слове), оставляя неизменными другие биты. Пусть, например, необходимо установить бит D5 ячейки памяти M1000 в «0», оставив при этом неизменными остальные биты. Составляем байт, у которого D5=0: 11011112=DF. Выполним команду: AND BYTE [1000],DF. Бит D5 ячейки памяти M1000 будет сброшен в «0». 43
6.7 Команда «Исключающая ИЛИ» Это команда сложения по модулю 2. При сложении чисел по модулю N в формировании разрядной суммы игнорируются все переносы, которые получаются при превышении разрядной суммой числа N. Составим таблицу истинности сложения по модулю 2 для 2-х двоичных переменных A и B: Таблица 6 —Таблица истинности mod2 А Комментарий А⊕В В 0 Внутриразрядная сумма = 0 0 0 Внутриразрядная сумма = 0 1 1 1 Внутриразрядная сумма = 1 1 1 0 Внутриразрядная сумма = 1 0, 0 1 Переполнение игнорируется А теперь выпишем ДНФ (дизъюнктивную нормальную форму записи) этой логической функции: A⊕B=((-A)∧B)∨(A∧(-B)). Что же является важным из таблицы истинности функции A⊕B? Произведем анализ зависимости выходной функции A⊕B от переменной B, если A=1. Он позволяет сделать вывод, что при A=1 существует зависимость A+B = -В, то есть B инвертируется. А верхние две строчки таблицы 6 говорят об обратном: если A=0, то B не инвертируется. Вот эти свойства и используются, главным образом. Обратимся к примеру. Пусть необходимо изменить бит D5 ячейки памяти M1000 на противоположное состояние. Составляем слово, где бит D5=1 (событие A), остальные биты равны нулю: 001000002=2016. После выполнения команды: XOR BYTE [1000],20 состояние разряда D5 ячейки памяти M1000 изменится на противоположное. Большой популярностью пользуется такое применение команд сложения по модулю 2: XOR AX,AX ; обнулить AX; XOR SI,SI ; обнулить SI; Эти команды сбрасывают в «0» регистры AX и SI, что собственно и должно быть при сложении по модулю 2 любого числа с самим собой. 44
6.8 Команда сравнения — компарации Здесь трудно что-либо добавить к тем комментариям, которые есть в таблице 5. Сравнение производится на основе операции вычитания, но разность нигде не фиксируется, потому что нужна не она, а ее признаки: был ли заем? нулевой ли результат? и тому подобное — которые заносятся во флажковые биты. Ассемблер команды (пример): CMP AX,[1CFO]. И в заключение главы — команда инверсии: а) Ассемблер: NOT dst. Комментарий: dst:=-. б) Машинный код операции:
Необходимо отметить, что эта команда флажки «не трогает». Так реализовано преднамеренно, так как часто бывает необходимо проинвертировать что-то, при этом состояние флажков — сохранить. Естественно, что бывает и наоборот, когда нужно проинвертировать и одновременно в соответствии с проинвертированным результатом взвести флажки. Для этих целей используют команду XOR dst, FF, если нужно инвертировать байт, или XOR dst, FFFF, если — слово. Суть действия этой команды изложена в примерах в п. 7 для команды XOR.
7 Команды ветвления и переходов 7.1 Команды ветвления Это важнейшая группа команд, позволяющая принимать решение. Все команды, которые до сих пор рассматривались, выполняли действие. А вот возможностью принять решение по результатам каких-либо действий обладают только команды ветвлений. Ветвление —это переход (скачок) на указанное в команде перехода место, если выполнилось указанное в команде условие. К примеру, команда «jump no Z 5CЗF» в переводе на русский язык означает: прыгнуть по адресу 5CЗF, если нет Z (ассемблер: JNZ 5СЗF). Она осуществляет прыжок на адрес 5СЗF, то есть следующая команда будет выбираться по адресу 5СЗF, если флаг Z = 0. В противном случае 45
происходит выборка следующей команды (JNZ —пустая команда, если Z = 1). Таких команд МП 8086 реализует в количестве 16 шт. Но все эти команды имеют единый формат КОПа и команды в целом. Формат КОПа:
Из формата команды следует, что типов команд —23= 8. Каждая команда имеет свой антипод. То есть, если есть команда JNZ Addr (перейти, если Z= 0), то и есть ее антипод JZ Addr (перейти, если Z= 1). Команда условного перехода в ассемблере всегда начинается с буквы J (jump — скачок). Поэтому в приведенной ниже таблице 7 указываются недостающие буквы, следующие за J для различных типов команд, и соответствующие им условия переходов. В скобках указаны допустимые альтернативные обозначения. То есть можно записать JB, а можно и JNAE. Таблица 7 — Синтез команд ветвлений по условиям ветвлений Тип команды 000 001 010 011 100 101 110 111
Признак D0 = 0 Признак D0 =0 Ассемблер(доп. Условие перехода Ассемблер (доп. к Условие J) J) перехода NO O OF = 1 OF = 0 B (C,NAE) CF = 1 NB(NC,AE) CF = 0 E(Z) ZF = 1 NE(NZ) ZF = 0 BE(NA) CF V ZF = 1 NBE (A) CF V ZF=0 S SF = 1 NS SF = 0 P (PE) PF = 1 NP (P0) PF = 0 L (NGE) NL (GE) SF ⊕ OF = 1 SF ⊕ OF = 0 NLE (G) LE (NG) (SF ⊕ OF) V (SF ⊕ OF) V ZF=0 ZF=1
Для системных специалистов определяющим является не обозначение команды в ассемблере, а условие перехода, которое определяется состоянием или состояниями тех или иных флажков. То есть, по какому событию происходит переход. Если нужно перейти по условию OF = 1, то пишем JO; если переход осуществляется по условию CF =1, то пишем JC, хотя C (вторая строчка в таблице 7) — альтернативное обозначение, о котором программисты часто не знают. Дело в том, что для программистов первоначальным является само условие перехода: «больше», «меньше» и тому подобное. Из таблицы 7 следует, что условия переходов диктуют 5 флагов (смотрите главу 2): 46
OF — арифметическое переполнение. Флаг OF=1, если относительно знакового бита в результате выполнения, например, арифметических команд произошла следующая метаморфоза: (+)+(+)=(-); (+)-(-)=(-); (-)+(-)=(+); (-)-(+)=(+); (здесь в скобках указаны знаки). CF —переполнение (байта, слова) или заем, если было вычитание. ZF —признак нулевого результата. ZF = 1 — значит получили в результате команды АЛУ, INC, или DEC — результат, равный нулю. SF —знак. Здесь все просто: если команда воздействует на флаги, то флаг SF запоминает содержимое старшего бита данных: а) SF:= , если операнд — 1 байт; б) SF:= , если операнд — 1 слово. PF — событие (признак) наличия в результате четного (PF = 1) числа единиц; касается только байта (если слово, то —младшего байта). Приведем пример. Пусть в AX хранится: 1DCO. Выполним команду: AND AX,1245 Н-код 1DCO
Двоичный код 0001 1101 1100 0000 (АХ) И И 1245 0001 0010 0100 0101 data Результат=1040 0001 0000 0100 0000 (АХ) │ (D15) Каково же будет состояние флагов? OF = 0; арифметического переполнения не было (хотя для этой команды это событие бессмысленно, но ЦА выполняет свой алгоритм); CF = 0; логическая операция —поразрядная операция, и у нее не может быть переноса (заема); ZF = 0; результат отличен от нуля: 1040 ≠ 0; SF = 0; знаковый флажок запоминает: SF= < D15> = 0; хотя это для данной команды то же не имеет смысла, но ЦА выполняет свой алгоритм; PF = 0 – в младшем байте одна единица, то есть нет четного числа единиц (кстати, 0 —это четное число единиц). Знание правил установки флагов и позволяет эффективно использовать команды условного перехода. В таблице 7 указаны и комбинированные условия переходов. В этом случае лучше использовать для обозначения команды в ассемблере буквы, не входящие в скобки. Разберем эти условия подробнее. 1) CF V ZF. Допустим, из числа А вычитается число В, или сравнивается число А с числом В (наиболее часто используемый прием применения этого условия). Каковы варианты состояний флагов, соответствующие этой функции? Для ответа на этот вопрос составим 47
таблицу истинности функции CF V ZF (таблица 8), исходя из смысла указанных операций. Исходя из таблицы 8, можно сделать следующие заключения: Таблица 8 CF ZF CFVZF Событие 0 0 0 A>B 0 1 1 A=B 1 0 1 A
48
2) Поскольку переход бывает необходимым как вперед, так и назад, то он, как и смещение disp (смотрите главу 3), задается в машинном коде команды – в дополнительном коде со знаком как смещение относительно текущего адреса, находящегося в IР. 3) Для удобства написания программы в ассемблере (для чего собственно и придуман ассемблер) в адресной части команды условного перехода ставится не смещение, а непосредственный адрес перехода в текущем сегменте программы, а смещение вычисляется транслятором. Теперь все это проследим на отдельных примерах синтеза команд в ассемблере и машинных кодах. Пример 1 — По адресу 0100 расположить команду условного перехода с условием: если результат 0 (Z = 1), то перейти на 010F. Ответ: а) в ассемблере (все просто): JZ 010F б) в машинном коде: сначала составляем КОП : 1) тип команды JZ = 010 (третья строчка таблицы 7); 2) признак = 0 (таблица 7).
Теперь составляем второй байт команды — смещение (disp). Учитывая, что размер формата команды JZ Addr — 2 байта, текущее значение адреса команды будет следующим: IP = 0100 + 2 = 0102. Вычитаем из конечного текущий адрес: disp = 010F — 0102 = 000D = 1310 < 12710. Окончательно: Address 0100 0101
Command 74 OD
Assembler JZ 010F
Пример 2 —По адресу 0100 расположить команду условного перехода с условием: если больше (без знака), то перейти на адрес 0092: Ответ: а) в ассемблере: JNBE 0092 б) в машинном коде: 1) КОП:
49
2) Смещение: Смещение (disp) вычисляем относительно текущего значения адреса (содержимого IP после выборки команды), учитывая что команда JNBE (JA) — двухбайтовая. Текущее значение адреса: IP= 0100 + 2 = 0102. Ищем разность между конечным и текущим адресом: (0092 — 0102) = -0070. Берем только младший байт -70 и преобразуем это отрицательное число из прямого кода в дополнительный (D7 —знак): Прямой S 1.11100002 Окончательно:
Обратный S 1.00011112
Address 0100 0101
Дополнительный S (S —знаковый бит) 1.00100002 = 9016.
Command 77 90
Assembler JNBE 0092
Пример 3 – тоже самое, что и в примере 1, только перейти на адрес 182. Ответ: Вычислим смещение: 182 —102 = 8016 = 12810 > 12710 неосуществимо! Перебор на 1 адрес, так как максимальное смещение в этом случае может быть только 12710 = 7F16.
7.2 Команды перехода Кроме команд типа JUMP с условным переходом (ветвления) есть и команды с безусловным переходом, которые позволяют «прыгать» не только в пределах ±7F, но и даже между сегментами. Рассмотрим их. JMP — команда с безусловным переходом (пять типов) 1) Короткая, с относительной адресацией (смещением), 2-х байтовая; максимальная величина disp = ±7F. а) ассемблер: JMP SHORT Addr; б) КОП = ЕВ. Пример 4 — Команда расположена на 0100 адресе. Прыгнуть на адрес 0105. Определяем текущее значение IP: IP = 0100 + 2 = 0102. Смещение: 0105 —0102 = 0003 = 03 (1 байт).
50
Address 0100 0101
Command EB 03
Assembler JMP SHORT 0105
2) Внутрисегментная, с относительной адресацией (смещением), 3-х байтовая (2-х байтовое смещение, D15 —знак); а) ассемблер: JMP NEAR Addr; б) КОП = Е9. Пример 5 — Пусть исходные данные те же самые, что в примере 4, только применить внутрисегментную JMP с относительной адресацией. Ответ: Address Command Assembler 0100 E9 JMP NEAR 0105 0101 03 0102 00 Примечание – Обычно при написании программ в ассемблере для команд с относительной адресацией не указывают SHORT или NEAR, так как транслятор по вычисленной им величине смещения сам выбирает тип перехода: короткий или внутрисегментный. 3) Внутрисегментная, с косвенной адресацией, 2-байтовая (КОП — 2 байта). а) ассемблер: JMP NEAR dst (или просто: JMP dst). Комментарий: перейти по адресу, который хранится в dst; б) КОП:
Пример 6 — Пусть в ячейке памяти с адресом 1CFO хранится число 5D, а в ячейке 1CF1 — 02. Представить команду перехода с косвенной адресацией (внутри сегмента), находящуюся по адресу 0100 и имеющую в качестве dst 2-х байтовый источник M1CF1,1CF0: Ответ: а) ассемблер: JMP NEAR [1CFO] (или просто: JMP [1CF0]); б) КОП: 51
Полностью: Address 0100 0101 0102 0103 (IP)
Command FF 26 FO 1C
Assembler JMP [1CFO]
После выполнения команды: IP:= <M1CF1,M1CF0> = 025D. С этого адреса будет выбираться КОП следующей команды. 4) Межсегментная, с прямой адресацией, 5-и байтовая команда (КОП —1 байт): а) ассемблер: JMP CS:IP; б) КОП= ЕА. Пример 7— Пусть команда расположена по адресу 175E:0100 =0176E0 (смотрите 2-ю главу — формирование физического адреса). Перейти по адресу: CS = F000, IP = E987. Ответ: Полное представление:
Address 175E : 0100 175E : 0101 175E : 0102 175E : 0103 175E : 0104 (CS) (IP)
Comman d EA 87 E9 00 F0
Assembler JMP F000:E987
После выполнения команды изменится не только IP (IP:=Е987),но и значение командного сегмента (CS:=F000), и следующий КОП будет выбираться с адреса F000:E987 = FE987. «Скачок» = FE987 — EO = E72A7, то есть намного больше размера сегмента (размер сегмента 1000016 = 6553610). 5) Межсегментная, с косвенной адресацией. 52
а) ассемблер: JMP FAR dst;
Примечание – Хранилищем адреса перехода может быть только ЗУ, так как длина этого слова 4 байта, а с таким размером регистров в составе МП нет. Поэтому в графе КОП всегда mod ≠ 11. Пример 8 — Пусть в указанных ячейках памяти ЗУ хранятся следующие байты: М2000 = 87, М2001 = Е9, М2002 = 00, М2003 = FO. Выполним следующие команды: MOV BX, 2000; BX:=2000 — адрес младшей ячейки адреса перехода; JMP FAR [BX]; перейти по этому адресу. После этого произойдет переход на следующий адрес: CS = F000, IP = E987. КОП этой команды JMP:
Примечание – Необходимо иметь ввиду, что источником адреса являются ячейки памяти в текущем сегменте DS. Если же эти ячейки расположены в другом сегменте, то сначала надо загрузить новое значение сегмента в DS (смотрите 3-ю главу). Например: MOV AX, значение сегмента MOV DS,AX или MOV AX, значение сегмента PUSH AX POP DS
53
8 Команды перехода между программой и подпрограммой В этой главе рассмотрим команды переходов, позволяющие осуществлять переход из тела программы к подпрограмме и возврат назад. Сразу поставим точки над i: подпрограммой будем называть такую программу, которая заканчивается безадресным переходом типа RET (RET — RETURN — возврат). Эти команды используются, главным образом, в двух видах. Что делает микропроцессор, обнаружив КОП безадресного перехода RET NEAR (КОП=СЗ, ассемблер: RETN) или RET FAR (КОП=СВ, ассемблер: RETF)? а) если КОП = СЗ (ассемблер: RET или RETN), то МП 8086 производит скрытую операцию чтения стека POP IP: IP := <Stack>. б) если КОП = СВ ( ассемблер: RETF — возврат издалека, из другого сегмента), то МП 8086 производит две скрытых операции чтения стека: сначала POP IP, потом POP CS: IP := <Stack>; CS := <Stack>. Примечание – Процедуры чтения-записи стека изложены в главе 4, поэтому подробности, связанные с организацией стека, здесь опускаются. Поскольку смысл любой подпрограммы в том, чтобы выполнять какую-то часто повторяемую процедуру и возвращаться туда, откуда произошел «скачок» на подпрограмму, и принимая во внимание, как происходит безадресный возврат, нетрудно догадаться, что где-то должны позаботиться о том, чтобы прежде, чем сделать «скачок», в стеке остался на сохранение адрес той команды, которая была следующей, но еще не успела выполниться. И судя по командам возврата, должно быть два типа таких команд-скачков, из которых одна перед «скачком» отправляет в стек только содержимое IP, а вторая сначала отправляет в стек содержимое CS, а потом —содержимое IP. Рассмотрим эти два типа команд, которые имеют мнемонику CALL1(CALL —вызов).
8.1 Внутрисегментные переходы 8.1.1 Внутрисегментный, с относительной адресацией; команда 3-х байтовая: а) ассемблер: CALL Addr; б) КОП = Е8. Все процедуры формирования смещения такие же, как в п.2 главы 7 для команды JMP. 54
Пример 1 — Пусть команда CALL 010F находится по адресу 0100. Вычисляем disp, учитывая, что команда трехбайтовая: disp = 010F — (0100 + 3) = 000C. В целом получаем: Address 0100 0101 0102 0103
Command E8 OC 00 КОП следующей команды
Assembler CALL 010F
Как выполняется команда CALL 010F ? 1). Stack:= = 0103 (спрятать в стек адрес следующей команды, то есть адрес возврата); 2). IP:= 010F (назначить IP новый адрес — адрес подпрограммы). 8.1.2 Внутрисегментный, с косвенной адресацией а) Ассемблер: CALL NEAR dst. Комментарий: перейти по адресу, который находится в dst (2 байта); б) КОП:
Пример 2 — Пусть АХ=010F и пусть имеет место следующий фрагмент программы: Address 0100 0101 0102
Command FF E0 КОП следующей команды
Assembler CALL AX
Результат выполнения этого фрагмента: 1) Stack := = 0106; 2) IP := = 010F.
8.2 Межсегментные переходы 8.2.1 Межсегментный, с прямой адресацией; команда 5-и байтовая: 55
а) ассемблер: CALL CS:IP; б) КОП = 9A. Пример 3 —Пусть имеет место следующий фрагмент программы: Address
Command
175 : 0100
9A
1750 1750 1750 1750
: : : :
0101 0102 0103 0104
1750 : 0105
Assembler JMP F000:E987
87 E9 00 F0 КОП следующей команды
Разберем подробнее результаты этой команды. Пусть текущая вершина стека была: SP = FFFE. Выполнение команды CALL F000:E987 можно разделить на 2 цикла. 1-й цикл: в стек засылается последовательно содержимое и . 2-й цикл: CS и IP присваиваются значения соответственно F000 и E987. Все иллюстрирующие пример 3 результаты представлены на рисунок 8.
8.2.2 Межсегментный, с косвенной адресацией: а) ассемблер: CALL FAR dst. Как и для соответствующей команды JMP FAR dst (см. пункт 5 главы 7), dst — это 4 ячейки памяти с адресом младшей ячейки Addr, так как адрес перехода 4-байтовый. б) КОП: 56
Порядок выполнения команды. 1) Загрузка прерванного адреса CS:IP в стек как в п.8.2.1: Stack : = ; Stack : = . Адрес новой вершины стека: SP = <SP>-4. 2) Переход на новый адрес в новом сегменте происходит как в п.5 главы 7 для команды JMP: IP:=[dst=<MAddr>]; CS:=[dst=<MAddr+2>]. Подводя итог, можно отметить, что однотипные команды JMP и CALL полностью совпадают по своим действиям в части перехода, но в отличие от команды JMP команда CALL перед переходом отправляет в стек адрес возврата в программу, то есть адрес команды, следующей за командой CALL.
9. Команды условного перехода для организации циклов Программный прием, именуемый циклом, является одним из самых востребованных. Суть организации цикла можно пояснить на следующем примере: Пример 1 — Пусть имеет место фрагмент программы: MOV CX, 0100 ; Загрузить в CX число 25610. M1: DEC CX ; Уменьшить содержимое CX на единицу, и JNZ M1 ; если CX ≠ 00, то снова перейти на команду DEC CX (метка М1). Здесь вместо адреса перехода, так как программа не транслирована (еще нет ни машинных кодов, ни адресов), ставим метку М1. Очевидно, что число циклов здесь 256. И пока цикл не выработается, программа дальше не пойдет. Поскольку циклы — это часто используемый прием (организация таймера, задержек, перебора данных и тому подобное), то в МП 8086 реализована специальная группа команд-циклов под общим названием LOOP Address (loop — делать петлю). Эти команды организует цикл по умолчанию только в CX. И прекращается цикл тогда, когда CX «обнулится» (за исключением одной команды).
57
Приведенный выше пример с помощью одной из этих команд можно продублировать так: Пример 2 — Программа цикла с использованием LOOP: MOV CX, 0100; Загрузить в CX число 25610. M1: LOOP M1 ; Уменьшить содержимое CX на единицу, и если CX = 0, то перейти на метку М1. Характеристика команды типа LOOP: 1) адрес короткий; самый длинный переход: ± 12710 адресов; 2) адрес в ассемблере — прямой; адрес в машинном коде — смещение со знаком в дополнительном коде (относительная адресация); 3) команда типа LOOP на флажки не воздействует (в отличие от команды DEC в примере 1) ; 4) команда двухбайтовая: КОП – 1 байт и смещение – 1 байт. Существует четыре разновидности этой команды. Ниже приведен обобщенный код операции:
В таблице 9 приведены данные для синтеза команды с указанием условий переходов (в скобках - альтернативное обозначение ассемблера). Из таблицы 9 следует, что если две верхних команды в качестве условия используют только состояние счетчика СX, то в двух нижних строках таблицы переход может состояться при одновременном выполнении двух условий. Только один маленький пример использования команды с двойным условием. Таблица 9 — Циклические команды Тип команды 11 10 01 00
Ассемблер
Условия перехода
Счетчик:1
JCXZ M1
Перейти на адрес М1, если CX=0
Нет
LOOP M1
Перейти на адрес М1, если CX≠0
Есть
LOOPZ M1 (LOOPE M1) LOOP NZ M1 (LOOP NE) M1
Перейти на адрес М1, если CX≠0 и Z=1 (конъюнкция) Перейти на адрес М1, если CX≠0 и Z=0 (конъюнкция)
Есть Есть
Пример 3 — Пусть в ОЗУ находится массив данных длиной в 25610 байт, начиная с адреса 0500. Составить программу просмотра 58
массива на предмет поиска в нем байта F6 (абстрактный пример, весь смысл которого — найти нужный байт). Составляем программу, используя подходящую для этого случая циклическую команду: MOV BX, 04FF ;загрузить предначальный адрес массива в BX; MOV CX, 0100 ;загрузить число байтов (циклов) в СX; M1: INC BX ;подготовить следующий адрес; CMP BYTE [BX],F6 ;сравнить элемент массива в М<ВХ> с F6, и LOOPNZ M1 ;если элемент обнаружен или CX = 0, то ;выйти из цикла. Таким образом, цикл будет повторяться до тех пор, пока CX≠0 и Z≠0, или более точно по смыслу: цикл будет продолжаться до конца в том случае, если до окончания заданного числа циклов не будет обнаружен байт F6. А иначе досрочное прекращение цикла, при этом в BX окажется адрес элемента массива F6.
10 Цепочные команды Цепочные (или строчные) команды реализованы в МП 8086 в количестве 5-и штук. Это очень «крутые» команды, хотя любая из этих команд состоит только из одного байта. При изучении данной группы команд важно понять механизм их выполнения, так как по умолчанию они используют до 6-и регистров с четко определенными функциями. Для облегчения изучения этой группы команд сначала «раскрутим» одну только команду, которая представлена в двух видах: а) команда MOVSB, KOП = A4; б) команда MOVSW, KOП = А5. По мнемокоду ассемблера можно догадаться, что это команда пересылки, только с некоторым расширением: S — цепочная (строчная) команда; B и W —соответственно байт и слово. Больше в мнемокодах нет никакой информации. Начнем «раскручивать» эту команду. Основные параметры и этапы выполнения команды: 1) Пересылка: dst := <src> — пересылка из источника в приемник, где dst = M<ES:DI> , src = M. Значит, команда позволяет переслать байт или слово из ячейки памяти одного сегмента в ячейку памяти другого сегмента. 2) После пересылки : а) DI:= ± 1, SI:= <SI> ± 1, если переслали байт; 59
б) DI:= ± 2, SI:= <SI> ± 2, если переслали слово. Примечания а) инкремент («+») происходит в том случае, если флаг DF был сброшен (DF = 0 — нормальное направление) ; б) декремент («-») происходит в том случае, если флаг DF был установлен (DF = 1 — обратное направление; D — DOWN — вниз). Установка флага DF производится с помощью специальных команд: а) установка флага (DF = 1) производится командой STD, КОП = FD ; б) сброс флага (DF = 0) производится командой CLD, КОП = FС. Пример – необходимо переслать 5 байт, начиная с адреса 015ЗС, на место, начиная с адреса 35000. Выделяем, с учетом команды типа MOVS, по своему усмотрению значения сегментов и адреса в сегментах источника и приемника. Адрес источника (src): 015ЗС = 0000:15ЗС; Адрес приемника (dst): 35000 = 3000:5000. Составляем программу: CLD ; Сбросить DF (инкремент адресов dst и src); MOV AX, 0000 ; загрузить в MOV DS, AX ; DS значение сегмента источника; MOV AX, 3000 ; загрузить в MOV ES, AX ; ES значение сегмента приемника; MOV SI, 15ЗС ; загрузить адрес источника; MOV DI, 5000 ; загрузить адрес приемника; MOVSW ; переслать два байта; MOVSW ; переслать два байта; MOVSB ; переслать байт. Команда очень удобная для перемещения массивов в памяти. Но если число цепочки не 5 байтов, и 5000? Очевидно, что нужно организовать цикл. Как это делается, уже рассматривалось в главе 9. Но фирма Intel усилила цепочные команды встроенным циклом, который запускается префиксом повторения. Команда префикса: а) ассемблер: REP (REPEAT — повторение); б) КОП = F2 или F3 (любой). Префикс повторения ставится перед цепочной командой и по умолчанию использует счетчик в CX; прекращает повторение при CX = 0. Применим в рассмотренном выше примере префикс повторения: CLD ; Сбросить DF (инкремент адресов dst и src); MOV AX, 0000 ; загрузить в MOV DS, AX ; DS значение сегмента источника; MOV AX, 3000 ; загрузить в 60
MOV ES, AX ; ES значение сегмента приемника; MOV SI, 15ЗС ; загрузить адрес источника; MOV DI, 5000 ; загрузить адрес приемника; MOV CX, 005 ; счетчик CX:= 510 — число пересылаемых байт; REP ; повторить пересылку MOVSB ; пять раз. Получили классический образец использования цепочной команды. Теперь можно сделать некоторые выводы, которые необходимо учитывать при использовании цепочных команд: — src в цепочной команде всегда M; — dst в цепочной команде всегда M<ES:DI>; — длина элемента цепочки равна байту или слову и задается в ассемблере команды последней буквой соответственно B и W; — повтор выполнения цепочной команды задается префиксом REP, стоящим перед цепочной командой; — число повторов выполнения строчной команды в случае применения префикса REP определяется предварительно заданным числом в регистре СХ; — направление перебора адресов в SI и DI задается флагом направления DF: при DF=0 — инкремент; при DF=1 — декремент. Поскольку оставшиеся нерассмотренные 4 цепочных команды в основе своей содержат тот же механизм, что и рассмотренная команда пересылки, дальнейшее изучение цепочных команд построим на их различии. Обобщенный код операции выглядит следующим образом:
Здесь: W=0 —длина элемента цепочки 1 байт; W=1 —длина элемента цепочки 2 байта. В таблице 10 приведены команды в ассемблере с комментариями их действия, привязанные к типу команды. Последние два типа команд требуют дополнительного пояснения, которые касаются их совместного использования с префиксом повторения. По сути — это арифметические команды, и они воздействуют на флажки. И префикс повторения перед этими командами микропроцессором воспринимается по-разному, в зависимости от кода операции: F2 или F3 (для пересылочных команд это 61
было безразлично). И ассемблер префикса повторения в этих случаях, естественно, отличается от безличного обозначения: REP. В таблице 11 приведены ассемблер и КОПы префиксов повторения, используемые совместно с цепочными командами сравнения. В скобках указаны альтернативные обозначения ассемблера префиксов повторения. Таблица 10 — Строчные команды Тип команд ы
Ассемблер команды
Краткий комментария действия команды
MOVSB 000
M<ES:DI> :=<M> MOVSW
101 110
STOSB STOSW LODSB LODSW
M<ES:DI>= M<ES:DI>= AL:=<M> AX:=<M>
CMPSB 011
<M>-<M<ES:DI>> CMPSW
111
-<M<ES:DI>> -<M<ES:DI>>
SCASB SCASW
Адрес следующего элемента DF=0
DF=1
DI=+1 SI=<SI>+1 DI=+2 SI=<SI>+2 DI=+1 DI=+2 SI=<SI>+1 SI=<SI>+2 DI=+1 SI=<SI>+1 DI=+2 SI=<SI>+2 DI=+1 DI=+2
DI=-1 SI=<SI>-1 DI=-2 SI=<SI>-2 DI=-1 DI=-2 SI=<SI>-1 SI=<SI>-2 DI=-1 SI=<SI>-1 DI=-2 SI=<SI>-2 DI=-1 DI=-2
Таблица 11 —Префиксы повторения для строчных команд Ассемблер префикса повторения
Код операции
REPZ (REPE)
F3
REPNZ (REPNE)
F2
Комментарий к выполнению префикса повторения с командами типа CMPS и SCAS Повторяется весь цикл, если выполняется условие: CX≠0 и Z=1 (конъюнкция). Повторяется цикл, если выполняется условие: CX≠0 и Z=0 (конъюнкция).
11 Другие одиночные команды Микропроцессор 8086 реализует ряд команд, каждую из которых можно назвать индивидуальной. Действия их достаточно просты и не требуют особых разъяснений. Часть их, наиболее часто используемых, приведена в таблице 12. Таблица 12 Ассембле КОП р NOP 90 HLT
62
F4
Комментарий действия команды Пустая команда. Не производит действий. Останов. Микропроцессор прекращает свое функционирование и переходит в 3-е состояние.
STI CLI
FB FA
Флаг IF=1 — разрешение аппаратных прерываний; флаг IF=0 — запрещение аппаратных прерываний.
STC CMC CLC
F9 F5 F8
Флаг CF = 1; флаг CF = - — инверсия флага CF; флаг CF = 0.
Другая группа команд позволяет заменять сегмент данных DS, используемый по умолчанию в командах, оперирующих с данными в области запоминающего устройства. Имеется в виду dst при mod<>112 (см. главу 3). Замена DS распространяется только на команду, следующую за командой замены сегмента. Эти команды называют префиксом замены сегмента или просто префиксом сегмента. Команды префиксов сегмента в ассемблере и машинных кодах приведены в таблице 13. Таблица 13 — Префиксы замещения сегментов Ассембле КОП Наименование Комментарий р При формировании Командный префикс CS: 2E физического адреса сегмента данных вместо сегмента Стековый префикс SS: 36 DS используется сегмента заданный сегмент. Резервный префикс ES: 26 сегмента Рассмотрим пример использования префикса сегмента. Пример 1 — Пусть в регистре DS=0000, в регистре CS=5FC0. Необходимо составить фрагмент программы пересылки байта данных из ячейки памяти с адресом 100 в нулевом сегменте — по 105-у адресу программы, в составе которой должен находится составленный фрагмент программы. Ответ: Поскольку программа выполняется в командном сегменте, то у приемника (dst) необходимо заменить сегмент данных на командный сегмент. Для источника никаких изменений не требуется, так как в DS по условиям примера уже содержится нулевое значение. Составляем фрагмент программы: XOR AX,AX ; загрузить в АХ ноль и MOV DS,AX ;переслать в DS; MOV AL,[0100] ;AL:=<MDS:0100>=<M0000:0100>; CS: ;в следующей команде —CS вместо DS; MOV [0105],AL ;MCS:0105=M5FC0:0105 := ; 63
Если здесь не использовать однократное переназначение сегмента, то пришлось бы составить, например, следующий фрагмент: XOR AX,AX ; загрузить в АХ ноль и MOV DS,AX ;переслать в DS; MOV AL,[0100] ;AL:=<MDS:0100>=<M0000:0100>; PUSH CS ; содержимое CS в стек, а оттуда POP DS ; в DS; MOV [0105],AL ; MCS:0105=M5FC0:0105 := ; В заключение можно отметить, что в настоящем пособии была рассмотрена только часть команд микропроцессора 8086. Но устойчивое знание даже этой части команд позволяет составлять на ассемблере программы и самостоятельно освоить нерассмотренные здесь команды. Полный перечень команд приведен в приложении А. Здесь не были представлены команды ввода-вывода и команды прерываний, которые будут рассмотрены при изучении соответствующих интерфейсных схем. Группа этих команд малочисленна, но весь механизм их действия связан со специфическим функционированием отдельных контроллеров, входящих в состав микропроцессорной системы.
12 Общие сведения об интерфейсных контроллерах. Команды ввода – вывода В главе 1 были представлены анализ структуры микропроцессорной системы и микропроцессорного модуля и организация системной шины. Исходя из этой информации, можно сделать вывод, что совершенно излишне «видеть» постоянно, как подключается та или иная интерфейсная схема (контроллер) к микропроцессорному модулю. Достаточно «ощущать» микропроцессорный модуль только посредством коммуникаций, то есть посредством системной шины. Следовательно, любая интерфейсная схема должна иметь стандартные коммуникационные входы и выходы для подключения к системной шине. Набор функциональных интегральных схем со стандартным единым способом подключения к системной шине и называется микропроцессорным комплектом. Функции обмена интерфейсных схем с системной шиной также стандартны. Все контроллеры специализированы. Их специализация зависит от объекта, с которым микропроцессорный модуль осуществляет обмен информацией, и посредством которого осуществляет функции управления. (CONTROL —управление, то есть управляемый, а значит программируемый интерфейс). Из всех интерфейсных контроллеров можно выделить следующие типовые контроллеры: — контроллер ОЗУ; его функции: сопряжение байтовой структуры ОЗУ с шиной данных системной магистрали; регенерация ОЗУ, если 64
ОЗУ — динамическое; организация ОЗУ, в случае большого объема, по строкам и столбцам; — контроллер параллельного интерфейса с протоколом обмена ИРПР или CENTRONICS; как правило используется универсальный параллельный интерфейс; — контроллер последовательного интерфейса с протоколом обмена RS-232 и ему аналогичных; — контроллер прерываний (в некоторых микропроцессорных комплектах встроен в интерфейсные схемы обмена данными): выставляет по инициативе внешнего устройства запрос на аппаратное прерывание микропроцессору и на ответный запрос микропроцессора «кто?» выставляет на шину данных вектор или адрес прерывания (начальный адрес подпрограммы обработки прерываний для соответствующего запроса внешнего устройства); — контроллер временных меток — таймер; — контроллер прямого доступа в память (КПДП): используется только в мощных микропроцессорных системах; реализует ускоренную «перекачку» массивов данных между ОЗУ и внешним устройством (флоппи-диском, компакт-диском и тому подобное), минуя микропроцессор; последнему, правда, в это время приходится «отдыхать». Перечисленный набор — это стандартный набор для минимальной конфигурации ЭВМ. Что можно еще добавить к основным интерфейсным схемам: — контроллер флоппи-диска; — контроллер жесткого диска типа «Винчестер»; — контроллер видеоизображения (черно-белого и цветного); — контроллер компакт-диска; Последующий материал направлен на изучение только части основного комплекта, причем будет рассмотрена только часть функций, ими реализуемых. Обусловлено это поверхностным изучением интерфейсных схем, необходимым и достаточным, чтобы сформировать устойчивое представление о функциональных возможностях микропроцессорной техники. Интерфейсные схемы, которые будут рассматриваться далее, разработаны фирмой Intel для 8-разрядной шины данных (интерфейсная шина, как правило, всегда 8-разрядная) и имеют следующие шифры : — 8259 — контроллер прерываний; — 8253 — таймер; — 8255 — параллельный интерфейс; — 8250 — последовательный интерфейс. Все интерфейсные схемы (ИФ) имеют стандартные входы и выходы для сигналов системной магистрали. Следовательно, со стороны подключения к системной магистрали все интерфейсные схемы являются «безликими»? Это не совсем так. Чтобы понять, как микропроцессором 65
выбирается та или иная интерфейсная схема, рассмотрим схему подключения к системной шине абстрактной (обобщенной со стороны системной шины) интерфейсной схемы. Схема подключения ИФ приведена на рисунке 9. Попробуем на этом примере произвести систематизацию и сделать кое-какие выводы. 1) Выводы ИФ D7...D0 подключаются непосредственно к шине данных системной магистрали. Эти выводы могут быть: а) входными или выходными (указано двунаправленной стрелкой); в) отключенными от внутренней шины данных ИФ (значок Z говорит о том, что микросхема электрически может быть отключена от шины данных (ШД). 2) Вывод -WR подключается к стробу записи -IOWR, то есть ИФ при записи данных в ИФ может обслуживаться только командами вывода. 3) Вывод -RD подключается к стробу чтения -IORD, то есть ИФ при чтении данных из ИФ может обслуживаться только командами ввода. Примечание – Контроллер ОЗУ аналогичными выводами подключается к -MEMWR и -MEMRD соответственно (MEMORY —
66
память). 4) Вывод RES подключается к RES — общий сброс микропроцессорной системы. Итак, по группам сигналов, рассмотренных в пунктах 1) – 4) для всех ИФ подключение со стороны системной шины одинаково, за исключением контроллера ОЗУ. Как же все-таки микропроцессор выбирает одну ИФ из многих? Для этих целей и существует адрес. В микропроцессорных системах на базе МП 8086 адресная шина интерфейса сужена с 20 разрядов (А19...А0) до 10 разрядов (А9...А0). Дело в том, что число адресуемых элементов интерфейса и в этом случае велико (210 = 1024), что никогда полностью не реализуется. Рисунок 9 — Схема подключения ИФ к системной шине Так вот, каждая интерфейсная микросхема имеет от одного до трех адресных входов (на рисунке 9 — два входа: А1, А0) для адресации внутренних элементов интерфейсных ИС. Общее свойство — каждая интерфейсная ИС имеет вход CS (CHIP SET - чип установить). CHIP — жаргонное слово в электронике, утвердилось для обозначения кристалла кремния, в котором выращена ИС. Иногда этот вход в других ИС обозначается ОЕ (OUT EXTENDED — выход протянуть (до шины), то есть внутреннюю шину данных интерфейсной схемы подсоединить к внешней). Следовательно, интерфейсная ИС «слепа» и «глуха» к системной шине, пока на инверсном входе «- CS» не будет «0». Обычно этот выбор осуществляют с помощью дешифратора (дешифратор — набор комбинационных схем И) с инверсными выходами, на вход которого подают незадействованные непосредственно интерфейсной ИФ старшие разряды адреса. В рассматриваемом примере (рисунок 9) нужна была только одна комбинация выбора CS, поэтому можно (в данном случае — произвольно) обойтись только одной схемой И-НЕ. Запишем логическое уравнение выборки ИФ согласно рисунку 9: -CS = A9∧A8∧A7∧A6∧A5∧A4∧A3∧A2, или CS = A9∧A8∧A7∧A6∧A5∧A4∧A3∧A2. Но для указания адреса одного из внутренних элемента ИФ такая форма записи не может быть достаточной. Для этого надо знать, как и какие элементы ИФ выбираются. Это делается при наличии CS=1 и с помощью логической функции ИФ: f(A1, A0). Эта функция выборки внутренних элементов ИФ дается в справочных данных в виде таблицы истинности. Пусть, например, ИФ является мультиплексором и имеет 3 восьмиразрядных входа (3 порта) с именами А, В и С и регистр управления портами с именем RGC. И пусть выбор элементов ИФ соответствует таблице истинности: 67
Имя Порта Адрес А1 А0 A 0 0 B 0 1 C 1 0 RGC 1 1 Теперь выпишем полные адреса этих элементов в двоичном и шестнадцатеричном кодах с учетом уравнения выборки чипа и адресов внутренних элементов ИФ: Таблица 14 —Синтез адресов выборки элементов ИФ Имя А9 А8 А7 А6 А5 А4 А3 А2 А1 А0 Адрес PA 1 1 1 1 1 1 1 1 0 0 3FC PB 1 1 1 1 1 1 1 1 0 1 3FD PC 1 1 1 1 1 1 1 1 1 0 3FE 3
F
C…F
Естественно, что в микропроцессорной системе в любой момент времени микропроцессор ведет диалог только с одной интерфейсной ИС, поэтому недопустимо, чтобы в интерфейсе были элементы с одинаковыми адресами (уравнениями выборки чипа ИФ). Итак, теперь известно, как по схеме подсоединения интерфейсной ИС к шине адреса системной магистрали можно определить адреса элементов интерфейса. Теперь можно познакомиться с командами ввода-вывода. Для этого сначала необходимо поточнее уяснить назначение сигналов системной магистрали: -IOWR, —IORD и MEMWR, -MEMRD. Если микропроцессор вырабатывает строб (короткий сигнал) MEMRD (чтение ячейки памяти) или строб -MEMWR (запись в ячейку памяти), то это может быть вызвано только командами, оперирующими пересылкой данных между запоминающим устройством (ЗУ) и микропроцессором. Например, MOV AX,[BX] или PUSH AX. Если микропроцессор оперирует с интерфейсом внешних устройств, то он должен вырабатывать : а) строб -IORD — при вводе данных из порта (INPUT); б) строб -IOWR — при выводе данных в порт (OUTPUT). МП 8086 поддерживает следующие команды ввода-вывода: 1) Ввод. а) Ассемблер: IN AL,DX; комментарий: ввести в регистр AL данные из порта, адрес которого взять из регистра DX. б) Машинный код команды состоит из одного КОП: КОП = ЕС. Следовательно, прежде. чем использовать команду IN, надо в DX загрузить адрес порта. Пример 1 — Ввести байт данных из порта В (смотрите рисунок 9 и таблицу 14): 68
Решение. MOV DX,ОЗFD ;DX := 3FD — адрес порта В ; IN AL,DX. ; ввести в AL МП из порта В байт данных. 2) Вывод. а) Ассемблер: OUT DX,AL; комментарий: вывести из регистра AL МП байт данных в порт, адрес которого взять из DX. б) машинный код состоит только из КОП: КОП = ЕЕ. Пример применения этой команды можно не приводить, так как по существу он не отличается от примера 1. Таким образом, выбор команд ввода-вывода невелик, но достаточен.
13 Обслуживание прерываний. Контроллер прерываний 13.1 Процедура прерываний и команды прерываний Что должен делать микропроцессор, обнаружив на своем входе INT сигнал «1» (смотрите рисунок 3 в главе 2)? Он должен: во-первых, закончить текущую команду, на которой его «прихватил» запрос: INT = 1; во-вторых, если флаг IF был равен «1» (разрешение аппаратного прерывания), то вместо сигналов чтения -MEMRD или -IORD микропроцессор вырабатывает сигнал чтения: -INTA. Что должен прочитать МП этим сигналом с шины данных системной магистрали? По логике событий — КОП следующей команды. Но он вырабатывает не сигнал чтения ячейки ЗУ –MEMRD, а сигнал INTA. Вместе с тем, МП посредством этого сигнала будет загружать КОП следующей команды, и это должна быть первая команда подпрограммы, которая обслуживает прерывание. Следовательно, источником этой команды должен быть необычный интерфейсный элемент, для которого сигнал –INTA является сигналом чтения (ввода). Вот этим элементом и является контроллер прерываний. Именно он обслуживает аппаратную часть процедуры прерывания. Но прежде, чем рассмотреть контроллер, давайте еще раз вернемся к процедуре прерывания. МП 8086 поддерживает (как и все другие микропроцессоры) программное и аппаратное прерывание. Программное прерывание инициируется по команде прерывания. а) Ассемблер: INT n, где n — однобайтовый вектор перехода, указывается в H-коде. б) Машинный код — 2 байта: 1-й байт — КОП, 2-й байт — вектор. КОП = CD. Вектор = 0...FF (0...25510). Что делает микропроцессор, обнаружив команду INT n? 1) Запрещает дальнейшее аппаратное прерывание: IF = 0 (то есть, выполняет скрытую команду CLI). 2) Загружает последовательно в стек: 69
Stack:= - загружает в стек PSW (содержимое регистра флагов); Stack:= - загружает в стек содержимое сегментного регистра CS; Stack:= - загружает в стек текущий адрес, то есть адрес следующей команды прерванной программы. 3) Начиная с адреса CS:EA, где CS = 0000, EA = 4×n — считывает 2 слова, (4 байта), первое (младшее) из которых попадает в IP, а второе (старшее) — в CS. Таким образом, следующая команда будет выбираться, начиная с адреса CS:IP, который установило программное прерывание INT n . Следовательно, в задачу пользователя входит: а) знать, в каком сегменте и с какого адреса расположена подпрограмма, которая вызывается прерыванием INT n; б) загрузить в ячейки памяти в нулевом сегменте, начиная с EA = 4×n, слово адреса и слово сегмента начала подпрограммы. Пример 1 – пусть подпрограмма должна вызываться прерыванием INT 2F, и эта подпрограмма располагается в ОЗУ, начиная с адреса: CS=1570, IP = 0100. Ответ: Вычисляем адрес вектора : EA = 2F×4=BC. Располагаем адрес начала подпрограммы по адресу вектора: Адрес Данные
IP 00BC 00
CS 00BD 00BE 00BF 01 70 15
Естественный вопрос: как вернуться из программного прерывания? Команду безадресного перехода RET FAR здесь можно использовать, но к ней необходимо добавлять команду POPF, чтоб восстановить и регистр флагов F, и указатель стека. Такой возврат обеспечивается специальной командой безадресного перехода, которая поглощает в себя эти две команды: а) Ассемблер: IRET; б) КОП = CF. Действие команды: IP := <Stack> ;возврат адреса из стека; CS := <Stack> ;возврат сегмента из стека; F := <Stack> ;возврат флагов из стека. Следовательно, если подпрограмма вызывается программным прерыванием, а не командой CALL, то она должна заканчиваться командой IRET. Теперь снова вернемся к аппаратному прерыванию. Итак, микропроцессор сигналом чтения -INTA требует у контроллера прерываний КОП следующей команды. По всей видимости, это должна быть команда программного прерывания INT n с кодом операции CD. 70
Этот код «зашит» технологически в контроллере прерываний 8259. А вектор n программируется при инициализации контроллера прерываний (ПКП) . Ознакомимся с архитектурой ПКП 8259, приведенной на рисунке 10. При этом опустим разъяснения относительно сигналов системной магистрали, считая, что это уже пройденный этап. Шинный формирователь осуществляет двунаправленное движение данных: - при -IORD=0: T=0 и шинный формирователь осуществляет направление справа налево; - при -IOWR=0: T=1 и шинный формирователь осуществляет направление слева направо. Таким образом коммутируется внутренняя шина данных (ВШД) с шиной данных системной магистрали. Но это при условии, что -CS = 0, что приводит к ОЕ = 1; а иначе шинный формирователь вообще отключен от системной шины. Это общий принцип управления встроенным в интерфейсные контроллеры шинным формирователем. Схема управления записью-чтением осуществляет генерацию необходимых для внутренних элементов ПКП управляющих сигналов. Теперь по существу функционирования ПКП. Относительно запросов на прерывание IRQi он представляет собой двухступенчатый регистр — систему со шлюзом. Всего реализовано IRQi для 8 запросов. Они неравнозначны: максимальный приоритет у IRQ 0, минимальный - у IRQ 7. 1-ый этап. Сначала передним фронтом (или потенциалом) IRQi устанавливается соответствующий разряд регистра запросов на прерывание (РЗП) — открылись 1-ые ворота шлюза. Сигнал с выхода РЗП этого разряда через это Рисунок 10 —Архитектура ПКП 8259
71
своеобразное сито — логику маскирования и приоритета — попадает на вход INT МП (INT=1). 2-ой этап. МП первым сигналом чтения -INTA считывает из ПКП на шину данных КОП = CD и одновременно переписывает соответствующий запрос из РЗП в регистр обслуживаемых запросов на прерывание (РОЗП). Соответствующий выход РОЗП, установившись в «1», блокирует прохождение INT через логику маскирования и приоритетов как собственного запроса, так и более низких по приоритету. Резюме: 1-ые ворота закрылись, INT — исчез (INT=0). 3-ий этап. МП, распознав по КОПу, что команда двухбайтовая, вырабатывает еще один сигнал чтения -INTA, который считывает из ПКП на шину данных вектор и одновременно сбрасывает соответствующий разряд РЗП в «0», который вызвал прерывание INT. Итак, первая ступень — в исходное состояние. Можно зафиксировать: аппаратная часть прерывания закончилась, но в результате: 1) флаг IF = 0 , то есть аппаратное прерывание МП заблокировано (запрещено); 2) IRQi , вызвавший прерывание, тоже заблокирован по входу i и по всем остальным, которые ниже по приоритету. 4-ый этап. Разблокировка этой двойной блокировки всегда производится программно в конце подпрограммы, вызванной прерыванием. Снятие блокировки со входа INT МП производится командой STI (IF = 1 — разрешение аппаратного прерывания). Сброс соответствующего разряда РОЗП осуществляется записью в ПКП при А0=0 (рисунок 10), например, кода «20» (20 — код команды сброса того разряда, который последним вызвал прерывание). 2-ые ворота шлюза открылись — процесс прерывания завершен. Пример 2 — Допустим, ПКП выбирается (с помощью дешифратора адреса) следующими кодами : OFO (AO=0) и OF1 (AO=1); Тогда заключительная часть подпрограммы, вызванной прерыванием, будет выглядеть следующим образом: . . . . . . . . . . . . . . . . . . . . . . . . . STI ; разрешение прерываний микропроцессору; MOV DX,OOFO ; адрес ПКП для А0=0 в DX; MOV AL,20 ; код завершения обработки прерывания ПКП — в AL, OUT DX,AL ; а оттуда в ПКП. IRET ; возврат в программу. На рисунке 10 (архитектура ПКП) имеется элемент, именуемый регистром маски. Маска устанавливается («1»—маскирование IRQi) 72
записью в ПКП при АО=1 соответствующего байта. Маску можно прочитать по тому же адресу, то есть при АО=1. Пример 3 — составить маску для только что рассмотренного примера 2 таким образом, чтоб разрешить прерывание только по запросам IRQO и IRQ6: Ответ: Составляем слово маски, «закрывая» все, кроме D6, D0: D7 D6 D5 D4 D3 D2 D1 D0 ┌───┬───┬───┬───┬───┬───┬───┬───┐ Маска: │ 1 0 1 1 1 1 1 0 │ └───┴───┴───┴───┴───┴───┴───┴───┘ └───────────┘ └───────────┘ Н-код = B E Составим фрагмент программы маскирования ПКП с адресами выборки из примера 2: MOV DX,00F1 ; адрес ПКП для АО=1 в DX; MOV AL,BE ; маску BE (IRQ 0, IRQ 6 — разрешить) в AL, OVT DX,AL ; а затем оттуда в ПКП — в регистр маски. Примечание – В начале работы, в момент подачи питания на ПКП все IRQ демаскируются, все разряды РЗП и РОЗП сбрасываются в «0» и устанавливается исходный приоритет: IRQ 0 — высший, IRQ 7 — низший (дно). Следующий элемент архитектуры ПКП (рисунок 10) называется: «Схема каскадирования». Он выполняет функции расширителя числа запросов на прерывание. Дело в том, что если не хватает 8 входов IRQ, то микросхемы можно каскадировать — до 8 штук, и число векторов довести до 8 x 8 = 64. На практике такое редко встречается, а вот каскад из двух ПКП реализован в IBM PC/АТ. Как это делается — в данном пособии не рассматривается. Это совершенно не принципиальный вопрос, а скорее узкотехнический. А теперь обратимся к программированию ПКП. Некоторые элементы этого процесса уже были представлены в примерах 2 и 3. Но в целом процесс программирования ПКП достаточно сложен и состоит из трех блоков. 1) блок инициализации (настройка режима и загрузка векторов и шага векторов); 2) блок команд окончания (завершения) прерывания; 3) блок команд обработки по опросу (без сигнала INT). Чтобы иметь возможность работы с контроллером по минимуму, необходимо знать: а) как накладывать маску (или прочитать ее); б) как завершать прерывание (частный случай: команда 20 при А0=0). 73
Теперь рассмотрим более подробно рассмотрим режим работы ПКП и синтез команд инициализации ICW и команд обслуживания OCW.
13.2 Режимы работы ПКП 13.2.1 Режим фиксированных приоритетов. В этом режиме контроллер находится сразу после инициализации. Запросы прерываний имеют жесткие приоритеты от 0 до 7 (0 — высший) и обрабатываются в соответствии с приоритетами. Прерывание с меньшим приоритетом никогда не будет обработано, если в процессе обработки прерываний с более высокими приоритетами постоянно возникают запросы на эти прерывания. 13.2.2 Автоматический сдвиг приоритетов. В этом режиме дается возможность обработать прерывания всех уровней без их дискриминации. Например, после обработки прерывания уровня 4 ему автоматически присваивается низший приоритет, при этом приоритеты для всех остальных уровней циклически сдвигаются и прерывания уровня 5 будут иметь в данной ситуации высший приоритет и, следовательно, возможность быть обработанными. 13.2.3 Программно-управляемый сдвиг приоритетов. Программист может сам передать команду циклического сдвига приоритетов ПКП, задав соответствующее управляющее слово. В команде задается номер уровня, которому требуется присвоить максимальный приоритет. После выполнения такой команды устройство работает так же, как и в режиме фиксированных приоритетов, с учетом их сдвига. Приоритеты сдвигаются циклически таким образом, что если максимальный приоритет был назначен уровню 3, то уровень 2 получит минимальный и будет обрабатываться последним. 13.2.4 Автоматическое завершение обработки прерывания (AEOI). В обычном режиме работы процедура обработки аппаратного прерывания должна перед своим завершением очистить свой бит в РОЗП специальной командой, иначе новые прерывания не будут обрабатываться ПКП. В режиме AEOI нужный бит в РОЗП автоматически сбрасывается в тот момент, когда начинается обработка прерывания нужной процедурой обработки и от нее не требуется издавать команду завершения обработки прерывания (EOI). Сложность работы в данном режиме обуславливается тем, что все процедуры обработки аппаратных прерываний должны быть повторно входимыми, так как за время их работы могут повторно возникнуть прерывания того же уровня. 13.2.5 Режим специальной маски. Данный режим позволяет отменить приоритетное упорядочение обработки запросов и обрабатывать их по мере поступления. После отмены режима специальной маски предшествующий порядок приоритетов уровней сохраняется. 74
13.2.6 Режим опроса. В этом режиме аппаратные прерывания не происходят автоматически. Появление запросов на прерывание должно определяться считыванием РЗП. Данный режим позволяет так же получить от ПКП информацию о наличии запросов на прерывания и, если запросы имеются, номер уровня с максимальным приоритетом, по которому есть запрос.
13.3 Программирование ПКП Для программирования и ввода информации в ПКП используются 2 порта ввода-вывода. Порт с четным адресом (обычно это порт 20h) и порт с нечетным адресом (обычно 21h). Через эти порты могут быть переданы 4 слова инициализации (Initialization Control Word, ICW1 — ICW4), задающие режим работы ПКП, и 3 операционных управляющих слова (слова рабочих приказов, Operation Control Words, OCW1 — OCW3). В порт с четным адресом выводятся ICW1, OCW2 и OCW3. OCW2 отличается от OCW3 тем, что бит 3 в OCW2 равен 0, а в OCW3 равен 1. В то же время бит 4 в OCW2 и OCW3 равен 0, а в ICW1 равен 1. Таким образом по значению, выводимому в порт с четным адресом, однозначно определяется, в какой регистр (ICW1, OCW2 или OCW3) заносятся данные. Порт с нечетным адресом используется для вывода ICW2, ICW3, ICW4 и OCW1. Неоднозначности интерпретации данных в этом случае так же не возникает, так как слова инициализации ICW2 —ICW4 должны непосредственно следовать за ICW1, выведенным в порт с четным адресом и выводить в промежутке между ними OCW1 не следует – онo не будет опознано контроллером. Выводом в порт с четным адресом управляющего слова инициализации ICW1 начинается инициализация ПКП. В процессе инициализации контроллер последовательно принимает управляющие слова ICW1 —ICW4. При наличии в системе одного контроллера ICW3 не выводится. Наличие ICW4 определяется содержанием ICW1. При наличии каскада из нескольких ПКП каждый из них инициализируется отдельно. Формат ICW1 следующий: D7 D6 D5 D4 D3 D2 - “1” LTIM ADI │ │ │ │ │ │
D1 D0 SNGL IC4
A0 “0”
│ │ │ │ │ └─ 1– будет вывод ICW4 │ │ 0– не будет │ └────── 1– один контроллер │ 0– каскад └─────────── игнорируется 75
└──────────────── 0–запуск запросов фронтом 1–запуск запросов уровнем Бит 4, равный 1, определяет, что выводится ICW1, а не OCW2 или OCW3. Бит 3 (LTIM), равный 0, задает запуск запросов фронтом, при этом действует описанная выше схема: бит в РЗП сбрасывается при установке соответствующего бита в РОЗП. Бит 2 (ADI) используется только в ПЭВМ на базе микропроцессоров Intel 8080/8085. Бит 1 (SNGL) указывает на наличие в системе одного контроллера (если равен 1) или каскада из нескольких контроллеров (если равен 0). Если этот бит равен 1, то ICW3 не выводится в процессе инициализации и следом за ICW2 сразу должно следовать ICW4. Бит 0 (IC4) определяет, будет ли выводиться ICW4. Если ICW4 не выводится (бит 0 = 0), то оно автоматически заполняется нулями. В описываемых ПЭВМ наличие ICW4 обязательно, так как тип микропроцессора 8086/8088 задается в нем значением 1 в одном из битов. Управляющее слово ICW2 задает номер вектора прерывания для прерываний уровня 0 (например 8 для IBM PC, у которых по уровню «0» происходят прерывания от таймера). Так как вектора аппаратных прерываний располагаются подряд друг за другом, вывод в ICW2 значения 8 не только задает восьмой вектор для таймера, но и девятый для прерываний уровня 1, десятый (0Ah) для прерываний уровня 2 и так далее. Управляющее слово ICW3 выводится только при наличии каскада и имеет разный формат для ведущего и ведомых контроллеров. ICW3 ведущего указывает, к каким входам IR0 —IR7 подключены ведомые контроллеры, при этом соответствующие биты устанавливаются в 1. Остальные биты при этом равны 0. Пример – ICW3 следующего вида: A0 D7 D6 D5 D4 D3 D2 D1 D0 1║ 0 0 0 1 0 0 1 0 означает, что в каскаде имеется 2 ведомых контроллера, подключенных к входам IR1 и IR4. ICW3 ведомого (подчиненного, slave) ПКП в трех младших битах задает номер уровня, на котором работает ведомый контроллер. Для ведомого контроллера, работающего на уровне 1 ICW3 будет выглядеть следующим образом: A0 D7 D6 D5 D4 D3 D2 D1 D0 1║ 0 0 0 0 0 0 0 1 Если ведомый контроллер работает на уровне 4, то его ICW3 будет таким: A0 D7 D6 D5 D4 D3 D2 D1 D0 76
1║ 0
0
0
0
0
1
0
0
Последнее слово инициализации (ICW4) имеет следующий формат: A0 D7 D6 D5 D4 D3 D2 D1 D0 ┌─╥─┬─┬─┬───┬───┬──┬───┬───┐ 1 0 0 0 SFNM BUF M/S AEOI mPM └─╨─┴─┴─┴───┴───┴──┴───┴───┘ │ │ │ │ │ │ │ │ │ └── 1– 8088/8086 │ │ │ │ 0– 8080/8085 │ │ │ └─ 1–AEOI │ │ │ 0– EOI │ │ └───── 1– ведущий │ │ 0– ведомый │ │ (только при BUF=1) │ └───────────1– режим буферизации │ └────────────── 1– специальный вложенный режим Бит 0 (mPM) определяет, с каким микропроцессором работает ПКП (0 —8080/8085, 1 —8086/8088). Бит 1 (AEOI), равный 1, задает режим автоматического завершения обработки прерывания, описанный выше. Если этот бит равен 0, действует обычное соглашение: процедура обработки аппаратного прерывания должна сама сбрасывать свой бит в РОЗП. Бит 2 (M/S) игнорируется, если бит 3 (BUF) = 0. При наличии одного контроллера и BUF = 1 устанавливается в 1. При наличии каскада должен быть равен 1 только для ведущего контроллера. Бит 4 (SFNM) устанавливает специальный вложенный режим, применяемый при каскадировании для определения приоритетов запросов от разных контроллеров. После инициализации ПКП готов к работе в заданном режиме. Для изменения режимов работы, задаваемых при инициализации требуется переинициализировать его заново. В процессе работы с ПКП можно без переинициализации: — маскировать и размаскировать аппаратные прерывания; — изменять приоритеты уровней; — издавать команду завершения обработки аппаратного прерывания; — устанавливать/сбрасывать режим специальной маски; — переводить контроллер в режим опроса и считывать состояние регистров РОЗП и РЗП; для этого потребуется вывести в порты ПКП одно из трех слов команд обслуживания прерывания OCW1 —OCW3. 77
Формат первой команды обслуживания прерываний OCW1, которая при чтении позволяет получить состояние маски, а при записи — наложить маску на прерывания, выглядит так: A0 D7 D6 D5 D4 D3 D2 D1 D0 1 ║ M7 M6 M5 M4 M3 M2 M1 M0 Единичное значение одного из битов М0 —М7 означает, что прерывания соответствующего уровня (IR0 —IR7) маскируются и не будут обрабатываться контроллером. Вторая команда обслуживания прерываний OCW2 предназначено для вывода команды завершения обработки аппаратного прерывания (EOI), циклического сдвига и прямого изменения приоритетов уровней. Назначение битов OCW2 следующее: A0 D7 D6 D5 D4 D3 D2 D1 D0 ┌──╥──┬──┬──┬─┬─┬──┬──┬──┐ 0 R SL EOI 0 0 L2 L1 L0 └──╨──┴──┴──┴─┴─┴──┴──┴──┘ │ │ │ │ │ └── Номер уровня прерывания │ │ │ │ └───── в двоичном коде, если он │ │ │ └─────── требуется в команде. │ │ └─ 1 – Завершение обработки аппаратного прерывания │ │ │ │ Используются вместе с EOI=1 ┌────┐ Безличный EOI (сбрасывается бит РОЗП с максималь0│ 0 ным приоритетом обрабатываемого прерывания) ├────┤ Персонифицированный EOI (сбрасывает бит, определя0│ 1 емый кодом L0 —L2 в РОЗП) ├────┤ 1│ 0 Циклический сдвиг приоритетов влево на одну позицию ├────┤ Назначение низшего приоритета уровню, определяе1│ 1 мому кодом L0 — L2 └────┘ Как уже говорилось, процедура обработки аппаратного прерывания должна перед своим завершением очистить свой бит в РОЗП выводом команды завершения обработки прерывания (EOI). Существует два варианта команды EOI: безличный (обычный) EOI и персонифицированный EOI. Обычный EOI очищает бит в РОЗП, соответствующий прерыванию с максимальным приоритетом. Персонифицированный EOI (R=0, SL=1, EOI=1, L0 —L2 равно номеру уровня прерывания) очищает в РОЗП бит, соответствующий 78
прерыванию с номером, указанным в L0 —L2, независимо от его приоритета. Команды с битом R=1 позволяют изменить приоритеты уровней. Циклический сдвиг приоритетов сдвигает приоритеты влево на единицу, при этом, если после обычного распределения приоритетов, издать команду циклического сдвига, уровень 0 получит низший приоритет, уровень 1 — наивысший, уровень 2 — следующий за ним и так далее. Команда явного назначения низшего приоритета одному из уровней изменяет приоритеты остальных уровней циклически. Таким образом, если задать низший приоритет уровню 5, то уровень 6 получит наивысший. Третья команда обслуживания прерываний OCW3 позволяет установить и отменить режим специальной маски, перевести контроллер в режим опроса и прочитать содержимое РЗП и РОЗП. Назначение битов OCW3 приведено ниже: A0 D7 D6 D5 D4 D3 D2 D1 D0 ┌──╥──┬────┬────┬─┬─┬─┬─┬──┐ 0 0 ESMM SMM 0 1 P RR RIS └──╨──┴────┴────┴─┴─┴─┴─┴──┘ ┌───────┘ │ │ │ │ │ ┌─────────┘ │ │ │ ┌─┬─┐ ┌──────┐ 1 0 Отменить режим 0│1│0 Чтение РЗП ├─┼─┤ специальной маски ├──────┤ 1 1 Установить режим 0│1│1 Чтение РОЗП └─┴─┘ специальной маски ├──────┤ 1│ х│ х Режим опроса └──────┘ Единичное значение бита Р переводит контроллер в режим опроса. Если после этого считать данные из порта с четным адресом, в регистр AL загрузится байт следующего содержания: D7 D6 D5 D4 D3 D2 D1 D0 INT 0 0 0 0 L2 L1 L0 Если INT=1, значит имеются запросы на прерывания, и тогда L0 — L2 —это номер уровня с наивысшим приоритетом, по которому имеется запрос на прерывание. Если P=0, то можно считать информацию из РОЗП или РЗП. Для этого необходимо выдать команду чтения РОЗП или РЗП (смотрите выше) и затем считать значение из порта с нечетным адресом. Единичное значение бита ESMM позволяет в зависимости от значения бита SMM установить или отменить режим специальной маски. 79
Рассмотрим пример инициализации ПКП. Пример 4 —Известно, что адреса ПКП в микропроцессорной системе 0020 (АО=0) и 0021 (АО=1). Необходимо проинициализировать ПКП в соответствии с заданными векторами прерываний от устройств, приведенных в таблице 15, считая, что каскадирование ПКП отсутствует. Запрос по переднему фронту IRQi. Таблица 15 IRQi (двоич.)
N IRQ
Вектор
IRQ 0 IRQ 1 IRQ 2 IRQ 3 IRQ 4
000 001 010 011 100
0008 0009 000А 000B 000C
Устройство, вызывающее прерывание Таймер (F = 18,206507 Гц) Клавиатура Канал ввода-вывода Последовательный порт СОМ 1 Последовательный порт СОМ 2
Ответ 1) Составляем OCW 1 в соответствии с назначением бит этой команды (запуск IRQ фронтом; произвольные состояния - «0»): 0 0 0 1 0 0 0 1 1 1 2) ICW 2 равен вектору 08. 3) ICW 3 не нужен, так как только один ПКП. 4) ICW 4 составляем из условия обычного (не автоматического) завершения прерывания для процессора типа 8086: 0
0
0
0 1
1
1
0
O D Составляем фрагмент программы инициализации: MOV DX,0020 ; Адрес ПКП в DX (при AO = 0); MOV AL,11 ; ICW 1 в AL и оттуда OUT DX,AL ; в ПКП (при АО = 0); INC DX ; приготовить адрес 21 (при АО = 1); MOV AL,08 ; ICW 2 в AL и оттуда OUT DX,AL ; в ПКП (при АО = 1). MOV AL,0D ; ICW 4 в AL и оттуда OUT DX,AL ; в ПКП (при АО = 1). Вычислим адрес начального вектора (адреса отстоят друг от друга с шагом в 4 адреса). Это будет прерывание таймера. Вычисляем адрес вектора: 80
А = 0008х4 = 002016 = 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 ст.байт адреса мл.байт адреса В заключение можно отметить следующее: - программа инициализация ПКП обычно включается (как фрагмент) в программу инициализации микропроцессорной системы; - размаскирование запросов (команда CLI) должно проводиться в в самом конце программы инициализации микропроцессорной системы или в конце настройки параметров системы загружаемой программы ; - любая подпрограмма, вызываемая аппаратным прерыванием, должна содержать команды разрешения следующего аппаратного прерывания STI для микропроцессора и команды завершения обработки прерывания OCW2 (например, код 20 при А0=0) для контроллера прерываний.
14 Параллельный интерфейс Как уже отмечалось в предыдущей главе, обмен между микропроцессорной системой и внешними устройствами происходит, как правило, параллельным словом (байтом) или последовательным словом, когда информация передается побитно. Остановимся пока на протоколах передачи-приема параллельного слова. Если проанализировать всевозможные варианты существующих реализаций параллельных интерфейсов, то их можно глобально разбить на 4 группы: 1) Прием-передача без фиксации данных в портах интерфейса. 2) Прием-передача с односторонней фиксацией данных в портах интерфейса. 3) Прием-передача с протоколом обмена ИРПР (IRPR). 4) Прием-передача с протоколом обмена CENTRONICS. Первый тип параллельного интерфейса. В этом режиме (см.п.1)) интерфейс работает шинным формирователем, то есть просто усилителем, хотя по отношению к логике это понятие бессмысленное. Но логика заключается в том, что шинный формирователь может быть двунаправленным, а значит может требовать и соответствующей настройки. Назначение шинных формирователей —мультиплексирование множества двунаправленных параллельных магистралей на шину данных системной магистрали. Второй тип параллельного интерфейса. В этом режиме (см. п.2) порт интерфейса работает в режиме «с защелкой», то есть как регистр. Причем, фиксацию данных в порту производит, как правило, микропроцессорная система. Третий тип параллельного интерфейса. Интерфейс типа ИРПР кратко можно охарактеризовать как способ осуществления передачи данных (байта) в режиме диалога между двумя абонентами: источником 81
(передатчиком) и приемником. Этот диалог лучше всего представляется графически (рисунок 12): все здесь делается в инверсном виде.
Как видно из рисунка 12, данные в интерфейсе, то есть в порту «висят» все время. Но приемное устройство, которое принимает данные, «берет» их только в соответствии с протоколом. В чем особенность этого протокола? На рисунке стрелками указана последовательность действий. Передающая сторона ждет, когда
приемник сообщит о готовности (-ASK:=0). Рисунок 12 —Временная диаграмма протокола ИРПР Обнаружив готовность приемника, передающая сторона выставляет в порт новые данные и практически одновременно выставляет -STB=0 (строб передачи). Именно его ждет приемник. Как только приемник обнаруживает появление строба (-STB=0), он «забирает» с шины данных интерфейса байт данных (это не видно на графике) и тут же выставляет «занято» (-ASK=1), сообщая тем самым передатчику, что байт принят, и с ним началась работа. Передатчик, получив подтверждение о приеме байта, снимает строб (-STB=1). Так происходит один цикл приема-передачи байта в ИРПР (ИРПР —интерфейс радиальный параллельный). Четвертый тип параллельного интерфейса —CENTRONICS. Этот тип интерфейса схож с ИРПР и отличается от него некоторыми временными параметрами (рисунок 13). Как только приемник готов (BUSY=0), передатчик выставляет на шину данных интерфейса новые данные и с небольшой задержкой (не регламентирована) выставляет строб (-STB=0) на фиксированное время» 0,5 мкс. Таким образом, в протоколе нет подтверждения приема байта для съема строба передатчика. Приемник должен успеть в отведенное время 0,5мкс принять байт и выставить «занято» (BUSY=1) на время, пока он 82
«переваривает» принятый байт. По окончании обработки принятого байта приемник выставляет «свободен» (BUSY=0) и подтверждает этот момент коротким стробом -ACK=0 длительностью» 2,5мкс (см. рисунок 13).
Рисунок 13 —Временная диаграмма протокола CENTRONICS На практике применение в протоколе CENRONICS сигнала -ACK встречается крайне редко. Задуман он был разработчиками интерфейса как вызов прерывания На базе того, что было изложено, можно сделать вывод, что любой разработчик параллельного интерфейса постарается реализовать как минимум эти четыре варианта, чтобы интерфейсная схема пользовалась спросом. Фирма Intel разработала подобный параллельный интерфейс (ИФ): 8255. Отечественная копия: 580ВВ55. В дальнейшем будет именоваться: ИФ55. Рассмотрим архитектуру ИФ55 (рисунок 14). Опускаем ту часть схемы, которая осуществляет сопряжение с системной шиной, и начнем изучение сразу с существенных элементов. Из архитектуры следует (рисунок 14), что ИФ55 имеет три 8-и разрядных порта, причем все три двунаправленные. Каждый порт связан через внутреннюю шину данных через шинный формирователь с шиной данных системной магистрали. В составе ИФ55 имеется РУС —регистр управляющего слова, который разделен на две части. Первая часть РУС 83
(группа А) управляет портом A и старшей тетрадой порта C. Вторая часть РУС (группа B) управляет младшей тетрадой порта C и портом B. В скобках названий портов и РУС проставлены значения адресов A1,A0 (номеров) этих элементов.
Рисунок 14 —Архитектура параллельного интерфейса 8255 Микросхема выполнена по n-МОП технологии и запитывается от +5 В. Выход сопрягается со входами ТТЛ (ТТЛШ) элементов: 1 элемент ТТЛ или до 4-х элементов ТТЛШ. ИФ55 реализует 3 режима работы: 1) Режим 0 —нестробированный ввод-вывод; 2) Режим 1 —стробированный ввод или вывод; 3) Режим 2 —стробированный ввод-вывод (через порт A). Кроме этого, ИФ55 позволяет иметь особый доступ к отдельным разрядам порта C (особый режим). Все перечисленные режимы настраиваются с помощью управляющего слова после загрузки его в РУС. Рассмотрим, как составляется управляющее слово (УС), формат которого представлен на рисунке 16. Характеристика режимов. Режим 0. Если для группы А или В установлен режим 0, то порты этой группы, в зависимости от настройки, могут быть входами или выходами (рисунок 15). 84
а) Если порт —в состоянии «ввод», то он является шинным формирователем: ВШД:= <Шина данных интерфейса>. б) Если порт —в состоянии «вывод», то он является регистром (RGпорта), и шина порта подключена к выходу регистра RGпорта. На рисунке 15 приведена упрощенная схема управления режимом «ввод» «вывод».
Рисунок 15 —Упрощенная схема управления вводом-выводом ИФ55
Рисунок 16 —Формат управляющего слова Следовательно, если, к примеру, порт настроен на режим «ввод», и при этом выполняется команда OUT в этот порт, то данные на выходе порта обнаружены не будут. Поэтому при программировании портов надо сразу определиться, какой порт будет выходным, а какой — входным, и соответственно запрограммировать ИФ55. И потом, не задумываясь, можно использовать команды IN к входным портам и команды OUT —к выходным, так как направления в портах заданы. Режим 0 —самый эксплуатируемый режим. Пример 1 —Пусть чип ИФ55 выбирается в соответствии со следующим логическим уравнением: 85
CSИФ55=(-A9)∧(-A8)∧(-A7)∧(-A6)∧(-A5)∧(-A4)∧(-A3)∧(-A2). Составим таблицу адресов портов и РУС ИФ55 (таблица 16). Таблица 16 Имя РА РВ РС РУС
А9 0 0 0 0
А8 0 0 0 0
А7 0 0 0 0
А6 0 0 0 0
А5 0 0 0 0
А4 0 0 0 0
А3 0 0 0 0
А2 0 0 0 0
А1 0 0 1 1
А0 0 1 0 1
Н-код 000 001 002 003
Далее, пусть к порту РА подключены сигналы датчиков, а к портам РС и РВ —логика исполнительных устройств. Составим фрагмент программы инициализации ИФ55. Для этого синтезируем УС, выбрав, исходя из описания ИФ55, соответствующий заданным условиям режим 0 для всех портов: Н-код
9
0
1 0 0 1 0 0 0 0
Реж. 0,1,2 Реж.0 для гр.А: РА,РС7…0
ввод
Порт А: Порт С: Реж. 0 Порт В: Порт С: РС...4 для гр.В: вывод РС3…0 вывод РВ, вывод РС3…0
MOV DX,0003 ; Адрес РУС в DX; MOV AL,90 ; Управляющее слово в AL и OUT DX,AL ; оттуда в регистр управления слова. После выполнения этого программного фрагмента ИФ55 будет настроена: Режим 0; РА —ввод; РС и РВ —вывод. Режим 1. Стробированный ввод-вывод. В стробированном вводе (рисунок 17) или выводе (рисунок 18) могут участвовать только порты А и В. При этом часть шин порта С отключается в точке «а» (рисунок 15) от разрядов порта С и переключается на схему управления протоколом интерфейса, реализованную внутри ИФ55. Здесь не рассматривается схемное решение ИФ55 для режимов 1. Достаточно знать, что ИФ55 в режиме 1 поддерживает протокол ИРПР (правда, с несущественными оговорками).
86
Рисунок 17—Схема порта А в режиме 1 в состоянии «ВВОД» При записи данных РА7...РА0 в порт А (в регистр РА) ИФ55 вырабатывает сигнал -ASK=1 («мы заняты»). Но как сообщить микропроцессору, что данные приняты, и что их надо ввести в МП из регистра РА? Для этих целей существует вывод РС3, который можно подключить к контроллеру прерываний, и через него вызвать подпрограмму ввода байта из порта А. Как только выполнится команда IN, сигналом -IORD этой команды установится сигнал готовности: — ASK=0. Цикл окончен. С помощью разряда РС4 регистра порта С можно запрещать или разрешать вызов прерывания. Уравнение INT: INT=ASK^<триггер РС4>.
Рисунок 18 —Схема порта А в режиме 1 в состоянии «ВЫВОД» Из рисунка 18 следует, что для доведения параметров интерфейса до ИРПР необходимо ставить инвертор по линии -ASK. Это и есть маленькая оговорка. Очевидно, что она несущественна. Опять возникает ситуация: как микропроцессор узнает, что выведенную им информацию забрали из порта A? Это можно сделать опять с помощью прерывания, подключив вывод РС3 ко входу 87
контроллера прерывания ПКП. И как только -STB=0, и если триггер РС6=1, то будет инициировано прерывание. А как им распорядиться — это рассматривалось в главе 13. Следующим в режиме 1 рассмотрим порт В. Сначала рассмотрим этот режим для состояния «Ввод» (рисунок 19). Анализ рисунка 19 позволяет сделать вывод, что здесь полная идентичность режиму 1, «Ввод»—для порта A. Поэтому без всяких комментариев можно переходить к режиму 1, «Вывод»— для порта В (рисунок 20). Как видно из рисунка 20, и здесь полная идентичность режиму 1, «Вывод»—для порта A. Примечание —Если некоторые выводы порта С не задействованы в той или иной группе в режиме 1, то эта часть порта С может использоваться для ввода или вывода в режиме 0. В частности, очень часто через эти оставшиеся собственностью порта С выводы заводят сигналы INT (см. рисунки 17 —20), и организуют прерывание по опросу
этого сигнала. Рисунок 19 —Схема порта В в режиме 1 в состоянии «ВВОД» Рисунок 20 —Схема порта В в режиме 1 в состоянии «ВЫВОД» Режим 2. Он устанавливается только для порта A. Если внимательно посмотреть на выводы управления в режиме 1 порта A, то
88
можно обнаружить, что они различны для ввода и вывода, кроме INT (PC3). Так вот, в режиме 2 работает весь набор управления вводом и выводом для режима 1. И порт A уже не программируется на ввод или вывод. Это игнорируется режимом 2. А ввод сразу коммутируется командой IN , а вывод —командой OUT. Этот режим чрезвычайно редко используется. Задумывался он для организации интерфейса с флоппидиском, но вскоре появились специализированные контроллеры флоппидисков, и этот режим остался практически не востребованным. Особый режим —режим побитной записи в порт С. Еще его называют режимом прямого управления битами порта C. Пожалуй, последнее более точно отображает суть этого режима. Хотя и слово «режим» здесь не совсем уместно. Попробуем разобраться с ним и с управляющим словом по существу (рисунок 21). Что здесь важно отметить? 1) Если D7=1, то УС, отправленное в РУС по адресу А1=1, А0=1, действительно попадает в РУС и производит настройку режимов портов. 2) Если D7=0, то слово, отправленное в РУС по адресу А1=1,А0=1, на самом деле не попадает в РУС, то есть оставляет неизменным настроенный до того режим. Так куда же он попадает? А попадает он на схему управления записью в один из триггеров порта C. Остается только ознакомиться с расшифровкой этого псевдоуправляющего слова, представленного на рисунке 21 (здесь х —произвольное состояние). Трудно переоценить наличие такой возможности, которая позволяет изменить один бит РС, не трогая остальные. Пример 2 —Пусть к порту C, настроенному на вывод, подключены (через усилители тока) реле. Пусть ИФ55 подключен к системной шине и настроен в режим 0 в соответствии с примером 1. Необходимо выключить одно реле, подключенное логически к РС5.
89
Рисунок 21 —Формат управляющего слова для особого режима ИФ55. Ответ: Составляем псевдоуправляющее слово: iРС=510 0
X=0 x=0 x=0 0
РСi=0 —выключить ┌───────┐ ┌┐ 1 0 1 0 А
Тогда: MOV DX,0003 ; № РУС в DX; MOV AL,OA ; псевдоуправляющее слово в AL; OUT DX,AL ; РС5=0. Отметим, что при этом остальные реле останутся в прежнем состоянии. Такую процедуру невозможно выполнить посредством вывода байта в порт C. Ведь кроме того, что нужно РС5:=0, неизвестно, в какие состояния надо поставить остальные биты порта C, чтобы продублировать их (то есть, оставить неизменными). Исходное состояние ИФ55 после подачи на него питания +5В или после сигнала RES: — все порты в режиме 0; — состояние всех портов —ввод. Обычно в IBM совместимых компьютерах параллельный интерфейс обслуживает порт печати (LPT1, LPT2, LPT3), при этом полностью задействованы разряды только порта А —для вывода символа в кодах КОИ-8. Для реализации протокола CENTRONICS (рисунок 13) на РВ7 через инвертор подается сигнал BUSY, а на РС0 с последующим инвертированием выводится строб -STB. Ниже приведены адреса портов в существующих IBM PC, используемых по умолчанию. Таблица 17 —Адреса параллельных портов РС Имя порта РС Порт А Порт В Порт С LPT1 378 379 37A LPT2 278 279 27A LPT3 3BC 3BD 3BE Пример —Пусть принтер типа EPSON подключен к LPT1, и пусть байт для вывода на печать хранится в регистре DL. Составить подпрограмму вывода на печать . MOV DX,379 ; Читаем M1: IN AL,DX ; порт В AND AL,80 ; и анализируем занятость (-BUSY=0); JZ M1 ; если занято, то снова чтение -BUSY. DEC DX ; Подготавливаем адрес порта А MOV AL,DL ; и выводим туда 90
OUT DX,AL ; байт данных из регистра DL. ADD DX,+2 ; Подготавливаем адрес порта С IN AL,DX ; и устанавливаем бит D0, OR AL,01 ; не меняя содержимое остальных разрядов, OUT DX,AL ; сначала: D0=1, AND AL,FE ; затем: OUT DX,AL ; D0=0 —формируя таким образом STB. RET ; Представленный материал по параллельному интерфейсу 8255 не является исчерпывающим, так как он постоянно модернизировался в процессе создания новых поколений IBM PC. Начиная с PC на базе процессора 80186 стал не доступен РУС, при этом был реализован технологически только один режим режим 0 (NORMAL): РA и РC — вывод, РB —ввод). Начиная с поколения IBM PC на базе Pentium были реализованы модификация режима 2 (ECP) и его расширенный вариант (EPP). Установка режимов производится в SETUP BIOS.
15 Последовательный интерфейс 15.1 Антология последовательного интерфейса Прежде чем начать знакомство с контроллером последовательного интерфейса, полезно задаться вопросом: а зачем он вообще нужен? Действительно, параллельный интерфейс, по крайней мере, в 8 раз производительнее, так как за один раз передает сразу 8 бит, в то время как последовательный интерфейс —1 бит. Более близкое знакомство с историей этого вопроса наводит на мысль, что последовательный интерфейс своим появлением на свет никак не связан с вычислительной техникой. В начале ХХ века появилась радиосвязь, где носителем информации была азбука Морзе, каждый символ которой был представлен последовательностью точек и тире. Как только появился телеграф, азбука Морзе перешла и туда. Появились телеграфные аппараты, которые по двухпроводной линии посылали токовые посылки с одной стороны, а на другой стороне с помощью приемных аппаратах эти токовые посылки (пропорционально их длительности) включали электромагнит с грифелем, и на движущейся ленте наносились соответственно точки (или похожие на точки изображения) и тире. Со временем развития техники, в том числе и машинописной, и в связи с неудобством чтения текстов в азбуке Морзе, произошла замена кода из точек и тире на другой код из пяти разрядов, где наличие бита в разряде соответствовало токовой посылке. Чтобы телеграфный аппарат
91
мог распознавать начало кодовой посылки, в начале посылки безусловно располагался стартовый бит. Именно первая токовая посылка включала электромагнит привода набора комбинации механического дешифратора, осуществляемого последующими токовыми посылками (или их отсутствием). По окончанию набора из линии приходил длинный (короткого не хватало) токовый импульс, который приводил в движение рычаг той литеры, код которой совпадал с набором механического дешифратора. Диаграмма такой посылки, если принять наличие тока за «1», представлена на рисунке 22): Рисунок 22 —Диаграмма токовой посылки Теперь обратим внимание на печатающую машинку. У нее 2 регистра: верхний и нижний. Введение 2-х регистров не является обязательным условием. Это связано с тем, что если реализовать один регистр, то количество клавиш пришлось бы увеличивать вдвое. А теперь оценим, сколько комбинаций обеспечивает 5 пятиразрядный код: 2 = 32. Это явно мало. Поэтому две из этих комбинаций были выделены для кодирования верхнего и нижнего регистров, и таким образом стало возможным кодировать 30х2=60 символов. Но телеграфный аппарат получил такое стремительное развитие и распространение в середине века, что пришлось ввести еще 3-й регистр для кодирования национального шрифта, поскольку основным шрифтом во всем мире является латинский. Производительность телеграфных аппаратов ограничивалась, главным образом, его электромеханическими характеристиками и оценивалась в бод/сек. В переводе на язык вычислительной техники — это число разрядов или бит, переданных за секунду. Скорость эта располагалась в области 110 бод/сек. Так как передача организованна асинхронно, то для того, чтобы все биты попадали в свои временные ворота (особенно D4 —он дальше всех может «убежать»), приводные двигатели комбинаторов настраивались на одну скорость, которая в свою очередь настраивалась с помощью оптико-механического камертона и центробежного регулятора двигателя. Такие телеграфные аппараты (телетайпы) снабжались перфораторами (чтобы иметь копию сообщения на бумажной перфоленте) и фотосчитывателем (чтобы вместо ручного набора текста передать уже набранный и отредактированный текст на перфоленте). А когда получило свое начало развитие ЭВМ, в качестве консоли (место оператора для диалога с ЭВМ) и было взято это устройство телеграфной связи. Под него был разработан адаптер, так как телетайп работал в линии 60 В и с токами 100мА. К этому адаптеру была разработана интерфейсная схема. Так появился последовательный интерфейс. На сегодняшний день в двухпроводных линиях связи —как низкочастотных, так и высокочастотных, с различными видами 92
модуляции (с целью уплотнения сигналов) —существует множество протоколов обмена. И поскольку микропроцессорная техника тоже стала абонентом этих линий связи, то ей приходится «играть» по правилам существующих протоколов обмена. Одним из самых устоявшихся протоколов является протокол RS232. Чтобы легче понять его суть, рассмотрим рисунок 23. Из рисунка 23 следует, что микропроцессорная система (МПС) с линией связи сопрягается через модем (модулятор-демодулятор), который является своеобразным адаптером. Линия может быть свободна (Uлин=Еп) или занята (Uлин=ОВ), или идет передача модулированного сигнала в линию, или наоборот —все это должно быть отражено в слове состояния модема. Разберемся со всеми сигналами по порядку. TxD (travsmit data) —выход передатчика; RxD (receivt dat) —вход приемника; Теперь по управлению модемом (все сигналы рассматриваем с позиции ИФ как ведущего абонента):
Рисунок 23 —Схема соединения МПС и модема (нуль-модем) RTS (request to send) —требование к модему перейти в режим передачи (ИФ готов принимать данные от модема); CTS (clear to send) —сообщение от модема, что модем готов принимать данные от ИФ; DTR (data terminal ready) —требование к модему перейти в режим приема (ИФ готов передать данные ); DSR (data set ready) —сообщения от модема, что модем готов передавать данные к ИФ;
93
DCD (data carrier detect) —сообщение от модема , что модем обнаружил в линии сигнал, несущий информацию (например, кодовый символ, соответствующий адресу или имени данного абонента); RI (ring indicator) —сообщение от модема, что идет сигнал телефонного зуммера (звонка или другого звукового сигнала). Представленная схема соединения RS-232С называется полной (нуль-модем). Но в зависимости от категории линии, а зачастую и в отсутствие модема (линия RS-232 работает в диапазоне напряжений ±12 В), есть еще три стандартные схемы соединений, которые часто используются при соединении к компьютеру внешних устройств.
Рисунок 24 —1-й вариант RS-232С
Рисунок 25 —2-й вариант RS-232С. Последний вариант RS-232С (простейший) используется для организации сети из двух ЭВМ:
Рисунок 26 —3-й вариант RS-232С Из рисунков 24 и 25 следует, что такая коммутация наполовину обманывает программу, которая обслуживает протокол связи с модемом. А последний вариант (рисунок 26) вообще для обслуживающей программы является фикцией: требуя модем перейти в готовность к 94
передаче, ИФ сам переходит в состояние готовности передавать; требуя модем перейти в режим приема, ИФ сам себе сообщает о необходимости перейти в режим приема. Здесь для творчества имеется большое поле, особенно когда к последовательному ИФ подсоединяют нестандартные устройства, например, манипулятор типа «мышь» (MOUSE). Теперь о скорости обмена. По мере того, как электроника вытесняла механику из систем приема-передачи, скорость обмена все увеличивалась и увеличивалась. И сегодня поддержка низких скоростей —это скорее дань уважения прошлому, а может просто консерватизм. Современный стандарт скоростей (бод/с или бит/с.): 110; 150; 300; 600; 1200; 2400; 4800; 9600; 19200; 38400; 76800. Основной размер посылки: 7 бит (КОИ-7) и 8 бит (кои-8). Вместе с тем, оставили и то, что сегодня практически не используется. Например, длину слова в 5 бит. Поэтому разрядность современных последовательных ИФ: 5 бит; 6 бит; 7 бит; 8 бит. И последнее. В протоколе последовательных интерфейсов, как правило, предусматривается контроль передаваемой посылки. Он заключается в том, что в конце посылки генерируется дополнительный бит —контрольный бит. Он дополняет количество единиц в посылке до четного («чет») или нечетного («нечет») числа —в зависимости от настройки ИФ. А при приеме, если есть на то разрешение, производится аппаратный контроль, и в случае ошибки «чета»и «нечета» производится ее регистрация. 15.2 Архитектура последовательного интерфейса 8250 Теперь рассмотрим архитектуру последовательного ИФ 8250, представленную на рисунке 27. Подключение к системной шине стандартно (смотрите главу 12). Из рисунка 27 и комментария к нему следует, что записать в буфер передатчика или прочитать буфер приемника можно с помощью команд соответственно OUT и IN. Но это совсем не значит, что командой OUT можно инициировать передачу. Точно также, как и командой IN забрать слово из приемника, которое действительно было принято, а не «лежало» там неизвестно с каких пор.
95
Рисунок 27 —Архитектура последовательного интерфейса 8250 Поэтому особый интерес представляет правая часть схемы ИФ, связанная с приемником и передатчиком. Отметим сразу, что временные диаграммы передаваемого слова в RS-232 отличаются от телеграфного интерфейса стартовым битом: в протоколе RS-232 стартовый бит идет нулем. 15.2.1 Передатчик TxRDY —сигнал готовности передатчика принять следующее слово от МП (в этот момент еще может идти передача, но буфер передатчика уже свободен); TxE (END) —сигнал передатчика о том, что «вытолкнут» последний бит из сдвигающего регистра. На рисунке 28 представлена временная диаграмма, поясняющая временные взаимосвязи сигналов последовательного интерфейса 8250 (ИФ50) в режиме передачи. Сигнал TxRDY обычно заводят на контроллер прерывания либо его аналог через схему управления прерыванием (рисунок 27). Из рисунка 28 следует, что вывод очередного слова на передачу должен предваряться опросом: готов ли передатчик? И для того, чтобы иметь 100% уверенности, что передатчик пуст, нужно ориентироваться на сигнал ТхЕ. Сигнал TxRDY берут за основу готовности тогда, когда уверены в полном обеспечении канала передачи, и это позволяет «бросать» слово передатчику, не дожидаясь даже начала передачи, что позволяет МПС производительно использовать время для своих целей на время передачи
одного слова. Рисунок 28 —Временная диаграмма в режиме передачи ИФ50 15.2.2 Приемник 96
RxRDY —сигнал готовности приемника; устанавливается в «1», когда слово, преобразованное из последовательного кода в параллельный, сбрасывается из сдвигающего регистра приемника в буфер приемника (рисунок 27). Это действие настолько простое, что временная диаграмма здесь не нужна. Сбрасывается сигнал RxRDY (RxRDY=0) командой чтения (IN), то есть, как только забрали слово из буфера приемника, так готовность приемника сбрасывается. Дело в том, что RxRDY также подключается к контроллеру прерывания через схему управления прерыванием (рисунок 27) для вызова подпрограммы ввода, и этот вызов автоматически должен сниматься, как только слово из приемника заберут.
15.3 Описание регистров 8250 и программирование Программирование последовательного порта производится посредством операций с семью его управляющими регистрами и счетчиком-делителем частоты. Каждый регистр выбирается комбинацией адресных бит А2-А0. Функции каждого регистра описаны ниже. Примечание —DLAB (Divisor Latch Access Bit) —7-й бит регистра управления линией (адрес 011) —демультиплексирует направление программирования: или на приемопередатчик и регистр прерывания, или на делитель частоты. А2А1А0 Операци Назначение я 000 Запись Регистр передатчика – сюда засылается байт для передачи, если DLAB=0 Чтение Регистр приемника – отсюда извлекается принятый байт, если DLAB=0 Запись, Если DLAB=1, то сюда засылается младший байт чтение скорости обмена , 001 Запись, если DLAB=1, то сюда засылается старший байт чтение скорости обмена. Скорость задается значением делителя, равным 11520/V, где V – скорость бит/сек. Запись Регистр управления прерываниями (1=разрешить прерывание) при DLAB=0. Формат слова приведен ниже. D7 D6 D5 D4 D3 D2 D1 D0 ┌─┬─┬─┬─┬─┬─┬─┬─┐ │0 0 0 0 └─┴─┴─┴─┴─┴─┴─┴─┘ Разрешение прерываний 97
│ │ │ └ │ │ └── │ │ │ └──── │ └──────
А2 А1 А0 011
1 – прерывание по приему символа; 1 – прерывание по завершению передачи символа; 1 – прерывание по обрыву линии или или ошибке в линии; 1 – прерывание по изменению состояния модема (CTS, DSR, RI и DCD);
Операция Чтение/запис ь
Назначение Регистр управления линией
Формат слова и назначение разрядов: D7 D6 D5 D4 D3 D2 D1 D0 ┌─┬─┬─┬─┬─┬─┬─┬─┐ Длина данных └─┴─┴─┴─┴─┴─┴─┴─┘ 5 бит 0 0
00
6 бит 7 бит 8 бит 0 1 1 1 0 1
Число стоп-битов: 0 –1 бит ; (в битах) 1 – 1.5 при 5 бит. данных и 2.0 – при 6-8 бит. данных Тип четности Нет Нечетная Четная х 0 1 0 1 1 Постоянная четность: 0 – отмена постоянной четности, 1 – постоянный бит четности: если биты 3-4=01, то бит четности=1; если биты 3-4=11, то бит четности=0 1 —имитировать обрыв линии (посылка нулей) Бит DLAB:
1 — порты 000 и 001 для загрузки скорости обмена; 0 — порты 000, 001 в обычном режиме;
А2 А1 А0
Операция
011
Чтение
7 6
98
5 4
3
2
Назначение Регистр идентификации прерывания. Содержит причину прерывания 1
0
┌─┬─┬─┬─┬─┬─┬─┬─┐ │0 0 0 0 0 └─┴─┴─┴─┴─┴─┼─┴─┘ 0 – было прерывание Причина прерывания 1 1 Ошибка или обрыв линии; сбрасывается чтением регистра состояния линии (порт 101); 1 0 Принят символ; сбрасывается чтением приемника (порт 000); 0 1 Передан символ; сбрасывается записью символа в регистр передатчика (порт 000); 0 0 Изменение состояния модема (линий CTS, DSR, RI или DCD); сбрасывается чтением регистра состояния модема (порт 110); А2 А1 А0 100
Операция Запись
Назначение Регистр управления модемом
7 6 5 4 3 2 1 0 ┌─┬─┬─┬─┬─┬─┬─┬─┐ │0 0 0 └─┴─┴─┴─┴─┴─┴─┴─┘ │ │ │ │ └ 1 — установка DTR: DTR:=1; │ │ │ └── 1 — установка RTS: RTS:= 1; │ │ └ 1 — установка OUT1 (не используется); │ └1 — установка OUT2 (разрешить прерывания от 8050); └ 1 — диагностический режим (соединить выход со входом). А2 А1 А0
Операция
101
Чтение
Назначение Регистр состояний линии. Биты 1-4 вызывают прерывания по ошибке, если оно разрешено.
7 6 5 4 3 2 1 0 ┌─┬─┬─┬─┬─┬─┬─┬─┐ │0 └─┴─┴─┴─┴─┴─┴─┴─┘ │ │ │ │ │ │ └ 1 — данные приняты; сбрасывается
99
│ │ │ │ │ │ чтением приемника; │ │ │ │ │ └── 1 — потеря предыдущего символа («наезд»); │ │ │ │ │ │ │ │ │ └──── 1 — ошибка четности; │ │ │ │ │ │ │ └────── 1 — неверный стоп-бит; │ │ │ │ │ └──────── 1 — обнаружен обрыв линии; │ │ │ └────────── 1 — сдвиговый регистр передатчика пуст; │ └──────────── 1 — регистр передатчика пуст (вытолкнут последний бит) А2 А1 А0
Операция
110
Чтение
Назначения Регистр состояния модема. Биты 0-3 вызывают прерывание по изменению состояния модем, если оно разрешено:
7 6 5 4 3 2 1 0 ┌─┬─┬─┬─┬─┬─┬─┬─┐ └─┴─┴─┴─┴─┴─┴─┴─┘ │ │ │ │ │ │ │ └ 1 — изменилось состояние линии CTS; │ │ │ │ │ │ └── 1 — изменилось состояние линии DSR; │ │ │ │ │ └──── 1 — изменилось состояние линии RI; │ │ │ │ └────── 1 — изменилось состояние линии DCD; │ │ │ └──────── Состояние линии CTS; │ │ └────────── Состояние линии DSR; │ └──────────── Состояние линии RI ; └────────────── Состояние линии DCD. Примечание: «Изменилось состояние линии...» означает, что данная линия стыка RS-232 изменила свое состояние по сравнению с последним чтением этого регистра.
15.4 Порядок инициализации 8250 Для подготовки контроллера 8250 к работе необходимо выполнить следующие шаги. 1) Установить бит DLAB регистра 011 и заслать делитель, задающий скорость обмена, в порты 000 и 001.
100
2) Инициализировать регистр управления линией (порт 011); при этом сбросить бит DLAB. 3) Инициализировать регистр управления модемом (порт 100). 4) Инициализировать регистр управления прерываниями (порт 001) и, если прерывания разрешены, установить адрес программы обработки прерываний от стыка RS-232. В состав IBM PC могут входить до четырех последовательных интерфейсов, работающих в стандарте RS-232 (отечественный аналог — стык С2) и именуемых СОМ1 —СОМ4. Им выделены следующие адреса в области портов ввода-вывода (по умолчанию): СОМ1: 3F8h-3FFh, COM3: 338h-33Fh, COM2: 278h-2FFh, COM4: 238h-23Fh, где каждый интерфейс связан с определенным уровнем контроллера прерываний: СОМ1 вызывает прерывание IRQ4 (Int 0Ch); COM2 вызывает прерывание IRQ3 (Int 0Bh); СОМ3 и СОМ4 не имеют стандартных векторов прерываний. Кроме этого, современные компьютеры IBM PC позволяют свободно комбинировать логические и физические адреса и вектора прерываний последовательных интерфейсов через SETUP BIOS. Пример 1 —Пусть необходимо настроить порт СОМ1 со следующим режимом работы: — скорость приемо-передачи: 9600 бит/с; — длина посылки —8 бит; — контроль чет/нечет отсутствует; — длина стоп-бита —1 бит; — прерывание только от приемника по моменту приема символа. Определяем число деления: 11520010/960010=1210=000С. Составляем подпрограмму инициализации: MOV DX,3FB ; Установить адрес регистра управления линией MOV AL,80 ; и установить OUT DX,AL ; DLAB=1. SUB DX,+3 ; Установить адрес младшей части делителя MOV AL,0C ; и заслать туда 0С — OUT DX,AL ; число десятичное 12. XOR AL,AL ; Заслать «0» INC DX ; в старшую часть OUT DX,AL ; делителя. MOV AL,03 ; Заслать в регистр управления линией: DLAB=0; ADD DX,+2 ; длина посылки=8, контроль паритета=нет, OUT DX,AL ; длина стоп-бита=1 бит. MOV AL,80 ; Разрешить выход INT INC DX ; разблокированием выхода OUT2, которые соеди101
OUT DX,AL ; нены по схеме «монтажное ИЛИ» (рисунок 27). SUB DX,+4 ; Сбросить флаг RxRDY, если он случайно взвелся, IN AL,DX ; чтением приемника (исключаем ложный INT). MOV AL,01 ; Разрешить установление INT INC DX ; по окончанию приема символа в приемник (то есть, OUT DX,AL ; по флагу RxRDY). RET ; Пример 2 —Составить подпрограмму вывода символа из регистра DL в порт СОМ1. Как и в случае с LPТ, прежде, чем вывести символ, надо убедиться в готовности устройства. В данном случае, эта готовность выражается в том, что передатчик пуст (TxE=1) или пуст буфер передатчика (TxRDY=1). В нашем примере устраивает любой вариант. MOV DX,3FD ; Читаем M1: IN AL,DX ; регистр состояния линии AND AL,20 ; и анализируем занятость (RxE=0); JZ M1 ; если занято, то снова чтение. ADD DX,+5 ; Подготавливаем адрес передатчика MOV AL,DL ; и выводим туда OUT DX,AL ; байт данных из регистра DL. RET ;
16 Программируемый таймер Для задания временных интервалов и формирования сигналов с различными временными параметрами в IBM PC/XT применяется программируемый таймер 8253, в последующих поколениях —8254. С точки зрения программиста они идентичны. В состав таймера входят: буфер шины данных, схема управления вводом-выводом и три независимых канала, каждый из которых содержит регистр режима, схему управления каналом, буфер и 16-разрядный счетчик (рисунок 29). Счетчики декрементирующие (убывающий счет). Каждый счетчик Счi имеет свой адрес: Имя счетчика Счетчик 0 Счетчик 1 Счетчик 2 РУС таймера
А1 А0 00 01 10 11
РУС таймера – регистр упровляющего слова 3-х счетчиков: разбит на 3 РУС. С помощью РУС любой счетчик можно настроить на 6 режимов.
Каждый счетчик имеет выведенные наружу два входа и один выход: Сi —вход счетный по переднему фронту (предельная частота 2,5 МГц); СЕi —разрешение счета, если СЕ=1; OUTi —выход. 102
Рисунок 29 —Архитектура таймера 8253 Все режимы можно разбить глобально на две группы: а) режим деления частоты сигнала, поступающего на вход Сi; б) формирование временного интервала. Охарактеризуем кратко эти режимы. Программирование канала осуществляется путем вывода управляющих слов в регистр режима каналов и начального значения в его счетчики. Каждый канал может работать в одном из шести режимов.
16.1 Режим 0 (задержанный запрос на прерывание) При загрузке управляющего слова в регистр режима канала на выходе ОUT устанавливается напряжение низкого уровня; загрузка счетчика не изменяет это состояние. Затем начинается декремент счетчика (последовательное вычитание из него единицы). В момент, когда счетчик обнулится, на выходе OUT установливается напряжение высокого уровня и сохраняется до загрузки счетчика новым значением. Счет возможен только при наличие сигнала высокого уровня на входе СЕ. Низкий уровень этого сигнала или ниспадающий фронт запрещают счет. Перезагрузка счетчика во время счета приводит к следующему: загрузка младшего байта останавливает текущий счет, загрузка старшего байта запускает новый цикл счета. Минимально допустимое значение счетчика равно 2.
16.2 Режим 1 (ждущий мультивибратор) На выходе OUT формируется отрицательный импульс длительностью t=n×T, где n —число, загруженное в счетчик, T —период тактовых импульсов. Низкий уровень на выходе OUT устанавливается со следующего такта после подачи на вход СЕ сигнала высокого уровня. Загрузка в счетчик нового числа не влияет на длительность текущего импульса, а учитывается при следующем запуске. Перезапуск счетчика производится нарастающим фронтом входа GATE (без перезагрузки счетчика). Минимальное допустимое n=1.
16.3 Режим 2 (делитель частоты со сквозным переносом) При достижении счетчиком нуля на выходе OUT появляется отрицательный импульс с длительностью один такт. Перезагрузка счетчика сказывается только после перезапуска счетчика. При исчезновении сигнала высокого уровня на входе СЕ прекращается счет и на выход OUT подается напряжение высокого уровня. Перезапуск счетчика происходит при наличии на входе СЕ сигнала высокого уровня.
103
16.4 Режим 3 (делитель частоты с выходным сигналом «меандр») В этом режиме положительный уровень выходного сигнала занимает первый полупериод, а отрицательный —второй полупериод. Точнее, если n (начальное значение счетчика) четно, то длительность положительного и отрицательного полупериодов равна n×T/2; если же n нечетно —то (n+1)×T/2 и (n-1)×Т/2 соотвественно. Низкй уровень сигнала на входе СЕ запрещает счет, на выходе OUT устанавливается сигнал высокого уровня. Высокий уровень СЕ разрешает счет, а нарастание его запускает счетчик от начального состояния. Отметим, что n=3 в этом режиме недопустимо. Непредсказуем результат при загрузке в счетчик при СЕ=1.
16.5 Режим 4 (одиночный строб с программным запуском) При обнулении числа, загруженного в счетчик, на выходе OUT формируется отрицательный импульс длительностью один такт. Запись в счетчик во время счета младшего байта не влияет на текущий счет, а запись старшего байта перезапускает счетчик. Низкий уровень входа СЕ запрещает счет, высокий —разрешает. Минимальное допустимое значение счетчика равно 1.
16.6 Режим 5 (одиночный строб с аппаратным запуском) Особенность режима 4 состоит в том, что каждое нарастание сигнала на входе СЕ перезапускает счетчик. Перезагрузка счетчика не влияет на текущий цикл, однако следующий цикл определяется вновь занесенным числом.
16.7 Временные диаграммы таймера Временные диаграммы таймера приведены на рисунках 30 — 35.
Рисунок 30 —Режим 0
104
Рисунок 31 —Режим 1
Рисунок 32 —Режим 2
105
Рисунок 33 —Режим 3
Рисунок 34 —Режим 4
Рисунок 35 —Режим 5
16.8 Программирование таймера В IBM PC таймер имеет следующие программируемые регистры: Таблица 18 —Адреса таймера и их назначение Адрес Операция Назначение запись Загрузка счетчика канала 0 40h чтение Чтение счетчика канала 0 запись Загрузка счетчика канала 1 41h чтение Чтение счетчика канала 1 запись Загрузка счетчика канала 2 42h Чтение счетчика канала 2 чтение
106
43h
Запись
Запись управляющего слова в регистр режима канала
Управляющее слово имеет следующий формат: D7 D6 D5 D4 D3 D2 D1 D0
┌─┬─┬─┬─┬─┬─┬─┬─┐ └─┴─┴─┴─┴─┴─┴─┴─┘ Режим счетчика │ │ │ └ D0 : 0 – двоичный код, │ │ │ 1-двоично-десятичный код. │ │ └D3,D2,D1: Режим работы канала: │ │ 000 —режим 0; 001 —режим 1; x10 —режим 2; │ │ x11 —режим 3; 100 —режим 4; 101 —режим 5. │ └ D5,D4: Вид загрузки счетчика: │ 00 —«защелкивание»; 01 —только младший байт; │ 10 —только старший байт; │ 00 —младший байт, затем старший. └ D7,D6: Выбор канала: 00 – канал 0; 01 – канал 1; 10 – канал 2; 11 — запрещенная комбинация.
16.9
Чтение содержимого счетчиков
Существует два способа чтения текущего значения счетчика канала. 1) Чтение с остановом счетчика. Для обеспечения стабильных показаний необходимо приостановить работу канала либо подачей сигнала низкого уровня на вход CЕ (кроме режима 1), либо блокированием тактовых импульсов по входам С. 2) Чтение «на лету». Для считывания счетчика без остановки процесса счета используется посылка в порт 43h управляющего слова в режиме «защелкивания» (смотрите формат управляющего слова). Это управляющее слово фиксирует текущее значение счетчика, и можно считать его младший байт, а затем старший байт.
16.10 Таймер на системной плате IBM PC В IBM PC каналы таймера имеют следующее назначение. Таблица 19 —Назначение каналов таймера Канал Назначение 0
системные часы (IRQ0)
1
запрос для канала 0 ПДП (регенерация памяти)
Режим 3, счетчик=0 (65536) 2, счетчик=18
107
2
генератор звука
──
Тактовая частота каждого канала равна 1,19318 МГц, то есть каждый такт имеет длительность 0,84 мсек. Вход СЕ каналов 0 и 1 всегда имеют высокий уровень, поэтому счет на этих каналах разрешен всегда. Вход СЕ канала 2 управляется битом 0 порта PB интерфейса 8255 (адрес 61h). При начальной загрузке BIOS инициализирует канал 0 для работы в режиме 3 со счетчиком 0 (то есть 65536 декрементов на цикл счета). Поэтому частота системных часов равна 1,19 МГц/65536 =18.2 Гц и прерывание IRQ0, связанное с вектором Int 8, происходит 18,2 раз в секунду, т. е. каждые 55 мсек. Примечание —Конечно, можно перепрограммировать канал 0, но тогда, как минимум, нарушится работа с гибкими дисками, так как включение и выключение их двигателей отсчитывается по текущему времени. Канал 1 в ранних типах РС работает в режиме 2, осуществляя цикл регенерации ОЗУ, которая происходит каждые 18 мсек. Перепрограммировать его нельзя, т. к. это приведет к потере данных в ОЗУ. Таким образом, в руках пользователя остается только канал 2, который предназначен для генерации звука. Простейший способ генерации звука состоит в программировании канала 2 таймера так, чтобы он выдавал прямоугольный импульс заданной частоты, лежащий где-то в диапазоне: 80 Гц —15 КГц. Для этого следует использовать режим 3 таймера с подходящим начальным значением счетчика. Если затем установить биты 0 и 1 порта РВ (адрес 61h), который уже настроен (при инизиализации РС) на вывод в режиме 0, то импульс с выхода OUT2 начнет поступать на вход звукового излучателя (бит 0 —это вход СЕ канала 2, разрешающий счет, а бит 1 — разрешение выдачи выхода OUT2 на вход звукового излучателя). Для выключения звука достаточно сбросить биты 0, 1 в РВ (адрес 61h). Значение счетчика 2-го канала вычисляется по формуле n=1193181/ f=1234DDh/f (1193181 —тактовая частота таймера в Гц, f —требуемая частота звука). Пример 1 – Составить подпрограмму генерации звука; значение частоты звучания в Гц находится в ВХ. Составляем подпрограмму: MOV AX,34DD ; Присваивоить значение тактовой MOV DX,12 ; частоты на входе С паре: dx,ax:=1193181. CMP DX,BX ; Если <18Гц, то возврат, JNB M1 ; чтобы избежать далее переполнения. DIV BX ; Находится число : ax=(dx,ax)/bx MOV BX,AX ; —счетчика и сохраняется в ВХ. 108
MOV AL,0В ; Управляющее слово таймера: MOV DX,43 ; канал 2, режим 3, двоичный счет OUT DX,AL ; и вывод его в регистр режима. DEC DX ; Подготовить адрес счетчика канала 2 MOV AL,BL ; и вывести туда OUT DX,AL ; младший байт счетчика, MOV AL,BH ; а затем OUT DX,AL ; старший байт счетчика. IN AL,61 ; Установить биты 0, 1 порта РВ OR AL,03 ; —без изменения OUT 61,AL ; остальных бит порта В. M1: RET Пример 2 —Составить подпрограмму выключения звука. Составляем: IN AL,61 ; Сбрасываем биты 0, 1 порта РВ AND AL,03 ; без изменения OUT 61,AL ; остальных бит порта В. RET
17 Клавиатурный интерфейс Клавиатура формально является внешним устройством по отношению к микропроцессорной системе. Клавиатура, как функциональное устройство, организована на основе однокристальной ЭВМ класса Intel-8048 поэтому является интеллектуальным устройством, что очень часто игнорируется пользователями. Поэтому поучительно будет рассмотреть это, на первый взгляд, примитивное устройство. Взаимодействие с клавиатурой в PC AT (101 клавиша) и выше базируется на микропроцессоре Intel-8042, который расположен на системной плате. Этот процессор обеспечивает синхронный последовательный интерфейс с клавиатурой и имеет со стороны системной шины два адреса (порта) выборки. Порт с адресом 60h: а) Чтение: осуществляется ввод 7-и разрядного скан-кода клавиши при ее нажатии и отжатии; дополнительный бит —старший (8-й) бит, который передается вместе со скан-кодом, принимает состояние «0» при нажатии клавиши и состояние «1»— при ее отжатии. При поступлении скан-кода процессор 8042 выставляет сигнал INT, который подается на IRQ1 (вектор 09) ПКП. б) Запись: осуществляется передача микропроцессорной системе клавиатуры команда, перечень которых приведен ниже в таблице 20. Порт 64h: 109
а) Чтение: осуществляется ввод слова состояния клавиатуры. Под это отведен всего один разряд D1 (BUSY). Если D1=1, то клавиатура занята. б) Запись: Осуществляется передача команды процессору 8042, перечень которых приведен в таблице 22. Таблица 20 —Система команд управления клавиатурой (порт 61h) Код команды Описание FF Сброс клавиатуры и запуск внутреннего теста. FE Повторить последнюю передачу. FD Вызов прерывания IRQ1. Привести клавиатуру в исходное состояние и F6 разрешить сканирование. Привести клавиатуру в исходное состояние и f5 запретить сканирование. Сбросить буфер клавиатуры и начать F4 сканирование. Задать задержку и скорость ввода символов (таблица 21; первоначально клавиатура F3 data1 начинает повторять нажатую клавишу через 0,5 сек со скоростью 10 повторов в секунду). Эхо (для диагностики). Просто возвращает ЕЕ EE . ED data2 Управление светодиодами клавиатуры. 1) Синтез data 1: D7 D6 D5 D4 D3 D2 D1 D0
┌─┬─┬─┬─┬─┬─┬─┬─┐ 0 └─┴─┴─┴─┴─┴─┴─┴─┘ │ └ D4-D0: Код количества повторов в секунду; └ D6-D5: Начальная задержка в мсек: 00-250, 01-500, 10-750, 11-1000. Количество повторов задается следующей таблицей: Таблица 21 —Таблица кодирования повторов Конст. Скорость Конст. Скорость Конст. Скорость 00h 30.0 0Bh 10.9 16h 4.3 01h 26.7 0Ch 10.0 17h 4.0 02h 24.0 0Dh 9.2 18h 3.7 03h 21.8 0Eh 8.6 19h 3.3 04h 20.0 0Fh 8.0 1Ah 3.0 05h 18.5 10h 7.5 1Bh 2.7 06h 17.1 11h 6.7 1Ch 2.5 110
07h 08h 09h 0Ah
16.0 15.0 13.3 12.0
12h 13h 14h 15h
6.0 5.5 5.0 4.6
1Dh 1Eh 1Fh
2.3 2.1 2.0
2) Синтез data 2: D7 D6 D5 D4 D3 D2 D1 D0
┌─┬─┬─┬─┬─┬─┬─┬─┐ X X X X X └─┴─┴─┴─┴─┴─┴─┴─┘ │ │ └ D0: 1 — включить ScrollLock │ └ D1: 1 — включить NumLock └ D2: 1 — включить CapsLock Ниже представлены команды управления процессором клавиатурного интерфейса Intel-8042. Таблица 20 —Команды управления Intel-8042 (порт 64h) Код команды Описание DF Разрешить 20-битовую адресацию. DD Запретить 20-битовую адресацию. D1 Запись в порт вывода 8042. D0 Чтение порта вывода 8042. C0 Чтение порта ввода 8042. AE Разрешение клавиатуры. AD Запрещение клавиатуры. AC Чтение ОЗУ контроллера. AB Тест синхронизации и данных. Рассмотрим несколько примеров. Пример 1 —Включить индикатор Lock». Используя синтез data 2, составляем следующую подпрограмму: CLI CALL WAIT MOV AL,ED OUT 60,AL CALL WAIT MOV AL,02 OUT 60,AL STI
; Запретить прерывания (из-за клавиатуры). ; Готова ли клавиатура? ; Выдать команду управления ; индикаторами. ; Готова ли клавиатура? ; Если готова, то выставить второй ; байт команды: включение Num Lock (D1=1). ; Снять запрет с прерываний 111
RET ; и выйти. WAIT: IN AL,64 ; Подпрограмма опроса готовности клавиаTEST AL,02 ; туры: ввести слово состояния и проверить: D1=0 JNZ WAIT ; если не ноль, то снова его чтение. RET ; Пример 2 —Составить подпрограмму настройки клавиатуры на максимальную скорость передачи повторения скан-кода нажатой клавиши и начальную задержку 0,5 секунд между моментом пердачи первого скан-кода и ее повтора. Используя синтез data 2, получим значение второго байта команды: 20. Составляем подпрограмму: CLI CALL WAIT MOV AL,F3 OUT 60,AL CALL WAIT MOV AL,20 OUT 60,AL STI RET WAIT:IN AL,64 TEST AL,02 D1=0 JNZ WAIT RET
112
; Запретить прерывания (из-за клавиатуры). ; Готова ли клавиатура? ; Выдать команду задержки и скорости ; вывода скан-кодов. ; Готова ли клавиатура? ; Если готова, то выставить второй ; байт команды 20h. ; Снять запрет с прерываний ; и выйти. ; Подпрограмма опроса готовности клавиа; туры: ввести слово состояния и проверить: ; если не ноль, то снова его чтение. ;
18. Заключение Изложенный материал не в силах охватить другие важнейшие аспекты функционирования и программирования микропроцессорной системы и отдельных ее функциональных элементов, таких как: — защищенный режим и операции с 32-х разрядными опрерандами и адресами; — операции сопроцессора; — программирование изображения; — программирование чтения-записи на магнитных носителях (поверхностях) и тому подобное; Для этого требуется, кроме знаний в рамках цифровой электроники и программирования, наличие практического опыта эксплуатации и программирования микропроцессорных систем. По этой же причине не раскрывались полностью рассмотренные в настоящем пособии интерфейсные схемы. Основная цель пособия —ознакомить читателя с типовыми техническими решениями и характеристиками микропроцессора и основных специализированных интефейсных схем, дать начальные знания и навыки по их программированию. При успешном освоении представленного в учебном пособии материала пользователь может переходить к самостоятельному изучению микропроцессорных систем на базе 32-х разрядных процессоров фирмы Intel с технологиями PRO и MMX. Основной состав команд для самостоятельного изучения и использования приведен в приложении А. В заключение нужно отметить, что успех освоения изложенного курса возможен только при закреплении на практике основных технологических приемов, применяемых в микропроцессорных системах, с использованием всевозможных отладчиков и эмуляторов.
113
Приложение А Коды операций команд микропроцессоров 8088/80x86 Пересылочные команды MOV - пересылка данных Действие команды
Hex
Регистр/память в/из регистра Данные в регистр/память Данные в регистр Память в аккумулятор Аккумулятор в память Регистр/память в сегмент. регистр Сегмент. регистр в регистр/память
1 – й байт Binary 5 4 3 0 0 1 0 0 0 1 1 W 1 0 0 1 0 0
7 1 1 1 1 1
6 0 1 0 0 0
8E
1
0
0
0
8C
1
0
0
0
PUSH — загрузка в стек Действие команды Регистр/память Регистр Сегментный регистр
POP — извлечение из стека Действие команды В регистр/память В регистр В сегментный регистр
7 6 Mod mod
2 – й байт Binary 5 4 3 2 1 0 reg R/m 000 r/m
0
Mod
0
0
mod
0
2 1 0 d 1 1 Reg 0 0 0 1
0 W W
1
1
1
1
1
0
W W Re g Re g
R/m r/m
7 1 0 0
6 1 1 0
5 4 3 2 1 0 7 6 5 4 3 2 1 0 1 1 1 1 1 1 mod 1 1 0 r/m Reg 0 1 0 0 Reg 1 1 0
7 1 0 0
6 0 1 0
5 0 0 0
4 3 0 1 1 1 Reg
2 1 0 1 1 1 Reg 1 1 1
7 6 5 4 3 2 1 0 mod 1 1 0 r/m
XCHG — обмен значениями
Действие команды
7 6
1-й байт 5 4 3 2 1 0
Регистр/память с регистром
1 0
0
0 0
1 1 w
Регистр с аккумулятором
1 0
0
1 0
reg
2-й байт 7 6 5 4 3 2 1 mo d
reg
OUT —вывод в порт из AL
Действие команды
7
6
5
4
3
2
1
0
В порт с прямым адресом В порт - с адресом порта в DX
1 1
1 1
1 1
0 0
0 0
0 1
1 1
w w
IN —ввод из порта в AL 114
R/m
Действие команды
7 1 1
Из порта с прямым адресом Из порта - c адресом порта в DX
Команда – действие команды
He x
XLAT — кодирование AL по таблице LEA — загрузка адреса в регистр LDS — загрузка указателя в DS LES — загрузка указателя в ES LAHF — загрузка в AH из регистра F SAHF — сохранение в F PUSHF —загрузка в стек POPF —извлечение из стека
D7
6 1 1
5 1 1
4 0 0
3 0 1
2 1 1
1 0 0
0 w w
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 1 1 0 1 0 1 1 1
8D 1 0 0 C5 1 1 0 C4 1 1 0 9F 1 0 0
0 1 1 0 1 0 0 1 0 1 0 0 1 0 0
mod mod mod
reg reg reg
R/m R/m R/m
1 1 1 1 1
9E 1 0 0 1 1 1 1 0 9C 1 0 0 1 1 1 0 0 9D 1 0 0 1 1 1 0 1
Арифметические команды ADD —сложение Действие команды Регистр/память с регистром Данные с регистром/памятью Данные с аккумулятором
7 0 1 0
6 0 0 0
1-й байт 5 4 3 2 0 0 0 0 0 0 0 0 0 1 0 1
1 D S 0
2-й байт 7 6 5 4 3 2 1 0 mod Reg r/m mod 000 r/m
0 w w w
ADC —сложение с переносом
Действие команды
7 6 5 4 3 2 1
0
7
Регистр/память с регистром Данные с регистром/памятью Данные с аккумулятором
0 0 0 1 0 0 d 1 0 0 0 0 0 s 0 0 0 1 0 1 0
w w w
mod mod
6
5 4 3 2 1 0 reg r/m 0 1 0 R/m
INC —увеличение
Действие команды
7 6 5 4 3
2 1 0
Регистр/память Регистр
1 1 1 1 1 0 1 0 0 0
1
7 6 5 4 3 2 1 0
1 w mod 0 0 0 r/m Reg
SUB —вычитание
Действие команды
7 6 5 4 3 2 1
0
Регистр/память с регистром
0 0 1 0 1 0 d
w
Данные с регистром/памятью
1 0 0 0 0 0 s
w
Данные с аккумулятором
0 0 1 0 1 1 0
w
7 6 5 4 3 2 1 0 mo reg r/m d mo 1 0 1 R/m d
115
SBB —вычитание с учетом заема
Действие команды
7 6 5 4 3 2 1
0
Регистр/память с регистром
0 0 0 1 1 0 d
w
Данные с регистром/памятью
1 0 0 0 0 0 s
w
Данные с аккумулятором
0 0 1 0 1 1 0
w
7 6 5 4 3 2 1 0 mo reg r/m d mo 0 1 1 R/m d
DEC —уменьшение
Действие команды
7 6 5 4 3 2 1 0 7 6 5 4 1 1 1 1 1 1 1 w mod 0 0 0 1 0 0 1 reg
Регистр/память Регистр
CMP —срвнение Действие команды
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 0 0 1 1 1 0 d w mod reg r/m mo 1 1 1 R/m 1 0 0 0 0 0 s w d 0 0 1 1 1 1 0 w
Регистр/память с регистром Данные с регистром/памятью Данные с аккумулятором
Команда – действие команды MUL —умножение беззнаковое IMUL —умножение со знаком DIV —деление беззнаковое IDIV —деление со знаком NEG —изменение знака AAA —символьная коррекция для сложения DAA —десятичная коррекция для сложения AAS —символьная коррекция для вычитания DAS —десятичная коррекция для вычитания AAM —символьная коррекция для умножения AAD —символьная коррекция для деления CBW —преобразование байта в слово CWD —преобразование слова в двойное слово
116
3 2 1 0 1 R/m
He x
7 6 5 4 3 2 1 0
7
1 1 1 1 1
mod mod mod mod mod
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
0 0 0 0 0
1 1 1 1 1
1 1 1 1 1
w w w w w
37
0 0 1 1 0 1 1 1
27
0 0 1 0 0 1 1 1
3F
0 0 1 1 1 1 1 1
2F
0 0 1 0 1 1 1 1
6 5 4 3 2 1 0 1 1 1 1 0
0 0 1 1 1
0 1 0 1 1
r/m R/m R/m R/m R/m
1 1 0 1 0 1 0 0
0
0 0 0 1 0 1 0
1 1 0 1 0 1 0 1
0
0 0 0 1 0 1 0
98
1 0 0 1 1 0 0 0
99
1 0 0 1 1 0 0 1
Логические команды NOT- инвертирование
Действие команды Инвертирование
7 6 5 4 3 2 1 1 1 1 0 1
1 0 7 6 5 4 1 w mod 0 1
3 2 1 0 0 R/m
AND —логическое «и»
Действие команды Регистр/память с регистром Данные с регистром/памятью
7 6 5 4 3 2 1 0 7 6 0 0 1 0 0 0 d w mod 1 0 0 0 0 0 s w mod
Данные с аккумулятором
0 0 1 0 0 1 0 w
5 4 3 2 1 0 reg r/m 1 0 0 R/m
TEST —установка флагов по логическому «И»
Действие команды Регистр/память с регистром Данные с регистром/памятью
7 6 5 4 3 2 1 1 0 1 0 1 0 d 1 1 1 1 0 1 s
0 w w
Данные с аккумулятором
1 0 1 0 1 0 0
w
7 6 mod mod
5 4 3 2 1 0 reg r/m 0 0 0 R/m
7 6 mod mod
5 4 3 2 1 0 reg r/m 0 0 1 R/m
OR —логическое «ИЛИ»
Действие команды Регистр/память с регистром Данные с регистром/памятью
7 6 5 4 3 2 1 0 0 0 0 1 0 d 1 0 0 0 0 0 s
0 w w
Данные с аккумулятором
0 0 0 0 1 1 0
w
XOR —исключающее «ИЛИ» (сложение по модулю 2)
Действие команды Регистр/память с регистром Данные с регистром/памятью
7 6 5 4 3 2 1 0 0 1 1 0 0 d 1 0 0 0 0 0 s
0 w w
Данные с аккумулятором
0 0 1 1 0 1 0
w
7 6 mod mod
5 4 3 2 1 0 reg r/m 1 1 0 R/m
Команды сдвига Команда – действие команды
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
SHL —сдвиг арифметический влево
1 1 0 1 0 0 v w
SHR —сдвиг арифметическ. вправо
1 1 0 1 0 0 v w
SAR —сдвиг арифметический со знаком вправо
1 1 0 1 0 0 v w
ROL —сдвиг циклический влево
1 1 0 1 0 0 v w
ROR —сдвиг циклический вправо
1 1 0 1 0 0 v w
RCL —сдвиг циклический влево через флаг С
1 1 0 1 0 0 v w
mo d mo d mo d mo d mo d mo d
1 0 0
R/m
1 0 1
R/m
1 1 1
R/m
0 0 0
R/m
0 0 1
R/m
0 1 0
R/m 117
RCR —сдвиг циклический вправо через флаг С
1 1 0 1 0 0 v w
mo d
0 1 1
R/m
Обработка цепочек
Команда – действие команды
7 6 5 4 3 2 1 0
REP/ REPZ/ REPNZ —повторение строчной кманды MOVSB / MOVSW —пересылка байта/слова CMPSB / CMPSW—сравнение байта/слова SCASB / SCASW —просмотр байта/слова через аккумулятор LODSB / LODSW —загрузка байта/слова в аккумулятор STOSB / STOSW —сохранение байта/слова из аккумулятора
1 1 1 1 0 0 1 z 1 0 1 0 0 1 0 w 1 0 1 0 0 1 1 w 1 0 1 0 1 1 1 w 1 0 1 0 1 1 0 w 1 0 1 0 1 0 1 w
Вызов подпрограммы
Команда – действие команды
He x
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
CALL NEAR Addr IP – Прямой близкий CALL NEAR Reg/Mem – Косвенный близкий CALL AddrCS:IP - Прямой далёкий CALL FAR Mem – Косвенный далёкий
E8
1 1 1 0 1 0 0 0
FF
1 1 1 1 1 1 1 1
9A
1 0 0 1 1 0 1 0
FF
1 1 1 1 1 1 1 1
Безусловный переход Команда – действие команды JMP NEAR Addr IP – Прямой близкий JMP NEAR Reg/Mem – Косвенный близкий JMP AddrCS:IP - Прямой далёкий JMP FAR Mem – Косвенный далёкий JMP SHORT Addr IP - Короткий
He x
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
E9
1 1 1 0 1 0 0 1
FF
1 1 1 1 1 1 1 1
EA
1 1 1 0 1 0 1 0
FF
1 1 1 1 1 1 1 1
EB
1 1 1 0 1 0 1 1
Возврат из подпрограммы Команда – действие команды RETN – Близкий RETN Disp – Близкий с коррекцией SP 118
mod
1 0 0
R/m
mod
1 0 1
R/m
Hex C3
7 6 5 4 3 2 1 0 1 1 0 0 0 0 1 1
C2
1 1 0 0 0 0 1 0
mod
0 1 0
mod
0 1 1
RETF – Далекий RETF Disp - Далекий с коррекцией SP
CB CA
1 1 0 0 1 0 1 1 1 1 0 0 1 0 1 0
Команды условного перехода (SHORT ADDRESS) Hex 7 6 5 4 3 2 1 0 Команда – действие команды JE/JZ —переход при [=] JL/JNGE —переход при [<] JLE/JNG —переход при [≤] JB/JNAE —переход при [<] без знака JBE/JNA —переход при [≤] без знака JP/JPE —переход при чётном числе «1» JO —переход при арифм. переполнении JS —переход при знаке [-] JNE/JNZ —переход при [≠] JNL/JGE —переход при [≥] JNLE/JG —переход при [>] JNB/JAE —переход при [≥] без знака JNBE/JA —переход при [>] без знака JNP/JPO —переход при нечёт. числе «1» JNO —переход при ариф. непереполнен. JNS —переход при знаке [+]
74 7C 7E 72 76 7A 70 78 75 7D 7F 73 77
0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 1 0 0 1 0 1 0 1 1 0 0
1 1 1 0 1 0 0 0 1 1 1 0 1
0 0 1 1 1 1 0 0 0 0 1 1 1
0 0 0 0 0 0 0 0 1 0 0 0 0
7B
0 1 1 1 1 0 1 0
71 79
0 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0
Команды для организации циклов (SHORT ADDRESS) Hex 7 6 5 4 3 2 1 0 Команда – действие команды LOOP —декремент СХ и переход, если СХ≠0 (конец цикла, если СХ=0) LOOPE/LOOPZ – декремент СХ и переход, если СХ≠0 и Z=1 (конец цикла, если Z=0 или СХ=0) LOOPNE/LOOPNZ – декремент СХ и переход, если СХ≠0 и Z=0 (конец цикла, если Z=1 или СХ=0) JCXZ —переход, если СХ=0
E2
1 1 1 0 0 0 1 0
E1
1 1 1 0 0 0 0 1
E0
1 1 1 0 0 0 0 0
E3
1 1 1 0 0 0 1 1
Команды для обработки прерываний Hex 7 6 5 4 3 2 1 0 Команда – действие команды INT 3 - Третьего типа INT n - Любого n-типа (вектор n -1 байт) INT 0 — прерывание по перполнению IRET —возврат из прерывания
CC
1 1 0 0 1 1 0 0
CD
1 1 0 0 1 1 0 1
CE CF
1 1 0 0 1 1 1 0 1 1 0 0 1 1 1 1
Команды управления флагами и состоянием микропроцессора
Команда – действие команды CLC — cброс флага C (C=0) CMC— инверсия флага C
Hex 7 6 5 4 3 2 1 0 7 F8 F5
6 5 4 3 2 1 0
1 1 1 1 1 0 0 0 1 1 1 1 0 1 0 1 119
STC — установка флага C (C=1) CLD — сброс флага D (D=0) STD — установка флага D (D=1) CLI — запрет аппаратного прерывания (I=0) STI — разрешение аппаратного прерывания (I=1) HLT— останов (отключение микопроцессора от системной шины) WAIT — ожидание ESC OPCODE— переключение направления загрузки кода операции на сопроцессор LOCK — префикс захвата NOP — пустая команда
F9 FC FD
1 1 1 1 1 0 0 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 1
FA
1 1 1 1 1 0 1 0
FB
1 1 1 1 1 0 1 1
F4
1 1 1 1 0 1 0 0
9B
1 0 0 1 1 0 1 1
D8
1 1 0 1 1 0 0 0
F0 90
1 1 1 1 0 0 0 0 1 0 0 1 0 0 0 0
mo d
0 0 0
Команды префикса однократного замещения сегмента
Команда – действие команды ES: —замещение на ES (кроме SS и CS) CS:—замещение на CS (кроме SS) SS: —замещение на SS (кроме CS) DS:—замещение на DS (кроме SS и CS)
120
Hex
7 6 5 4 3 2 1 0
26 2E 36
0 0 1 0 0 1 1 0 0 0 1 0 1 1 1 0 0 0 1 1 0 1 1 0
3E
0 0 1 1 1 1 1 0
R/m