Что такое cdq в ассемблере
Что такое cdq в ассемблере
Базовая команда пересылки данных. Копирует содержимое источника в приемник, источник не изменяется. Команда MOV действует аналогично операторам присваивания из языков высокого уровня, то есть команда
языка С, за исключением того, что команда ассемблера позволяет работать не только с переменными в памяти, но и со всеми регистрами процессора.
В качестве источника для MOV могут использоваться: число (непосредственный операнд), регистр общего назначения, сегментный регистр или переменная (то есть операнд, находящийся в памяти). В качестве приемника — регистр общего назначения, сегментный регистр (кроме CS) или переменная. Оба операнда должны быть одного и того же размера — байт, слово или двойное слово.
Нельзя выполнять пересылку данных с помощью MOV из одной переменной в другую, из одного сегментного регистра в другой и нельзя помещать в сегментный регистр непосредственный операнд — эти операции выполняют двумя командами MOV (из сегментного регистра в обычный и уже из него в другой сегментный) или парой команд PUSH/POP.
|
|
|
|
Главная | Загрузка | Инструкция | Команды x86 | Карта сайта |
КОМАНДЫ ПЕРЕСЫЛКИ ДАННЫХКоманда пересылки данных
Команда MOV копирует содержимое второго операнда в первый операнд. При этом содержимое второго операнда не изменяется. Команда MOV не воздействует на флажки, состояние флажков не изменяется. В командах MOV с кодами A0, A1, A2, A3 обозначение addr(2/4) это задание адреса в оперативной памяти. Задается смещение относительно начала сегмента DS. Байты (два или четыре), задающие адрес, располагаются в самой команде следом за кодом операции. Размер адреса (2 или 4 байта) определяется атрибутом размера адреса команды. В командах MOV с кодами 89, 8B, A1, A3 размер операнда (2 или 4 байта) определяется атрибутом размера операнда команды. (Не путайте атрибут размера адреса и атрибут размера операнда, это две разные вещи.) Команда для засылки констант
Команда MOV с кодами C6, C7 обычно используется только для засылки константы в память и не используются для засылки константы в регистр, потому что для засылки константы в регистр есть более удобные команды с кодами от B0 до BF. Другие команды MOVКоманды пересылки с расширением операнда
Первый операнд является приемником (destination), второй операнд источником (source). Обе команды берут содержимое операнда источника, расширяют это значение до величины атрибута размера операнда команды (до 16 бит или до 32 бит) и заносят результат в операнд приемник. Команды MOVSX и MOVZX не воздействуют на флажки, состояние флажков не изменяется. Команды расширения операнда
Например, команда CBW берет знаковый бит из регистра AL (то есть, старший бит из AL) и заносит его во все биты регистра AH. Точно также, команда CWD берет знаковый (старший) бит из AX и заносит его во все биты регистра DX. При записи на языке ассемблера для этих команд операнды не указываются. Операнды заранее определены по умолчанию и не могут быть изменены. В таблице показаны операнды, действующие по умолчанию. Команды CBW, CWDE, CWD, CDQ не воздействуют на флажки, состояние флажков не изменяется. В таблице указан атрибут размера операнда, который требуется для каждой из команд. Если требуемый для команды размер не совпадает с общим режимом работы всей программы, то перед кодом операции данной команды должен стоять префикс для изменения атрибута размера операнда. (Это учитывает ассемблер при генерации кода). Команда обмена данными
Команда XCHG обменивает содержимое двух своих операндов. Значение, которое было до выполнения команды в первом операнде, оказывается в результате во втором операнде. А значение, которое было до выполнения команды во втором операнде, оказывается в результате в первом операнде. Команда XCHG не воздействует на флажки, состояние флажков не изменяется. Команда XCHG всегда имеет два операнда, причем оба операнда должны иметь одинаковый размер (1 байт, или 2 байта, или 4 байта). Операнды могут быть указаны в команде в любом порядке. Это очевидно из смысла выполняемой операции. Из всех вариантов команды XCHG только команда с кодом 86 может работать с операндами размером один байт. Машинные команды с кодами 90-97 и 87 могут работать с операндами, размером два байта или четыре байта. Размер операнда (2 или 4 байта) определяется атрибутом размера операнда команды. Пустая операцияИзвестны и еще несколько команд, которые тоже могут применяться, чтобы просто занимать место, причем занимать не один байт, а несколько. Но эти команды не имеют своего отдельного имени на языке ассемблера. Команда перестановки байтов в 32-битном регистре
Как известно, в процессорах x86 принят обратный порядок для расположения данных. Иногда возникает потребность показать результат с прямым порядком байтов. Изменить порядок байтов можно одной командой BSWAP, не делая лишних сдвигов и пересылок. Команда BSWAP не воздействует на флажки, состояние флажков не изменяется. Использование команды BSWAP для размера операнда «16 бит» не предусмотрено. Результат операции в этом случае не определен. 12. Команды расширенияВ программах довольно часто нужно переслать меньшее по длине значение в большую по длине переменную или регистр. В качестве примера предположим, что нам нужно загрузить 16-разрядное беззнаковое значение, хранящееся в переменной count, в 32-разрядный регистр ЕСХ. Самое простое решение этой задачи заключается в том, что вначале нужно обнулить регистр ЕСХ, а затем загрузить 16-разрядное значение переменной count в регистр СХ: Для выполнения расширения можно использовать готовые команды: Команда MOVZX Команда MOVSX Команды MOVSX и MOVZX применимы к следующим операндам: Ассемблер под Windows для чайников. Часть 9Приветствую постоянных читателей, а также тех, кто только решил влиться в ряды изучающих ассемблер под Windows. Сегодня весьма полезная тема и для первых, и для вторых. Потому что сегодня мы подробно рассмотрим основные команды ассемблера в теории. Обычно я строил наши занятия по большей части с практическим уклоном. Но теперь, когда вы уже получили достаточно примеров использования тех или иных команд ассемблера, пришла пора четко и безо всякой двусмысленности зафиксировать их в вашем понимании. Обычно ассемблер начинают изучать именно с теории. Но без представления возможностей практического применения тех или иных команд такое обучение, скорее всего, покажется скучным и малопонятным. Добавьте к этому сложность предмета программирования самого по себе, и получите вполне ожидаемый результат — потерю желания изучать ассемблер вообще. Надеюсь, что вы уже имеете определенное положительное мнение об ассемблере и твердо решили идти до конца. Если же вы все еще не верите в свои силы, то попытаюсь вас успокоить: основных команд в ассемблере немногим более сотни, учитывая то, что многие из них — синонимы (близкие или одинаковые по значению) или антонимы (прямо противоположные). Команд, которые необходимо запомнить для каждодневного использования — вообще не более двух-трех десятков. Причем запоминать их все и сразу вам не обязательно. Просто сохраните эту статью, и всегда сможете быстро вспомнить название и назначение той или иной команды. Не забывайте, что данный цикл статей опирается на синтаксис, используемый в компиляторе FASM. Прежде всего, придется помучить вас маленьким, но очень важным моментом — регистром флагов. По общим правилам изучения ассемблера с этим регистром принято знакомиться на первом или втором занятии, сразу же после знакомства с регистрами общего назначения и сегментными регистрами. Однако, дабы не сильно пугать вас сразу, я отложил знакомство с ним аж до сегодняшнего занятия, а сегментные регистры пока что вообще не трогал. Пишут же люди программы на языках высокого уровня, даже не подозревая о таких «мелочах», так зачем вам, все еще местами сомневающимся в собственных силах касательно освоения ассемблера, изначально забивать голову пугающей теорией? И все же азы надо знать, так что соберитесь: регистр флагов! Регистр флагов в 32-битных процессорах имеет размер 32 бита и называется EFLAGS. Как вы могли заметить, приставка «E» в названии 32-битного регистра обычно свидетельствует о том, что он имеет 16-битное происхождение (64-битные регистры имеют приставку R). Значит, из соображений обратной совместимости со старыми 16-битными программами должен существовать и 16-битный предок — FLAGS. На его примере мы и начнем знакомство с данным регистром:
На данном этапе вам понадобится запомнить лишь 3-4 флага, поэтому не пугайтесь этой таблицы: ее цель — лишь получение вами общего представления о регистре флагов 16-битного процессора, который, тем не менее, сохранился и в 32-, и в 64-битных потомках. CF устанавливается (1), если в результате операции из старшего бита происходит перенос при сложении или заем при вычитании, иначе CF сбрасывается (0). Кроме того, CF используется в логических и унарных операциях. ZF устанавливается (1), если результат операции равен нулю, иначе ZF сбрасывается (0). Главное — впоследствии не запутаться в том, что ZF=0, если результат отличен от ноля, но ZF=1 при нулевом результате. SF отражает состояние старшего (знакового) бита результата. SF=1, если старший бит результата равен единице, и ZF=0 — если старший бит результата нулевой. OF фиксирует факт потери старшего (знакового) бита результата при арифметических операциях. OF=1, если произошел перенос в старший бит результата или заем из старшего бита, ZF=0 при отсутствии переноса или заема. PF устанавливается (1), если младшие 8 битов результата содержат четное число единиц. Теперь мы можем перейти к знакомству с часто применяемыми командами. Команды обмена данными: MOV, XCHG. MOV приемник,источник mov bx,ax ;копировать содержимое РОН в РОН XCHG операнд1,операнд2 xchg ax,bx ;обменять содержимое РОН и РОН Обмен данными через стек: PUSH, POP. Стек — область памяти, специально выделяемая каждой программе для временного хранения промежуточных данных. Обычно адреса в памяти растут от ноля к максимальному адресу. В стеке все наоборот: он растет от дна (максимальный адрес сегмента стека) к нолю. Для того, чтобы поместить данные в стек, применяется команда PUSH, ее синтаксис следующий: PUSH источник push ax ;сохранить РОН POP приемник Примеры: INC операнд ADD приемник,источник ADC приемник,источник DEC операнд SUB приемник,источник SBB приемник,источник CMP приемник,источник NEG приемник Мы прибавили 300 к отрицательному значению ax, что по законам математики дает такой же результат, что и вычитание ax из 300. XADD приемник,источник Размеры операндов арифметических команд должны быть одинаковыми. Поэтому, если необходимо произвести арифметическое действие над операндами, имеющими разные размеры, следует сначала преобразовать один из них так, чтобы оба операнда имели одинаковый размер. Для этого в системе команд процессора предусмотрены команды преобразования типов. Они служат для преобразования байтов в слова, слов — в двойные слова, двойных слов — в учетверенные (qword). Эти преобразования могут выполняться способом знакового расширения — увеличение размера операнда с учетом знака (заполнение старших разрядов увеличенного операнда значением старшего бита исходного операнда) или нулевого расширения (заполнение старших разрядов увеличенного операнда нолями). Команды преобразования со знаковым расширением без операндов: MOVSX приемник,источник MOVZX приемник,источник Десятичная арифметика — упакованный, когда каждый байт (8 бит) может содержать две десятичные цифры (по 4 бита каждая). В таком случае каждый байт содержит десятичное число в диапазоне от 00 до 99. — неупакованный, когда каждый байт содержит лишь одну десятичную цифру в младших четырех битах, а старшие четыре бита имеют нулевое значение. Диапазон представления неупакованного BCD-числа в отдельно взятом байте составляет от 0 до 9. Десятичная арифметика осуществляется методом комбинирования вышеописанных команд двоичной арифметики с командами, специально предназначенными для десятичных операций. Команды десятичной арифметики используются для приведения результата предыдущих двоичных вычислений к упакованному/неупакованному формату BCD-числа или, наоборот, для подготовки введенных данных к двоичным арифметическим операциям. DAA корректирует результат сложения двух упакованных BCD-чисел в регистре AL. Эта команда должна следовать за командой сложения (ADD или ADC), если в сложении участвовали два упакованных BCD, и результат находится в AL. Если откорректированный результат превысит 99, то будет установлен флаг CF, а в AL останутся лишь две младшие цифры. Пример: В данном примере наглядно показано, что упакованные BCD можно записывать просто как шестнадцатеричные числа (буковка h в конце числа означает HEX), только без использования символов ABCDEF. Когда будет произведено сложение 49h и 52h, результат будет неверным. Точнее, он будет верным, но лишь применительно к шестнадцатеричным числам, потому что процессор, складывая эти числа, считает их не упакованными десятичными, а стандартными двоичными или шестнадцатеричными, если хотите. Однако команда DAA все расставляет по своим местам, и в результате в AL получается 01 (две младшие цифры от 101), а установленный флаг CF позволяет определить, что единичка для следующего третьего разряда «в уме». DAS работает аналогично DAA, только используется для корректировки результата вычитания. У команды также отсутствует операнд, потому что действие производится над регистром AL. Флаг CF (если установлен) указывает на то, что вычитаемое оказалось больше уменьшаемого, и необходимо это дело обработать, например, уменьшением третьего разряда на единицу. AAA предназначена для корректировки результата сложения НЕупакованных BCD-чисел размером в байт, то есть одноразрядных. Операнды отсутствуют, действие производится над регистром AL. Если результат превышает 9, то в AL помещается лишь младший разряд, а AH увеличивается на единицу, и устанавливается флаг CF. AAS аналогична AAA за исключением того, что применяется для корректировки вычитания неупакованных одноразрядных BCD-чисел. При необходимости заема устанавливается флаг CF, а содержимое AH уменьшается на единицу. AAM корректирует результат умножения двух неупакованных BCD, находящийся в AL. Данная команда просто делит содержимое AL на 10 и помещает частное в AH, а остаток — в AL. Таким образом в AX помещается двухразрядное неупакованное BCD. Стандартная версия команды не имеет операндов, однако существует расширенная версия AAM, в которой в роли операнда выступает непосредственное значение — база, на которую будет производиться деление. Так что, выполнив, к примеру, команду AAM 5, вы поделите нацело содержимое AL, получив частное в AH, а остаток — в AL. Очень удобный способ для деления нацело небольших (до 8 бит) чисел. AAD подготавливает к делению неупакованное BCD-число, находящееся в AX. Команда просто добавляет к AL содержимое AH, умноженное на 10, потом AH обнуляется. Несмотря на свое основное назначение, команда отлично справляется не только с подготовкой к делению, но и с простым преобразованием неупакованного двузначного BCD в двоичный эквивалент. Также команда может оказать неоценимую помощь в преобразовании символьного кода цифр сразу в двоичный код. Например, в таблице ASCII цифра «1» имеет код 31h, цифра «2» — 32h и т.д. Значит, для того, чтобы из символьного кода получить неупакованное BCD, нам достаточно обнулить старший шестнадцатеричный разряд (старшие 4 бита) ASCII-кода. Поместим число 15 в символьном виде в AX и переведем его в двоичное значение: После выполнения этих команд в AX у нас будет 0Fh, то есть число 15 в нормальном двоичном (шестнадцатеричном) виде, привычном для процессора. В расширенном варианте команды AAD есть возможность указать в качестве операнда непосредственное значение, на которое будет умножаться AH, прежде чем прибавиться к AL. Это дает еще один вариант использования команды: быстрое умножение небольших чисел. Что ж, на сегодня, думаю, с вас достаточно. Очень сложная тема, хотя, надеюсь, и весьма интересная. Примеров программ в газете на этот раз не будет, но вы всегда можете найти их на форуме: сайт BarMentaLisk, SASecurity gr., q@sa-sec.org Компьютерная газета. Статья была опубликована в номере 30 за 2008 год в рубрике программирование
|