## Тема 7. Уровень архитектуры команд

Исторически уровень архитектуры команд развивался раньше других и сначала был единственным. В наши дни этот уровень называют «архитектурой» машины. Уровень архитектуры команд имеет особое значение: он является связующим звеном между аппаратным и программным обеспечением.

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

Когда появляется новая машина, первые вопросы, который задает покупатель: «Совместима ли машина с предыдущими версиями?», «Могу ли я установить мою старую операционную систему?» и «Будут ли работать старые программы?». Покупатели редко рвутся выбросить старое ПО и заняться разработкой нового с нуля.

Этот факт заставляет разработчиков сохранять один и тот же уровень команд в разных моделях и обеспечивать совместимость ПО (по крайней мере снизу вверх). Разработчики должны обеспечить совместимость на уровне команд, но они могут делать что угодно с аппаратным обеспечением. Таким образом возникает задача построения лучших машин но совместимых с предыдущими версиями.

Какую архитектуру команд можно считать хорошей?

1. Хорошая архитектура должна определять набор команд, которые можно эффективно реализовать в современной и будущей технике, что приводит к рентабельным разработкам на несколько поколений.

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

### 7.1 Общий обзор уровня архитектуры команд

#### 7.1.1. Свойства уровня команд

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

В связи с этим определением такие вопросы как программируется ли микроархитектура или нет, конвейеризирован компьютер или нет, является ли компьютер суперскалярным, не относятся к уровню архитектуры команд, однако знания об этом могут повысить эффективность разрабатываемых компиляторов.

Для одних архитектур уровень команд определяется формальным документом, который выпускается промышленным консорциумом, для других – нет. Например, для системы V9 SPARC и JVM имеются официальные определения. Цель такого официального документа – дать другим производителям выпускать машины данного типа, чтобы эти машины могли выполнять одни и те же программы и получать одни т те же результаты. В документе говорится, какая модель памяти используется, какие имеются регистры, какие действия выполняют команды, но не описывается микроархитектура.

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

Для уровня архитектуры набора команд процессора Pentium 4 такого документа нет, поскольку Intel не хочет, что бы другие производители выпускали микросхемы Pentium 4. Компания Intel даже обращалась в суд, что бы запретить производство своих микросхем другим производителем, но проиграла процесс.

Другое важное качество уровня архитектуры команд состоит в том, что в большинстве машин поддерживается по крайней мере два режима:

1. В привилегированном режиме запускается операционная система. Этот режим позволяет выполнять все команды.

2. Пользовательский режим предназначен для запуска прикладных программ. Он не позволяет запускать некоторые потенциально опасные программы.

#### 7.1.2. Модели памяти

Во всех компьютерах память разделена на ячейки, которые имеют последовательные адреса. В настоящее время наиболее распространены ячейки в 8 разрядов (1 байт). Причиной применения байта – ASCII-символ, который занимает 7 разрядов и бит четности. Если в будущем будет доминировать кодировка UNICODE, то ячейки, возможно, станут 16-разрядными (24 лучше, чем 23).

Байты обычно группируются в слова по 4 или 8 байт. Многие архитектуры требуют, чтобы слова были выровнены. При этом память работает более эффективно.

Большинство машин имеет единое адресное пространство. В некоторых машинах содержатся отдельные адресные пространства для команд и данных. Такая система гораздо сложнее, чем единое адресное пространство, но зато она имеет два преимущества:

1. Появляется возможность иметь 232 байтов для программы и 232 байтов для данных при размере регистра адреса в 32 разряда;

2. Исключается сама возможность интерпретировать код как данные и наоборот.

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

#### 7.1.3. Регистры

Во всех компьютерах имеется несколько регистров, которые видны на уровне архитектуры команд. Они нужны для хранения промежуточных результатов, для контроля выполнения программы и для других целей.

Регистры уровня команд можно разделить на две категории: специальные регистры и регистры общего назначения. Специальные регистры включают счетчик команд, указатель стека, а также другие регистры с особой функцией. Регистры общего назначения содержат ключевые локальные переменные, и промежуточные результаты. Их основная функция – обеспечить быстрый доступ к часто используемым данным (избегать обращений в память). Машины RISC с высокоскоростным процессором обычно содержат минимум 32 регистра общего назначения, и их количество постоянно растет.

В некоторых машинах все регистры взаимозаменяемы, в некоторых регистры общего назначения могут быть специализированы. Например, в Pentium 4 регистр EDX может использоваться в качестве регистра общего назначения, но который получает половину произведения и содержит половину делимого при делении.

Кроме регистров, доступных на уровне команд, всегда существует довольно большое количество регистров, доступных только в привилегированном режиме. Эти регистры контролируют различные блоки кэш-памяти, основную память, устройства ввода/вывода и другие элементы аппаратного обеспечения.

Существует регистр, который представляет собой «гибрид», доступный и в пользовательском и в привилегированном режимах. Это регистр PSW (Program State Word – слово состояния программы, который еще называют флаговым. Флаговый регистр содержит различные биты, необходимые центральному процессору. Самые важные из них – коды условий. Они устанавливаются в каждом цикле АЛУ и отражают состояние результата предыдущей операции:

1. N – результат отрицательный (Negative);

2. Z – результат равен нулю (Zero);

3. V – переполнение (Overflow)

4. C – перенос самого левого бита (Carry Out);

5. F – перенос бита 3 (Auxiliary carry – служебный перенос);

6. P – результат четный (Parity).

Флаговый регистр хранит не только коды условий, его содержимое в каждой машине может быть разным. Флаговый регистр обычно читается в пользовательском режиме, но некоторые поля могут записываться только в привилегированном режиме.

### 7.2. Общий обзор уровня команд машины Pentium 4

Процессор Pentium 4 развивался на протяжении многих лет. Основная архитектура команд обеспечивает выполнение программ, написанных для 8086 и 8088, а в машине даже содержатся элементы 8-разрядного процессора 8080. На процессор 8080, в свою очередь сильно повлияли требования совместимости с процессором 8008, который был основан на процессоре 4004 (4-битная схема).

Pentium 4 имеет 3 операционных режима, в двух из которых он работает как 8086.

Real Address Mode – режим реальной адресации (или просто реальный режим), полностью совместим с 8086. В этом режиме возможна адресация до 1 Мб физической памяти.

Существенным дополнением является Virtual 8086 Mode – режим виртуального процессора 8086. Этот режим является особым состоянием задачи защищенного режима, в котором процессор функционирует как 8086. На одном процессоре в таком режиме могут параллельно выполняться несколько задач с изолированными друг от друга ресурсами. При этом использование физического адресного пространства памяти управляется механизмами сегментации и трансляции страниц. Попытки выполнения недопустимых команд, выхода за пределы отведенного пространства памяти контролируются системой защиты. Когда пользователь WINDOWS начинает работу с MS-DOS, программа, которая действует под DOS, запускается в виртуальном режиме, чтобы программа WINDOWS не могла вмешаться.

Protected Virtual Address Mode – защищенный режим виртуальной адресации (или просто защищенный режим). В этом режиме процессор позволяет адресовать до 4 Гб физической памяти. В этом режиме доступны 4 уровня привилегий.

#### 7.2.1. Регистры

В Pentium имеется 31 регистр; они подразделяются на 16 регистров прикладного программиста (пользовательские регистры) и 15 регистров системного программиста (системные регистры).

Пользовательские регистры процессора изображены на рис. 7.2.

Регистры общего назначения по сути являются расширением 16-ти разрядных регистров, например EAX есть расширение AX, причем доступ к старым 16-ти разрядным и 8-ми разрядным частям регистра типа (AH) сохраняется. Роль регистров общего назначения сохранилась из 8086 и подробно на них останавливаться не будем.

В общем, каждый сегментный регистр определяет сегмент (т.е. блок смежных ячеек) памяти. Если в процессоре 8086 содержимое сегментного регистра прямо задает физический базовый адрес сегмента и максимальный размер всех сегментов составляет 64 Кбайт, то в процессорах 286 и старше содержимое сегментного регистра определяет сегмент косвенно, через так называемую дескрипторную таблицу (descriptor table). С помощью дескрипторной таблицы для каждого сегмента задаются базовый адрес, размер (limit) и право доступа (access rights), показывающие, какие программы и в каких операциях могут обращаться к конкретному сегменту. Производить прямые обращения по физическим адресам памяти программист не может.

Записываемые в сегментный регистр слова (16 бит) называют селекторами (selector), поскольку оно выбирает или «селектирует» один из сегментов из множества возможных.

Указатель команды EIP\IP предназначен для адресации команд внутри текущего сегмента кода.

Регистр флажков EFLAGS\FLAGS содержит флажки, которые подразделяются на восемь флажков состояния и шесть управления. Формат регистра приведен на рис. 7.3 (флажки управления помечены *, а флажки состояния – ^).

31

15

7 0

Аккумулятор

База

Счетчик (для сдвигов)

Данные

(в/вв – содержится адрес порта)

Указатель стека

Указатель базы

Индекс источника

Индекс получателя

EAX AX |
| AH | AL |
EBX BX
| BH | BL
ECX CX
| CH | CL
EDX DX | Регист-ры общего назначе-ния
| DH | DL
31 | 15 | 7 0
ESP
| SP
EBP
| BP
ESI
| SI
EDI
| DP
| 15 | 7 0 |  |

CS

Сегмент кода

Сегмент стека

Сегмент данных

Доп. сегмент данных

Доп. сегмент

Доп. сегмент

сегмент-ные регистры

| SS
| DS
| ES
| FS
| GS
31 | 15 | 7 0 |  |
EIP |  | указатель команды
| IP
31 | 15 | 7 0 |  |
EFLAGS |  | регистр флажков
| FLAGS

Рис. 7.2

31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ID | VIP | VIF | AC | VM | RF
|  |  |  |  |  |  |  |  |  | * | * | * | * | * | *

15 | 14 | 13 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
0 | NT | IOPL | OF | DF | IF | TF | SF | ZF | 0 | AF | 0 | PF | 1 | CF
| ^ | ^ | ^ | * | * | * | ^ | ^ |  | ^ |  | ^ |  | ^

Рис. 7.3

Биты 31-22, 15, 5, 3, 1 зарезервированы. При записи в эти биты должны устанавливаться в предварительно прочитанное состояние.

##### Флаги состояния:

1. CF (Carry Flag) – флажок переноса (бит 0). Этот бит устанавливается в единицу, если арифметическая операция вызвала перенос или заем из старшего бита результата. Программно доступен.

2. PF (Parity Flag) – флажок четности (бит 2). Флажок устанавливается в единицу, если младшие восемь бит результата содержит четное число единичных бит.

3. AF (Auxiliary carry Flag) – флажок вспомогательного переноса (бит 4). Устанавливается в единицу, если арифметическая операция вызвала перенос или заем из младшей тетрады. Главное применение флажка связано с десятичной арифметикой. Программно не доступен.

4. ZF (Zero Flag) – флажок нуля (бит 6). Устанавливается в единицу, если результат операции равен нулю.

5. SF (Sing Flag) – флажок знака (бит 7). Большинство команд устанавливает этот флажок в тоже состояние, что и старший бит результата.

6. OF (Overflow Flag) – флажок переполнения (бит 11). Устанавливается в единицу, если в арифметических операциях со знаковыми операндами результат превышает допустимый диапазон.

7. IOPL (Input / Output Privilege Level) – уровень привилегий ввода\вывода (биты 12 и 13). Это поле содержит два бита и показывает минимальный уровень привилегий для данной задачи. Более подробно будет рассмотрено в теме о системе защиты.

8. NT (Nested Flag) – флажок вложенной задачи (бит 14). Более подробно будет рассматриваться при изучении многозадачности. Используется для контроля за прерванными задачами и при вызове процедур.

##### Флаги управления.

1. TF (Trap Flag или Trace Flag) – флажок покомандной работы (бит 8). Если он установлен в 1, то после выполнения каждой команды генерируется внутреннее прерывание. Используется для отладки программ.

2. IF (Interrupt Flag) – флажок прерывания (бит 9). Если он установлен в единицу, то внешние прерывания разрешены по входу INTR. Флажок не влияет на прерывания по входу NMI.

3. DF (Direction Flag) – флажок направления (бит 10). Задает направление обработки цепочек. Доступен программисту.

4. RF (Resume Flag) – флажок возобновления (бит 16). Если флажок установлен в 1 можно маскировать некоторые особые случаи в отладке программы.

5. VM (Virtual Mode) – флажок виртуального режима (бит 17).

6. AC (Alignment Check) – флажок контроля выравнивания (бит 18). Если от установлен в 1, то разрешен контроль выравнивания. Рассматривать не будем.

7. VIF (Virtual Interrupt Flag) – флаг виртуального прерывания (бит 19, Pentium). Используется в специальном расширенном режиме обработки прерываний, является виртуальным подобием флага IF. Применяется совместно с флагом VIP и позволяет обеспечивать нормальное функционирование устаревшего ПО.

8. VIP ((Virtual Interrupt Pending) – ожидание виртуального прерывания (бит 20 Pentium).

9. ID (Id Flag) – флаг доступности команды идентификации CPUID (бит 21, Pentium). Если программа или процедура способна установить или сбросить этот флаг, значит команда CPUID поддерживается.

Системные регистры GDTR, LDTR, IDTR предназначены для хранения базовых адресов таблиц дескрипторов. Их еще называют регистрами управления памятью. Они определяют местонахождение структур данных, управляющих сегментацией памяти. Регистр задачи TR применяется для слежения за тем, какая задача выполняется процессором в данный момент.

Для доступа к системным регистрам используются команды: LGDT, SGDT, LLDT, SLDT, LIDT, SIDT.

Регистр глобальной дескрипторной таблицы GDTR имеет длину 48 бит. Содержит 32 битный (для 286 –24-битный) базовый адрес и 16-битный предел.

47 | 15 | 0 |
Линейный базовый адрес | Предел | GDTR |

Рис. 7.4

Регистр локальной дескрипторной таблицы LDTR Видимая часть (которую можно программно читать и изменять) 10-байтного регистра содержит 16-разрядный селектор дескриптора LDT. Сам дескриптор LDT (базовый адрес, предел, атрибуты) автоматически загружается в скрытую часть LDTR из глобальной таблицы дескрипторов. Формат LDTR:

0 | 15 |  |
Селектор |  |  | База | Предел | Атрибуты |
|  | программно недоступно, загружается автоматически

Рис. 7.5

Регистр таблицы дескрипторов прерываний содержит 32-битный (для 286 – 24-битный) базовый адрес и 16-битный предел. Формат регистра:

47 | 15 | 0 |
Линейный базовый адрес | Предел | IDTR |

Рис. 7.6

Регистр задачи TR. Видимая часть регистра содержит 16-битный селектор дескриптора сегмента состояния задачи (TSS). Сам дескриптор TSS загружается автоматически в скрытую часть TR из глобальной таблицы дескрипторов. Формат регистра задачи совпадает с форматом регистра локальной дескрипторной таблицы.

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

Доступ к управляющим регистрам возможен с помощью команд MOV CR, SMSW, LMSW, CLTS (очистить флаг переключени якоманд).

Регистр CR0. Первые 16 бит – слово состояния машины. Биты NE, WP, AM, GW, CD были введены в регистр начиная с Intel486.

31 | 30 | 29 | 28 | 19 | 18 | 17 | 16 | 15 | 6 | 5 | 4 | 3 | 2 | 1 | 0
PG | CD | GW | *......* | AM | * | WP | * ... * | NE | ET | TS | EM | MP | PE
| MSW (Слово состояния машины I286)

Рис. 7.7

PE (разрешение защиты, бит 0) – предназначен для переключения процессора (реальный/защищенный режим). PE=0 – режим реальной адресации, PE=1 – защищенный режим.

MP (слежение за сопроцессором, бит 1) – Если сопроцессор не установлен, то этот бит должен быть равен 0. Для процессоров со встроенным сопроцессором бит должен быть установлен в 1.

EM (эмуляция сопроцессора, бит 2) – предназначен для генерации особой ситуации для всех команд сопроцессора. При отсутствии сопроцессора флаг должен быть установлен. Для выполнения команд MMX – сброшен.

TS (задача переключена, бит 3) –устанавливается при каждом переключении задачи. Вызывает ситуацию исключения при выполнении команд сопроцессора, ММХ/3Dnow!, SIMD. Предназначен для исключения выполнения этих команд над данными, оставшимися от других задач. Команда CLTS очищает этот бит.

ET (тип сопроцессора, Intel 386, 486) – при ET =1 используется 32-битный протокол, а при ET=0 16 битный. В процессорах Pentium считается зарезервированным.

NE (ошибка сопроцессора, бит 5, Intel486) – в зависимости от того, как установлен этот бит происходит обработка ошибок сопроцессора: либо как внешнее прерывание, либо как внутреннее.

Механизмы реакции различных моделей процессоров и сопроцессоров на возникновение исключительных прерываний могут изменяться для различных моделей. (СМ. тех. описание)

WP (защита записи, бит 16, Intel 486 ...) – защищает страницы пользовательского уровня (определенные только для чтения) от записи программой–супервизором, работающей на более высоком уровне привилегий. Если WP=0, то супервизор может осуществлять запись в пользовательские страницы, защищенные от записи.

AM (маска выравнивания, бит 18, Intel486 ...) – если бит сброшен – контроль запрещен, а если установлен (совместно с флагом AC), то генерируется особая ситуация контроля выравнивания.

NW (запрет сквозной записи, бит 29, Intel486 ...) – предназначен для управления встроенной кэш-памятью.

CD (разрешение работы кэш-памяти, бит 30, Intel486 ...) – если СВ =0, то работа внутренней кэш-памяти разрешена, в противном случае – запрещена.

PG (включение страничного механизма, бит 31, Intel386...) – если PG=1, то страничный механизм включен, иначе –выключен. Используется только в защищенном режиме. Если этот бит установить в реальном режиме, то будет генерироваться ошибка общей защиты.

Регистр CR1 – зарезервирован.

Регистр CR2. Если включен механизм страничной адресации и генерируется особая ситуация (страничная ошибка), то в этом регистре будет полный 32-разрядный адрес, поступление которого в блок страничной адресации вызвало ошибку.

Регистр CR3. При включенном страничном механизме (CR4.PAE=0) регистр CR3 (20 старших бит) содержат 20 старших бит физического адреса каталога страниц. Младшие 12 принимаются равными нулю. Начиная с процессора 486 используются еще два бита этого регистра (PWT и PCD), управляющие кэшированием. В процессорах (Pentium ...), которые поддерживают расширение физического адреса (CR4.PAE=1), в режиме расширенного адреса уже 27 разрядов содержат адрес таблицы указателей на каталоги страниц. Младшие 5 разрядов полагают равными 0.

PWT (сквозная запись страниц, бит 3, Intel486 ...) – используется для управления кэшированием страниц.

PCD (запрещение кэширование страниц, бит 4, Intel486 ...) – используется для управления кэшированием текущего каталога страниц.

| 31 |  | 3 | 4 |  |  |
| Физ. адрес каталога страниц |  |  | PSD | PWT |  | CR3 |

Рис. 7.8

Регистр CR4. Обеспечивает включение/выключение самых разнообразных режимов и дополнительных возможностей процессора. Впервые был использован в процессоре Pentium. Различные модификации процессора обеспечивают различные наборы возможностей. Поэтому перед программированием любых битов этого регистра следует с помощью команды CPUID проверить наличие возможностей для конкретной модификации процессора.

WME (расширение виртуального 8086 режима, бит 0, Pentium ...)

PVI (виртуальные прерывания защищенного режима, бит 1, Pentium ...)

TSD (ограничение маркера времени бит 2, Pentium ...)

DE (расширение отладки бит 3, Pentium ...)

PSE (расширение размера страниц, бит 4, Pentium ...) Если бит установлен в 1, то разрешает использование страниц расширенного размера (4 или 2 Мб) в зависимости от текущей разрядности физического адреса. В противном случае размер страниц ограничен 4 Кб.

PAE (расширение физического адреса, бит 5, Pentium Pro ...) – если бит установлен в 1, то разрешено использование 36-битной физической адресации.

MCE (расширение контроля машины, бит 6, Pentium ...)

PGE (разрешение глобальных страниц, бит 7, Pentium Pro...)

PCE (разрешение счетчика производительности, бит 8, Pentium Pro ...) – предназначен для разрешения мониторинга производительности в пользовательских программах.

OSFXSR (использование команд быстрого охранения/восстановления, бит 9, Pentium II...) используется для быстрого восстановления/сохранения состояния FPU/MMX/SIMD.

OSXMMEXCPT (разрешение особой ситуации SIMD, бит 10, Pentium III...) – управляет реакцией процессора на SIMD-исключения.

##### Отладочные регистры

Регистры отладки DR0 –DR3 содержат линейные адреса четырех точек останова. Регистры DR4, DR5 – зарезервированы.

DR6 содержит информацию о том, какая из точек останова вызвала особую ситуацию отладки.

DR7 устанавливает режимы срабатывания точек отладки; служат целям отладки.

Регистры TR6, TR7 для работы с кэш–памятью.

##### Регистры FPU

Первые процессоры архитектуры х86 не поддерживали напрямую вычисления с плавающей точкой. Фирмой Intel выпускались отдельные устройства (микросхемы), именуемые сопроцессором (8087, 80287, 80387), реализующие такие вычисления. Сейчас FPU встраивается в сам процессор. Тем не менее, поскольку в х86 сопроцессор представляет собой отдельное устройство, необходимо представлять специфику его работы.

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

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

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

FPU x86 опирается на стековую организацию, особенности и преимущества которой уже обсуждались. Программная модель FPU представлена на рис. 7.9.

Основу программной модели составляет регистровый стек из 8 80-разрядных регистров R0–R7, называемых также численными или арифметическими регистрами. В них хранятся числа в так называемом расширенном вещественном формате. В любой момент трехразрядное поле TOP (top of stack) в слове состояния SW определяет регистр, являющейся вершиной стека и обозначаемый ST(0) или ST. Пример приведен на рис. 7.10. Здесь вершина стека R3 (ST(0)), регистр R4 –это ST(1), регистр R2 в самом низу стека и обозначается ST(7). Команды в FPU рассчитаны на такую относительную адресацию.

Операция загрузки в стек декремент поля TOP и загружает данные в новую вершину, извлечение из стека действует наоборот.

Особенностями этого регистрового стека является следующее: стек имеет кольцевую структуру; контроль использования стека должен осуществлять сам программист; в командах допускается явное и неявное обращение к регистрам стека с модификацией и без модификации поля TOP.

ТЭГИ

| 79 |  | 63 | 0 | 1 | 0
R0 | S | E | M |  |  |
R1 |  |  |
R2 |  |  |
R3 |  |  |
R4 |  |  |
R5 |  |  |
R6 |  |  |
R7 |  |  |
| 15 | 0 |
CW | регистр управления |
SW | регистр состояния
TW | Слово ТЭГов |
| 47 | 0 |
IP | указатель команды
DP | указатель данных

Рис. 7.9

С каждым регистром стека ассоциируется двухбитный тег (признак) совокупность которых образует слово тегов TW. Тег регистра R0 находится в младших битах этого слова, а тег регистра R7 – в старших. Тег в общем виде показывает, что содержится в соответствующем регистре:

1. 00 – допустимое ненулевое число;

2. 01 – нуль;

3. 10 – специальное значение (о них позже);

4. 11 – пустой регистр.

При своей инициализации FPU записывает 11 во все теги регистров, отмечая регистры как пустые. Попытка обращения к такому регистру вызывает особый случай (прерывание). Регистры CW, SW будут рассмотрены позже; регистры IP и DP используются в процедурах при обработке особых случаев.

Устройство FPU имеет два программно–доступных 16-разрядных регистра, содержимое которых определяет режим его работы и текущее состояние. Регистры представлены на рис. 7.11.

| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
CW | x | x | x | x | R | C | P | C | x | x | PM | UM | OM | ZM | DM | IM
SW | B | C3 | T | O | P | C2 | C1 | C0 | ES | SF | PE | UE | OE | ZE | DE | IE

Рис.7.11

Слово управления CW. Определяет для FPU варианты обработки численных данных. Шесть младших разрядов представляют собой индивидуальные маски особых случаев, т.е. необычных и ошибочных ситуаций, обнаруживаемых устройством FPU при выполнении программы. К битам маски относятся:

1. PM – маска точности (истинный результат операции не представим в формате получателя;

2. UM – маска анти переполнения;

3. OM – маска переполнения:

4. ZM – маска деления на ноль;

5. DM – маска денормализованного операнда;

6. ID – маска недействительной функции.

Если любой из этих бит установлен в состояние 1, то возникновение соответствующего особого случая не будет вызывать прерывания процессора; в противном случае – будет.

Поясним понятие недействительной операции — сюда могут относиться корень квадратный из отрицательного числа и т.д.

Управление точностью. Поле PC (2 байта) определяет точность вычислений 24 бита (PC = 00), 53 бита (10) и 64 бита (11). По умолчанию используется 64 бита.

Управление округлением. Устройство FPU имеет четыре режима округления, выбираемые полем RC слова управления:

00 – округление к ближнему;

01 – округление вниз (к -∞);

10 – округление вверх (к +∞);

11 – усечение (к 0).

По умолчанию принимается округление к ближнему.

Слово состояния SW. Занимает 16 бит и отражает общее состояние устройства FPU. В слове состояния SW младшие 6 бит отведены для регистрации особых случаев; назначение этих бит аналогично слову CW. При обнаружении любого из незамаскированных особых случаев устройство FPU устанавливает в состояние 1 соответствующий флажок и вызывает прерывание ЦП.

Бит SF нарушения стека предназначен для того, чтобы регистрировать ошибки в работе регистрового стека. Устройство FPU устанавливает его в состояние 1, если команда вызывает переполнение стека (особый случай недействительной операции).

Биты C0–C3 кода условия похожи на арифметические флажки центрального процессора в регистре EFLAGS. Они регистрируют особенности результатов команд сравнения. Эти биты, в основном, применяются для условных переходов. Команда FSTSW AX передает слово состояния в регистр AX. Затем командой SAHF модно переместить биты C0 –C3 и биты флажков.

Трехадресное поле вершины стека TOP показывает, какой из внутренних регистров данных является текущей вершиной стека.

Бит B занятости служит для совместимости с 8087 (совпадает с ES).

#### 7.2.2. Технология MMX

Технология MMX ориентирована на приложения мультимедиа, 2D/3D-графику и коммуникации. Это расширение базовой архитектуры появилось только после второго поколения процессоров Pentium. Основная идея ММХ заключается в одновременной обработке нескольких элементов данных за одну инструкцию —технология SIMD (Single Instruction–Multiple Data). Расширение ММХ использует новые типы упакованных целочисленных данных:

1. упакованные байты (Packed Byte) –восемь байт;

2. упакованные слова (Packed word)–четыре слова;

3. упакованные двойные слова (Packed doubleword)–два двойных слова;

4. учетверенное слово (Quadword)–одно слово.

Эти типы данных специальным образом могут обрабатываться в регистрах ММХ0–ММХ7, представляющие собой младшие биты стека 80–битных регистров FPU. Эти регистры, также как и регистры FPU не могут быть использованы для адресации памяти. Совпадение регистров ММХ и FPU накладывает ограничения на чередование кодов ММХ и FPU. Частое чредование кодов ММХ и FPU снижает производительность за счет необходимости сохранения и восстановления весьма объемного контекста FPU – и забота об этом лежит на программисте.

Еще одна особенность технологии ММХ – поддержка арифметики с насыщением (при переполнении фиксируется максимально/минимально допустимое число). Граничные значения определяются типом данным.

В систему команд введено дополнительно 57 инструкций для одновременной обработки нескольких единиц данных. Одновременно обрабатываемое 64-битное слово может содержать как одну единицу обработки, так и 8 однобайтных, 4 двухбайтных или 2 четырехбайтных операнда.

Новые инструкции включают следующие группы:

1. арифметические (+,- в различных режимах, умножение, комбинацию умножения и сложения);

2. сравнение элементов данных;

3. преобразование форматив;

4. логические, выполняемые на 64-разрядными кодами;

5. сдвиги (арифметические и логические)

6. пересылки данных между регистрами ММХ и целочисленными регистрами и памятью;

7. очистка ММХ – установка признаков пустых регистров в слове ТЕГов.

Регистры ММХ в отличие от регистров FPU адресуются физически, а не относительно указателя стека ТОР. Любая инструкция ММХ обнуляет поле ТОР регистра состояния FPU. В слове ТЕГов свободному регистру соответствует комбинация 11, а все остальные комбинации соответствуют занятому регистру. После каждой операции ММХ биты ТЕГов используемого регистра обнуляются. Неиспользуемые в ММХ биты (79-64) регистров FPU заполняются единицами, поэтому ошибочное использование данных ММХ инструкциями FPU приведет к исключению. Команда EMMS предназначена для предназначена для очистки контекста ММХ т.е. помечает все регистры как пустые.

Наличие поддержки ММХ определяется по биту 23 регистра EDX после вызова инструкции CPUID(1).

Технология 3DNow! введена фирмой AMD в процессорах K6–2, расширяет возможности ММХ. Она позволяет оперировать с новым типом данных – парой упакованных чисел в формате с плавающей точкой. Эти числа занимают по двойному слову в 64-разрядных регистрах ММХ. Процессор К6–2 имеет два исполнительных блока, которые способны одновременно выполнять операции с плавающей точкой над своими регистрами. Каждая такая операция занимает всего два такта, операции полностью конвейеризируются. Таким образом, с конвейеров процессора за каждый такт могут сходить четыре результата операций с плавающей точкой. В систему команд добавлена 21 новая инструкция ММХ, большая часть которых предназначена для обработки упакованных чисел с плавающей точкой. Имеется также новая целочисленная ММХ инструкция для усреднения 8 пар 8-битных чисел. Имеется команда быстрого переключения FPU-MMX. Технология 3Dnow! программно совместима с прежними процессорами и операционными системами, поскольку регистры ММХ отображаются на регистры FPU и для них работают механизмы сохранения контекста в многозадачных ОС.

Поддержка 3Dnow! определяется по биту 31 регистра EDX после вызова CPUID(8000_0001h).

#### 7.2.3. Регистры SIMD

В процессорах, начиная с Pentium III, возможно использование специального архитектурного расширения, предназначенного для потоковой обработки данных. Это расширение включает дополнительный набор команд, дополнительные режимы генерации ошибок и исключений, дополнительные внутренние регистры и форматы данных, воспринимаемые процессором. Данное расширение – усовершенствование команд мультимедийной обработки ММХ.

Доступ ко всем SIMD–регистрам возможен только с помощью новых SIMD–команд. Перед использованием данного расширения ПО должно с помощью команды CPUID проверить, поддерживается ли оно конкретной моделью микропроцессора.

Регистры общего назначения SIMD Восемь регистров общего назначения (ХММ0 …ХММ7) вводятся в процессор Pentium III … для использования командами потоковой обработки. В отличие от ММХ-регистров, эти регистры не являются отображаемыми – это новые физические регистры, доступ к которым осуществляется с помощью новых команд. Поэтому при совместном использовании команд SIMD, FPU, MMX не возникает никаких проблем. Регистры ХММ0 … ХММ7 могут использоваться только для хранения данных, но не для косвенной адресации.

### 7.3. Общий обзор архитектуры уровня команд системы UltraSPARC III

Архитектура SPARC была впервые введена в 1987 г. и была первой архитектурой промышленного назначения типа RISC. Изначально она была 32-разрядной, но UltraSPARC III – это 64-разрядная машина.

Структура памяти проста: память представляет собой линейный массив из 264 байтов. Память настолько велика, что в настоящее время она не реализуема. Современные реализации имеют размер адресного пространства 244 (UltraSPARC III), но в будущем память будет увеличиваться.

Одна из проблем разработки архитектуры заключается в том, что архитектура команд ограничивает размер адресуемой памяти.

Архитектура команд SPARC достаточно проста, хотя организация регистров усложнена для повышения эффективности вызова процедур.

В системе UltraSPARC имеется две группы регистров: 32 64-битных регистров общего назначения и 32 регистра с плавающей точкой. Варианты названий регистров приведены в таблице 7.1.

Таблица 7.1

##### Регистр

Вариант названия

##### Функция

R0 | GO | Связан с 0. Все, что сохраняется в этом регистре, просто игнорируется
R1- R7 | G1—G7 | Содержит глобальные переменные
R8 – R13 | O0 – O5 | Содержит параметры вызываемой процедуры
R14 | SP | Указатель стека
R15 | O7 | Временный регистр
R16 – R23 | L0 – L7 | Содержит локальные переменные для текущей процедуры
R24 – R29 | I0 – I5 | Содержит входные параметры
R30 | FP | Указатель на основу текущего стекового фрейма
R31 | I7 | Адрес возврата для текущей процедуры

В действительности процессор UltraSPARC имеет более 32 регистров общего назначения, но видимы для программиста только 32 в любой момент времени. Эта особенность, называемая «регистровыми окнами», предназначена для повышения эффективности вызова процедур. Идея состоит в том, что имеется несколько наборов регистров, точно также, как существует несколько фреймов в стеке. Ровно 32 регистра видны в текущий момент; регистр CWP (Current Window Pointer – указатель текущего окна) следит за тем, какой набор регистров используется в данный момент.

Команда вызова процедуры скрывает старый набор регистров и предоставляет новый набор, который может использовать вызванная процедура. Однако некоторые регистры из старого набора переносятся в новый. Система эффективна, если нет многократных вложений.

В системе UltraSPARC III также есть 32 разряда с плавающей точкой, которые могут содержать либо 32-битные (одинарная точность), либо 64-битные (двойная точность) значения. Предусмотрена возможность использования пары регистров для поддержания 128-битных значений.

Архитектура UltraSPARC III – это архитектура загрузки/хранения. Это значит, что единственные операции, которые обращаются в память – это операции записи и чтения, служащие для передачи данных между регистрами и памятью. Все операнды для команд арифметических действий должны браться из регистров или предоставляться самой командой, а все результаты должны сохраняться в регистрах.

### 7.4. Общий обзор микросхемы 8051

Микросхема 8051 умеет работать только в одном режиме, никаких аппаратных средств защиты не предусмотрено. На микросхеме никогда не выполняется больше одной программы. Модель памяти поддерживает два адресных пространства по 64 Кбайт для программ и данных. Эти пространства разделены, что позволяет реализовать пространства программ в ПЗУ, а пространство данных – в ОЗУ.

Допускается несколько вариантов реализации памяти. В простейшем варианте предусматривается 4 Кбайт ПЗУ для программ и 128 байт ОЗУ для данных. Вся память размещается в одном корпусе с микросхемой.

В модели 8051 емкость обоих модулей увеличена вдвое: 8 Кбайт ПЗУ и 256 байт ОЗУ. В случае использования этой модели программа записывается в ПЗУ на этапе производства и пользователю недоступна.

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

Поддерживается также промежуточная модель, в которой 4 Кбайт ПЗУ и 128 байт ОЗУ размещаются в одном корпусе с микросхемой, а остальная память – вне микросхемы.

Рассмотрим механизм работы с регистрами. Большинство программ 8051 составляются с расчетом на 8 8-ми разрядными регистрами. Существует 4 набора регистров, хотя в каждый конкретный момент времени активен только один из них. Активный регистр определяется значением поля в слове состояния программы (регистр PSW). Наличие нескольких наборов позволяет ускорить обработку прерываний, что существенно для систем реального времени.

Вторая особенность регистров заключается в том, что все они представлены в адресном пространстве памяти. Байты 0-7 соответствуют первому набору регистров, 8-15 – второму и т.д. до 31 байта (рис 7.12).

Память для программ | 4095 |
| C | A | ХХ | RS | O | XX | P | PSW
0 |
|  | IE | XX | E2 | ES | E1 | X1 | E0 | X0 | IE
Сверхоперативная память | 127 |
XX | XX | E2 | ES | E1 | X1 | E0 | X0 | IP
Память с побитовой адресацией | 48 |
O1 | R1 | O0 | R0 | E1 | T1 | E0 | T0 | TCON
4 банка регистров | 32 |
0 | Таймер 1 | Таймер 2 | TMOD

Рис. 7.12

Непосредственно над 4 банками регистров, по адресам 32-47 расположены 16 байт памяти с побитовой адресацией (0-127) В 8051 набор команд установки, сброса, логических операций для работы с этими битами. Специальные регистры:

1. PSW: бит переноса, бит служебного переноса, биты, определяющие набор регистров, бит переполнения, бит четности.

2. IE: позволяет включать/отключать прерывания вместе или по отдельности. Если бит IE =0, все прерывания отключены. Если IE=1, то модно включать/отключать прерывания, для которых установлены индивидуальные биты. Биты Е0, Е1, Е2 – для таймеров, ES – последовательные каналы, Х0, Х1 – прерывания от внешних источников.

3. IP: приоритет прерываний низкий или высокий. 1 – высокий приоритет.

4. TCON: регулирует главные таймеры. Биты О1 и О2 устанавливаются аппаратно в случае переполнения таймеров. Остальные – управление.

5. TMOD: определяет разрядность таймера (8, 13, 16 бит), переключает из режима реального времени в счетчик тактов и т.п.

Все упомянутые регистры, а также другие (сумматор, порты ввода/вывода) расположены в диапазоне памяти 128-255. Обращение к ним осуществляется также, как к регистрам R0-R7. Тогда, в процессорах с увеличенным объемом памяти возможно неоднозначное толкование адресов. В таких моделях для обращения к регистрам используется прямая адресация, а для обращения к ОЗУ – косвенная.

### 7.5. Типы данных

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

#### 7.5.1. Типы данных процессора Pentium 4

Таблица 7.2

Тип | 1 бит | 8 бит. | 16 бит. | 32 бита | 64 бита | 128 бита
Бит |  |  |  |  |  |
Целые числа со знаком |  | * | * | * |  |
Целые числа без знака |  | * | * | * |  |
Двоично-десятичные целые числа |  | * |  |  |  |
Числа с плавающей точкой |  |  |  | * | * |

Pentium 4 также может манипулировать 8-ми разрядными символами ASCII: существуют специальные команды для копирования и поиска цепочки символов. Эти команды используются и для цепочек, длина которых известна заранее, и для цепочек, в конце которых стоит специальный маркер. Эти операции часто используются в библиотеках операций над строками.

Операнды не обязательно должны быть выровнены в памяти, но если адреса слов кратны 4 (выравнивание по словам), то производительность повышается.

7.5.1.1. Типы данных FPU

Устройство FPU определяет численные данные в 7-ми внешних форматах, образуя при этом три класса:

1. двоичные числа – целые числа (16, 32, 64 разряда);

2. упакованные десятичные целые числа;

3. двоичные вещественные числа – 32, 64, 80 разрядов.

Целые числа представляются в дополнительном коде и могут занимать 16 бит (целое слово), 32 бита (короткое целое), 64 бита (длинное целое). Эти форматы существуют только в памяти, внутри FPU они автоматически преобразуются в 86-разрядный расширяемый вещественный формат.

Упакованные десятичные целые. Они представляются в прямом коде и упакованном формате, т.е. каждый байт содержит две десятичные цифры. Старший бит старшего разряда байта отведен для знака числа, остальные биты этого байта игнорируются. Длина этого формата –10 байт (80 бит). Опять же этот формат существует только в памяти.

Вещественные числа. Имеется три формата с плавающей точкой (одинарной точности ОТ, двойной точности ДТ, расширенной точности РТ). Значащие числа находятся в поле мантиссы, поле порядка показывает фактическое положение десятичной точки в разрядах мантиссы, а бит знака определяет знак числа (рис. 7.13).

|  |  | 7 0 | 23 | 0 |  |  |  |  |
32 р. | ОТ | S | E | M |  | M=24 | E=8 | E=+127; -126 | Cм=127
|  |  | 10 | 0 | 52 | 0 |  |  |  |
64 р. | ДТ | S | E | M | M=53 | E=11 | E=+1023;-1022 | Cм=1023
|  |  | 14 | 0 | 63 |  | 0 |  |  |  |
80 р. | РТ | S | E | 1 | M | М=64 | Е=15 | Е=+16383;-16382 | См=16383

Рис. 7.13

Порядок E задается в смещенной форме, он равен истинному порядку, увеличенному на значение смещения.

E = истинный порядок + смещение.

Значение числа с плавающей точкой равно:

(-1)S•2E-смещение•(F0).(F1)(F2) …(Fn),

где n = 23, 52, 63.

Устройство FPU обычно поддерживает представление мантиссы в нормализованной форме, т.е. старший бит равен 1. Следовательно, за исключением числа нуль мантисса состоит из целой части и дроби в следующем виде: 1.(F1)(F2)(F3) … (Fn), где Fi = 0 или 1.

В форматах ОТ и ДТ бит F0 при передаче чисел и хранении их в памяти не фигурирует. Это т.н. скрытый и неявный бит, который содержит 1. Следовательно, в этих форматах невозможно представить ненормализованные числа (за некоторым исключением). Кроме того, скрытый бит не позволяет представить в этих форматах нуль, и он должен кодироваться как специальное значение.

Числа в формате РТ имеют явный бит F0. Напомним, что внутри FPU числа хранятся только в этом формате. Перевод в другие форматы из них осуществляется автоматически.

В качестве примера рассмотрим представление числа –247.375 в вещественных форматах FPU.

-247.375 =>-11110111.011

Определяем истинный порядок. Он равен –7.

Смещенный порядок:

· для обычной точности: 7+127=134 è 1000 0110

· для двойной точности: 7+1023=1030 è100 0000 0110

· для расширенной точности: 7+16383=16390 è 100 0000 0000 0110.

Значения чисел:

· ОТ: 1 1000 0110 1110 1110 0110 00 ….00

· ДТ: 1 100 0000 0110 1110 1110 0110 00 ….00

· РТ:1 110 0000 0000 0110 1111 0111 0011 00…00.

Специальные значения. Форматы чисел допускают представление специальных объектов и значений. Для их представления зарезервированы значения смещенного порядка 000 … 0 и 111 … 1.

Денормализованные вещественные числа – это число, которое меньше минимального нормализированного числа для каждого вещественного формата. Такие числа имеют минимальный смещенный порядок 000 … 0 и ненулевую мантиссу, бит (F0) явный или неявный считается нулевым. Введены потому, что иногда промежуточные результаты вычислений могут принимать очень малые значения.

Истинный нуль. Нуль кодируется нулевым смещенным порядком и мантиссой. Нуль является знаковым (положительные или отрицательные нули).

Бесконечность. Поддерживается знаковое представление бесконечности. Это значение кодируется со смещенным порядком из всех единиц и мантиссой 1.000… . Знаки бесконечностей учитываются и сравнение возможно. Бесконечности интерпретируются так:

.

Нечисла. Обозначаются NaN (Not-a-Number). Оно имеет смещенный порядок из всех единиц, любой знак и любую мантиссу, за исключением 1.000… 0. В свою очередь могут делиться на типы. Возникают иногда как результат недействительных операций. Могут использоваться для отладки программ.

Неподдерживаемые форматы. Формат РТ имеет ряд двоичных наборов, не попадающих в рассмотренные классы. Они представляют устаревшие форматы, использовавшиеся в сопроцессоре 8087.

#### 7.5.2. Типы данных машины UltraSPARC III

Таблица 7.3

Тип | 1 бит | 8 бит. | 16 бит. | 32 бита | 64 бита | 128 бита
Бит |  |  |  |  |  |
Целые числа со знаком |  | * | * | * | * |
Целые числа без знака |  | * | * | * | * |
Двоично-десятичные целые числа |  |  |  |  |  |
Числа с плавающей точкой |  |  |  | * | * | *

Все операнды должны быть выровнены в памяти.

UltraSPARC представляет собой регистровую структуру, и почти все команды оперируют 64-разрядными регистрами. Символьные и строковые типы данных специальными командами аппаратного обеспечения не поддерживаются.

#### 7.5.3. Типы данных 8051

Количество типов данных строго ограничено. Поддерживается тип данных, не используемый в арифметических операциях – бит. Для работы с битами имеются специальные операции.

Таблица 7.4

Тип | 1 бит | 8 бит. | 16 бит. | 32 бита | 64 бита | 128 бита
Бит | * |  |  |  |  |
Целые числа со знаком |  | * |  |  |  |
Целые числа без знака |  |  |  |  |  |
Двоично-десятичные целые числа |  |  |  |  |  |
Числа с плавающей точкой |  |  |  |  |  |

### 7.6. Форматы команд

Команда – представляет собой код, определяющий операцию вычислительной машины и данные, участвующие в операции. Команда содержит также в явной или неявной форме информацию об адресе, по которому помещается результат операции и адрес следующей команды.

Код команды можно представить состоящим из нескольких частей или полей. Команда в общем случае состоит из операционной и адресной частей.

код операции

операционная адресная

часть часть

Рис. 7.14

Эти части, в свою очередь, могут состоять из нескольких полей.

Операционная часть содержит код операции (КОП), который задает вид выполняемой операции. Адресная часть команды содержит информацию об адресах операндов и результата операции, а в некоторых случаях информацию об адресе следующей команды.

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

Рассмотрим некоторые классические структуры команд.

Чтобы команда содержала в явном виде всю необходимую информацию о задаваемой операции, она должна содержать код операции и четыре поля адреса для указания ячеек памяти, содержащих два операнда, ячейки, в которую помещается результат операции и адрес следующей команды. Такой порядок выполнения называется принудительным, а приведенный формат команды является труднореализуемым и неэффективным и в настоящее время не применяется.

КОП | А1 | А2 | А3 | А4

Рис. 7.15

Очевидно, что в большинстве машин и большинстве случаев за командой, хранящейся по адресу K и занимающей L ячеек, будет выполняться команда, с адресом K+L . Такой порядок выработки команд называется естественным, и он нарушается только специальными командами. Тогда учитывать адрес следующей команды в явном виде нет необходимости и можно использовать трехадресную команду (рис. 4.14).

Операция, описываемая трехадресной командой, символически представляется в виде:

ОП[A3] := ОП[A1] *ОП[A2].

Можно условиться, что результат операции всегда помещается на место одного из операндов. Тогда получаем двухадресную команду, задающую операцию (рис. 7.14):

ОП[A1] := ОП[A1] *ОП[A2].

В одноадресной команде подразумеваемые адреса имеют уже и результат операции, и один из операндов (рис. 4.15.).

КОП | А1 | А2 | А3 |  | КОП | А1 | А2 |  | КОП | А1

Рис. 7.13. Рис. 7.14. Рис. 7.15.

Подразумеваемым операндом является в данном случае внутренний регистр процессора, называемый регистром результата или аккумулятором. Результат такой операции также записывается в аккумулятор:

Акк := Акк * ОП[А1].

Наконец, в некоторых случаях возможно использование безадресных команд, когда подразумеваются адреса обоих операндов и результата. Например, при использовании стековой памяти.

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

Обычно в ЭВМ используется несколько форматов различной длины. Рассмотренные структуры команд достаточно схематичны. В действительности адресные поля команд большей частью содержат не сами адреса, а только информацию об этих адресах. Способы адресации рассматриваются в следующем разделе.

#### 7.6.1. Критерии разработки для форматов команд

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

Если речь идет об одинаковых машинах, то лучше иметь короткие команды, чем длинные. Такие программы занимают в памяти меньше места. Но минимизация размера команд может усложнить их декодирование. Следовательно, достижение минимальной длины команды должно уравновешиваться временем, затрачиваемым на декодирование и выполнение команд.

Следующая причина минимизации длины команд связана с увеличением скорости работы процессора. Значительный рост скорости работы процессора не соответствует относительно низкой пропускной способности памяти. Трудности, связанные с пропускной способностью памяти имеют отношение не только к основной памяти, но и ко всем видам кэш-памяти.

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

Второй аспект разработки – достаточно большой объем пространства в формате команд для выражения всех требуемых команд.

(M – число команд).

История доказывает, что обязательно нужно оставлять большее количество свободных кодов операций для будущих дополнений к наборам команд.

Третий критерий связан с числом битов в адресном поле. Для адресации S ячеек памяти адресная часть одного операнда должна иметь число разрядов

Для адресации памяти требуется более длинные адреса. Одна крайность – это организация памяти, при которой адресуется каждый бит (Burroughs B1700). Другая крайность – это память, состоящая из очень длинных слов (например, серия CDC Cyber содержала 60-битные слова).

Кроме того, для упрощения аппаратуры и увеличения производительности ЭВМ желательно, чтобы длина формата команды была согласована с длиной машинных слов.

Современные компьютерные системы пришли к компромиссу, который в некотором смысле объединяет в себе худшие качества обоих вариантов. Он требует, чтобы адреса были у каждого байта, но при обращении к памяти всегда считывается одно, два, а иногда и четыре слова сразу. В результате считывания одного байта в машине UltraSPARC II сразу вызывается минимум 16 байтов, а иногда и строка кэш-памяти в 64 байта.

#### 7.6.2. Расширение кода операций

Наряду с обычными компромиссами между числом разрядов, отводимых под код операции и адресную часть при фиксированной длине команд, рассмотрим прием, который называется расширением кода операций. Суть приема заключается в том, чтобы увеличивать разрядность кода за счет изменения количества адресов в команде. Рассмотрим 16-битную команду:

| 16 бит |
4-битный код операции | 0000 0001 …. 1110 | Xxxx Xxxx …. xxxx | Yyyy Yyyy …. yyyy | Zzzz Zzzz …. Zzzz | 15 трехадресных команд
8-битный код операции | 1111 1111 …. 1111 | 0000 0001 …. 1101 | Yyyy Yyyy …. yyyy | Zzzz Zzzz …. zzzz | 14 трехадресных команд
12-битный код операции | 1111 1111 …. 1111 | 1110 1110 …. 1111 | 0000 0001 …. 1110 | Zzzz Zzzz …. zzzz | 31 трехадресная команда
16-битный код операции | 1111 1111 …. 1111 | 1111 1111 …. 1111 | 1111 1111 …. 1111 | 0000 0001 …. 1111 | 15 трехадресных команд

Рис. 7.16

Другой вариант расширения количества команд – использование команд различной длины. Предлагается делать часто используемые команды короткими, а редко используемые – длинными. Однако в этом случае возникает проблема с декодированием и выравниванием (например, Intel).

#### 7.6.3. Форматы команд процессора Pentium 4

Общий формат команды процессора приведен на рис. 7.17. Команда содержит следующие поля:

1. префиксы команды (необязательны),которые могут следовать в произвольном порядке;

2. одного или двух байт (главного) кода операции;

3. спецификатора адреса, представленного битами mod r/m и sib;

4. смещения в команде (displacement) – если необходимо;

5. поле непосредственного значения (если такое значение присутствует).

7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |  | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
mod | reg/коп | r/m |  | ss | index | base

Префиксы

повтор | размер адреса | размер операнда | замена сегмента |  | код операции | mod r/m | sib | смещение (в команде) | непосред. операнд
0 или 1 | 0 или 1 | 0 или 1 | 0 или 1 | 1 или 2 | 0 или 1 | 0 или 1 | 0,1,2 или 4 | 0,1,2 или 4
число байт | число байт

Байт 0 –код операции
код операции | D | W

Рис. 7.17

(Base – база, MODe – режим, Register/Memory – регистр/память, Scale – масштаб, Index – индекс).

Из всех полей команды обязательными являются только один или два байта кода операции.

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

1. префиксы команды (REP\REPE\REPZ\REPNE, применяется в строковых командах, для автоматической обработки всех элементов цепочки и блокировки шины (LOCK) – допускается перед некоторыми командами с обращением к памяти для запрета другим процессорам в мультипроцессорных системах);

2. замены сегмента (Segment override), явно определяет сегментный регистр для конкретной команды вместо сегментного регистра, принимаемого по умолчанию;

3. размера операнда (OperandSize), переключает 16– и 32–битные операнды;

4. размера адреса (AddressSize), коммутирует формирование 16– и 32–битных адресов.

По сравнению с 16-ти разрядными процессорами х86, начиная с I80386 система команд расширена в двух направлениях: во-первых, все команды, рассчитанные на 16-разрядные операнды работают и с 32–разрядными; во-вторых, доступны 32-разрядные режимы адресации. Такое расширение реализовано введением бита D (Default) в дескриптор сегмента кода и двух префиксов. Когда бит D установлен в 0, команды текущей программы работают с 16-разрядными данными и адресами, если D установлен в 1, то они работают с 32-разрядными данными и адресами.

Префиксы размера и адреса операнда заставляют процессор изменять для команды размеры операнда или адреса.

В большинстве команд вслед за байтом кода операции, который указывает местонахождение операнда в памяти, следует второй байт, который сообщает всю информацию об операнде. Эти 8 бит распределены в 2-битном поле mod и в двух 3-битных регистровых полях reg и r/m.

Рассмотрим поле reg. Это поле определяет один из регистров общего назначения. Кодирование этого поля зависит от того, имеется ли в КОП поле W (определяющее размер операнда), а при его наличии – от типа операнда. Это поле может находится в байте КОП и в байте mod r\m.

Режим адресации определяют один или два байта адресации, которые находятся после байта адресации. Первым является байт mod r/m, вторым байт sib (масштаб, индекс, база). Байт sib может присутствовать только в командах с 32-разрядной адресацией, когда байт mod r/m содержит r/m = 100 и значение в поле mod≠11.

Таблица 7.5

reg | поля W нет | Поле W есть
16 р | 32 р | 16 разрядов | 32 разряда
W=0 | W=1 | W=0 | W=1
000 | AX | EAX | AL | AX | AL | EAX
001 | CX | ECX | CL | CX | CL | ECX
010 | DX | EDX | DL | DX | DL | EDX
011 | BX | EBX | BL | BX | BL | EBX
100 | SP | ESP | AH | SP | AH | ESP
101 | BP | EBP | CH | BP | CH | EBP
110 | SI | ESI | DH | SI | DH | ESI
111 | DI | EDI | BH | DI | BH | EDI

#### 7.6.4. Форматы команд FPU

Особенности задания команд. Команды бинарных операций допускают несколько форм. В случае пустого поля операнда (безадресная команда) операция выполняется с двумя верхними элементами стека ST(0) и ST(1). Поcле выполнения операции осуществляется инкремент указателя стека и результат помещается в новую вершину стека, заменяя исходное содержание ST(1). Это классическая операция для машин со стековой адресацией.

Когда в бинарной операции определен один операнд, она выполняется с привлечением указанного в команде регистра (ячейки памяти) и содержимого вершины стека. Результат загружается в старую вершину стека и указатель стека не изменяется.

Если же в бинарной команде указаны два операнда, ими является содержимое двух регистров стека, причем одним из них будет ST(0), а вторым ST(i). Возможны три случая:

1. источникам является ST(0), а получателем ST(i);

2. источник – ST(i), получатель – ST(0);

3. источникам является ST(0), получателем ST(i) и производится инкремент указателя стека, т.е. «источник» пропадает.

Отметим, что в несимметричных операциях деления и вычитания обычно получатель делится на источник (из получателя вычитается источник). FPU допускает и обратные (Reverse) формы таких команд.

Многие команды допускают несколько форм задания операндов, которые при этом принято записывать через слэш «/», например

FADD //src/dst,src .

Эта запись подразумевает три возможные формы команды: без операндов, с одним операндом, с двумя операндами.

src – Source — источник;

dst – Destionation – получатель.

В мнемониках команд FPU приняты следующие соглашения:

· первая буква команды всегда F (только команды FPU начинаются с F);

· вторая буква I обозначает операцию с целым двоичным числом из памяти, буква B – операцию с десятичным числом из памяти, без этих букв – вещественное число;

· предпоследняя или последняя буква R указывает обратную операцию (для вычитания или деления);

· последняя буква P идентифицирует команду, заключительным действием которой является извлечение из стека.

Рассмотрим машинный формат команд.

Для команд FPU существует пять различных форматов кодирования (рис. 7.18), однако в любом формате старшие пять битов двухбайтного кода команды FPU всегда содержит специальное значение 11011, по которому процессор распознает команды FPU.

Команда | Доп. поле
Первый байт | Второй байт |
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |  |
1 | 1 | 0 | 1 | 1 | OP1 | 1 | Mod | 1 | OP2 | R/m | sib | Disp
1 | 1 | 0 | 1 | 1 | MF | OP1 | Mod | OP2 | R/m | sib | Disp
1 | 1 | 0 | 1 | 1 | d | p | OP1 | 1 | 1 | OP2 | R | ST(i) |  |
1 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | OP |  |
1 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | OP |  |

Рис. 7.18

Поля имеют следующее назначение и кодирование:

1. MF – формат ячейки памяти. (00 – 32-битное вещественное, 01- 32-битное целое, 10 – 64-битное вещественное, 11 – 64-битное целое);

2. P– извлечение из стека (0 – не извлекать; 1 – извлекать);

3. D – назначение (0- ST(0), 1 – ST(1));

4. R– направление операции;

5. ST(i) – элемент регистрового стека;

6. OP1, OP2 – первая и вторая части кода операции.

7. Поля mod, r/m, sib кодируются также, как для базовых команд процессора.

В ассемблере резервирование памяти осуществляется с помощью директив: DD – двойное слово; DQ – учетверенное слово; DT – определить 10 байт.

#### 7.6.5. Форматы команд процессора UltraSPARC III

Команды 32-битные, выровненные в памяти. Каждая команда определяет только одно действие. Типичная команда указывает два регистра, из которых берутся операнды и выходной регистр. Вместо одного регистра допускается использование константы со знаком. При выполнении команды считывания два регистра (или один регистр и одна константа) складываются вместе и определяют адрес памяти, по которому производится считывание; результат записывается в указанный регистр.

Изначально SPARC имела ограниченное число форматов (рис. 7.19). Со временем добавлялись дополнительные форматы и сейчас их 31.

Первые два бита команды помогают определить формат команды и сообщают программному обеспечению, где найти оставшуюся часть кода операции, если она есть.

| 2 | 5 | 6 | 5 | 1 | 8 | 5 |
1a |  | Вых. Рг. | КОП | Вх. Рг1 | 0 х | Операция с п/з | Вх. Рг.2 | 3 регистра

1b

Вых. Рг.

КОП

Вх. Рг1

1

Непосредственная константа

###### Непосредственный операнд

######

| 2 | 5 | 3 | 22 |

2

Вых. Рг.

КОП

Непосредственная константа

###### SETHI

######

| 2 | 1 | 4 | 3 | 22 |
3 |  | A | условие | КОП | Смещение относительно счетчика команд | BRANCH (команда перехода)
| 2 | 30 |
4 |  | Смещение относительно счетчика команд | CALL (команда вызова процедур)

Рис. 7.19

В формате 1а оба источника расположены в регистрах. В формате 1b один операнд – константа. Бит 13 (0 или 1) определяет один из этих форматов.

Поскольку все команды 32-битные, то включить в команду 32-битную константу невозможно. Команда SETHI устанавливает 22 бита, оставляя пространство для другой команды, чтобы установить оставшиеся 10 битов. Это единственная команда, использующая данный формат.

Для непрогнозируемых условных переходов используется формат 3, в котором поле условие определяет, какое условие надо проверить. Бит А нужен для того, чтобы избегать пустых операций при определенных условиях. Прогнозируемые переходы используют тот же формат, но только с 19-битным смещением.

Последний формат используется для вызова процедур. Требуемый адрес – это целевой адрес, разделенный на четыре.

#### 7.6.6. Форматы команд 8051

В 8051 предусмотрены шесть форматов команд (рис. 7.20). Размер команды может быть 1, 2 или 3 байта.

| 8 | 8 | 8 |
1 | КОП |

2

КОП

Рг

######

3 | КОП | операнд |
4 | КОП | 11-разрядный адрес |
5 | КОП | 16-разрядный адрес |
6 | КОП | Операнд1 | Операнд2 |

Рис. 7.20

Первый вариант предусматривает только наличие кода операции.

Второй вариант также состоит из одного байта: 5 – КОП, 3 – номер регистра.

В третьем формате используется 2 байта: КОП и операнд, размером в 1 байт.

Четвертый и пятый форматы используются для команд перехода. 11-разрядный адрес используется в случае отсутствия внешней памяти. Если присутствует внешняя память и ее объем составляет более 4 Кбайт, используются 16-разрядные адреса.

Шестой формат использует два операнда. Может использоваться для переноса константы по некоторому адресу.

### 7.7. Адресация

Как было сказано ранее, для адресации S ячеек памяти адресная часть одного операнда должна иметь число разрядов

Это требование находится в противоречии с желанием иметь малую разрядность команды и возможностью использовать большое адресное пространство. Существуют два основных подхода к решению этой проблемы.

1. Использовать регистры общего назначения. Это существенно повышает быстродействие, но имеет эффект толь в том случае, если операнд используется многократно. Кроме того, существует ограничение на количество регистров общего назначения.

2. Второй подход подразумевает определение одного или нескольких операндов неявным образом. Это означает использование не трехадресной команды, а двух- одно- и безадресных команд.

Следует различать понятия адресный код в команде Ак и исполнительный адрес Аи. Адресный код –это информация об адресе команды, содержащаяся в команде. Исполнительный адрес – это номер ячейки памяти, к которой производится обращение. В современных ЭВМ адресный код, как правило, не совпадает с исполнительным адресом. В свою очередь исполнительный адрес может не совпадать с физическим из-за таких особенностей ЭВМ как сегментация и виртуальная память.

Рассмотрим способы адресации, используемые в современных ЭВМ.

#### 7.7.1. Способы адресации

##### 7.7.1.1.Подразумеваемый операнд.

В команде не содержится в явном виде указаний об адресе операнда. Операнд подразумевается и фактически задается кодом операции команды. Вообще, данный метод используется нечасто, однако в архитектуре х86 имеется достаточное количество таких команд: INC, DEC.

##### 7.7.1.2.Подразумеваемый адрес.

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

##### 7.7.1.2. Непосредственная адресация.

В команде содержится не адрес операнда, а непосредственно операнд. Непосредственная адресация удобна при использовании различного рода констант.

##### 7.7.1.3. Прямая адресация.

Исполнительный адрес совпадает с адресной частью кода команды. Этот способ адресации был общепринятым в первых вычислительных машинах и продолжает применяться в настоящее время в комбинации с другими способами.

##### 7.7.1.4.Регистровая адресация.

В качестве операнда используется содержимое регистров процессора (ячейки сверхоперативной памяти). Например, если таких регистров 16, то для адреса регистра достаточно 4-х битов. Регистровая адресация наряду с сокращением длины адресов операндов позволяет увеличивать скорость выполнения операций.

##### 7.7.1.5. Косвенная адресация.

Адресный код команды указывает адрес ячейки памяти, в которой находится адрес операнда или команды. Т.е. происходит «адресация адреса». Если в качестве адресная часть команды – регистр, то такая адресация называется регистровой косвенной адресацией, а используемых регистр – указателем.

Косвенная адресация начала широко использоваться в свое время в малых ЭВМ и микропроцессорах, имеющих короткое машинное слово, для преодоления короткого формата команды.

Особенно часто применяется совместное использование регистровой и косвенной адресаций.

Рис. 7.21

На рис. 7.21 описаны следующие поля:

КОП – код операции;

Рг – номер регистра;

УА – указатель косвенной адресации.

На рис. 7.21 показан механизм пересылки числа 4527 из регистра 5 в ячейку памяти 1765. Операнд 4527 указывается в регистровой прямой адресации, а для задания адреса 1765 используется регистровая косвенная адресация.

##### 7.7.1.6. Относительная адресация или базирование.

Исполнительный адрес определяется суммой адресного кода команды Ак и некоторого числа Аб, называемого базовым адресом:

Аи = Аб + Ак.

Для хранения базовых адресов в машине могут быть использованы специальные регистры или ячейки памяти (базовые регистры). В команде выделяется поле B для указания номера базового регистра.

Относительная адресация позволяет при меньшей длине адресного кода команды обеспечить доступ к любой ячейке памяти. Для этого число разрядов в базовом регистре выбирается таким, чтобы можно было адресовать любую ячейку ОП, а адресный код Ак самой команды используют для представления сравнительно короткого «смещения» (обозначим D). Смещение D определяет положение операнда относительно начала массива, задаваемого базовым адресом Аб. Схема формирования исполнительного адреса приведена на рис. 7.22.

Большей частью исполнительный адрес при базировании образуется с помощью сумматора согласно выражению:

Аи = (В) + D,

где (В) – содержимое регистра с номером В.

Иногда применяют формирование исполнительного адреса методом совмещения. В этом случае базовый адрес содержит старшие, а смещение – младшие разряды исполнительного адреса, которые объединяются в регистре адреса путем их составления.

Однако при совмещении базовый адрес может задавать не любые ячейки памяти, а только те, адреса которых содержат нули в младших разрядах, соответствующих смещению.

Относительная адресация обеспечивает так называемую перемещаемость программ, т.е. возможность перемещения программ в памяти без изменений внутри самой программы.

##### 7.7.1.7. Индексная адресация.

Характерной особенностью вычислительных процессов, происходящих в ЭВМ, является цикличность, при которой повторяются одни и те же процедуры, но над различными операндами (как правило, элементами массивов, расположенными упорядочено в памяти). Поскольку операнды, обрабатываемые при построении цикла, имеют разные адреса, можно для каждого повторения составить свою последовательность команд, отличающуюся только адресными частями.

Такая программа, состоящая из групп команд, отличающихся только адресной частью, является, очевидно, слишком длинной, а написание ее – слишком трудоемким.

Программирование вычислительных циклов существенно упроститься, если после каждого выполнения цикла обеспечить автоматическое изменение в соответствующих командах их адресных частей согласно расположению в ОП обрабатываемых операндов. Такой процесс называется модификацией команд, точнее адресных частей команд. Модификация команд основана на возможности выполнения над кодами команд или их частями арифметических и логических операций. Идея модификации команд была предложена фон Нейманом.

В первых вычислительных машинах действительно использовалась модификация команд. В современных ЭВМ используется механизм индексации. Это понятие включает в себя специальный способ кодирования команд, командные и аппаратные средства задания и выполнения модификации команд и управления вычислительными циклами. Упомянутые средства называются индексной арифметикой. По своей сути индексация является дальнейшим развитием базирования.

Для выполнения индексации в архитектуру процессора вводятся так называемые индексные регистры. В формате команды вводится поле X для указания индексного регистра. Исполнительный адрес при индексации формируется путем сложения адресного кода команды (смещения) с содержимым индексного регистра (индексом). Во многих архитектурах содержимое индексного регистра дополнительно умножается на размер операнда. При наличии базирования добавляется еще и базовый адрес.

##### 7.7.1.8.Стековая адресация.

Стековая память реализует безадресное задание операндов. Стек представляет собой группу последовательно пронумерованных регистров (аппаратный стек) или ячеек памяти, снабженных указателем стека (обычно регистром SP), в котором автоматически при записи и считывании указывается номер (адрес) последней занятой ячейки стека (вершины стека). При выполнении операции записи в стек слово помещается в следующую ячейку стека, а при считывании из стека последнее поступившее в него слово. Таким образом, в стеке реализуется дисциплина обслуживания «последний пришел – первый ушел» (LIFO).

Указанное правило при обращении к стеку реализуется автоматически, и поэтому при операциях со стеком возможно безадресное задание операндов.

Механизм стековой адресации может быть проиллюстрирован рисунком (рис. 7.23).

SP | 97 |  | 96 |  | 97 |  | 98 |
|  | 214 |  |  |  |  |
97 | 321 | 321 |  | 535 |  |  |
98 | 175 | 175 |  | 175 |  | 175 |
99 | 253 | 253 |  | 253 |  | 253 |
100 | 100 |  | 100 |  | 100 |  | 100 |
|  |  | Заслать в стек из РГ3 |  |  |  | загрузить из стека в РГ4
|  | 214 |  | Сложить |  | 535 |  |

Рис. 7.23

При выполнении команды передачи в стек слова указатель стека увеличивается на 1, а затем слово помещается в ячейку стека, указываемую SP. При загрузке из стека сначала извлекается слово, а затем указатель уменьшается на 1.

При соответствующем расположении операндов в стеку можно вычислять выражения полностью безадресными командами, указывающими только тип операции. Такая команда извлекает из стека в соответствии с кодом операции один или два операнда, выполняет предписанную операцию и заносит результат в стек.

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

Например, выражение

в бесскобочной записи имеет вид:

Выражение в польской инверсной записи не содержит скобок, но порядок действий определен однозначно. Программа вычисления такого выражения может иметь следующий, достаточно условный вид:

push k

push l

add

push m

sub

push p

push s

sub

mul

Безадресные команды на основе стековой адресации предельно сокращают форму команд, экономят память и способствуют повышению производительность ЭВМ.

Однако при такой структуре команд возникают сложности с построением команд передачи управления и работы с периферийными устройствами.

В современной архитектуре процессоров стек и стековая адресация применяется при организации переходов к подпрограммам и системах прерывания. Элементы стековой адресации используются в процессорах х86 при работе с данными с плавающей точкой.

##### 7.7.1.9. Способы адресации команд перехода

Командам перехода (а также командам вызова процедур) также нужны особые способы адресации для определения целевого адреса. Способы, существующие для адресации данных могут быть также использованы для вычисления исполнительных адресов команд перехода. Один из возможных вариантов – прямая адресация, когда целевой адрес просто полностью включается в команду.

Другие способы адресации также имеют смысл. Косвенная и регистровая адресация позволяют программа вычислить целевой адрес, помещать его в регистр, а затем переходить по этому адресу. Такой способ дает максимальную гибкость, поскольку целевой адрес вычисляется во время выполнения программы. Но такой подход предоставляет огромные возможности для появления ошибок, которые практически невозможно найти.

Индексная адресация, при которой известно смещение от регистра, также может быть использована.

Может быть также использована относительная адресация по счетчику команд. В этом случае для получения целевого адреса смещение (со знаком), находящееся в самой команде прибавляется к программному счетчику.

#### 7.7.2. Способы адресации процессора Pentium 4

Способы адресации процессора Pentium II нерегулярны и зависят от того, в каком формате находятся команды: 16- или 32-битном.

Режим адресации определяют один или два байта адресации, которые находятся после байта адресации. Первым является байт mod r/m, вторым байт sib (масштаб, индекс, база). Байт sib может присутствовать только в командах с 32-разрядной адресацией, когда байт mod r/m содержит r/m = 100 и значение в поле mod≠11.

Для адресации теперь можно использовать любой регистр общего назначения, а индекс разрешается масштабировать (умножать) на 1, 2, 4 или 8. Ниже приводятся все способы 32-разрядной адресации.

Таблица 7.6

Непосредственная | mov | eax, | 12345678h
Регистровая | mov | eax, | ecx
Прямая (абсолютная) | mov | eax, | [3456789h]
Регистровая косвенная | mov | eax, | [ecx]
Базовая (индексная) со смещением | mov | eax, | [ecx]+1200h
Базовая индексная со смещением | mov | eax, | [ecx][edx]+40h
Индексная с масштабированием и смещением | mov | eax, | [eci*4]+400h
Базовая индексация с масштабированием | mov | eax, | [edx][ecx*8]
Базовая индексация с масштабированием и смещением | mov | eax, | [ebx][edi*2]+20h

Проблема заключается в том, что не все способы адресации применимы ко всем командам и не все регистры могут использоваться при всех способах адресации. Это существенно усложняет работу компилятора.

Схема формирования адреса в 32-разрядной адресации приведена на рис 7.24

Рис. 7.24.

32–разрядные режимы адресации кодируются с помощью двух байт mod r/m и sib.

Байт mod управляет способами адресации. Один из операндов определяется по комбинации полей mod и r/m. Второй операнд всегда является регистром и определяется по значению поля reg. Формирование адреса памяти в 32-битной адресации (r/m ≠100).

Таблица 7.7

r/m | Адрес памяти второго операнда
mod = 00 | mod = 01 | mod = 10 | Mod = 11
000 | М[EAX] | M[EAX+d8] | M[EAX+d32] | EAX или AL
001 | M[ECX] | M[ECX+d8] | M[ECX+d32] | ECX или CL
010 | M[EDX] | M[EDX+d8] | M[EDX+d32] | EDX или DL
011 | M[EBX] | M[EBX+d8] | M[EBX+d32] | EBX или BL
100 | имеется sib | имеется sib | имеется sib | ESP или AH
101 | Прямая адр. | M[EBP+d8] | M[EBP+d32] | EBP или CH
110 | M[ESI] | M[ESI+d8] | M[ESI+d32] | ESI или DH
111 | M[EDI] | M[EDI+d8] | M[EDI+d32] | EDI или BH

M[x] – слово в памяти с адресом х. D – смещение Колонки 01 и 10 включают способы адресации, при которых значение регистра прибавляется к 8-битному или 32-битному смещению, которое следует за командой.

Иногда вслед за байтом mod следует дополнительный байт sib. Байт sib определяет масштабный коэффициент и два регистра.

Поле SS указывает масштабный коэффициент индекса, поле index определяет любой регистр, кроме ESP, который служит индексным регистром, а поле base – определяет базовый регистр. Формирование адреса памяти в 32-битной адресации (r/m =100, имеется sib) приведено в табл. 7.8.

Таблица 7.8

поле base | Адрес памяти второго операнда
mod = 00 | mod = 01 | mod = 10
000 | M[EAX+ss*ind] | M[EAX+ss*ind+d8] | M[EAX+ss*ind+d32]
001 | M[ECX+ss*ind] | M[ECX+ss*ind+d8] | M[ECX+ss*ind+d32]
010 | M[EDX+ss*ind] | M[EDX+ss*ind+d8] | M[EDX+ss*ind+d32]
011 | M[EBX+ss*ind] | M[EBX+ss*ind+d8] | M[EBX+ss*ind+d32]
100 | M[ESP+ss*ind] | M[ESP+ss*ind+d8] | M[ESP+ss*ind+d32]
101 | M[d32+ss*ind] | M[D32+ss*ind+d8] | M[d32+ss*ind+d32]
110 | M[ESI+ss*ind] | M[ESI+ss*ind+d8] | M[ESI+ss*ind+d32]
111 | M[EDI+ss*ind] | M[EDI+ss*ind+d8] | M[EDI+ss*ind+d32]

Таблица кодирования полей index и ss.

Таблица 7.9

index | индексный регистр | ss | Множитель
000 | EAX | 00 | *1
001 | ECX | 01 | *2
010 | EDX | 10 | *4
011 | EBX | 11 | *8
100 | нет |  |
101 | EBP |  |
110 | ESI |  |
111 | EDI |  |

#### 7.7.3. Способы адресации процессора UltraSPARC III

В архитектуре команд процессора UltraSPARC III все команды используют непосредственную и регистровую адресацию за исключением тех команд, которые непосредственно обращаются к памяти. При регистровом способе адресации 5 битов просто сообщают, какой регистр нужно использовать. При непосредственной адресации данные обеспечивает 13-битная константа со знаком. Для арифметических, логических и подобных команд никакие другие способы адресации не используются.

К памяти обращаются команды трех типов: считывания (Load), записи (Store) и одна команда синхронизации мультипроцессора. Для команд записи и считывания существует два способа обращения к памяти.

Первый. Вычисляется сумма двух регистров, а затем через полученное значение производится косвенная адресация.

Второй способ представляет собой обычное индексирование с 13-битным смещением со знаком.

#### 7.7.4. Способы адресации процессора 8051

Предусмотрено пять режимов адресации.

Первый – неявная адресация. Первый операнд находится в сумматоре, второй в памяти или регистрах. Использование сумматора определяется по коду операции.

Второй способ – регистровая адресация. Регистры могут быть как входными, так и выходными.

Третий режим – прямая адресация, адрес операнд указан в команде.

Четвертый режим – косвенная регистровая адресация, подразумевающая размещение в регистре указателя на операнд. Поскольку разрядность обычных регистров составляет 8 бит, то операнды с такой адресацией должны занимать нижние 256 байт памяти.

В пятом режиме непосредственной адресации операнд является частью команды.

Предусмотрен специализированный режим адресации, применяемый к некоторым командам для доступа в память. К микросхеме можно подключить до 64 Кбайт внешней памяти для программ и столько же для данных. За взаимодействие с внешней памятью программ отвечают команды LJMP и LCALL. Для взаимодействия с внешней памятью данных используется 16-разрядный регистр DPTR, в котором размещаются 16-разрядные адреса памяти. Таким образом используется двойной указатель.

#### 7.7.4. Сравнение способов адресации

Таблица 7.9

Способ адресации | Pentium II | UltraSPARC II | JVM
Неявная адресация |  |  | *
Непосредственная | * | * | *
Прямая | * |  | *
Регистровая | * | * | *
Косвенная регистровая | * | * | *
Индексная | * | * |
Относительная индексная |  | * |
Стековая |  |  |

На практике для эффективной архитектуры команд совсем не обязательно использовать большое число способов адресации. Поскольку практически весь код, написанный на этом уровне порождается компилятором, то способов адресации должно быть мало, они д.б. четкими и ясными.

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

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

### 7.8. Типы команд

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

#### 7.8.1. Команды перемещения данных

Как правило, в машинах с фиксированной длиной слова единицей перемещаемых данных является слово. Однако, существуют архитектуры команд дают возможность копировать отрезки данных меньше слова, а также группу слов. Некоторые машины с изменяемой длиной слова содержат команды, которые определяют только адреса источника и получателя, а не количество данных. Копирование продолжается до тех пор, пока не появится специальное поле в конце данных.

#### 7.8.2. Бинарные операции

Бинарные операции берут два операнда и получают результат. Все архитектуры команд содержат операции с фиксированной точкой. Большинство компьютеров сегодня поддерживают операции с плавающей точкой. Большинство машин содержит по крайней мере 2 варианта таких чисел: более короткие для скорости и более длинные для получения высокой точности вычислений.

#### 7.8.3. Унарные операции

Унарные операции используют один операнд и производят один результат. Команды таких операций могут быть короче.

#### 7.8.4. Команда вызова процедур

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

Адрес возврата может быть размещен в одном из трех мест: в памяти, в регистре или в стеке.

Самое худшее решение – размещение в фиксированной ячейке памяти. В таком случае, если процедура вызывает другую процедуру, то адрес теряется.

Более удачное решение – сохранять адрес возврата в первом слове процедуры. Недостаток такой схемы – процедура не может вызвать сама себя, т.к. первый адрес возврата будет уничтожен вторым вызовом.

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

Самое лучшее решение – поместить адрес возврата в стек. Когда процедура завершена, она выталкивает адрес возврата.

### 7.9. Сравнение наборов команд

Наборы команд сравниваемых архитектур существенно отличаются друг от друга.

Pentium 4 – классическая двухадресная 32-битная машина CISC. Эта машина с долгой историей и она содержит много команд, которые обращаются к памяти.

UltraSPARC II – это современная трехадресная 64-битная машина RISC с архитектурой загрузки/сохранения, всего двумя способами адресации и компактным набором команд.

8051 – небольшой встроенный процессор, устанавливаемый на единственную микросхему.

Говорят, что в основу разработки компьютера Pentium 4 лежали три основных фактора:

1. Обратная совместимость.

2. Обратная совместимость.

3. Обратная совместимость.

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

Современная разработка уровня команд представлена в процессоре UltraSPARC III. Он содержит полную 64-битную архитектуру команд. Процессор содержит много регистров и имеет набор команд, в которых преобладают трехрегистровые операции, а также небольшая группа команд записи/считывания. Все команды одного размера, хотя число форматов вышло из-под контроля. Большинство новых разработок очень похожи на UltraSPARC III, но содержат меньшее число форматов команд.

В микросхеме 8051 реализован простой стандартный набор команд. Отличительная особенность – четыре набора регистров для ускоренной обработки прерываний, возможность доступа к регистрам в пространстве памяти и мощные команды побитовой обработки. Основное преимущество – низкая стоимость.

Ядро современного компьютера представляет собой сильно конвейеризированное трехрегистровое устройство загрузки/сохранения типа RISC. UltraSPARC II декларирует эту структуру. Pentium II скрывает систему RISC, перенимает старую архитектуру команд и разбивает команды CISC на микрооперации RISC. Машина PicoJava также использует ядро архитектуры RISC, но для этого комбинируется несколько команд для получения одной операции RISC.

### 7.10. Поток управления

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

#### 7.10.1. Последовательный поток управления и переходы

В большинстве команды выполняются последовательно и состояние счетчика команд представляет собой возрастающую функцию.

Если программа содержит переход, то соответствие между порядком расположения команд и порядком их выполнения нарушается. В результате последовательность выполнения команд из самой программы уже не видна. Это привело к появлению статьи Дейкстры под названием «Оператор goto следует считать вредным», в которой предлагалось избегать использовать этот оператор. Эта статья дала толчок революции в программировании. Одним из нововведений было устранение операторов goto более структурированными формами потока управления, например, while. Конечно, эти программы компилируются в программы второго уровня, которые могут содержать команды переходов, поскольку без них не обойтись.

#### 7.10.2. Процедуры

Самым важным способом структурирования программ является процедура. Процедура с одной стороны вызывает изменение порядка следования операций, но с другой стороны процедуру можно интерпретировать как определение новой команды на более высоком уровне.

Особый интерес представляет рекурсивная процедура. Это такая процедура, которая вызывает сама себя либо непосредственно, либо через цепочку других процедур.

#### 7.10.3. Сопрограммы

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

Рассмотрим две процедуры А и В. Процедура А вызывает процедуру В. По окончанию процедуры В происходит возврат к процедуре А, и она продолжает выполняться дальше, с команды, следующей за командой вызова процедуры В. При повторном вызове процедуры В она будет выполняться с самого начала, а не с места возврата в процедуру А (рис. 7.25).

Иногда нужно иметь две процедуры А и В, каждая из которых вызывает другую в качестве процедуры так, как это показано на рис. 7.26.

При возврате из В к А процедура В совершает переход к тому оператору, за которым последовал вызов процедуры В. Когда процедура А передает управление процедуре В, она возвращается не к самому началу процедуры в, а к тому месту, на котором произошел предыдущий вызов. Две процедуры, работающие таким образом, называются сопрограммами.

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

#### 7.10.4. Ловушки

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

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

#### 7.10.5. Прерывания

Прерывания – это изменения в потоке управления, вызванные не самой программой, а чем-либо другим и обычно связано с процессом ввода-вывода. Как и ловушка, прерывание останавливает работу программы и передает управление программе обработки прерываний, которая выполняет некоторое действие. После окончания этого действия программа обработки прерываний передает управление прерванной программе. Она должна заново начать прерванный процесс в том же самом состоянии, в котором она находилась, когда произошло прерывание. Это значит, что прежнее состояние всех регистров должно быть восстановлено.

Различие между ловушкой и прерыванием следующее: ловушки синхронны с программой, а прерывания асинхронны.

Для иллюстрации работы прерываний, рассмотрим пример: компьютер должен вывести на терминал строку символов. Программное обеспечение сначала собирает в буфер все символы, инициирует глобальную переменную prt, указывающую на начало буфера и устанавливает вторую глобальную переменную count, которая равна числу выводимых символов. Затем ПО проверяет, готов ли терминал и, если терминал готов, выводит первый символ. Начав процедуру вывода, центральный процессор освобождается и может запустить другую программу.

Через некоторое время символ появляется на экране. Теперь может начаться прерывание. Основные шаги в упрощенной форме следующие.

Действия аппаратного обеспечения:

1. Контроллер устройства устанавливает линию прерывания на системной шине.

2. Когда центральный процессор готов к обработке прерывания, он устанавливает символ подтверждения прерывания на шине.

3. Когда контроллер устройства узнает, что сигнал прерывания был подтвержден, он помещает небольшое целое число на информационные линии, что бы «представиться» (то есть показать, что это за устройство). Это число – номер прерывания.

4. Центральный процессор удаляет номер прерывания с шины и временно его сохраняет.

5. Центральный процессор помещает в стек счетчик команд и слово состояния программы.

6. Затем центральный процессор определяет местонахождение нового счетчика команд, используя номер прерывания в качестве индекса. Например, если размер счетчика команд составляет 4 байта, тогда номер прерывания n соответствует адресу 4n. Новый счетчик команд указывает на начало программы обслуживания прерываний для устройства, его вызвавшего. Иногда помимо этого загружается или изменяется слово состояния программы.

Действия программного обеспечения:

1. Программа обработки прерываний сохраняет все нужные ей регистры таким образом, чтобы их можно было восстановить позднее. Их можно сохранить в стеке или в системной таблице.

2. Каждый номер прерывания разделяется всеми устройствами данного типа, поэтому в данный момент времени еще не известно, какое устройство вызвало прерывание. Номер устройства можно считать из какого-нибудь регистра.

3. Теперь можно считывать любую другую информацию о прерывании, например, коды состояния.

4. Если происходит ошибка ввода-вывода, ее нужно обработать здесь.

5. Глобальные переменные prt и count обновляются. Первая увеличивается на 1 для того, чтобы показать следующий байт, а вторая уменьшается на 1, чтобы указать, что осталось ввести на один байт меньше. Тот символ, на который указывает в данный момент prt, копируется в выходной буферный регистр.

6. В случае необходимости выдается специальный код, который сообщает устройству или контроллеру прерывания, что прерывание обработано.

7. Восстанавливаются все сохраненные регистры.

8. Выполнение команды RETURN FROM INTERRUPT (выход из прерывания): возвращение центрального процессора в то состояние, в котором он находился до прерывания. После этого компьютер продолжает работать с того места, в котором ее приостановил.

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

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

Для разрешения этой ситуации существуют два подхода.

Первый подход – для всех программ обработки прерываний в первую очередь (даже до сохранения регистров) предотвратить последующие прерывания.

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