Assembler - язык неограниченных возможностей

         

Пересылка данных




  • Команда:
  • MOV приемник, источник
  • Назначение:
  • Пересылка данных
  • Процессор:
  • 8086

    Базовая команда пересылки данных. Копирует содержимое источника в приемник, источник не изменяется. Команда MOV действует аналогично операторам присваивания из языков высокого уровня, то есть команда

    mov ax,bx

    эквивалентна выражению

    ах := bх;

    языка Паскаль или

    ах = bх;

    языка С, за исключением того, что команда ассемблера позволяет работать не только с переменными в памяти, но и со всеми регистрами процессора.

    В качестве источника для MOV могут использоваться: число (непосредственный операнд), регистр общего назначения, сегментный регистр или переменная (то есть операнд, находящийся в памяти). В качестве приемника — регистр общего назначения, сегментный регистр (кроме CS) или переменная. Оба операнда должны быть одного и того же размера — байт, слово или двойное слово.

    Нельзя выполнять пересылку данных с помощью MOV из одной переменной в другую, из одного сегментного регистра в другой и нельзя помещать в сегментный регистр непосредственный операнд — эти операции выполняют двумя командами MOV (из сегментного регистра в обычный и уже из него в другой сегментный) или парой команд PUSH/POP.

    Загрузка регистра SS командой MOV автоматически запрещает прерывания до окончания следующей за этим команды MOV, так что можно загрузить SS и ESP двумя последовательными командами MOV, не опасаясь, что в этот момент произойдет прерывание, обработчик которого получит неправильный стек. В любом случае для загрузки значения в регистр SS предпочтительнее команда LSS.

  • Команда:
  • CMOVcc приемник, источник
  • Назначение:
  • Условная пересылка данных
  • Процессор:
  • P6

    Это набор команд, которые копируют содержимое источника в приемник, если удовлетворяется то или иное условие (см. табл. 5). Источником может быть регистр общего назначения или переменная, а приемником — только регистр. Условие, которое должно удовлетворяться, — просто равенство нулю или единице тех или иных флагов из регистра FLAGS, но, если использовать команды CMOVcc сразу после команды СМР (сравнение) с теми же операндами, условия приобретают особый смысл, например:

    cmp ах,bх ; сравнить ах и bх cmovl ax,bx ; если ах < bх, скопировать bх в ах


    Слова «выше» и «ниже» в таблице 5 относятся к сравнению чисел без знака, слова «больше» и «меньше» учитывают знак.

    Таблица 5. Разновидности команды CMOVcc

    Код команды Реальное условие Условие для CMP
    CMOVA
    CMOVNBE
    CF = 0 и ZF = 0 если выше
    если не ниже или равно
    CMOVAE
    CMOVNB
    CMOVNC
    CF = 0 если выше или равно
    если не ниже
    если нет переноса
    CMOVB
    CMOVNAE
    CMOVC
    CF = 1 если ниже
    если не выше или равно
    если перенос
    CMOVBE
    CMOVNA
    CF = 1 и ZF = 1 если ниже или равно
    если не выше
    CMOVE
    CMOVZ
    ZF = 1 если равно
    если ноль
    CMOVG
    CMOVNLE
    ZF = 0 и SF = OF если больше
    если не меньше или равно
    CMOVGE
    CMOVNL
    SF = OF если больше или равно
    если не меньше
    CMOVL
    CMOVNGE
    SF <> OF если меньше
    если не больше или равно
    CMOVLE
    CMOVNG
    ZF = 1 и SF <> OF если меньше или равно
    если не больше
    CMOVNE
    CMOVNZ
    ZF = 0 если не равно
    если не ноль
    CMOVNO OF = 0 если нет переполнения
    CMOVO OF = 1 если есть переполнение
    CMOVNP
    CMOVPO
    PF = 0 если нет четности
    если нечетное
    CMOVP
    CMOVPE
    PF = 1 если есть четность
    если четное
    CMOVNS SF = 0 если нет знака
    CMOVS SF = 1 если есть знак
  • Команда:
  • XCHG операнд1, операнд2
  • Назначение:
  • Обмен операндов между собой
  • Процессор:
  • 8086
    Содержимое операнда 2 копируется в операнд 1, а старое содержимое операнда 1 — в операнд 2. XCHG можно выполнять над двумя регистрами или над регистром и переменной.

    xchg eax,ebx ; то же, что три команды на языке С: ; temp = eax; eax = ebx; ebx = temp; xchg al,al ; а эта команда не делает ничего

  • Команда:
  • BSWAP регистр32
  • Назначение:
  • Обмен байт внутри регистра
  • Процессор:
  • 80486
    Обращает порядок байт в 32-битном регистре. Биты 0 – 7 (младший байт младшего слова) меняются местами с битами 24 – 31 (старший байт старшего слова), а биты 8 – 15 (старший байт младшего слова) меняются местами с битами 16 – 23 (младший байт старшего слова).

    mov eax,12345678h bswap eax ; теперь в еах находится 78563412h



    Чтобы обратить порядок байт в 16- битном регистре, следует использовать команду XCHG:

    xchg al,ah ; обратить порядок байт в АХ

    В процессорах Intel команду BSWAP можно использовать и для обращения порядка байт в 16-битных регистрах, но в некоторых совместимых процессорах других фирм этот вариант BSWAP не реализован.

  • Команда:
  • PUSH источник
  • Назначение:
  • Поместить данные в стек
  • Процессор:
  • 8086
    Помещает содержимое источника в стек. Источником может быть регистр, сегментный регистр, непосредственный операнд или переменная. Фактически эта команда копирует содержимое источника в память по адресу SS:[ESP] и уменьшает ESP на размер источника в байтах (2 или 4). Команда PUSH практически всегда используется в паре с POP (считать данные из стека). Так, например, чтобы скопировать содержимое одного сегментного регистра в другой (что нельзя выполнить одной командой MOV), можно использовать такую последовательность команд:

    push cs pop ds ; теперь DS указывает на тот же сегмент, что и CS

    Другое частое применение команд PUSH/POP — временное хранение переменных, например:

    push eax ; сохраняет текущее значение ЕАХ ... ; здесь располагаются какие-нибудь команды, ; которые используют ЕАХ, например CMPXCHG pop eax ; восстанавливает старое значение ЕАХ

    Начиная с 80286, команда PUSH ESP (или SP) помещает в стек значение ESP до того, как эта же команда его уменьшит, в то время как на 8086 SP помещался в стек уже уменьшенным на два.

  • Команда:
  • POP приемник
  • Назначение:
  • Считать данные из стека
  • Процессор:
  • 8086
    Помещает в приемник слово или двойное слово, находящееся в вершине стека, увеличивая ESP на 2 или 4 соответственно. POP выполняет действие, полностью обратное PUSH. Приемником может быть регистр общего назначения, сегментный регистр, кроме CS (чтобы загрузить CS из стека, надо воспользоваться командой RET), или переменная. Если в роли приемника выступает операнд, использующий ESP для косвенной адресации, команда POP вычисляет адрес операнда уже после того, как она увеличивает ESP.

  • Команда:
  • PUSHA
    PUSHAD
  • Назначение:
  • Поместить в стек все регистры общего назначения
  • Процессор:
  • 80186
    80386
    <


    /p> PUSHA помещает в стек регистры в следующем порядке: АХ, СХ, DX, ВХ, SP, ВР, SI и DI. PUSHAD помещает в стек ЕАХ, ЕСХ, EDX, ЕВХ, ESP, EBP, ESI и EDI. (В случае SP и ESP используется значение, которое находилось в этом регистре до начала работы команды.) В паре с командами POPA/POPAD, считывающими эти же регистры из стека в обратном порядке, это позволяет писать подпрограммы (обычно обработчики прерываний), которые не должны изменять значения регистров по окончании своей работы. В начале такой подпрограммы вызывают команду PUSHA, а в конце — РОРА.

    На самом деле PUSHA и PUSHAD — одна и та же команда с кодом 60h. Ее поведение определяется тем, выполняется ли она в 16- или в 32-битном режиме. Если программист использует команду PUSHAD в 16-битном сегменте или PUSHA в 32-битном, ассемблер просто записывает перед ней префикс изменения размерности операнда (66h).

    Это же будет распространяться на некоторые другие пары команд: РОРА/POPAD, POPF/POPFD, PUSHF/PUSHFD, JCXZ/JECXZ, CMPSW/CMPSD, INSW/INSD, LODSW/LODSD, MOVSW/MOVSD, OUTSW/OUTSD, SCASW/SCASD и STOSW/STOSD.
  • Команда:
  • POPA
    POPAD
  • Назначение:
  • Загрузить из стека все регистры общего назначения
  • Процессор:
  • 80186
    80386
    Эти команды выполняют действия, полностью обратные действиям PUSHA и PUSHAD, за исключением того, что помещенное в стек значение SP или ESP игнорируется. РОРА загружает из стека DI, SI, BP, увеличивает SP на два, загружает ВХ, DX, CX, AX, a POPAD загружает EDI, ESI, ЕВР, увеличивает ESP на 4 и загружает ЕВХ, EDX, ЕСХ, ЕАХ.

  • Команда:
  • IN приемник, источник
  • Назначение:
  • Считать данные из порта
  • Процессор:
  • 8086
    Копирует число из порта ввода-вывода, номер которого указан в источнике, в приемник. Приемником может быть только AL, АХ или ЕАХ. Источник — или непосредственный операнд, или DX, причем можно указывать только номера портов не больше 255.

  • Команда:
  • OUT приемник, источник
  • Назначение:
  • Записать данные в порт
  • Процессор:
  • 8086
    Копирует число из источника (AL, АХ или ЕАХ) в порт ввода-вывода, номер которого указан в приемнике. Приемник может быть либо непосредственным номером порта, либо регистром DX. На командах IN и OUT строится все общение процессора с устройствами ввода-вывода — клавиатурой, жесткими дисками, различными контроллерами, и используются они, в первую очередь, в драйверах устройств. Например, чтобы включить динамик PC, достаточно выполнить команды:

    in al,61h or al,3 out 61h,al



    Программирование портов ввода-вывода рассмотрено подробно в главе 5.10.

  • Команда:
  • CWD
  • Назначение:
  • Конвертирование слова в двойное слово
  • Процессор:
  • 8086
  • Команда:
  • CDQ
  • Назначение:
  • Конвертирование двойного слова в учетверенное
  • Процессор:
  • 80386
    Команда CWD превращает слово в AХ в двойное слово, младшая половина которого (биты 0 – 15) остается в АХ, а старшая (биты 16 – 31) располагается в DX. Команда CDQ выполняет аналогичное действие по отношению к двойному слову в ЕАХ, расширяя его до учетверенного слова в EDX:EAX. Эти команды всего лишь устанавливают все биты регистра DX или EDX в значение, равное значению старшего бита регистра АХ или ЕАХ, сохраняя таким образом его знак.

  • Команда:
  • CBW
  • Назначение:
  • Конвертирование байта в слово
  • Процессор:
  • 8086
  • Команда:
  • CWDE
  • Назначение:
  • Конвертирование слова в двойное слово
  • Процессор:
  • 80386
    CBW расширяет байт, находящийся в регистре AL, до слова в АХ, CWDE расширяет слово в АХ до двойного слова в ЕАХ. CWDE и CWD отличаются тем, что CWDE располагает свой результат в ЕАХ, в то время как CWD, команда, выполняющая точно такое же действие, располагает результат в паре регистров DX:AX. Так же как и команды CWD/CDQ, расширение выполняется путем установки каждого бита старшей половины результата равным старшему биту исходного байта или слова, то есть:

    mov al,0F5h ; AL = 0F5h = 245 = -11 cbw ; теперь АХ = 0FFF5h = 65 525 = -11

    Так же как и в случае с командами PUSHA/PUSHAD, пара команд CWD/CDQ — это одна команда с кодом 99h, и пара команд CBW/CWDE — одна команда с кодом 98h. Интерпретация этих команд зависит от того, в каком (16-битном или в 32-битном) сегменте они исполняются, и точно так же, если указать CDQ или CWDE в 16-битном сегменте, ассемблер поставит префикс изменения разрядности операнда.
  • Команда:
  • MOWSX приемник, источник
  • Назначение:
  • Пересылка с расширением знака
  • Процессор:
  • 80386
    Копирует содержимое источника (регистр или переменная размером в байт или слово) в приемник (16- или 32-битный регистр) и расширяет знак аналогично командам CBW/CWDE.

  • Команда:
  • MOWZX приемник, источник
  • Назначение:
  • Пересылка с расширением нулями
  • Процессор:
  • 80386
    <


    /p> Копирует содержимое источника (регистр или переменная размером в байт или слово) в приемник (16- или 32-битный регистр) и расширяет нулями, то есть команда

    movzx ax,bl

    эквивалентна паре команд

    mov al,bl mov ah,0

  • Команда:
  • XLAT адрес
    XLATB
  • Назначение:
  • Трансляция в соответствии с таблицей
  • Процессор:
  • 8086
    Помещает в AL байт из таблицы в памяти по адресу ES:BX (или ES:EBX) со смещением относительно начала таблицы, равным AL. В качестве аргумента для XLAT в ассемблере можно указать имя таблицы, но эта информация никак не используется процессором и служит только как комментарий. Если этот комментарий не нужен, можно применить форму записи XLATB. В качестве примера использования XLAT можно написать следующий вариант преобразования шестнадцатеричного числа в ASCII-код соответствующего ему символа:

    mov al,0Ch mov bx, offset htable xlatb

    если в сегменте данных, на который указывает регистр ES, было записано

    htable db "0123456789ABCDEF"

    то теперь AL содержит не число 0Сh, а ASCII-код буквы «С». Разумеется, это преобразование можно выполнить, используя гораздо более компактный код всего из трех арифметических команд, который будет рассмотрен в описании команды DAS, но с XLAT можно выполнять любые преобразования такого рода.

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

    Команду LEA часто используют для быстрых арифметических вычислений, например умножения:

    lea bx,[ebx+ebx*4] ; ВХ=ЕВХ*5

    или сложения:

    lea ebx,[eax+12] ; ЕВХ=ЕАХ+12

    (эти команды меньше, чем соответствующие MOV и ADD, и не изменяют флаги)

    Содержание раздела