Текст
                    В. Л. Григорьев
АРХИТЕКТУРА
И ПРОГРАММИРОВАНИЕ
арифметического
сопроцессора
МОСКВА
ЭНЕРГОАТОМИЗДАТ
1991


ББК 32.97 Г 83 УДК 681.326.3 Рецензент К. Н. Чернышов Григорьев В. Л. Г 83 Архитектура и программирование арифметического сопроцессора.— М.: Энергоатомиздат, 1991.— 208 с: ил. ISBN 5-283-01606-4 Рассмотрены внутренняя организация, режим работы, форматы, чисел и система команд арифметического (математического) сопроцессора К1810ВМ87. Приведены особенности со- проаессорных конфигураций и примеры программирования. Для инженерно-технических работников, занимающихся разработкой н применением микропроцессорной техники, и студентов вузов, специализирующихся в области электронной об- . работки данных. 2404000000-016 Г 226-91 ББК 32.97 051(01)-91 ISBN 5-283-01606-4 © Автор. 1991
ПРЕДИСЛОВИЕ В связи с расширением сферы применения микропроцессоров постоянно предъявляются все более высокие^ требования к их быстродействию, допустимым форматам данных и точности вычислений. Существующие однокристальные микропроцессоры с длиной слова 8 и 16 бит оперируют фактически с двумя простыми форматами численных данных: знаковыми и беззнаковыми целыми двоичными числами, хотя с определенными ограничениями допускают десятичные целые числа. Вычислительные возможности их ограничены только арифметическими операциями. Реализация расширенных форматов данных и систем команд в однокристальных микропроцессорах ведет к их чрезмерному усложнению и трудностям программирования. Программная реализация сложных команд (по принципу «запрограммировать можно все») связана со значительным снижением производительности. Более того, появившиеся стандарты на численные данные и особенности их обработки, во-первых, усложнили форматы чисел (достаточно сказать, что числа с плавающей точкой могут иметь 15 бит порядка и 64 бита мантиссы) и, во-вторых, потребовали учета многочисленных особых случаев и единообразных реакций на их возникновение. Программная реализация операций над числами в стандартных форматах становится чрезвычайно громоздкой. Как возможный подход представляется применение секционных микропроцессоров. Разработав соответствующие микропрограммы, можно реализовать практически любые операции с приемлемым быстродействием. Однако такое решение имеет свои недостатки, один из которых заключается в увеличении числа микросхем [например, для параллельного процессора с длиной слова 80 бит потребуется 20 (!) 4-битных процессорных секций]. Кроме того, объем микропрограмм, рассчитанных на стандартные форматы чисел, специальные численные значения и особые случаи, окажется чрезмерно большим. !♦ 3
Наконец, нельзя забывать и об увеличений мощности, потребляемой процессором. В сложившейся ситуации плодотворным оказался принцип специализации, который давно применяется в процессорах средних и больших компьютеров. Суть его заключается в разработке вспомогательных процессорных модулей со своими системами команд, ориентированными на конкретные прикладные области, — процессор арифметики с плавающей точкой, процессор символьных данных, процессор ввода-вывода и др. Такие вспомогательные процессоры работают под общим управлением центрального (главного) процессора и обычно разделяют с ним основную память. Специализация позволяет достичь очень высокого быстродействия и повысить эффективную производительность системы благодаря параллельной работе нескольких процессоров. Имеются4 Две основные конфигурации сильно связанных мультипроцессорных систем, т.е. систем, в которых процессоры взаимодействуют через основную память. Конфигурация с независимыми процессорами предполагает наличие у каждого вспомогательного процессора своей программы, содержащей команды именно этого процессора. При необходимости центральный процессор формирует блок# параметров для вспомогательного процессора и инициирует его действия специальным сигналом. После этого центральный и вспомогательный процессоры работают параллельно, выполняя свои программы. В такой конфигурации у независимого процессора могут быть локальные память и периферийные устройства. В сопроцессорной конфигурации вспомогательный процессор (именно его и называют сопроцессором) подключается к системной шине параллельно центральному процессору. Сопроцессор не имеет своей отдельной программы и не может считывать команды из памяти, но может обращаться к памяти для записи и считывания данных, запрашивая для этого шину центрального процессора. Кроме того, сопроцессор контролирует системную шину и может «перехватывать» адреса и данные при обращениях к памяти центрального процессора. Часть кодов операций центрального процессора резервируется для команд сопроцессора, и действия центрального процессора при их «выполнении» сводятся к формированию физического адреса памяти и обращению в память. Со- 4
процессор не может выполнять команды центрального процессора, но свои команды выполняет очень быстро (по сравнению с их программной эмуляцией в командах центрального процессора). Таким образом, программа оказывается смесью команд центрального процессора и сопроцессора, причем считывание команд из памяти осуществляет только центральный процессор, а затем команды подаются параллельно в оба процессора. Каждый из них выбирает из общего командного потока и выполняет свои команды. Такое своеобразное «разделение труда» позволяет достичь в системе очень высокой производительности в тех задачах, на которые ориентирован сопроцессор. Первым из сопроцессоров, предназначенных для работы с центральным процессором К1810ВМ86, появился процессор численных данных, или арифметический сопроцессор К1810ВМ87. Он рассчитан на применение в системах с интенсивной численной обработкой, в которых: зисленные данные изменяются в очень широком диапазоне; при реализации алгоритмов возникают очень большие и малые промежуточные результаты; требуется высокая точность вычислений; необходима производительность, превышающая возможности центрального процессора. Примерами подобных систем могут служить системы обработки экономической информации, управления технологическими процессами со сложными алгоритмами обработки, прецизионные системы численного программного управления, робототехнические и навигационные системы, графические интерактивные терминалы с локальной обработкой изображений и др. Кроме того, приведенные выше требования предъявляются в задачах моделирования, цифровой обработки сигналов, оптимизации й т. д. Необходимо учитывать также, что относительная простота программирования и поразительные возможности сопроцессора К1810ВМ87 делают его доступным для большой группы пользователей, не знакомых с тонкостями программирования сложных вычислительных задач. Достаточно сказать, что диапазон чисел его внутреннего формата составляет примерно ±3«10±500°, точность соответствует 18 десятичным разрядам. Наряду с традиционными арифметическими 5
командами он имеет команды таких сложных операций, как извлечение квадратного корня, вычисления тригонометрических и обратных тригонометрических функций, возведение в степень, логарифмирование и др. Необходимо отчетливо представлять себе, что сопроцессор К1810ВМ87 не может работать изолированно от центрального процессора К1810ВМ86, Вдвоем они образуют мощный тандем, производительность которого в задачах численной обработки данных в 10—50 раз и более выше производительности одного центрального процессора. В этом тандеме объединены системы команд, внутренние регистры и форматы данных обоих процессоров. Его вычислительная мощность сравнима с вычислительной мощностью мини-ЭВМ. Конечно, при совместной работе двух процессоров возникают специфические проблемы их взаимодействия — разделение общей системной шины, доступ к памяти, синхронизация по командам и данным. Чтобы читатель ориентировался в тонкостях этого взаимодействия, в гл. 1 дано краткое описание микропроцессора К1810ВМ86. Целесообразность включения в книгу этого материала объясняется еще и тем, что при программировании управление программой и адресация памяти осуществляются только с помощью команд и режимов адресации микропроцессора К1810ВМ86. Наконец, наличие такого описания делает книгу достаточно автономной. В гл. 2 достаточно подробно рассмотрена архитектура сопроцессора К18Л0ВМ87, а в гл. 3 приведено несколько примеров его программирования. Цель издания книги определяется, во-первых, необходимостью все' более широкого использования арифметических сопроцессоров, и, во-вторых, отсутствием литературы по их применению. Считаю своим приятным долгом выразить благодарность рецензенту канд. техн. наук Ю. Н. Чернышову и всем читателям, которые выскажут замечания и предложения по книге. Их можно направлять по адресу: 113Н4, Москва, М-114, Шлюзовая наб., 10, Энергоатом- издат. Автор
Глава 1 МИКРОПРОЦЕССОР К1810ВМ86 КАК ЦЕНТРАЛЬНЫЙ ПРОЦЕССОР Микропроцессор К1810ВМ86 относится к классу однокристальных центральных процессоров с фиксированными системой команд и длиной слова. Он является базовым для нескольких моделей профессиональных персональных компьютеров, обладающих очень широкими возможностями. Безусловно, этот микропроцессор будет применяться и во многих специализированных системах, где требуется высокий уровень «машинного интеллекта», С появлением арифметического сопроцессора будут реализованы мощные микросистемы, предназначенные для сложной обработки данных. Однокристальный процессор ввода-вывода расширит область их применения на системы с интенсивными операциями ввода-вывода. Естественным следствием увеличения возможностей микропроцессоров является все более громоздкое и сложное описание их функционирования, что приводит и к усложнению языка ассемблера. В то же время для программирования систем с арифметическим сопроцессором К1810ВМ87 необходимо знать именно язык ассемблера, так как языки высокого уровня с поддержкой арифметического сопроцессора пока не получили широкого распространения. Поэтому в настоящей главе очень кратко рассмотрена архитектура микропроцессора К1810ВМ86 [1—3]. 1.1. ОБЩАЯ.ХАРАКТЕРИСТИКА МИКРОПРОЦЕССОРА Микросхема К1810ВМ86 выполнена по высококачественной NMOII-технологии с плотностью упаковки около 30 000 транзисторов. Адресное пространство памяти составляет 1М байт, и адрес любого байта состоит из 7
20 j6ht. Два смежных байта образуют слово; адресом слова считается меньший адрес, по которому хранится младший байт слова. Принцип «младшее — по меньшему адресу» распространяется на хранение всех производных от байта единиц данных, в том числе и на данные арифметического сопроцессора. Микропроцессор (МП) оперирует только байтами и словами, поэтому все обрабатываемые им адресные* объекты должны иметь длину 16 бит. Для образования 20-битных физических адресов памяти .применяется специальный механизм сегментации памяти. С точки зрения программиста наиболее важными элементами МП являются внутренние регистры, к которым приходится обращаться при разработке ассемблерных программ. Микропроцессор имеет 14 16-битных регистров. Четыре регистра общего назначения -(РОН) могут содержать любые данные и находятся в полном распоряжении программиста, хотя в некоторых командах они выполняют специальные функции. Два указательных и два индексных регистра предназначены для адресации данных в памяти, т. е. привлекаются для формирования эффективного адреса в соответствии с режимами адресации. Но они же могут участвовать в арифметических и логических операциях, что повышает гибкость адресации памяти. Четыре сегментных регистра, идентифицирующих базовые (начальные) адреса сегментов, привлекаются для образования физических адресов памяти. При каждом обращении к памяти один из сегментных регистров участвует в формировании физического адреса. Регистр указателя команды IP адресует программную память, т. е. выполняет функции программного счетчика PC (или счетчика команд). Регистр флажков разделен на две половины. Его младший байт содержит пять арифметических флажков, фиксирующих особенности (признаки) результатов операций. В старшем байте находятся флажок переполнения и три флажка управления МП. Микропроцессор имеет развитую систему команд, многие из которых оперируют байтами и словами. Предусмотрены команды всех арифметических операций, разнообразных сдвигов, команды манипуляций цепочками, множество команд передачи управления, команды прерываний и управления МП. Общая организация «регистр — память» предполагает, что в двухоперандных 8
командах нельзя адресовать две ячейки памяти. Режимы адресации МП ориентированы на эффективную реализацию языков высокого уровня и обработку сложных структур данных. Пространство ввода-вывода образуют 64К портов ввода-вывода, причем их адресация осуществляется без привлечения механизма сегментации. Имеются прямая и косвенная адресация портов. Через порты разрешается вводить/выводить байты и слова. Взаимодействие МП с другими компонентами системы производится с помощью мультиплексной шины адреса/данных/состояния и управляющих-сигналов. Особенностью МП является возможность работы в двух конфигурациях, определяемых уровнем сигнала на одном из входов. В зависимости от конфигурации изменяются функции восьми управляющих сигналов. В максимальной конфигурации, предназначенной для сложных мультипроцессорных систем, в частности систем с сопроцес-. сором, управляющие сигналы формирует контроллер, шины (микросхема К1810ВГ88). Во внутренней организации МП выделяются два сравнительно автономных устройства: шинный интерфейс и операционное устройство, первое из которых осуществляет выборку команд и считывание/запись данных, а второе собственно выполняет команды. Эти устройства работают параллельно, т. е. шинный интерфейс самостоятельно инициирует выборку следующей команды из памяти, в то время как операционное устройство занято выполнением ранее выбранной команды. Считанная шинным интерфейсом кбманда попадает во внутреннюю очередь (буфер) команд, и, когда операционное устройство заканчивает выполнение текущей команды, оно обычно находит следующую команду в очереди. Благодаря такой опережающей выборке команд повышается произво- Де a cm Вин тинного интерфейса: Выборка [ команды Выборка капапды Выборка команды Выборка • команды Выборка команды Обращения к данным | ^**ч^ ^^^-^Г *-__ / у Ожидание Выполнение команды Выполнение команды f Выполнение команды 1 Действия операционного устройства Рис. 1.1. Параллельная работа двух устройств микропроцессора
дительность МП. Когда операционному устройству тре-1 буется обращение к памяти данных, оно запрашивает] его у шинного интерфейса. Принцип опережающей вц-< борки команд показан на рис. 1.1. i 1.2. СИГНАЛЬНЫЕ ЛИНИИ Взаимодействие МП .с внешней средой заключается в выполнении одного из двух действий: МП либо выво- дит (записывает) данные, либо вводит (считывает) дан-| ные или команды. В каждом из этих действий он должен j адресовать ячейку памяти или порт ввода-вывода. Для передачи данных или выборки команды МП иниJ циирует цикл шины: строго определенную последбватель-] ность событий, в результате которой слово (байт) передается из источника в получатель. В течение цикла шины МП выдает адрес ячейки памяти или порта, ввода-выво-1 да, а также показывает сигналами состояния тип цикла j шины. Эти сигналы контроллер шины преобразует в необходимые управляющие импульсы, определяющие конкретные действия в цикле шины. Адресованное устройство либо воспринимает данные с шины (МП выдает их] после адреса), либо помещает на шину свои данные. , \ На рис. 1.2 показано группирование сигнальных линий МП по функциональному назначению. Уровень напряжения на входе MN/MX задает конфигурацию МП — минимальную или максимальную. Рассмотрим назначение сигнальных линий в максимальной конфигурации. Системную шину адреса/данных/состояния образуют. 20 линий. AD1S-AD0 — мультиплексная двунаправленная] шина адреса/данных. По ее 16 тристабильным линиями с разделением во времени передаются младшие 16 бит адреса памяти (или полные адреса ввода-вывода) и данные. A19/ST6-A16/ST3 — мультиплексная выходная шина адреса/состояния. В начале цикла шилы на эти линии; выдаются старшие 4 бита адреса памяти, а затем сигналы состояния ST, которые обычно не используются. Шесть выходных сигналов определяют действия МП в текущем цикле шины. _ R (или RD) — считывание. Сигнал R идентифицирует считывание из памяти или ввода-вывода. ST2—ST0 — сигналы состояния. Эти сигналы в зако- 10
Рис. 1.2. Сигнальные линии микропроцессора К1810ВМ86 днрованной форме показывают тип текущего цикла шины. Они подаются в контроллер шины, который форми- рует управляющие импульсы для системной шины. LOCK — блокировка шины. Активный сигнал на этом выходе информирует о том, что доступ к шине должен быть заблокирован (запрещен). Он генерируется по однобайтному префиксу блокировки шины и поддерживается активным до окончания следующей за префиксом команды. BHE/ST7 — разрешение старшего байта/состояние. Низкий уровень этого сигнала в начале цикла шины означает, что байт данных передается по старшей половине AD15-AD8 шина данных. Два сигнала предназначены только для сопроцессоров. QS1-QSQ —-состояние очереди команд. Значения этих выходных сигналов идентифицируют операцию очереди команд. Сопроцессор также поддерживает очередь команд, но его сигналы QS1-QS0 являются входными. Соединение линий микропроцессора и сопроцессора обеспечивает синхронизацию действий -обоих устройств. Две двунаправленные линии предназначены для разделения шины с другими компонентами системы, которые могут управлять шиной. 11
RQ/E 1, RQ/EO — запрос/разрешение (подтверждение) шины. Последовательность запроса/разрешения представляет собой трехфазный цикл. Сначала запрашивающий шину процессор генерирует отрицательный импульс на линии RQ/E. Микропроцессор, действующий как центральный процессор, отвечает выходным импульсом на той же линии, сигнализируя о приостановке своих действий, и освобождает шину. В течение последую1 щего временного интервала шинный интерфейс логически отключен от шины. Когда другой процессор закончил ^операции на шине, он генерирует импульс на линии RQ/E, и МП начинает снова управлять шиной. Оба взаимодействующих процессора должны синхронизироваться от одного источника синхроимпульсов. Запрос по линии RQ/E0 имеет больший приоритет, чем запрос по линии RQ/E1. Если в системе имеются арифметический сопроцессор и процессор ввода-вывода, то- запрос от арифме» тического сопроцессора подается по линии RQ/E1. Две сигнальные линии относятся к прерываниям. NMI — немаскируемое прерывание. Этот входной импульсный сигнал МП распознает по завершении текущей команды независимо от того, разрешены прерывания или нет. По входу NMI сообщается о та^сих критических ситуациях, как аварийное отключение сети или ошибка в памяти. ШТ — запрос прерывания. Входной потенциальный сигнал показывает, что внешнее устройство требует обслуживания со стороны МП. Если прерывания разрешены, МП завершает текущую команду и выполняет два цикла шины подтверждения прерывания. В результате их МП вводит по линиям AD7—ADO байт типа прерывания, а затем осуществляет косвенный переход к соответствующей процедуре прерывания. Когда прерывания запрещены, МП игнорирует сигнал INT. Пять входных сигналов предназначены для управления работой МП. RDY — готовность. Сигнал готовности позволяет приостановить действия МП (RD-Y=0) на произвольное число тактов синхронизадии. Обычно он используется в интерфейсе памяти, быстродействия которой недостаточно для работы синхронно с МП. TEST — проверка. Этот входной сигнал применяется 12
только вместе с командой ожидания WAIT. Выполняя ее, МП проверяет уровень сигнала TEST и либо переходит к следующей по порядку команде (TEST=0), либо зацикливается и периодически проверяет уровень сигнала на входе TEST (TEST=1). Таким образом, вход TEST и команда WAIT позволяют синхронизировать действия МП с внешним событием. Этот механизм применяется для синхронизации работы МП и арифметического сопроцессора. CLR — сброс или начальная установка. При активном уровне сигнала CLR действия МП прекращаются и он переходит в известное начальное состояние. CLC — синхронизация или тактирование. На этот вход подаются периодические прямоугольные сигналы с коэффициентом заполнения 1/3, частотой 2—5 МГц, предназначенные для синхронизации всех действий МП. MN/MX — минимальный/ма^мальный. Уровень этого сигнала определяет конфигурацию МП. 1.3. ПРОГРАММНАЯ МОДЕЛЬ МИКРОПРОЦЕССОРА В программной (регистровой) модели МП, показанной на рис. 1.3, фигурируют-регистры, которые доступны программисту на "уровне языка ассемблера. Модель показывает те ресурсы МП, которыми программист может распоряжаться при разработке программ. • В группу 16-битных регистров общего назначения (РОН), называемых также регистрами данных, входят регистры АХ, ВХ, СХ и DX. Их особенность заключается в том, что допускается индивидуально указывать их старшие (Н) и младшие (L) байты. Двойственный характер РОН обеспечивает простые манипуляции байтами и словами. Остальные регистры МП можно использовать только как 16-битные. Регистры AX-DX находятся в полном распоряжении программиста, и единообразно участвуют в арифметических и логических операциях. Однако имеются команды, которые неявно • специализируют их на определенные функции, что отражено в названиях регистров. Группа указательных и индексных регистров представлена регистрами'SP, BP, SI и DI. Они предназначены в основном для хранения относительных (внутрисегментных) адресов, обеспечивают косвенную адресацию памяти и участвуют в вычислениях эффективного адре- 13
Рис. 1.3. Программная модель микропроцессора К1810ВМ86 са. Гибкость таких вычислений достигается тем, что эти регистры могут участвовать в арифметических и логиче-; ских операциях так же, как и РОН. Поэтому регистры этой группы и регистры AX-DX часто называют общими: регистрами. Указатель стека SP адресует текущую вершину аппаратного стека в памяти. С помощью указателя базы ВР организуется простой доступ к любым данным, находящимся в стеке. Наиболее часто регистр ВР привлекается для адресации параметров, передаваемых подпрограммам. Индексные регистры SI и DI применяются для адресации цепочек. Наличие в программной модели четырех специальных сегментных регистров объясняется способом адресации памяти. Хотя МП выдает 20-битный физический адрес памяти, он оперирует двумя 16-битными значениями, называемыми логическим адресом: базовый (начальный) адрес сегмента и внутрисегментный адрес или сме- 14
щение. Эти компоненты логического адреса называются также сегментным- адресом и относительным адресом, а весь логический адрес сегмент: смещение называется еще сегментированным адресом. Схема преобразования адресов в составе шинного интерфейса превращает пару сегмент : смещение в 20-битный физический адрес. Пространство памяти 1М байт разделяется на логические сегменты с максимальной емкостью 64К байт. Реальная емкость сегмента может варьироваться от 16 байт до максимальной. При выполнении программы МП может обращаться к четырем сегментам, базовые адреса которых находятся в сегментных регистрах CS (кода), DS (данных), SS (стека) и ES (дополнительных данных). Регистр CS указывает на начало текущего сегмента кода, т. е. программы, откуда выбираются команды. Регистр SS адресует начало текущего сегмента стека, в котором реализуются все стековые операции. Регистр DS определяет текущий сегмент данных, содержащий программные переменные. Наконец, регистр ES указывает на текущий дополнительный (Extra — «лишний») сегмент, который обычно применяется для хранения данных. В большинстве команд фигурирует только внутрисегментное смещение, определяемое в соответствии с указанным режимом адресации. Физический адрес формируется путем суммирования смещения с умноженным на 16 содержимым одного из сегментных регистров (подробнее.см. в § L4). Указатель команды ГР осуществляет адресации внутри текущего сегмента кода, т. е. функционирует аналогично программному счетчику PC (или счетчику команд) большинства других МП. Шинный интерфейс модифицирует его так, что он указывает на ту команду (и даже часть команды), которую шинный интерфейс будет выбирать при очередном обращении к памяти. Из-за опережающей выборки команд содержимое IP не совпадает со смещением той следующей команды, которую будет выполнять операционное устройство. Поэтому при сохранении содержимого IP в стеке при вызовах подпрограмм и прерываниях оно автоматически корректируется так, чтобы адресовать правильную команду, которая будет выполняться при восстановлении IP. Эта механика «прозрачна» для программиста, и он может считать IP обычным программным счетчикам. 15
15 8 7 О тяж- J3F IF TF SF IF 4& ш ш ~cf\ Рис. 1.4. Регистр флажков Формат регистра флажков приведен на рис. 1.4. Шесть его арифметических флажков фиксируют определенные свойства или признаки результата арифметической или логической операции. Команды МП воздействуют на эти флажки по-разному, но в общем они отражают следующие особенности результата. 1. Флажок переноса CF фиксирует значение бита переноса (заема), возникающего при сложении (вычитании) байт или слов, а также значение выдвигаемого бита во всех операциях сдвигов. Кроме того, он отражает особенность результата операций сравнения и умножения^ 2. Флажок паритета PF (или четности) показывает наличие четного (0) или нечетного (1) числа единиц в младшем байте результата. 3. Флажок вспомогательного переноса AF аналогичен флажку CF, но фиксирует перенос (заем) из младшей, тетрады. Этот фларкок необходим в операциях десятичной арифметики. 4. Флажок нуля ZF сигнализирует о получении нулевого результата операции. 5. Флажок знака SF повторяет значение старшего бита результата, который в дополнительном коде соответствует знаку числа. 6. Флажок переполнения OF отмечает потерю старшего бита результата операции сложения или вычитания над знаковыми числами. Он же показывает изменение старшего (знакового) бита в арифметических сдвигах влево» Три оставшихся флажка предназначены для управления некоторыми действиями МП, Программист может одной или несколькими командами задать состояние любого из этих флажков. 1. Флажок направления DF определяет сканирование цепочек от меньших адресов к большим (DF = 0) или наоборот (DF=1). Такие действия называются еще прохождением цепочек «слева направо» н «справа налево». 2. Флажок прерывания IF задает реакцию МП на запрос внешнего прерывания по входу ШТ. Если IF=0, 16
запрос прерывания игнорируется (прерывания запрещены или замаскированы), а если 1F=1, МП распознает и соответственно реагирует на запрос прерывания. 3. Флажок прослеживания (трассировки) TF при установке в 1 переводит МП в одношаговый или командный режим работы, который применяется для отладки программ. В этом режиме МП автоматически генерирует внутреннее прерывание после выполнения каждой команды. 1.4. ОРГАНИЗАЦИЯ И РЕЖИМЫ АДРЕСАЦИИ ПАМЯТИ Для программы пространство памяти Ш байт выглядит как группа сегментов (блоков или областей), определяемых самой программой. Сегмент, как уже отмечалось, есть логическая единица памяти размером 64К байт. Каждый сегмент идентифицируется начальным адресом (базой), являющимся адресом его первого байта. Единственное требование к размещению сегментов заключается в том, что они должны начинаться на 16- байтных границах памяти. Следовательно, младшие 4 бита базового адреса сегмента должны содержать нули. Других ограничений на размещение сегментов в памяти нет. В сегментных регистрах CS, DS, SS и ES находятся базовые адреса четырех текущих сегментов, причем младшие нулевые биты адресов не хранятся, а подразумеваются. Если, например, регистр DS содержит 2345, то базовый адрес сегмента данных равен 23 450 (здесь и далее адреса приводятся исключительно в 16-ричной системе счисления). На рис. 1.5, а показана максимальная память, доступная при фиксированном содержимом сегментных регистров (всего адресуется 256К байт), а на рис. 1Дб — более «умеренный» случай, когда размер сегменте кода составляет 16К байт, сегмента данных 4К байт и сегмента стека 256 байт. Ранее было сказано о том, что внутри МП любая ячейка памяти идентифицируется логическим адресом, состоящим из 16-битных базового адреса сегмента и внутрисегментного смещения, показывающего расстояние в байтах от начала сегмента до конкретной ячейки. Когда шинный интерфейс обращается к памяти, он образует из логического адреса сегментгсмещение физи- 2-723 17
Рис 1.5. Адресуемая память при различном содержимом сегментных регистров ческий адрес. Для этого база сегмента сдвигается влево на 4 бита (т. е. умножается на 16) и суммируется со смещением (рис. 1.6). Шинный интерфейс получает компоненты логического адреса из различных источников в зависимости от типа текущего обращения к памяти, что показано в табл. 1.1. Таблица 1.1. Источники компонентов логического адреса Тип обращения к памяти Выборка команды Стековая операция Обращение к переменной Цепочка — источник Цепочка — получатель ВР как базовый регистр Ваза (по уыодчл- нию) CS SS DS | DS ES SS Смещение IP SP ЕА SI D1 ЕА Вариант Нет » CS, SS, ES CS, SS, ES Нет CS, DSe ES Команды всегда выбираются из текущего сегмента кода — логический адрес находится в регистрах CS : IP. Стековые операции всегда обращаются к текущему сегменту стека — привлекаются регистры SS : SP. Обычно переменные находятся в текущем сегменте данных, определяемом регистром DS, но программист может заставить МП обратиться к переменной в сегменте, базовый адрес которого находится не в регистрах DSt а в каком- то другом сегментном регистре. Такая возможность показана в столбце «Вариант» табл. 1.1. Явная специфика- is
Рис. 1.6. Преобразование логического адреса в физический 19
ция сегмента достигается с помощью так называемого префикса замены сегмента. Байт префикса предшествует команде и сообщает шинному интерфейсу, какой сегментный регистр использовать в следующей за ним команде для формирования физического адреса памяти. В ассемблерных программах необходимость замены сегмента указывается оператором замены сегмента. Например, команда MOV AX, [DI] будет обращаться к текущему сегменту данных, т. е. через регистр DS, а команда MOV AX, ES:[DI] —к текущему дополнительному сегменту. Смещение переменной вычисляет операционное устройство в соответствии с режимом адресации в команде. Результат вычисления называется эффективным адресом ЕА операнда. Режим адресации должен идентифицировать операнд (ы) команды, в частности указывать способ формирования ЕА. Эффективный адрес является либо адресом данных (в командах манипуляций данными), либо адресом перехода (в командах передачи управления). Команды МП адресуют максимум два операнда. Первым операндом (в порядке записи команды на языке ассемблера) является содержимое регистра или ячейки памяти, а вторым — содержимое регистра или непосредственный операнд. Впрочем, Нумерация «первый» и «второй» довольно условна. Общий формат двухоперандной команды приведен на рис. 1.7, а, причем штриховые линии показывают необязательные байты. Первый байт содержит код операции (КОП) и два однобитных поля: d и т. Поле d определяет направление передачи: если <f=lf то направле: ние «в», а если d=0 — направление «из». Само направление относится ко второму операнду: регистру, указанному в поле reg второго байта. Поле w показывает тип операнда: байт (а>=0) или слово (w=l). Второй байт команды называется постбайтом режима адресации; как видно, он состоит.из трех полей. Поле reg (регистр) показывает один из регистров МП (табл. 1.2). Поле mod (режим) определяет интерпретацию поля г/т (регистр/память) при нахождении первого операнда. Если mod=U, операнд находится в регистре и поле г/т показывает конкретный регистр, а в остальных случаях адресуется память, при этом поле mod показывает, чему равно смещение disp, содержащееся в команде как конс- 20
Т а б л и ц а 1.2. Режимы адресации reg и rim 000 001 010 011 100 101 110 111 mod 00 (BX) + (SI) (BX) + (D1) (BP) + (SI) (BP) + (DI) (SI) (DI) D16 (BX) 0, (BX)+(SI)+D8 (BX) + (D1)+D8 BP) + (SI)+D8 (BP) + (DI)+D8 (SI)+D8 (DI)+D8 (BP)+D8 (BX)+D8 Продолжение табл. 1.2 reg и rim 000 001 010 on 100 10J 110 111 10 (BX) + (SI)+D16 (BX) + (DI)+D16 <BP) + (SI)*D16 (BP)+(DI)+D16 (SI)+D16 (DI)+DI6 (BP)+D16 (BX)+D16 mod Ш = 0 ЛЬ СЬ DL ВЬ АН СН DH ВН и го= 1 & DX ВХ StP да SI DI Примечание. DS-dispL — одна байт смещения; D16~dispLt dispti-m два байта смещения. танта. В случае адресации памяти (moduli) поле r/m определяет способ формирования ЕА в соответствии с табл. 1.2. В командах с непосредственным операндом (рис. 1.7,6) второй операнд адресовать не нужно, поэтому поле reg отводится под код операции. Кроме того, здесь не нужен бит d, так как результат можно поместить только на место первого операнда. Однако необходимо определить тип непосредственного операнда, для чего служат поля s и w. Наконец, на рис. 1.7, в показан формат однооперанд- ной команды, который не имеет ничего нового. Рассмртрнм стандартные режимы адресации МП с учетом приведенных способов формирования ЕА. Регистровая адресация. Операнд или операнды находятся во внутренних регистрах МП. Команды с таким 21
режимом адресации оказываются наиболее короткими и быстрыми. Непосредственная адресация. Микропроцессор может оперировать непосредственными операндами (константами) длиной в байт или слово и содержимым регистров или ячеек памяти. Однако команды непосредственной загрузки сегментных регистров и включения константы в стек отсутствуют. Абсолютная адресация. В абсолютной адресации ЕЛ берется из поля disp в команде. Этот режим применяется для обращения к простым переменным (скалярам). Косвенная регистровая адресация. В этом режиме ЕА находится в одном из регистров ВР, ВХ, S-I и DI, что указывается путем заключения имени регистра в квадратные скобки. Базовая адресация. При указании этого режима ЕА равен сумме значения disp> находящегося в команде, и содержимого регистра ВХ или ВР. Напомним, что при задании регистра ВР шинный интерфейс обращается к операнду в текущем сегменте стека, что упрощает доступ к параметрам подпрограммы, передаваемым в стеке. Основное применение базовой адресации связано с обработкой структур данных, когда номер элемента структуры известен при ассемблировании программы, а начальный адрес структуры должен определяться при выполнении программы. Обычно ассемблеры допускают задание базовой адресации в нескольких формах. Например, следующие три команды производят одно и то же действие: MOV АХДВР-К4] MOV АХ,4[ВР] MOV АХДВР1+4 Индексная адресация. В режиме индексной адресации ЕА равен сумме значения disp и содержимого регистра SI или DI. Обычно disp определяет известный при ассемблировании начальный адрес одномерного массива, а индексный регистр показывает нужный элемент. Изменяя содержимое индексного регистра, можно обращаться к различным элементам массива. Базовая индексная адресация. В этом режиме ЕА равен сумме содержимого базового регистра ВР или ВХ, индексного регистра SI или DI и необязательного значения disp. Гибкость такой адресации объясняется 22
тем, что два компонента адреса можно определять и варьировать при выполнении программы. С помощью базовой индексной адресации обеспечивается удобный доступ к элементам массива, находящегося в стеке, а также обращение к двумерному массиву. Относительная адресация. В режиме относительной адресации ЕА равен сумме значения disp и текущего содержимого указателя команды* IP. При этом полагается, что в IP находится адрес байта, следующего за командой с таким режимом ■ адресации. В МП К1810ВМ86 относительная адресация применяется только в командах передачи управления. Смещение disp имеет длину 8/16 бит, представлено в дополнительном ч коде и имеет диапазон от —128 до +127 и от —32 768 до +32 767 соответственно. В программах указывается не значение смещения, а метка той команды, которой . передается управление. Значение смещения вычисляет программа-ассемблер. Адресация цепочек» При обработке цепочек предполагается, что регистр SI адресует в сегменте данных первый или последний байт (слово) цепочки-источника^ а регистр DI — в дополнительном сегменте адресует первый или последний байт (слово) цепочки-получателя. В повторяющихся операциях МП автоматически корректирует SI и DI по мере продвижения к другим элементам цепочек. Специальные цепочечные команды рассчитаны на такую неявную адресацию цепочек. Адресация портов ввода-вывода. Для обращений к портам в пространстве ввода-вывода применяются два режима адресации. При прямой адресации фиксированный адрес порта находится непосредственно в команде, как ее второй байт, что обеспечивает доступ к портам 0—255. При косвенной'адресации номер порта находится в регистре DX и имеет диапазон от 0 до 65 535. 1.5. СИСТЕМА КОМАНД В систему команд МП K181QBM86 входят 113 базовых команд, многие из которых допускают разнообразные режимы адресации. При рассмотрении системы команд принято группировать команды с примерно одина-- ковым функциональным назначением.
1.5.1. КОМАНДЫ ПЕРЕДАЧ ДАННЫХ Микропроцессор имеет обширную группу команд, предназначенных для пересылок данных между регистрами и между регистрами и памятью. Команды этой группы, за исключением команд POPF и SAHF (см. далее), не воздействуют на флажки. Команда MOV. Наиболее гибкая из всех команд передач данных MOV имеет следующее содержательное представление: MOV dst, src dst+-{$rc) Содержимое источника src копируется в получатель dst. Чтобы показать разнообразие машинных команд микропроцессора, на рис. 1.8 представлены все форматы команд MOV, а далее форматы команд не приводятся. Приняты следующие сокращения: reg — регистр, тет — память, data — данные, disp — смещение (в команде), ас — аккумулятор (АХ или AL), sreg — сегментный регистр. Как видно# из рисунка, с помощью команды MOV можно осуществить следующие передачи байта или слова: из регистра ^ регистр, из регистра в память и наоборот, непосредственного операнда в регистр или память. Приведенные также более короткие команды, в которых фигурируют аккумулятор АХ или AL, 'Дадим несколько примеров ассемблерных команд MOV с различными источниками и получателями: MOV DX,CX ;Слово, из регистра в ре- ; гистр * MOV BX,ES:[SI] ;Слово, из памяти в ре- ; гистр MOV TEMP[DI],AL ;Байт, из регистра в па- ; мять MOV IBX1SI30H Непосредственный байт • ; в память Конечно, при всей своей универсальности команда MOV имеет и определенные ограничения. Во-первых, как уже отмечалось, невозможно одной командой передать содержимое какой-либо ячейки памяти в другую ячейку. При необходимости такую передачу следует производить через внутренний регистр МП. Рекоменду- 24
Рис. 1.8. Форматы команды MOV 25 <
ется максимально привлекать для этого аккумулятор АХ или AL, так как команда получается короче на одив байт. Во-вторых, команда MOV не может загрузить непосредственное значение в сегментный регистр. Поэтому для инициализации сегментных регистров приходится применять две команды и промежуточный общий регистр, которым чаще всего выступает АХ, например: инициализировать регистр DS MOV AX,DATA_S MOV DS,AX через аккумулятор АХ Наконец, командой MOV невозможно передать содержимое одного сегментного регистра в другой. Такая передача осуществляется через промежуточный общий регистр: MOV AX,DS ; Передача из регистра DS MOV ES.AX ; в регистр ES Команда XCHG. Команда обмена XCHG dst, src (ds()~(src) позволяет обменять содержимое двух общих регистррв, а также любого общего регистра и ячейки памяти. В обмене могут участвовать байты и слова. Однако в этой команде нельзя указывать сегментные регистры. Отметим, что. команда XCHQ АХ, АХ используется как холо-' стая команда NOP. Примеры ассемблерной записи команды XCHG: XCHG AL,DH ;Обмен байт в регистрах ;Обмен слов регистр—па- XCHG AX,[DI] ; мять Команда XLAT. Однобайтная команда преобразования XLAT с пустым полем операнда XLAT AL4-((BX) + (AL)) заменяет содержимое AL на байт из 256-байтной таблицы, начальный адрес которой находится в регистре ВХ, при этом содержимое AL действует как индекс таблицы (pjfc. 1.9). Команда XLAT обычно применяется для быстрого преобразования символов из одного символьного кода в другой, так как она выполняется всего за 11 тактов синхронизации. 26
Рис. 1.9. Выполнение команды преобразования Сегмент данных i После Зыполне- нал команды XLAT 39Н 0700 OWT B70Z 0103 070* 0105 0706 Отметим, что иногда для вх Г won лучшего понимания программы в поле операнда команды XLAT указывается «бесполезное» для нее символическое имя начального адреса таблицы преобразования. Кроме того, некоторые ассемблеры допускают мнемонику XLATB, подчеркиваю-5* тую тот факт, что команда XLAT преобразует байты. Команды LEA, LDS и LES. При . выполнении этих команд в указанный (е) регистр (ы) передаются не данные, а адреса, поэтому их основное применение связано с инициализацией адресных регистров. При выполнении команды загрузки эффективного адреса LEA reg, mem образуется эффективный адрес ЕА памяти и именно его значение, а не адресуемое им слово в памяти, загружается в общий регистр reg. Передача адреса требуется, например, для инициализации ре* гистра ВХ до его использования в команде XLAT. Команды загрузки полных указателей LDS reg, mem и LES reg% mem.выполняют более сложные действия: вычисляется ЕА, и производится обращение к памяти, а затем считываемое слово загружается в общий регистр reg и следующее ялово из памяти передается в регистр DS (команда LDS) или в регистр ES (команда LES). Обычно в команде LDS как reg указывается индексный регистр SI, а в команде LES — индексный регистр DI, что согласуется с использованием регистров в цепочечных командах. Команды LDS и LES должны адресовать в памяти двойное слово. Примеры команд: LEA LDS LES BX.TABLE SIJDI] DIJDI+4] Адрес таблицы в ВХ Инициализировать регистры для. пересылки цепочки Команды SAHF и LAHF. Однобайтные безолеранд- ные команды LAHF и SAHF введены только для упрощения программной совместимости микропроцессоров К1810ВМ86 и КР580ИК80. В 8-битном МП КР580ИК80 27
регистр флажков, полностью соответствующий млад, шему байту регистра флажков МП К1810ВМ86, вместе с аккумулятором А образует слово состояния процессора PSW. Команда LAHF передает младший байт регистра флажков в регистр АН, образуя в аккумуляторе АХ аналог P*SW (сами флажки при передаче, конечно, не изменяются). Команда SAHF осуществляет обратную передачу — содержимое регистра АН передается в младший байт регистра флажков. Стековые команды. Вершина TOS (Top of Stack) аппаратного стека в сегменте стека оперативной памяти адресуется регистрами SS и SP. Все стековые команды оперируют только словами ji сопровождаются автоматической модификацией SP: при включении (push) в стек производится декремент, а при извлечении (pop) из стека — инкремент SP. Команды PUSH включения в стек PUSH src SP ч- <SP) — 2, TOS *- (src) осуществляет запись в стек содержимого общего регистра, сегментного регистра или ячейки памяти, указываемой в любом режиме адресации. Команда POP извлечения из стека POP dst dst*-(TOS), SP +- (SP) -f 2 выполняет противоположные действия. . До использования стековых команд, необходимо правильно инициализировать регистры SS и SP (помня о том, что стек в памяти «растет вверх>, в область меньших адресов), а также тщательно следить за тем, чтобы в программе каждой команде PUSH соответствовала команда POP. В МП К1810ВМ86 нет аппаратных средств контроля переполнения и антипереполнения [(«опустошения») стека, поэтому ответственность за правильное использование стека возлагается на программиста. При этом следует учитывать, что некоторые команды (например CALL, RET и INT) автоматически используют стек. Однобайтные безоперандные команды PUSHF и POPF манипулируют регистром флажков. Примеры стековых команд на языке ассемблера: PUSH SI ; Включение в стек общего ре- ; гистра PUSH ES ;Включение в стек сегментно- g го регистра 28
;Включение в стек слова из ; памяти ;Включение в стек регистра ; . флажков ; Извлечение из стека в ре- ; гистр флажков ; Извлечение из стека в память извлечение из- стека в сег- ; ментный регистр ;Извлечёние из стека в общий 1 регистр С помощью команд PUSH* и POP можно передать содержимое одного сегментного регистра в другой без привлечения промежуточного общего регистра: PUSH DS ;Эти команды передают ЮР ES ; содержимое DS в ES Конечно, из-за обращений к памяти эти команды выполняются дольше эквивалентных команд:. MOV AX,DS ; Эти команды также передают MOV ES,AX содержимое DS в ES Команды ввода-вывода. Команды ввода IN и вывода OUT могут передавать байты и слова. Получателем при вводе и источником при выводе могут быть только аккумуляторы АХ ил if AL. Команды IN ащ port OUT port, ас содержат байт прямого адреса входного или выходного порта (так называемый статический ввод-вывод), а в командах IN ас, DX OUT DX, ас 16-битный адрес порта берется из регистра DX '(так называемый динамический ввод-вывод). Косвенная адресация через регистр DX удобна в тех случаях, когда адрес нужного порта определяется при выполнении программы/ 29 PUSH [BXHSI] PUSHF POPF POP ALPHAISI] POP DS POP AX
Примеры команд ввода-вывода: IN AX;8GH ;Ввод слова (статический) IN AL,DX ;Ввод байта (динамический) OUT 04H.AL ;Вывод байта (статический) OUT DX,AX «Вывод слова (динамический) 1.5.2. АРИФМЕТИЧЕСКИЕ КОМАНДЫ Микропроцессор К18ШВМ86. имеет достаточно оё ширный набор арифметических команд, что позволяет применять его для сложной обработки данных. Арифметические операции выполняются над целыми числами в четырех форматах: беззнаковые двоичные, знаковые двоичные, упакованные десятичные и неупакованные десятичные (рис. 1Л0). В данной книге операции с деся- Ряс. 1.10. Форматы численных данных 80
гичнымй числами не рассматриваются. Поэтому отме- i им только, что они реализуются в два этапа: сначала тлполняется соответствующая операция с двоичными числами, а полученный ею результат корректируется специальной командой (как исключение, при делении коррекция делимого осуществляется первой). Беззнаковые двоичные числа представляются байтами и словами, имеющими диапазоны от 0 до 255 и от 0 до 05 535 соответственно. Знаковые двоичные числа в форматах байта и* слова изображаются в обычном дополнительном коде, имея диапазоны от —128 до +127 для байта и от —32 767 до +32 767 для слова. Сложение и вычитание знаковых и беззнаковых чисел выполняет одни и те же команды (в этом заключается одно из достоинств дополнительного кода), а для умножения и деления предусмотрены отдельные команды. В арифметических операциях особенности получающихся результатов фиксируются в шести арифметических флажках, состояния которых (за исключением флажка AF вспомогательного переноса) можно проверит^ командами условных переходов. Команды сложения. Микропроцессор имеет команду ADD собственно сложения и команду ADC сложения с переносом: ADD dst, src dst ^ (dst) + (src) ADC d#, src dst<-(dst) + (src) + (CF) В качестве dst и src можно указывать общие регистры и ячейки памяти с любым режимом адресации, а в качестве src — еще и непосредственные операнды. К командам сложения обычно относят однооперанд- ную команду инкремента (увеличения на 1): INC dst dst*-(ds()+l В этой команде операнд dst, которым может быть общий регистр или ячейка памяти, считается беззнаковым двоичным числом, и при ее выполнении состояние флажка CF це изменяется. Команда INC часто применяется для инкремента счетчика цикла и продвижения указателей (т.е. регистров адреса) при обработке регулярных структур данных. 31
Команды вычитания. Команды вычитания SUB dst, src dst<-(dsf) — {src) SBB dst% src dst+-(dsi) — (src)—(GF) DEC dst dst<-(ds[)—\ отличаются от соответствующих команд сложения только выполняемой операцией. Следует подчеркнуть, что флажки CF и AF в операциях вычитания становятся флажками заема и устанавливаются в 1, когда вычитаемое больше уменьшаемого. Команды ADC и SB В (вычитание с заемоМ) предназначены для обработки операндов, длина которых составляет несколько байт или слов (так называемые числа многократной точности). К командам вычитания традиционно относят команду NE<3 изменения знака, так как ее действие эквивалентно вычитанию операнда из нуля: NEG dst dst+-0 — (dsf) Если операнд равен нулю, его значение, не изменяется. Попытка изменить знак максимального (по модулю) отрицательного числа, т.е. числа вида 100...00, не вызывает изменения операнда, но при этом устанавливается флажок переполнения OF. При выполнении команды NEG флажок CF устанавливается в 1, кроме случая, когда операнд равен нулю, — тогда CF=0. Необходимо отчетливо различать смысл флажков переполнения OF и переноса (заема) CF. Состояние CF=1 показывает, что при сложении (вычитании) воз^ ник перенос (заем) из старшего бита. При обработке чисел длиной в несколько байт или слов перенос (заем) следует учитывать в операции со следующим байтом или словом. Однако состояние CF=1 можно интерпретировать и как переполнение в операциях сложения и вычитания беззнаковых чисел. Оно показывает, что при сложении или вычитании произошло переполнение, т.е. результат выходит за диапазон представимых чисел и, следовательно, неверен. Покажем различия между флажками CF и OF на нескольких примерах. 32
• 01-111001 . 121 , (+121) * CF=1 "Ч 1 0 1 0 1 1 0 ^214 Ч—42) OF=0 1ч- 0 10 0 1111 79(?) ~+79 . О 1 1 1 i 0 0 1 • .121 , (+121) CF=0 ^010101 10 ^86 4+86) OF=l 110 0 1111 ~207 —49(?) • 10000000 ,128 • (—128) CF=1 "М 0000000 428 Ч—128) OFc=l 14-0 00 0 00000 0(?) Щ~ Примеры ассемблерных команд сложения и вычитания: ADD AX.CX ;Регистр — регистр, слово ADD ALPHA.DI ;Память — регистр» слово ADD СЦЗ •; Константа к регистру, байт INC . WORD PTR ;Инкремент слова в памяти GAMMAIDU SUB DX, [ВР+21 ;Регистр — память, слово DEC BYTE PTR [BX] -Декремент байта в памяти NEQ WORD PTR [SI] ;Изменение знака слова в па- ; мяти Команда сравнения. Команда СМР сравнения CMP dst, src (dsf)—(src) осуществляет вычитание источника из йолучателя, но разность нигде не запоминается, т. е. команда реализует так называемое неразрушающее сравнение операндов. О результате сравнения сигнализируют арифметические флажки (табл. 1.3). Команды умножения. Микропроцессор К1810ВМ86 имеет две команды умножения: MUL src) . / \ w / \ IMUL src J предназначенные для умножения беззнаковых и знаковых операндов соответственно. Обе они выполняют ум«- ножение адресуемого операнда src (им может быть общий регистр или ячейка памяти и не может быть непо- 3-723 33,
Таблица 1.3. Результаты операции сравнения Условие Беззнаковые операнды: (src)<(d$t) (src)^(dst) (src)>(dst) Знаковые операнды: (src)<(d$t) (src)=(dst) (src)>(d$t) i op X X X -0/1 0 i 0/1 Флажки г ■ | SF 1 2F X X X 0 0 1 i 1 0 1 0 0 1 1 0 | CF 1 ' 0 0 1 X X X средсгвенный операнд) и аккумулятора ас. В операции над байтами аккумулятором ас служит регистр AL, а произведение двойной длины образуется в регистрах АН и AL, причем регистр АН называется расширением ext аккумулятора AL. В операции над словами аккумулятором ас является регистр АХ, а произведение получается в регистрах DX и АХ. Здесь регистр DX выступает расширением аккумулятора АХ. Команды умножения своеобразно воздействуют на флажки, позволяя оценить произведение. Если после выполнения команды MUL старшая половина произведения не является нулевой, а после команды IMUL она не является расширением знака младшей половины, флажки CF и OF устанавливаются в 1, а в противном случае CF, OF=0. Состояния всех остальных флажков после выполнения команды .MUL и IMUL не определены. Примеры записи команд умножения на языке ассемблера: MUL BL ;Байты, без знака MUL WORD PTR [DM ;Слова, без знака IMUL CX ;Слова, со знаком IMUL BYTE PTR [BXJ [SI] ;Байты, со знаком MOV DX, 100 ^ ;Эти две команды MUL DX ; умножают АХ на 100 Команды деления. В двух командах деления операндами являются беззнаковые (DIV) и знаковые (IDIV) двоичные числа: DIV src) ac+-quoi{{ext\ac)I(src)) IDIV src J ext+-rern((ext:ac)/(src)) 34
Здесь делимым двойной длины служит содержимое аккумулятора ас (АХ или AL) и его расширения ext (DX или АН), делителем — адресуемый операнд src (общий регистр или ячейка памяти, но не константа), частное quot образуется в аккумуляторе ас, а остаток rеm — в его расширении. Дробное частное усекается до целого, а состояния всех арифметических флажков не определены. Если длина частного превышает длину аккумулятора (например, при делении беззнаковых байт частное больше 255), МП генерирует внутреннее прерывание типа 0 и автоматически переходит к соответствующей процедуре обработки прерывания. При этом содержимое регистров ext и ас непредсказуемо. Примеры ассемблерных команд деления; DIV. ВН ;Байты, без знака DIV WORD PTR [ВР] ;Слова, без знака IDIV ВХ ;Слова, со знаком IDIV BYTE PTR [DI] -Байты, со знаком MOV CX, 1000 ;Этй две команды делят DIV CX ; DX:AX на 1000 К командам деления относятся также две команды преобразования, позволяющие удвоить длину знакового операнда с сохранением его численного значения. Команда CBW преобразования байта в слово копирует в регистр АН знак числа, находящегося в регистре AL, a команда CWD преобразования слова в двойное слово копирует в регистр DX знак.числа, находящегося в регистре АХ. Обе команды не влияют на состояние флажков. Наличие этих команд упрощает операции над данными смешанных типов, например: CWD ;Дёление слова из регистра АХ IDIV ВХ ; на слово из регистра ВХ CBW Суммирование, байта из AL ADD АХ, ВХ ; и слова из ВХ 1.5.3. ЛОГИЧЕСКИЕ КОМАНДЫ И КОМАНДЫ СДВИГОВ Логические команды. Поразрядные логические операции МП К1810ВМ86 представлены булевыми операторами NOT (инверсия), AND (конъюнкция), OR (дизъюнкция), XOR (сложение по mod 2) и командой TEST проверки, которая выполняет конъюнкцию операндов, но не изменяет ни один из них: 3* 35
AND OR XOR TEST NOT dst, src dst, src dst, src dst, src dst dst<-(dst)A(src) dst<-(dst)\/(src) dst<-(dst)Q(src) (dst)A(src) dst<-(dst) Бинарные операции AND, OR, XOR и TEST воздействуют на арифметические флажки следующим образом: флажки CF и OF переводятся в нулевое состояние; состояния флажков SF, ZF и PF зависят от результата; состояние флажка AF не определено. Команда NOT не изменяет состояний флажков. В качестве dst и src можно указывать общие регистры и ячейки памяти с любым режимом адресации, а в качестве src — еще и непосредственные данные (за очевидным исключением команды NOT). Операнды могут быть байтами и словами. Команды AND и OR применяются в основном для установки в 0 и 1 тех бит операнда dst, которые определяются другим операндом src% называемым маской. С помощью команды XOR можно инвертировать выбираемые маской биты операнда dst, сравнивать операнды на абсолютное равенство (при равенстве результат, равен нулю и ZF=1) и переводить регистр в нулевое состояние. Примеры ассемблерной записи логических команд: AND AX, BX ;Конъюнкция двух регистров .AND [SIJ, 1 > ;Проверка младшего бита OR АХ,8000Н ;Установка в 1 старшего бита XOR ВХ, ВХ ;Сброс регистра ВХ XOR DI, 1 инвертирование младшего ; бита NOT BYTEPTR[SI] инвертирование байта в памяти , Команды сдвигов. Действия команд сдвигов представлены на рис. 1.11. Поле операнда всех команд имеет вид memfreg, count. Здесь mem/reg обычным образом адресует общий регистр или ячейку памяти, а счетчик count определяет число сдвигов. Он может быть указан как константа 1 (статический сдвиг на один бит) или как регистр CL (динамический сдвиг, в котором число сдвигов задается содержимым регистра CL)« 36
Рис. 1.11. Действия команд сдвигов С помощью команд сдвигов осуществляются циклические и обычные сдвиги. В циклических сдвигах выдвигаемый бит помещается на место освобождающегося бита (см. первые четыре команды на рис. 1.11). Команды RCL и RCR называются циклическими сдвигами через перенос, так как в кольцо сдвига включается флажок CF. «Обычные» сдвиги подразделяются на логические (команды SHL и SHR), в которых операнды считываются беззнаковыми числами, и' арифметические (команды SAL и SAR), оперирующие знаковыми числами. Для логического сдвига характерно, что в освобождающийся бит помещается 0, а выдвигаемый бит теряется. В арифметическом сдвиге Biipago (команда SAR) знаковый бит сохраняется путем его дублирова- 37
ния, а в арифметическом сдвиге влево (команда SAL) он не сохраняется, но изменение его фиксируется установкой флажка OF=l. При выполнении команд сдвигов флажки модифицируются следующим образом: состояние флажка AF всегда не определено; флажок GF всегда содержит значение последнего выдвинутого бита; в статических сдвигах флажок OF=l, если знаковый бит изменился; в динамических сдвигах состояние OF не определено; циклические сдвиги воздействуют только на флажки OF и CF; в «обычных» -сдвигах флажки SF, ZF и PF фиксируют соответствующие признаки результата. Приведем примеры ассемблерных команд сдвигов: SHL DH, 1 Логический сдвиг 3 байта в регистре SAR BYTE PTR [SI], CL арифметический сдвиг * бяйтэ в памяти ROR WORD PTR [BX] [DI], 1 -Циклический сдвиг I слова ё памяти Одно из применений Команд сдвигов заключается в быстром (по сравнению с соответствующими явными командами) умножении и делении операндов на степени 2. Следующие команды показывают, как умножить и разделить содержимое регистра ВХ на 8 с предположении, что регистр CL содержит 3: SHL BX, CL ;Умножение беззнакового числа SAL BX, CL ;Умножение знакового числа SHR BX, CL ;Деление беззнакового числа SAR BX, CL -.Деление знакового чцсла Следующий фрагмент осуществляет умножение содержимого регистра АХ на 15: MOV CL, 4 ;Константа сдвига MOV DX, АХ ;Сохранить содержимое АХ SAL AX, CL ;Умножить содержимое АХ ; на 16 SUB АД, DX ^корректировать для умно* ; жения на 15 .38
1.5.4. КОМАНДЫ ПЕРЕДАЧИ УПРАВЛЕНИЯ В разветвляющихся и циклических программах, при организации подпрограмм и обработке прерываний требуется выполнять не следующую по порядку команду, а команду» находящуюся в другой ячейке программной памяти и определяемую адресом перехода. Специальные команды, которые каким-либо образом модифицируют указатели программной памяти (регистры PC и CS), называются командами передачи управления. Они не изменяют состояний флажков (за исключением команды ЩЕТ возврата из прерывания). Сегментная организация памяти определяет две разновидности команд передачи управления. Передача управления в пределах текущего сегмента кода называется внутрисегментной, при этом модифицируется только PC и адрес перехода представлен одним словом. Передача управления вне текущего сегмента кода называется межсегментной; здесь необходимо модифицировать регистры PC и CS и адрес перехода должен быть представлен двумя словами сегментхмещение. В ассемблерных программах операндом команд передачи управления служит адресное выражение, определяющее ту команду {target), которой передается управление. Команда безусловного перехода. В МП К1810ВМ86 мнемоника JMP обозначает команды безусловного перехода пяти форматов, которые имеют одно и то же ассемблерное представление: JMP target где target каким-либо образом определяет адрес перехода. Формат команды ассемблер выбирает автоматически в соответствии с атрибутами операнда. Двухбайтная команда JMP во втором байте содер-. жит знаковое значение из диапазона —128ч—hl27. При выполнении команды оно прибавляется к. содержимому регистра PC, которое соответствует адресу команды, находящейся после команды JMP. Эта команда удобна для организации коротких программных циклов. Трехбайтная команда JMP производит такое же действие, как и предыдущая команда, но содержит 16-битное смещение. Оно по-прежнему считается знаковым целым, поэтому область перехода составляет от —32 768 до +32 767 байт. Обе эти команды реализуют внутрисегментный переход. 89
Еще одна команда JMP осуществляет внутрисегментный косвенный переход. Здесь адресом перехода, загружаемым в PC, служит содержимое общего регистра или слова из памяти, определяемого в любом режиме адресации. Например, команда JMP ВХ загружает в PC содержимое регистра ВХ, а команда JMP WORD PTR [SI] загружает в PC слово из памяти, находящееся в сегменте данных и имеющее смещение в регистре SI. Последние две команды JMP реаллзуют прямой и косвенный межсегментные переходы. Первая из них содержит два слова прямого адреса перехода, которые загружаются в регистры PC и CS. В команде косвенного межсегментного перехода допускается указывать только память. При ее выполнении слово из адресуемой ячейки загружается в регистр PC, а следующее слово — в регистр CS. Примеры команд безусловного перехода: JMP SHORT LABEL ;Короткий переход JMP NEAR PTR LABEL внутрисегментный ; переход JMP DWORD PTR ES:[BX] [SI] ;Межсегментйыйкос- ; венный переход Команды условных переходов. При выполнении любой из 19 двухбайтных команд условных переходов проверяется некоторое условие, представленное текущими состояниями флажков (а в команде JCXZ — содержимым регистра СХ), и в зависимости от удовлетворения условия переход осуществляется или нет. Эти команды поз-, воляют проверить оба состояния всех арифметических флажков, кроме флажка AF, а также ряд комбинаций нескольких флажков. Если условие «истинно», управление передается по адресу перехода путем прибавления к содержимому регистра PC однобайтного знакового смещения, а если условие «ложно», выполняется следующая по порядку команда. Следовательно, все условные переходы.являются короткими и диапазон перехода составляет от —128 до +127 байт. Многие команды условных переходов имеют две мнемоники, подчеркивающие содержательный смысл проверяемого условия. Например, в командах SUB AX, DX JZ ZERO ;Перейти, если нуль 40
переход к метке ZERO происходит, если» команда вычитания образует в регистре АХ нулевой результат. Вместе с тем команды CMP AX, DX JE ZERO ;Перейти, если равно выполняют переход к метке ZERO, если в регистрах АХ и DX находятся одинаковые числа. Команды JZ и JE осуществляют переход, если ZF=1,-ho их мнемоники лучше передают содержательный смысл. Обычно команды условного перехода применяются после команды сравнения и позволяют Проверить все отношения между знаковыми и беззнаковыми числами в соответствии с табл. 1.4. Таблица 1.4. Условные переходы после команды сравнения Перейти, если Получатель больше источника Получатель равен источнику Получатель не равен источнику Получатель меньше источника Получатель меньше или равен источнику Получатель больше или равен источнику Беззнаковое число JA JE JNE . JB JBE JAE Знаковое число JG <щ JNE ' Jb JLE JGE Термины больше (Greater) и меньше (Less) относятся к знаковым числам, а термины выше (Above) и ниже (Below) — к беззнаковым. Например, число ВЕ^ (равное 190 как беззнаковое и —66 как знаковое) оказывается меньше и выше числа 37ie (как беззнаковое и знаковое оно равно 55). Команды вызова подпрограмм. В поле операнда команды CALL вызова подпрограммы находится адресное выражение (в простейшем случае — метка), определяющее точку входа подпрограммы, и последнее действие этой команды заключается в загрузке значения адресного выражения в регистр PC (внутрисегментный вызов) или в регистры PC и CS (межсегментный вызов). Однако при переходе к подпрограмме необходимо временно запомнить точку вызова или адрес возврата — им является адрес команды, находящейся после команды CALL. Завершающая подпрограмму команда RET (urn) возврата должна передать управление по запомненному 41
адресу возврата. Удобным «хранилищем» адресов воз- вратов является стек. Поэтому первое действие команды CALL заключается в том, чтобы включить в стек содержимое регистра PC (внутрисегментный вызов) или содержимое регистров PC и CS (межсегментный вызов) с соответствующей коррекцией указателя стека SP. Команда CALL допускает такие же режимы адресации, как и команда JMP, но короткий вызов отсутствует (обычно подпрограмма удалена более чем на 128 байт). Примеры команд вызова подпрограммы: CALL SUBR ; Внутрисегментный прямой .; вызов CALL BX ;Внутрисегментный косвенный ; вызов CALL NEAR PTR [ВХ] внутрисегментный косвенны Г ; вызов CALL FAR PTR SUBR ^Межсегментный прямой вызов Команды возврата из подпрограммы. Каждая подпрограмма должна иметь минимум одну команду RET возврата, которая йередает управление вызывающей программе, привлекая для этого сохраненный в стеке адрес возврата. В соответствии с типами команды CALL име,- ются команды возврата двух типов: внутрисегментные и межсегментные. Выполнение команды внутрисегмецт^ ного возврата заключается в том, что слово из вершины стека передается в PC и производится инкремент указателя стека на 2. Выполнение команды межсегментного возврата несколько сложнее: слово из вершины стека передается в PC; производится инкремент SP на 2; слови из новой вершины стека передается в CS, и производится заключительный инкремент SP на 2. Длина таких команд RET составляет всего 1 байт. В трехбайтных командах возврата вида RET n содержатся 2 байта данных, интерпретируемых как беззнаковое целое число. Дополнительное действие этих команд заключается в прибавлении к SP числа п (после извлечения из стека адреса возврата). Коррекция SP упрощает возврат из тех подпрограмм, параметры которым передаются в стеке, так как продвижение SP вперед эквивалентно удалению параметров из стека (говорят также про «очистку» стека). Примеры команд возврата из подпрограмм: 42
RET ;Тип возврата определяется ; соответствующей коман- RET 16 . ; дой вызова Команды управления циклами. Три двухбайтные команды управления циклами упрощают организацию программных циклов. В них предполагается, что счетчиком цикла служит регистр СХ. Второй байт команд представляет собой знаковое число, которое при переходе к началу цикла прибавляется' к содержимому регистра PC. В ассемблерных программах поле операнда команд управления циклами занято меткой первой команды цикла. При выполнении команды LOOP производится декремент регистра СХ и, если (СХ)=0, второй байт команды прибавляется к PC, т. е. осуществляется переход к началу цикла; в противном случае выполняется следующая по порядку команда, что соответствует выходу из цикла. Таким образом, команда LOOP MORE эффективно заменяет две команды: DEC СХ и JNZ MORE. Довольно часто требуется оргайизовать цикл, условием окончания которого является не просто достижение нуля в регистре СХ, а какое-то дополнительное событие. Мнемоники LOOPE и LOOPZ определяют одну и ту же машинную команду, которая производит декремент СХ, а затем передает управление в начало цикла, если (СХ)=0 и ZF=l. В командах LOOPNE и LOOPNZ дополнительным условием перехода к-.началу цикла является нулевое состояние флажка ZF. Следующий фрагмент отыскивает в массиве байт первый ненулевой элемент. Предполагается, что длина массива находится в регистре СХ, а начальный адрес — в регистре ВХ. DEC ВХ ;Подготовить цикл MORE:- INC BX^ ;Продвинуть указатель CMP BYTEPTR[BX], 0;Сравнить элемент с ; нулем LOOPE MORE ;Повторять JNZ NOFOUND ;Нулевых байт нет . . . ;Адрес нулевого байта ; вВХ Команды прерываний. Микропроцессор К1810ВМ86 имеет три команды программных прерываний. Выполнение их напоминает реакцию МП на запросы аппаратных 43
прерываний по входам INT и NMI, но без циклов шины подтверждения прерывания: в стек последовательно включается содержимое регистров флажков, CS и PC, а затем в соответствии с типом прерывания (он встроен в команду) осуществляется косвенный межсегментный переход через память к нужной процедуре прерывания. Двухбайтные команды INT n имеют во втором байте тип прерывания, который программист задает в ноле операнда как беззнаковое число из диапазона от 0 до 255. Если поле операнда пустое, ассемблер дбразует однобайтную команду прерывания с фиксированным типом 3—это так называемое прерывание контрольной точки или контрольною останова. Наконец, команда INTO прерывания при переполнении генерирует прерывание с фиксированным типом 4, если только установлен флажок переполнения OF. Возврат из процедур прерываний осуществляет специальная команда IRET, которая извлекает из стека и возвращает «по назначению» запомненное содержимое регистров PC, CS и флажков. 1.5.5. ЦЕПОЧЕЧНЫЕ КОМАНДЫ Цепочкой (или строкой) называется последовательность байт или слов, находящихся в смежных ячейках памяти. Микропроцессор К1810ВМ86 имеет пять однобайтных команд, оперирующих одним элементом цепочки (эти команды иногда называются элементарными опера-, циями или примитивами). Однако комацде может предшествовать префикс повторения ( модификатор) REP (eate), который вызывает повторение действия, команды над следующими элементами. Благодаря пре«; фиксу повторения цепочки обрабатываются значительно быстрее, veM при организации цикла. Повт<грение рассчитано на максимальную длину цепочек 64К байт и заканчивается по одному или двум условиям. Аппаратно подразумевается, что цепочка-источник по умолчанию находится в текущем сегменте данных (но допускается замена сегмента) и смещение ее текущего элемента содержится в регистре SI, — отсюда и название этого регистра «индекс источника». Цепочка-получатель всегда находится в дополнительном сегменте данных, а смещение ее текущего элемента берется из регистра DL Следовательно, явно адресовать цепочки не 44
нужно и ассемблер привлекает поле операнда только для определения типа элементов цепочки — байты или слова. При выполнении команд индексные регистры автоматически модифицируются так, чтобы адресовать следующие элементы.цепочек. Флажок направления DF показывает их автоинкремент (DF==0) или автодекремент (DF=1). Инкремент/декремент производится на 1 при обработке цепочек байт и на 2 при обработке цепочек слов. При указании префикса повторения в каждой элементарной операции осуществляется декремент регистра СХ. Когда его содержимое достигает нуля, управление передается следующей по порядку команде. Префикс повторения. Этот префикс имеет пять мнемонических обозначений, которые определяют всего 2 байта- кода префикса. Префикс REP в командах передачи MOVS и запоминания STOS означает «повторять до достижения конца цепочки», т. е. до получения (СХ)=0. Префиксы REPE и REPZ в командах сравнения, CMPS и сканирования SCAS для инициирования следующего повторения дополнительно требуют ZF«=1. Наконец, префиксы REPNE и REPNZ для повторения этих же команд требуют ZF=0. Команда MOVS. Команда MOVS передачи цепочки MOVS dst, src dst-<-(src) передает байт (слово) из цепочки src в цепочку dst и соответственно модифицирует регистры SI и DI. Эта команда с префиксом повторения REP осуществляет блоковую передачу память—память. Для реализации передачи необходима следующая подготовка: установить нужное состояние флажка DF; загрузить смещение цепочки-источника в регистр SI; загрузить смещение цепочки-получателя в регистр QI; загрузить в регистр СХ число передаваемых элементов (байт или слов). После этого выполняется команда MOVS с префиксом REP. Следующий фрагмент копирует 100 слов из цепочки SOURCE (находящейся в сегменте данных) в цепочку DEST (она находится в дополнительном сегменте данных) : 45
DEST DW 100 DUP (?) Зарезервировать ; место CLD Движение вперед LEA SI, SOURCE ;Адрес источника LEA DI, ES: DEST ;Адрес получателя MOV CX, 100 ;Счетчик элементов REP MOVS DEST, SOURCE ;Пересылать слова Ассемблер узнает о передаче слов по типу переменное DEST, которая определена директивой DW и формирует' команду передачи именно слов. Если бы переменная DEST была определена директивой DB, ассемблер сфор-' мировал бы команду передачи байт. Таким образом, ассемблер обращается к полю операнда в общей команде MOVS только для определения типа элементов цепочек, а местоположение цепочек задают регистры DS : SI u ES : DI. Поэтому целесообразно предусмотреть в ассемблере мнемоники MOVSB и MOVSW, явно указывающие тип элементов (В — байт, W — слово) и не требующие никакой информации в поле операнда. Команда CMPS. Команда сравнения цепочек СМР имеет следующее общее представление: CMPS dst, src (src) — (dsf) Она производит вычитание текущих элементов цепочек и по результату вычитания устанавливает все арифметические флажки. Сами операнды не изменяются, а регистры SI и DI продвигаются на следующие элемента цепочек. Префикс REPE (или REPZ) придает команде смысл, «сравнивать до тех пор, пока не достигнут конец цепочек или элементы цепочек будут не равны», а префикс REPNE (или REPNZ) — «сравнивать до тех пор, пока не достигнут конец цепочек или элементы цепочек будут равны». Например, фрагмент CLD MOV СХ, 100 REPE CMPS DEST, SOURCE будет сравнивать до 100 элементов цепочек DEST и SOURCE, пытаясь найти неодинаковые элементы. Следующий фрагмент 46
CLD MOV CX, 100 REPNE CM PS DEST, SOURCE также сравнивает цепочки DEST и ROURCE. Операция прекращается после производства 100 сравнений или обнаружения одинаковых элементов цепочек. Для явного указания типа элементов обычно допускаются мнемоники CMPSB и CMPSW. Команда SCAS. Команда сканирования (просмотра) цепочки SCAS dst (ac) — (dst) вычитает элемент цепочки, адресуемый ES : DI, из содержимого аккумулятора AL (байт) или АХ (слово). Разность определяет состояния арифметических флажков, но сами операнды не изменяются. С префиксом REPE (или REPZ) команду SCAS можно использовать для поиска элемента цепочки, отличающегося от заданного значения, а с префиксом REPNE (или REPNZ) — равного заданному в аккумуляторе значению. Мнемоники SCAS В и SCASW явно задают тип элементов цепочки. Рассмотрим, например, следующий фрагмент: CLD -Движение вперед MOV AL, 30 :Отыскиваемое значение MOV CX, 100 ;Длина цепочки REPNZ SCASB ;Сканировать цепочку Здесь команда SCASB просматривает до 100 байт цепочки, пытаясь найти элемент, который содержит 30. Если такой элемент обнаруживается» в регистре D1 возвращается смещение следующего за ним элемента, а флажок ZF будет содержать 1. Условие окончания поиска можно проверить командой JCXZ (перейти, если в СХ содержится 0): переход будет выполнен, если в цепочке нет байта, содержащего 30. Команда LODS. Команда загрузки элемента цепочки в аккумулятор LODS src ас*-(src) передает элемент цепочки, адресуемый DS : SI, в аккумулятор AL или АХ и продвигает SI на следующий элемент. Обычно команда LODS с префиксом повторения не применяется, но ее удобно использовать в программных циклах вместо команд MOV ас, src и INC SI (или DEC 47
SI). Обычно допускаются мнемоники LODSB и LODSW, явно указывающие тип элементов цепочки. Команда STOS. Команда запоминания аккумулятора в цепочке STOS dst dst<-{ac) передает байт (слово) из аккумулятора AL (АХ) в эле- .мент цепочки, адресуемый ES : DI, и продвигает DI на следующий элемент. С префиксом повторения этой командой можно инициализировать целую цепочку (т. е. область памяти) на некоторое фиксированное значение, например' на нуль или пробел. Мнемоники STOSB п STOSW явно индентифицируют тип элементов цепочки. 1.5.6. КОМАНДЫ УПРАВЛЕНИЯ МИКРОПРОЦЕССОРОМ Несколько команд этой группы предназначены для управления состоянием флажков. С их помощью можно установить (STC), сбросить (CLC) и инвертировать (CMC) флажок переноса CF, установить (STD) и сбросить (CLD) флажок направления DF, установить (STI) и сбросить (CLI) флажок прерывания IF. Команда HLT останова прекращает действия МП и переводит его в состояние останова. Из этого состояния МП выводится сигналом CLR сброса, а также запросами прерываний на входах NMI и INT. Таким образом, с помощью команды HLT действия МП синхронизируются с прерываниями от внешних источников. Команда WAIT ожидания заставляет МП циклически проверять уровень сигнала на входе TEST.- При появлении активного (низкого) уровня сигнала TEST будет выполняться команда, находящаяся за командой WAIT. При выполнении команды WAIT микропроцессор стандартным образом реагирует на внешние прерывания, возвращаясь к прерванной команде после обслуживания прерывания. Механизм WAIT—TEST позволяет синхронизировать действия МП с работой какого-либо внешнего устройства. Команда LOCK, называемая префиксом блокировки шины, заставляет МП сформировать активный сигнал LOCK на время выполнения следующей команды. В мультипроцессорных конфигурациях сигнал LOCK подается в, арбитр шины, который не разрешает доступ к шине других устройств (процессоров). 48
Холостая команда NOP не производит никаких действий, кроме инкремента программного счетчика PC, и обычно применяется в программных циклах задержки. С помощью команды NOP можно также удалять из программы ненужные команды без ее повторного ассемблирования. Команда ESC переключения на сопроцессор не является в строгом смысле командой МП К1810ВМ86. За этой мнемоникой скрываются все команды арифметического сопроцессора К1810ВМ87. Встретив такую команду*, МП К1810ВМ86 может только обратиться к памяти за операндом и выдать его на шину данных (подробнее см. в гл. 2). Глава 2 АРИФМЕТИЧЕСКИЙ СОПРОЦЕССОР К1810ВМ87 В настоящей главе достаточно подробно рассмотрен арифметический сопроцессор К1810ВМ87: его внутренняя организация, программная модель, типы обрабатываемых данных и система команд. При необходимости изложение сопровождается небольшими программными фрагментами. Отметим, что § 2.8, посвященный специальным числовым значениям и особым случаям, предназначен для опытных пользователей и его при первом чтении можно пропустить. 2.1. СОПРОЦЕССОРНЫЕ КОНФИГУРАЦИИ Как отмечалось в предисловии, необходимо отчетливо представлять себе механизм взаимодействия процессоров э сопроцессорных конфигурациях. Поэтому рассмотрим его сначала в общем виде, а детально в § 2.7 [4-7]. Сопроцессоры, называемые вспомогательными процессорами (а т'акже подчиненными процессорами и процессорами расширения), проектируются с учетом их потенциальных областей применения. На эти области ориентируются форматы обрабатываемых ими данных 4-723 49
и система команд. Сопроцессор подключается к системной шине параллельна с центральным процессором (иногда называемым главным процессором или даже хост-процессором) и может работать только совместно с ним. Объясняется это тем, что сопроцессор не имеет своей индивидуальной программы и не может самостоятельно инициировать выборку команд из программной памяти.. Его команды замешаны в командном потоке централь* ного процессора. Выборку команд осуществляет центральный процессор, все команды попадают в оба процессора, а выполняет каждый из них только свои команды. Часть кодов операций центрального процессора резервируется для сопроцессора, и «выполнение» соответствующих команд центральным процессором сводится максимум к обращению в память за операндом. Если выбранная команда оказывается командой центрального процессора, он выполняет ее обычным образом, а сопроцессор не привлекается — он просто игнорирует такие команды. Когда выбирается команда сопроцессора, действия центрального процессора зависят от специфики конкретной команды. Если команда не связана с обращением к памяти, центральный процессор ее игнорирует и переходит к следующей команде. Но если команда требует обращения к памяти, центральный процессор вычисляет физический адрес операнда и обращается к памяти, при этом сопроцессор перехватывает с общей шины физический адрес операнда, а в операции со считыванием из памяти — еще и данные. После этого сопроцессор реализует конкретные действия по выполнению команды. Они могут производиться параллельно с дальнейшими действиями центрального процессора, что повышает эффективную производительность системы. Приведенное выше простое объяснение взаимодействия центрального процессора и сопроцессора необходимо утрчнить для тех ситуаций, когда их совместная работа требует синхронизации. Действительно, центральный процессор как бы проскакивает команды сопроцессора, и продолжительность их выполнения равна незначительному времени обращения к памяти. Реальное выполнение этих команд в сопроцессоре обычно требует гораздо больше времени, особенно таких сложных команд, как извлечение квадратного корня, возведение в степень, нахождение логарифма и др. Далее покажем, что элементарные и быстро выполняемые в обычных процессорах 50
операции загрузки и запоминания могут оказаться для сопроцессора сложными и продолжительными. Объясняется этот парадокс преобразованием чисел из одного формата в другой. Синхронизация по командам. Когда центральный процессор выбирзет для выполнения команду сопроцессора, последний может быть занят операциями своей предыдущей команды и, естественно, не может начать выполнять выбранную команду. Центральный процессор не должен пропускать в сопроцессор его команды быстрее, чем сопроцессор может их выполнять. Следовательно, перед каждой командой сопроцессора в программе должна находиться специальная команда центрального процессора, которая только проверяет текущее состояние сопроцессора и, если он занят, переводит центральный процессор в состояние ожидания» Разумеется, зто ожидание оказывается для центрального процессора бесполезной потерей времени. Таким образом, в системе команд центрального процессора потребуется команда проверки состояния сопроцессора (конечно, ей окажется команда WAIT), а введение этих команд в объектную программу перед каждой командой сопроцессора могут осуществить ассемблер или компилятор языка высокого уровня автоматически без специальных указаний про-, граммиста. Принципиально команду проверки и ожидания можно помещать и после каждой команды сопроцессора. Но в этом случае центральный процессор не будет выполнять никаких команд до тех пор, пока сопроцессор не освободится, и степень параллелизма работы обоих процессоров ухудшается. . '• Синхронизация по данным. Если выполняемая сопроцессором команда записывает операнд в ячейку памяти, перед прследующей командой центрального процессора, которая обращается к этой же ячейке, также необходима аналогичная команда проверки состояния сопроцессора. В том случае, когда сопроцессор не успел записать результат в память до того, как он потребовался центральному процессору, последний должен ожидать завершения действий сопроцессора. Автоматически учесть такие ситуации довольно сложно, поэтому вводить команда, которые проверяют состояние сопроцессора и при необходимости заставляют центральный процессор ожидать, должен программист. 4» 51
Рис. 2.1. Действия центрального процессора Когда команда сопроцессора требует дополнительных обращений к памяти, сопроцессор должен запрашивать шину у центрального процессора. При получении разрешения (или подтверждения запроса) сопроцессор самостоятельно инициирует обращение к памяти. Следовательно, в механизме взаимодействия центрального про-, цессора и сопроцессора необходимы сигналы запроса/ разрешения шины. На рис. 2.1 и 2.2 дано графическое пояснение действий центрального процессора и сопроцессора при выполнении команд программы. Выделенные линии на рис. 2.1 показывают, когда центральный процессор должен ожидать завершения действий сопроцессора. Еще одна интерпретация совместной работы обоих процессоров во времени представлена на рис. 2.3. Фрагмент программы содержит команды центрального процессора и арифметического сопроцессора (они обозначены Щ1'£ и AC-i соответственно). Правый столбец иллюстрирует действия центрального процессора» причем заштрихованные места соответствуют выполнению им комад сопроцессора, а левый — действия сопроцессора. Из рисунка видно, что к.моменту начала выполнения команды АС-2 центральным процессором сопроцессор еще не закончил выполнять команду АС-1 и централь- 62
Рис. 2.2. Действия сопроцессора ный процессор будет ожидать. Такая же ситуация возникает и при выполнении команды АС-2. Эти два случая соответствуют синхронизации по командам. На рис. 2.3 предполагается, что команды сопроцессора АС-3 и АС-5 осуществляют запись результатов в память, а команды центрального процессора ЦП-4 и ЦП-7 обращаются к этим результатам, • Поэтому команды ЦП-4 и ЦП-7- не начинают выполняться до тех пор, пока не будут завершены команды АС-3 и АС-5. Здесь возникает необходимость синхронизации по данным. 2.2. ВНУТРЕННЯЯ ОРГАНИЗАЦИЯ СОПРОЦЕССОРА Арифметический ^сопроцессор К1810ВМ87 предназначен для работы с микропроцессором К1810ВМ86, выступающим в роли центрального процессора в конфигурации максимального режима. Сопроцессор в вычислительных задачах повышает производительность системы в 10—50 и более раз по сравнению с их программной эмуляцией на центральном процессоре (по образному выражению «сопроцессор превращает минуты в секунды»). Отдельные его команды могут, заменять сотни команд центрального процессора. Микросхема Ю810ВМ87 производится. по высококачественной ЫМОП-технологии, имеет 40-контактный корпус с двухсторонним расположением выводов (DIP), 53
Рис. 2.3. Временная диаграмма взаимодействия центрального. лро- цессора и сопроцессора напряжение питания составляет + 5±0,25 в, а потребляемая мощность — около 2 Вт. Однофазные сигналы синхронизации имеют частоту 2—5 МГц. На кристалле сопроцессора размещено около 75 тыс. транзисторов (в 2,5 раза больше, чем у центрального процессора!). Механизм взаимодействия центрального процессора * и сопроцессора требует, чтобы они синхронизировались от одного и того же источника синхроимпульсов [5]. Временная диаграмма работы сопроцессора и его управляющие сигналы совместимы с МП К1810ВМ86, поэтому они подключаются к общей шине без специаль- 54
ных согласующих схем, Солродессор имеет почти такую же разводку сигнальных линий, что и МП К1810ВМ86, поэтому их не приводим. Однако с учетом особенностей его работы имеются следующие отличия в определении сигнальных линий: сигналы NMI, LOCK и MN/MX отсутствуют, вход TEST заменен на выход BUSY (занят тость), сигнал прерывания INT является выходным, а сигналы состояния очереди QS1 и QS0 —входные. Два варианта структурных схем сопроцессора, представленные на рис. 2.4, а, б, показывают, что он состоит из двух сравнительно автономных устройств: устройства управления (или шинного интерфейса) и численного операционного (исполнительного) устройства [3, 7]. Устройство управления предназначено для восприятия команд, считывания и записи данных, выполнения команд управления сопроцессором, а также согласования действий сопроцессора и центрального процессора. Как показано выше, команды сопроцессора в потоке команд, выбираемых из программной памяти только .центральным процессором, чередуются с командами самого центрального процессора. Сопроцессор определяет цикл выборки команды по сигналам состояния ST2— ST0, и при появлении байта или слова команды на шине адреса/данных устройство управления подключается к ней параллельно с центральным процессором и воспринимает команду. В устройстве управления предусмотрена очередь команд, аналогичная очереди команд центрального процессора. Путем контроля сигналов на линиях QS центрального процессора устройство управления сопроцессора выбирает (из очереди) и дешифрует команды синхронно с центральным процессором. Другими словами, оба процессора работают со своими очередями команд параллельно, но выполняют команды по-разному. Первые 5 бит кода операции всех команд сопроцессора одинаковы (код 11011) —они определяют команду ESC переключения на сопроцессор. По существу, мнемоника ESC в системе команд центрального процессора как бы заменяет собой мнемоники всех команд сопроцессора и в ассемблерных программах не употребляется — вместо нее указывается одна из команд сопроцессора. Свою команду, т. е. команду сопроцессора, устройство управления либо выполняет само, либо передает в численное 65
Рис. 2.4. Структурная схема арифметического сопроцессора 66
операционное устройство, а команды центрального процессора оно игнорирует. Центральный процессор различает несколько типов команды ESC. Если в команде требуется обращение к памяти, он вычисляет физический адрес, а затем инициирует цикл обращения к памяти. При считывании из памяти центральный.процессор игнорирует данные, т. е. для него это действие оказывается фиктивным считыванием. Когда команда ESC не связана с обращением к памяти, центральный процессор просто переходит к следующей команде. Воспринятая сопроцессором команда ESC может потребовать загрузки операнда из памяти или записи результата в память, но может быть и не связана .с обращением к памяти. В первых двух случаях устройство управления сопроцессора использует цикл фиктивного считывания, инициируемый центральным процессором. Оно воспринимает и сохраняет 20-битный физический адрес операнда, который центральный процессор выдает на шину адреса/данных/состояния. Если команда определяет загрузку (т. е. передачу данных в сопроцессор), устройство управления воспринимает первое и, возможно, единственное слово операнда в момент его появления на шине адреса/данных» Когда длина операнда превышает одно слово, устройство управления сразу запрашивает шину у центрального процессора и считывает остальную часть операнда. Команда с записью в память заставляет устройство управления зафиксировать физический адрес памяти. Если сопроцессор готов к операции записи, устройство управления запрашивает шину у центрального процессора и записывает результат по ранее перехваченному адресу. В зависимости от длины результата инициируется необходимое число последовательных циклов шины. В устройстве управления имеются два программно доступных 16-битных регистра, в которых хранятся слово управления и слово состояния (их назначение и форматы см. в § 2.5). Четыре 16-битных регистра указателей содержат физические адреса команды и операнда, а также 11 бит кода операции. Указатели явно в командах не адресуются, но их содержимое может быть передано в память и в них можно загружать слова из памяти как элементы полного состояния сопроцессора. В основном 57>
ими оперируют процедуры обработки особых случаев (см. §2.8). Численное операционное устройство выполняет все чиеленные команды, так или иначе связанные с*внутрен- ним регистровым стеком. В его составе есть несколько быстродействующих специализированных модулей, реализующих операции над мантиссами и порядками, а также параллельные сдвиги. Параллельные передачи по внутренней шине данных осуществляются с очень высокой скоростью. С точки зрения программиста сопроцессор К1810ВМ87 можно считать просто расширением центрального процессора КД810ВМ86 в части регистров, допустимых форматов чисел и системы команд. Взаимодействие между ними на аппаратном уровне невидимо (или прозрачно) для программ. 2.3. ПРОГРАММНАЯ МОДЕЛЬ СОПРОЦЕССОРА Напомним, что в программную (регистровую) модель любого процессора включаются только те регистры, которые доступны программисту на уровне машинных команд. С такой точки зрения сопроцессор имеет удивительно простую программную модель. Он, как и большинство других арифметических сопроцессоров, опирается на общую стековую организацию. Выбор ее обусловлен несколькими обстоятельствами. Одно из них заключается в том, что в математических расчетах результат текущей операции часто может заместить один или оба исходных операнда и является операндом следующей команды. Стековая организация позволяет в этих случаях применять так называемые безадресные (нуль- адресные) команды небольшой длины, сокращая таким образом число обращений к памяти и, следовательно, повышая быстродействие. Представление математических выражений в обратной польской записи, естественно, приводит к стековой организации процессора, который вычисляет эти выражения. Основу программной модели сопроцессора, показанной на рис. 2.5, образует регистровый стек из восьми 80-битных регистров RO—R7, В этих (арифметических) регистрах хранятся числа, представленные в так называемом временном вещественном формате (см. § 2.4). В любой момент времени трехбитное поле ST в слове состояния определяет регистр, являющийся текущей вер- 58
Рве. 2.5. Программная модель сопроцессора шиной стека (Stack Top) ц обозначаемый ST(0) или просто ST (иногда в литературе встречается обозначение 70S —Top of Stack). При операции включения в стек (push) осуществляется декремент поля ST и загружаются адресуемые данные в новую вершину стека. При оле- рации извлечения из стека (pop) в получатель, которым чаще всего является память, передается содержимое текущей» вершины стека, а затем производится инкремент поля ST. Таким образом, при стандартных стётовых операциях поле ST выполняет функции традиционного указателя стека SP (Stack Pointer). В организации регистрового стека сопроцессора имеется несколько отлйчяй от классического стека, который в большинстве современных сопроцессоров аппаратно реализуется в памяти [6]. Во-первых, стек имеет круговую (кольцевую) орга- 59
низацию. Это означает, что, если поле ST содержит 0002 и производится его декремент, новым содержимым ST будет 1112,'а если поле ST содержит 1112 и осуществляется его инкремент, новым содержимым ST будет 000г. Контроль за использованием стека должен осуществлять программист. В частности, необходимо помнить, что максимальное число включений в стек без промежуточных извлечений равно восьми, а девятое включение перезапишет элемент, помещенный в стек первым (на самом деле сопроцессор зафиксирует здесь особый случай недействительной операции и перезаписывание произойдет, если только прерывание от этого особого случая замаскировано или запрещено). Во-вторых, в командах сопроцессоре допускается явное или неявное обращение к регистрам стека с модификацией или без модификации поля ST. Так, в некоторых унарных операциях операндом служит содержимое вершины стека, а результат замещает операнд. Например, команда FSQRT замещает число из вершины стека значением квадратного корня из этого числа. В некоторых бинарных операциях операндами служат числа в двух верхних регистрах стека, а результат пбмещается на место одного из них. . Более того, команда сравнения: FCOMPP сравнивает содержимое двух верхних регистров стека и удаляет его, производя инкремент ST на 2. Наконец, в бинарных операциях допускается явное указание регистров, содержащих операнды. Явная адресация регистров осуществляется относительно текущей вершины стека, jl обозначение ST(/) определяет i-й регистр в стеке, 0^t^7, считая от ST(0). Если, например, поле ST содержит 1002, т. е. вершиной стека является регистр R4, то команда FADD ST, ST(2) прибавит к числу в регистре R4 число из регистра R6 (рис. 2.6). Программист работает относительно текущей вершины стека и не употребляет абсолютных номеров (имен) регистров R0, R1 и т. д. Принятые в сопроцессоре организация стека и адресация регистров упрощают программирование с использованием подпрограмм. Через стек удобно передавать подпрограмме параметры и осуществлять доступ к ним в процессе ее выполнения; а также обращаться к результатам после завершения подпрограммы. 60
Рис. 2.6. Адресация регистров стека В-третьих, сопроцессор имеет команды, в которых не выдерживаются обычные соглашения о стеке, т. е. о том, что любая стековая операция автоматически модифицирует указатель стека. Например, команда FST (запомнить в памяти) передает содержимое вершины стека в память, но не производит инкремент поля ST. Команда FXCH (обменять) позволяет обменять содержимое вершины стека и любого другого регистра. Предусмотрены также специальные команды инкременте и декремента поля ST. С каждым регистром стека ассоциируется двухбитный тзг (признак), совокупность которых образует слово тэгов. Тэг регистра R0 находится в младших битах этого слова, а тэг регистра R7 — в старших. Тэг фиксирует наличие в регистре действительного числа (конечное ненулевое число) — код 00, истинного нуля — код 01, специального числа (денормализованное число, не-число или бесконечность) — код 10 и отсутствие данных — код 11. В последнем случае регистр называется пустым (неинициализированным) и одно из действий сопроцессора при инициализации заключается в загрузке в биты тэгов всех регистров кода 11. Попытка команды извлечь число из пустого регистра фиксируется как особый случай недействительной операции. Кроме того, попытка загрузить число в непустой регистр также вызывает регистрацию аналогичного особого случая. Таким образом, наличие регистра тэгов позволяет сопроцессору быстрее обнаруживать особые случаи и эффективнее обрабатывать специальные численные значения, включая и нуль. Программист может использовать слово тэгов для интерпретации содержимого регистров (разумеется, после передачи этого слова в память). Так как размещение тэгов соответствует физическим регистрам R7—R0, для ассоциирования тэгов с относительными регистрами ST(7)—ST(0) потребуется привлекать поле ST из слова состояния сопроцессора. 61
Рис 2.7. Формат регистров-указателей 62 Остальными регистрами в программной модели сопроцессора являются регистр управления, регистр состояния, два регистра указателя команды и два регистра указателя данных. Длина всех этих регистров составляет 16 бит. Форматы и функции регистров управления и состояния рассмотрены в § 2.5. Информация, содержащаяся в регистрах указателя команды и операнда (совместно их называют указателями особого случая), предназначена только для процедур обработки особых случаев. Когда сопроцессор выполняет численную команду, он автоматически сохраняет в этих регистрах физический адрес команды сопроцессора (т. е. адрес ее первого байта), физический адрес операнда, если он присутствует в команде, и лер&ые 11 бит кода one- рации. Так как физические адреса имеют длину 20 бит, каждый из указателей состоит из двух 16-битных регистров. Их формат показан на рис. 2.7. С помощью' команд запоминания среды FSTENV и запоминания полного состояния сопроцессора FSA- VE содержимое указателей Ряс. 2.8. Формат хранения среды сопроцессора в памяти
Рис 2.9. Формат хранения полного состояния сопроцессора в па- мяти передается в память. Следовательно, процедура обработки особого случая может точно определить команду н операнд* вызвавшие особый случай, и установить причину его возникновения. Под средой сопроцессора К1810ВМ87 понимается содержимое регистров управления, состояния» тэгов и обоих указателей. Команда FSTENV передает его в область памяти с начальным адресом, указанным в команде. Формат хранения среды в памяти показан на рис 2.8. Наконец, полное состояние сопроцессора представля- 63
ет собой содержимое вбех регистров программной модели — среды и восьми регистров стека. Размер полного состояния сопроцессора составляет 94 байта. Команда FSAVE передает его в области памяти с начальным адресом, указанным в команде. Формат размещения полного состояния сопроцессора в памяти (его иногда называют «образом в памяти») показан на рис. 2.9. Для,, возвращения среды и полного состояния из памяти в регистры сопроцессора предусмотрены команды- FLDENV и FRSTOR соответственно. В заключение отметим, что большинство прикладных программистов не касается регистров указателей и регистра тэгов, а также команд» манипулирующих средой и полным состоянием сопроцессора. Эти средства предназначены только для разработчиков процедур обработки особых случаев; такие процедуры обычно входят в состав системного программного обеспечения. 2.4. ФОРМАТЫ ЧИСЛЕННЫХ ДАННЫХ Система вещественных чисел, применяемая при ручных вычислениях, предполагается бесконечной и непрерывной. Это означает, что не существует никаких ограничений на диапазон используемых чисел и точность (количество значащих цифр) их представления. Для любого вещественного числа имеется бесконечно много чисел, которые больше и меньше его, а между любыми двумя вещественными числами также находится бесконечно много чисел. Реализовать такую систему в технических устройствах, в частности в компьютерах, невозможно. Во всех компьютерах размеры регистров и ячеек памяти фиксированы, что ограничивает систему представимых чисел. Ограничения касаются как диапазона-; так и точности представления чисел, т. е. система машинных чисел оказывается конечной и дискретной, образуя подмножество системы вещественных чисел. Арифметический сопроцессор К1810ВМ87 оперирует численными данными в семи форматах, образующих три класса: двоичные целые, упакованные десятичные целые и двоичные вещественные числа (числа с плавающей точкой). Может показаться неожиданным, что сопроцессор работает с целыми числами, так как их может обрабатывать центральный процессор. Но если исключить
Рис. 2.J0. Тип численных данных сопроцессора этот тип данных, сопроцессор не смог бы вычислить выражения, в которых фигурируют целые и вещественные числа [5, 8]. Форматы чисел показаны на рис. 2.10» а их основные характеристики (диапазон и точность) приведены в табл. 2.1. На рис. 2.10 значок вставки (Л) показывает позицию неявной точки, отделяющей целую часть числа от дробной. Отметим, что во всех форматах старший (левый) бит отведен для знака числа со стандартным кодированием: 0 означает плюс, а 1 — минус. На рис. 2.10 и в дальнейшем приняты следующие сокращения: ЦС — целое слово, КЦ — короткое целое, ДЦ —длинное целое, УПК — упакованное десятичное, KB —короткое вещественное, ДВ — длинное вещественное и ВВ — временное вещественное. Двоичные целые числа. Три формата целых двоичных чисел (ЦС, КЦ н ДЦ) отличаются только длиной и, следовательно, диапазоном допустимых чисел. Только в этих форматах для представления чисел применяется стан- 5-723 65
Таблица 2.1. Основные характеристики численных данных Формат 1 Диапазон Целое слово Короткое целое Длинное целое Упакованное десятичное Короткое вещественное Длинное вещественное Временное вещественное 10* 10» 101» low 10±38 ш±308 Точность J Особенность 16 бит 32 бита 64 бита Г8 цифр 24 бита 54 бита 64 бита Дополнительный код То же > > Прямой код Неявный бит F0 Те же Явный бит F0 дартный дополнительный код. Число 0 имеет единственное, кодирование (положительный нуль), в котором все биты содержат нули. Формат целого слова соответствует основному численному формату МП K18J0BM86. Наибольшее положительное число кодируется как 011...1, а наибольшее (по модулю) отрицательное число имеет вид 100...0. Упакованные десятичные целые. Десятичные целые числа (УПК) представляются в прямом коде и упакованном формате, т. е. каждый байт содержит две десятичные цифры в коде 8421. Старший бит левого байта отведен для знака числа, а остальные биты этого байта игнорируются, но при записи в память в них помещаются нули, В отличие от предыдущих форматов для десятичных чисел принят прямой код. Напомним, что основная причина использования дополнительного кода заключается в том, чтобы складывать и вычитать знаковые и беззнаковые целые числа одними и теми же командами. Однако в сопроцессоре нет операций над десятичными числами, а прямой код проще преобразовывать в последовательность, символов для печати по сравнению-с дополнительным кодом. Как всегда, в прямом коде появляются два представления нуля: положительный и отрицательный нули. Сопроцессор не различает их (кроме операции деления), так как знак частного зависит от знака делителя. Младшая тетрада в старшем байте не используется, что 66
объясняется стремлением к совместимости со стандартами некоторых языков программирования. Следует иметь в виду, что при наличии в тетраде запрещенных комбинаций 1010—1111 результат операции с десятичным операндом не определен. Другими словами, сопроцессор не контролирует правильность десятичных цифр. Вещественные числа. Для вещественных чисел применяется формат с плавающей точкой (KB, ДВ и ВВ). Значащие цифры числа находятся в поле мантиссы; поле порядка показывает фактическое положение двоичной точки в разрядах мантиссы, а бит знака S определяет знак числа. Мантисса, называемая также дробью F (Fraction), представлена в прямом коде. Порядок Е (Exponent) дается в так называемой смещенной форме: он равен истинному порядку, увеличенному на значение смещения:- Е=истинный порядок+смещение Значение смещения для соответствующих форматов равно 127, 1023 и 16383. Задание порядка в форме со смещением упрощает операцию сравнения чисел с плавающей точкой, превращая ее в операцию сравнения целых чисел (если операнды имеют одинаковые знаки и нормализованы), а выполнение других операций практически не усложняется. Так как. операция с целыми числами выполняется значительно быстрее операции над числами с плавающей точкой, сравнение чисел с плавающей точкой* будет производиться быстрее, что важно в алгоритмах с большим числом сравнений, например в алгоритмах сортировки. Смещенный порядок называется также характеристикой; ее можно считать целым положительны^ или беззнаковым числом. Значение числа равно Г- l)s х 2Е-смещс,пи> х F0. F, F,...Fnt где п для разных форматов равно 23, 52 или 63. Числа с плавающей точкой длиной 32 и 64 бита применяются во многих компьютерах, например в ЕС ЭВМ, СМ ЭВМ, многих персональных компьютерах, и обычно называются числами с одинарной и двойной точностью. Как правило, порядок имеет фиксированную длину, определяя один и тот лее диапазон предетавимых чисел, а для повышения точности вводятся дополнительные би- б* .67
ты мантиссы, при этом схемы арифметическо-логическо- го устройства усложняются незначительно. Однако при удвоении длины числа предпочтительнее часть бит отвести для расширения порядка. Поэтому порядок чисел в длинном вещественном формате сопроцессора состоит из 11 бит. Такой порядок обеспечивает, в частности, получение точного произведения без переполнения в антипереполнения, когда сомножители представлены в коротком вещественном формате. Отметим наличие в мантиссе бита единиц Fo. В форматах чисел с плавающей точкой большинства компьютеров бит Fb отсутствует и мантисса оказывается правильной дробью. Сопроцессор обычно поддерживает представление мантиссы в нормализованной форме, т. е. ее старший бит равен 1. Следовательно, за исключением числа О мантисса состоит из целой части и дроби в следующем виде: гяе Ft равно нулю или- единице. Благодаря нормализации устраняются старшие 0 в числах, меньших 1, что максимизирует количество значащих цифр мантиссы при ее фиксированной длине. В коротком и длинном вещественных форматах бит Fo при передачах чисел и хранении их в памяти не фигурирует. Это так называемый скрытый или неявный бит, который в нормализованных числах содержит 1. Следовательно, в этих форматах невозможно представить числа, которые не нормализованы (за исключением нулевого порядка — см-далее). Кроме того, скрытый бит не позволяет представить в этих форматах нуль и он должен кодироваться как специальное значение. Отметим также, что скрытый бит можно реализовать только при основании, на степень которого умножается мантисса, равном 2. В машинах ЕС ЭВМ это основание равно 16. Числа во временном вещественном формате имеют явный бит Fo. Такой формат позволяет несколько повысить скорость выполнения операций и обеспечить некоторые преимущества благодаря простоте представления чисел, не являющихся нормализованными. Числа во вре- меннс*м вещественном формате называются еще числами е расширенной точностью. 68
Покажем представление десятичного числа —247.375 в вещественных форматах сопроцессора. Двоичный код его равен —11110111.011г» и истинный порядок получается +7. Смещенный порядок в трех вещественных форматах равен 134, 1030 и 16390. С учетом бита Fo имеем следующие представления: Знак Порядок Мантисса Короткое вещест- 1 10000110 11101110110...0 венное Длинное вещест- 1 1Q000000110 11101110110...0 венное Временное веще-1 100000000000110 111101110110...0 ственное Независимо от исходного формата при загрузке числа из памяти в регистр сопроцессора оно автоматически преобразуется во временный вещественный формат, а при записи в память осуществляется обратное преобразование в формат получателя (вот почему элементарные и быстрые для других процессоров команды загрузки и запоминания двоичных и особенно десятичных целых чисел выполняются в сопроцессоре очень долго). Таким образом, временный вещественный формат является единственным внутренним форматом представления чисел, причем в нем абсолютно точно кодируются любые загружаемые из памяти числа. Число во временном вещественном формате можно передавать в память; это приходится делать Для хранения промежуточных результатов из-за нехватки внутренних регистров. Благодаря аппаратному преобразованию всех форматов данных во временный вещественный формат программист может не заботиться о явных преобразованиях форматов. Умножение числа с плавающей точкой на упакованное десятичное число осуществляется так же просто, как и умножение двух целых чисел. Конечно, при возвращении результата в память программист должен обеспечить, чтобы формат получателя был достаточен для восприятия результата. • Сопроцессор может представить огромное количеств во, но разумеется, не все вещественные числа из диапазонов своих форматов. Между любыми двумя соседними числами всегда существует промежуток, и результат операции может попасть именно в этот промежуток. В та* кой ситуации сопроцессор округляет истинный результат 69
до числа, которое он может представить. Следовательно, вещественное число с большим количеством значащих цифр, чем допускает сопроцессор, будет представлено неточно. Как обычно в формате с плавающей точкой, между любыми последовательными степенями двух находится одно и то же количество представимых чисел. Например, между 4 и 8 находится столько же представимых чисел, сколько между 524 288 и 1 048 576. Другими словами, промежутки между представимыми числами расширяются по мере увеличения чисел. Однако целые числа из диапазона —264-7-+2е4 (примерно ±1018) представляются во временном вещественном формате абсолютно точно. Специальные значения. В большинстве компьютеров каждый двоичный набор в конкретном формате является действительным (допустимым) численным значением. В сопроцессоре KI810BM87 большой класс двоичных наборов зарезервирован для представления специальных численных и даже нечисленных значений, например значения неинициализированной переменной в.программе. Во многих прикладных программах наличие этого класса двоичных наборов можно безопасно игнорировать. Поэтому здесь кратко охарактеризуем все специальные значения (подробнее см. в § 2.8). Отметим, что в вещественных форматах для этих значений зарезервированы смещенные порядки 00...0 и 11 1. Денормализованные числа. В операциях могут возникать настолько малые результаты, что их смещенный порядок должен быть отрицательным. Такая ситуация называется исчезновением порядка или антипереполнением (будем пользоваться вторым термином). В большинстве компьютеров антипереполнение ведет к возвращению как результата операции нуля..Однако сопроцессор сдвигает мантиссу вправо с одновременным инкрементом порядка до тех пор, пока он не будет равным нулю. Такие числа с нулевым смещенным порядком (истинный порядок равен минимальному ненулевому значению —126, —1022 и —16 382 соответственно для различных вещественных форматов) и ненулевой мантиссой называются денормализованными. Разумеется, каждый старший нуль в мантиссе ведет "к потере значимости, поэтому расширение диапазона в сторону малых чисел сопровождается потерей точности. При загрузке из памяти или использовании как опе- 70
ранда в операции денормализованное число превращается в эквивалентное ненормализованное число (с ненулевым смещенным порядком) путем сдвига мантиссы вправо и инкремента порядка. Следовательно, денорма- лизованные числа допустимы в арифметических операциях, хотя трансцендентные команды предполагают без проверки нормализованные операнды, а при нарушении нормализации возвращают непредсказуемые результаты.. Ненормализованные числа. Результат арифметической операции может"оказаться ненормализованным числом; такие числа существуют только во временном вещественном формате. Они распознаются по нулю в старшем бите Fo мантиссы и ненулевому смещенному порядку. Ненормализованные числа допустимы во всех арифметических операциях, причем по возможности результат нормализуется. Для программиста наличие денормализованных и ненормализованных чисел оказывается удобным, так как иногда вычислительные алгоритмы порождают очень малые промежуточные результаты. Вместо сигнализации об антипереполнении или возвращении нулевого результата сопроцессор разрешает продолжить выполнение программы с поддержанием максимально возможной точности. Расширение допустимых значений на ненормализованные и денормализованные числа иногда называется постепенным (или плавным) антипереполнением. Нуль. Нуль имеет нулевой смещенный порядок и нулевую мантиссу (истинный нуль) и обычно не учитывается как специальное значение. Однако необходимо знать* как сопроцессор выполняет операции с нулевыми операндами. Вещественный нуль может иметь положительный или отрицательный знак, но в операция:* знак нуля игнорируется. Некоторые операции с нулевыми операндами сопроцессор выполняет непривычно для нас. Например, результатом деления 5/0 будет бесконечность, а результатом 0/0 — неопределенность. Псевдонули. Под псевдонулем понимается число' во временном вещественном формате, которое имеет нулевую мантиссу .и смещенный порядок, отличающийся от 00...0 и 11...1. Псевдонули могут возникать в операции умножения ненормализованных сомножителей, но такие ситуации очень редки. Обычно псевдонули ведут себя как нуль, и наличие их можно безопасно игнорировать. Бесконечность. Во всех вещественных форматах до- 71
пускаются «плюс бесконечность» и «минус бесконечность», значение которых больше любого вещественного числа, представимого в конкретном формате. Бесконечности имеют смещенный порядок 11..Л и нулевую мантиссу; наличие бесконечности в регистре отмечается тэгом специального числа. Бесконечности допускаются как операнды в большинстве арифметических операций сопроцессора и обрабатываются по соответствующим правилам. Вещественная неопределенность. Под неопределенностью понимается специальное значение, которое-относится к классу яе-чисел (см. далее) и возвращается как результат операции при таких операндах, цри которых никакой осмысленный ответ невозможен. Примерами могут служить извлечение квадратного корня из отрицательного числа и деление 0/0. Неопределенность имеет отрицательный знак, смещенный порядок 11...1 и мантиссу 1дЮО...О. Наличие в регистре неопределенности отмечается тэгом специального числа. Сопроцессор формирует вещественную неопределенность как результат маскированной реакции на особый случай недействительной операции (подробнее см/в § 2.8), Целые двоичная и десятичная неопределенности. Во всех трех форматах двоичного целого наибольшее (по модулю) отрицательное число, т. е. —215, —231 и —263, считается неопределенностью. Двоичная неопределенность имеет кодирование 100...0, а десятичная —1111 1111 1111 1111 ХХХХ...ХХХХ. Использования целой двричной и десятичной неопределенностей следует избегать, так как сопроцессор считает двоичную неопределенность максимальным отрицательным числом, т.е. она не распространяется в вычислениях, а при загрузке десятичной неопределенности в регистр его содержимое оказывается непредсказуемым. Двойная интерпретация кода неопределенности (как специального значения и максимального по модулю отрицательного числа) является следствием отсутствия особых наборов в форматах целых чисел... Целая двоичная неопределенность возникает толькй в одной недействительной операции — запоминание не-числа в целом формате. He-число. Все значения, за исключением 'бесконечности и неопределенности, имеющие смещенный порядок П..Л, относятся к класоу не-чисел (NAN—Not A Number). Любая операция не-числом дает как результат не- 72
Рис. 2.11. Хранение в памяти чисел в различных форматах число, т. е. не-числа распространяются в вычислениях; передаются в окончательный ответ и могут содержать информацию о месте возникновения ошибки. При необходимости можно разработать программное обеспечение, в котором не-числа интерпретируются любым требуемым образом. Например, в статистических расчетах конкретное не-число программист может назначить отсутствующим данным. Хранение чисел в памяти. В § 1.1 подчеркивалось, что МП К1810ВМ86 предполагает хранение многобайтных элементов данных по принципу «младшее — по меньшему адресу». Этот же принцип, как видно из рис. 2.11, распространяется и на хранение в памяти чисел сопроцессора. На рис. 2.11 приняты следующие обозначения; Мл. — младший, Ст. — старший, Мл.М — младший бит мантиссы, Ст. М —старший бит мантиссы, Мл. П—» младший бит порядка, От. П — старший бит порядкд. Логически во всех форматах левый бит является стар* 73
шим, а правый — младшим. В физической памяти первым, т. е. по меньшему адресу, хранится младший байт, (этот адрес считается и адресом всего числа), а последним, т. е. по большему адресу, — старший байт. Такой своеобразный обратный порядок размещения данных в памяти принят в большинстве современных мини- и микрокомпьютеров. Передача данных всегда начинается с младшего адреса. Рекомендации по применению. В подавляющем большинстве применений для исходных данных и результатов рекомендуется использовать длинный вещественный формат. Он обеспечивает достаточные для получения правильных результатов диапазон и точность, требуя от • программиста минимальных усилий. Короткий вещественный формат целесообразен в системах с ограничениями на память, но, конечно, он имеет меньшие диапазон и точность. Его же удобно применять для отладки программ^ так как ошибки округления проявляются в этом формате наиболее быстро. Временный вещественный формат не предназначен для представления входных я выходных данных, его следует .применять для хранения промежуточных результатов, в циклических фраг-' ментах и для представления констант. Его огромный диапазон и высокая точность (значительно большие, чем у базовых форматов) гарантируют защиту окончательных результатов от ошибок округления, а также уменьшает вероятность возникновения переполнений и антипереполнений. Как правило, такие ситуации свидетельствуют об ошибках в данных или программе. Временный вещественный формат обеспечивает получение результатов с 19 десятичными значащими цифрами. Даже когда длинная последовательность вычислений приводит к значительным накопленным ошибкам округления, потеря трех или четырех цифр точности сохраняет достаточно точный результат при представлении его в длинном вещественном формате. 2.5. РЕЖИМЫ РАБОТЫ И СОСТОЯНИЕ Сопроцессор имеет два программно доступных 16-битных регистра, содержимое которых определяет его режим работы и текущее состояние. Форматы этих регистров, содержащих слово управления CW (Control Word) и слово состояния SW (Status Word), приведены на 74
Рис. 2.12. Форматы слова управления и слова состояния рис. 2.12. Регистр управления содержит 6 бит масок особых случаев, а регистр состояния 6 бит флажков особых случаев: *Р (Precision)—потеря точности, U (Underflow) — антипереполнение, О (Overflow) —-переполнение, Z (Zero divide)—деление на нуль, D (Denormal) — де- нормализованный операнд, I (Invalid operation)—недействительная операция. Слово-управления. Слово управления определяет для сопроцессора один из нескольких вариантов обработки численных данных. Для каждого варианта программист задает маскирование особых случаев, точность вычислений, способ округления и интерпретацию бесконечности. Слово управления загружается из памяти специальной командой. Следовательно, программа центрального процессора может сформировать в памяти «образ» необходимого слова управления, а затем заставить сопроцессор загрузить его в регистр CW. Кроме того, содержимое полей слова управления устанавливается при инициализации сопроцессора и может быть оставлено .по умолчанию. Рассмотрим назначение отдельных полей слова управления. Маски особых случаев. Шесть младших бит слова управления представляют собой индивидуальные маски особых случаев, т. е. необычных и даже ошибочных ситуаций, обнаруживаемых сопроцессором при выполнении команд. Если любой из этих бит установлен в 1, то возникновение соответствующего особого случая не будет вызывать прерывания центрального процессора (прерывание запрещено или замаскировано), а если бит содержит 0 — сопроцессор устанавливает в 1 бит запроса прерывания, относящийся к конкретному особому случаю,, в слове состояния и при общем разрешении прерываний генерирует сигнал INT прерывания центрального процессора.
Особый случай денормализованного операнда фиксируется, когда в операции встречается денормализован- ный операнд. При попытке деления ненулевого конечного числа на нуль сопроцессор регистрирует особый случай деления на нуль. Особый случай переполнения возникает, когда порядок истинного результата выходит за диапазон (т. е. больше) допустимого порядка получателя. Если значение истинного порядка результата слишком мало, фиксируется особый случай антипереполнения. В типичных алгоритмах появление очень больших или очень малых чисел характерно в основном для промежуточных, а не окончательных результатов. Если хранить промежуточные результаты во временном вещественном формате, переполнение и антипереполнение в сопроцессоре возникают очень редко (действительно, трудно представить себе числа, большие 104932 или меньшие 10~4932, имеющие какой-то практический смысл). Наконец, когда результат операции не может быть точно представлен в формате получателя, сопроцессор производит округление его и фиксирует особый случай (потери) точности. Он возникает довольно часто и указывает лишь на то, что происходит некоторая, обычно приемлемая, потеря точности. Этот особый случай предназначен для применений, в которых требуется только точное выполнение операций. Анализ рассмотренных особых случаев показывает, что для каждого из них нетрудно предусмотреть возвращение математически приемлемого результата операции, вызвавшей Ьсобый случай: денормализованный операнд — преобразовать операнд в эквивалентное ненормализованное число и продолжить .операцию; деление на нуль и переполнение — возвратить как результат бесконечность с правильным знаком *; точность — возвратить округленный результат. Наиболее тяжелым является особый случай недействительной операции, который, как правило, свидетельствует об ошибке в программе. Он включает в себя несколько ситуаций, которые не имеют очевидных решений, как предыдущие особые случаи. Например, без 1 Отметим, что особый случай переполнения в целых двоичных в десятичных форматах не возникает, так как эти форматы не имеют представления бесконечности; вместо переполнения регистрируется особый случай недействительной операции. 76
анализа вычислительных шагов, которые привели к делению нуля на нуль, невозможно образовать приемлемый результат. Это же относится к умножению и делению бесконечностей, умножению бесконечности на нуль, сложению бесконечностей с разными знаками, извлечению квадратного корня из отрицательного числа, любой операции с не-числом, загрузке в непустой регистр, считыванию из пустого регистра и др. Лучшее, что можно сделать при возникновении особого случая недействительной операции, — это возвратить как результат операции не-число, если им является один из операндов, большее (т. е. с большей мантиссой) из двух не-чисел, когда ими являются оба операнда, и неопределенность в остальных ситуациях. Как видно, после возникновения ие-числа оно не исчезает, а распространяется в последующих вычислениях. Обнаружение особых случаев недействительной операции, деления на нуль и денормализованного операнда происходит до выполнения операции, а остальные особые случаи регистрируются только после вычисления истинного результата. Если возник ранний особый случай, стек и память еще не были модифицированы и содержат такие данные, как будто сомнительная операция не выполнялась. При обнаружений, позднего особого случая содержимое стека и памяти изменено. Возникновение особого случая отмечается установкой в 1 соответствующего флажка в слове состояния. Далее сопроцессор проверяет маску в слове управления и определяет, следует ли только зарегистрировать особый случай (маска содержит 1) или сформировать запрос прерывания центрального процессора с последующим вызовом процедуры обработки особого случая (маска содержит 0). В первом случае сопроцессор выполняет встроенную процедуру маскированной реакции без прерывания выполнения программы, а во втором прерывает центральный процессор. Маскированные реакции сопроцессора были тщательно разработаны так, чтобы образовать наиболее правильный результат для каждого условия. Выше были приве> дены наиболее естественные реакции для всех особых случаев. Как видно, в большинстве особых случаев сопроцессор образует наиболее естественный численный результат, который может участвовать в дальнейших вычислениях, и только в особом случае недействитель- 77
ной операции возвращается не-число. Поэтому в большинстве прикладных программ рекомендуется маскировать все особые случаи, за исключением недействительной операции. Впрочем, сопроцессор реализуют маскированные реакции и на разнообразные ситуации, вызывающие особый случай недействительной операции (подробнее см. в § 2.8). Маска разрешения прерываний. Бит 7 слова управления содержит маску управления прерыванием IEM (Interrupt Enable Mask), которая разрешает (1ЕМ=0) или запрещает (1ЕМ=1) прерывание центрального процессора. Если 1ЕМ = 1, прерывания центрального процессора не будет даже при возникновении индивидуально не замаскированного особого случая. Управление точностью. Двухбитное поле управления точностью PC (Precision Control) определяет точность вычислений в 24 бита (PC=00), 53 бита (РС = 10) или 64 бита (РС=11). По умолчанию вводится наиболее подходящий режим с максимальной точностью в о4 бита. Остальные режимы предусмотрены только для совместимости с некоторыми языками программирования. Задание пониженной точности ликвидирует достоинства временного вещественного формата по достижении максимальной точности, а производительность сопроцессора не увеличивается. Управление округлением. Двухбитное поле управления округлением RC (Rounding Control) определяет один из четырех возможных вариантов округления результатов операций сопроцессора. Интерпретация поля RC показана в табл. 2.2, где принято, что a<b<ct причем числа а и с представимы в формате сопроцессора, а результат операции Ь не представим. Значения а и с наиболее близки к Ь, и округление заключается в замене Ъ на а или с. Округление происходит в арифметических операциях, а также при записи в память, если формат получателя не дает возможности точно представить истинный результат. Оно вносит ошибку (погрешность), значение которой не превышает единицы последнего младшего разряда, сохраняемого в результате. По умолчанию принимается режим округления к ближайшему, обеспечивающий наиболее точную и статистически несмещенную оценку результатов. Округление к ближайшему имеет специальный слу- 78
Таблица 2.2. Режимы округления Поле RC 00 01 10 11 Режим Округление к ближайшему Округление вниз (к .—оо) Округление вверх (к +оо) Отбрасывание (усечение к нулю) Принимаемый результат Принимается то число из а и с, которое ближе к Ь\ при равенстве расстояний берется число с нулевым младшим битом (четное) а с Берется меньшее (по абсолютному значению) из чисел а и Ъ чай, когда полученный результат находится точно посередине между'двумя представимыми числами. Довольно часто в этой ситуации производится округление вверх, что приврдит к появлению ненужного смещения. Чтобы исключить его, в сопроцессоре при 6—а=с—b осуществляется округление к четному из чисел а и с, т. е. к числу, младший бит которого содержит нуль. Следовательно, средние результаты округляются и вверх, а вниз; такой способ округления иногда называется «несмещенным округлением к ближайшему четному*. Для реализации округления в схемах сопроцессора имеются три дополнительных младших бита мантисс. Округления вверх и вниз, называемые также направленным округлением, применяются в интервальной арифметике в целях получения достоверного результата независимо от ошибок округления. Верхняя и нижняя границы интервала значений результата находятся путем реализации алгоритма 2 раза — первый раз с округлением вверх, а второй — с округлением вниз. Режим округления с отбрасыванием применяется в целочисленной арифметике. Управление бесконечностью. Бит 12 управления режимом бесконечности 1С (Infinity Control) определяет одну из двух моделей интерпретации бесконечности: проективную (1С=0) или аффинную (1С=1). По умолча* нию вводится проективный режим, в котором сопроцес- -79
сор обрабатывает два специальных значения «плюс бесконечность» и «минус бесконечность» как одно и то же значение «бесконечность», не имеющее знака (аналогично интерпретации нулей со знаком). В аффинном режиме сопроцессор допускает значения бесконечности со знаком плюс или минус. Аффинный режим обычно дает больше информации, чем проективный, но в некоторых ситуациях знак бесконечности оказывается вредным. Пусть, например, при одной реализации алгоритма промежуточный результат х имеет значение +0, а при другой — значение —0 -(известно, что это одно и то же значение). При последующем вычислении 1/х в аффинном режиме получаются два совершенно разных значения: +оо и —оо, хотя х один и тот же. Проективный режим дает меньше информации, но никогда не приводит к подобной ошибке. Поэтому обычно рекомендуется пользоваться проективным режимом, привлекая аффинный режим для локальных вычислений, в которых знак бесконечности играет важную роль, а сами вычисления не могут дать неверного результата. Слово состояния. В слове состояния младшие 6 бит отведены для регистрации особых случаев, смысл которых рассмотрен выше. Бит 7 запроса прерывания IR (Interrupt Request) устанавливается в состоянии 1 при возникновении любого незамаскированного особого случая, но фактическое генерирование прерывания зависит, от состояния бита IEM в слове управления. Битй СЗ—СО фиксируют код условия в операциях сравнения, проверки и анализа. Три бита ST представляют собой указатель стека. Если, например, это поле содержит 1012| то вершиной стека является, регистр R5. Стековые операции сопровождаются модификацией поля ST. Наконец, флажок занятости В (Busy) устанавливается в состояние 1, когда численное операционное устройство выполняет операцию. Состояние этого бита выведено как сигнал BUSY. При программировании важную роль играют биты кода условия, которые аналогичны арифметическим флажкам центрального процессора и фиксируют особенности результата операции. Коды условия привлекаются для реализации условных переходов. Сопроцессор самостоятельно не может влиять на ход выполнения программы, поэтому для условных переходов по результатам 80
Таблица 2.3. Интерпретация кода условия Команда Сравнение и проверка (FCOM, FCOMP, FTST) Нахождение остатка (FPREM) Анализ (FXAM) СЗ 0 0 1 1 Qi X 0 0 0 0 0 0 0 0 1 С2 X X х X 0 1 0 - 0 0 0 1 1 1 I 0 1 0 | 0 0 1 1 1 1 1 01 X X X X Q0 X 0 0 1 1 0 ! ч. 0 I 1 -! о 0 I 1 0 0 1 1 со 0 1 0 1 Q2 X 0 ] о 1 0 1 0 1 0 1 0 1 0 I 0 1 I Охшспнне (ST)>источника (src) или 0 (ST) < источника (src) или 0 (ST) «источнику {src) или 0 Не сравнимы Полное приведение с получением младших 3 бит частного (команда завершена) Неполное приведение (команда не завершена) Положительное, ненормализованное Положительное, не-чи- сло Отрицательное, ненормализованное Отрицательное, не*чи- сло Положительное, норма* лизованное Положительная бесконечность Отрицательное, нормализованное Отрицательная бесконечность Положительный нуль Пустой регистр Отрицательный нуль Пустой регистр * Положительное, денор- мализовавное Пустой регистр Отрицательное, денор- мализованное Пустой регистр 6-723
операций сопроцессора приходится сначала передавать код условия в память, а затем загружать один из регистров центрального процессора. Обычно им является регистр АХ (точнее, регистр АН). После этого код условия передается в регистр флажков и производится условный переход (подробнее см. в §3.1). Интерпретация поля кода условия приведена в табл. 2.3. 2.6. СИСТЕМА КОМАНД Система команд сопроцессора содержит 69 базовых команд, которые удобно разделить на шесть групп: команды передач данных, арифметические команды, команды сравнения, команды трансцендентных операций, команды загрузки констант и команды управления сопроцессором. Полная система команд сопроцессора дается в приложении. Типичная команда сопроцессора воспринимает один или два операнда, выполняет указанную операцию и формирует результат. Операндами наиболее часто служит содержимое регистров, но может привлекаться и содержимое ячеек памяти. Операнды некоторых команд определяются неявно, например безоперандная команда FSQRT извлекает квадратный корень из числа, находящегося в вершине стека ST(0). Другие команды допуска- ют или требуют явного задания операндов. Например, имеются команды с одним явным и одним неявным операндами, которыми обычно является содержимое вершины стека. При рассмотрении системы команд сопроцессора будем пользоваться обозначениями из гл. 1. Напомним, что src обозначает источник, т. е. операнд, значение которого команда не изменяет, a dst — получатель, т. е. операнд, значенье которого замещается результатом операции. 2.6.1. ОСОБЕННОСТИ ЗАДАНИЯ КОМАНД Команды бинарных операций, например сложения, вычитания и др., допускают несколько различных форм. При пустом поле операнда (нуль-адресная команда) операция выполняется с двумя верхними элементами стека ST и ST(1). После производства операции осуществляется инкремент указателя стека и результат помещается в новую вершину стека, заменяя исходное содержимое ST(1). Другими словами, два операнда заменяются 82
в стеке одним результатом — такое действие считается классической операцией в стековых машинах. Когда в бинарной команде определен один операнд, операция выполняется с привлечением указанного в команде регистра (или ячейки памяти) и содержимого вершины стека. Результат загружается в старую вершину стека, и указатель стека не модифицируется. Если в бинарной команде указаны два операнда, ими является содержимое двух регистров стека, причем одним из них будет ST, а вторым ST(i). Принимая указанный выше смысл источника и получателя, имеем три возможных случая: источником является ST, а получателем ST (i); источником выступает ST(t), а получателем ST; источником служит ST, получателем ST(t), и производится инкремент указателя стека, т. е. извлечение из стека. При программировании удобна такая возможность, как обратная форма команд вычитания и деления. Например, в обычной форме команды деления получатель делится на источник, а в обратной форме источник делится на получатель. В^обоих формах результат помещается в получатель. Наличие обратной формы команд часто позволяет избежать операций обмена содержимого двух регистров стека. Команды в обратной форме выполняются всего на 1—2 такта синхронизации дольше команд в обычной форме, а обмен требует 12 тактов синхронизации. • Как указано выше, многие команды допускают несколько способов задания операндов". Например, команда FADD сложения вещественных чисел разрешает, запись без операндов, только с источником или с источником и получателем. Альтернативные формы операндов условно показываются с помощью наклонной черты (черты деления), причем черта без последующей спецификации означает отсутствие явно задаваемых операндов. Например, команда FADD имеет следующий общий вид: FADD/jsrcfdst, src Такая запись подразумевает три возможных формы команды: без операндов, с одним источником, с получателем и источником. В мнемониках команд сопроцессора приняты следующие соглашения: 6* 83
Рис. 2ЛЗ. Форматы команд сопроцессора первая буква всегда F (Floating) и обозначает плавающую точку (отметим, что ни одна из команд МП К1810ВМ86 не начинается с буквы F, и в программе можно легко идентифицировать команды сопроцессора); вторая буква I (Integer) обозначает операцию с.целыми двоичными числами, буква В (Binary-coded decimal) — операцию с десятичным операндом, а пустая вторая буква определяет операцию с вещественными числами; предпоследняя или последняя буква R (Reversed) указывает обратную операцию; последняя буква Р (Pop) идентифицирует команду, заключительным действием которой является извлечение из стека. 2.6.2. МАШИННЫЕ ФОРМАТЫ КОМАНД Сопроцессор К1810ВМ87 имеет пять форматов команд, представленных на рис. 2.13. Во всех форматах минимальная длина команды составляет 2 байта и все команды начинаются с двоичного набора 11011, который выделяет класс команд сопроцессора (ESC). Отметим, что операнд в памяти разрешается указывать в ассемблерных программах с привлечением любого режима адресации памяти центрального процессора. 84
Команды с форматами, показанными на рис. 2.13, а, б, осуществляют обращение к памяти, поэтому mod (режим) и г/т (регистр/память) имеют тот же смысл, что и в командах центрального процессора. Напомним, что они определяют, как формируется эффективный адрес Г.А памяти. Эти же команды в зависимости от кодировался поля mod могут не иметь ни одного, иметь один или два байта смещения disp% участвующего в образовании L-:.\. Команда с форматом, приведенным на рис. 2.13, а, передает данные в памягь и извлекает их из нее, включая соответствующие передачи в командах управления сопроцессором. Команды с форматом, приведенным на рис. 2.13,6, выйолняют арифметические операции и сравнения. Поле формата памяти MF (Memory Format) определяет тип операнда, находящегося в памяти. Оно имеет следующее кодирование: 00 — короткое вещественное число (32 бита); 01 — короткое целое двоичное число (32 бита); 10 — длинное вещественное число (64 бита); 11 —целое слово (16 бит) или упакованное десятичное число (80 бит). Во всех остальных форматах поле mod содержит комбинацию 11. В командах центрального процессора эта комбинация задает режим регистровой адресации, который не относится к сопроцессору. Именно такие команды центральный процессор проскакивает, не производя никаких действий. Команды с форматом, приведенным на рис. 2.13, в, выполняют арифметические операции и операции сравнения с привлечением регистров сопроцессора. В этом формате поле reg определяет регистр стека ST(t). Бит R (Reverse) показывает, возвращается результат в вершину стека (R=0) или в другой регистр стека (R=l), т. е. он показывает операции обратного вычитания и деления. Бит Р (Pop) идентифицирует, производится ли после операции извлечение, из стека (Р = 1) или нет (Р=0). Формат на рис. 2.13, г относится к командам, оперирующим константами, а также к трансцендентным и дополнительным арифметическим командам. Для этих команд характерно отсутствие явных спецификаций операндов, т. е. операнды определяются неявно кодом операции. Наконец, формат на рис. 2.13, д зарезервирован для команд управления сопроцессором, которые не обраща- 85
ются к памяти. В этом формате, как и в предыдущем, нет явной спецификации операндов. 2.6.3. ОСОБЕННОСТИ ПРОГРАММИРОВАНИЯ НА ЯЗЫКЕ АССЕМБЛЕРА При рассмотрении команд сопроцессора будем приводить примеры записи команд на языке ассемблера. Поэтому целесообразно привести минимальные сведения по этому языку, которые необходимы для понимания фрагментов программ. Для программирования микропроцессорной системы, содержащей сопроцессор К1810ВМ87, следует расширить стандартный ассемблер МП К1810ВМ86 средствами поддержки сопроцессора. Такой ассемблер позволяет программисту пользоваться всеми ресурсами центрального процессора и сопроцессора: совместными системами команд, регистрами и данными всех форматов. Расширенные форматы данных сопроцессора требуют введения в ассемблер специальных директив определения данных. Напомним, что в ассемблере МП К1810ВМ86 имеются следующие директивы резервирования памяти для переменных и констант: DB — определить байт; DW — определить слово; DD—определить двойное слово (32 бита). Резервирование памяти для переменных и констант сопроцессора осуществляют следующие директивы: DW—определить слово (16 бит); DD — определить двойное слово (32 бита); DQ — определить счетверенное слово (64 бита)? DT — определить 10 байт. С каждой переменной, определяемой этими директивами, ассоциируется тип, значение которого равно длине резервируемой памяти в байтах. В процессе ассемблирования производится контроль совместимости типа переменной и формата операнда в команде. Например, в команде загрузки упакованного десятичного числа FBLD GAMMA будет зафиксирована ошибка, если тип переменной GAMMA не равен 10. Кроме того, тип операнда сообщает ассемблеру, какую машинную команду он должен ге- 86
нерировать (напомним о поле MF в командах с обращением к памяти). Иногда программисту необходимо воспользоваться командой, тип операнда которой не объявлен директивой (это так называемые анонимные обращения к памяти). Но поскольку ассемблер все-таки должен знать тип операнда, его можно задать в команде с ломощыо указателя PTR. Например, в команде FLD [ВХ] неясно, что загружается: короткое или длинное вещественное число? В команде с указателем типа FLD QWORD PTR IBX) определена загрузка длинного вещественного числа. Ассемблер не контролирует тип операнда в командах управления сопроцессором, так как в них структура операнда подразумевается смыслом команды. Например, команда восстановления полного состояния сопроцессора FRSTOR [ВР] предполагает, что регистр ВР адресует 94-байтную, область в стеке (адресация с регистром ВР определяет обращение к текущему сегменту стека), в которой ранее было запомнено полное состояние сопроцессора. Обычно ассемблер допускает несколько способов записи констант. Двоичные целые константы можно задавать как двоичные наборы (с заключительным дескриптором В), десятичные целые (с дескриптором D или без дескриптора), 8-ричные целые (с дескриптором О или Q) и 16-ричные числа (с дескриптором Н). Упакованные десятичные числа обычно представляются как десятичные целые, но ассемблер допускает и другие формы. Вещественные числа требуется записывать в формате с (десятичной) точкой, но для специальных значений (бесконечность, не-число и ненормализованное число) целесообразно применять 16-ричную форму. Ниже приведены примеры определения одной и той же константы — 87: EVEN ;Выравнять на ; границу слова W-INT DW ШИП 110101001В Двоичное целое с 87
S-INT L-INT S-REAL L-REAL P-DEC DD DQ DD DQ D.T 0FFFFFFA9H —87 —87.0 —8.7E1 —87 ; Короткое целое Длинное целое •.Короткое вещест- ; венное ;Длинное вещест- ; венное ;Упакованное де- ; сятичное Отметим, что в строке LJREAL фигурирует запись вещественного числа в форме с показателем Е (Exponent) степени десяти. Специальная директива EVEN (четный) заставляет ассемблер назначить константе W-INT четный адрес. Такое выравнивание по границам слов повышает производительность системы, так как слово с четным адресом передается за один цикл шины, а передача слова с нечетным адресом требует двух циклов шины. Поскольку длина- всех форматов данных сопроцессора кратна длине слова, можно указать единственную директиву EVEN перед несколькими константами и переменными. В заключение покажем определение специального значения «минус бесконечность»: Т. REAL DT OFFFF8000000000000000R. Здесь буква R(Real) сообщает ассемблеру о том, что 16-ричное целое представляет собой вещественное число. 2.6.4. КОМАНДЫ ПЕРЕДАЧ ДАННЫХ Команды этой группы производят передачи данных между регистрами стека, а также между вершиной стека и памятью. Одной командой число из памяти, представленное в любом формате сопроцессора, преобразуется во временный вещественный формат и загружается (включается) в стек; аналогичным образом, но в обратном порядке, осуществляется передача числа в память. При выполнении команд автоматически модифицируется тэг регистра, отражая его новое содержимое. Команды загрузки. Три команды загрузки имеют следующий вид: вещественное: FLD src двоичное целое: FILD src десятичное целое; FBLD src ST4-(ST)—1, [ ST(0)^(src) 88
Как видно из общего описания, эти команды осуществляют декремент указателя стека и передачу в новую вершину стека содержимого источника, т. е. производят включение в стек. Для предотвращения переполнения стека перед загрузкой проверяется тэг регистра. Если регистр не отмечен как пустой, генерируется особый случай недействительной операции и загрузка не производится (когда особый случай не замаскирован). В команде FLD источником может быть один из регистров стека или вещественное число с любым форматом в памяти, а в командах FILD и FBLD — только операнд в памяти. При выполнении всех команд [за естественным исключением команд вида FLDST(i) и с операндом в памяти во временном вещественном формате] производится автоматическое преобразование операнда во временный вещественный формат с сохранением специальных значений (нуль, бесконечность и не-число). Команды FILD и FBLD-являются точными, т. е. в них ошибки округления отсутствуют. Команда FBLD не контролирует наличие в операнде запрещенных тетрад, и результат загрузки числа с такими тетрадами непредсказуем. Если проводить аналогию с командами МП К1810ВМ86, эти три команды напоминают команду PUSH src. Приведем песколько примеров ассемблерного кодирования команд загрузки. Примечание. Во всех приводимых здесь и далее примерах при отсутствии явной спецификации типа операнда предполагается, что он определен соответствующей директивой. FLD ST(0) FLD QWORD PTR [BX] FILD WORD PTR ARR [DI] FBLD VOLUME Копирует вершину стека Загружает длинное вещественное Загружает целое слово Загружает целое десятичное Команды запоминания, две команды запоминания вещественное: FST dst \ .. »„ms двоичное це- FIST dst ) ast^'^i\{}> лое: 89
производят передачу содержимого вершины стека в па- мять без модификации указателя стека ST и, разумеется, содержимого ST(0). В команде FST получателем может быть регистр стека или вещественная переменная в памяти (только короткий или длинный формат). Мантисса округляется в соответствии с полем управления округлением RC и длиной мантиссы получателя, а порядок корректируется с учетом длины и смещения порядка получателя. Когда вершина стека отмечена как специальное значение (т. е. содержит бесконечность, не-число или денор- мализованное число), мантисса не округляется, а усе-, кается справа; порядок также усекается справа. Такие действия сохраняют вид специального значения, поэтому в дальнейшем оно может быть правильно загружено и отмечено. В команде FIST получателем является переменная в памяти, имеющая формат короткого целого или целого слова. Команда округляет содержимое вершины стека до целого в соответствии с полем RC и передает результат в получатель. При наличии в ST(0) отрицательного нуля он будет запомнен как положительный нуль в виде 00...0. Примеры ассемблерных команд запоминания: Передает ST(0) в регистр стека Передает вещественное в память Передает целое слово в память FST ST(5) FST [BP] [SI] FIST WORD PTR MEAN Рассмотренные команды не допускают получатель в форматах длинного целого, временного вещественного и упакованного десятичного. Объясняется такая асимметричность недостатком двоичных наборов для кодов операций. Команды запоминания с извлечением из стека. Три команды помимо передачи содержимого ST(0) в получатель осуществляют извлечение из стека: регистр, бывший вершиной стека, отмечается как пустой и производится инкремент указателя стека: вещественное: FSTP dst двоичное целое: FISTP dst десятичное целое: FBSTP dst <te^-ST(0), ST4-(ST).+1 90
Чтобы предотвратить антипереполнение (опустошение) стека, перед запоминанием проверяется тэг регистра, являющегося вершиной стека. Если тэг показывает неинициализированное значение (пустой регистр), генерируется особый случай недействительной операции. Действия команды FSTP очень похожи на действия команды FST с добавлением, конечно, извлечения из стека. Однако она позволяет передать в память число в любом вещественном формате, в том числе и во временном вещественном формате, чего не может делать команда FST. Команда FISTP, похожая на команду FIST, обеспечивает передачу в память числа в любом формате целого двоичного, включая и длинное целое. Последний формат недопустим в команде FIST. Наконец, команда FBSTP преобразует операнд из вершины стека в упакованное десятичное число, передает его в память и производит извлечение из стека. Округление реализуется путем прибавления к исходному числу 0.5 и последующего отбрасывания разрядов дробной части. Если для программиста важен способ округления, перед командой FBSTP следует поместить команду FRNDINT округления до целого (см. далее). Примеры записи рассмотренных команд на языке ассемблера: FSTP ST(0) Извлечение из стека без ; передачи FISTP DWORD PTR [BX] ;Передает короткое целое в ; память FISTP QWORD PTR [SI] ;Передает длинное целое в ; память FBSTP PAYROLL . . ;Передает десятичное целое ; в память В командах запоминания обоих видов при преобразовании формата числа может возникнуть несколько особых случаев. Если в процессе округления число изменяется, генерируется особый случай точности. Когда округленное число слишком велико для формата получателя, фиксируется особый случай переполнения. Наконец, при преобразовании в короткий или длинный вещественный формат возникает особый случай антипереполнения, ког» да округленное число не является нулем, но меньше порога антипереполнения соответствующего формата. 91
Команда обмена. Команда обмена содержимого регистров FXCHI/dsi ST(0)~(dsO обменивает содержимое получателя ST(£) и вершины стека ST(0). При пустом поле операнда обменивается содержимое регистров ST(1) и ST(0). Наличие команды FXCH объясняется тем, что многие команды сопроцессора оперируют содержимым вершины стека, а с помощью команды FXCH их действия можно распространить на все регистры стека. Например, следующие три команды формируют в ST{5) значение квадратного корня из находящегося в нем числа: FXCH ST(5) ;Содержимое ST (5) в вершине ; стека FSQRT ;Извлечь квадратный корень ; H3ST(0) FXCH ST (5) ;Возвратить на прежнее место Отметим, что команда FXCHST(O) эквивалентна холостой команде. 2.6.5. АРИФМЕТИЧЕСКИЕ КОМАНДЫ Набор арифметических команд сопроцессора включает в себя разнообразные варианты основных арифметических операций, а также удобные и мощные команды извлечения квадратного корня, масштабирования, выделения частей вещественного числа и др. Основные арифметические команды ориентированы на разработку эффективных алгоритмов, что позволяет программисту минимизировать число обращений к памяти и оптимально использовать регистровый стек. В табл. 2.4 приведены допустимые комбинации операций и операндов для основных арифметических операций. В дополнение к четырем обычным операциям- команды двух обратных операций делают вычитание и деление симметричными, аналогичными сложению и умножению. Приведение в табл. 2.4 пять основных форм команд могут быть использованы для всех основных операций. Стековая форма превращает сопроцессор в классическую стековую машину. В этой форме поле операнда является пустым: в качестве источника подразумевается вершина стека ST(0), а в качестве получателя — следующий регистр стека ST(1). Выполнив операцию, сопро- ■92
Таблица 2.4. Формы основных арифметических команд Форме команды Стековая Регистровая Регистровая с извлечением из стека Вещественные операнды (с памятью) Целые операнды (с па» мятью) Мнемоника Fop . Fop FopP Fop Flop • Операнд(ы) (ST(I), ST} ST(h, ST или 1 ST, ST(i) ST(i), ST {ST,} короткое/длинное вещественное {S.T,} целое слово/ короткое целое Пример записи FSUB FADD ST, ST(2) FMULP, ST(3),ST FADD BETA FIDIV GAMMA Примечания: l. Фигурные скобки обозначают неявные операнды, которые в ассемблерных командах могут не указываться. 2. Обозначения: op = ADD { dst, src } • dst <- {dst) -f (src) SUB { dst, src ) <fc< *- (rfs/) — (src) SUBR { dst, src ) dst*- (src) — (dst) MUL { dstt src ) ^ 4&t- (dst) X (src) DIV { dstt src ) dst - (dsi)J(src) DIVR { ds/, src ) dst -*- (src)/(dst) цессор производит инкремент указателя стека и загружает результат в новую вершину стека. Регистровая форма представляет собой обобщение стековой формы: одним из операндов является содержимое вершины стека, другим — произвольный регистр стека, а результат можно загрузить на место любого из операндов. Указание получателем вершины стека обеспечивает удобный доступ к константам из других регистров. Когда вершина стека служит источником, регистр-получатель превращается в аккумулятор. Часто операнд, находящийся в вершине стека ST(0), необходим только для одной операции, а в дальнейшем не требуется. Регистровая форма с извлечением из стека обеспечивает выбор вершины стека в качестве источника и последующее уничтожение этого операнда путем инкремента указателя стека. Указание операндов в виде ST(1), ST(0) с мнемоникой извлечения из стека эквивалентно классической стековой операции: содержимое вершины стека удаляется, а результат помещается-* новую вершину стека. 93
Две формы команд с обращением к памяти позволяют использовать в качестве источника вещественное или целое число, находящееся в памяти. Это удобно в тех ситуациях, когда операнды привлекаются редко и их хранение в регистрах нецелесообразно. Для указания таких операндов применяются все режимы адресации памяти центрального процессора. Необходимо отметить, что вещественные числа в памяти не могут быть в формате временного вещественного, а целые числа — в формате длинного Целого. Здесь вновь сказывается недостаточность наборов кодов операций. Команды сложения. Операция сложения реализуется командами со следующими формами: вещественные числа FADD f/srcfdst, src вещественные числа с из- FADDP dst, src влечением из стека целые числа FIADD src Отметим, что команда FADD ST, ST(0) удваивает содержимое вершины стека. Команды вычитания. Обычное вычитание dst*^(dst) — [src) осуществляют команды: вещественные числа FSUB//src/dst, src вещественные числа с из- FSUBP dst, src влечением из стека целые числа FISUB src Для производства обратного вычитания dsi<-(src)— (dst) предназначены команды FSUBR, FSUBRP и FISUBR, имеющие аналогичные формы. Команды умножения. Операция умножения реализуется следующими командами: вещественные числа FMXJL/Jsrc/dst, src вещественные числа с FMULP dst src извлечением из стека целые числа FIMUL src Команды% деления. Для выполнения обычной операции деления предусмотрены команды: вещественные числа FDIV jjsrcfdst, src вещественные числа с FDIVP dst, src извлечением из стека целые числа FIDIV src 94
Соответствующие команды обратного деления FDIVR, FDIVRP и FIDIVR загружают в получатель частное от деления источника на получатель. Приведем несколько примеров арифметических команд: FADD ST, ST(5) FIADD WORD PTR COUNT [SI] FSUBP ST(2), ST FMUL QWORD PTR [BP] TEMP FDIVR DWORD PTR [SI] FIDIVR DWORD PTR [BX+5] ;Сложить содержимое pe- ; гистров ;Прибавить целое слово Вычесть содержимое регистров Умножить на длинное вещественное Разделить короткое вещественное Разделить короткое целое - При программировании вычислительных алгоритмов следует иметь в виду следующее обстоятельство. Хотя сопроцессор имеет полный набор команд целочисленной двоичной арифметики, применять их в массовом порядке не рекомендуется, так как быстродействие сопроцессора в такой арифметике значительно ниже быстродействия центрального процессора. Например, МП К1810ВМ86 выполняет 16-битное сложение вида память- регистр примерно за 20 тактов синхронизации (если команда уже находится в очереди команд), а аналогичная команда сопроцессора занимает 120 тактов синхронизации. Объясняется такая несколько парадоксальная ситуация тем, что в сопроцессоре для обработки целых чисел используется временный вещественный формат, что требует соответствующего преобразования операнда (и обратного преобразования при передаче результата в память). Преимущество сопроцессора при обработке таких «малых для него чисел проявляется в специальных вычислениях с привлечением вещественных и целых чисел. Благодаря тому что сопроцессор представляет любые числа в одном и том же внутреннем формате, в вычислениях могут фигурировать числа различных форматов. В заключение сделаем замечание о явном и неявном указании регистровых операндов. В стековой форме ST(0) всегда подразумевается источником, a ST(1) — 95
получателем, и они в командах явно не фигурируют. Отсутствующие операнды могут вызвать некоторую путаницу у неопытного программиста. Дело в том, что команда с двумя неявными операндами имеет другой смысл, чем та же самая команда с -явными операндами. По соглашению два неявных операнда сообщают ассемблеру о том, что следует произвести извлечение из стека после выполнения операции. Например, команда FADD подразумевает источником ST(0) и получателем ST(l). Ассемблер транслирует эту команду как FADDP ST(1), ST, которая отличается от команды FADD ST(1), ST. Поэтому' целесообразно, хотя бы на первых порах, явно указывать в командах оба операнда. Отметим также, что во всех арифметических операциях может возникать множество особых случаев. Уникальна в этом отношении операция деления, в которой могут возникнуть все шесть особых случаев, фиксируемых сопроцессором. Дополнительные команды. К арифметическим командам относятся также семь дополнительных команд, имеющих безоперандную форму. Команда FSQRT извлечения квадратного корня заменяет число, находящееся в вершине стека, значением квадратного корня: FSQRT STfO^KSTCO) В этой команде по определению полагается, что 1/*—0=—0. Относительно команды FSQRT отметим следующее. Во-первых, она выполняется несколько быстрее команд деления, так как здесь не нужно контролировать переполнение и антипереполнение. Во-вторых, точность ее соответствует точности обычных арифметических операций, (погрешность результата равна ъ младшего бита мантиссы). Наконец, в команде FSQRT доступны режимы округления. По существу, программисты могут считать извлечение корня обычной арифметической операцией, вместо того чтобы интуитивно избегать ее. Команда FSCALE масштабирования интерпретирует содержимое регистра ST(1) как целое двоичное число и прибавляет его к смещенному порядку числа, находящегося в вершине стека: FSCALE ST(0) +- ST(0) X 2ST(1) Таким образрм, команда FSCALE осуществляет 96
быстрое умножение [когда ST(1)>0J или деление [когда ST(1)<0] содержимого вершины стека на целую степень 2. В этой команде предполагается, что масштабный коэффициент в ST(1) является целым числом из диапазона —2,5<ST(1) <21Б. Если он не является целым числом, но находится в указанном диапазоне и больше по абсолютному значению lf в команде принимается ближайшее целое, меньшее по абсолютному значению исходного масштабного коэффициента. Другими словами, команда FSCALE производит усечение к нулю. Когда число в ST(I) находится вне допустимого диапазона или является правильной дробью, команда формирует непредсказуемый результат и не сигнализирует об особом случае. Поэтому во избежание возможных ошибок рекомендуется всегда позаботиться о задании масштабного коэффициента в виде целого слова. Нахождение масштабного коэффициента не в вершине стека ST(0), а в регистре ST(1) обеспечивает удобное масштабирование последовательности чисел, например элементов массива. На каждый элемент массива требуются три операции (загрузка, масштабирование и запоминание) без дополнительных действий. Команда FPREM вычисляет частичный остаток (смысл этого термина будет понятен из описания команды) от деления числа, находящегося в вершине стека ST(0), на следующий элемент стека ST(l) и загружает результате ST(0): FPREM ST(0) ч- ST (0) — (q X ST (1)) где q — целое число. Другими словами, здесь содержимое ST(1) выступает модулем в операции деления. Знак остатка имеет знак исходного делимого, т. е. содержимого ST(0). Команда FPREM предназначена в основном для приведения аргумента (операнда) периодических трансцендентных функций в диапазон, допустимый в соответствующих командах сопроцессора. Например, команда FPTAN вычисления (частичного) тангенса требует, чтобы аргумент находился в диапазоне от 0 до я/4. Для повышения точности вычисления функций необходимо, чтобы команда FPREM давала точный результат (без регистрации особого случая точности). Этого можно достичь только путем последовательных масштабированных 7-723 97.
вычитаний модуля из делимого до достижения момента, когда вычитание без получения отрицательной разности невозможно, т. е. когда очередная разность меньше модуля. Такой способ требует значительного времени в тех ситуациях, когда исходное делимое намного больше «модуля и имеется соответствующая задержка центрального процессора. Чтобы предотвратить «зависание» центрального процессора в продолжительной операции без реакции на запросы прерываний, команда FPREM рассчитана на повторяющееся (итеративное) выполнение в программном цикле. Она производит максимум 64 вычитания и возвращает полученный при этом результат, даже если необходимы дальнейшие вычитания. Когда в результате выполнения команда FPREM дает остаток, меньший модуля, ее функция считается законченной и бит С2 кода условия в слове состояния сопроцессора будет содержать нуль. Если приведение не закончено, бит С2 содержит 1 и результат в вершине стека ST(0) называется частичным остатком. Программа должна проверить состояние С2 после выполнения команды FPREM и при необходимости инициировать ее повторное выполнение с использованием в качестве делимого частичного остатки из ST(0). Потребуется цикл примерно такого вида: LOOP; FPREM if С2= 1 goto LOOP Проверка состояния бита С2 осуществляется с привлечением центрального процессора: слово состояния передается через память в регистр АХ, затем команда SAHF пересылает код условия в регистр флажков и состояние бита С2 показывает флажок PF. Другой способ определения завершения команды заключается в сравнении ST(0) и ST(I): остаток получен, если ST(0)<ST(1). Кроме остатка в ST(0) команда FPREM образует в битах СЗ, С1, СО слова состояния, младших 3 бита частного. Фактически по своим весам эти биты упорядочены как СО, СЗ, С1. Наличие 3 бит частного позволяет определить нахождение исходного. угла в одном из октантов. Следует иметь в виду, что точные младшие биты частного получаются при производстве в команде FPREM не более 62 вычитаний [7]. Команда FRNDINT осуществляет округление числа, 98
находящегося в вершине стека ST(0), до целого. Режим округления показывает поле RC в слове управления сопроцессора. Например, число 8087.875 в вершине стека будет заменено числом 8087 (округление вниз или отбрасывание) или числом 8088 (округление вверх или к ближайшему) . Команда FXTRACT выделения компонентов числа с плавающей точкой преобразует число, находящееся в вершине^стека ST(0), в два числа, представляющих собой фактические значения его порядка и мантиссы. Выделенный порядок заменяет исходный операнд в вершине стека, а мантисса включается в стек (с декрементом указателя стека). После выполнения команды в ST(0) находится вещественное число, знак и мантисса которого равны знаку и мантиссе исходного операнда, а истинный порядок равен нулю (смещенный порядок равен 16 383). В регистре ST(1) находится истинный порядок исходного операнда, также выраженный в формате вещественного числа. Когда операнд равен нулю, команда FXTRACT образует нули в ST(0) и ST(l) со знаком исходного числа. Покажем пример выполнения команды FXTRACT: Операнд 0 1000000Q0000010 1ЛП0100...00 ST(0) 0 011Ш11Ш1111 1Л1ЮЮ0...00 ST(1) 0 100000000000001 1Л100000...00 Команда FXTRACT обычно применяется вместе с командой FBSTP для преобразования чисел из временного вещественного формата в десятичный формат с плавающей точкой при выводе чисел на дисплей или принтер. Она также удобна для отладки программ, так как дает возможность отдельно проанализировать порядок и мантиссу вещественного числа. Отметим, что с помощью команды FSCALE разложенное число можно превратить в исходное. Две последние команды выполняют элементарные операции нахождения абсолютного значения и изменения знака числа, которое содержится в вершине стека: FABS БТ(0)ч- |ST(0)| FCHS ST(0)« ST(0) 7* 99
2.6.6. КОМАНДЫ СРАВНЕНИЯ Команды данной группы предназначены для анализа числа в вершине стека (иногда по отношению к другому числу) и формированию кода условия в слове состояния сопроцессора. К основным операциям относятся сравнение, проверка (или сравнение с нулем) и анализ (получение подробной информации о числе). Имеются специальные формы команд, допускающие сравнение с целым и вещественными числами, находящимися в памяти, и извлечения из стека после сравнения. Проверить образованный код условия может только центральный процессор. Команда сравнения вещественных чисел имеет форму FCOM//src и осуществляет сравнение содержимого вершины стека ST(0) и источника src. Источником может быть регистр стека или вещественное число в памяти (в формате короткого или длинного вещественного). Если поле операнда пустое, производится сравнение ST(0) и ST(l)! Код условия отражает отношение-между числами-операндами в соответствии с табл. 2.3. Операнды считаются несравнимыми (СЗ, СО=11), когда хотя бы один из них имеет специальное значение (проективная бесконечность или не-число). Команда FCOMPffsrc сравнения и извлечения из стека действует аналогично команде FCOM, но дополнительно осуществляет извлечение из стека. Команда FCOMPP сравнения ST(0) и ST(l) и двойного извлечения из стека похожа на команду FCOMP ST(1), но дополнительно она производит еще одно извлечение из стека, так что оба операнда оказываются уничтоженными (в слове тэгов соответствующие регистры отмечены как пустые). При выполнении команды FICOM src содержимое источника, интерпретируемое как целое слово или короткое целое, преобразуется во временный вещественный ^формат и сравнивается с ST(0). Команда FICOMP src '"производит такие же действия и дополнительно извлечение из стека. Разумеется, в обеих командах в качестве источника -может выступать только память. Команда FTST производит проверку числа, находящегося в вершине стека, путем сравнения его с нулем. Результат проверки фиксируется в коде условия в соответствии с табл. 2.3, но с заменой источника (src) -в команде сравнения на нуль. 100 -
Последняя в этой группе команда FXAM анализа содержимого вершины стека формирует в битах СЗ—СО кода условия подробное сообщение об особенностях операнда (см. табл. 2.3). Примеры команд сравнения: FCOM QWORD PTR сравнение длинных ве- LENGTH ; щественных чисел FCOMP ' DWORD PTR Сравнение коротких ве- [ВР+4] ; щественных чисел FCOMPP Сравниваются ST(0) и ; ST(i) FICOM WORD PTR ^Сравнение с целым ело- COUNT [SI] ; вом FICOMP DWORD PTR сравнение с коротким HEIGHT ; целым FTST Сравнение ST(0) с ну- ; лем FXAM ;АнализБТ(0) 2.6.7. КОМАНДЫ ТРАНСЦЕНДЕНТНЫХ ФУНКЦИЙ Команды настоящей группы выполняют базовые вычисления, относящиеся к тригонометрическим, обратным тригонометрическим, логарифмическим и показательным функциям. При программной реализации этих функций производительность центрального процессора оказывается очень низкой (напомним о временном вещественном формате, с которым работает сопроцессор). Например, сопроцессор вычисляет значение показательной функции за 100 мке, а программная реализация этой же функции на МП К1810ВМ86 занимает 17 100 мке (при частоте синхронизации 5 МГц) [7, 9]. Операнды команд находятся в одном или двух верхних регистрах стека, и результат также возвращается в стеке. Предполагается, что операнды являются нормализованными числами и находятся в допустимом для каждой из команд диапазоне. Ответственность за удовлетворение этих требований возлагается на программиста. При нарушении их результат операции непредсказуем; более того, сопроцессор не оповещает об этом никаким особым случаем. Причина ограниченного диапазона операндов заключается в экономии емкости внутренней микропрограммной памяти сопроцессора. 101
Команда FPTAN вычисления частичного тангенса ^как результат формирует числа X и Y, отношение которых дает тангенс угла а в виде tga=Y/X. Значение угла a в радианах должно находиться в вершине стека ST(0) и быть в диапазоне 0 до л/4 (0<а<я/4). После выполнения команды FPTAN значение Y замещает аргумент, а значение X включается в стек и находится, следовательно, в новой вершине стека. Допустимый диапазон угла в команде FPTAN исключает 0, поэтому tgO (или денормализованного числа) должен фиксироваться программой и вычисляться как специальный случай. Особых сложностей это не вызывает, так как для малых а справедливо приближенное равенство tga«a. Несколько необычное представление результата команды FPTAN (термин «частичный» показывает необходимость дополнительной команды для получения истинного тангенса) предназначено для удобного вычисления остальных тригонометрических функций, которые получаются из значений' X и Y на основе тригонометрических тождеств. Команда FPATAN вычисления частичного арктангенса формирует результат a=arctg (Y/X), причём значение X берется из вершины стека ST(0), а значение Y — из регистра ST(1). Значения исходных операндов должны удовлетворять требованию 0<Y<X<oo, которое совместимо с результатами команды FPTAN. При выполнении команды происходит извлечение из стека значений X и Y, а затем результат (значение а в радианах) помещается в новую вершину стека, замещая собой Y. Тригонометрические команды FPTAN и FPATAN оказываются очень точными (погрешность результата составляет несколько единиц младшего разряда) и выполняются довольно быстро — всего в 3—4 раза медленнее деления. Эти команды, а также команда FSQRT образуют основу для вычисления всех остальных тригонометрических и обратных тригонометрических функций. Если, например, обозначить через г значение в ST(0) до выполнения команды FPTAN, а через X и Y значения в ST(0) и ST(1) после деления z на 2 и последующего выполнения команды FPTAN, то smz= 2(™ , ; cos2= *-(Y/*)2 tg(z/2)=Y/X; ctg(*/2)-X/Y; secz==-l±^g; 102
Здесь тригонометрические функции выражены через tg (z/2), а не tgz, так как при этом уменьшается погрешность округления. Если обозначить через z аргумент обратной тригонометрической функции f, через X и Y значения в ST(0) и ST(1) до выполнения команды FPATAN, то получение в ST(0) значений f[z) осуществляется по следующим формулам: Отметим различие в вычислениях тригонометрических и обратных тригонометрических функций. Первые находятся при первоначальном выполнении команды FPTAN с последующими операциями над двумя числами X и Y, полученными этой командой. Во вторых сначала производятся операции над аргументом, а затем выполняется команда FPATAN над двумя результатами этих операций. Например, для вычисления arcsinz необходимы следующие действия: вычислить Х= У (1—z) (1+г) и Y=z; включить Y и X в стек; выполнить команду FPATAN. Команда с несколько необычной мнемоникой F2XM1 вычисляет значение функции Y=2A—1. В мнемонике как раз и завуалирована функция команды — два в степени X минус 1. Значение X берется из вершины стека ST(0) и должно находиться в диапазоне 0<Х<0.5. Результат операции замещает значение X в вершине стека. На первый взгляд более естественной кажется команда, коуорая вычисляет 2 х вместо 2х—1. Однако команда F2XM1 позволяет получить очень точный результат, когда аргумент X близок к нулю. Например, значение 2Q.00OO01 приблизительно равно 1.000000693. Нетрудно 103
убедиться в том, что вычитание единицы сохраняет в результате больше значащих цифр. Можно осуществить возведение в степень X любых чисел, пользуясь формулами 10х == 2х l06t i0- ex = 2х Io& e- Yx = 2х [CRs Y. Необходимые для таких вычислений константы Iog2l0 и log2£ встроены в сопроцессор, а рассматриваемая ниже команда вычисляет двоичный логарифм любого числа. Команда FYL2X предназначена для вычисления значения функции Z=Ylog2X. Аргумент X находится в вершине стека ST(0), а аргумент Y — в регистре ST(l). Диапазоны аргументов составляют 0<Х<оо, —oo<Y< .<оо. Команда производит извлечение из стека аргументов и загружает Z в новую вершину стека, заменяя Y. С помощью этой команды удобно вычисляются логарифмы чисел по любому основанию с применением тождества lognX=logn2Xlog2X. Последняя из трансцендентных команд FYL2XP1 вычисляет значение функции Z=YIog2 (X+l). Аргумент X берется из вершины стека ST(0) и должен находиться в диапазоне 0<|Х|<1 — У^2/2, а аргумент Y — из регистра ST(1) и должен быть в диапазоне —oo<Y<oo. Команда производит извлечение аргументов из стека и загружает Z в новую вершину стека, т. е. на место аргумента Y. Команда FYL2XP1 обеспечивает большую точность по сравнению с предыдущей командой при вычислении логарифмов чисел, близких к 1. Задание как аргумента функции числа е(е<1) вместо {1+е) позволяет сохранить в аргументе больше значащих цифр. 2.6.8. КОМАНДЫ ЗАГРУЗКИ КОНСТАНТ Простые команды загрузки наиболее часто встречающихся в вычислениях констант приведены в табл. 2.5. Загрузка осуществляется путем' включения константы в стек, т. е. декремента указателя стека и передачи в новую вершину стека значения константы, представленного во временном вещественном формате." Так как в этом формате каждая из констант занимает 10 байт памяти, двухбайтные команды загрузки констант обеспечивают экономию памяти, повышение производительности и, кроме того, упрощают программирование. 104
Таблица 2.5, Команды загрузки констант Мнемоника FLDZ FLD1 FLDPI FLDL2T FLDL2E FLDLG2 FLDLN2 Операция Загрузить +0.0 Загрузить 4-1.0 Загрузить я Загрузить log210 Загрузить log2e Загрузить logI02 Загрузить Iog«2 2.6.9. КОМАНДЫ УПРАВЛЕНИЯ Команды данной группы, показанные в табл. 2.6, ориентированы в основном на операции системного уровня. К ним относятся операции инициализации, обработки особых случаев и переключения задач. Для прикладных программистов наибольший интерес представляют команды, оперирующие словами управления и состояния. С помощью этих команд можно задать режим работы сопроцессора (например, режим округления или режим управления бесконечностью), а также проанализировать результаты команд сравнения и'проверки. Как видно из табл. 2.6, для многих команд имеются альтернативные мнемоники, второй буквой которых является N. Мнемоники такого типа сообщают ассемблеру о том, что перед этими командами не нужно вводить команду WAIT (ожидания) центрального процессора. Команды с этой формой игнорируют незамаскированные особые случаи, а команды «с ожиданием» контролируют их наличие. Форма команд «без ожидания» применяется в критических программных сегментах, когда задание команды WAIT и контроль особого случая могут привести к возникновению бесконечного ожидания. Следовательно, если прерывания центрального процессора запрещены (1ЕМ=1), а сопроцессор может сформировать запрос прерывания, следует пользоваться формой «без ожидания». Если прерывания центрального процессора разрешены, что обычно имеет место при выполнении прикладных программ, следует применять команды в форме «с ожиданием». Команда FINIT инициализации сопроцессора функционально эквивалентна сигналу сброса CLR, но она не ГО5
Таблица 2.6. Команды управления. Мнемоник» FINIT/FN1NIT FDISI/FNDISI FENI/FNENI FLDCW FSTCW/FNSTCW FSTSW/FNSTSW FCLEX/FNCLEX FLDENV/FNLDENV FSTENV/FNSTENV FSAVE/FNSAVE FRSTOR FINCSTP FDECSTP FFREE FNOP» FWAIT Операция Иницнализпровать сопроцессор Запретить прерывания Разрешить прерывания Загрузить слово управления Запомнить слово управления Запомнить слово состояния Сбросить флажки особых случаев Загрузить среду Запомнить среду Сохранить полное состояние Восстановить полное состояние Инкремент указателя стека Декремент указателя стека Освободить регистр Холостая команда Ожидать влияет на синхронизацию выборки команд центрального процессора и сопроцессоре. Команда инициализации в форме «без ожидания» заставляет прекратить любую операцию, выполняемую численным операционным устройством. Если команда инициализации приходится на то время, когда сопроцессор производит обращение к па- <мяти, текущий цикл шины прекращается. Состояние сопроцессора после команды инициализации приведено в табл. 2.7. С помощью команд FDISI и FENI программист управляет запрещением (маскированием) и разрешением прерываний от сопроцессора. Обе команды соответствующим образом воздействуют на бит IEM маски разрешения прерываний в слове управления. Основное назйачение команды FLDCW sre заключается в том, чтобы загрузить в регистр управления сопроцессора новое содержимое из источника (им должно быть целое слово в памяти) в целях установки или изменения режима работы, например режима управления округлением. Отметим, что, если в слове состояния установлен любой флажок особого случая, загрузка нового слова управления, которое разрешает прерывание от этого особого случая и задает 1ЕМ=0, приводит к генерированию запроса прерывания перед выполнением следу- 106
Таблица 2.7. Состояние сопроцессора после команды инициализации Поле Слово управления: управление бесконечностью управление точностью управление округлением маска разрешения прерываний маски особых случаев Слово состояния: занятость , код условия указатель стека j запрос прерывания флажки особых случа- ! ёв | Слово тэгов: тэги регистры указатели особого случая Состояние 0 и 00 1 111111 0 хххх 000 0 000000 И Интерпретация Проективная 64 бита Округление к ближайшегому Прерывания запрещены Замаскированы Не занят Ие определен Начало стека Отсутствует » Пустые регистры Не изменяются Тоже ющей команды. Поэтому перед загрузкой нового слова управления рекомендуется сбрасывать флажки особых случаев в слове состояния. Команды F.STCW dst и FSTSW dst осуществляют запоминание текущих слов управления и состояния соответственно в ячейке памяти, определяемой получателем dst. Программист довольно часто пользуется командой FSTSW для реализации условных переходов по результатам команд сопроцессора, определения занятости сопроцессора, а также вызова процедур обработки особых случаев в таких системах, где не применяются прерывания. После этой команды следует указать команду ожидания FWAIT (см. далее), чтобы состояние сопроцессора, в частности код условия, было передано в память до продолжения программы. Получатель dst должен иметь формат целого слова. Функция команды FCLEX сброса особых случаев заключается в том, чтобы сбросить в нуль флажки особых случаев, флажок запроса прерывания и флажок занятости в слове состояния, при этом на выходных линиях 1NT 107
и BUSY формируется низкий уровень. Данную команду процедура обработки особых случаев должна выполнить перед возвратом в прерванную программу, в противном случае сразу же будет сформирован новый запрос прерывания, в результате чего может возникнуть бесконечный цикл. Команда FSAVE dst предназначена для сохранения полного состояния сопроцессора (94 байта), включающего в себя содержимое всех регистров программной модели сопроцессора, в области памяти, идентифицируемой получателем dst (см. формат полного состояния сопроцессора в памяти на рис. 2.9). Обычно местом сохранения полного состояния сопроцессора является область стека центрального процессора. После выполнения этой команды сопроцессор переводится в начальное состояние, как после команды FINIT. Команда FSAVE удобна в тех случаях, когда программисту необходимо сохранить текущее состояние сопроцессора и «переключить» его на новую программу. Такие ситуации возникают, когда сопроцессор нужен процедуре обработки особого случая или когда программист хочет передать подпрограмме «чистый» сопроцессор. Восстановление полного состояния реализуется командой FRSTOR src. Необходимо, чтобы информация о состоянии была ранее запомнена командой FSAVE и не модифицировалась другими командами. Сопроцессор реагирует на свое новое состояние сразу же по завершении команды FRSTOR. Например, он сформирует запрос прерывания, если флажки особых случаев и маски прерываний в загруженных словах состояния и управления требуют прерывания. Для сохранения и восстановления состояния сопроцессора обычно применяется следующий ассемблерный фрагмент: SUB SP, 94 Зарезервировать пространст- ; во в стеке MOV BP, SP ;ВР является базой для со- ; стояния FSAVE [BP] ;Сохранить полное состояние MOV BP, SP ;ВР является базой для состоя : ния 108
PRSTOR [BP] восстановить состояние ADD SP, 94 ;Освободить пространство в ; стеке Напомним, что при адресации через регистр ВР неявные обращения осуществляются к текущему сегменту стека. Сохранение в памяти наиболее важной информации о состоянии сопроцессора, называемой его средой, реализует команда FSTENV dst. При ее выполнении в адресуемую dst область памяти передаются 14 байт — слова управления, состояния, тэгов и указателей особого случая. Обычно информация о среде запоминается в стеке центрального процессора (см. рис. 2.8 о размещении среды в памяти). Команда FSTENV применяется в процедуре обработки особого случая, так как она обеспечивает доступ к указателям особого случая, которые идентифицируют адреса команды и операнда (если он был в памяти), вызвавших особый случай. Команда FSTENV выполняется примерно в 4 раза быстрее команды FSAVE. До выборки из очереди следующей команды сопроцессора выполнение команды FSTENV должно закончиться, поэтому после нее перед следующей командой сопроцессора необходима команда FWAIT. Парная предыдущей команде команда FLDENV src осуществляет загрузку среды сопроцессора из области памяти, определяемой src. После команды FLDENV не требуется команда FWAIT, так как сопроцессор автоматически контролирует завершение передачи всех слов среды до перехода к своей следующей команде. Если маска разрешения прерывания 1ЕМ=0, то загрузка среды с незамаскированным особым случаем вызовет немедленный запрос прерывания. Команды FINCSTP и FDECSTP производят только инкремент и декремент указателя стека. Отметим две важные особенности этих команд. Во-первых, регистр предыдущей вершины стека при выполнении команды FINCSTP не отмечается как пустой и действие этой команды не эквивалентно извлечению из стека. Во-вторых, команда FDECSTP вообще не изменяет содержимого ни одного регистра или тэга. Напомним также о круговой организации стека: инкремент указателя стека 1112 дает 000, а при декременте 000 получается 1112. Команда FFREE dst записывает в тэг указанного регистра комбинацию 11, т. е. отмечает регистр как пустой, но содержимое регистра не изменяется. 109
Команда FWAIT ожидания является альтернативной мнемоникой команды WAIT центрального процессора и введена только для большей ясности программ. Она применяется в тех ситуациях, когда необходимо синхронизировать действия центрального процессора и сопроцессора, т. е. приостановить в них выборку команд из очереди до завершения сопроцессором текущей команды. Центральный процессор не должен производить обращение к операнду в памяти, который считывается и^и записывается сопроцессором. Примером служит такая последовательность команд: FSTSW STATUS ;Запомнить слово состоя- ; ния FWAIT ;Ожидать завершения MOV AX, STATUS ;Передать слово состоя- ; ния в АХ Холостая команда FNOP, как обычно, не производит никаких действий и не модифицирует содержимое регистров сопроцессора. 2.7. ВЗАИМОДЕЙСТВИЕ СОПРОЦЕССОРА И ЦЕНТРАЛЬНОГО ПРОЦЕССОРА Сопроцессор представляет собой аппаратное расширение центрального процессора и не может работать автономно. Схема их совместных подключений приведена на рис. 2.14. Центральный процессор «выполнит* команду ESC, т. е. закодированные команды сопроцессора, гораздо I L Рис. 2.14. Взаимодействие центрального процессора и сопроцессора 110
быстрее, чем сопроцессор закончит фактические действия этой команды. Например, команду FSQRT центральный процессор «выполняет» всего за 2 такта синхронизации, а сопроцессору требуются 180 тактов. Завершив команду ESC, центральный процессор дешифрует и выполняет следующие свои команды, а устройство управления сопроцессора повторяет его действия по выборке команд из очереди, но игнорирует команды центрального процессора. Следовательно, часть времени оба процессора работают параллельно, что повышает производительность системы. Однако в двух ситуациях необходимо синхронизировать выполнение команд в сопроцессоре и центральном процессоре: команда сопроцессора, к выполнению которой привлекается численное операционное устройство, не мажет начинаться до завершения им предыдущей команды; центральный процессор не должен выполнять команду с обращением к операнду в памяти, адресуемому сопроцессором, до тех пор, пока сопроцессор не завершит обращение к требуемой ячейке. Команда ожидания WAIT позволяет синхронизировать центральный процессор так, что он не будет «выполнять» следующую команду сопроцессора или свою команду до тех пор, пока сопроцессор не закончит текущую команду. Когда сопроцессор выполняет команду, он формирует на выходной линии BUSY высокий уро- вень напряжения. Эта линия подключена на вход TEST центрального процессора. При выполнении команды WAIT центральный процессор опрашивает сигнал на входе TEST и, пока им не будет сигнал низкого уровня, не переходит к следующей команде. Дешифрование команды, находящейся за командой WAIT, сопроцессор и центральный процессор осуществляют одновременно. Таким образом, для удовлетворения первого требования перед каждой численной командой сопроцессора должна находиться команда WAIT, обеспечивающая готовность численного операционного устройства. Автоматическое формирование команд WAIT может производить программа-ассемблер. Если, например/ в программе встретились последовательные команды умножения FMUL и деления FDIV, ассемблер образует последовательность из четырех команд: WAIT, FMUL, WAIT, FDIV. ill
Чтобы удовлетворить второе требование, программист должен явно задавать команду FWAIT перед командой центрального процессора, которая производит' обращение к операнду в памяти, фигурировавшему в предыдущей команде сопроцессора. Следовательно, сопроцессор обязательно закончит запись результата в память до того, как к нему попытается обратиться центральный процессор. Устройство управления может выполнять многие команды управления сопроцессором автономно, независимо от действий численного операционного устройства. Поэтому для таких команд у сопроцессора появляется возможность выполнять две команды одновременно и в языке ассемблера предусмотрены мнемоники «с ожиданием» и «без ожидания». Например, команда запрещения прерываний имеет мнемоники FDISI и FNDISI. Во втором случае ассемблер не генерирует предшествующую команду WAIT и прерывания запрещаются одновременно с действиями численного операционного устройства по выполнению предыдущей команды. Когда команда сопроцессора должна считывать из памяти более одного слова или записывать любые данные в память, сопроцессор запрашивает у центрального процессора шину сигналом на линии RQ/Ё. При считывании из памяти сопроцессор запрашивает шину сразу после операции считывания центрального процессора, а в команде с записью в память — после того, как результат будет готов к записи, т. е. после преобразования результата из временного вещественного формата в формат получателя. В любом случае сопроцессор производит передачу данных в последовательных циклах шины, а затем освобождает ее. Обычно линия RQ/E0 сопроцессора подключается к линии RQ/E1 центрального процессора, а линия RQ/E0 центрального процессора, имеющая белее высокий приоритет, отводится для процессора вводатвывода. Линия RQ/E1 сопроцессора предназначена для подключения второго процессора ввода-вывода. Сопроцессор запрашивает прерывание центрального процессора сигналом INT, который обычно подается на один из входов программируемого контроллера прерываний. Прерывание генерируется при обнаружении особого случая с условием, что он не замаскирован ir прерывания сопроцессора разрешены. Если особый случай Н2
замаскирован, сопроцессор реализует маскированную реакцию и не устанавливает бит IR запроса прерывания. Когда особый случай не замаскирован, но прерывания запрещены (1ЕМ=1), действия сопроцессора зависят от того, находится центральный процессор в состоянии ожидания или нет. Если центральный процессор не находится в этом состоянии, сопроцессор устанавливает бит IR запроса прерывания в слове состояния и поддерлсивает BUSY=1. Устройство управления сопроцессора следит за командами центрального процессора и при поступлении команды сопроцессора (без предшествующей команды WAIT) выполняет ее. Обычно ею бывает команда разрешения прерываний FNENI (в форме «без ожидания»); она снимает маску (1ЕМ=0), и сопроцессор формирует сигнал INT. . Если центральный процессор находится в состоянии ожидания, появляется опасность возникновения состояния бесконечного ожидания: центральный процессор ожидает низкий уровень на линии BUSY, а сопроцессор ожидает вызова процедуры обработки особого случая и сохраняет BUSY—1. Чтобы предотвратить бесконечное ожидание (тупик), сопроцессор игнорирует запрещение прерываний и формирует сигнал INT. Бит запроса прерывания IR в слово состояния остается установленным до тех пор, пока не будет явно сброшен. Для сброса IR применяются команды FNCLEX, FNSAVE и FNINIT, которые воздействуют на слово состояния. Процедура обработки особого случая должна сбрасывать IR до возвращения в прерванную программу. Если этого не происходит, сопроцессор сразу же формирует повторное прерывание и возникает бесконечный цикл. Остановимся на достоинствах и недостатках сопро- цессорной конфигурации. Ее альтернативой оказывается разработка центрального процессора со всеми функциональными возможностями сопроцессора. Однако центральный процессор и сопроцессор в отдельности проще разработать, и, кроме того, при умелом программирова- вании оба процессора могут работать параллельно. Наличие двух процессоров обеспечивает разработчикам микросистем дополнительную гибкость — сопроцессор применяется только там, где он нужен. Конечно, сопроцессорный подход имеет и ряд недостатков. Отметим среди них вынужденное дублирование 8-723 113
в сопроцессоре схем выборки команд, трудности постро-, ения систем с несколькими сопроцессорами (так как цен-* тральный процессор имеет только один вход TEST и не может узнать, какой сопроцессор занят) и, наконец, реализацию условных переходов по результатам операций сопроцессора через центральный процессор, что несколько снижает производительность системы. 2.8. СПЕЦИАЛЬНЫЕ ЧИСЛОВЫЕ ЗНАЧЕНИЯ И ОСОБЫЕ СЛУЧАИ Для расширения вычислительных возможностей сопроцессора в нем наряду с обычными целыми и вещественными числами предусмотрены кодирование и обработка нескольких специальных значений. Они имеют определенный смысл и дают важную информацию об алгоритмах или операциях, в которых появляются эти значения. К специальньш значениям относятся вещественные числа с нарушением нормализации, нули и псевдонули, бесконечности, не-числа и неопределенности. Подавляющее большинство пользователей может не заботиться о специальных численных значениях, так как их вполне устроят маскированные реакции сопроцессора. Поэтому материал настоящего параграфа ориентирован в основном на тех пользователей, которым может потребоваться разрабатывать процедуры обработки особых случаев [5, 8]. 28.1. ВЕЩЕСТВЕННЫЕ ЧИСЛА С НАРУШЕНИЕМ НОРМАЛИЗАЦИИ Сопроцессор обычно хранит ненулевые вещественные числа в нормализованной форме, т.е. старший бит мантиссы, являющийся разрядом целой части, содержит единицу. Этот бит явно представлен во временном вещественном формате и неявно фигурирует в коротком и длинном вещественных форматах. Отсутствие старших нулей в мантиссе, имеющей в каждом формате фиксированную длину, позволяет сохранить в ней (мантиссе) максимум значащих цифр. Требование нормализации предполагает наличие в каждом формате вещественных чисел минимального представимого числа в виде 6 = Х 00...G1 1л000...00 114
Отметим, что минимальный смещенный порядок нормализованных чисел равен единице, а не нулю, как в большинстве компьютеров. Нулевой смещенный порядок зарезервирован в сопроцессоре для некоторых специальных значений. В дальнейшем в силу симметрии положительных и отрицательных чисел будем обозначать их знак символом X. Для представления чисел из диапазона 0—б приходится нарушать нормализацию, т. е. допускать числа, мантисса которых содержит один нуль или несколько старших нулей. Такие числа возникают, когда результат операции слишком мал для представления в нормализованной форме. Сопроцессор имеет две формы представления чисел с нарушением нормализации: денормализованное число имеет нулевой смещенный порядок, т.е. максимальное (по модулю) отрицательное значение истинного порядка, и произвольную, но не равную нулю мантиссу; ненормализованное число имеет один нуль или несколько старших нулей в мантиссе и произвольный, но не равный нулю, смещенный порядок. Наличие старших нулей в мантиссе расширяет диапазон в область малых чисел, но, разумеется, за счет некоторой потери точности, так как количество значащих цифр мантиссы уменьшается. В типичных алгоритмах очень малые числа обычно возникают как промежуточные, а не как окончательные результаты. Напомним, что при хранении промежуточных результатов во временном вещественном формате значение б равно ±3.4Х10-4932. Очевидно, вероятность появления столь малых чисел ничтожна. Тем не менее сопроцессор может загружать, обрабатывать и запоминать вещественные числа с нарушением нормализации. Денормализованные числа. Денормализованное число возникает в результате реакции сопроцессора на замаскированный особый случай антипереполнения (исчезновения порядка). Антипереполнение появляется, когда абсолютное значение вещественного числа становится слишком малым для представления в формате получателя, т. е. истинный порядок нормализованного результата операции слишком отрицателен. Например, получение истинного порядка —131 вызывает антипереполнение, когда получатель имеет формат короткого вещественного, так как этот формат допускает наименьший по- 8* 115
рядок, равный —126. Конечно, в форматах длинного и временного вещественного истинный порядок —131 не ведет к антипереполнению. Во многих компьютерах реакцией на антипереполнение является возвращение нулевого результата, т. е. всё числа, меньшие б, считаются нулем (так называемый машинный нуль). Если после этого продолжить вычисления, то окончательный результат окажется неприемлемым (нуль — слишком специальное число). В сопроцессоре обработка антипереполнения осуществляется более гибко. Когда особый случай антипереполнения не замаскирован, сопроцессор генерирует сигнал прерывания INT и обработка особого случая возлагается на специальную процедуру. Она может предпринять любое действие, зависящее от контекста решаемой задачи. Например, в простейшем случае ока может вернуть как результат операции нуль и сообщить об этом пользователю. Если особый случай антипереполнения замаскирован, потеря значимости происходит постепенно, при этом результат денормализуется до тех пор, пока смещенный порядок не станет нулевым. Денорма л изация осуществляв ется путем инкремента порядка и сдвига мантиссы вправо с введением нулей в ее старшие разряды {рис. 2.15). Главной целью маскированной реакции на антипереполнение является продолжение вычислений без вмешательства программиста. Конечно, при этом вводится ошибка, вызываемая потерей выдвигаемых младших раз- Истинный Операция Знак порядок • Мантисса Истинный результат Денорма- лизация Денорма- лизация Денорма- лизация Денорма- лизацня ДенорШ- лизация X X X X X X —133 —130 —129 —128 —127 —126 1Л1000Ю...0101010Ш 0Л1100010...0101010Ш 0л0и0001О...О1ОЮ10111 0Л001100010...01010ЮШ 0Л0001100010.. .0101010Ш 0Л00001Ю0010...01010101П Рис. 2.15. Денормалнаация в коротком вещественном формате 116
рядов мантиссы и имеющая такую же природу, как и по- грешность округления. При работе с вещественными числами погрешности округления возникают довольно часто и предсказать их влияние на окончательный результат сложных вычислений практически невозможно. Обычно вычисления продолжаются с игнорированием погрешностей округления, а программист анализирует окончательный результат и пытается выяснить их последствия. Маскированная реакция сопроцессора на антипереполнение, по существу, пытается интерпретировать антипереполнение аналогичным образом — вычисления продолжаются, а программист по окончательному результату оценивает последствия антипереполнений. Сели антипереполнение связано с серьезными последствиями, в дальнейших вычислениях возникнет особый случай недействительной операции. В процессе денормализации получается' либо денор- малнзованное число, либо нуль. Во всех вещественных форматах ненормализованные числа имеют нулевой смещенный порядок и ненулевую мантиссу (напомним, что нуль содержит нулевые порядок и мантиссу). Загрузка в регистр сопроцессора денормализовавного числа отмечается специальным тэгом. Как видно на рис. 2.15, денормализация вызывает потерю младших бит мантиссы, В предельном случае выдвигаются вправо и заменяются нулями все биты мантиссы — получается истинный нуль, наличие которого в регистре отмечается особым тэгом. Такие ситуации возникают редко, и их последствия, конечно, не хуже, чем возвращение нуля при возникновении антипереполнения. В большинстве прикладных программ денормализо- ванные числа встречаются редко, так как очень малыми обычно бывают промежуточные, а не окончательные результаты, представляемые короткими или длинными вещественными числами. Если использовать для промежуточных результатов временный вещественный формат, его огромный диапазон делает антипереполнения маловероятными. В табл. 2.8 показаны операции, при выполнении которых в сопроцессоре фиксируется особый случай денор- мализованного операнда. Отметим, что операции деления.' и вычисления остатка не допускают денормализОУ ванного делителя и генерируют особый случай недейст^ вительной операции, который маскировать не рекомендуй 117
Табляца 2.8. Особые случаи из-за депормализованного операнда Операция Загрузка (короткий или длинный вещественный операнд) Арифметические операции (кроме следующих) Сравнение и проверка Деление или вычисление остатка с денормалиэован- ным делителем Особый случай D D D I Маскированная реакция Загружается эквивалентное ненормализованное число Депормализованный операнд преобразуется в эквивалентное ненормализованное число, л операция продолжается То же Возвращает вещественную неопределенность ется. Трансцендентные команды требуют нормализованных операндов и не контролируют их на денормализацию. В остальных ситуациях сопроцессор преобразует дейормализованное число в ненормализованное (сдвиг мантиссы вправо и инкремент порядка), которое и участвует в операции как допустимый операнд. Большинство пользователей маскируют особый случай денормали- зованного операнда, и вычисления продолжаются. Ненормализованные числа. Ненормализованное число является результатом операции с привлечением денор- мализованного операнда и оказывается следствием маскированной реакции сопроцессора на антипереполнение. Ненормализованные числа существуют только во временном вещественном формате: их смещенный порядок может иметь любое, ненулевое значение (нулевой смещенный порядок, как было показано, зарезервирован для денормалнзованных чисел и нуля), бит целой части Мантиссы равен нулю, а остальные биты мантиссы произвольны (но не все нули). Ненормализованное число в регистре сопроцессора отмечается тэгом действительного (разрешенного) числа. Ненормализованные числа позволяют продолжать арифметические операции после антипереполнения, сохраняя при этом свое отличительное свойство как чисел с уменьшенной значимостью. Другими словами, некоторые операции формируют ненормализованные результаты до тех пор, пока их ненормализованное представление оказывает значительное влияние на последующие вы- 118
Таблица 2.10. Нулевые операнды и результаты FLD, FBLD: +0 -0 FILD +0 FST, FSTP: +0 Операция j i операнды +0 -0 +0 Результат 119 Таблица 2.9. Ненормализованные операнды и результаты Операция Сложение/вычитание Умножение Деление (с ненормализованным делимым) Вычисление остатка (с ненормализованным делимым) Деление или вычисление остатка (с ненормализованным делителем) Сравнение и проверка Округленна до целого Извлечение квадратного корня Запоминание в коротком или длинном вещественном формате Запоминание во временном пещественном получателе Запоминание в целом или десятичном получателе Загрузка Обмен Трансцендентные команды Результат Получение нормализованного или ненормализованного результата определяется представлением операнда с большим абсолютным значением Если хотя бы один операнд не- нормализован, результат будет ненормализованным Результат ненормализованный Результат нормализуется Особый случай недействительной операции Максимально возможная нормализация до производства сравнения Максимально возможная нормализация Особый случай недействительной операции Особый случай недействительной операции, если значение выше границы антипереполнения получателя; в противном случае —особый случай антиперсполнения 1 Обычная операция Особый случай недействительной операции Обычная операция То же Результат не определен
Продолжение табл. 2JO Операция и операнды —0 +Х*> -X*1 FIST, FISTP: +0 -0 +Х«* —Х'« Сложение: (+0) + (+0) -(0)-М-0) ■ (+0) + (-0), (_0)+(+0) ] (-Х) + (+Х), (+X)+(-X) (±0Ж±Х), (±Х) + (±0) 1 Вычитание: (+0)-{-О) | (-0 -(+0) (+0)-(+О), (-О)-(-О) <+Х)-(+Х), (-Х)-(-Х) (±0)-(±Х), (±Х)^(±0) Сравнение: , (±0) сравнить (+Х) J (±0) сравнить (±0) (±0) сравнить С—X) | Умножение: (+0)Х(+0), (-О)Х(-О) +0)Х<-0), |_0)х(+0) +0)Х(+Х),Н-Х)х(+0) |+0)Х<-Х), ?-Х)Х{+0) (-0)Х(+Х), +Х)Х(-0) (_0)X(-X). (-Х).ХГ-О) (+X)X(-Y), (_X)X(+Y) Деление: (±0): (±0) (±Х):(±0) j (+0) : <+Х , (-0): (-Х) (+0): (-ХК \-Q): (+Х) (-Х) : 1-У), (+Х): (+Y) (-Х) : \+Y), (+X) : (-Y) Вычисление остатка (FPREM): (±О)\(±0) (±Х)\(±0) j (+0)\(±Х) (+X)\(±Y) (-X)\(=FY) Результат 1 -0 +0 -0 +0 +р +0 +0 +0 -0 О'» о*» Х'« +0. -0 о*» О*3 X*4 А<В А=В А>В +0 -0 . +о -0 -0 +0 +о*5 —0»' Недействительная .операция Деление на нуль +0 —0 +0'* —0** Недействительная операция То же Н-0 -0 +0*7 _0" 120
Продолжение тйбл. 2АО Операция я операнды Извлечение квадратного корня (FSQRT): У=о V-+o Проверка (FTST): -±0 Изменять знак (FCHS): +0 -0 Абсолютное значение (FABS): ±0 Показательная функция (F2XM1): +0 -0 Округлить до целого (FRNDINT): +0 -0 Выделить (FXTRACT): +0 —0 Результат -0 +о Нуль -0 +0 +0 +0 -0 +0 -0 Оба +0 Оба —0 *' В случае антипереполнения при запоминании в коротком или длинном вещественном формате могут возникать нули. *' Числа, меньшие единицы, могут округляться до нуля. ♦э Знак определяется режимом округления: положителен при округлении к ближайшему, вверх или усечении; отрицателен при округлении вниз. •4 Сохраняется знак X. *в Очень малые значения X и Y могут образовывать нуль после округления истинного результата. Формирование нуля из ненулевых операндов сопроцессор отмечает особым случаем антипереполнення. *° См. *', но с малым X и очень большим Y. •* Когда X точно (без остатка) делятся на Y. числения. Следовательно, ненормализованные числа не могут выдавать себя за нормализованные, которые сохраняют полную значимость. Но если ненормализованное число оказывает несущественное воздействие на вычисления с нормализованными числами, результат будет нормализован. Например, сложение небольшого ненормализованного числа с большим нормализованным числом дает нормализованный результат, а в противоположной ситуации получится ненормализованный результат. В табл. 2.9 показано, как действуют различные команды с ненормализованными операндами. Отметим, что ненормализованное число может быть исходным операндом 121
или временным результатом, полученным сопроцессором из денормализованных чисел. 2.8.2. НУЛИ И ПСЕВДОНУЛИ Число нуль (или истинный нуль) в десятичном и вещественных форматах может иметь положительный или отрицательный знак, но знак двоичного целого нуля всегда положителен. В вычислениях положительный и отрицательный нули интерпретируются одинаково, и программисты обычно не заботятся о двух представлениях нуля. Однако при необходимости с помощью команды анализа FXAM можно определить знак нуля. При загрузке истинного нуля в регистр его содержимое отмечается специальным тэгом. В табл. 2.10 показаны результаты выполнения команд с нулевым (и) операндом (ами), а также получение истинного нуля в командах с ненулевыми операндами. Во временном вещественном формате предусмотрен специальный класс значений, называемых псевдонулями. Псевдонуль—это ненормализованное число с нулевой «мантиссой и ненулевым смещенным порядком (истинный нуль имеет нулевой смещенный порядок). У псевдонулей не может быть максимального смещенного порядка вида It... 11, так как этот код отведен для других специальных значений. Псевдонуль может получиться при умножении двух ненормализованных операндов, в которых суммарное число старших нулевых бит мантиссы сомножителей больше 64. Псевдонули-операнды обрабатываются как ненормализованные числа, за исключением следующих команд и операций, в которых они аналогичны истинным нулям: -команды сравнения и проверки; команда FRNDINT округления до целого; операция деления, в которой делимое является истинным нулем или псевдонулем, а делитель — псевдонуль. При сложении и вычитании псевдонуля и истинного нуля или второго псевдонуля псевдонули ведут себя как ненормализованные числа, но результат определяется в соответствии с табл. 2.10 для двух истинных нулей. 2.8.3. БЕСКОНЕЧНОСТИ В вещественных форматах предусмотрено представление специальных значений, называемых бесконечнос- 122
тями. Они кодируются с максимальным смещенным порядком 11...1I и мантиссой 1Л00...00. При загрузке бесконечности в регистр его содержимое отмечается тэгом специального значения. От других специальных значений, имеющих смещенный порядок 11 11 (ом. далее), бесконечности отличаются кодированием мантиссы. Сопроцессор может образовать бесконечность как результат маскированной реакции на особые случаи переполнения и деления на нуль. Отметим, что при округлении вверх или вниз маскированная реакция может сформировать вместо бесконечности наибольшее допустимое число, представимое в формате получателя (табл. 2.11), Таблица 2.11. Маскированная реакция на переполнение с направленным округлением Истшпшй результат Нормализация Нормализован Нормализован Нормализован Нормализован Не нормализован Не нормализован Не нормализован Не нормализован Знак + + *~ — + + — Режим округления Вверх Вниз Вверх Вниз Вверх Вниз Вверх Вниз Получаемый результат Плюс бесконечность Наибольшее положительное число Наибольшее отрицательное число Минус бесконечность Плюс бесконечность Наибольший порядок, мантисса результата То же Минус бесконечность Поведение бесконечностей как операндов команд сопроцессора зависит от содержимого поля управления бесконечностью в слове управления. При задании проективной модели бесконечность имеет одно беззнаковое представление, поэтому бесконечность нельзя сравнивать ни с каким значением, кроме бесконечности. В аффинном режиме учитываются знаки бесконечностей и сравнение оказывается возможным. Суммарные сведения по бесконечностям-операндам приведены в табл1 2.12. Здесь X обозначает нулевой или ненулевой операнд, a Y — только ненулевой операнд. 123
Таблица 2.12. Бесконечности-операнды и результаты Операция и период Сложение: (+<*>) + (+«>) (-oo)-f-/.оо) ( + оо)-Н—оо) (~оо)-Н+оо) (dzOo) + (±X) (±Х) + (±«) Вычитание: (+оо) + (—оо) (-оо)_(+оо) ( + оо)—(ч-оо) (-ooW-oo) (iooj-(dbX) (±Х)-(±оо) Умножение: (dfc°o) X (±оо) (±o°)X(Y) (±0)X(±«>) или (±«>)X(±0) Деление: (±oo) : (±oo) (zfcoo : ±X) (±X): <±oo} FSQRT: —oo + 00 FPREM: (±oo) \ (ioo) (±«>)\(±X) 1 |±X)\(±oo) FRNDINT: ±o° FSCALE: | (±oo) op (±oo) (rfcoo) op (±X) (±0) Op (±oo) (zhY) op (±oo) FXTRACT: ±oo Сравнение (±oo) сравнить (±oo) Проективная 1 модель Недействительная операция То же > » » » оо1 oo' Недействительная операция Тоже > » * » >• оо« оо* оо» оо» Недействительная операция То же ОС» 0s Недействительная операция Тоже | > » ж » х' ! ooi Недействительная операция оо* - °J Недействительная -операция Тоже > » 1 1 Аффинная модель 1 + оо 1—00 Недействительная операция Тоже оо» — оо* + оо —-оо Недействительная операция То же 00> оо* оо» оо» Недействительная операция Тоже оо» О8 Недействительная операция +оо Недействительная операция Тоже X* оо' Недействительная -операция ooi О1 Недействительная операция Тоже —оо<+оо 124
1 Знак равен знаку исходного операнда. * Знак противоположен знаку исходного операнда. • Знак равен сумме по модулю 2 знаков операндов. 2.8.4. НЕ-ЧИСЛА He-число является элементом класса специальных значений, которые существуют только в вещественных форматах. He-число имеет любой знак, максимальный смещенный порядок П...11 и любую мантиссу, кроме 1А00...00 (такая мантисса зарезервирована для бесконечностей). Наличие не-числа в регистре отмечается тэгом специального значения. Сопроцессор формирует особое не-число, называемое- вещественной неопределенностью, в результате маскированной реакции на особый случай недействительной операции. Такое не-число имеет отрицательный знак, смещенный порядок 11...11 и мантиссу 1дЮО...О0. Все остальные не-числа образуются программистом. Когда не-число оказывается операндом, сопроцессор фиксирует в слове состояния особый случай недействительной операции. Если этот особый случай замаскирован, сопроцессор возвращает как результат не-число, а если оба операнда являются не-числами, результатом будет не-число с большей мантиссой. Таким образом, полученное однажды не-число распространяется в вычислениях и выдается как окончательный результат. Однако в трансцендентных командах операнды не контролируются, и в случае операнда не-числа результат непредсказуем. Программист может не маскировать особый случай недействительной операции и использовать не-числа для прерывания центрального процессора и перехода к процедуре обработки особого случая. Общность такого подхода и большое количество значений не-чисел позволя- 125 Операция я период (±оо) сравнить (d:X) FTST: Продолжение табл. 2.12 П^АГЯ ( Аффинная модель А?В и недействительная операция Тоже —оо<Х<+оо оо»
ют опытному программисту учесть множество специальных ситуаций. Например, не-числа можно использовать для ускорения отладки. На начальном этапе сложная программа обычно содержит ошибки. Процедура обработки особого случая при каждом своем вызове передает диагностическую информацию в память. После этого она формирует конкретное не-число как результат команды с ошибкой, и оно определяет соответствующую диагностическую область памяти. Затем программа про* должается, порождая различные не-числа для каждой ошибки. По окончании программы не-числа применяются для доступа к диагностической информации, сохранен* ной в моменты появления ошибок. Таким образом, один тестовый прогон позволяет обнаружить и исправить несколько ошибок. 2.8.5. НЕОПРЕДЕЛЕННОСТИ Для каждого типа численных данных особый код выделен для представления специального значения, называемого неопределенностью. Сопроцессор формирует этот код как свою реакцию на маскированный особый случай недействительной операции. Для вещественных чисел неопределенностью является специальный код из диапазона не-чисел. Ее можно запоминать и загружать, как любое не-число, а она всегда сохраняет свой специальный смысл. В связи с этим программисту не рекомендуется применять код неопределенности для какой-то другой цели. Десятичная неопределенность имеет следующее кодирование: • 111! 1111 1111 1111 ХХХХ ХХХХ...ХХХХ ХХХХ Команда FBSTP запоминает десятичную неопределенность, но использование кода неопределенности в команде загрузки FBLD приводит к непредсказуемому результату. В форматах двоичных целых чисел один и тот же код представляет собой либо неопределенность, либо максимальное (по модулю) отрицательное число каждого формата, т. е. —215, —231 или —263. В двоичном представлении получается код 100...00. Сопроцессор запомнит этот код либо в результате маскированной реакции на особый случай недействительной операции, либо когда 126
значение в регистре является или округляется к наибольшему (по модулю) отрицательному числу, предста- вимому в получателе. Когда происхождение кода неопределенности оказывается неоднозначным, можно проверить флажок особого случая недействительной операции: не получена ли неопределенность как реакция на особый случай. При загрузке кода неопределенности или использовании его в командах целочисленной арифметики он всегда интерпретируется как целое число. Следовательно, неопределенность нельзя загрузить из упакованного десятичного или двоичного целого числа. 2.8.6. КОДИРОВАНИЕ ВЕЩЕСТВЕННЫХ СПЕЦИАЛЬНЫХ ЧИСЛОВЫХ ЗНАЧЕНИЙ Как показано выше, в форматах целых двоичных и десятичных <шсел только одно специальное значение — неопределенность со следующим кодированием: двоичное целое: 100...00 десятичное целое: 1111 1111 1111 1111 ХХХХ...ХХХХ Кодирование обычных и специальных числовых значений в вещественных форматах приведено в табл. 2.13 и 2.14. Как всегда, младшие биты находятся справа и при хранении в памяти они содержатся в байте с наименьшим адресом. Знаковый бит является левым битом байта с наибольшим адресом. Таблица 2.13* Кодирование в коротком и длинном вещественных форматах Численное аиачение Нормализованное число: минимальное максимальной Нуль Денормализованное число: минимальное максимальное Бесконечность Не-числа: минимальное максимальное неопределенность Знак X X X X X X X X 1 ; Смещенный порядок 08... 01 U...10 00...СО 00...00 00..,00 И...11 11...11 ll.s.li 11...И Мантисса (дробь) 00...00 11...11 00...00 00...01 11...11 00...00 00...01 11...11 10...00 ш
Таблица 2.14. Кодирование во временном вещественном формате Численное значение Нормализованное число: минимальное максимальное Нуль Ненормализованное число: минимальное максимальное Денормалнзованное число: минимальное максимальное Бесконечность Не-числа: минимальное максимальное неопределенность Знак X X X X X X х х X X 1 Смещенный порядок 00...01 И...10 00...00 1 00..,01 11...10 00...00 00...00 11...11 U...11 11...И 11...11 Маитясса ' 100...00 111.. .11 000...00 000...00 011...11 000...01 111.-.11 000,..00 100...01 111..'.11 ПО...00 ZB.7. ЧИСЛЕННЫЕ ОСОБЫЕ СЛУЧАИ Когда сопроцессор пытается выполнить численную операцию с недействительным операндом или образует результат, который не может быть представлен в формате получателя, он фиксирует численный особый случай. Имеются следующие виды особых случаев. Недействительная операция. Этот особый случай, который обычно свидетельствует об ошибке в программе, регистрируется при возникновении любого из следующих событий: попытка осуществить загрузку в непустой регистр (переполнение стека); попытка извлечь операнд из пустого регистра (антипереполнение стека); операндом команды является не-число; результат операции с фактическим операндом не определен (например, извлечение квадратного корня из отрицательного числа). Деление на нуль. Особый случай деления на нуль фиксируется, когда в команде деления делимое является конечным ненулевым числом, а делятель равен нулю. Переполнение. Особый случай численного переполнения возникает, когда порядок результата слишком велик для формата получателя. 128
Аитипереполнение. Особый случай численного антипереполнения регистрируется, когда порядок результата слишком мал для формата получателя. Таким образом, особые случаи переполнения и антипереполнения показывают, что результат операции находится вне диапазона представимых в формате получателя чисел. Благодаря очень широкому диапазону временного вещественного формата возникновение переполнения и антипереполнения маловероятно. Денормализованный операнд. Особый случай денор- мализованного операнда возникает, когда один или два операнда команды оказываются денормализованными числами. Неточный результат. Особый случай точности фиксируется, если результат операции не точно представим в формате получателя и сопроцессор вынужден округлять его. Например, дробь 1/7 невозможно точно представить ни в одном из двоичных форматов. Этот особый случай появляется довольно часто и сигнализирует о некоторой, обычно приемлемой, потере точности; поэтому он не маскируется только в тех прикладных программах, где требуется выполнять только точные операции. 2.8.8. ОБРАБОТКА ЧИСЛЕННЫХ ОСОБЫХ СЛУЧАЕВ При возникновении численного особого случая сопроцессор предпринимает одно из двух действий: либо он самостоятельно обрабатывает особый случай, образуя наиболее приемлемый результат и разрешая продолжение выполнения программы, либо сообщает об особом случае центральному процессору с последующим вызовом процедуры обработки. Каждый из шести особых случаев имеет отдельный бит флажка в слове состояния и бит маски в слове управления. Если особый случай замаскирован, т. е. бит маски содержит 1, сопроцессор предпринимает действия по умолчанию, называемые маскированной реакцией на особый случай, и продолжает выполнение программы. Когда особый случай не замаскирован (бит маски содержит 0), сопроцессор генерирует сигнал прерывания INT, который через программируемый контроллер прерываний подается в центральный процессор. Реагируя на запрос прерывания, центральный процессор вызывает процедуру обработки особого случая. 9-723 129
130 Таблица 2.15. Маскированные реакции на особые случаи Условие тоэникнооеввя Маскированная реакция Недействительная операция Регистр-источник отмечен как пустой Регистр-получатель не отмечен как пустой Один или два операнда являются не-числами Один пли два операнда в командах проверки и сравнения являются не-числами Операция сложения: указано аффинное замыкание, а операндами являются бесконечности с разными знаками; указано проективное замыкание, а операндами являются бесконечности Операция вычитания: указано аффинное замыкание, а операндами являются бесконечности с одинаковыми знаками; указано проективное замыкание, а операндами являются бесконечности Операция умножения: (оо) х Х(0) или (0)Х(«>) Операция деления: (оо) : (оо), (0) : (0), (0) : (псевдонуль), делитель ненормализован или денор- малиэован Команда FPREM: модуль- (делитель) денормализован или ненормализован; делимое является бесконечностью Команда FSQRT: ненулевой отрицательный операнд; денормали- зованный или ненормализованный операнд; операнд (—оо) с аффинным замыканием или (оо) с проективным замыканием ' Команда сравнения: указано проективное замыкание и (оо) сравнивается с (0), (оо) или нормализованным числом Команда FTST: указано проективное замыкание, а операндом является (оо) Возвращает вещественную неопределенность Возвращает (с записью в регистр) вещественную неопределенность Возвращает пе-число с большей мантиссой Устанавливает условие «не сравнимы» Возвращает вещественную неопределенность То же » » » » Возвращает вещественную неопределенность. Условие «остаток получен» Возвращает вещественную неопределенность Устанавливает условие «не сравнимы» То же
131 Условие возникновения Команды FIST, FISTP: регистр- источннк отмечен как пустой, содержит не-число, (оо), денормали- зованное или ненормализованное число или его содержимое превышает диапазон получателя Команда FBSTP: регистр-источник является пустым, содержит не-число, (оо), денормализованиое или ненормализованное число или его содержимое превышает 18 цифр Команды FST, FSTP: регистр- источник содержит ненормализованное число (порядок в диапазоне), а получатель имеет короткий или длинный вещественный формат Команда FXCH: один или оба регистра отмечены как пустые Денормализовш Команда FLD: операнд-источник денормализован Арифметические операции: один или два операнда деяормалнзова- ны Операции сравнения и проверки: один или два операнда денор- мализованы или ненормализованы (но не псевдонуль) Деление н Операция деления: делитель равен нулю Перепом Арифметические операции: указано округление к ближайшему или усечение, а порядок истинного результата больше 16 383 1 Продолжение табл. 2.15 Маскированная реакция Запоминает целочисленную неопределенность Запоминает десятичную неопределенность Запоминает вещественную неопределенность Помещает в пустой (ые) регистр (ы) вещественную неопределенность и производит обмен шый операнд Обычная загрузка Преобразует операнд в эквивалентное ненормализованное число, и операция продолжается Преобразует денормализованиое число в эквивалентное ненормализованное число; по возможности число нормализуется, и операция продолжается а нуль Возвращает бесконечность со знаком, учитывающим знаки операндов чение Возвращает бесконечность с правильным знаком и сигнализирует особые случай точности
Сопроцессор регистрирует особый случай, устанавливая в единицу бит флажка конкретного особого случая в слове состояния. После этого он проверяет соответствующую маску в слове управления и либо реализует маскированную реакцию, дающую стандартный результат, либо оповещает центральный процессор сигналом прерывания. Маскированные реакции сопроцессора, приведенные в табл. 2.15, тщательно проработаны с тем, чтобы продолжить программу с сохранением наиболее безопасных и осмысленных результатов. Управляя масками, про- 132 Условие возникновения Команды FST, FSTP: указано округление к ближайшему или усечение» а порядок истинного результата больше 127 (короткий вещественный получатель) или больше 1023 (длинный вещественный получатель) Продолжение табл. 2.15 Маскированная реакция Возвращает бесконечность с правильным знаком н сигнализирует особый случай точности Антипереполнение Арифметические операции: порядок истинного результата меньше—16382 Команды FST, FSTP: получатель имеет короткий (длинный) вещественный формат, а порядок истинного результата меньше —126 (-1022) Точны Возникает погрешность округления Ранее в команде сопроцессор выполнил маскированную реакцию на переполнение Денормализует до тех пор, цока порядок не станет равным —16 382, округляет мантиссу до 64 бит. Вели денормализо- ванная округленная мантисса равна нулю, возвращает истинный нуль; в противном случае возвращает денормалиэованное число То же, но с учетом минимально допустимого порядка (—126 и —1022) и длины мантиссы (24 и 53 бита) сть Операция продолжается без специальных воздействий То же
граммист может возложить обработку большинства особых случаев на сопроцессор, предусмотрев программную обработку наиболее серьезных ситуаций. Для большинства прикладных программ маскирование всех особых случаев, за исключением недействительной операции, дает приемлемые результаты с минимумом усилий. Особый случай недействительной операции свидетельствует о серьезной (фатальной) ошибке в программе, которую необходимо исправлять. Поэтому данный случай маскировать не рекомендуется, хотя сопроцессор обеспечивает встроенную реакцию и на этот особый случай [6]. Флажки в слове состояния как бы накапливают особые случаи, возникающие после того, как флажки были последний раз сброшены. Установленные флажки можно сбросить только командой FCLEX путем инициализации сопроцессора или перезаписью флажков с помощью команд FRSTOR или FLDENV. Следовательно, программист может замаскировать все особые случаи (кроме недействительной операции), выполнить программу, а затем проверить по слову состояния, были особые случаи или нет. .Незамаскированный особый случай инициирует прерывание центрального* процессора. В ходе реакции на прерывание центральный процессор опрашивает программируемый контроллер прерываний и выходит на процедуру обработки особого случая. Эта довольно сложная программа обычно входит в состав системного программного обеспечения. Действия типичной процедуры обработки особого случая следующие: передать в память среду сопроцессора на момент возникновения особого случая; сбросить флажки особых случаев в слове состояния сопроцессора; разрешить восприятие прерываний центральным процессором (они запрещаются в ходе реакции на прерывание); идентифицировать особый случай, анализируя слова управления и состояния в запомненной среде; предпринять некоторые системно-зависимые действия по исправлению особого случая; возвратиться в прерванную программу и возобновить ее выполнение. Иногда при выполнении команды могут возникнуть 133
несколько особых случаев. Сопроцессор сигнализирует о них в соответствии со следующим старшинством: де- нормализованный операнд (незамаскированный особый случай), недействительная операция, деление на нуль, деиормализованный операнд (замаскирован), переполнение/антипереполнение, потеря точности. Например, при делении нуля на нуль возникает особый случай недействительной операции, а не особый случай деления на нуль. Упомянутые выше системно-зависимые действия определяются требованиями конкретного применения. В наиболее простом варианте они состоят в следующем: осуществить инкремент счетчика особых случаев для последующей индикации; показать диагностическую информацию, например среду и регистры сопроцессора; запомнить диагностическое значение (не-число) как результат операции и продолжить программу. Чтобы исправить ошибку, вызванную особым случаем, процедура его обработки должна иметь в своем распоряжении точное состояние сопроцессора и уметь восстанавливать состояние сопроцессора перед возникновением особого случая. Для восстановления состояния программист должен четко лонимать, когда фактически распознаются особые случаи при выполнении команд сопроцессором. Особые случае недействительной операции, деления на нуль и денормализованного операнда обнаруживаются до начала операции, а особые случае переполнения/ /антипереполнения и потери точности не фиксируются до получения истинного результата. В первой ситуации регистры сопроцессора и память еще не модифицировались и выглядят так, как будто «подозрительная» команда не выполнялась. Во второй ситуации регистры сопроцессора и память содержат такие значения, которые получены по окончании команды. Однако в командах запоминания FST и запоминания с извлечением из стека FSTP незамаскированные особые случаи переполнения и антипереполнения генерируются так, как будто команды не выполнялись, т. е. память не модифицирована и извлечения из стека не было.
Глава 3 ПРОГРАММИРОВАНИЕ СИСТЕМ С СОПРОЦЕССОРОМ В § 2.1 говорилось о том, что программирование систем с арифметическим сопроцессором К1810ВМ87 на языке ассемблера особых,сложностей не вызывает. Программисту доступны все регистры и команды обоих процессоров, а также все режимы адресации памяти центрального процессора. Необходимо внимательно следить за синтаксисом команд сопроцессора и идентифициро? вать правильные форматы данных в памяти с помощью указателей PTR. Кроме того, в нужных случаях следует вводить команды FWAIT. В языках высокого уровня пока отсутствует поддержка сопроцессора К1810ВМ87. Поэтому критические фрагменты программ целесообразно оформлять в виде ассемблерных подпрограмм (модулей), которые объединяются с программами на языках высокого уровня. В настоящей главе приведено несколько ассемблерных программ для арифметического сопроцессора [6—10]. Они призваны помочь читателю разобраться в особенностях программирования сопроцессора и ускорить переход к разработке собственных прикладных программ. 3.1. ЭЛЕМЕНТАРНОЕ ПРОГРАММИРОВАНИЕ СОПРОЦЕССОРА Суммирование элементов массива. В первой программе с привлечением сопроцессора предположим, что в памяти находится массив чисел в коротком вещественном формате (длина элемента 4 байта)* Число элементов массива равно N, а адрес первого элемента массива равен ARRAY. Необходимо вычислить сумму всех элементов массива, представить ее в длинном вещественном формате и поместить в ячейку SUM (фактически SUM— это начальный адрес из смежных 8 байт). Программа 1 СУММИРОВАНИЕ ЭЛЕМЕНТОВ МАССИВА MOV CX, N ;Образовать счетчик FLDZ ;Подготовить акку- ; мулятор 135
JCXZ DONE Закончить, если N ; равно нулю XOR SI, SI ;Начать цикл с пер- ; вого элемента MORE: FADD DWORD PTR ;При'бавить теку- ARR AY [SI] ; щий элемент ADD SI, 4 ;Продвинуть индекс LOOP MORE ;Повторпть при ие- ; обходи мости DONE: FSTP SUM ;Сохранить сумму В этом фрагменте фигурируют три команды сопроцессора. Команда FLDZ включает в его стек нуль, подготавливая ST(0) к накоплению суммы элементов массива. Предполагается, что стек имеет хотя бы один свободный (пустой) регистр. Если уверенности в этом нет, нужно ввести команду FINIT, которая инициализирует сопроцессор и, в частности, очищает стек. Команда FADD прибавляет к ST(0) текущий элемент массива. Указатель типа DWORD PTR и мнемоника FADD означают, что операндом является число с плавающей точкой в коротком вещественном формате. После передачи в сопроцессор рперанд преобразуется во временный вещественный формат и прибавляется к ST(0). Наконец, команда FSTP при выходе из цикла записывает а ячейку SUM накопленную сумму. Определение SUM (им должна быть директива QWORD где-тр еще в программе) и мнемоника FSTP сообщают, что результат необходимо представить в длинном вещественном формате. Буква Р в мнемонике FSTP показывает, что после выдачи в память содержимого ST(0) производится извлечение из стека. Следовательно, после окончания этого фрагмента стек сопроцессора возвращается в первоначальное состояние. Интересно проанализировать временные соотношения при выполнении показанного фрагмента. Ассемблер автоматически введет перед командой FADD команду \VAIT, заставляющую центральный процессор ожидать готовности численного операционного устройства к выполнению команды FADD, и цикл несколько изменится: MORE: WAIT FADD DWORD PTR ARRAY [SI] ADD SI, 4 LOOP MORE 136
При входе в цикл действует сигнал BUSY=^=1, так как команда FLDZ еще не закончена. Действительно, она выполняется в течение 3 мкс, а команды JCXZ и XOR выполняются в течение 1,6 и 0,8 мкс соответственно. Поэтому центральный процессор будет ожидать в течение примерно 1 мкс. Отсюда следует, что команду FLDZ целесообразно поместить перед командой MOV СХ, N, что гарантирует завершение команды FLDZ перед вводом в цикл. Затем оба процессора одновременно дешифруют и начинают выполнять команду FADD. Центральный процессор «выполнит» ее за 3 мкс, а сопроцессору требуется 25 мкс. Центральный процессор дешифрует команду ADD SI, 4, выполняет ее за 1 мкс, переходит к команде LOOP MORE и выполняет ее за 3,4 мкс (предполагается, что осуществляется переход в начало.цикла). Сопроцессор продолжает выполнять команду FADD. После этого центральный процессор переводится в состояние ожидания, й по завершении сопроцессором команды FADD оба процессора начинают выполнять новую команду FADD, операндом которой будет следующий элемент массива. Таким образом, одно прохождение цикла занимает 25 мкс, а не 25+1+3,4=29,4 Мкс, как представляется без учета параллельной работы обоих процессоров, при этом занятость сопроцессора составляет 100 % времени, так как он одну за другой (без промежутков) выполняет команды FADD с различными операндами, а центрального процессора — только 33%. Остальное время он бесполезно ожидает завершения выполнения сопроцессором команды FADD. Ассемблер введет команду WAIT и перед командой FSTP. Поэтому при выходе из цикла, когда СХ=0, центральный процессор подождет окончания выполнения сопроцессором последней команды FADD, и оба процессора одновременно начнут выполнять команду FSTP. Конечно, центральный процессор «выполнит» ее быстрее сопроцессора, и, если его следующая (или другая близкая) команда обращается к ячейке SUM, перед ней необходимо указать команду WAIT. Рассмотренный фрагмент показывает практический прием использования параллельной работы процессоров для повышения скорости выполнения программы: после продолжительной команды сопроцессора следует по возможности ввести большее число команд центрально- 137
Рис. 3.1. Реализация условных переходов го процессора, не обращающихся к результату команды сопроцессора. Реализация условных переходов. Ранее говорилось о том, что сопроцессор не может непосредственно влиять на ход выполнения программы в зависимости от результатов его команд сравнения, проверки, анализа и вычисления частичного остатка. Хотя эти команды формируют код условия в слове состояния сопроцессора, выполнить условный переход может только центральный процессор. Для этого код условия необходимо передать в регистр флажков МП К1810ВМ86. Реализация условного перехода по результату операции сопроцессора включает в себя три этапа (оис 3.1): VF ■ выполнить команду сопроцессора, формирующую код условия; передать код условия через память в регистр флаж- кЬв центрального процессора; выполнить команду условного перехода центрального процессора* Микропроцессор К1810ВМ86 не имеет четырех отдельных команд условных переходов, соответствующих четырем комбинациям СЗ и СО, т.е. тех бит кода условия, на которые воздействуют команды сравнения и проверки. Команда JB осуществляет переход, если С0=1 (т. е. если CF=1), а команда JE —если С3= 138
= 1 (т.е. если ZF=I). Программный фрагмент, учитывающий все комбинации кода условия (в нем предполагается, что STATUS является рабочим словом в памяти, которое определено в программе где-то еще) имеет следующий вид. Программа 2 ПОЛНЫЙ АНАЛИЗ РЕЗУЛЬТАТА СРАВНЕНИЯ -.Предполагается, что сравнение выполнено FSTSW STATUS ;Передать код усло- ; вия в память FWAIT ;Ожидать заверше- ; ния передачи MOV АН, BYTE PTR ;Код условия в ре- STATUS+1 .; гистреАН SAHF ;Код условия в реги- ; стре флажков JB LORNON ;Перейти, если мень* ; ше или не срав- ; нимы JE EQUAL ;Перейти, если рав- ; ны EQUAL: • ;Условие равенства LORNON: JE NOCOMP ;Перейти, если не ; сравнимы {Продолжать, если ; меньше NOCOMP: . ;He сравнимы Как видно из рис. 3.1, бит условия С1 не попадает ни в один из флажков МП К1810ВМ86. Поэтому для его проверки приходится применять две команды (считая, что код условия сопроцессора находится в регистре АН): 139
Продолжение прогр. 2 CMP АН, 10В ^Выделить бит С1 JE С10 FF ;Перейти, если С1 =0 ; Продолжать, если ; Ci = l C10FF: Решение квадратного уравнения. Предположим, что необходимо найти корни Х\ и х2. квадратного уравнения ax2+bx+c=0. Будем считать, что коэффициенты а, Ь> с представлены в коротком вещественном формате и размещены в памяти как массив с начальным адресом COEF. Корни уравнения в таком же формате требуется поместить в ячейки памяти, начиная с адреса ROOT. Приведем известную формулу корней квадратного уравнения: jcli2 = (— Ъ ± Vb* — 4oc)/(2e). Когда детерминант Ь2—4ас<0, уравнение не имеет действительных корней. В этой ситуации программа переходит на метку ERROR. Программа 3 РЕШЕНИЕ КВАДРАТНОГО УРАВНЕНИЯ XOR SI, SI ;Сбросить индекс FLD DWORD PTRCOEF [SI] ;Передать А FLD DWORD PTRCOEF [SI+4J;Передать В FLD DWORD PTRCOEF [SI+8];Передать С FMUL ST, ST (2) Образовать A * С FLD1 Образовать 2 в вер - ; шине стека FLD1 FADD FXCH ;Обменять 2 и А • С FSCALE Образовать 4 ♦ А « С FSTP ST(1) ;Удалить2 FLD ST(1) ;ВключитьВ FMUL ST, ST(0) Образовать В • ♦ 2 FSUBR ;Детерминант в вер- ; шине стека FTST ; Проверить детер- ; минант FSTSW STATUS ;Перёдать код усло- 5 вия в память 140
Продолжение прогр. 3 FWAIT ;Ожидать заверше- ; ния передачи . MOV АН, BYTE PTR STATUS+1 SAHF ;Код условия в ре- ; гистре флаж- ; ков JC ERROR ;0трицательный де- ; терминант FSQRT ;Извлечь квадрат- ; ный корень FLD ST(2) ;Включить в стек А ADD ST, ST(3) Образовать 2 • А FLD ST (2) ^Включить в стек В FCHS Образовать —В FADD ST, ST (2) Образовать — В + (В* • 2—4» А» С) «• • * 1/2 FDIV ST, ST<1) ;Найти корень XI FSTP DWORD PTR ;Запомнить XI ROOT [SI] FLD ST (2) ;Вклк?чить в стек В FCHS Образовать —В FSUB ST, ST (2) Образовать — В — (В# « 2—4* А* С) «• * * 1/2 FDIV ST, ST(1) ;Найти корень Х2 FSTP DWORD PTR Запомнить Х2 ROOT [SI+4] FINIT Очистить стек Программа носит иллюстративный характер, доказывая несколько непривычное программирование про»- цессора со стековой структурой. На рис. 3.2 представлено состояние регистрового стека после выполнения каждой команды. При программировании сопроцессора целесообразно максимально пользоваться быстрыми внутренними командами без обращений к памяти. При ограниченной емкости регистрового стека программирование сложных задач потребует от программиста определенных усилий. В программе использован интересный прием умножения на целую степень числа 2. Для умножения на 4 141
142 Рис. 3.2. Использование стека в программе нахождения корней квадратного уравнения
в стеке образуется число -f 2, а затем командой FSCALE оно прибавляется к порядку множимого, что эквивалентно умножению на 2*=4. Преобразование координат. Одна из зада,ч обработки изображений заключается в повороте их на задаваемый или вычисляемый угол. Преобразование координат (xh у{) элемента изображения при повороте на угол а осу- ществляется по формулам X, = x,cosa + tysina; Y,=— x<sfna+ t/fcosa. В приведенной ниже программе предполагается, что регистр СХ содержит число N элементов изображения, а в регистре SI находится начальный адрес массива координат fa, tji). Сами координаты имеют формат целого слова и размещаются в памяти как последовательность *ь Уи *2, 1/2,...» xn, yN. Угол а, удовлетворяющий ограничению |а|<я/4, находится в вершине стека сопроцессора. Слово STATUS и байт SIGN являются рабочими ячейками. Программа 4 ПОВОРОТ ИЗОБРАЖЕНИЯ ;Программа осуществляет поворот изображе- ; ния «на месте» ;Число элементов в СХ, адрес массива в SI, ; уголв5Т(0) MOV SIGN, 0 ^Считать угол лоло- ; жительным FTST ^Проверять знак уг- ? ла FSTSW STATUS FWAIT MOV АН, BYTE PTR STATUS-И SAHF JNC PLUS MOV SIGN, —1 ;Отметить отрица- ; тельный угол FABS ;Теперь угол поло- ; жительный PLUS; ;Вычислить синус и косинус угла поворота FPTAN ;Образовать частич- ; ный тангенс 143
Продолжение прогр. 4 FLD ST(1) FMUL ST, ST(O) FLD ST(1) FMUL ST, ST(O) FADD FSQRT FDIV ST(1),ST(0) ;Синус находится FDIVP ST(2),ST(0) ; в ST(1), а ко- ; синус в ST (0) ;Учестъ знак угла TEST SIGN, 0FFH Проверить знак уг- ; ла JZ POS <;Угол положитель- ; ный FXCH 'Изменить знак си- FCHS t нуса FXCH POS: ;Теперь можно начать цикл поворота нзобра- ; жения MORE: F1LD WORD ;Включить в стек ко- PTR[SI] ; ординаты эле- FILI> WORD ; мента PTR [SI+2] FLD ST (1) ^Продублировать их FLD ST(1) FMUL ST, S T (5) ;Вычислить Y ♦ SIN FXCH FMUL. ST, ST(4) вычислить X» COS FADD ;Новая координата Х FISTP WORD ;Передать ее в па- PTR[S4 .; мять FMUL ST, ST (2) ;ВычислитьУ# COS FXCH FMUL ST, ST (3) вычислить X ♦ SIN FSUBR ;Новая координата У FISTP WORD -.Передать ее в па- PTR[SI+2] ; мять ADD SI, 4 ;Продвинуть указа-: ; тель массива LOOP MORE {Повторить при не- 5 обходимости 144
На рис. 3.3 показано, как используется регистровый стек сопроцессора при вычислении координат X и Y после образования в ST(0) и ST(l) косинуса и синуса угла поворота (т.е. начиная с метки MORE). Преобразование координат с метки POS одного элемента длится примерно 200 мкс, причем половина этого времени приходится на две команды FILD и две команды FISTP. Они выполняются сравнительно долго, так как должны осуществлять преобразование данных из одного формата в другой. Следовательно, значительного повышения производительности в подобных задачах от применения сопроцессора ожидать не приходится. 3.2. ЛОГАРИФМИРОВАНИЕ Трансцендентная команда FYL2X вычисляет значение Yxlog2X, т.е. позволяет наТГги логарифм любого числа по основанию 2. Число X находится в вершине стека ST(0), a Y — в следующем регистре стека ST(l). После извлечения из стека, т.е. удаления X» результат помещается на место Y. В вычислительных задачах часто требуется находить натуральные и десятичные логарифмы. Переход от двоичных логарифмов к логарифмам по любому основанию осуществляется в соответствии с тождеством log^X» = log„2 X log2X. Необходимые для вычисления натуральных и десятичных логарифмов константы log*2 и log ю 2 предусмотрены в командах загрузки констант. В подпрограммах LN и LOG находятся Iog?X я logmX числа X из вершины стека. Предполагается, что в стеке сопроцессора есть минимум один, свободный регистр. Время выполнения обеих подпрограмм составляет около 200 мкс. Программа 5 ВЫЧИСЛЕНИЕ НАТУРАЛЬНОГО ЛОГАРИФМА Подпрограмма вычисления натурального ло- ; гарифма числа, находящегося в ST(0) LN PROC FAR FLDLN2 ;Включить в стек г, LN2 10-723 145
Рис, 3,3, Использование стека в программе поворота изображений 146
Продолжение прогр. 5 FXCH ;Обменять с аргу- ; ментом FYL2X ; Вычислить нату- ; ральный лога- 5 рифм RET LN ENDP Программа 6 ВЫЧИСЛЕНИЕ ДЕСЯТИЧНОГО ЛОГАРИФМА {Подпрограмма вычисления десятичного ло- ; гаряфма числа, находящегося в ST (0) LOG PROC FAR FLDLG2 ;Включить в стек <; нужную кон- ; - станту FXCH ;Обменять с аргу- ; ментом FYL2X ;Вычислить десятич- ; ный логарифм RET LOG ENDP 3.3. ВОЗВЕДЕНИЕ В СТЕПЕНЬ В арифметическом сопроцессоре имеется единствен* ная команда FX2M1 возведения в степень. Она воспря- нимает аргумент X из диапазона 0^X^/2 в вершине стека ST(0) и вычисляет значение Y=2X—1, возвращая его на место аргумента: ST(0)-«-2*T(0) —I. При необхо* димости вычислений общей стеленной функции Ух следует пользоваться основным тождеством для изменения основания степени: Yx=2xlce,Y# Из этого тождества видно, что реализация общей степенной функции требует возведения 2 в произвольную степень. Здесь на помощь приходит команда FSCALE умножения числа в вершине стека на целую степень 2: ST(0)4-ST(0) X2sT(l>. Следовательно, произвольный показатель степени Z целесообразно разбить на две части: целое число Z\ (для команды FSCALE) и правильную дробь Z2 (для команды F2XM1). Когда Z2>lh> т.е. находится вне допустимого 10* 147
диапазона аргумента F2XM1, следует вычесть У2 из Z2, а затем умножить результат на 21/2. Алгоритм возведения 2 в произвольную степень Z состоит из следующих этапов: 1) образовать 2\ — наибольшее целое, которое меньше или равно Z. На этом этапе необходимо изменить режим округления в сопроцессоре. По умолчанию в нем принят наиболее благоприятный для вычислений режим округления к ближайшему (поле RC в слове управления содержит 00), а нахождение Zi требует округления вниз (полеИС=01); 2) сформировать правильную дробь Z2=Z—Zi, которая обязательно будет положительной; 3) если Z2>!/2, необходимо вычесть */2 из Z2 и отметить факт вычитания; 4) возвести 2 в степень Z2 (командой F2XM1) и масштабировать на 2Z| (командой FSCALE); 5) если из Z2 вычиталась 7г> следует умножить результат на 21'2. В приводимой ниже подпрограмме возведения 2 в произвольную степень Z предполагается, что Z содержится в вершине стека и определены • следующие ячейки памяти: STATUS — два байта для сохранения текущего слова управления; CONTROL — два байта для сохранения текущего слова управления; TEMP — рабочее слово; HALF — двойное слово, инициализированное на 0,5 в коротком вещественном формате. Программа 7 ВОЗВЕДЕНИЕ 2 В ПРОИЗВОЛЬНУЮ СТЕПЕНЬ ;Стек сопроцессора имеет минимум два сво- ; бодных регистра TWOZ PROC FAR PUSH AX ;Запомнить АХ FSTCW CONTROL {Сохранить слово уп- ; равления FSTCW TEMP ;Передать слово уп- .; равления FWAIT ;Ожидать заверше- ; ния передачи AND TEMP, 0F3FFH ;Сбросить биты RC 148
Продолжение прогр. 7 OR TEMP,0400H ;3адать округление • вниз FLDCW TEMP -Вернуть слово уп- ; равления ; с RC=01 FLD ST(0) {Образовать копию Z FRNDINT {Образовать Z1 FLDCW CONTROL ^Восстановить ре- 1 жим округле- • ния FSUB ST (1), ST -Образовать Z2 FXCH ;Обменять местами ; Z1 и Z2 FLD HALF ^Включить в стек ; 0.5 FXCH ;Обменять Z2 и 0.5 FPREM ;Йри необходимости ? вычесть 0.5 FSTSW STATUS ;Передать слово со- ; стояния FWAIT ;Ожидать заверше- ; ния передачи FSTP ST (1) ;Удалить из стека 0.5 F2XM1 Образовать 2* • ; •* Z2—1 FLD1 ;Прибавить к ре- ? зультату I для ; коррекции FADD ST(1),ST TEST BYTE PTR Проверить бит CI STATUS + 1,00000010В JZ NOCORR ;Вычитания 0.5 не ; было FLD1 ;Включить в стек 1.0 FADD ST, ST (0) ^Образовать 2 FSQRT {Найти квадратный ; корень из 2 FMUL ST(2), ST ^Скорректировать 5 результат NOCORR: FSCALE {Возвести в целую 5 степень 149
Продолжение прогр. 7 FSTP ST(1) ;Удалить21 POP АХ восстановить АХ RET TWOZ ENDP Особых пояснений эта подпрограмма не требует. Отметим, что в ней не предполагается нулевое содержимое поля RC, но, если такая ситуация имеет место, команду AND, которая сбрасывает поле RC, можно удалить. Далее, вычитание Уа из Z2» если оно требуется, осуществляется командой FPREM. После ее выполнения бит С1 кода условия фиксирует факт вычитания г- (0, если вычитания не было; II, если вычитание производилось. Состояние С1 (т.е. необходимость умножения результата на 2J'2) проверяется командами TEST и JZ центрального процессора. Образование 21'2 производится командами FLD1, FADD и FSQRT, хотя, конечно, эту константу можно хранить в памяти. Наконец, в подпрограмме не контролируется возникновение переполнения и антипереполнения. 3.4. ВЫЧИСЛЕНИЕ ТРИГОНОМЕТРИЧЕСКИХ ФУНКЦИЙ Основой для вычисления сопроцессором всех тригонометрических функций является команда FPTAN. Напомним, что она находит для утла а, который содержится в вершине стека и лежит в диапазоне 0<а^я/4, два таких числа X и Y, что tga=Y/X, при этом Y замещает значение аргумента, а X включается в стек. Если угол a находится в требуемом диапазоне, вычисление tga не представляет трудностей и реализуется всего двумя командами: FPTAN ;Образовать частич- ? ный тангенс FDIVP ST(1), ST ;Найти тангенс угла После выполнения этих команд значение tga замещает собой аргумент а в вершине стека. Имея числа X и Y, на основе тригонометрических тождеств нетрудно получить и другие тригонометрические функции. Ниже приведен фрагмент вычисления 150
sin а, если а по-прежнему находится в диапазоне от О до я/4. FPTAH {Образовать частичный ; тангенс FMUL ST, ST (0) {Образовать X • X FLD ST(1) {Включить Y в стек FMUL ST, ST (0) {Образовать Y • Y FADD {Сложить квадраты X и Y FSQRT {Извлечь квадратный ко- { рень FDIVP ST(1), ST {Найти синус угла Если допустить- произвольный угол а, а не ограничивать его первым октантом, вычисление тригонометрических функций заметно усложняется. Во-первых, прихо-. дится учитывать знак исходного угла. Это не вызывает трудностей при использовании тождеств tg(—а) = =—tga, cos (—a)=cosa-H др. Во-вторых, угол требуется приводить в диапазон команды FPTAH, т. е. в первый (а точнее, в нулевой) октант. Приведение реализуется с помощью команды FPREM, которая ориентирована именно на эту задачу. Напомним, что она образует частичный остаток от деления ST(0) на модуль из ST(i) и, кроме того, фиксирует в коде условия (СО, СЗ, С1) младших 3 бита частного. Полное приведение требует организации программного цикла, повторяемого до тех пор, пока в бите С2 кода условия не будет зафиксирован нуль. Очевидно, в качестве модуля следует использовать я/4, так как при этом биты СО, СЗ, С1 определяют октант, в котором находится исходный угол. В-третьих, в зависимости от фактического октанта потребуется вычислять тригонометрические функции по различным формулам. Пусть, например, исходный угол а приведен в диапазон 0<р<я/4, а фактически угол a находится в первом октанте, т.е. cc=2fot+Y> где я/4< <7<я/2, ft=0, 1, 2... Тогда вычислять tga придется по формуле tg a= 1/tg '(я/4—р). Вычисление тангенса. Рассмотрим подпрограмму вычисления тангенса произвольного угла, значение которого находится'в вершине стека ST(0){ она возвращает результат также в ST(0). Будем полагать, что слово STATUS зарезервировано в памяти для хранения слова состояния сопроцессора, байт SIGN фиксирует знак угла, а слово MIN2 инициализировано на —2. С учетом 151
Рас. 3.4. Нумерация октантов по младшим битам частного тождества tg(—a) = —tga в табл. 3.1 показаны состояния бита СЗ, С1 после выполнения команды FPREM, определяемые ими октанты, формулы, которые рассчитаны на диапазон аргумента команды FPTAN, и значения, принимаемые при нулевом приведенном аргументе р. Нумерация октантов представлена на рис. 3.4 (в скобках показаны значения бит СО, СЗ.С1 после выполнения команды). Таблица сз а 0 0 0 1 1 0 1 1 ЗЛ. Информация к подпрограмме вычислеиня таагенса Октант 1 0.4 1.5 2, 6 3.7 Формула с учетом команды PPTAN ""~~м" tgP J 1/tg (я/4-p) -1/tgP -tg (п/4-р) Значение Jg a при 02=0 00
FSTSW STATUS FWAIT MOV SAHF JNC MOV FABS PLUS: Продолжение прогр. 8 ;Передать в память ; код условия ;Ожидать заверше- ; ния передачи AH.BYTEPTR STATUS+1 ".Код условия в ре- ; гистре флажков PLUS ;Угол положйтель- ; ный SIGN, —1 ;Отметить отрица- ; тельный угол ;Теперь угол поло- ; жительный -.Привести исходный угол ; FPTAN в диапазон команды FILD FLDPI FSCALE FSTP FXCH MIN2 RANGE: FPREM FSTSW FWAIT MOV SAHF JP ST(1) STATUS Включить в стек —2 Включить в стек PI Образовать PI/4 Удалить —2 Угол в ST(0), PI/4 bST(1) Начать приведение Передать в память код условия Ожидать завершения передачи АН, BYTE PTR STATUS+1 Код условия в регистре флажков При необходимости повторить Регистр АН содержит код условия от команды FPREM Проверить приведенный угол на нуль RANGE FTST FSTSW STATUS FWAIT MOV BX,0 Сравнить угол с нулем Передать в память код условия Ожидать завершения передачи Предположить ненулевой угол 153
Продолжение прогр, 8 AND BYTE PTR STATUS+1,010G0001B CMP BYTE PTR STATUS+1,01000000В JNE NOZERO приведенный угол ; не равен нулю MOV BX, —1 Приведенный угол ; равен нулю NOZERO; ;Вычислить тангенс с учетом табл. 3.1. TEST АН, 10В Проверить С1 JNE OFF ;С1=0, октант 0 ; или 2 ;Исходный угол в октанте 1 или 3 СМР ВХ,0 Приведенный угол ; равен нулю? JE ZER01 ;Да, перейти к ZEROl FSUB .Образовать раз- ; ность PI/4 и уг- ; Jia FPTAN ;Найти частичный ; тангенс JMP DONE ZERO I: FSTP ST (0) ;Удалить угол FSTP ST (0) 'Удалить PI/4 FLD1 Подготовка для по* FLD1 ; лучения танген* ; са, равного 1 ; или —1 JMP DONE OFFi Исходный угол в октанте 0 или 2 FSTP ST(1) ;Удалить PI/4, угол bST(0) CMP BX, 0 Приведенный угол ; равен нулю? JE ZER02 ;Да, перейти к ZER02 FPTAN ;Найти частичный ; тангенс JMP DONE ZER02: FSTP ST(0) Извлечь угол 154
Продолжение прогр. 8 FLDZ ; Подготовка для по- ; лучения танген- FLD1 ; са, равного ну- ; лю или веско- * нечности DONE: (FXCH) -Для вычисления ; котангенса ^В ST(0) и ST(l) находится частичный тангенс ;Необходимо учесть октант исходного угла MOV ВХ,0 Предположить ок- ; тант 0 или 1 TEST AH.01000000B Проверить СЗ JZ NOC3 ;Октант 0 иди 1, знак ; плюс FCHS ;Октант 2 или 3, знак ; минус MOV BX, 1 ;Отметить октант 2 ; или 3 NOC3: TEST АН, 10В Проверить С1 J2 RECIP Перейти, если С1 = ; =0 (октант ; 0,2) XOR ВХ, 1 ;Инвертировать ; младший бит ВХ RECIP: ;Если исходный угол был в октанте 1 или 2, ВХ ; содержит I ;При этом необходимо вычислять обратное отно ; шение СМР . ВХ, 1 Проверить ВХ JNfc NOREC ;Обратное отноше- ; ние не требу- ; ется FXCH ;Обменять местами результаты FPTAN NORECFDIVP ST(1),ST Образовать тангенс ;Учесть знак исходного аргумента CMP SIGN, 0 Проверить знак JE POS ;Обгавить знак тан- ? генса 155
Продолжение прогр. 8 FCHS ;Изменить знак тан- ; генса POS: {Завершить подпрограмму POP ВХ ; Восстановить реги- ? стры Pop ax RET {Возврат TAN ENDP Дадим некоторые пояснения программы. Она оформлена как подпрограмма типа FAR и начинается с сохранения в стеке центрального процессора используемых ею регистров АХ и В)С. Регистр АХ (точнее, регистр АН) привлекается для проверки кода условия сопроцессора, а регистр ВХ является рабочим-и фиксирует некоторые условия, например получение нулевого приведенного угла. Следующий фрагмент помещает в байт SIGN значение —1 (FFH), если исходный угол отрицательный, и нуль в противном случае. После этого команда FABS делает исходный угол положительным. Команды от метки PLUS до метки RANGE вычисляют модуль приведения, равный я/4. Деление я на 4 реализовано не стандартной командой деления, а командой FSCALE, при этом к смещенному порядку числа прибавляется —2, что эквивалентно делению я на 4. Такой прием экономит слово памяти, которое потребовалось бы для хранения 4, и несколько повышает точность. Следующие шесть команд осуществляют приведение аргумента в диапазоне команды FPTAN. Условием повторения цикла является получение С2=1 после команды FPREM..npn передаче кода условия в регистр флажков центрального процессора бит С2 попадает во флажок PF, поэтому зацикливание приведения производит команда JP (перейти, если PF=1). Затем проверяется приведенный угол и, если он равен нулю, в регистр ВХ помещается —1 (FFFFH). В противном случае (т.е. приведенный угол не равен нулю) регистр ВХ будет содержать нуль. Начиная с метки NOZERO, осуществляется вычисление Igp или tg(n/4— p). Чтобы подпрограмма давала абсолютно точные значения тангенса 0 и 1, в ней отдельно 156
обрабатываются случаи нулевого приведенного аргумента (кроме того, и команда FPTAN исключает нулевой аргумент). Для определения октанта исходного угла привлекается содержимое регистра АН, в которое сохраняется код услрвия, образованный командой FPREM. От метки RECIP до метки NOREC производится присваивание, отрицательного знака, если исходной угол находится в октанте 2 или 3, и обмен значений X и Y, сформированных командой FPTAN, когда исходный угол находится в октанте / или 2. Команда FDlvP вычисляет тангенс, а три следующие команды присваивают ему окончательный знак с учетом знака исходного угла. Две заключительные команды POP восстанавливают из стека содержимое регистров АХ и ВХ, а команда RET осуществляет возврат в вызывающую программу. Отметим, что при вызове подпрограммы TAN в стеке сопроцессора должны быть свободными не менее двух регистров. Разработка подпрограммы вычисления котангенса не вызывает трудностей благодаря тождеству tgaXctga= = 1. По существу, в подпрограмме ТАЫ следует ввести единственную дополнительную команду FXCH у метки DONE (она показана в скобках). Вычисление функций синуса и косинуса также происходит в соответствии с командой FPTAN. Пр числам X и Y, полученным как результат команды FPf AN, вычисляются: sin p — YlVX*+ Y?; cos p'— X/1/Xa + Y^. Конечно, в соответствии с нахождением угла р в определенном октанте надо учесть знаки синуса и косинуса. Поскольку cosp=sin(ji/2+p), Целесообразно разработать одну подпрограмму для обеих функций. При вычислении косинуса необходимо просто увеличить частное, полученное в результате выполнения команды FPREM, на 2, так как я/2 соответствует двум октантам. Функция синуса является положительной в октантах 0—3 и отрицательной в октантах 4—7. Функция косинуса положительна в октантах 0, 1, 6, 7 и отрицательна в октантах 2—4, 5. Для учета знака исходного угла применяются тождества sin (—a) =—sin a и cos (—a) =cos a. Из табл. 3.2 видно, по каким формулам вычисляется синус для разных октантов и значения синуса при нулевом приведенном угле р. В подпрограмму SINE введен дополнительный рабо- 157
чий байт COS IN, определяющий вычисляемую функцию: m<;?N №• если вычисляется sin а; 1— lf если вычисляется cosa. В общих с предыдущей подпрограммой фрагментах для наглядности сохранены одни и те же метки. Таблица 32. Информация ■ подпрограмме вычисления синуса СЭС1 0 0 0 1 1 0 11 .Октант 0 1 2 3 Формула с учетом команды 1 FPTAN i smp cos <я/4+Р) cos0 sin (я/4—р) Значения sin a при £=0 0 VT/2 1 /T/2
Продолжение прогр. 9 PLUS: MOV COSIN, О {Вычислять синус COSENT: ;Точка входа для ; косинуса ;Прввести исходный угол в диапазон коман- ; ды FPTAN FILD MIN2 ;Включить в стек —2 FLDPI ; Включить в стек ; pi FSCALE {Образовать PI/4 FSTP ST(1) ;Удалить—2 FXCH ;Уг6л в ST(0), PI/4 ; bST(1) RANGE: FPREM ;Начать приведение FSTSW STATUS ;Передать в пагёять ; код условия FWAIT ^Ожвдатъ заверше- ; ния передачи MOV АН, BYTE PTR STATUS-}-1 SAHF ;Код условия в ре- ; гистре флажков JP RANGE ;При необходимости ; повторить {Регистр АН содержит код условия от команды FPREM ;При вычислении косинуса прибавить 2 к част- ; ному CMP COSIN, 0 {Вычисляется коси- ; нус? JE SINUS r {Нет, синус XOR АН, {Прибавить 2 (в СЗ) 01000000В TEST АН, {Был перенос? 01000000В JNZ SINUS {He было, сложение ; закончено XOR АН, 1В {Учесть перенос (в 5 СО) SINUS* 159
Продолжение прогр. 9 ;Проверить приведенный угол на нуль FTST ;Сравнить угол с ну- ; лем FSTSW STATUS Передать в память ; код условия FWAIT ;Ожидать заверше- ; ния передачи MOV ВХ, 0 предположить ну- ; левой угол AND BYTE PTR STATUS + 1,01000001В CMP BYTE PTR STATUS+liGiOQOQOOB JNE NOZERO Приведенный угол ; не равен нулю MOV ВХ,—1 приведенный угол ; равен нулю NOZERO: ;Вычислить тангенс с учетом табл. 3.1 TEST АН, 10В Проверить С1 JZ OFF ;C1=0, октант 0 ; или 2 Исходный угол в октанте 1 или 3 CMP BX, 0 Приведенный угол ; " равен нулю JE ZER01 ;Да, перейти к ; ZER01 FSUBP ST(1),ST Образовать раз- ; ность PI/4 и ; угла FPTAN ;Найти частичный ; тангенс JMP DONE ZERO I: FSTP ST (0) ;Уда лить угол FSTP ST (0) ;Удалить PI/4 FLD1 Подготовка для по- ; лучения танген- FLD1 ; са, равного 1 ; или—1 JMP DONE OFF: 160
Продолжение прогр. 9 ^Исходный угол в октанте 0 или 2 FSTP ST(0) ;Удалить PI/4, угол ; bST(O) CMP ВХ, О приведенный угол ; равен нулю? JE ZER02 ;Да, перейти к ZER02 FPTAN ;Найти частичный ; тангенс JMP DONE ZER02: FSTP ST (0) -.Удалить угол FLDZ ;Подготовка для по- ; лучения танген- FLD1 5 са, равного ну- { лю или беско- 5 нечности DONE: ;В ST(0) и ST(l) находится частичный тан- ; гене ;Теперь необходимо учесть октант исходного ; угла MOV ВХ, 0 ^Предположить ок- ; тант 0 или 1 TEST АН, ;Проверить СЗ 01000000В JZ NOC3 ;Октант 0 или 1, знак .; плюс MOV ВХ, 1 ;Отметить октант 2 ; илиЗ NOC3: TEST АН, 10В Проверить С1 JZ NOC1 ;Перейти, если С1 = ; =0 (октант 2 ; или 3) XOR ВХ, 1 ;Инвертировать ; младший бит ВХ NOC1: ;Проверить, какая функция вычисляется CMP COSIN,— 1 ;Какая функция ; ну^кна? JNE FSIN ;Требуется синус FXCH ;Требуется косинус, 11-723 161
Продолжение прогр. 9 ; обменять X и Y FSIN: FMUL ST(0), ST ;Эгн команды вычнс- ; ляют синус FLD ST(1) FMUL ST(0),ST FADD FSQRT FDIVP ST(1),ST ;Проверить октант исходного угла TEST АН, IB .Проверить СО JZ COO ;Октанты 0,1, 2, 3 NOT SIGN ;Инвертировать знак С00: Необходимо ли иэменять знак ^peзyльтaтa? CMP SIGN, 0 ;Проверить оконча- ; тельный знак JE POS ;Сохранить знак ре- ; * зультата FCHS ;Изменить знак ре- ; зультата POS: ;3авершить подпрограмму POP ВХ восстановить реги- ; стры POP AX RET SINE ENDP Как отмечалось, в подпрограмме SINE предусмотрено и вычисление косинуса, поэтому подпрограмма для косинуса будет очень простой. Программа 10 ВЫЧИСЛЕНИЕ КОСИНУСА ПРОИЗВОЛЬНОГО УГЛА COS PROC FAR PUSH AX ;Сохранить используемые PUSH ВХ ; регистры централь- ; ного процессора FABS ;Учесть правильный знак 162
Продолжение прогр. 10 MOV SIGN, 0 MOV COSIN, —1 ;Отметить вычисление ко- + синуса * JMP COSENT {Перейти к подпрограмме j SINE COS ENDP Подчеркнем, что при вызове подпрограммы SINE (a также COS) в стеке сопроцессора должны быть свободными минимум три регистра. Рассмотрим также подпрограмму TPIG, в которой вычисляются все шесть тригонометрических функций произвольного угла и оригинально используются некоторые тождества. В отличие от подпрограмм TAN и SINE здесь после приведения угла в диапазон от нуля до я/4 сразу выполняется команда FPTAN, образующая такие значения ST(0)=X и ST(l)=Y, что tgp=Y/X. Если считать X и Y катетами прямоугольного треугольника, то л«* ==R cosfi и Y=R sin р, где R = У X2- + Y* является гипотенузой. После команды FPTAN производится анализ кода условия, сформированного командой FPREM, т. е. определение октанта, в котором находится исходный угол, и необходимая коррекция значений X и Y. Когда угол находится в четном октанте, коррекция сводится к двум действиям: перестановка X и Y и изменение их знаков. Для нечетных октантов используются тождества cos р + sin р = V2 sin (я/4 + Р); cosp — sin p = |/2 cos (я/4 + Р). На рис. 3.5 показаны схема анализа октанта (рис. 3.5, а) и содержимое вершины стека ST(Q)_h следующего регистра ST(1) после проверки бит СО, СЗ, С1 частного (рис. 3.5, б). Для упрощения подпрограммы функции выделяются стандартным образом без привлечения констант и исходный угол считается положительным. Вычисленные значения функций передаются в область памяти, адресуемую регистром ВХ. Эти значения представлены в коротком вещественном формате* 11* 163
J Октант Г ° 1 г 1 z 1 j * 1 5 5 1 7 1 Проверка СО sf(r) У у У У , -У -У -К -К | St(0) X X JC 1 i -or -дг -х 1 Проверка G3 ST(T) г Y i -V -У 1 -X -X ST(O) X X "У -Y -X -X Y У 1 Проверка СТ ] 5^ У X+Y 1 X Х-Г -У -<*:к; ** -#-tf 1 sr(o) 1 * х-г -к ~(Х+У) -х ~(Х-У) у Х+У \ В) Рис. 3.5. Анализ октанта исходного угла Программа 11 ВЫЧИСЛЕНИЕ ТРИГОНОМЕТРИЧЕСКИХ ФУНКЦИИ ПРОИЗВОЛЬНОГО УГЛА Подпрограмма возвращает в области памя- ; ти, адресуемой ВХ, значения всех триго- ; нометрических функций угла, который ; при вызове находится в ST(0) 164
Продолжение прогр. 11 TRIG PROG FAR PUSH AX ;Сохранить исполь* ; зуемый регистр ;Привести исходный угол в диапазон коман- ; ды FPTAN FILD MIN2 ;Включить в стек ; -Л FLDPI ;Включить в стек PI FSCALE Образовать PI/4 FSTP ST(1) {Удалить ^-2 FXCH ;Угол в ST<0), PI/4 ; bST(1) RANGE: FPREM {Начать приведение. FSTSW STATUS {Передать в память ; код условий FWAIT ;Ожидать заверше- ; ния передачи MOY АН, BYTE PTR STATUS+1 SAHF ;Код условия в ре- ; гистре флажков JP RANGE ;При необходимости ; повторить {Регистр АН и флажки содержат код условия ; от команды FPREM FPTAN ;Найти частичный ; тангенс JNC Ml {Проверить СО; ок: ; такты О, Ц 2,3 FCHS {Для октантов 4, 5, FXCH ; 6, 7 изменить FCHS { знаки X и Y FXCH Ml: JNZ M2 {Проверить СЗ; ок- ; тантыО, 1,4, 5 FXCH ;Для октантов 2, 3, FCHS ; 6, 7 обменять { и изменить знак М2: TEST АН, 10В {Проверить С1 JZ МЗ ; Перейти, если, ок- ; танты 0, 2, 4, 6 FLD ST(0) {Для октантов 1, 3, FLD ST(2) ; 5, 7 образовать 165
FADD FXCH FSUB ; Вычислить FLD Продолжение прогр. И сумму и разность ST(0) и ST(1) FMUL FLD FMUL FADD FSQRT ^Вычислить FLD FLD FDIV FST FLD1 FDIVR FSTP ST (2) гипотенузу ST(0) ST, ST(0) ST (2) ST, ST<0) После этого фрагмента ST(0) содержит гипотенузу, ST(1) содержит X, ST (2) содержит Y косинус и секанс ST(1) ST(1) DWORD PTR [BX] DWORD PTR [BX+4] ; Включить X в стек ;Включить гипотёну- ; зу в стек ;Найти косинус ;Запомнить косинус ;Включить 1 в стек ;Найти секанс ;Запомнить секанс ^Вычислить синус и косеканс FLD ST(2) FLD ST(1) FDIV FST FLD1 FDIVR FSTP {Вычислить FLD DWORD PTR [BX+8J ; Включить Y в стек ;Включить гипотену- ; зу в стек ;Найти синус 'Запомнить синус ;Включить 1 в стек ;Найти косеканс Запомнить косеканс DWORD PTRIBX+lfl тангенс и котангенс ST{2) ;Включить Y в стек
Продолжение прогр. 11 FDIV ST, ST (2) ;Найти тангенс FSTP DWORD ;Запомнить тангенс PTR[BX+16] FSTP ST(0) ;Удалить гипотенузу FDIVR ;Найти котангенс FSTP DWORD ;Запомнить котан- PTR[BX+20]; гене ;3авершить подпрограмму FINIT -.Очистить регистро- ; вый стек POP AX -^Восстановить ре- RET ; гистр АХ TRIG ENDP Конечно, рассмотренные подпрограммы вычисления тригонометрических функций несколько разочаровывают . своей неожиданно большой длиной. Казалось бы, при наличии у сопроцессора специальных команд подпрограммы таких вычислений должны быть гораздо короче. Здесь, однако, необходимо учесть два обстоятельства. Во-пер« вых, подпрограммы будут существенно короче, если обеспечить нахождение исходного угла в диапазоне для команды FPTAN. Тогда не нужно приводить угол и определять октант, в котором он находится. Во-вторых, аналогичные подпрограммы для МП К1810ВМ86 окажутся намного длиннее (даже трудно представить себе вычисления во временном вещественном формате). Вычисления в сопроцессоре всех обратных тригонометрических функций основаны на команде FPATAN. Она находит arctg Z, где Z=Y/X, причем X находится в вершине стека ST(0), a Y—в следующем регистре стека $Т(1). Числа X и Y должны удовлетворять требованию 0<Y<X<oo. Команда FPATAN прризродит извлечение рз стека и формирует результат в новой вершине стека, *. $. результат замещает аргумент Y. Для вычисления арктангенса произвольного аргумента Z необходимо проверить следующие варианты! Z=0, .Z>0, Z<0, |Z|<1, |Z|=1 и IZ|>1. Приведение в диапазон аргументов команды FPATAN осуществляется в соответствии с тождествами arctg Z =— arctg (— Z); arctg Z = я/2 — arctg (1/Z). Отсюда следует, что знак аргумента учитывается отдель- 167
«io и далее можно работать с абсолютным значением Z. Если |Z| <1, то |Z| принимается за X, a Y полагается равным 1. Если JZ|;>1, за X принимается 1, а за Y— \Z\\ результат команды FPATAN корректируется по второму тождеству. Подпрограмма ATAN вычисляет арктангенс произвольного аргумента Z, передаваемого в вершине стека, ST(O). В ней считаются определенными слово STATUS и байт SIGN, назначения которых такие же, как и в предыдущих подпрограммах. Предполагается, что при вызове подпрограммы ATAN в стеке сопроцессора имеются минимум три свободных регистра.. Программа 12 ВЫЧИСЛЕНИЕ АРКТАНГЕНСА ПРОИЗВОЛЬНОГО АРГУМЕНТА Подпрограмма возвращает в ST(0) арк- ; тангенс аргумента, передаваемого ; bST(o) ATAN PROC FAR PUSH AX ;Сохранить регистр AX ;Проверить знак и равенство нулю исход- ;. ного аргумента MOV SIGN, 0 'Считать аргумент ; положительным FTST ;Проверить аргумент FSTSW STATUS ;Передать в память ; код условия FWAIT ;Ожидать заверше- ; ния передачи MOV АН, BYTE PTR STATUS-f l SAHF ;Код условия в ре- ; гистре флажков JA PLUS -.Аргумент положи- ; тельный JZ ZERO ;Аргумент равен ну- ; лю JMP NEG ;Аргумент отрица- • тфльний ZERO: FSTP ST(O) -Удалить аргумент FLDZ ; Включить 0.0 в стек JMP DONE 166
Продолжение прогр. 12 NEG: FCHS- ;Теперь аргумент по- ; ложительный MOV SIGN, —1 ;Отметить отрица- ; тельный аргу- ; мент PLUS: ;Сравннть аргумент с единицей FLDI ;Включить 1.0 в стек FCOM {Произвести сравне- ; ние FSTSW STATUS ;Передать в память ; код условия FWAIT ;Ожидать заверше- ; ния передачи MOV АН, BYTE PTR STATUS+1 SAHF ;Код условия в реги- ; стре флажков JA LESS1 ; Аргумент меньше ; единицы JC GRT1 ; Аргумент больше ; единицы ;Аргумент равен I * угол равен PI/4 FCHS ;B ST(0) находится .; 1#0 FADD ST (0), ST -Образовать —2.0 FLDPI ;Включить PI в стек FSCALE {Образовать PI/4 FSTP ST(1) {Удалить—2.0 JMP SIGN1 {Перейти к учету ; знака GRTb ;Использовать второе тождество FXCH ;ST(0)=Zt ST(l) = ; =1 FPATAN ^Вычислить арктан- { .гене FLD1 {Включить 1.0 в стек FCHS {Образовать —1.0 FLDPI {Включить PI в стек FSCALE {Образовать Р1/2 FSTP ST(1) {Удалить—1.0 FSUBRP ST{1),ST {Образовать резуль- { тат №9
Продолжение прогр. 12 JMP SIGN1 ^Перейти к учету ; знака LESS1: ;Числа в диапазоне команды FPATAN FPATAN ; Вычислить арктан- ; гене SIGN1: ;Учесть знак аргумента ; TEST SIGN, ;Проверить знак ар- 0FFH ; гумента JZ DONE ;Аргумент положи- 5 тельный FCHS ^Результат отрица- >; тельный DONE: -Завершить подпрограмму POP AX восстановить ре- ; гистр АХ RET ATAN ENDP 3.5. УМНОЖЕНИЕ МАТРИЦЫ НА ВЕКТОР Рассматриваемая ниже программа относится к области машинной графики и осуществляет умножение матрицы 4X4 на четырехэлементный вектор. Предположим, что на экране дисплея находится трехмерное изображение, состоящее из отрезков прямых. Необходимая для формирования его информация хранится в дисплейной памяти как список опорных точек—концов отрезков. Если изображение дается в перспективе, описание каждой точки удобно задать в виде четырехмерного вектора. Это объяс-, няется тем, что проективные преобразования, необходим мые для показа изображения с различных точек зрения, наиболее просто описываются матрицами 4X4. Для реализации проективного преобразования в общей форме трехмерный вектор (х, у, г) превращается в четырехмерный (*, #,2, 1). Затем матрица преобразования умножается на этот вектор, в результате чего получается четырехмерный вектор (xf, у\ z\ w'). Чтобы перейти к требуемому трехмерному вектору, надо разделить координаты xft у\ г9 на* о;', а затем удалить четвертую координату w'. 170
показывает, что данную точку не нужно соединять прямой с предыдущей точкой, а значение 1 показывает, что точки необходимо соединить. Такое кодирование применяется в некоторых графопостроителях для управления подъемом и опусканием чертежного механизма. В подпрограмме умножения PROD регистр DI адресует четырехмерный вектор, а регистр ВХ — матрицу преобразования, которая хранится в памяти по строкам в смежных ячейках. Предполагается, что вектор и матрица находятся в одном и том же сегменте данных. Результирующий четырехмерный вектор замещает исходный. Полные начальные адреса (сегментсмещение) вектора и матрицы передаются подпрограмме в стеке. На рио/3.6 показано состояние сегмента стека и сегмента данных после вызова подпрограммы. Символическое имя RS при- Йавнено четырем вне подпрограммы. рограмма 13 УМНОЖЕНИЕ МАТРИЦЫ НА ВЕКТОР
Продолоюение прогр. 13 FADD ;Наколление FLD DWORD PTR ;Третий элемент [ВХ+2» RS] ; строки FMUL ST, ST (4) ;Умножить на ХЗ FADD ;Накопление FLD DWORD PTR ;Четвертый элемент [ВХ+3* RS] ; строки FMUL ST, ST (5) ;Умножить на Х4 FADD ;Накопление FSTP DWORD .Запомнить элемент PTR [DI] ; вектора ADD DI, RS ;Продвинуть указа- ADD ВХ, 4 • RS ; тели вектора и матрицы LOOP ROW ;Повторить еще 3 ; раза POP BP ,-Восстановить реги- ; стры POP DS RET 8 ;Возврат PROD ENDP Подпрограмма начинается с запоминания в стеке центрального процессора содержимого используемых ею регистров DS и ВР и загрузки указателей DI и ВХ. Команда FINIT инициализирует сопроцессор, в частности очищает стек. Затем в регистровый стек сопроцессора включаются элементы вектора, после чего 4 раза выполняется цикл умножения вектора на каждую строку. Элементы вектора в стеке сопроцессора не теряются и участвуют в каждом проходе цикла. Отметим, что подпрограмма завершается командой возврата RET 8, которая удаляет из стека центрального процессора два полных указателя вектора и матрицы. 3.6. РЕГИСТРАЦИЯ ОШИБОК ВЫЧИСЛЕНИЙ В § 2.5 говорилось о том, что в обычных вычислительных алгоритмах рекомендуется маскировать все особые случаи, кроме недействительной операции. Маскированные реакции сопроцессора разрешают продолжать вычисления с получением наиболее приемлемого результата. Однако сопроцессор всегда фиксирует, возникал или нет особый случай. Так, денормализованный результат пока- 173
зывает предыдущее антипереполнение; получение бесконечности может означать предшествующее переполнение, а не-число свидетельствуете недействительном операнде. Нетрудно разработать программу, которая проверяет наличие в результатах вычислений особых численных значений. Следующий фрагмент проверяет наличие в массиве, элементы которого имеют короткий или длинный вещественный формат, специальных численных значений. Элементы массива поочередно передаются в сопроцессор, где анализируются с помощью команды FXAM. Когда встречается специальное численное значение, в байт ERROR записывается —1, а в регистр DI — адрес элемента массива. Предполагается, что начальный адрес массива находится в регистре ВХ, число элементов — в регистре СХ, а длина элементов массива (4 или 8 байт) — в регистре АХ. Программа 14 ПРОВЕРКА МАССИВА 174
Продолжение прогр. 14 CMP DH, 00000001В ;Это не-число? JE ERR ;Да, отметить в ; ERROR CMP DH, 00000101В ;Это бесконечность? JE ERR ;Да, отметить в ; ERROR CMP DH, 01000100B Ненормализованное ; число? JNE NOTDN ;Нет ERR: MOV ERROR,—1 ;Отметить специаль- ; ное значение MOV DI, ВХ ;Запомнить адрес ; элемента . NOTDNj ADD ВХ, АХ -.Продвинуть указа- ; тель FSTP ST(0) ;Очистить вершину ; стека LOOP CHECK Проверять весь ; массив DONE: ;Проверка закончена Команда анализа FXAM формирует в битах СЗ —СО кода условия подробную информацию о содержимом вершины стека. С помощью команд FSTSW и MOV старший байт регистра состояния передается в регистр DH микропроцессора К1810ВМ86. Затем команда AND сбрасывает все ненужные биты, в том числе и бит С1, который показывает знак числа в вершине стека. Три команды сравнения СМР проверяют по битам СЗ, С2, СО наличие в вершине стека специального численного значения. Команда MOV DI, ВХ сохраняет в регистре DI адрес последнего элемента, содержащего специальное численное значение. 3.7. ОСОБЕННОСТИ ПРОГРАММИРОВАНИЯ СОПРОЦЕССОРА В ПЕРСОНАЛЬНЫХ КОМПЬЮТЕРАХ В персональных компьютерах на базе МП К1810ВМ86 подключение сопроцессора К1810ВМ87 не вызывает трудностей, если, конечно, МП К1810ВМ86 работает в максимальном режиме. Встраивание сопроцессора не требует никаких дополнительных схем. Несколько сложнее программирование персонального компьютера, имеющего сопроцессор. При программировании на языке ассемблера 176
особых трудностей не возникает: программист просто пользуется расширенным набором регистров и объединенной системой команд. Конечно, для этого программа- ассемблер должна иметь средства поддержки сопроцессора: распознавать мнемоники команд сопроцессора, вводить при необходимости команды ожидания WAIT и генерировать машинные команды. Однако многие языки высокого уровня пока не рассчитаны на поддержку сопроцессора К1810ВМ87. Поэтому фрагменты прикладных программ на этих языках, ориентированные на привлечение сопроцессора, приходится разрабатывать на языке ассемблера. Чаще всего такие фрагменты оформляются в виде подпрограмм, хотя возможно и прямое встраивание команд машинного языка в программу на языке высокого уровня [10, И], Необходимо отчетливо представлять себе, что главные достоинства сопроцессора — быстродействие и точность — проявляются только в сложных численных расчетах (в англоязычной литературе такую сферу применения компьютеров образно называют number crunching— перемалывание чисел). В этой области, как показывают сравнительные оценки (бенчмарки) быстродействия, персональный компьютер с сопроцессором К1810ВМ87 ведет себя не как быстродействующий микрокомпьютер, а как медленный крупный компьютер. При разработке ассемблерных подпрограмм (процедур), которые объединяются с программой на языке высокого уровня, необходимо учитывать следующие факторы: форматы численных данных и их совместимость с форматами сопроцессора; особенности общей организации ассемблерных подпрограмм; способы передачи параметров в подпрограмму и результатов в вызывающую программу. 3.7.1. ФОРМАТЫ ЧИСЛЕННЫХ ДАННЫХ Каждый из языков программирования высокого уровня поддерживает несколько типов данных. В контексте применения арифметического сопроцессора интересны только форматы (типы) численных данных. Поэтому не будем касаться таких типов данных, как цепочечный (строковый), символьный, булев, множественный, регулярный и др. 176
Рис. 3.7. Форматы численных данных в языке БЕЙСИК Далее рассматриваются форматы численных данных трех распространенных языков программирования высокого уровня. Следует иметь в виду, что среди пользователей имеет хождение много версий интерпретаторов и компиляторов, иногда даже неизвестного происхождения. Поэтому в каждом конкретном случае читателям настоятельно рекомендуем познакомиться с форматами численных данных (а также особенностями организации ассемблерных подпрограмм) применяемого языка программирования. Язык БЕЙСИК. В БЕИСИКе применяются три формата численных данных: целые числа (INTeger) и числа с плавающей точкой в коротком и длинном форматах, называемые числами с одинарной (SiNGle) и двойной (DouBLe) точностью. Явная идентификация форматов (или типов) переменных и констант осуществляется с помощью символов определения типа, завершающих их имена: символ процент (%) обозначает целое число, восклицательный знак (!)—число с одинарной точностью и символ номер (ф)— число с двойной точностью. Неявной типизацией управляет оператор DEFtype, где type= =INT, SNG или DBL. Операторы uEFtype, которые размещаются в начале программы, содержат буквы или диапазоны букв, например I—N. Переменным, имена которых начинаются с указанных в операторах DEFtype букв, присваивается тип type. При отсутствии операторов DEF- type и символов определения типа (т. е. по умолчанию) принимается тип SNG. Форматы численных данных в языке БЕЙСИК показаны на рис. 3.7. Целые числа занимают 2 байта (слово) и представляются в дополнительном коде, имея диапазон от 12-723 177
Рис. 3.8. Форматы численных данных в языке ПАСКАЛЬ —32768 до +32 767. Этот формат полностью аналогичен формату целого слова сопроцессора К1810ВМ87. ЁЕИ- СИК не поддерживает такой разновидности этого формата, как беззнаковые 16-битныё целые числа, которые применяются для адресов. Поэтому в операциях с адресами необходимо быть очень внимательными. Числа с плавающей точкой различаются только длиной мантиссы. Короткий формат обеспечивает точность 6— 7 десятичных цифр, а длинный—16—17. В обоих форматах порядок занимает левый байт и представлен в смещенной форме, причем смещение равно 128. Мантисса считается нормализованной правильной дробью с неявным старшим битом, равным 1. Бит знака занимает место неявного старшего бита мантиссьь Таким образом, формат чисел с плавающей точкой в БЕЙСИКЕ не совпадает с внешними форматами аналогичных чисел в сопроцессоре
Рис. 3.9. Форматы численных данных в языке СИ ре К1810ВМ87. Это обстоятельство необходимо учитывать при разработке для БЕЙСИК-программы ассемблерных подпрограмм с привлечением сопроцессора. Язык ПАСКАЛЬ. Этот язык, по-видимому, наиболее разнообразен по количеству рабочих версий компиляторов. Поэтому при работе на нем следует изучить спецификации конкретного компилятора. На рис. 3.8 показаны форматы численных данных языка ПАСКАЛЬ, причем звездочками отмечены типы, отсутствующие в стандартном ПАСКАЛЕ. Тип INTEGER аналогичен типу INT в БЕЙСИКЕ и ровпадает с форматом целого слова сопроцессора К1810ВМ87. Тип INTEGER4 появился в новых компиляторах ПАСКАЛЯ, но применяется ограниченно; он соответствует формату короткого целого в сопроцессоре. Среди форматов чисел с плавающей точкой (называемых в ПАСКАЛЕ REAL —вещественный) во всех компиляторах поддерживается тип REAL, который аналогичен формату с одинарной точностью SNG в БЕЙСИКЕ и не совпадает с коротким вещественным форматом в сопроцессоре. Сравнительно новые форматы REAL4 и REAL8 эквивалентны короткому и длинному вещественным форматам в сопроцессоре К1810ВМ87. Язык СИ. Форматы численных данных языка СИ представлены на рис. 3.9. Как следует из рисунка, в язы- 12» 179.
ке СИ наблюдается наибольшая совместимость с сопроцессором К1810ВМ87: тип INT аналогичен формату целого слова, тип LONG — формату короткого целого, типы FLOAT и LONG FLOAT (или DOUBLE) — короткому и длинному вещественным форматам соответственно. 3.7.2. ОБЩАЯ ОРГАНИЗАЦИЯ АССЕМБЛЕРНЫХ ПОДПРОГРАММ И ПЕРЕДАЧА ПАРАМЕТРОВ При разработке прикладных программ для персонального компьютера целесообразно большую часть программы написать на языке высокого уровня, например БЕЙСИКЕ или ПАСКАЛЕ, а критические секции написать на языке ассемблера. Целесообразность диктуется как стремлением сократит* сроки и усилия, затрачиваемые на разработку и отладку программы, так и желанием повысить эффективность программы в смысле скорости ее выполнения. В контексте арифметического сопроцессора критическими секциями являются программные фрагменты со сложными численными расчетами, требующие высокой точности. Разработка программ на одном языке программирования требует знания только этого языка. Но как трлько программисту приходится разделять программу на части (модули), написанные на разных языках программирования, необходимо глубже разобраться в соглашениях, принятых в операционной системе и применяемы? языках. Знание операционной системы нужно для того, чтобы скомпоновать программные модули в загружаемую программу, а в каждом языке придется учитывать те его требования к программным интерфейсам, которые обеспечивают взаимодействие различных языков программирования. Под программным интерфейсом понимается фрагмент ассемблерного кода, который позволяет программе на языке высокого уровня взаимодействовать с ассемблерной подпрограммой. В программном интерфейсе выделяют два основных момента. Управляющий интерфейс реализует действия по. вызову и возврату, т. е. передает управление от одного модуля к другому и обратно. Информационный интерфейс (или взаимодействие по данным) позволяет 'взаимодействующим программным модулям правильно обращаться к общим данным и интерпретиро- вать'их. 180
В процессе взаимодействия вызывающей программы, вызываемой подпрограммы и интерфейса должны быть реализованы следующие действия. Вызов подпрограммы. Вызвать подпрограмму МП К1810ВМ86 может с помощью команды прерывания INT и команды вызова CALL. Вызов подпрограмм с помощью команды прерывания обычно применяется при необходимости обращения к обслуживаниям операционной системы. В прикладных программах вызов подпрограммы обычно осуществляется командой CALL; ей в языке высокого уровня соответствует оператор, синтаксис которого зависит от конкретного языка. Напомним, что МП К1810ВМ86 имеет команды CALL двух типов: NEAR CALL вызывает подпрограмму в текущем сегменте кода, a FAR CALL — подпрограмму из любого сегмента. В различных языках высокого уровня допускаются либо один, либо оба типа команды CALL. Возврат из подпрограммы. Обычно передача управления вызывающей программе осуществляется командой возврата RET, тип которой соответствует типу команды CALL. Однако иногда после выполнения подпрограммы требуется возврат в операционную систему. Среда работы подпрограммы. Под средой работы подпрограммы понимается установка сегментных регистров и местонахождение стека. Обычно регистр CS адресует сегмент кода вызывающей программы, регистр DS — ее сегмент данных, а регистры SS и SP —стек вызывающей программы. Вызванная подпрограмма, как правило, продолжает пользоваться стеком вызывающей программы, но, если ей требуется значительное стековое пространство, она может образовать в памяти собственный стек. Передача параметров и результатов. Обычно программы и подпрограммы работают с фиксированным числом параметров, хотя в некоторых языках допускается переменное число параметров. По соглашениям, принятым в персональных компьютерах, параметры всегда передаются через стек либо непосредственно (в стек включается само значение параметра), либо косвенно (в стек включается адрес или указатель параметра). Способ передачи параметров зависит от языка программирования; например, в некоторых языках в стеке не допускается передавать значения параметров. В любом случае вызванная подпрограмма должна абсолютно точно знать тот способ, который принят в конкретном языке высокого 181
уровня. Передача параметров оказывается наиболее сложной частью программного интерфейса. Сохранение важной информации. Подпрограмма должна сохранить неизменной всю ту информацию, которая потребуется вызывающей программе. В ассемблерной подпрограмме содержимое одних регистров можно изменять, содержимое других регистров разрешается модифицировать, нЬ оно должно быть восстановлено при завершении подпрограммы, а содержимое третьих регистров вообще нельзя затрагивать. По соглашению вызывающая программа не ожидает сохранения содержимого регистров данных АХ, ВХ, СХ, DX и индексных регистрбв SI if DI, поэтому их можно использовать как угодно. Содер^ жимое регистра флажков также не сохраняется. Следует иметь в виду, что регистр АХ часто применяется для возвращения результата, а другие регистры используются для передачи параметров, которые при выполнении под* программы уничтожаются. Особенно внимательно необходимо следить за сегментными регистрами. При модификации любого сегмента регистра его прежнее содержимое обязательно сохраняется в стеке, хотя это требование обычно не относится к регистру ES. Непосредственная модификация регистров CS и PC не допускается,- но их содержимое может косвенно изменяться при вызове других подпрограмм. Наконец, очень важно следить за использованием регистра ВР, через который производится обращение к параметрам в стеке. Очистка стека при возврате. При завершении подпрограммы в стеке могут находиться некоторые параметры, адрес возврата, содержимое регистров, запоминаемое после вызова, и, наконец, рабочая область подпрограммы. Подпрограмма сама удаляет из стека свою рабочую область и содержимое регистров командами POP, а адрес возврата удаляется командой возврата RET. Способы удаления параметров варьируются в различных языках программирования. В некоторых языках принято соглашение о том, что удаление параметров реализует подпрограмма путем указания в команде RET n числа п удаляемых из стека байт. В других языках удаление параметров возлагается на вызывающую программу. Оформление ассемблерной подпрограммы. Общий вид оформления ассемблерной подпрограммы как программного модуля удобно показать на пяти уровнях. 182
Уровень 1. Служебная директива определения модуля. Уровень 2. Директивы определения подпрограммы. Уровень 3. Код входа. Уровень 4. Получение параметров. Уровень 5. Тело подпрограммы. Уровень 4. Возвращение результатов в вызывающую программу. Уровень 3. Код выхода. Уровень 2. Директивы завершения подпрограммы. Уровень 1. Директивы завершения модуля. Уровни 1 и 2 выполняют служебные функции и не порождают машинных команд. Они, в основном, предназначены для редактора связей (компоновщика) и позволяют подключить подпрограмму к любой программе. Уровень 1 имеет следующий общий вид, который может несколько варьироваться в различных языках высокого уровня; MODULE SEGMENT 'CODE7 ASSUME CS: MODULE ;3десь находятся уровни 2—5 MODULE ENDS END В первой стрэке определения сегмента указывается произвольное (т. е. выбираемое программистом) имя, которое назначается сегменту, содержащему ассемблерную подпрограмму. Вторая строка с директивой ASSUME сообщает, что в сегментном регистре кода CS будет содержаться начальный адрес подпрограммы. Две последние строки — это стандартные директивы, завершающие сегмент и модуль. Типичное кодирование уровня 2 имеет следующий вид: PUBLIC ^SUBRT SUBRT PROC FAR (или NEAR) ;3десь находятся уровни 3—5 SUBRT ENDP Директива PUBLIC превращает подпрограмму в глобальную, т. е. доступную для объединения ее с другими программами. Директивы PROC и ENDP должны окайм* яять подпрограму, определяя ее начало и конец. Ключевые слова FAR или NEAR показывают тип подпрограммы, в соответствии с ними вызов подпрограммы ©существля- 183
Рис. ЗЛО. Образование стекового кадра при вызове подпрограммы ется командой FAR CALL или NEAR CALL. Приведенный формат уровня 2 является стандартным для большинства языков программирования высокого уровня. На уровне 3 появляются первые машинные команды, которые выполняют служебные действия, обеспечивающие совместную работу подпрограммы и вызывающей программы. Стандартный вид уровня 3 следующий: PUSH BP MOV BP, SP ;3десь находятся уровни 4 и 5 POP BP RET N ;N необязательно Первые две команды необходимы для доступа и сохранения всех параметров, которые были переданы вызывающей программой. Напомним, что стандартный способ передачи параметров состоит во включении их в стек непосредственно перед вызовом подпрограммы. В МП Ю810ВМ86 регистр ВР специально предназначен для доступа к параметрам в стеке, так как указание его в адресном выражении предполагает неявное обращение к текущему сегменту стека. Первая команда сохраняет в стеке исходное содержимое регистра ВР, т. е. то, что в нем было при вызове, а вторая передает в ВР адрес текущей вершины стека. Восстановление исходного содержимого регистра ВР осуществляется командой POP BP при за- 184
вершении подпрограммы. Командой MOV BP, SP образуется так называемый стековый кадр, и регистр ВР сохраняет отсчетную точку этого кадра независимо, от того» что затем включается в стек. На рис. ЗЛО показан пример передачи параметров через стек в предположении, что подпрограмме, передаются четыре параметра (слова) Р< и она имеет тип FAR. Если подпрограмма должна сохранять в стеке содер- ?имре дополнительных регистров, потребуются команды USH reg сразу после команды MOV BP, SP и соответствующие команды POP reg перед командой* POP BP. Напомним, что извлечение из стека производится в порядке, обратном порядку включения в стек. Команда RET имеет тип FAR или NEAR в зависимости от типа подпрограммы и соответствующей команды CALL (в ассемблерных подпрограммах тип команды RET явно не указывается, так как он очевиден из параметра директивы PROC). Она возвращает в CS : PC или PC запомненный в стеке адрес возврата и управление передается команде, находящейся в вызывающей программе после команды CALL. Общий формат команды возврата имеет вид RET n, причем п либо равно нулю (это значение п принимается и по умолчанию), либо нет. В первом случае удаление параметров из стека возлагается на вызывающую программу, а во втором —на саму подпрограмму. При выполнении команды RET n значение п прибавляется к содержимому указателя стека SP после извлечения из стека адреса возврата. Это действие переводит стек в то состояние, в котором он был до вызова подпрограммы, т. е. эффективно удаляет из стека переданные подпрограмме параметры. Например, на рис. ЗЛО значение п должно быть равно 8, так как каждый параметр состоит из 2 байт. Доступ к параметрам на уровне 4 зависит от того, что передается в качестве параметра — собственно данные (значения переменных) или их адреса. В любом случае обращение к тому, что передано, осуществляется через смещение относительно регистра ВР. В соответствии с рис. ЗЛО эти смещения определяют: О — содержимое регистра ВР в вызывающей программе; 2 — адрес возврата (содержимое PC); 4—адрес возврата (содержимое CS); отсутствует в 185
подпрограммах с типом NEAR, и тогда последующие смещения уменьшаются на 2; 6 — параметр Р4; 8—параметр РЗ; 10 —параметр Р2; 12 —параметр Р1. В большинстве языков программирования высокого уровня параметры включаются в стек в том порядке, в каком они записаны в операторе вызова. Следовательно, последний параметр оказывается наиболее близким к вершине стека. Однако в языке СИ принят обратный порядок. Когда в стеке передаются значения параметров, для доступа к ним применяется команда MOV. Например, передачу в регистр АХ параметра Р2 как данного производит команда MOV АХ, [ВР+10] ;Передать в АХ параметр Р2 Если в стеке передан адрес параметра, обращение к значению параметра потребует двух команд. Пусть, например, РЗ является адресом, тогда передачу значения параметра в регистр АХ выполняют команды MOV SI, [ВР+8] ;Передать адрес па- ;; раметра в ре- ••: гистр SI MOV AX, [SI] ;Пере^ать в АХ зна-_ ; чение парамет- ; ра В качестве буферного регистра адреса удобно пользоваться теми регистрами МП К1810ВМ86, которые привлекаются для адресации памяти, т. е. регистрами ВХ, S1 hDI. Наконец, на уровне 5 находится тело • подпрограммы— команды, которые реализуют ее функцию. Здесь могут фигурировать любые команды микропроцессоров К1810ВМ86 и К1810ВМ87. Рассмотрим конкретные особенности оформления ассемблерных подпрограмм на нескольких языках высокого уровня, применяемых в персональных компьютерах. Интерпретируемый БЕЙСИК. В БЕЙСИКЕ для вызова ассемблерных подпрограмм используются оператор CALL и функция USR. Не будем рассматривать функцию USR, так как подробное изучение ее потребует сведений, выходящих за рамки настоящей книги. 186
Общий формат оператора CALL имеет вид CALL имя [(переменная [.переменная]...)] Здесь имя является именем численной переменной, по-- казывающей начальный адрес вызываемой подпрограммы В виде относительного адреса в текущем сегменте памяти. Сегмент определяется последним оператором DEp SEG или принимается по умолчанию. В круглых скобка^ дается список переменных (параметров или аргументов, как их иногда называют), передаваемых подпрограмме. Квадратные скобки показывают необязательные элемента. При входе в подпрограмму сегментные регистры DS, SS и ES установлены на пространство данных БЕЙСИ-. КА. Регистр CS содержит значение, определенное в последнем 'операторе DEF SEG. Если этот оператор отсутствует, в CS находится то же значение, что и в остальных сегментных регистрах. Интерфейсные соглашения в интерпретируемом БЕЙСИКЕ сводятся к следующим правилам. 1. Все параметры передаются путем включения в стек их относительных адресов. Следовательно, подпрограмма может возвратить результат в БЕЙСИК через параметр, изменяя значение переменной в списке переменных. 2. Подпрограмма вызывается командой FAR CALL и должна заканчиваться командой FAR RET. 3. Параметры передаются в порядке записи их в one-, раторе CALL. Смещение в стеке относительно ВР любого параметра равно 2Х(/г—/п)+6, где п — число передаваемых параметров, т — позиция конкретного параметра в списке оператора CALL. 4. Удаление* параметров из стека возлагается на подпрограмму. Следовательно, подпрограмме должно передаваться фиксированное число параметров, а в команде RET л значение п равно удвоенному числу параметров в операторе CALL. Специально подчеркнем, что ответственность за соответствие числа и типа параметров в операторе CALL тому, что ожидает подпрограмма, несет программист. В показанных выше уробнях оформления ассемблерных подпрограмм имеются два несущественных отличия. В директиве SEGMENT отсутствует класс CODE, а директива PUBLIC не нужна. Объясняются эти отличия тем, что ассемблерная подпрограмма не связывается с интерпретируемым БЕЙСИКОМ: в компилируемых язы- 187
188
Если обратиться к формату стека после вызова подпрограммы (как на рис. ЗЛО), то никаких особых пояснений эта подпрограмма не требует. Язык ПАСКАЛЬ. Приведенные выше общие правила оформления ассемблерных подпрограмм без всяких изменений распространяются на язык ПАСКАЛЬ. Однако он допускает большую гибкость в передаче параметров; в нем передаются как адреса параметров, так и значения параметров. Если в объявлении подпрограммы параметр определен VAR или VARS, то при вызове подпрограммы в стек будет включен адрес параметра. По существу, такое определение сообщает подпрограмме о возможности изменения параметра. Указание VAR заставляет передать в стеке двухбайтный относительный адрес в текущем сегменте данных, a VARS —полный четырехбайтный адрес в формате сегмент : смещение. Размер передаваемых адресов необходимо учитывать в команде RET п. Если параметр не определен VAR или VARS, ПАСКАЛЬ защищает згдечение параметра от модификации его подпрограммой. Такая защита осуществляется двумя способами. Когда параметр имеет совместимый тип, например тип целого, в стек включается его значение. В противном случае в памяти образуется копия параметра и в стек включается адрес этой копии. Применяемый способ влияет на то, как подпрограмма обращается к параметрам: прямо или косвенно. На практике целесообразно применять единообразный способ передачи параметров, например, объявляя все параметры VAR и требуя передачи через стек адресов параметров, при этом обработка параметров становится стандартной и совместимой с БЕЙСИКОМ, а программист делает меньше ошибок. Подпрограммы, объявленные в ПАСКАЛЕ как функции (FUNCTION), возвращают одно значение. Достаточно простое значение возвращается в регистре АХ, а более сложное —в памяти. Его относительный адрес помещается в стек после параметров функции. По суще-, ству, ПАСКАЛЬ создает для программы-функции один дополнительный параметр VAR и использует его для возвращения результата функции. Язык СИ. По сравнению с рассмотренными выше языками в языке СИ наблюдается больше отступлений от «стандартного» оформления ассемблерных подпрограмм. 189
хотя общий вид уровней 1 —3 сохраняется. Ниже приведены уровни 1 — 3 для компилятора языка СИ, ориентированного на так называемую малую (SMALL) модель памяти. В этой модели объемы кода (программы) и данных ограничены одним сегментом 64К байт. PGROUP GROUP MODULE MODULE SEGMENT BYTE PUBLIC 'CODE' PUBLIC SUBR ASSUME CS: MODULE SUBR PROC NEAR PUSH BP MOV BP, SP 190
обходимо учитывать при задании смещений относительно регистра ВР. 3.7.3. ПРИМЕРЫ АССЕМБЛЕРНЫХ ПОДПРОГРАММ Приведем две ассемблерные подпрограммы, в которых привлекается сопроцессор К1810ВМ86 и которые иллюстрируют рассмотренные выше правила их оформления. Статистическая обработка. Предположим, что fc области памяти находится массив ARRAY из N результатов йабЛюдений, представленных в коротком веществен* ном формате (длина каждого элемента составляет 4 байта). Подпрограмма HANDLE должна вычислить среднее т и стандартное отклонение сг по формулам Постановка задачи предполагает наличие в подпрограмме четырех параметров: ARRAY — исходный массив результатов наблюдений; N — целочисленная переменная, значение которой равно числу элементов массива; MEAN и STD — переменные в коротком вещественном формате, значениями которых после выполнения подпрограммы будут среднее и стандартное отклонения. Из БЕИСИК-программы подпрограмма HANbLE вызывается оператором CALL HANDLE (ARRAY (0), N, MEAN, STD) При вызове подпрограммы в стеке передаются адреса параметров. Относительно ВР они имеют смещения 12, 10, 8 и 6 в порядке следования параметров в операторе CALL. Программа 16 ВЫЧИСЛЕНИЕ СРЕДНЕГО И СТАНДАРТНОГО ОТКЛОНЕНИИ CSEG SEGMENT ASSUME CS:CSEQ HANDLE PROC FAR PUSH ВР -.Подготовить MOV BP, SP ; стековый кадр FLDZ ;Включить 0.0 в стек 191
Продолжение прогр. 16 XOR SI, SI ■ ;Сбросить индекс ; ный регистр MOV DI, [ВР+10] ;Передать число эле- ; ментов MOV CX,{DIJ ; в регистр СХ MOV DX, СХ ; и регистр DX MOV DI, [BP+12] ;Передать адрес ; массива MOV BXJDI] ; в регистр ВХ LMEAN: PADD DWORD PTR -.Прибавить элемент [BX][SI] ADD SI, 4 ;Продвинуть индекс ; элемента LOOP LMEAN ;При необходимости ; повторить MOV DI, [BP+10J ;Адрес N в регистре FIDI.V WORD PTR вычислить среднее [DI] MOV DI, [BP+8] {Адрес среднего в Г регистре DI FST DWORD PTR ;Запомнить среднее [DI] MOV СХ, DX '.Передать N в СХ FLDZ -Включить 6.0 в стек LSTD: FLD DWORD PTR ;Передать элемент [BX][SI] ; массива SUB SI, 4 ;Продвинуть указа- ) тель (назад) FSUB ST, ST(2) ^Разность X и сред- ; него FMUL ST, ST (0) ;Квадрат разности FADDP ST(1), ST -Накапливать квад- ; раты разностей LOOP LSTD ;При необходимости ; повторить FLD1 ;Вклк>чягь 1.0 а стек MOv DI, [BP-flO] ;Адрес N в регистре DI FISUBR WORDPTR Образовать N—1 [DI] FDIV ^Образовать диспер- ; сию 192
Продолжение прогр. 16 FSQRT MOV FSTP FWAIT RET HANDLE ENDP CSEG ENDS END Отметим команду FWAIT, которая находится перед командой возврата RET. Она гарантирует завершение записи в память стандартного отклонения до выполнения команды RET, т. е. возвращения из подпрограммы. Следовательно, сразу же после возврата из подпрограммы центральный процессор может обращаться к ячейке STD. Обобщенное суммирование численного массива. Следующая подпрограмма иллюстрирует еще одну интересною возможность арифметического . сопроцессора IU8T0BM87. Автоматическое . преобразование входных данных во внутренний вещественный формат, а выходных данных в формат получателя позволяет разработать в некотором смысле универсальные подпрограммы. В таких подпрограммах тип обрабатываемых данных передается как параметр и учитывается в командах загрузки и запоминания, а внутренняя обработка в сопроцессоре оказывается одинаковой для всех типов данных. Подпрограмма SUMMA вычисляет сумму массива, элементами которого могут быть целые числа в формате слова (2 байта), а также короткие (4 байта) или длинные (8 байт) вещественные числа. Как параметры подпрограмме передаются массив ARRAY, целая переменная TYPE, определяющая длину элементов массива '(2, 4 или 8), переменная N, задающая число элементов массива, и переменная SUM в длинном вещественном формате, через которую возвращается накопленная сумма. Под- •.Вычислить стандартное отклонение ;Адрес результата в DI DWORD PTR ;Запомнить стандартное отклонение ♦Ждать, пока сопро- \ цессор закончит ^Возврат DI, IBP+6J [DI] 13-723 193
Продолжение прогр. 16 программа вызывается в БЕЙСИК-программе оператором CALL SUMMA (ARRAY (0), TYPE, N, SUM) Программа 17. ВЫЧИСЛЕНИЕ СУММЫ ЭЛЕМЕНТОВ МАССИВА CSEG SEGMENT ASSUME CS:CSEG SUMMA PROC FAR PUSH BP ^Образовать егеко* MOV BP, SP ; вый кадр MOV BXJBP+12] ;B регистре ВХ ад- ; pec массива MOV SI, [BP+10] ;B регистре SI ад- ; pec TYPE MOV AX, [SI] ;B регистре АХ тин ; -элементов MOV SI,[BP+8] ;B регистре SI ад- ; pec N MOV CX,[SI] ;B регистре СХ зна* \ чение N ;Подготовка завершена FLDZ ; Включить 0,0 в стек CMP CX, 0 Проверить N JLE DONE ;Массива нет LADD: СМР АХ, 2 ;Формат целого ело- * ва? JNE NOINT -Нет, перейти FIADD WORD PTR ;Да, прибавить эле- [ВХ] ; мент JMP . NEXT NOINT: CMP AX, 4 ^Короткий вещест- •; венный фор» ; мат? JNE NOSNG ;Нет„ перейти FADD DWORD PTR ;Да, прибавить эле- [BXJ ; мент JMP NEXT NOSNG: FADD QWORD PTR Длинный вещест- {ВХ] $ венный формат 194
13*
196
197
198
199
200
201
202
203
СПИСОК ЛИТЕРАТУРЫ 1. Григорьев В. Л. Программирование однокристальных микропроцессоров. Мл Энергоатомиздат, 1987. 2. Одноплатные микроЭВМ/В. Г. Домрачев, С. Н. Иванов, А. Ф. Фоманов, Ю. Н. Чернышов. М.: Энергоатомиздат, 1988. 3. Лю Ю-Ч., Гибсон Г. Микропроцессоры семейства 8086/8086. М.: Радио и свяэь, 1987. 4. Morgan С L., Waite М. 8086/8088 16-bit microprocessor primer. McGraw-Hill 1982. 5. The 8086 family user's manual. Numeric supplement Intel Corp., 1980. 6. Startz R. 8087 applications and programming for the IBM PC and other PCs. Prentice-Hall, 1988. 7. Palmer J. F.f Morse S. P. The 8087 primer. Wiley, 1984. 8. IAPX^ee Programmer's reference manual. Intel Corp., 1984. 9. Morse S. P., Albert .D. JL The 80286 architecture. Wiley, 1986. 10. Scanlon L. J. IBM PC and XT assembly language: a guide for programmers. Brady, 1985. 11. Norton P. Programmer's guide to the IBM PC. Microsoft Press, 1985.
ОГЛАВЛЕНИЕ Предисловие ... 3 Глава 1. Микропроцессор К1810ВМ86 как центральный процессор 7 1.1. Общая характеристика микропроцессора 7 1.2. Сигнальные линии 10 1.3. Программная модель микропроцессора 13 1.4. Организация и режимы адресации памяти 17 1.5. Система команд 23 1.5.1. Команды передач данных 24 1.5.2. Арифметические команды 30 1.5.3. Логические команды и команды сдвигов 35 1.5.4. Команды передачи управления . . . 39 1.5.5. Цепочечные команды 44 1.5.6. Команды управления микропроцессором 48 Глава 2. Арифметический сопроцессор К1810ВМ87 . . 49 2.1. Сопроцессорные конфигурации ...... 49 2.2. Внутренняя организация сопроцессора • . 53 2.3. Программная модель сопроцессора . . . • • 58 2.4. Форматы численных данных . . . . 64 2.5. Режимы работы л состояние .. 74 2.6. Система команд .......... 82 2.6.1. Особенности задания команд 82 2.6.2. Машинные форматы команд 84 2.6.3. Особенности программирования на языке ассемблера 86 2.6.4. Команды передач данных ...... 88 2.6.5. Арифметические команды 92 2.6.6. Команды сравнения . 100 2.6.7. Команды трансцендентных функций . 101 2.6.8. Команды загрузки констант 104 2.6.9. Команды управления 105 2.7. Взаимодействие сопроцессора и центрального процессора 110 2.8. Специальные числовые значения и особые случаи . 114 2.8.1. Веществшшые числа с нарушением нормализации 114 2.8.2. Нули и псевдонули 122 2.8.3. Бесконечности 122 2.8.4. He-числа 125 2.8.5. Неопределенности 126 2.8.6. Кодирование вещественных специальных числовых значений 127 2.8.7. Численные особые случаи 128 2.8.8. Обработка численных особых случаев . 129 205
Глава 3/ Программирование систем с сопроцессором 135 3.1. Элементарное программирование сопроцессора 135 3.2. Логарифмирование 145 3.3. Возведение в степень 147 3.4. Вычисление тригонометрических функций 150 3.5. Умножение матрицы на вектор 170 3.6. Регистрация ошибок вычислений 173 3.7. Особенности программирования сопроцессора в персональных компьютерах 175 3.7.1. Форматы численных данных 176 3.7.2. Общая организация ассемблерных подпрограмм и передача параметров 180 3.7.3. Примеры ассемблерных подпрограмм . . . 191 Приложение. Система команд арифметического сопроцессора К1810ВМ87 196 Список литературы 204
Производственно-практическое издание ГРИГОРЬЕВ ВЯЧЕСЛАВ ЛЕОНИДОВИЧ Архитектура и программирование арифметического сопроцессора Редактор издательства Л. Н. Гусяцкая Художественный редактор Т. А. Дворецкова Технический редактор Н. В. Чиранова Корректор Е. В. Кудряшова ИБ № 3526 Сдано в набор 15.01.91. Подписано в печать 09.04.91. Формат 84X1081/2, Бумага типографская Гарнитура литературная. Печать высокая. Усл. печ. л. 10.92. Усл. хр.-втт. 11,13. •Уч.-изд. л. 11,24. Тираж 20 000 эха. Заказ № 723. Цева 1 р-, 50 к. Энергоатомиадат, 113114, Москва, М-114, Шлюзовая на б., .10 Владимирская типография Госкомпечати СССР 600000, г. Владимир, Октябрьский проспект, д. 7.