assembler. Учебник для вузов_Юров В.И_2003 -637с (862834), страница 49
Текст из файла (страница 49)
Кроме того, наличие директивыorg lOOh предполагает:П отсутствие разделения сегментов данных и стека, то есть данные необходимо описать в сегменте кода, а для их обхода использовать команду безусловного перехода JMP;П применение директивы ASSUME для указания транслятору на необходимостьсвязать содержимое регистров DS и SS с сегментом кода:codeseg segment para "code"assume cs: codeseg,ds:codeseg,ss:codesegorg lOOhjmp ml;здесь описываем данныеml:;далее идут команды программыii Во-вторых, можно использовать специальную утилиту ехе2Ып.
Эта утилитапозволяет преобразовать уже полученный ранее исполняемый модуль в формате ЕХЕ в формат СОМ:e x e 2 b i n имя_файла_ехе имя_файла_сом.сотЭтот вариант не требует специального оформления исходного текста программы. Единственным требованием является то, чтобы исходный текст был довольно мал по объему.Интересный вариант использования директивы ORG рассмотрен в [8], гдес ее помощью выполняется динамическая модификация машинного кода команды.Безусловные переходыПредыдущее обсуждение выявило некоторые детали механизма перехода.
Команды перехода модифицируют регистр указателя команды EIP/IP и, возможно, сегментный регистр кода CS. Что именно должно подвергнуться модификации,зависит:Безусловные переходы215••• от типа операнда в команде безусловного перехода (ближний или дальний);от модификатора, который указывается перед адресом перехода в команде перехода и может принимать следующие значения (сам адрес при прямом переходе находится непосредственно в команде, а при косвенном — в регистре илиячейке памяти):П NEAR PTR — прямой переход на метку внутри текущего сегмента кода, приэтом модифицируется только регистр EIP/IP (в зависимости от заданноготипа сегмента кода use!6 или use32) на основе указанного в команде адреса(метки) или выражения, использующего символ извлечения значения счетчика адреса команд ($);П FAR PTR — прямой переход на метку в другом сегменте кода, при этом адресперехода задается в виде непосредственного операнда или адреса (метки)и состоит из 16-разрядного селектора и 16/32-разрядного смещения, которые загружаются, соответственно, в регистры CS и EIP/IP;D WORD PTR — косвенный переход на метку внутри текущего сегмента кода, приэтом модифицируется (значением смещения размером 16 или 32 бита изпамяти по указанному в команде адресу или из регистра) только регистрEIP/IP;D DWORD PTR — косвенный переход на метку в другом сегменте кода, при этоммодифицируются (значением из памяти — и только из памяти, из регистранельзя) оба регистра, CS и EIP/IP (первое слово/двойное слово адреса перехода, представляющее собой смещение, загружается в EIP/IP; второе/третьеслово — в CS).Команда безусловного переходаСинтаксис команды безусловного перехода без сохранения информации о точкевозврата:jmp [модификатор] адрес_переходаЗдесь адрес_перехода представляет метку или адрес области памяти, в которойнаходится указатель перехода.Всего в системе команд процессора есть несколько кодов машинных командбезусловного перехода JMP.
Их различия определяются дальностью переходаи способом задания целевого адреса. Дальность перехода определяется местоположением операнда адрес_перехода. Этот адрес может находиться в текущем сегменте кода или в некотором другом сегменте. В первом случае переход называетсявнутрисегментным, или близким, во втором — межсегментным, или дальним.Внутрисегментный переход предполагает, что изменяется только содержимоерегистра EIP/IP. Можно выделить три варианта внутрисегментного использованиякоманды JMP:к прямой короткий переход;К прямой переход;Ш косвенный переход.216Глава 10. Команды передачи управленияПрямой короткий внутрисегментный переход применяется, когда расстояниеот команды JMP до адреса перехода не превышает -128 или +127 байт. В этом случае транслятор ассемблера формирует машинную команду безусловного переходадлиной всего два байта (размер обычной команды внутрисегментного безусловного перехода составляет три байта). Первый байт в этой команде — код операции,значение которого говорит о том, что процессор должен особым образом трактовать второй байт команды.
Значение второго байта вычисляется транслятором какразность между значением смещения команды, следующей за JMP, и значениемадреса перехода. При осуществлении прямого короткого перехода нужно иметьв виду следующий важный момент, связанный с местоположением адреса перехода и самой команды JMP. Если адрес перехода расположен до команды JMP, то ассемблер формирует короткую команду безусловного перехода без дополнительных указаний. Если адрес перехода расположен после команды JMP, транслятор неможет сам определить, что переход короткий, так как у него еще нет информацииоб адресе перехода. Для оказания помощи компилятору в формировании командыкороткого безусловного перехода в дополнение к ранее упомянутым модификаторам используют модификатор SHORT PTR:jmp short ptr ml...
;не более 35-40 команд (127 байт)ml:Еще вариант:ml:. . . ; н е более 35-40 команд (-128 байт)jmp mlПрямой внутрисегментный переход отличается от прямого короткого внутрисегментного перехода тем, что длина машинной команды JMP в этом случае составляет три байта. Увеличение длины связано с тем, что поле адреса перехода в машинной команде JMP расширяется до двух байтов, а это, в свою очередь, позволяетпроизводить переходы в пределах 64 Кбайт относительно следующей за JMP команды:ml:...
расстояние более 128 байт и менее 64 Кбайтjmp mlКосвенный внутрисегментный переход подразумевает «косвенность» заданияадреса перехода. Это означает, что в команде указывается не сам адрес перехода,а место, где он «лежит». Приведем несколько примеров, в которых двухбайтовыйадрес перехода выбирается либо из регистра, либо из области памяти:lea bx.mljmp bx;адрес перехода в регистре Ьхml:.dataaddrjnl dw.codemlБезусловные переходыjmp addr_ml217;адрес перехода в ячейке памяти addrjnlmi:'Еще несколько вариантов косвенного внутрисегментного перехода:<2>.data<3>addr dw<4> dw m2ml<6>.code<8>cycl:mov s i , 0jmp addr[si];адрес перехода в слове памяти addr+(si)<14>ml:mov si.2jmp cycl<16>m2:В этом примере одна команда JMP (строка 10) может выполнять переходы наразные метки.
Выбор конкретной метки перехода определяется содержимым регистра SI. Операнд команды JMP определяет адрес перехода косвенно после вычисления выражения addr+(SI).<l>. . .<2>.data<3>addr dw ml<4>. . .<5>.code<6>...<7>lea si ,addr<8>jmp near ptr [si ] ;адрес перехода в ячейке памяти addrВ данном случае указание модификатора NEAR PTR обязательно, так как, в отличие от предыдущего способа, адрес ячейки памяти addr с адресом перехода транслятору передается неявно (строки 3, 7 и 8), и, не имея информации о метке, он неможет определить, какой именно переход осуществляется — внутрисегментный илимежсегментный. Межсегментный переход предполагает другой формат машиннойкоманды JM Р.
При осуществлении межсегментного перехода кроме регистра EIP/IPмодифицируется также регистр CS. Аналогично внутрисегментному переходу, межсегментный переход поддерживают два варианта команд безусловного перехода:прямой и косвенный.Команда прямого межсегментного перехода имеет длину пять байтов, из которых два байта составляют значение смещения и два байта — значение сегментнойсоставляющей адреса:seg_l segmentjmp far ptr m2mllabelseg_lendsfar;здесь far обязательно218Глава 10. Команды передачи управленияseg_2m2segmentlabeljmp mlfar;здесь far необязательноРассматривая этот пример, обратите внимание на модификатор FAR PTR в команде JMP.
Его необходимость объясняется все той же логикой работы однопроходного транслятора. Если описание метки (метка ml) встречается в исходном тексте программы раньше, чем соответствующая ей команда перехода, то заданиемодификатора необязательно, так как транслятор все знает о данной метке и самформирует нужную пятибайтовую форму команды безусловного перехода. В случае, когда команда перехода встречается до описания соответствующей метки,транслятор не имеет еще никакой информации о метке, и модификатор FAR PTRв команде JMP опускать нельзя, так как транслятор не знает, какую форму команды формировать — трехбайтную или пятибайтную.
Без специального указания модификатора транслятор будет формировать трехбайтную команду внутрисегментного перехода.Команда косвенного межсегментного перехода в качестве операнда имеет адресобласти памяти, в которой содержатся смещение и сегментная часть целевого адреса перехода:datasegmentaddrjnl dd ml ;в поле addr_ml значения смещения;и адреса сегмента метки mldataendscode_l segmentjmp mlcode_l endscode_2 segmentmllabelfarmov ax.bxcode_2 endsКак вариант косвенного межсегментного перехода необходимо отметить косвенный регистровый межсегментный переход.
В этом виде перехода адрес перехода указывается косвенно — в регистре. Это очень удобно для программированиядинамических переходов, в которых адрес перехода может изменяться на стадиивыполнения программы:datasegmentaddr_ml dd ml ;в поле addr_ml значения смещения;и адреса сегмента метки mldataendscode_l segmentlea bx,addrjnljmp dword ptr[bx]code_lcode_2mlendssegmentlabelfarmov ax.bxcode 2endsБезусловные переходы219Таким образом, модификаторы SHORT PTR, NEAR PTR и WORD PTR применяютсядля организации внутрисегментных переходов, a FAR PTR и DWORD PTR — межсегментных.Для полной ясности нужно еще раз подчеркнуть, что если тип сегмента — use32,то в тех местах, где речь шла о регистре IP, можно использовать регистр EIP и, соответственно, размеры полей смещения увеличить до 32 битов.ПроцедурыДо сих пор мы рассматривали примеры программ, предназначенные для однократного выполнения.
Но, приступив к программированию достаточно серьезной задачи, вы наверняка столкнетесь с тем, что у вас появятся повторяющиесяфрагменты кода. Одни из них могут состоять всего из нескольких команд, другиезанимать и достаточно много места в исходном коде. В последнем случае эти фрагменты существенно затруднят чтение текста программы, снизят ее наглядность,усложнят отладку и послужат неисчерпаемым источником ошибок. В языке ассемблера есть несколько средств, решающих проблему дублирования фрагментовпрограммного кода.