Инструменты пользователя

Инструменты сайта


examination:asm:question10

Вопрос №10. Запись команд на ЯА, основные форматы команд, сегментирование и индексирование. Счетчик адреса. Примеры.

Запись команд на языке Ассемблера

Если в команде присутствуют оба операнда (и отправитель, и получатель), при ее описании используется естественный порядок операндов, принятый во всех командах процессоров Intel 80×86: первым указывается операнд-получатель данных, а вторым — операнд-отправитель или источникданных. Например, при выполнении приведенной ниже команды MOV содержимое исходного операнда будет скопировано в операнд-получатель:

MOV получатель, источник

Основные форматы команд в ассемблере

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

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

Мнемоникой команды называется короткое имя, с помощью которого определяется тип выполняемой процессором операции. В английском толковом словаре слово мнемоника определяется как методика запоминания чего-либо. По этой причине мнемоникам команд назначены короткие, но в тоже время осмысленные имена, такие как mov, add, sub, mul, jmp или call.

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

Ниже приведено несколько примеров ассемблерных команд, содержащих различное количество операндов.

Например, команда STC не содержит операндов вовсе:

stc; Установить флаг переноса (Carry flag)

Команда inc содержит только один операнд:

inc ах; Увеличить на 1 значение регистра АХ

Команда MOV имеет два операнда:

mov count, bх;Переместить содержимое регистра ВХ в переменную count

Основные форматы двухоперандных команды:

на примере mov:

MOV reg,reg

MOV reg,mem

MOV reg,reg

MOV reg,imm

MOV mem,imm(?)

MOV regl6, segreg

MOV segreg, regl6

MOV segreg, meml6

MOV meml6,segreg

Сегментирование и индексирование

Сегментирование.

Сегменты памяти. Сегментные регистры.

Первые модели ПК имели оперативную память объемом 2^16 байтов (64Кб) и потому использовали 16-битовые адреса. В последующих моделях память была увеличена до 2^20 байтов (1Мб=1000Кб), для чего уже необходимы 20-битовые адреса. Однако в этих ПК ради сохранения преемственности были сохранены 16-битовые адреса: именно такие адреса хранятся в регистрах и указываются в командах, именно такие адреса получаются в результате модификации по базовым и индексным регистрам. Как же удается 16-битовыми адресами ссылаться на 1Мб памяти?

Эта проблема решается с помощью сегментирования адресов (неявного базирования адресов). В ПК вводится понятие «сегмент памяти». Так называется любой участок памяти размером до 64Кб и с начальным адресом, кратным 16. Абсолютный (20-битовый) адрес A любой ячейки памяти можно представить как сумму 20-битового начального адреса (базы) B сегмента, которому принадлежит ячейка, и 16-битового смещения D - адреса этой ячейки, отсчитанного от начала сегмента: A=B+D. (Неоднозначность выбора сегмента не играет существенной роли, главное - чтобы сумма B и D давала нужный адрес.)

Адрес B заносится в некоторый регистр S, а в команде, где должен быть указан адрес A, вместо него записывается пара из регистра S и смещения D (в MASM такая пара, называемая адресной па рой или указателем, записывается как S:D). Процессор же устроен так, что при выполнении команды он прежде всего по паре S:D вычисляет абсолютный адрес A как сумму содержимого регистра S и смещения D и только затем обращается к памяти по этому адресу A. Вот так, заменяя в командах абсолютные адреса на адресные пары, и удается адресовать всю па мять 16-битовыми адресами (смещениями).

В качестве регистра S разрешается использовать не любой регистр, а только один из 4 регистров, называемых сегментными: CS, DS, SS и ES.

Сегментирование, базирование и индексирование адресов

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

Счетчик адреса

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

Транслятор ассемблера обеспечивает нам две возможности работы с этим счетчиком:

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

Классический пример:

.data

;вычисление длины строки в сегменте данных

Str_Mes db «Займись делом - учи ассемблер …»

Len_Msg=$-Str_Mes

После ассемблирования значение Len_Msg будет равно длине строки, так как значение символа $ в месте его появления отличается от Str_Mes ровно на длину строки.

  • Другое применение, избавляющее программиста от необходимости «плодить» лишние метки в программе, — реализация близкого, буквально через следующую или предыдущую команды, перехода. Для примера рассмотрим фрагмент программы:

cmp dl,9h ;сравнить (dl) с 9h

jle $+5 ;перейти на команду mov cl.,4h, если dl<9h или dl=9h

sub dl,7h ;вычитание: (dl)=(dl)47h

;M1: mov cl,4h ;пересылка 4h в регистр cl

cmp al,9h ;сравнить (al) с 9h 28

jle $+4 ;перейти на команду add dl.al, если al<9h или al=9h

sub al,7h ;вычитание: (al)=(al)47h

;M2:/ add dl.al

examination/asm/question10.txt · Последние изменения: 2014/01/15 12:12 (внешнее изменение)