
- •1. Регистры
- •1.1. Регистры общего назначения
- •1.2. Указатель команд
- •1.3. Регистр флагов
- •1.3.1. Флаги состояния
- •1.3.2. Управляющий флаг
- •1.3.3. Системные флаги и поле iopl
- •1.4. Сегментные регистры
- •1.5. Использование стека
- •2. Основные понятия языка ассемблера
- •2.1. Идентификаторы
- •2.2. Целые числа
- •2.3. Символьные данные
- •2.4. Комментарии
- •2.5. Директива эквивалентности
- •2.6. Директивы определения данных
- •2.7. Команды
- •2.8. Операнды команд
- •3. Пересылка и арифметические команды
- •3.1. Команды пересылки и обмена
- •3.2. Оператор указания типа
- •3.3. Команды сложения и вычитания
- •3.4. Команды умножения и деления
- •3.4.1. Команды умножения
- •3.4.2. Команды деления
- •3.5. Изменение размера числа
- •4. Переходы и циклы
- •4.1. Безусловный переход
- •4.1.1. Прямой переход
- •4.1.2. Косвенный переход
- •4.2. Команды сравнения и условного перехода
- •4.3. Команды управления циклом
- •4.3.1. Команда loop
- •4.3.2. Команды loope/loopz и loopne/loopnz
- •5. Массивы
- •5.1. Модификация адресов
- •5.2. Команда lea
- •5.3. Обработка массивов
- •6. Поразрядные операции
- •6.1. Логические команды
- •6.2. Команды сдвига
- •6.3. Умножение и деление с помощью поразрядных операций
- •6.3.1. Умножение
- •6.3.2. Деление
- •6.3.3. Получение остатка от деления
- •7. Программа. Процедуры
- •7.1. Структура программы на языке ассемблера
- •7.2. Команды работы со стеком
- •7.3. Синтаксис процедуры
- •7.4. Вызов процедуры и возврат из процедуры
- •7.5. Передача параметров процедуры
- •7.6. Передача результата процедуры
- •7.7. Сохранение регистров в процедуре
- •7.8. Локальные данные процедур
- •7.9. Рекурсивные процедуры
- •8. Оптимизация программ, написанных на языке ассемблера
- •8.1. Высокоуровневая оптимизация
- •8.2. Оптимизация среднего уровня
- •8.2.1. Вычисление констант вне цикла
- •8.2.2. Перенос проверки условия в конец цикла
- •8.2.3. Выполнение цикла задом наперёд
- •8.2.4. Разворачивание циклов
- •8.3. Низкоуровневая оптимизация
- •8.3.1. Основные принципы
- •8.3.2. Использование команды lea
- •8.3.3. Замена команд
- •8.3.4. Выравнивание
- •9. Примеры
6.1. Логические команды
Операция отрицания меняет значение всех битов переменной на противоположное. Операция имеет один операнд, который может быть регистром или ячейкой памяти. Операция не меняет флаги.
NOT <операнд>
Операция поразрядное «и» выполняет логическое умножение всех пар бит операндов.
AND <операнд1>, <операнд2>
Операция поразрядное «или» выполняет логическое сложение всех пар бит операндов.
OR <операнд1>, <операнд2>
Операция поразрядное исключающее «или» выполняет сложение по модулю 2 всех пар бит операндов.
XOR <операнд1>, <операнд2>
Операции AND, OR и XOR имеют по два операнда. Первый может быть регистром или ячейкой памяти, а второй – регистром, ячейкой памяти или непосредственным операндом. Операнды должны иметь одинаковый размер. Результат помещается на место первого операнда. Операции меняют флаги CF, OF, PF, SF и ZF.
Операция XOR имеет интересную особенность – если значения операндов совпадают, то результатом будет значение 0. Поэтому операцию XOR используют для обнуления регистров – она выполняется быстрее, чем запись нуля с помощью команды MOV.
xor eax, eax ; При любом значении EAX результат будет равен 0
Операцию XOR можно также использовать для обмена значений двух переменных.
xor eax, ebx xor eax, ebx xor eax, ebx
6.2. Команды сдвига
Операции сдвига вправо и сдвига влево сдвигают биты в переменной на заданное количество позиций. Каждая команда сдвига имеет две разновидности:
<мнемокод> <операнд>, <непосредственный операнд> <мнемокод> <операнд>, CL
Первый операнд должен быть регистром или ячейкой памяти. Именно в нём осуществляется сдвиг. Второй операнд определяет количество позиций для сдвига, которое задаётся непосредственным операндом или хранится в регистре CL (и только CL).
Команды сдвига меняют флаги CF, OF, PF, SF и ZF.
Существует несколько разновидностей сдвигов, которые отличаются тем, как заполняются «освобождающиеся» биты.
6.2.1. Логические сдвиги
При логическом сдвиге «освобождающиеся» биты заполняются нулями. Последний ушедший бит сохраняется во флаге CF.
SHL <операнд>, <количество> ; Логический сдвиг влево SHR <операнд>, <количество> ; Логический сдвиг вправо
6.2.2. Арифметические сдвиги
Арифметический сдвиг влево эквивалентен логическому сдвигу влево (это одна и та же команда) – «освобождающие» биты заполняются нулями. При арифметическом сдвиге вправо «освобождающиеся» биты заполняются знаковым битом. Последний ушедший бит сохраняется во флаге CF.
SAL <операнд>, <количество> ; Арифметический сдвиг влево SAR <операнд>, <количество> ; Арифметический сдвиг вправо
6.2.3. Циклические сдвиги
При циклическом сдвиге «освобождающиеся» биты заполняются ушедшими битами. Последний ушедший бит сохраняется во флаге CF.
ROL <операнд>, <количество> ; Циклический сдвиг влево ROR <операнд>, <количество> ; Циклический сдвиг вправо
6.2.4. Расширенные сдвиги
Расширенные сдвиги немного отличаются от остальных сдвигов. В расширенных сдвигах участвуют два регистра или ячейка памяти и регистр, которые как бы объединяются в единое целое и «освобождающиеся» биты одного операнда заполняются битами из другого операнда.
SHLD <операнд1>, <операнд2>, <количество> ; Расширенный сдвиг влево SHRD <операнд1>, <операнд2>, <количество> ; Расширенный сдвиг вправо
Команда SHLD сдвигает влево биты операнда1 на указанное количество позиций. Младшие («освободившиеся») биты операнда1 заполняются старшими битами операнда2. Сам операнд2 не меняется.
Команда SHRD сдвигает вправо биты операнда1 на указанное количество позиций. Старшие («освободившиеся») биты операнда1 заполняются младшими битами операнда2. Сам операнд2 не меняется.
Количество, как и в других операциях сдвига, задаётся непосредственным операндом или хранится в регистре CL. Но используются только последние 5 бит операнда, определяющего количество, т.е. максимальное количество позиций сдвига равно 32.
Команды расширенного сдвига обычно используют для создания упакованных данных.