Суббота
18.05.2024
07:00
Форма входа
Категории раздела
Макроинструкции [3]
Управление данными [4]
Макросы [0]
ПК и железо [0]
Осиписание. :) [1]
Разное [4]
Поиск
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Статистика

    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0

    OPEN SOURCE PROJECT

    Каталог статей

    Главная » Статьи » Макроинструкции

    Инструкции часть первая
    2.1  Инструкции архитектуры x86

    В этом параграфе вы найдете всю информацию о синтаксисе и назначении инструкций ассемблера. Если вам нужно больше технической информации, смотрите Intel Architecture Software Developer's Manual. Инструкции ассемблера состоят из мнемоника (имени инструкции) и нескольких операндов (от нуля до трех). Если операндов два или три, то обычно первым идет адресат, а вторым источник. Операндом может быть регистр, память или непосредственное значение (подробнее о синтаксисе операндов смотрите в 1.2). После описания каждой инструкции ниже будут примеры разных комбинаций операндов, если, конечно, она содержит операнды.
        Некоторые инструкции работают как префиксы и могут быть перед другой инструкцией на той же строке. На одной строке может несколько префиксов. Каждое имя сегментного регистра это тоже мнемоник инструкции-префикса, хотя рекомендуется использовать замещение сегмента внутри квадратных скобок вместо этих префиксов.


    2.1.1  Инструкции перемещения данных

    "mov" переносит байт, слово или двойное слово из операнда-источника в операнд-адресат. Этот мнемоник может передавать данные между регистрами общего назначения, из этих регистров в память, обратно, но не может перемещать данные из памяти в память. Он также может передавать непосредственное значение в регистр общего назачения или в память, сегментный регистр в регистр общего назначения или в память, регистр общего назначения в сегментный регистр или в память, контрольный или отладочный регистр в регистр общего назначения и назад. "mov" может быть ассемблирована только если размер операнда-источника и размер операнда-адресата совпадают. Ниже приведены примеры каждой из перечисленных комбинаций:

        mov bx,ax       ; из регистра общего назначения в регистр общего назначения
        mov [char],al   ; из регистра общего назначения в память
        mov bl,[char]   ; из памяти в регистр общего назначения
        mov dl,32       ; непосредственное значение в регистр общего назначения
        mov [char],32   ; непосредственное значение в память
        mov ax,ds       ; из сегментного регистра в регистр общего назначения
        mov [bx],ds     ; из сегментного регистра в память
        mov ds,ax       ; из регистра общего назначения в сегментный регистр
        mov ds,[bx]     ; из памяти в сегментный регистр
        mov eax,cr0     ; из контрольного регистра в регистр общего назначения
        mov cr3,ebx     ; из регистра общего назначения в контрольный регистр

        "xchg" меняет местами значения двух операндов. Инструкция может поменять два байтовых операнда, операнды размером в слово и размером в двойное слово. Порядок операндов не важен. В их роли могут выступать два регистра общего назначения либо регистр общего назначения и адрес в памяти. Например:

        xchg ax,bx      ; меняет местами два регистра общего назначения
        xchg al,[char]  ; регистр общего назначения и память

    "push" уменьшает значение указателя стекового фрейма (регистр ESP), потом переводит операнд на верх стека, на который указывает ESP. Операндом может быть память, регистр общего назначения, сегментный регистр или непосредственное значение размером в слово или двойное слово. Если операнд - это непосредственное значение и его размер не определен, то в 16-битном режиме по умолчанию он обрабатывается как слово, а в 32-битном режиме как двойное слово. Мнемоники "pushw" и "pushd" - это варианты этой инструкции, которые сохраняют соответственно слова и двойные слова. Если на одной строке содержится несколько операндов (разделенных пробелами, а не запятыми), компилятор проассемблирует цепь инструкций "push" с этими операндами. Вот примеры с одиночными операндами:

        push ax         ; сохраняет регистр общего назначения
        push es         ; сохраняет сегментный регистр
        pushw [bx]      ; сохраняет память
        push 1000h      ; сохраняет непосредственное значение

       Инструкция "pusha" сохраняет в стек содержимое восьми регистров общего назначения. У неё нет операндов. Существует две версии этой инструкции: 16-битная и 32-битная. Ассемблер автоматически генерирует версию, соответствующую текущему режиму, но, используя мнемоники "pushaw" или "pushad",это можно изменить для того, чтобы всегда получать, соответственно, 16- или 32-битную версию. 16-битная версия этой инструкции сохраняет регистры общего назначения в таком порядке: AX, CX, DX, BX, значение регистра SP перед тем, как был сохранен AX, далее BP, SI и DI. 32-битная версия сохраняет эквивалентные 32-битные регистры в том же порядке.
        "pop" переводит слово или двойное слово из текущей верхушки стека в операд-адресат и после уменьшает ESP на указатель на новую верхушку стека. Операндом может служить память, регистр общего назначения или сегментный регистр. Мнемоники "popw" и "popd" - это варианты этой инструкции, восстанавливающие соответственно слова и двойные слова. Если на одной строке содержится несколько операндов, разделенных пробелами, компилятор ассемблирует цепочку инструкций с этими операндами.

        pop bx          ; восстанавливает регистр общего назначения
        pop ds          ; восстанавливает сегментный регистр
        popw [si]       ; восстанавливает память

    "popa" восстанавливает регистры, сохраненные в стек инструкцией "pusha", кроме сохраненного значения SP (или ESP)? который будет проигнорирован. У этой инструкции нет операндов. Чтобы ассемблировать 16 или 32-битную версию этой инструкции, используйте мнемоники "popaw" или "popad".


    2.1.2 Инструкции преобразования типов.

    Инструкции преобразования типов конвертируют байты в слова, слова в двойные слова и двойные слова в четверные слова. Эти преобразования можно совершить, используя знаковое или нулевое расширение. Знаковое расширение заполняют дополнительные биты большего операнда значением бита знака меньшего операнда, нулевое расширение просто забивает их нулями.
        "cwd" и "cdq" удваивают размер регистра AX или EAX соответственно и сохраняет дополнительные биты в регистр DX или EDX. Преобразование делается, используя знаковое расширение.  Эти инструкции не имеют операндов.
        "cbw" растягивает знак байта AL по регистру AX, а "cwde" растягивает знак слова AX на EAX. Эти инструкции также не имеют операндов.
        "movsx" преобразует байт в слово или в двойное слово и слово в двойное слово, используя знаковое расширение. "movzx" делает то же самое, но используя нулевое расширение. Операндом-источником может быть регистр общего назначения или память, тогда как операндом-адресатом должен быть регистр общего назначения. Например:

        movsx ax,al         ; байт в слово
        movsx edx,dl        ; байт в двойное слово
        movsx eax,ax        ; слово в двойное слово
        movsx ax,byte [bx]  ; байт памяти в слово
        movsx edx,byte [bx] ; байт памяти в двойное слово
        movsx eax,word [bx] ; слово памяти в двойное слово


    2.1.3 Двоичные арифметические инструкции

    "add" заменяет операнд-адресат суммой операнда-источника и адресата и ставит CF, если было переполнение. Операндами могут байты, слова или двойные слова. Адресатом может быть регистр общего назначения или память, источником регистр общего назначени или непосредственное значение. Также это может быть память, если адресат - это регистр.

        add ax,bx       ; прибавляет регистр к регистру
        add ax,[si]     ; прибавляет память к регистру
        add [di],al     ; прибавляет регистр к памяти
        add al,48       ; прибавляет непосредственное значение к регистру
        add [char],48   ; прибавляет непосредственное значение к памяти

        "adc" суммирует операнды, прибавляет единицу, если стоит CF и заменяет адресат результатом. Приавила для операндов такие же как с инстукцей "add". "add" со следующими за ней несколькими инструкциями "adc" может быть использована для сложения чисел длиннее, чем 32 бита.
        "inc" прибавляет к операнду единицу, он не может изменить CF. Операндом может быть регистр общего назначения или память, размером он может быть в байт, слово или двойное слово.

        inc ax          ; прибавляет единицу к регистру
        inc byte [bx]   ; увеличивает единицу к памяти

        "sub" вычитает операнд-источник от операнда адресата и заменяет адресат результатом. Если требуется отрицательный перенос, устанавливается CF. Правила для операндов такие же, как с инструкцией "add".
        "sbb" вычитает источник из адресата, отнимает единицу, если установлен CF и заменяет адресат результатом. Правила для операндов такие же, как с инструкцией "add". "sub" со следущими за ней несколькими инструкциями "sbb" может быть использована для вычитания чисел длиннее, чем 32 бита.
        "dec" вычитает из операнда единицу, не может изменить CF. Правила для операнда такие же, как с инструкцией "inc".
        "cmp" вычитает операнд-источник из оператора-адресата. Эта инструкция может устанавливать флаги, как и "sub", но не вносит изменения в операнды. Правила для операндов такие же, как с инструкцией "sub".
        "neg" отнимает от нуля целочисленный операнд с знаком. Эффект от этой инструкции - это смена знака операнда с положительного на отрицательный или с отрицательного на положительный. Правила для операндов такие же, как с инструкцией "inc".
        "xadd" меняет местами операнд-адресат и операнд-источник, потом загружает сумму двух значений в операнд-адресат. Правила для операндов такие же, как с инструкцией "add". Все вышеперечисленные инструкции изменяют флаги SF, ZF, PF и OF. SF всегда принимает значение, равное биту знака результата, ZF устанавливается, если результат равен нулю, PF устанавливается, если восемь битов нижнего разряда содержат четное число единиц, OF устанавливается, если результат слишком большой для положительного числа или слишком маленький для отрицательного (исключая бит знака) для того, чтобы уместиться в операнде-адресате.
        "mul" выполняет беззнаковое перемножение операнда и аккумулятора. Если операнд - байт, процессор умножает его на содержимое AL и возвращает 16-битный результат в AH и AL. Если операнд - слово, процессор умножает его на содержимое AX и возврщает 32-битный результат в DX и AX. Если же операнд - это двойное слово, процессор умножает его на содержимое EAX и возвращает 64-битный результат в EDX и EAX. "mul"устанавливает CF и OF, если верхняя половина результата ненулевая, иначе они очищаются. Правила для операндов такие же, как с инструкцией "inc".
        "imul" выполняет знаковое перемножение операндов. У этой инструкции есть три вариации. Первая имеет один операнд и работает так же, как инструкция "mul". Вторая имеет два операнда, и здесь операнд-адресат умножается на операнд-источник и результат заменяет операнд-адресат. Этоим операндом может быть регистр общего назначения, память или непосредственное значение. Третья форма инструкции имеет три операнда, операндом-адресатом должен быть регистр общего назначения, длиной в слово или в двойное слово, операндом-источником может быть регистр общего назначения или память, третьим операндом должно быть непосредственное значение. Источник умножается на непосредственное значение и результат помещается в регистр-адресат. Все три формы вычисляют результат размером в два раза больше размера операндов и ставят CF и OF, если верхняя часть результата ненулевая, но вторая и третья формы усекают результат до размера операндов. Так, их можно использовать для беззнаковых операндов, потому что нижняя половина результата одна и та же для знаковых и беззнаковых операндов. Ниже вы видите примеры всех трех форм:

        imul bl         ; умножение аккумулятора на регистр
        imul word [si]  ; умножение аккумулятора на память
        imul bx,cx      ; умножение регистра на регистр
        imul bx,[si]    ; умножение регистра на память
        imul bx,10      ; умножение регистра на непосредственное значение
        imul ax,bx,10   ; регистр, умноженный на непосредственное значение, в регистр
        imul ax,[si],10 ; память, умноженная на непосредственное значение, в регистр

        "div" производит беззнаковое деление аккумулятора на операнд. Делимое (аккумулятор) размером в два раза больше делителя (операнда), частное и остаток такого же размера , как и делитель. Если делитель - байт, делимое берется из регистра AX, частное сохраняется в AL, а остаток - в AH. Если делитель - слово, верхняя половина делимого берется из DX, а нижняя - из AX, частное сохраняется в AX, а остаток - в DX. Если делитель - двойное слово, верхняя половина делимого берется из EDX, а нижняя - из EAX, частное сохраняется в EAX, а остаток - в EDX. Правила для операндов такие же, как с инструкцией "mul".
        "idiv" выполняет знаковое деление аккумулятора на операнд. Инструкция использует те же регистры, что и "div", правила для для операнда тоже такие-же.


    2.1.4  Десятичные арифметические инструкции

    Десятичная арифметика представлена в виде соединения двоичных арифметических инструкций (описанных в предыдущем параграфе) с десятичными арифметическиими инструкциями. Десятичные арифметические инструкции используются для того, чтобы приспособить результаты предыдущей двоичной арифметической операции для создания допустимого сжатого или несжатого (?) десятичного результата, или приспособить входные данные для последующей двоичной арифметической операции так, чтобы эта операция также давала допустимый сжатый или несжатый десятичный результат.
        "daa" прилаживает результат сложения двух допустимых сжатых десятичных числа к AL. "daa" всегда должна следовать за суммированием двух пар сжатых десятичных цифр (один знак в каждой половине байта), чтобы получить как результат пару допустимых сжатых десятичных символов. Если потребуется перенос, будет установлен флаг переноса. У этой инструкции нет операндов.
        "das" прилаживает результат вычитания двух допустимых сжатых десятичных числа к AL. "das" всегда должна следовать за вычитанием одной пары сжатых десятичных цифр (один знак в каждой половине байта) из другой, чтобы получить как результат пару допустимых сжатых десятичных символов. Если потребуется отрицательный перенос, будет установлен флаг переноса. У этой инструкции нет операндов.
        "aaa" изменяет содержимое регистра AL на допустимое несжатое десятичное число и обнуляет верхние четыре бита. "aaa" всегда должна следовать за сложением двух несжатых десятичных операндов в AL. Если необходим перенос, устанавливется флаг переноса и увеличивается на единицу AH. У этой инструкции нет операндов.
        "aas" изменяет содержимое регистра AL на допустимое несжатое десятичное число и обнуляет верхние четыре бита. "aas" всегда должна следовать за вычитанием одного несжатого десятичного операнда из другого в AL. Если необходим перенос, устанавливется флаг переноса и уменьшается на единицу AH. У этой инструкции нет операндов.
        "aam" корректирует результат умножения двух допустимых несжатых десятичных чисел. Для создания правильного десятичного результата инструкция должна всегда следовать за умножением двух десятичных чисел. Цифра верхнего регистра передается в AH, а нижнего - в AL. Обобщенная версия этой инструкции делает возможной подгонку содержимого AX для создания двух несжатых цифр с любым основанием. Стандартная версия этой инструкции не имеет операндов, у обобщенной версии есть один операнд - непосредственное значение, определяющее основание создавакмых чисел.
        "aad" модифицирует делимое в AH и AL, чтобы подготовится к делению двух допустимых несжатых десятичных операндов так, чтобы частное стало доустимым несжатым десятичным числом. AH должен содержать цифру верхнего регистра, а AL - цифру нижнего регистра. Эта инструкция корректирует значение и помещает результат в AL, тогда как AH будет содержать ноль. Обобщенная версия этой инструкции делает возможной подгонку двух несжатых цифр с любым основанием. Правила для операнда такие же, как с инструкцией "aam".


    2.1.5  Логические инструкции

    "not" инвертирует биты в заданном операнде к форме обратного кода операнда. Не оказывает влияния на флаги. Правила для операнда таки же, как с инструкцией "inc".
        "and", "or" и "xor" производят стандартные логические операции. Они изменяют флаги SF, ZF и PF. Правила для операнда таки же, как с инструкцией "add".
        "bt", "bts", "btr" и "btc" оперируют с единичным битм, который может быть в памяти или регистре общего назначения. Расположения бита определяется как смещение от конца нижнего регистра операнда. Значение смещения берется из второго операнда, это может быть либо регистр общего назначения, либо байт. Эти инструкции первым делом присваивают флагу CF значение выбранного байта. "bt" больше ничего не делает, "bts" присваивает выбранному биту значение 1, "btr" сбрасывает его на 0, "btc" изменяет значение бита на его дополнение. Первый операнд может быть словом или двойным словом.

        bt  ax,15        ; тестирует бит в регистре
        bts word [bx],15 ; тестирует и ставит бит в памяти
        btr ax,cx        ; тестирует и сбрасывает бит в регистре
        btc word [bx],cx ; тестирует и дополняет бит в памяти

        Инструкции "bsf" и "bsr" ищут в слове или двойном слове первый установленный бит и сохраняют индекс этого бита в операнд-адресат, которым должен быть регистр общего назначения. Сканируемая строка битов определяется операндом-источником, им может быть либо регистр общего назначения, либо память. Если срока нулевая (ни одного единичного бита), то установливается флаг ZF; иначе он очищается. Если не найдено ни одного установленного бита, значение операнда адресата не определено. "bsf" сканирует от нижнего регистра к верхнему (начиная с бита с индексом ноль). "bsr" сканирует от верхнего регистра к нижнему (начиная с бита с индексом 15 в слове или с индекса 31 в двойном слове).


        bsf ax,bx        ; сканирование регистра по возрастанию
        bsr ax,[si]      ; скнирование пмяти в обратном порядке

        "shl" сдвигает операнд-адресат влево на определенное вторым операндом количество битов. Операндом-адресатом может быть регистр общего назначения или память размером в байт, слово или двойное слово. Вторым операндом может быть непосредственное значение или регистр CL. Процессор "задвигает" нули справа (с нижнего регистра), и биты "выходят" слева. Последний "вышедший" бит запоминается в CF. "sal" - это синоним "shl".

        shl al,1         ; сдвиг регистра влево на один бит
        shl byte [bx],1  ; сдвиг памяти влево на один бит
        shl ax,cl        ; сдвиг регистра влево на количество из CL
        shl word [bx],cl ; сдвиг памяти влево на количество из CL

        "shr" и "sar" сдвигают операнд-адресат вправо на число битов, определенное во втором операнде. Правила для операндо такие же, как с инструкцией "shl". "shr" "задвигает" нули с левой стороны операнда-адресата, биты "выходят" справа. Последний "вышедщий" бит запоминается в CF. "sar" сохраняет знак операнда, "забивая" слева нулями, если значение положительное, и единицами, если значение отрицательное.
        "shld" сдвигает биты операнда-адресата влево за заданное в третьем операнде число битов, в то время как справа "задвигаются" биты верхних регистров операнда-источника. Операнд-источник не изменяется. Операндом-адресатом может быть регистр общего назначения или память размером в слово или двойное слово, операндом-источником должен быть регистр общего назначения, третьим операндом может быть непосредственное значение либо CL.

        shld ax,bx,1     ; сдвиг регистра влево на один бит
        shld [di],bx,1   ; сдвиг памяти влево на один бит
        shld ax,bx,cl    ; сдвиг регистра влево на количество из CL
        shld [di],bx,cl  ; сдвиг памяти влево на количество из CL

        "shrd" cдвигает биты операнда-адресата вправо, в то время как слева "задвигаются" биты нижних регистров операнда-источника. Операнд-источник остается неизменным. Правила для операндов такие же, как с инструкцией "shld".
        "rol" и "rcl" циклически сдвигают байт, слово или двойное слово влево на число битов, заданное во втором операнде. Для каждой заданной ротации старший бит, выходящий слева, появляется справа и становится самым младшим битом. "rcl" дополнительно помещает в CF каждый бит высшего регистра, выходящий слева, перед тем, как он возвратится в операнд как младший бит во время следующего цикла ротации. Правила для операндов такие же, как с инструкцией "shl".
        "ror" и "rcr" циклически сдвигают байт, слово или двойное слово вправо на число битов, заданное во втором операнде. Для каждой заданной ротации младший бит, выходящий справа, появляется слева и становится самым старшим битом. "rcr" дополнительно помещает в CF каждый бит низшего регистра, выходящий слева, перед тем, как он возвратится в операнд как старший бит во время следующего цикла ротации. Правила для операндов такие же, как с инструкцией "shl".
        "test" производит такое же действие, как инструкция "and", но не изменяет операнд-адресат, только обновляет флаги. Правила для операндов такие же, как с инструкцией "and".
        "bswap" переворачивает порядок битов в 32-битном регистре общего назначения: биты от 0 до 7 меняются местами с битами от 24 до 31, а биты от 8 до 15 меняются с битами от 16 до 23. Эта инструкция предусмотрена для преобразования значений с прямым порядком байтов к формату с обратномым порядком и наоборот.

        bswap edx        ; перестановка байтов в регистре

    Категория: Макроинструкции | Добавил: fasm (19.07.2008)
    Просмотров: 1588 | Комментарии: 1 | Рейтинг: 0.0/0
    Всего комментариев: 0
    Добавлять комментарии могут только зарегистрированные пользователи.
    [ Регистрация | Вход ]