ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 24.12.2021
Просмотров: 12169
Скачиваний: 10

338
Глава 5. Уровень архитектуры команд
Другое важное качество уровня команд состоит в том, что в большинстве ма-
шин есть, по крайней мере, два режима.
Привилегированный режим
предназначен
для запуска операционной системы. Он позволяет выполнять все команды.
Пользо-
вательский
режим предназначен для запуска программных приложений. Этот ре-
жим не позволяет выполнять некоторые чувствительные команды (например, те,
которые непосредственно манипулируют кэш-памятью). В этой главе мы в пер-
вую очередь сосредоточимся на командах и свойствах пользовательского режима.
Модели памяти
Во всех компьютерах память разделена на ячейки, которые имеют последова-
тельные адреса. В настоящее время наиболее распространенный размер ячейки —
8 битов, но раньше использовались ячейки от 1 до 60 битов (см. табл. 2.1). Ячейка
из 8 битов называется байтом. Причина применения именно 8-битных байтов тако-
ва: символы ASCII кода занимают 7 битов, поэтому один символ ASCII плюс бит
четности как раз подходит под размер байта. Если в будущем будет доминировать
UNICODE, то ячейки памяти, возможно, будут 16-битными. Вообще говоря, чис-
ло 2
4
лучше, чем 2
3
, поскольку 4 — степень двойки, а 3 — нет.
Байты обычно группируются в 4-байтные (32-битные) или 8-байтные (64-бит-
ные) слова с командами для манипулирования целыми словами. Многие архитек-
туры требуют, чтобы слова были выровнены в своих естественных границах. Так,
например, 4-байтное слово может начинаться с адреса 0,4,8 и т. д., но не с адреса
1 или 2. Точно так же слово из 8 байтов может начинаться с адреса 0,8 или 16, но не
с адреса 4 или 6. Расположение 8-байтных слов показано на рис. 5.2.
8 байтов
Адрес
15 14 13 12 11 10
9
8
24
16
8
VV
Выровненное 8-байтовое
слово в ячейке с адресом 8
Адрес
- * —
15 14 13
8 байтов -
12
19
-
I j
18 ! 17 ! 16
! I
24
16
8
О
Невыровненное 8-байтовое
слово в ячейке с адресом 12
Рис.
5.2. Расположение слова из 8 байтов в памяти: выровненное (а); невыровненное (б).
Некоторые машины требуют, чтобы слова в памяти были выровнены

Общий обзор уровня архитектуры команд 339
Выравнивание адресов требуется довольно часто, поскольку при этом память
работает более эффективно. Например, Pentium II, который вызывает из памяти
по 8 байтов за раз, использует 36-битные физические адреса, но содержит только
33 адресных бита, как показано на рис. 3.41. Следовательно, Pentium II даже не
сможет обратиться к невыровненной памяти, поскольку младшие три бита не
определены явным образом. Эти биты всегда равны 0, и все адреса памяти кратны
8 байтам.
Тем не менее требование выравнивания адресов иногда вызывает некоторые
проблемы. В процессоре Pentium II программы могут обращаться к словам, начи-
ная с любого адреса, — это качество восходит к модели 8088 с шиной данных ши-
риной в 1 байт, в которой не было такого требования, чтобы ячейки располагались
в 8-байтных границах. Если программа в процессоре Pentium II считывает 4-байт-
ное слово из адреса 7, аппаратное обеспечение должно сделать одно обращение к
памяти, чтобы вызвать байты с 0-го по 7-й, и второе обращение к памяти, чтобы
вызвать байты с 8-го по 15-й. Затем центральный процессор должен извлечь тре-
буемые 4 байта из 16 байтов, считанных из памяти, и скомпоновать их в нужном
порядке, чтобы сформировать 4-байтное слово.
Возможность считывать слова с произвольными адресами требует усложнения
микросхемы, которая после этого становится больше по размеру и дороже. Разра-
ботчики были бы рады избавиться от такой микросхемы и просто потребовать, что-
бы все программы обращались к словам памяти, а не к байтам. Однако на вопрос
инженеров: «Кому нужно исполнение старых программ для машины 8088, кото-
рые неправильно обращаются к памяти?» последует ответ продавцов: «Нашим
покупателям».
Большинство машин имеют единое линейное адресное пространство, которое
простирается от адреса 0 до какого-то максимума, обычно 2
32
байтов или 2
е4
байтов.
В некоторых машинах содержатся отдельные адресные пространства для команд
и для данных, так что при вызове команды с адресом 8 и вызове данных с адресом
8 происходит обращение к разным адресным пространствам. Такая система гораздо
сложнее, чем единое адресное пространство, но зато она имеет два преимущества.
Во-первых, появляется возможность иметь 2
32
байтов для программы и дополни-
тельные 2
32
байтов для данных, используя только 32-битные адреса. Во-вторых,
поскольку запись всегда автоматически происходит только в пространство дан-
ных, случайная перезапись программы становится невозможной, и следовательно,
устраняется один из источников программных сбоев.
Отметим, что отдельные адресные пространства для команд и для данных —
это не то же самое, что разделенная кэш-память первого уровня. В первом случае
все адресное пространство целиком дублируется, и считывание из любого адреса
вызывает разные результаты в зависимости от того, что именно считывается: сло-
во или команда. При разделенной кэш-памяти существует только одно адресное
пространство, просто в разных блоках кэш-памяти хранятся разные части этого
пространства.
Еще один аспект модели памяти — семантика памяти. Естественно ожидать,
что команда LOAD, которая встречается после команды STORE и которая обращается
к тому же адресу, возвратит только что сохраненное значение. Тем не менее, как
мы видели в главе 4, во многих машинах микрокоманды переупорядочиваются.

3 4 0 Глава 5. Уровень архитектуры команд
Таким образом, существует реальная опасность, что память не будет действовать
так, как ожидается. Ситуация усложняется в случае с мультипроцессором, когда
каждый процессор посылает разделенной памяти поток запросов на чтение и за-
пись, которые тоже могут быть переупорядочены.
Системные разработчики могут применять один из нескольких подходов к этой
проблеме. С одной стороны, все запросы памяти могут быть упорядочены в после-
довательность таким образом, чтобы каждый из них завершался до того, как нач-
нется следующий. Такая стратегия сильно вредит производительности, но зато дает
простейшую семантику памяти (все операции выполняются в строгом программ-
ном порядке).
С другой стороны, не дается вообще никаких гарантий. Чтобы сделать обраще-
ния к памяти упорядоченными, программа должна выполнить команду SYNC, кото-
рая блокирует запуск всех новых операций памяти до тех пор, пока предыдущие
операции не будут завершены. Эта идея сильно затрудняет работу тех, кто пишет
компиляторы, поскольку для этого им нужно очень хорошо знать, как работает
соответствующая микроархитектура, но зато разработчикам аппаратного обеспе-
чения предоставлена полная свобода в оптимизации использования памяти.
Возможны также промежуточные модели памяти, в которых аппаратное обес-
печение автоматически блокирует запуск определенных операций с памятью (на-
пример, тех, которые связаны с RAW- или WAR-взаимозависимостью), при этом
запуск всех других операций не блокируется. Хотя разработка этих особенностей
на уровне команд довольно утомительна (по крайней мере, для составителей ком-
пиляторов и программистов на языке ассемблера), сейчас существует тенденция
использовать такой подход. Эта тенденция вызвана такими реализациями, как пе-
реупорядочение микрокоманд, конвейеры, многоуровневая кэш-память и т. д. Дру-
гие неестественные примеры такого рода мы рассмотрим в этой главе чуть позже.
Регистры
Во всех компьютерах имеется несколько регистров, которые видны на уровне ко-
манд. Они нужны там для того, чтобы контролировать выполнение программы,
хранить временные результаты, а также для некоторых других целей. Обычно ре-
гистры, которые видны на микроархитектурном уровне, например TOS и MAR
(см. рис. 4.1), не видны на уровне команд. Тем не менее некоторые из них, напри-
мер счетчик команд и указатель стека, присутствуют на обоих уровнях. Регистры,
которые видны на уровне команд, всегда видны на микроархитектурном уровне,
поскольку именно там они реализуются.
Регистры уровня команд можно разделить на две категории: специальные ре-
гистры и регистры общего назначения. Специальные регистры включают счетчик
команд и указатель стека, а также другие регистры с особой функцией. Регистры
общего назначения содержат ключевые локальные переменные и промежуточные
результаты вычислений. Их основная функция состоит в том, чтобы обеспечить
быстрый доступ к часто используемым данным (обычно избегая обращений к па-
мяти). Машины RISC с высокоскоростными процессорами и медленной (относи-
тельно медленной) памятью обычно содержат как минимум 32 регистра общего
назначения, а в новых процессорах количество этих регистров постоянно растет.

Общий обзор уровня архитектуры команд 341
В некоторых машинах регистры общего назначения полностью симметричны и
взаимозаменяемы. Если все регистры эквивалентны, для хранения временного
результата компилятор может использовать и регистр R1, и регистр R25. Выбор
регистра не имеет никакого значения.
В других машинах некоторые регистры общего назначения могут быть специа-
лизированы. Например, в процессоре Pentium II существует регистр EDX, кото-
рый может использоваться в качестве регистра общего назначения, но который
также получает половину произведения и содержит половину делимого при де-
лении.
Даже если регистры общего назначения полностью взаимозаменяемы, опера-
ционная система или компиляторы часто принимают соглашения о том, каким
образом используются эти регистры. Например, некоторые регистры могут содер-
жать параметры вызываемых процедур, а другие могут использоваться в качестве
временных регистров. Если компилятор помещает важную локальную перемен-
ную в регистр R1, а затем вызывает библиотечную процедуру, которая восприни-
мает регистр R1 как временный регистр, доступный для нее, то когда библиотеч-
ная процедура возвращает значение, регистр R1 может содержать ненужные данные.
А если существуют какие-либо системные соглашения по поводу того, как нужно
использовать регистры, составители компиляторов и программисты на языке ас-
семблера должны следовать им.
Кроме регистров, доступных на уровне команд, всегда существует довольно
большое количество специальных регистров, доступных только в привилегирован-
ном режиме. Эти регистры контролируют различные блоки кэш-памяти, основную
память, устройства ввода-вывода и другие элементы аппаратного обеспечения
машины. Данные регистры используются только операционной системой, поэто-
му компиляторам и пользователям не обязательно знать об их существовании.
Есть один регистр управления, который представляет собой привилегирован-
но-пользовательский гибрид. Это
флаговый регистр,
или
PSW (Program State
Word — слово состояния программы.
Этот регистр содержит различные биты,
которые нужны центральному процессору. Самые важные биты — это
коды усло-
вия.
Они устанавливаются в каждом цикле АЛ У и отражают состояние результата
предыдущей операции. Биты кода условия включают:
• N — устанавливается, если результат был отрицательным (Negative);
• Z — устанавливается, если результат был равен 0 (Zero);
• V — устанавливается, если результат вызвал переполнение (oVerflow);
• С — устанавливается, если результат вызвал выход переноса самого левого
бита (Carry out);
• А — устанавливается, если произошел выход переноса бита 3 (Auxiliary
carry — служебный перенос);
• Р — устанавливается, если результат четный (Parity).
Коды условия очень важны, поскольку они используются при сравнениях и
условных переходах. Например, команда СМР обычно вычитает один операнд из
другого и устанавливает коды условия на основе полученной разности. Если

3 4 2 Глава 5. Уровень архитектуры команд
операнды равны, то разность будет равна 0 и во флаговом регистре будет установ-
лен бит Z. Последующая команда BEQ (Branch Equal — переход в случае равенства)
проверяет бит Z и совершает переход, если он установлен.
Флаговый регистр содержит не только коды условия. Его содержимое меняет-
ся от машины к машине. Дополнительные поля указывают режим машины (на-
пример, пользовательский или привилегированный), трассовый бит (который
используется для отладки), уровень приоритета процессора, а также статус разре-
шения прерываний. Флаговый регистр обычно можно считать в пользователь-
ском режиме, но некоторые поля могут записываться только в привилегированном
режиме (например, бит, который указывает режим).
Команды
Главная особенность уровня, который мы сейчас рассматриваем, — это набор ма-
шинных команд. Они управляют действиями машины. В этом наборе всегда при-
сутствуют команды LOAD и STORE (в той или иной форме) для перемещения данных
между памятью и регистрами и команда MOVE для копирования данных из одного
регистра в другой. Всегда присутствуют арифметические и логические команды и
команды для сравнения элементов данных и переходов в зависимости от результа-
тов. Некоторые типичные команды мы уже рассматривали (см. табл. 4.2.). А в этой
главе мы рассмотрим многие другие команды.
Общий обзор уровня команд машины Pentium II
В этой главе мы обсудим три совершенно разные архитектуры команд: IA-32 ком-
пании Intel (она реализована в Pentium II), Version 9 SPARC (она реализована в
процессорах SPARC) и JVM (она реализована в picojavall). Мы не преследуем
цель дать исчерпывающее описание каждой из этих архитектур. Мы просто хотим
продемонстрировать важные аспекты архитектуры команд и показать, как эти ас-
пекты меняются от одной архитектуры к другой. Начнем с машины Pentium II.
Процессор Pentium II развивался на протяжении многих лет. Его история вос-
ходит к самым первым микропроцессорам, как мы говорили в главе 1. Основная
архитектура команд обеспечивает выполнение программ, написанных для процес-
соров 8086 и 8088 (которые имеют одну и ту же архитектуру команд), а в машине
даже содержатся элементы 8080 — 8-разрядный процессор, который был попу-
лярен в 70-е годы. На процессор 8080, в свою очередь, сильно повлияли требова-
ния совместимости с процессором 8008, который был основан на процессоре 4004
(4-битной микросхеме, применявшейся еще в каменном веке).
С точки зрения программного обеспечения, компьютеры 8086 и 8088 были
16-разрядными машинами (хотя компьютер 8088 содержал 8-битную шину дан-
ных). Их последователь 80286 также был 16-разрядным. Его главным преимуще-
ством был больший объем адресного пространства, хотя небольшое число программ
использовали его, поскольку оно состояло из 16 384 64 К сегментов, а не представ-
ляло собой линейную 2
24
-байтную память.