Ассемблер для начинающих
🕛 17.09.2009, 12:20
Эта статья начинает цикл, посвященный более глубокому изучению ассемблера. Теперь каждая статья будет разделена на две части. В первой части будут рассматриваться некоторые теоретические свнедения, а во второй - новые команды, примеры кода и приемы программирования на ассемблере.Формат машинных команд IA-32
В настоящее время существует несколько сотен (если не больше) языков программирования, но почти все компиляторы транслируют программы в язык ассемблера. Ассемблер, в свою очередь, транслирует программу в особые комбинации нулей и единиц - машинный язык (язык машинных команд), единственный язык, который понимает компьютер. На первых компьютерах все программы писались на машинном языке, но в 50-х гг. стали использовать его символический аналог - язык ассемблера.Давайте посмотрим, каким машинных командам соответствуют команды ассемблера. Рассмотрим простейшую команду:
mov ebx, eax
На машинном языке это будет выглядеть так:
8B D8
Здесь 8B - код операции. Рассмотрим другой пример:
mov ecx, 128
На машинном языке ей соответствует:
B9 00000080
Код операции - B9. Можно сделать вывод, что прямого соответствия между командой ассемблера и соответствующей машинной командой нет. Команда в примере одна и та же, а коды операций машинного языка - разные. Дело в том, что большинство команд ассемблера имеют несколько возможных вариантов сочетания операндов, а машинная команда всегда однозначна по отношению к производимым действиям на уровне аппаратуры. Код операции является номером микропрограммы в блоке микропрограммного управления. Для каждой конкретной команды ассемблера с конкретным вариантом сочетания операндов существует своя микропрограмма и свой код операции.
Любая команда ассемблера содержит несколько элементов:
* Элемент, описывающий, что делать, называется кодом операции (далее КОП). * Элементы, описывающие объекты, с которыми нужно что-то делать, называются операндами. Операнды могут не задаваться явно, а подразумеваться по умолчанию * Элементы, описывающие, как делать, называются типами операндов. Они обычно задаются неявно.
Команды передачи управления
Последовательно работает очень мало программ. Обычно в программе есть точки, в которых принимается решение о том, какая команда будет выполняться следующей. Это решение может быть безусловным (управление передается конкретной команде, которая находится на некотором удалении от текущей) и условным (команда, которая будет выполняться следующей, определяется на основе анализа некоторых условий и данных). Но каким же образом обозначается место, куда необходимо передать управление? Оно обозначается с помощью меток. Метка - символическое имя определенной ячейки памяти, предназначенное для использования в командах передачи управления в качестве операнда. Транслятор ассемблера присваивает каждой метке три атрибута:
* Имя сегмента кода, в котором эта метка описана * Смещение, то есть расстояние в байтах от начала этого сегмента * Тип метки
Метки бывают двух типов:
* near. Переход на такую метку возможен только в пределах того сегмента кода, в котором она описана * far. Переход на метку возможен в результате межсегментной передачи управления
Определить метку можно двумя способами:
* с помощью директивы LABEL * с помощью оператора “:” (двоеточие).
Используя оператор “:”, можно определить метку только ближнего типа (near). Например:
m:
mov eax,1
Используя оператор LABEL, можно определить метку любого типа. Например:
m label near
mov eax,1
или
m label far
mov eax,1
Применение меток оправдано во многих случаях. В одних лучше использовать метки ближнего типа, в других - дальнего. В следующих уроках мы рассмотрим эти случаи и научимся правильно выбирать тип метки.
Синтаксис команды безусловного перехода такой:
jmp [модификатор] адрес_перехода
Существует несколько кодов машинных команд, соответствующих JMP. Они отличаются дальностью перехода и способом задания целевого адреса. Операнд адрес_перехода может находиться в текущем сегменте(близкий переход) кода или в другом (дальний переход). Адресом перехода может являться имя метки:
jmp m
m:
mov eax,1
Есть еще такой вариант (указывается не адрес перехода, а место, где он хранится):
lea eax,m
jmp eax
m:
mov eax,1
Теперь перейдем к командам условного перехода. В таких командах решение о том, какая команда будет выполняться следующей, принимается в зависимости от некоторых условий, различных для разных команд перехода . Таких команд 18, они позволяют проверить:
* отношение операндов со знаком (больше либо меньше) * отношение операндов без знака (выше или ниже) * состояние арифметических флагов ZF, SF, CF, OF, PF(но не AF)
Все команды условного перехода имеют одинаковый синтаксис:
jcc метка_перехода
Любая из них начинается с символа “j” (от слова jump), а вместо “cc” указывается конкретное условие, которое должна проанализировать программа. Метка перехода может находиться только в пределах текущего сегмента! Поэтому необходимость в модификаторе отпадает (всегда near). Условие обязательно должно быть сформировано до команды передачи управления. Его источником может служить любая команда, изменяющая состояние арифметических флагов или регистра ECX/CX.
В большинстве случаев Вы будете пользоваться командой CMP. Поэтому сейчас я немного расскажу вам о ней. Команда CMP производит практически те же действия, что и команда SUB, только она не записывает результат вычитания на место первого операнда, а просто устанавливает флаги (нас интересует флаг знака результата, и флаг нулевого результата). Вот ее синтаксис:
cmp операнд_1, операнд_2
Флаги, устанавливаемые командой CMP, можно проанализировать командами условного перехода. Понимание принципа формирования названий команд условного перехода облегчит их запоминание и дальнейшее практическое использование (см. табл. 1).
Таблица 1. Принцип формирования элемента “сс” команд условного перехода
Мнемоническое обозначение Оригинальный термин Перевод Тип операндов e Equal Равно Любые n Not Нет Любые g Greater Больше Числа со знаком l Less Меньше Числа со знаком a Above Выше(то есть больше) Числа без знака b Below Ниже(то есть меньше) Числа без знака
Привожу пример программы, которая обнуляет поле pole_m длинной n байт:
.data
n equ 50
pole_m db n dup (?)
.code
;...
xor bx, bx ; очищаем bx
m1:
mov mem[bx], 0 ; заносим в mem[bx] 0
inc bx ; увеличение bx на 1
cmp bx, n ; сравниваем bx с n (вычитаем n из bx)
jne m1 ; если bx не равен n, то повторяем все завново
exit:
;...
В табл. 2 перечислены команды условного перехода, которые можно использовать после команды cmp:
Таблица 2. Команды условного перехода
Типа операндов Мнемокод команды
условного перехода Критерий условного
перехода Значения флагов
для перехода Любые JE операнд_1=операнд_2 ZF=1 Любые JNE операнд_1<>операнд_2 ZF=0 Со знаком JL/JNGE операнд_1<операнд_2 SF<>OF Со знаком JLE/JNG операнд_1<=операнд_2 SF<>OF или ZF=1 Со знаком JG/JNLE операнд_1>операнд_2 SF=OF или ZF=0 Со знаком JGE/JNL операнд_1=>операнд_2 SF=OF Без знака JB/JNAE операнд_1<операнд_2 CF=1 Без знака JBE/JNA операнд_1<=операнд_2 CF=1 или ZF=1 Без знака JA/JNBE операнд_1>операнд_2 CF=0 и ZF=0 Без знака JAE/JNB операнд_1=>операнд_2 CF=0
Теперь, используя эту таблицу, Вы сможете с легкостью применять команды условного перехода. На этом мы закончим. Удачи!