Учебный курс. Часть 30. Команды работы с битами

Автор: xrnd | Рубрика: Учебный курс | 13-12-2010

Работать с отдельными битами операндов можно, используя логические операции и сдвиги. Однако, кроме них в системе команд x86 существуют специальные команды для работы с битами: это команды сканирования битов и команды проверки (и модификации) битов. Впервые они появились в процессоре i386. Так что сейчас вы вряд ли найдёте процессор, в котором их нет.

Команды сканирования битов

Сканирование битов выполняется командами BSF и BSR. Эти команды очень похожи. У них 2 операнда. Первый операнд должен быть 16-битным регистром, в него записывается результат. Второй операнд может быть 16-битным регистром или словом в памяти — это обрабатываемое значение.

Команда BSF просматривает биты второго операнда от младшего к старшему и помещает индекс первого единичного бита в регистр. Биты нумеруются, начиная с нуля. Если единичный бит найден, то флаг нуля сбрасывается (ZF=0). Если все биты нулевые, то флаг нуля устанавливается (ZF=1), а значение первого операнда будет неопределённым (на разных процессорах может быть по-разному). Например, мой процессор (Athlon XP) в этом случае не изменяет значение в регистре. Пример кода:

    mov ax,01011000b  ;AX=58h
    bsf bx,ax         ;BX=3, ZF=0
    xor ax,ax         ;AX=0
    bsf bx,ax         ;BX=?, ZF=1

Читать полностью »

Instruction Set Reference

Автор: xrnd | Рубрика: Книги | 22-10-2010

Полное название: «Intel Architecture Software Developer’s Manual. Volume 2: Instruction Set Reference»

Язык: английский.

Эта книга — официальная документация компании Intel по системе команд архитектуры x86. В ней содержится подробное описание всех целочисленных команд 32-битного ассемблера, а также команд некоторых расширений процессора. Кроме того рассматривается формат машинных команд и их коды. Это лучший справочник, которой должен быть всегда под рукой. Рекомендую всем, кто программирует на ассемблере.

Книга на английском языке и, насколько я знаю, на русский она не переводилась. Но чтобы пользоваться ею, серьезного знания английского не требуется. Описание каждой команды включает в себя алгоритм её работы на псевдоязыке, который понятен без перевода.

Скачать книгу

Учебный курс. Часть 26. Локальные переменные

Автор: xrnd | Рубрика: Учебный курс | 17-10-2010

До этой части учебного курса все переменные в наших программах были только глобальными — они создавались и инициализировались при запуске программы и к ним можно было обратиться из любой её части.

Локальные переменные используются для хранения промежуточных результатов во время выполнения процедуры. В отличие от глобальных, эти переменные являются временными и создаются при запуске процедуры. Для локальных переменных существует понятие области видимости — так называется область программы, в которой доступна переменная. Обычно в ассемблере область видимости ограничена процедурой, создавшей локальную переменную. Хотя возможны и более сложные варианты ;)

Создание локальных переменных

Чтобы создать локальные переменные в процедуре, необходимо выделить для них память. Эта память выделяется в стеке. Сделать это очень просто — достаточно вычесть из регистра SP значение, равное суммарному размеру всех локальных переменных в процедуре. Так как ширина стека равна 16 бит, то это значение должно быть кратно 2 байтам. При выходе из процедуры нужно восстановить указатель стека. Обычно это выполняется командой mov sp,bp (В bp сохраняется значение sp при входе в процедуру, как в случае с параметрами, передаваемыми через стек). Код процедуры с локальными переменными будет выглядеть следующим образом:

;Процедура с локальными переменными
myproc:
    push bp                 ;Сохранение BP
    mov bp,sp               ;Копирование указателя стека в BP
    sub sp,locals_size      ;Выделение памяти для локальных переменных
    ...
    mov sp,bp               ;Восстановление указателя стека
    pop bp                  ;Восстановление BP
    ret                     ;Возврат из процедуры

Читать полностью »

Учебный курс. Часть 24. Команды управления флагами

Автор: xrnd | Рубрика: Учебный курс | 10-09-2010

В предыдущей части учебного курса мы использовали флаг CF, чтобы вернуть из процедуры информацию об ошибке. Чтобы у вас сложилась полная картина, я решил в этой части подробнее рассказать о командах управления флагами.

Как вы, наверно, помните флаги изменяются в результате выполнения арифметических и логических команд, а также команд сдвига. Регистр флагов можно сохранить в стек с помощью команды PUSHF и восстановить из стека с помощью команды POPF. Кроме того, в процессоре существуют специальные команды, которые позволяют явно установить или сбросить флаги CF, DF и IF. Это очень простые команды: у них нет операндов и результатом является только изменение значения соответствующего флага.

Флаг переноса CF

Команда CLC сбрасывает флаг CF.

Команда STC устанавливает флаг CF в единицу.

Команда CMC инвертирует значение флага CF.

Читать полностью »

Учебный курс. Часть 21. Простые процедуры

Автор: xrnd | Рубрика: Учебный курс | 08-07-2010

В этой части учебного курса мы рассмотрим основы создания процедур. Процедура представляет собой код, который может выполняться многократно и к которому можно обращаться из разных частей программы. Обычно процедуры предназначены для выполнения каких-то отдельных, законченных действий программы и поэтому их иногда называют подпрограммами. В других языках программирования процедуры могут называться функциями или методами, но по сути это всё одно и то же :)

Команды CALL и RET

Для работы с процедурами предназначены команды CALL и RET. С помощью команды CALL выполняется вызов процедуры. Эта команда работает почти также, как команда безусловного перехода (JMP), но с одним отличием — одновременно в стек сохраняется текущее значение регистра IP. Это позволяет потом вернуться к тому месту в коде, откуда была вызвана процедура. В качестве операнда указывается адрес перехода, который может быть непосредственным значением (меткой), 16-разрядным регистром (кроме сегментных) или ячейкой памяти, содержащей адрес.

Читать полностью »

Учебный курс. Часть 20. Стек

Автор: xrnd | Рубрика: Учебный курс | 31-05-2010

Стеком называется структура данных, организованная по принципу LIFO («Last In — First Out» или «последним пришёл — первым ушёл»). Стек является неотъемлемой частью архитектуры процессора и поддерживается на аппаратном уровне: в процессоре есть специальные регистры (SS, BP, SP) и команды для работы со стеком.

Обычно стек используется для сохранения адресов возврата и передачи аргументов при вызове процедур (о процедурах в следующей части), также в нём выделяется память для локальных переменных. Кроме того, в стеке можно временно сохранять значения регистров.

Схема организации стека в процессоре 8086 показана на рисунке:

Читать полностью »

Учебный курс. Часть 19. Циклический сдвиг

Автор: xrnd | Рубрика: Учебный курс | 13-05-2010

Циклический сдвиг отличается от линейного тем, что выдвигаемые с одного конца биты вдвигаются с другой стороны, то есть движутся по кольцу. В процессора x86 существует 2 вида циклического сдвига: простой и через флаг переноса (CF). У всех команд, рассматриваемых в этой части учебного курса, по 2 операнда, таких же, как у команд линейного сдвига. Первый операнд — сдвигаемое значение и место для записи результата. Второй операнд — счётчик сдвигов, который может находится в регистре CL или указываться непосредственно.

Простой циклический сдвиг

Циклический сдвиг вправо выполняется командой ROR, а влево — командой ROL. Схема работы этих команд представлена на рисунке (на примере 8-битного операнда):

Читать полностью »

Учебный курс. Часть 18. Линейный сдвиг

Автор: xrnd | Рубрика: Учебный курс | 07-05-2010

Сдвиги — это особые операции процессора, которые позволяют реализовать различные преобразования данных, работать с отдельными битами, а также быстро выполнять умножение и деление чисел на степень 2. В этой части мы рассмотрим операции линейного сдвига, а в следующей будут циклические.

Логический сдвиг вправо

Логический сдвиг всегда выполняется без учёта знакового бита. Для логического сдвига вправо предназначена команда SHR. У этой команды два операнда. Первый операнд представляет собой сдвигаемое значение и на его место записывается результат операции. Второй операнд указывает, на сколько бит нужно осуществить сдвиг. Этим операндом может быть либо непосредственное значение, либо регистр CL. Схема выполнения операции показана на рисунке:

Читать полностью »

Учебный курс. Часть 17. Команды LOOPZ и LOOPNZ

Автор: xrnd | Рубрика: Учебный курс | 05-05-2010

Кроме команды LOOP и команд условных переходов существуют ещё две команды, позволяющие организовывать циклы. Это команды LOOPZ (или её синоним LOOPE) и LOOPNZ (синоним — LOOPNE). Действие этих команд очень напоминает LOOP, за исключением того, что дополнительно анализируется флаг нуля ZF.

Переход к метке цикла осуществляется в том случае, если после декремента содержимое CX не равно 0 и выполняется условие: ZF=1 (для команды LOOPZ/LOOPE) или ZF=0 (LOOPNZ/LOOPNE).

Эти команды удобно использовать в алгоритмах, где цикл должен завершаться в двух случаях:

  • выполнено требуемое количество итераций;
  • выполнено некоторое условие досрочного завершения цикла.

Читать полностью »

Учебный курс. Часть 16. Условные и безусловные переходы

Автор: xrnd | Рубрика: Учебный курс | 27-04-2010

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

Безусловные переходы

Безусловный переход — это переход, который выполняется всегда. Безусловный переход осуществляется с помощью команды JMP. У этой команды один операнд, который может быть непосредственным адресом (меткой), регистром или ячейкой памяти, содержащей адрес. Существуют также «дальние» переходы — между сегментами, однако здесь мы их рассматривать не будем. Примеры безусловных переходов:

    jmp metka    ;Переход на метку
    jmp bx       ;Переход по адресу в BX
    jmp word[bx] ;Переход по адресу, содержащемуся в памяти по адресу в BX

Читать полностью »