Максимов Н.В., Партыка Т.Л., Попов И.И. Архитектура ЭВМ и вычислительных систем (2005) (1186253), страница 79
Текст из файла (страница 79)
В этом регистре (слове памяти)должен находиться адрес, по которому и будет произведен переход.Например, по команде JMP BX осуществляется переход по адресу,находящемуся в регистре вх.4. Межсегментный абсолютный прямой переход.JMP s e g : o f s (CS := seg, IP := o f s )Здесь seg — начало (первые 16 битов начального адреса) некоторого сегмента памяти, a o f s — смещение в этом сегменте. Параs e g : o f s определяет абсолютный адрес, по которому делается переход. В MASM эта пара всегда задается конструкцией FAR PTR <метка>, которая указывает, что надо сделать переход по указанной метке, причем эта метка — «дальняя», из другого сегмента.
Отметим,что ассемблер сам определяет, какой это сегмент, и сам подставляетв машинную команду его начало, т. е. seg.5. Межсегментный абсолютный косвенный переход.JMP m32 (CS := [т32 + 2 ] , IP := [т32])Здесь под т32 понимается адрес двойного слова памяти, в котором находится пара s e g : o f s , задающая абсолютный адрес, по которому данная команда должна выполнить переход. Напомним, что в180X86 величины размером в двойное слово хранятся в «перевернутом» виде, поэтому смещение o f s находится в первом слове двойногослова тЗ2, а смещение seg — во втором слове (по адресу тЗ2 + 2).Команды межсегментного перехода используются тогда, когдакоманды программы размещены не в одном сегменте памяти, а внескольких (например, если команд так много, что в совокупности4.3.
Режимы процессора. Система команд процессоров 180x86...405они занимают более 64 Кб, т. е. больше максимального размера сегмента памяти). При переходе из одного такого сегмента в другойнеобходимо менять не только счетчик команд IP, но и содержимоерегистра CS, загружая в последний начальный адрес второго сегмента. Такое одновременное изменение обоих этих регистров и делаюткоманды межсегментного перехода.При записи в MASM команд перехода следует учитывать, чтоони могут восприниматься неоднозначно. Скажем, как воспринимать командуJMP Aкак переход по метке А или как переход по адресу, хранящемуся вячейке с именем А?Кроме того, какой это переход — внутрисегментный или межсегментный? Ответ зависит от того, как описано имя А, и от того,когда описано имя А — до или после команды перехода.Пусть А описано до команды перехода (ссылка назад).
Если именем А помечена некоторая команда текущего сегмента команд (т. е.А — метка), тогда ассемблер формирует машинную команду внутрисегментного относительного перехода. Если же А — имя переменной, тогда ассемблер формирует машинную команду косвенного перехода — внутрисегментного, если А описано в директиве DW, илимежсегментного, если А описано в директиве DD.В случае же, если имя А описано после команды перехода (ссылка вперед), ассемблер всегда формирует машинную команду внутрисегментного относительного длинного перехода.
С учетом этого имяА обязательно должно быть меткой команды из текущего сегментакоманд, иначе будет зафиксирована ошибка. Если такая трактовкассылки вперед не удовлетворяет автора программы, то он обязан спомощью оператора SHORT или PTR уточнить тип имени А:JMP SHORT А /внутрисегментный короткий переход по меткеJMP WORD PTR A ;внутрисегментный косвенный переходJMP DWORD РТЕ А /межсегментный косвенный переходОтметим, что переход по метке А из другого сегмента командвсегда должен указываться с помощью FAR PTR (независимо от того,описана метка А до или после команды перехода):JMP FAR PTR А /межсегментный переход по меткеУ с л о в н ы е п е р е х о д ы .
Практически во всех командах условного перехода проверяется значение того или иного флага (например, флага нуля ZF) и, если он имеет определенное значение,1406Глава 4. Персональные компьютерывыполняется переход по адресу, указанному в команде. Значениефлага должно быть установлено предыдущей командой, напримеркомандой сравненияCMP o p l , o p 2которая вычисляет разность ор! - ор2, однако результат никуда незаписывает, а только меняет флаги, на которые будет реагироватькоманда условного перехода.В MASM команды условного перехода имеют следующуюформу:Jxx opгде хх — одна или несколько букв, в сокращенном виде отражающих проверяемое условие (обычно в предположении, что перед этойкомандой находится команда сравнения).Примеры некоторых мнемонических записей:JE - переход «по равно» (jump if equal)JL - переход «по меньше» (jump if less)JNL - переход «по не меньше» (jump if not less)Особенностью всех машинных команд условного перехода является то, что они реализуют внутрисегментный относительный короткий переход, т.
е. добавляют к счетчику команд IP свой операнд,рассматриваемый как число со знаком от -128 до 127. В MASM этотоперанд всегда должен записываться как метка, которую ассемблерзаменит на соответствующий сдвиг.Такая особенность команд условного перехода вызывает неудобство при переходах на «дальние» команды. Например, если надосделать переход при А < в на команду, помеченную меткой L ирасположенную далеко от команды перехода, то приходится использовать команду длинного безусловного перехода:MOV AX,AСМР АХ,В ;сравнение А и ВJNL М ;не меньше —> М (обход команды JMP)JMP L ;меньше —> L (длинный переход)М: ...К о м а н д ы у п р а в л е н и я ц и к л о м .
В 180X86 есть несколькокоманд, упрощающих программирование циклов с заранее известным числом повторений. Применение этих команд требует, чтобы кначалу цикла в регистр сх было занесено число шагов цикла. Самикоманды размещаются в конце цикла, они уменьшают значение сх4.3. Режимы процессора. Система команд процессоров 180x86...407на 1 и, если сх еще не равно 0, передают управление на началоцикла. Например, найти s — сумму элементов массива х из 10 чисел-слов можно так:MOV АХ,0 ;начальное значение суммы (накапливается в АХ)MOV 31,0 /начальное значение индексного регистраMOV СХ,10 ;число повторений циклаL: ADD AX,X[SI] ;АХ:=АХ+Х[i]ADD SI,2 ;SI:=SI+2LOOP L ;CX:=CX-1; if CXOO then goto LMOV S,AX ;S:=AXПомимо команды LOOP есть еще две «циклические» команды —LOOPZ и LOOPNZ (они имеют синонимичные названия LOOPE иLOOPNE), которые, кроме регистра сх, проверяют еще и флаг нуляZF; например, команда LOOPZ «выходит» из цикла, если сх = 0 илиZF = 1.
Эту команду можно, например, использовать при поиске вмассиве первого нулевого элемента, где должно быть предусмотренодва условия выхода из цикла: либо будет найден нулевой элемент(ZF = 1, если перед LOOPZ поставить команду сравнения очередного элемента с 0), либо будет исчерпан весь массив (сх = 0).Отметим, что все эти «циклические» команды реализуют короткий относительный переход, как и команды условного перехода,поэтому их можно использовать только для циклов с небольшимчислом команд.В MASM есть еще две команды перехода — CALL (переход с возвратом) и RET (возврат из подпрограммы).Строковые операции.
В 180X86 под строкой понимается последовательность соседних байтов или слов. В связи с этим все строковыекоманды имеют две разновидности:• для работы со строками из байтов (в мнемонику операцийвходит буква в);• для работы со строками из слов (в мнемонику входит w).Имеются следующие операции над строками:• пересылка элементов строк (в память, из памяти, память—память);• сравнение двух строк;• просмотр строки с целью поиска элемента, равного заданному.Каждая из этих операций выполняется только над одним элементом строки, однако одновременно происходит автоматическаянастройка на следующий или предыдущий элемент строки.
Имеются специальные команды повторения (REP и др.), которые заставляют следующую за ними строковую команду многократно по-408Глава 4. Персональные компьютерывторяться (до 2 ) 6 раз), в связи с чем такая пара команд позволяетобработать всю строку, причем намного быстрее, чем запрограммированный цикл.Кроме того, строки можно просматривать вперед (от их началак концу) и назад. Направление просмотра зависит от флага направления DF, значение которого можно менять с помощью команд STD(DF := 1) и CLD (DF := 0 ) . При DF = О все последующие строковые команды программы просматривают строки вперед, а приDF = 1 — назад..В строковых командах операнды явно не указываются, а подразумеваются. Если команда работает с одной строкой, то адрес очередного (обрабатываемого сейчас) элемента строки задается паройрегистров DS и SI или парой ES и DI, а если команда работает сдвумя строками, то адрес элемента одной из них определяется парой DS:SI, а адрес элемента другой — парой ES:DI.
После выполнения операции значение регистра SI и/или DI увеличивается (приDF = 0) или уменьшается (при DF = 1) на 1 (для байтовых строк)или на 2 (для строк из слов).Начальная установка всех этих регистров, а также флага DFдолжна быть выполнена до начала операции над строкой. Если сегментный регистр DS уже имеет нужное значение, тогда загрузить регистр SI можно с помощью командыLEA SI,<начальный/конечный адрес строки>Если же надо загрузить сразу оба регистра DS и SI, тогда можновоспользоваться командойLDS SI,m32,которая в регистр si заносит первое слово, а в регистр DS — второеслово из двойного слова, имеющего адрес т32 (таким образом, поадресу т32 + 2 должен храниться сегмент, а по адресу т32 — смещение начального или конечного элемента строки).
Начальную загрузку регистров ES и DI обычно осуществляют одной командойLES DI,m32,которая действует аналогично команде LDS.Перечислим вкратце строковые команды 180X86:• команда загрузки элемента строки в аккумулятор (LODSB илиLODSW) пересылает в регистр AL или АХ очередной элементстроки, на который указывает пара DS.-SI, после чего увеличивает (при DF = 0) или уменьшает (при DF = 1) регистр siна 1 или 2;4.3. Режимы процессора. Система команд процессоров 180x86...409• запись аккумулятора в строку (STOSB или STOSW); содержимоерегистра AL или АХ заносится в тот элемент строки, на который указывает пара ES:Di, после чего изменяет регистр DI наI или 2;• пересылка строк (MOVSB или MOVSW); элемент первой строки,определяемый парой DS:Si, заносится в элемент второй строки, определяемый парой ES.-DI, после чего одновременно меняет регистры SI и DI;• сравнение строк (CMPSB или CMPSW); сравниваются очередныеэлементы строк, указываемые парами DS.-SI и ES.-DI, и результат сравнения (равно, меньше и т.
п.) фиксирует в флагах,после чего меняется содержание регистров si и DI;• сканирование строки (SCASB или SCASW) — сравнивается элемент строки, адрес которого задается парой ES:DI, со значением регистра AL или АХ и результат сравнения фиксирует вфлагах, после чего меняется содержимое регистра DI.Перед любой строковой командой можно поставить одну издвух команд, называемых «префиксами повторения», которая заставит многократно повториться эту строковую команду. Числоповторений (обычно это длина строки) должно быть указано в регистре сх.Префикс повторения REPZ (синонимы — REPE, REP) сначала заносит 1 в флаг нуля ZF, после чего, постоянно уменьшая сх на 1,заставляет повторяться следующую за ним строковую команду дотех пор, пока в сх не окажется «О» или пока флаг ZF не изменитсвое значение на 0.Другой префикс повторения REPNZ (синоним — REPNE) действует аналогично, но только вначале устанавливает флаг ZF в 0, а приизменении его на 1 прекращает повторение строковой команды.Пример.