Лекции по ВМСС. Конспект лекций по курсу "Электронные вычислительные машины, системы и сети"
Скачать 3.89 Mb.
|
В качестве примера рассмотрим команду, показанную на рис. 2.12. Поле кода операции содержит 1111111 000 и определяет команду INC. Поле w = 1 показывает длину операнда 16 бит. Поле mod= 01 и операнд, следовательно, находится в памяти; кроме того, смещение в команде из следующего байта необходимо расширить со знаком до 16 бит: 0000 0000 0101 1100. Поле r/т = 100, поэтому со смещением в команде следует просуммировать содержимое регистра SI (пусть оно равно 1010 0000 1000 0110); +1010 0000 1000 0110 (содержимое SI) 0000 0000 0101 1100 (смещение в команде) 1010 0000 1110 0010 (результат) Так как в вычислениях не участвует регистр ВР, операнд находится в текущем сегменте данных. Предположим, что регистр DS содержит 1111 0000 1111 0000 и процессор работает в реальном режиме. Тогда адрес операнда в памяти равен: +1111 0000 1111 0000 (сегмент) 1010 0000 1110 0010 (смещение в сегменте) 1111 1010 1111 1110 0010 (адрес памяти) Д лина операнда 16 бит (w = 1), поэтому им является содержимое двух байт с адресами 1111 1010 1111 1110 0010 (младший) и 1111 1010 1111 1110 0011 (старший). О перанд не обязательно должен находиться только в текущих сегментах данных и стека. Его можно считывать из любого сегмента, введя перед командой однобайтный префикс, обозначающий сегментный регистр (рис. 2.13). На рис. 2.14 показана та же команда, что и на рис. 2.12, но теперь операнд находится в текущем дополнительном сегменте. М ы рассмотрели задание смещения операнда в памяти с помощью базового и/или индексного регистров, но часто операнд находится в фиксированной ячейке одного из сегментов. В этом случае целесообразно определить все смещение непосредственно в команде. Такой режим адресации операндов называется прямой адресацией памяти: смещение находится в двух байтах самой команды (конечно, "наоборот"). Как обычно, команда должна определить также код операции и сам факт прямой адресации памяти. Было бы удобно использовать для указания режима комбинацию бит в полях modи r/т. К сожалению, все комбинации уже исчерпаны для косвенной адресации памяти и регистровой адресации, поэтому для нашей цели придется привлечь какую-то редко используемую комбинацию. Такой комбинацией оказалась mod= 00 и r/т = 110. Как пример, на рис. 2.15 показана команда, которая производит инкремент байта со смещением 0101 1010 1111 0000 в текущем сегменте данных. Для прямой адресации пришлось пожертвовать косвенной адресацией через ВР (без индексного регистра и с нулевым смещением в команде), но ее можно реализовать, указав mod= 01 и введя дополнительный байт для нулевого смещения в команде. Два операнда. Разобравшись с однооперандными командами, обратимся к командам, имеющим два операнда, например ADD. Мы уже говорили, что эта команда берет значение одного операнда, прибавляет его к значению второго операнда и запоминает результат на месте любого операнда. Если разрешить нахождение обоих операндов в памяти, в команде потребовались бы поля modи r/т для каждого из них. Чтобы сократить длину команд, было решено, что, по крайней мере, один из операндов должен быть в регистре. Тогда в команде потребуются поля modи r/т только для одного операнда, а для другого достаточно поля reg(рис. 2.16). Поле wпоказывает, являются операнды байтами (w = 0) или словами (w = 1). В команде появилось также новое поле d(приемник); если d= 0, результат запоминается в операнде, определяемом полями modи r/т, a если d - 1 - в операнде, определяемом полем reg. Операнд, в котором запоминается результат, называется приемником, а другой операнд называется источником. В качестве примера рассмотрим команду ADD, показанную на рис. 2.17. Она имеет код операции 000000. Поле w = 0 показывает, что оба операнда являются байтами. Определяемым полем regоперандом оказывается регистр СН. Поле mod= 11 означает, что поля modи r/т определяют регистр, а поле r/т конкретизирует регистр BL. Поле d = 1 показывает запись результата в операнд, определяемый полем reg, т.е. в регистр СН. Следовательно, команда прибавляет содержимое регистра BL (источника) к содержимому регистра СН (приемника) и помещает результат в СН. Одним из операндов в двухоперандной команде может быть константа, содержащаяся в самой команде как непосредственный операнд. Этим достигаются два преимущества: уменьшается требуемая память (не нужно хранить адрес данных и сами данные) и процессор быстрее получает данные. П римером команды с непосредственным операндом служит команда MOV (переслать). Она часто применяется для загрузки константы в регистр. Здесь непосредственный операнд можно определить полем reg, и команда приобретает простую форму, показанную на рис. 2.18. Поле wпо-прежнему задает длину операнда 8 (w= 0) или 16 (w= 1) бит; в первом случае непосредственный операнд занимает один байт в команде, а во втором — два байта. Как пример, на рис. 2.19 представлена команда, которая передает значение 1111 0000 0000 1111 в регистр DI. В несколько более сложной команде операнд-приемник определяется полями modи r/т вместо поля reg, поэтому в команде появляется дополнительный байт (рис. 2.20). Показанная на рис. 2.21 команда передает значение 1111 0000 0000 1111 в слово, находящееся в сегменте данных со смещением из регистра DI. Т ак как двух операндная команда имеет только одно поле w, оба операнда должны иметь длину 8 или 16 бит. Однако часто непосредственные операнды являются небольшими числами и не требуют 16 бит. Это утверждение особенно справедливо для команд сложения, вычитания и сравнения, хотя для операндов логических команд оно обычно не выдерживается. Следовательно, можно уменьшить размер команд с непосредственными операндами, если не отводить 16 бит для хранения небольших чисел. Поэтому в некоторых командах (сложение, вычитание и сравнение) введен бит s (sозначает "с расширением знака"). Он занимает место бита d, так как в командах с непосредственными операндами возможно только одно направление. Поле s имеет смысл только для 16-битных операндов (w = 1) и показывает, содержатся ли в команде все 16 бит непосредственного операнда (s = 0) или только 8 бит (s = 1), которые должны расширяться со знаком до 16 бит для образования 16-битного операнда. Такая форма команды иллюстрируется рис. 2.22. Соответствующий пример показан на рис. 2.23. Здесь к содержимому слова в памяти прибавляется значение 0000 0000 0000 1111 и результат помещается в это же слово. Слово находится в сегменте данных, а смещение его берется из регистра DI. Отметим, что благодаря биту s экономится один байт. 2.7. ЗАМЕЧАНИЯ О РЕЖИМАХ АДРЕСАЦИИ После знакомства с режимами адресации возникают следующие вопросы: 1. Нужно ли практически пользоваться полями mod, reg, r/т, w, s, d и др. при использовании любой команды с операндами? 2. Зачем предусмотрено так много режимов адресации? Ответ на первый вопрос отрицательный, если, конечно, вы не собираетесь писать программу на машинном языке. Имея такие средства программирования, как Ассемблер или компилятор, вам никогда не придется обращаться к полям mod, reg, r/т и др.; любой Ассемблер или компилятор освободит вас от этих деталей. Для понимания ответа на второй вопрос нужно знать, что семейство процессоров 86 разработано с учетом трансляции программ на языках высокого уровня в эффективный код, т.е. в программы на машинном языке. Были проанализированы типичные фрагменты программ на языках высокого уровня и их требования к режимам адресации. Рассмотрим некоторые из этих требований. Большинство языков программирования оперируют простыми переменными и массивами. Переменная называется простой, если она представляет единственное значение, а массивом называется переменная, которая представляет последовательность значений. Рассмотрим типичный оператор присваивания, имеющийся в большинстве языков высокого уровня: А(i) = Х Он читается так: "i-й элемент А становится равным X". Его можно преобразовать в команды, которые пересылают содержимое ячейки памяти, соответствующей простой переменной X, в регистр, например BL, а затем пересылают содержимое BL в ячейку памяти, соответствующую i-му элементу массива А. Пусть X - это содержимое ячейки со смещением 0FF0 в текущем сегменте данных, а А(0) - это первый элемент массива А со смещением 0FF1 в этом же сегменте. Машинная команда, которая пересылает X в регистр BL, показана на рис. 2.24, а. В ней с помощью специальной комбинации полей mod и r/т задается прямая адресация памяти. Поскольку обращения к простым переменным (таким, как X) встречаются часто, неудивительно наличие такого режима адресации. На рис. 2.24, б показана машинная команда, которая передает содержимое регистра BL в ячейку А (I). Здесь предполагается, что в индексном регистре уже находится значение индекса I. Подобные обращения к массиву показывают необходимость режима косвенной адресации памяти "индексный регистр + смещение (в команде)". Операторы присваивания вида A(I) - B(J) требуют, по крайней мере, двух индексных регистров с указанным выше режимом адресации "SI + смещение (в команде)" и "DI + смещение (в команде)". Такие обращения к массиву, как А (I + 2), не встречают дополнительных сложностей; поле смещения в команде на рис. 2.24, б будет просто содержать 0FF3, т.е. смещение А(2), а не смещение А(0). В некоторых языках высокого уровня применяются указатели. Указатель - это переменная, содержащая адрес памяти некоторой другой переменной, которую мы назовем указываемой или адресуемой. Если значение указателя (т.е. значение в ячейке памяти, соответствующей указателю) изменяется, указываемая переменная будет соответствовать другой ячейке памяти. Удобный доступ к указываемой переменной заключается в том, чтобы поместить значение указателя в регистр ВХ, а затем воспользоваться режимом адресации с привлечением ВХ, т.е. режим "ВХ" следует применять для обращения к простой указываемой переменной (простой переменной, адресуемой указателем), а режимы "ВХ + SI" и "ВХ + DI" - к элементу в указываемом массиве (массиве, адресуемом указателем). В языках высокого уровня применяются также записи. Под записью (иногда называемой структурой) понимается набор именованных элементов данных, возможно, различных типов. Запись не совпадает с понятием массива, представляющего собой последовательность (наименованных) элементов данных одного и того же типа. Например, в программе начисления заработной платы имеются записи, соответствующие каждому работнику. Запись может содержать фамилию работника, номер страхового полиса, год поступления на работу и почасовую ставку. Конкретный элемент записи, например год поступления на работу, находится в одной и той же позиции во всех записях. Если, например, эта информация находится в четвертом байте от начала записи и запись для Джона Доу начинается со смещением 0ЗВ4, то год поступления на работу этого сотрудника содержится в ячейке памяти со смещением 0ЗВ7. Следовательно, положение любого элемента в записи фиксировано, и к нему можно обратиться с помощью прямой адресации; по существу, здесь нет отличий от простой переменной. Рассмотрим теперь указываемую запись и предположим, что указатель записи находится в регистре ВХ. Режим адресации для обращения к элементу такой записи имеет вид "ВХ + смещение (в команде)", причем смещение в команде соответствует позиции элемента в записи. Например, для указываемой записи о работнике смещение (в команде) байта о годе поступления на работу равно 3. Если запись невелика (менее 256 байт), для смещения в команде достаточно S бит и можно использовать режим с mod= 01. Хотя режим адресации операнда для обращения к элементу указываемой записи похож на режим обращения к элементу массива (оба они имеют вид "регистр + смещение (в команде)", между ними имеется существенная разница. В случае массива элементов смещение в команде соответствует началу массива, а регистр - расстоянию в массиве. В случае же указываемых записей регистр соответствует началу записи, а смещение в команде - расстоянию в записи. Рассмотрим массив, в котором каждый элемент является записью о работнике. Более того, будем считать, что это указываемый массив. Предположим, что указатель находится в регистре ВХ, а индекс, соответствующий элементу массива, в регистре SI. Тогда режим адресации для доступа к элементу года поступления конкретной записи имеет вид "ВХ + SI + смещение (в команде)", где смещение в команде равно 3. Такая ситуация оправдывает наличие в процессоре 80286 наиболее сложного режима адресации "базовый регистр + индексный регистр + смещение (в команде)". Остается показать необходимость режимов адресации с привлечением ВР как базового регистра и сегмента стека вместо сегмента данных. Эти режимы предназначены для эффективной реализации языков с блоковой структурой и реентрантных процедур. Процедура называется реентрантной, если ее можно вызывать тогда, когда она выполняется от предыдущего вызова. Подобная ситуация возникает, если: процедура вызывает саму себя; процедура вызывается некоторой другой процедурой, которая, в свою очередь, вызвана первоначальной процедурой; выполнение процедуры было приостановлено из-за прерывания, а при обработке прерывания эта же процедура была вызвана вновь. Все используемые реентрантной процедурой данные (локальные переменные и параметры) должны иметь уникальное размещение в памяти для каждого параллельного вызова процедуры, иначе данные, используемые одним вызовом процедуры, будут разрушены последующим вызовом. Это означает, что при каждом вызове процедуры для ее данных нужно распределять память. Такая область памяти называется стековым кадром (подробнее см. гл. 3). Конечно, весьма желательно, чтобы при своем завершении процедура освобождала бы эту область памяти. Поскольку последняя вызванная процедура заканчивается первой, удобным местом для распределения памяти оказывается стек. При каждом вызове процедуры для стекового кадра резервируется блок памяти в вершине стека путем простого изменения содержимого регистра SP. При выполнении процедуры необходим указатель начала стекового кадра, функции которого выполняет регистр ВР. К элементам внутри стекового кадра можно обращаться в режимах адресации с привлечением регистра ВР. Например, к простой переменной в стековом кадре можно обратиться в режиме "ВР + смещение (в команде)", а к элементу массива - в режиме "ВР + SI + + смещение (в команде)". Поскольку в образовании адреса участвует регистр ВР, обращение происходит к текущему сегменту стека (а не к текущему сегменту данных), в котором и находится стековый кадр. Применение режимов адресации в языках высокого уровня показано в табл. 2.5.
|