Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
57
Добавлен:
20.03.2015
Размер:
395.26 Кб
Скачать

5.2. Команды ia-32

Набор команд архитектуры IA-32 очень обширен. Машинные команды имеют пе­ременную длину и не всегда однотипный формат, о чем будет рассказано ниже. В большинстве команд IA-32 задаются один или два операнда. Если опе­рандов два, только один их них может храниться в памяти, а другой должен находиться в регистре процессора. Наряду с обычными командами для пересыл­ки данных между памятью и регистрами процессора, выполнения арифметиче­ских операций в наборе команд IA-32 имеется множество команд для реализации логических операций, операций сдвига и циклического сдвига, а также для мани­пулирования стеком процессора. Для обработки нечисловых данных предусмот­рены команды, оперирующие строками байтов.

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

ADD dst,src

выполняет операцию

dst <- [dst] + [src]

а команда

MOV src dst

как вы уже знаете, — операцию

dst <- [src]

Предположим, что операнды хранятся в регистрах ЕАХ и ЕВХ. Следующие две команды вычисляют сумму операндов в регистре ЕАХ и сохраняют ее в памя­ти по адресу SUM:

ADD EAX,EBX

MOV SUM,EAX

Поскольку в памяти может располагаться только один из операндов команды, для реализации операции С<-[А]+[В] с тремя операндами в памяти потребуется целых три команды:

MOV ЕАХ,А

ADD EAX,B

MOV С,ЕАХ

Команда вычитания

SUB dst,src

выполняет операцию

dst <- [dst] - [src]

Для увеличения и уменьшения операнда на 1 предназначены команды авто­увеличения (инкремента) и автоуменьшения (декремента), INC и DEC.

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

JG LOOPSTART

осуществляет переход по адресу LOOPSTART. Все команды условного перехода начинаются с буквы J, соответствующей слову Jump (переход), за которой следу­ют буквы, обозначающие условие. В данном примере буква G обозначает «боль­ше нуля». О других командах условного перехода будет рассказано чуть позже.

Чтобы получить возможность при косвенной регистровой адресации исполь­зовать регистр общего назначения, нужно сначала загрузить в такой регистр ад­рес операнда команды. Это можно сделать двумя способами. Если для нужного адреса в программе явно определена адресная метка, скажем LOCATION, этот ад­рес можно загрузить в регистр при помощи команды Move и с применением непо­средственной адресации, вот так:

MOV EBX,OFFSET LOCATION

Данная команда загружает в регистр ЕВХ адрес, представленный меткой LO­CATION. В качестве альтернативы можно задействовать команду Load Effective Address (загрузка исполнительного адреса) с мнемоническим обозначением LEA. Команда

LEA EBX,LOCATION

выполняет ту же операцию, что и приведенная выше команда. При помощи ко­манды LEA можно загружать в регистры адреса, динамически вычисляемые во время выполнения программы. Предположим, нам нужно загрузить в регистр ЕВХ адрес операнда, для доступа к которому применяется базовая адресация со смещением. Команда

LEA ЕВХ,[ЕВР+12]

загрузит в регистр ЕВХ адрес операнда, расположенного по адресу [ЕВР]+12. Ад­рес зависит от содержимого регистра ЕВP в момент выполнения команды.

Программа для сложения чисел

Используя только что описанные команды, мы можем создать программу для сложения чисел при помощи цикла. Предположим, что в памяти по адресу N со­держится набор 32-разрядных чисел, расположенных последовательно начиная с адреса NUM1. На рис. 5.8. приведена программа на языке ассемблера, склады­вающая эти числа и помещающая результат в память по адресу SUM.

Рис. 5.8. Простая программа для процессоров IA-32, выполняющая сложение последовательности чисел.

В регистр ЕВХ загружается значение адреса NUM1. Он используется как ба­зовый регистр при базовой индексной адресации в первой команде цикла, распо­ложенной по адресу STARTADD. Индексным регистром здесь является EDI. Пе­ред началом цикла он очищается путем записи в него значения 0. На первой итерации цикла к содержимому регистра ЕАХ, первоначально установленному в 0, прибавляется первое число из списка, хранящееся по адресу [ЕВХ] = NUM1. Затем значение индексного регистра увеличивается на 1. На второй итерации цикла к содержимому регистра ЕАХ прибавляется второе 32-разрядное число, расположенное по адресу NUM1 + 4, поскольку в команде Add задан коэффици­ент масштабирования 4. На следующих итерациях к сумме прибавляются числа, находящиеся по адресам NUM1 + 8, NUM1 + 12,.... В качестве счетчика исполь­зуется регистр ЕСХ. Сначала вторая команда программы загружает в него значе­ние, хранящееся в памяти по адресу N. Далее на каждой итерации цикла значение в этом регистре уменьшается на 1. Команда условного перехода JG выполняет пе­реход к началу цикла по адресу STARTADD, если [ЕСХ] > 0. Когда содержимое регистра ЕСХ становится равным нулю, это означает, что все числа списка сложе­ны. В таком случае переход не осуществляется и следующая команда пересылки сохраняет содержимое регистра ЕАХ в памяти по адресу SUM.

Приведенную на рис. 5.8. программу можно переписать более компактно. Обратите внимание на команды

DEC ЕСХ

JG STARTADD

в конце программного цикла. Они очень часто выполняются в конце циклов. По­этому в набор команд процессора IA-32 включена команда, объединяющая их функции. Команда

LOOP STARTADD

сначала уменьшает содержимое регистра ЕСХ, а затем выполняет переход по ад­ресу STARTADD, если значение ЕСХ не равно нулю.

Рис. 5.9. Усовершенствованная версия программы для процессоров IA-32, выполняющая сложение списка чисел;

Вторая возможность сокра­тить размер программы связана с двумя регистрами, EDI и ЕСХ, которые исполь­зовались в качестве счетчиков. Если мы будем сканировать список складываемых чисел в обратном направлении, то есть от конца к началу, то нам потребуется только один счетчик. Воспользуемся регистром ЕСХ, поскольку он неявно при­меняется в команде LOOP. Так как [N] = n, последовательные значения регистра EDI в первой программе равны 0,1, 2,..., n, и программа считывает числа по адре­сам NUM1, NUM1 + 4, NUM1 + 8,..., NUM1 + 4(n - 1). Новая программа считы­вает числа по адресам (NUM1 - 4) + 4n, (NUM1 - 4) + 4(n - 1),.... (NUM1 - 4) + 4(1), а регистр ЕСХ в ней принимает значения n, n - 1,..., 1 (рис. 5.9.). Поэтому значение в базовом регистре ЕВХ, в первой программе равное NUM1, нужно изме­нить на NUM1 - 4, что позволит учесть различие между значениями регистров EDI и ЕСХ. На последней итерации цикла новой программы перед выполнением команды LOOP регистр ЕСХ содержит значение 1, и из памяти по адресу NUM1 считывается последнее из складываемых чисел.

Обработка списков и массивов всегда требует внимательности, особенно при выборе условия перехода и метода индексации — с нуля или единицы. Неверный выбор может привести к ошибкам в программе. В языках высокого уровня эта за­дача упрощается, поскольку к элементам списка можно явно обращаться как к LIST(0), LIST(1), ..., LIST(n-l), а начало и конец цикла можно явно связать со значениями индекса при помощи таких выражений, как

FOR I FROM 0 UPTO (n-1)

или

FOR I FROM (n-1) DOWNTO 0

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

Формат машинных команд

Общий формат машинных команд процессоров IA-32 показан на рис. 5.10. Ко­манды имеют переменную длину — от 1 до 12 байт и могут включать до четырех полей. Команды длиной в 1 байт содержат только обязательное поле кода опера­ции. Как правило, длина этого поля составляет 1 байт, иногда — 2 байта. Информа­ция о режиме адресации содержится в одном или двух байтах, следующих за полем кода операции. В тех командах, где для формирования исполнительного адреса операнда используется только один регистр, поле режима адресации имеет длину 1 байт. Второй байт нужен для кодирования двух последних режимов адресации (см. табл. 5.1). В этих режимах для формирования исполнительного адреса опе­ранда нужно иметь 2 байта.

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

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

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

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

Рис. 5.10. Формат команды IA-32

Однобайтовые команды

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

Соседние файлы в папке Архитектура компьютеров