Рефераты. ЯЗЫК МАКРОАССЕМБЛЕРА IBM PC В систему команд ПК входит обычный для ЭВМ набор команд перехода: безусловные и условные переходы, переходы с возвратами и др. Однако в ПК эти команды имеют некоторые особенности, которые здесь и рассматриваются.
Абсолютный адрес команды, которая должна быть выполнена следующей, определяется парой CS:IP, поэтому выполнение перехода означает изменение этих регистров, обоих или только одного (IP). Если изменяется только счетчик команд IP, то такой переход называется внутрисегментным или близким (управление остается в том же сегменте команд), а если меняются оба регистра CS и IP, то это межсегментный или дальний переход (начинают выполняться команды из другого сегмента команд). По способу изменения счетчика команд переходы делятся на абсолютные и относительные. Если в команде перехода указан адрес (смещение) той команды, которой надо передать управление, то это абсолютный переход. Однако в команде может быть указана величина (сдвиг), которую надо добавить к текущему значению регистра IP, чтобы получился адрес перехода, и тогда это будет относительный переход; при этом сдвиг может быть положительным и отрицательным, так что возможен переход вперед и назад. По величине сдвига относительные переходы делятся на короткие (сдвиг задается байтом) и длинные (сдвиг - слово). Абсолютные же переходы делятся на прямые и косвенные: при прямом переходе адрес перехода задается в самой команде, а при косвенном - в команде указывается регистр или ячейка памяти, в котором (которой) находится адрес перехода.

1.5.1 Безусловные переходы.
В MASM все команды безусловного перехода обозначаются одинаково:
JMP op
но в зависимости от типа операнда, ассемблер формирует разные машинные команды.
1) Внутрисегментный относительный короткий переход.
JMP i8 (IP:=IP+i8)
Здесь i8 обозначает непосредственный операнд размеров в байт, который интерпретируется как знаковое целое от -128 до 127. Команда прибавляет это число к текущему значению регистра IP, получая в нем адрес (смещение) той команды, которая должна быть выполнена следующей. Регистр CS при этом не меняется.
Необходимо учитывать следующую особенность регистра IP. Выполнение любой команды начинается с того, что в IP заносится адрес следующей за ней команды, и только затем выполняется собственно команда. Для команды относительного перехода это означает, что операнд i8 прибавляется не к адресу этой команды, а к адресу команды, следующей за ней, поэтому, к примеру, команда JMP 0 - это переход на следующую команду программы.
При написании машинной программы сдвиги для относительных переходов приходится вычислять вручную, однако MASM избавляет от этого неприятного занятия: в MASM в командах относительного перехода всегда указывается метка той команды, на которую надо передать управление, и ассемблер сам вычисляет сдвиг, который он и записывает в машинную команду. Отсюда следует, что в MASM команда перехода по метке воспринимается не как абсолютный переход, а как относительный.
По короткому переходу можно передать управление только на ближайшие команды программы - отстоящие от команды, следующей за командой перехода, до 128 байтов назад или до 127 байтов вперед. Для перехода на более дальние команды используется
2) Внутрисегментный относительный длинный переход.
JMP i16 (IP:=IP+i16)
Здесь i16 обозначает непосредственный операнд размером в слово, который рассматривается как знаковое целое от -32768 до 32767. Этот переход аналогичен короткому переходу.
Отметим, что, встретив команду перехода с меткой, которой была помечена одна из предыдущих (по тексту) команд программы, ассемблер вычисляет разность между адресом этой метки и адресом команды перехода и по этому сдвигу определяет, какую машинную команду относительного перехода - короткую или длинную - надо сформировать. Но если метка еще
не встречалась в тексте программы, т.е. делается переход вперед, тогда ассемблер, не зная еще адреса метки, не может определить, какую именно машинную команду относительного перехода формировать, поэтому он на всякий случай выбирает команду длинного перехода. Однако эта машинная команда занимает 3 байта, тогда как команда короткого перехода - 2 байта, и если автор программы на MASM стремится к экономии памяти и знает заранее, что переход вперед будет на близкую метку, то он должен сообщить об этом ассемблеру, чтобы тот сформировал команду короткого перехода. Такое указание делается с помощью оператора SHORT:
JMP SHORT L
Для переходов назад оператор SHORT не нужен: уже зная адрес метки, ассемблер сам определит вид команды относительного перехода.
3) Внутрисегментный абсолютный косвенный переход.
JMP r16 (IP:=[r])
или JMP m16 (IP:=[m16])
Здесь r16 обозначает любой 16-битовый регистр общего назначения, а m16 - адрес слова памяти. В этом регистре (слове памяти) должен находиться адрес, по которому и будет произведен переход. Например, по команде JMP BX осушествляется переход по адресу, находящемуся в регистре BX.
4) Межсегментный абсолютный прямой переход.
JMP seg:ofs (CS:=seg, IP:=ofs)
Здесь seg - начало (первые 16 битов начального адреса) некоторого сегмента памяти, а ofs - смещение в этом сегменте. Пара seg:ofs определяет абсолютный адрес, по которому делается переход. В MASM эта пара всегда задается конструкцией FAR PTR <метка>, которая "говорит", что надо сделать переход по указанной метке, причем эта метка - "дальняя", из другого сегмента. Отметим, что ассемблер сам определяет, какой это сегмент, и сам подставляет в машинную команду его начало, т.е. seg.
5) Межсегментный абсолютный косвенный переход.
JMP m32 (CS:=[m32+2], IP:=[m32])
Здесь под m32 понимается адрес двойного слова памяти, в котором находится пара seg:ofs, задающая абсолютный адрес, по которому данная команда должна выполнить переход. Напомним, что в ПК величины размером в двойное слово хранятся в "перевернутом" виде, поэтому смещение ofs находится в первом слове двойного слова m32, а смещение seg - во втором слове (по адресу m32+2).
Команды межсегментного перехода используются тогда, когда команды программы размещены не в одном сегменте памяти, а в нескольких (например, команд столь много, что в совокупности они занимают более 64Кб, т.е. более максимального размера сегмента памяти). При переходе из одного такого сегмента в другой необходимо менять не только счетчик команд IP, но и содержимое регистра CS, загружая в последний начальный адрес второго сегмента. Такое одновременное изменение обоих этих регистров и делают команды межсегментного перехода.
При записи в MASM команд перехода следует учитывать, что они могут восприниматься неоднозначно. Скажем, как воспринимать команду
JMP A
- как переход по метке A или как переход по адресу, хранящемуся в ячейке с именем A? Кроме того, какой это переход - внутрисегментный или межсегментный? Ответ зависит от того, как описано имя A, и от того, когда описано имя A - до или после команды перехода.
Пусть A описано до команды перехода ("ссылка назад"). Если именем A помечена некоторая команда текущего сегмента команда (т.е. A - метка), тогда ассемблер формирует машинную команду внутрисегментного относительного перехода. Если же A - имя переменной, тогда ассемблер формирует машинную команду косвенного перехода - внутрисегментного, если A описано в директиве DW, или межсегментного, если A описано в директиве DD.
В случае же, если имя A описано после команды перехода ("ссылка вперед"), ассемблер всегда формирует машинную команду внутрисегментного относительного длинного перехода. С учетом этого имя A обязательно должно метить команду из текущего сегмента команд, иначе будет зафиксирована ошибка. Если такая трактовка ссылки вперед не удовлетворяет автора программы, тогда он обязан с помощью оператора SHORT или PTR уточнить тип имени A:
JMP SHORT A ;внутрисегментный короткий переход по метке
JMP WORD PTR A ;внутрисегментный косвенный переход
JMP DWORD PTE A ;межсегментный косвенный переход
Отметим, что переход по метке A из другого сегмента команд всегда должен указываться с помощью FAR PTR (независимо от того, описана метка A до или после команды перехода):
JMP FAR PTR A ;межсегментный переход по метке
1.5.2 Условные переходы.
Практически во всех командах условного перехода проверяется значение того или иного флага (например, флага нуля ZF) и, если он имеет определенное значение, выполняется переход по адресу, указанному в команде. Значение флага должно быть установлено предыдущей командой, например, командой сравнения
CMP op1,op2
которая вычисляет разность op1-op2, однако результат никуда не записывает, а только меняет флаги, на которые и будет реагировать команда
условного перехода.
В MASM команды условного перехода имеют следующую форму:
Jxx op
где xx - одна или несколько букв, в сокращенном виде отражающие проверяемое условие (обычно в предположении, что перед этой командой находится команда сравнения). Примеры некоторых мнемоник:
JE - переход "по равно" (jump if equal)
JL - переход "по меньше" (jump if less)
JNL - переход "по неменьше" (jump if not less)
Особеностью всех машинных команд условного перехода является то, что они реализуют внутрисегментный относительный короткий переход, т.е. добавляют к счетчику команд IP свой операнд, рассматриваемый как знаковое число от -128 до 127. В MASM этот операнд всегда должен записываться как метка, которую ассемблер заменит на соответствующий сдвиг (см. выше).
Такая особенность команд условного перехода вызывает неудобство при переходах на "дальние" команды. Например, если надо сделать переход при A<B на команду, помеченную меткой L и расположенную далеко от команды перехода, то приходится использовать команду длинного безусловного перехода:
MOV AX,A
CMP AX,B ;сравнение A и B
JNL M ;не меньше --> M (обход команды JMP)
JMP L ;меньше --> L (длинный переход)
M: ...

1.5.3 Команды управление циклом
В ПК есть несколько команд, упрощающих программирование циклов с заранее известным числом повторений. Применение этих команд требует, чтобы к началу цикла в регистр CX было занесено число шагов цикла. Сами команды размещаются в конце цикла, они уменьшают значение CX на 1 и, если CX еще не равно 0, передают управление на начало цикла. Например, найти S - сумму элементов массива X из 10 чисел-слов можно так:
MOV AX,0 ;начальное значение суммы (накапливается в AX)
MOV SI,0 ;начальное значение индексного регистра
MOV CX,10 ;число повторений цикла
L: ADD AX,X[SI] ;AX:=AX+X[i]
ADD SI,2 ;SI:=SI+2
LOOP L ;CX:=CX-1; if CX<>0 then goto L
MOV S,AX ;S:=AX
Помимо команды LOOP есть еще две "циклические" команды - LOOPZ и LOOPNZ (они имеют синонимичные названия LOOPE и LOOPNE), которых кроме регистра CX проверяют еще и флаг нуля ZF; например, команда LOOPZ "выходит" из цикла, если CX=0 или ZF=1. Эту команду можно, например, использовать при поиске в массиве первого нулевого элемента, где должно быть предусмотрено два условия выхода из цикла: либо будет найден ну-
левой элемент (ZF=1, если перед LOOPZ поставить команду сравнения очередного элемента с 0), либо будет исчерпан весь мсассив (CX=0)
Отметим, что все эти "циклические" команды реализуют короткий относительный переход, как и команды условного перехода, поэтому их можно использовать только для циклов с небольшим числом команд.
В MASM есть еще две команды перехода - CALL (переход с возвратом) и RET (возврат из подпрограммы), они рассматриваются в 1.7.

1.6. СТРОКОВЫЕ ОПЕРАЦИИ

Страницы: 1, 2, 3, 4, 5



2012 © Все права защищены
При использовании материалов активная ссылка на источник обязательна.