
- •Лекция №1. Основные понятия. Первая программа для dos и под Windows. Представление данных в компьютере.
- •Сам ассемблер — программа, которая переводит текст с языка, понятного человеку, в язык, понятный процессору, получает объектный модуль;
- •Компоновщик (linker), который создает исполнимые файлы из одного или нескольких объектных модулей, полученных после запуска ассемблера;
- •Дополнительные вспомогательные программы — компиляторы ресурсов, расширители dos и тому подобное (см. Табл.).
- •Написать её в блокноте, сохранять в *.Asm файл;
- •Из командной строки вызвать ассемблер tasm32.Exe (tasm.Exe);
- •Из командной строки вызвать линковщик tlink32.Exe (tlink.Exe);
- •Процессоры и их регистры
- •Процессоры x86
- •Регистры процессора
- •Описание регистров
- •Задача: найти старшую часть расширенного регистра (eax, ebx, ..., esi, edi)?
- •0030:4012 (Всё шестнадцатиричное)
- •4) Нельзя использовать сегментный регистр cs в качестве операнда назначения.
- •5) Оператор ptr можно применять и когда требуется принудительно поменять размерность операндов. К примеру, требуется переслать значение 0ffh во второй байт поля flp:
- •Xchg eax,ebx ; обменять содержимое регистров eax и ebx.
- •Xchg al,al ; а эта команда не делает ничего
- •Xchg ax, word ptr [si] ; обменять содержимое регистра ах и слова в памяти по адресу в [si].
- •Технология sse. Блок xmm
- •Имеются специальные команды сравнения двух вещественных чисел. После их выполнения формируются и помещаются в eflags признаки, характеризующие результат операции.
- •8 Флагов состояния. Эти флаги могут изменяться после выполнения машинных команд;
- •1) Первой известной кодировкой символов была кодировка ascii, и она используется до сих пор. В ascii-кодировке каждый символ занимает 8 бит, или один байт.
- •2. Адресные операнды – задают физическое расположение операнда в памяти с помощью указания двух составляющих адреса: сегмента и смещения. К примеру:
- •6. Структурные операнды используются для доступа к конкретному элементу структуры.
- •7. Записи (аналогично структурному типу) используются для доступа к битовому полю некоторой записи.
- •Команды безусловной передачи управления:
- •Команды условной передачи управления:
- •Команды управления циклом:
- •Лекция № 4. Условные переходы. Арифметиченские команды. Bcd числа.
- •1111111011101101 Инвертируем 0000000100010010
- •Лекция №5. Арифметические команды над целыми числами (продолжение). Арифметические операции над двоично-десятичными числами (bcd числами)
- •К содержимому младшей тетрады al прибавляется 6;
- •Флаг cf устанавливается в 1, тем самым фиксируется перенос в старший разряд для того, чтобы его можно было учесть в последующих действиях.
- •Из содержимого младшей тетрады регистра al вычитается 6;
- •Обнуляется старшая тетраду регистра al;
- •Устанавливает флаг cf в 1, фиксируя воображаемый заём из старшего разряда.
- •Делит ax на 10;
- •Результат деления записывается так: частное – в ah, остаток в al.
- •1) Преобразует двузначное неупакованное bcd-число в регистре ах в двоичное число;
- •2) Полученное двоичное число используется в качестве делимого в операции деления;
- •3) Полученное двоичное число помещается в регистр aх.
- •Деление с остатком
- •Блок-схема вывода результата при делении с остатком Числа с плавающей запятой. Работа с сопроцессором
- •Число имеет вид 1,1100011 × 2-1 или 0,11100011.
- •Переводом в десятичную систему счисления получаем 0,88671875. Лекция №6. Работа с сопроцессором. Команды для работы с fpu. Работа с fpu.
- •Блок-схема вывода на экран вещественного числа, которое хранится в регистре st(0) сопроцессора.
- •Деление с остатком, используя команды целочисленного деления
- •Блок-схема вывода результата при делении с остатком Трансцендентные операции fpu
- •Массивы
- •Перечислением элементов массива в поле операндов одной из директив описания данных. Например:
- •Используя оператор повторения dup. К примеру:
- •4) Mov esi,6*2 ; 2 байта – размер элементов
- •Индексная адресация со смещением — режим адресации, при котором полный адрес формируется из двух компонентов:
- •Базовая индексная адресация со смещением — режим адресации, при котором полный адрес формируется максимум из трех компонентов:
- •Структуры
- •Организовать обращение к элементам структуры.
- •Цепочечные команды или команды обработки строк символов
- •Организация обращения к элементам записи.
- •Iotest record
- •Работа с записями
- •1) Для выделения элемента записи необходимо:
- •2) Чтобы поместить измененный элемент на его место в запись необходимо:
- •3. В конце работы файл следует закрыть.
- •4. Признаком ошибки при выполнении функции dos является взведенный флаг с (переноса).
- •2. Создание файла с усечением существующего до нулевой длины.
- •LpFileName — указатель на asciiz-строку с именем (путем) открываемого или создаваемого файла;
- •DwDesiredAccess — тип доступа к файлу:
- •4) Mov esi,6*2 ; 2 байта – размер элементов
- •Индексная адресация со смещением — режим адресации, при котором полный адрес формируется из двух компонентов:
- •Базовая индексная адресация со смещением — режим адресации, при котором полный адрес формируется максимум из трех компонентов:
- •Структуры
- •Организовать обращение к элементам структуры.
- •Цепочечные команды или команды обработки строк символов
- •Организация обращения к элементам записи.
- •Iotest record
- •Работа с записями
- •1) Для выделения элемента записи необходимо:
- •2) Чтобы поместить измененный элемент на его место в запись необходимо:
- •3. В конце работы файл следует закрыть.
- •4. Признаком ошибки при выполнении функции dos является взведенный флаг с (переноса).
- •2. Создание файла с усечением существующего до нулевой длины.
- •LpFileName — указатель на asciiz-строку с именем (путем) открываемого или создаваемого файла;
- •DwDesiredAccess — тип доступа к файлу:
- •3) Создать и открыть новый файл
- •4) Чтение из файла или устройства
- •5) Переместить указатель чтения/записи
- •1) HFile – хэндл того файла, в котором перемещается указатель.
- •7) Запись в файл или устройство
- •8) Закрыть файл
- •9) Удаление файла
- •Функция 01h – ожидание ввода символа с эхопечатью
- •Функция 0ah – получение строки символов
- •1) Создать каталог
- •2) Удалить каталог
- •5) Определить текущий каталог
- •Перечень функций прерывания 21h, работающих с файлами, которые имеют длинные имена и соответствующие функции api Win32.
- •Перечислим функции api Win32, имеющие отношение к работе с файловой системой.
- •1) В Win32 получить время создания, время последнего доступа и время последней модификации файла можно с помощью функции GetFileTime.
- •3) В Win32 имеется функция GetFileInformationByHandle, с помощью которой можно получить все атрибуты файла:
- •Int 10h ; вызов прерывания bios
- •Основные графические режимы vga
- •Int 10h ; считываем символ и его атрибут
- •Стандартные цветовые палитры в режимах 4,5,6.
- •02H/03h - Чтение/запись секторов.
- •Прямое программирование видеобуфера в текстовом режиме
- •Лекция №6. Работа с сопроцессором. Команды для работы с fpu. Работа с fpu.
- •Лабораторная работа №12. Тема: Графические видеорежимы. Работа с vga-режимами
- •Лабораторная работа № 8. Тема: Работа с файлами
- •Лабораторная работа №5. Тема: Работа с массивами
- •Лекция №1. Основные понятия. Первая программа для dos и под Windows. Представление данных в компьютере.
- •Сам ассемблер — программа, которая переводит текст с языка, понятного человеку, в язык, понятный процессору, получает объектный модуль;
- •Компоновщик (linker), который создает исполнимые файлы из одного или нескольких объектных модулей, полученных после запуска ассемблера;
- •Дополнительные вспомогательные программы — компиляторы ресурсов, расширители dos и тому подобное (см. Табл.).
- •Написать её в блокноте, сохранять в *.Asm файл;
- •Из командной строки вызвать ассемблер tasm32.Exe (tasm.Exe);
- •Из командной строки вызвать линковщик tlink32.Exe (tlink.Exe);
- •Процессоры и их регистры
- •Процессоры x86
- •Регистры процессора
- •Описание регистров
- •Задача: найти старшую часть расширенного регистра (eax, ebx, ..., esi, edi)?
- •0030:4012 (Всё шестнадцатиричное)
- •4) Нельзя использовать сегментный регистр cs в качестве операнда назначения.
- •5) Оператор ptr можно применять и когда требуется принудительно поменять размерность операндов. К примеру, требуется переслать значение 0ffh во второй байт поля flp:
- •Xchg eax,ebx ; обменять содержимое регистров eax и ebx.
- •Xchg al,al ; а эта команда не делает ничего
- •Xchg ax, word ptr [si] ; обменять содержимое регистра ах и слова в памяти по адресу в [si].
- •Технология sse. Блок xmm
- •Имеются специальные команды сравнения двух вещественных чисел. После их выполнения формируются и помещаются в eflags признаки, характеризующие результат операции.
- •8 Флагов состояния. Эти флаги могут изменяться после выполнения машинных команд;
- •1) Первой известной кодировкой символов была кодировка ascii, и она используется до сих пор. В ascii-кодировке каждый символ занимает 8 бит, или один байт.
- •2. Адресные операнды – задают физическое расположение операнда в памяти с помощью указания двух составляющих адреса: сегмента и смещения. К примеру:
- •5. Структурные операнды используются для доступа к конкретному элементу структуры.
- •6. Записи (аналогично структурному типу) используются для доступа к битовому полю некоторой записи.
- •Команды безусловной передачи управления:
- •Команды условной передачи управления:
- •Команды управления циклом:
- •От типа операнда в команде безусловного перехода (ближний или дальний);
- •Лабораторная работа №1. Тема: знакомство с системой программирования Турбо-ассемблер.
- •1) Пересылка данных
- •2) Xor логическое исключающее или
- •3) Команды передачи управления
- •Задание для самостоятельной работы
- •Лабораторная работа №1. Тема: знакомство с системой программирования Турбо-ассемблер.
- •1) Пересылка данных
- •2) Xor логическое исключающее или
- •3) Команды передачи управления
- •Команды вычитания.
- •Команды умножения.
- •Команда деления
- •Команды преобразования
- •Команды сдвига
- •Задание для самостоятельной работы.
- •Лабораторная работа №4. Тема: перевод чисел из шестнадцатиричной системы исчисления в десятичную и в двоичную.
- •Задание для самостоятельной работы.
- •Лекция №10. Сложные структуры данных. Массивы. Структуры.
- •4) Mov esi,6*2 ; 2 байта – размер элементов
- •Индексная адресация со смещением — режим адресации, при котором полный адрес формируется из двух компонентов:
- •Базовая индексная адресация со смещением — режим адресации, при котором полный адрес формируется максимум из трех компонентов:
- •Структуры
- •Организовать обращение к элементам структуры.
- •Цепочечные команды или команды обработки строк символов
- •Организация обращения к элементам записи.
- •Iotest record
- •Работа с записями
- •1) Для выделения элемента записи необходимо:
- •2) Чтобы поместить измененный элемент на его место в запись необходимо:
- •3. В конце работы файл следует закрыть.
- •4. Признаком ошибки при выполнении функции dos является взведенный флаг с (переноса).
- •2. Создание файла с усечением существующего до нулевой длины.
- •LpFileName — указатель на asciiz-строку с именем (путем) открываемого или создаваемого файла;
- •DwDesiredAccess — тип доступа к файлу:
- •Лекция №6. Работа с сопроцессором. Команды для работы с fpu. Работа с fpu.
- •Лекция №6. Работа с сопроцессором. Команды для работы с fpu. Работа с fpu.
- •Лекция №6. Работа с сопроцессором. Команды для работы с fpu. Работа с fpu.
- •Лабораторная работа №1. Тема: знакомство с системой программирования Турбо-ассемблер.
- •1) Пересылка данных
- •2) Xor логическое исключающее или
- •3) Команды передачи управления
- •Лабораторная работа №2. Тема: Работа с арифметическими командами.
- •Команды сложения
- •Команды вычитания.
- •Команды умножения.
- •Команда деления
- •Команды преобразования
- •Команды сдвига
- •Лабораторная работа №4. Тема: перевод чисел из шестнадцатиричной системы исчисления в десятичную и в двоичную.
- •Директива extrn Режимы Ideal, masm
- •Преимущества и недостатки ]Преимущества
- •Недостатки
- •Блок-схема вывода на экран вещественного числа, которое хранится в регистре st(0) сопроцессора.
- •Трансцендентные операции fpu
- •Функция MessageBox
- •1) Первой известной кодировкой символов была кодировка ascii, и она используется до сих пор. В ascii-кодировке каждый символ занимает 8 бит, или один байт.
- •2.Адресные операнды – задают физическое расположение операнда в памяти с помощью указания двух составляющих адреса: сегмента и смещения. К примеру:
- •5. Структурные операнды используются для доступа к конкретному элементу структуры.
- •6. Записи (аналогично структурному типу) используются для доступа к битовому полю некоторой записи.
- •4) Нельзя использовать сегментный регистр cs в качестве операнда назначения.
- •5) Оператор ptr можно применять и когда требуется принудительно поменять размерность операндов. К примеру, требуется переслать значение 0ffh во второй байт поля flp:
- •Xchg eax,ebx ; обменять содержимое регистров eax и ebx.
- •Xchg al,al ; а эта команда не делает ничего
- •Xchg ax, word ptr [si] ; обменять содержимое регистра ах и слова в памяти по адресу в [si].
-
От типа операнда в команде безусловного перехода (ближний или дальний);
-
от указания перед адресом перехода (в команде перехода) модификатора; при этом сам адрес перехода может находиться либо непосредственно в команде (прямой переход), либо в регистре или в ячейке памяти (косвенный переход).
Модификатор может принимать следующие значения:
– near ptr – прямой переход на метку внутри текущего сегмента кода (изменяется только содержимое регистра ip);
– far ptr – прямой переход на метку в другом сегменте кода (изменяется содержимое регистров cs и ip);
– word ptr – косвенный переход на метку внутри текущего сегмента кода (изменяется только содержимое регистра ip);
– dword ptr – косвенный переход на метку в другом сегменте кода (изменяется содержимое регистров cs и ip);
Безусловный переход jmp
Общий синтаксис:
Jmp [модификатор] адрес_перехода – безусловный переход без сохранения точки возврата.
Существуют несколько кодов машинных команд безусловного перехода jmp.
Дальность перехода определяется местоположением операнда адрес_перехода и бывает внутрисегментным или близким или межсегментным или дальним.
Можно выделить три варианта внутрисегментного использования команды jmp:
– прямой короткий (расстояние от команды jmp до адреса перехода не более чем -128 или +128 байтов, машинная команда безусловного перехода длиной в 2 байта);
– прямой (машинная команда безусловного перехода длиной в 3 байта);
– косвенный.
Если адрес перехода расположен до команды jmp, то ассемблер формирует короткую команду безусловного перехода без дополнительный указаний. Если адрес перехода располагается после команды jmp, то для формирования короткого безусловного перехода используют модификатор short ptr.
Пример 1: (формирование короткого безусловного перехода):
…
jmp short ptr m1
… ; не более 35-40 команд (127 байтов)
m1:
Пример 2: (формирование короткого безусловного перехода):
m1:
… ; не более 35-40 команд (127 байтов)
…
jmp m1
…
При прямом внутрисегментном переходе можно производить переходы в приделах 64 Кбайт относительно следующей за jmp команды.
Пример 3:
M1:
… ; расстояние более 128 байт и менее 64 Кбайт
jmp m1
….
При косвенном внутрисегментном переходе указывается не сам адрес перехода, а место, где он записан.
Пример 4:
Lea bx,m1
Jmp bx ; адрес перехода в регистре bx
…
m1:
…
Пример 5:
.data
addr dw m1
dw m2
…
.code
…
cycl:
mov si,0
jmp addr[si] ; адрес перехода в слове addr+(si)
…
mov si,1
jmp addr[si] ; адрес перехода в слове addr+(si)
jmp cycl
m1:
…
m2:
Межсегментный переход изменяет регистры cs и eip/ip. Межсегментный переход поддерживает два варианта команд безусловного перехода: прямой и косвенный.
Команда прямого межсегментного перехода имеет длину пять байтов, из которых два байта составляют значение смещения и два байта – значение сегментной составляющей адреса.
Пример 6:
Seg_1 segment
…
jmp far ptr m2
…
m1 label far
…
seg_1 ends
seg_2 segment
…
m2 label far
jmp m1
Команда косвенного межсегментного перехода в качестве операнда имеет адрес области памяти , в которой содержатся смещение и сегментная часть адреса перехода.
Таким образом, модификаторы short ptr, near ptr, word ptr применяются для организации внутрисегментных переходов, а far ptr, dword ptr – межсегментных.
Процедуры
В языке ассемблера есть несколько средств, решающих проблему дублирования участков программного кода. К ним относятся:
– механизм процедур;
– макроассемблер;
– механизм прерываний.
Обратиться к процедуре можно с помощью любой команды перехода.
Контекст – информация о состоянии программы в точке вызова процедуры.
Есть две команды, осуществляющие работу с контекстом. Это команды call и ret:
– call[модификатор] имя_процедуры – вызов процедуры. Команда call, подобно jmp передаёт управление по адресу с символическим именем имя_процедуры, но при этом в стеке сохраняется адрес возврата. Адрес возврата – это адрес команды, следующей после команды call;
– ret [число] – возвратить упраление вызывающей программе. Команда ret считывает адрес возврата из стека и загружает его в регистр cs и eip/ip тем самым возвращая управление на команду следующую в программе за командой call. [число] – необязательный параметр, обозначающий количество элементов, удаляемых из стека при возврате из процедуры.
Вызов процедуры командой call может быть:
– внутрисегментным – процедура находиться в текущем сегменте кода (имеет тип near), и в качестве возврата команда call сохраняет в стек только содержимое регистра eip/ip;
– межсегментным – процедура находится в другом сегменте кода (имеет тип far) и для осуществления возврата команда call заносит в стек содержимое обоих регистров cs и eip/ip. Очерёдность такова: сначала в стек помещается регистр cs, а потом eip/ip.
Подобно команде jmp существует четыре разновидности команды call, в зависимости от значения [модификатор] и атрибута дальности в описании процедуры.
Значения [модификатор] такие же, как и у команды jmp за исключением short ptr.
– near ptr;
а) прямой короткий (short ptr);
б) прямой;
в) косвенный.
– far ptr;
– word ptr
– dword ptr
Условные переходы
Микропроцессор имеет 18 команд условного перехода, позволяющие проверить:
– отношение между операндами со знаком (больше-меньше);
– отношение между операндами без знака (выше-ниже);
– состояние арифметических флагов zf,sf, cf, of, pf.
Команды условного перехода имеют одинаковый синтаксис:
Jcc метка_перехода
Межсегментной передачи управления в условных переходах не допускается (максимальный переход равен размеру сегмента).
Источниками условия для перехода могут быть:
– любая команда, изменяющая состояние арифметических флагов;
– команда сравнения cmp;
– состояние регистра ecx/cx.
Команда cmp выполняет вычитание операторов и устанавливает флаги, не записывает результат вычитания на место первого операнда.
Cmp операнд_1, операнд_2
Значения аббревиатур в названии команды jcc:
Пример 7: сравним очередной элемент массива с 5:
Команды условного перехода и флаги
cmp x, y
Опкод |
Значение(переход,если...) |
Условие |
JA |
Jump if above (X > Y) |
CF=0 & ZF=0 |
JAE |
Jump if above or equal (X >= Y) |
CF=0 |
JB |
Jump if below (X < Y) |
CF=1 |
JBE |
Jump if below or equal (X < Y) |
CF=1 or ZF=1 |
JC |
Jump if carry (cf=1) |
CF=1 |
JCXZ |
Jump if CX=0 |
регистр CX=0 |
JE (то же, что и JZ) |
Jump if equal (X = Y) |
ZF=1 |
JG |
Jump if greater (signed) (X > Y) |
ZF=0 & SF=OF |
JGE |
Jump if greater or equal (signed) (X >= Y) |
SF=OF |
JL |
Jump if less (signed) (X < Y) |
SF != OF |
JLE |
Jump if less or equal (signed) (X <= Y) |
ZF=1 or SF!=OF |
JMP |
Безусловный переход |
- |
JNA |
Jump if not above (X <= Y) |
CF=1 or ZF=1 |
JNAE |
Jump if not above or equal (X < Y) |
CF=1 |
JNB |
Jump if not below (X >= Y) |
CF=0 |
JNBE |
Jump if not below or equal (X > Y) |
CF=1 & ZF=0 |
JNC |
Jump if not carry (cf=0) |
CF=0 |
JNE |
Jump if not equal (X != Y) |
ZF=0 |
JNG |
Jump if not greater (signed) (X <= Y) |
ZF=1 or SF!=OF |
JNGE |
Jump if not greater or equal (signed) (X < Y) |
SF!=OF |
JNL |
Jump if not less (signed) (X >= Y) |
SF=OF |
JNLE |
Jump if not less or equal (signed) (X > Y) |
ZF=0 & SF=OF |
JNO |
Jump if not overflow (signed) (of=0) |
OF=0 |
JNP |
Jump if no parity (pf=0) |
PF=0 |
JNS |
Jump if not signed (signed) (sf=0) |
SF=0 |
JNZ |
Jump if not zero (X != Y) |
ZF=0 |
JO |
Jump if overflow (signed) (of=1) |
OF=1 |
JP |
Jump if parity (pf=1) |
PF=1 |
JP |
Jump if parity (pf=1) |
PF=1 |
JPE |
Jump if parity even |
PF=1 |
JPO |
Jump if parity odd |
PF=0 |
JS |
Jump if signed (signed) |
SF=1 |
JZ |
Jump if zero (X = Y) |
ZF=1 |
Пример 8: надо преобразовать строчные буквы в прописные. Строчным буквам в таблице ASCII символов соответствует диапазон 61h-7ah, прописным – 41h-5ah. Для выполнения преобразования между строчными и прописными буквами достаточно инвертировать 5 бит.
Например:
а – 01100001 z – 01111010
А – 01000001 Z – 01011010
Таблица ASCII кодов.
|
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
A |
B |
C |
D |
E |
F |
0 |
... |
... |
|
0 |
@ |
P |
' |
Р |
А |
Р |
а |
... |
... |
... |
р |
Ё |
1 |
... |
... |
! |
1 |
A |
Q |
a |
Q |
Б |
С |
б |
... |
... |
... |
с |
ё |
2 |
... |
... |
" |
2 |
B |
R |
b |
R |
В |
Т |
в |
... |
... |
... |
т |
Є |
3 |
... |
... |
# |
3 |
C |
S |
c |
S |
Г |
У |
г |
... |
... |
... |
у |
є |
4 |
... |
... |
$ |
4 |
D |
T |
d |
T |
Д |
Ф |
д |
... |
... |
... |
ф |
Ї |
5 |
... |
... |
% |
5 |
E |
U |
e |
U |
Е |
Х |
е |
... |
... |
... |
х |
ї |
6 |
... |
... |
& |
6 |
F |
V |
f |
V |
Ж |
Ц |
ж |
... |
... |
... |
ц |
Ў |
7 |
... |
... |
' |
7 |
G |
W |
g |
W |
З |
Ч |
з |
... |
... |
... |
ч |
ў |
8 |
... |
... |
( |
8 |
H |
X |
h |
X |
И |
Ш |
и |
... |
... |
... |
ш |
° |
9 |
... |
... |
) |
9 |
I |
Y |
i |
Y |
Й |
Щ |
й |
... |
... |
... |
щ |
∙ |
A |
... |
... |
* |
: |
J |
Z |
j |
Z |
К |
Ъ |
к |
... |
... |
... |
ъ |
· |
B |
... |
... |
+ |
; |
K |
[ |
k |
{ |
Л |
Ы |
л |
... |
... |
... |
ы |
√ |
C |
... |
... |
, |
< |
L |
\ |
l |
| |
М |
Ь |
м |
... |
... |
... |
ь |
№ |
D |
... |
... |
- |
= |
M |
] |
m |
} |
Н |
Э |
н |
... |
... |
... |
э |
¤ |
E |
... |
... |
. |
> |
N |
^ |
n |
~ |
О |
Ю |
о |
... |
... |
... |
ю |
■ |
F |
... |
... |
/ |
? |
O |
_ |
o |
¤ |
П |
Я |
п |
... |
... |
... |
я |
|
Команды условного перехода и регистр есх/сх.
Регистр есх/сх выполняет роль счётчика в командах управления циклами и при работе с цепочками символов.
Синтаксис этой команды таков:
– Jcxz метка_перехода (Jump if is zero) – прыжок, если сх ноль;
– jecxz метка_перехода (Jump equal ecx zero) – переход, если есх ноль.
В отличие от других команд условной передачи управления, команды Jcxz/ jecxz могут адресовать только короткие переходы – на -128 байт или на +127 байт от следующей за ней командой.
Организация циклов
В системе команд микропроцессора существует три команды для работы с циклами. Данные команды:
1) loop метка_перехода – повторить цикл. Работа команды заключается в выполнении следующих действий:
а) декремента регистра есх/сх;
б) сравнение регистра есх/сх с нулём;
если (есх/сх)>0, то управление передаётся на метку перехода;
если (есх/сх)=0, то управление передаётся на следующую после loop команду;
2) loope/loopz метка_перехода – повторить цикл пока сх<>0 или zf=0. Команды loope и loopz – абсолютные синонимы. Работа команд заключается в выполнении следующих действий:
а) декремента регистра есх/сх;
б) сравнение регистра есх/сх с нулём;
в) анализа состояния флага нуля zf;
если (есх/сх)>0, и zf=1, управление передаётся на метку перехода;
если (есх/сх)=0, или zf=0, управление передаётся на следующую после loop команду;
3) loopne/loopnz метка_перехода – повторить цикл пока сх<>0 или zf=1. Команды loope и loopz – абсолютные синонимы. Работа команд заключается в выполнении следующих действий:
а) декремента регистра есх/сх;
б) сравнение регистра есх/сх с нулём;
в) анализа состояния флага нуля zf;
если (есх/сх)>0, и zf=0, управление передаётся на метку перехода;
если (есх/сх)=0, или zf=1, управление передаётся на следующую после loop команду;
Команды loop loope/loopz и loopne/loopnz реализуют только короткие переходы (от -128 до _127 байтов). Для работы с длинными циклами необходимо использовать команду jmp.
При работе с вложенными циклами возникает проблема сохранения значения счётчика внешнего цикла есх/сх на время выполнения внутреннего цикла. Для этого можно использовать регистры, ячейки памяти или стек.
Пример программы, содержащей три цикла вложенных один в другой.
Сложение двоичных чисел без знака
Если при сложении результат превышает размерность поля операнда, то результат оказывается неверным. Например: 254+5=259 (11111110+0000101=1 00000011). Для фиксирования ситуации выхода за разрядную сетку результата предназначен флаг переноса cf. Поэтому после операции сложения в программе предполагается включение участков кода, в которых анализируется флаг cf. Это можно сделать с помощью команды условного перехода jc <метка>.
В системе команд микропроцессора имеются три команды двоичного сложения:
– INC <операнд> ; операция инкремента, то есть увеличение значения операнда на 1.
– ADD <операнд_1><операнд_2>;
Принцип действия:
операнд_1=операнд_1+операнд_2.
В этой команде нельзя использовать переменную одновременно и для опернда_1, и для операнда_2. Команда ADD не различает числа со знаком и без знака.
– ADC <операнд_1><операнд_2>; команда сложения с учётом флага переноса cf.
Принцип действия:
операнд_1=операнд_1+операнд_2+значение_cf.
Имеющиеся варианты приёмника и источник:
Операнд_1 |
Операнд_2 |
пример |
регистр |
регистр |
add ecx, edx |
регистр |
память |
add ecx, dword ptr [104h]/add ecx, [edx] |
регистр |
значение |
add eax, 102 |
память |
значение |
add dword ptr [401231h], 80 |
память |
регистр |
add dword ptr [401231h], edx |
Сложим, например, два 64-битных целых числа: одно число находится в регистрах EDX:EAX, а другое в регистрах ЕВХ:ЕСХ:
add eax,ecx
adc edx,ebx
Если при сложении младших двойных слов произошел перенос из старшего разряда (флаг CF=1), то он будет учтен следующей командой ADC.
Вычислим сумму 254+17 в регистр ах. При этом известно, что результат сложения выходит за границы операнда.
– XADD <операнд_1><операнд_2>; выполняет команду «обменять между собой и сложить».
Выполняет сложение, помещает содержимое операнд_1 в операнд_2, — сумму операндов — в операнд_1. Операнд_2 всегда регистр, операнд_1 может быть регистром и переменной.
Сложение двоичных чисел со знаком
Флаг переноса cf, установка которого в 1 говорит о том, что произошёл выход за пределы разрядности операндов. Регистрация состояния старшего (знакового) разряда операнда осуществляется с помощью флага переполнения of в регистре eflags (бит 11).
Пример1.
30566=0111011101100110
+
00687=0000001010101111
=
31253=0111101000010101 – результат правильный.
Пример2.
30566=0111011101100110
+
30566=0111011101100110
=
61132=1110111011001100 – результат неправильный, значение получилось отрицательное (в старшем бите 1).
Пример3.
-30566=1000100010011010
+
-04875=1110110011110101
=
-35441=0111010110001111 – результат неправильный, так как получилось положительное число (в старшем бите 0)
Пример4.
-4875=1110110011110101
+
-4875=1110110011110101
=
-9750=1101100111101010 – результат правильный.
Таким образом, ситуация переполнения (установка флага of в 1) происходит при переносе:
-
из 14-го разряда (для положительных чисел);
-
из 15-го разряда (для отрицательных чисел).
Переполнения не происходит (флаг of сбрасывается в 0), если есть перенос из обоих разрядов или перенос отсутствует в обоих разрядах.
Правильный процесс сложения чисел со знаком и без знака необходимо проводить, анализируя флаги cf и of. Состояние флагов после выполнения команд ADD, ADC, INC сведено в табл. 1.
Таблица 1.
Пример: найдём сумму чисел -6+7. Для чисел отведено 2 байта. Для этого -6 представим в дополнительном коде: 0000000000000110 инвертируем, получим:
1111111111111001
+
0000000000000001
=
11111111111110102 =6553010 =fffa16
Тогда:
mov ax,FFFAh
mov dx, 7h
add ax,dx
fffa+7=1 0001 – результат не помещается в регистр АХ, будет установлен флаг переноса cf в 1. Если значение cf проигнорировать, то оставшееся в АХ значение будет правильным.
Пример: вычтем 25-300
0000000000011001
-
0000000100101100
=
11111110111011012 =6526110 = -27510
Если произошёл заём 1 из старшего разряда, то состояние флага cf установлено в 1 – значит результат получился в дополнительном коде.
1111111011101101 инвертируем 0000000100010010
+ 0000000000000001
= 00000001000100112 = 27510
При выполнении команды сложения устанавливаются следующие флаги:
1) CF=1 , если результат не помещается в приемнике, т.е. произойдет перенос.
2) PF=1; если результат имеет четное число битов с 1.
3) AF=1, если результат сложения десятичных чисел требует коррекции.
4) ZF=1, если результат =0.
5) SF= 1, если результат отрицателен.
6) OF=1, если при сложении 2-х чисел одного знака результат превышает диапазон допустимых значений в обратном коде, а сам приемник меняет знак. SF и OF имеют смысл при сложении чисел со знаком, AF – для десятичных чисел.
Вычитание двоичных чисел без знака
Команды вычитания выполняют вычитание, по рассмотренным алгоритмам, а учёт особых ситуаций должен производиться самим разработчиком программного продукта.
К командам вычитания относят:
– DEC <операнд> – операция декремента. Флаг CF не затрагивается, а остальные арифметические флаги (OF, SF, ZF, AF, PF) устанавливаются в соответствии с результатом вычитания.
– SUB <операнд_1>,<операнд_2> – команда вычитания;
Принцип действия:
операнд_1=операнд_1-операнд_2.
Нельзя использовать переменную одновременно и для операнд_2, и для операнд_1. Команда SUB не делает различий между числами со знаком и без знака.
– SBB <операнд_1>,<операнд_2> – команда вычитания с учётом заёма (флага cf).
Принцип действия:
операнд_1=операнд_1-операнд_2-значение_cf.
Пример: вычтем из одного 64-битного числа, хранящегося в EDX:EAX другое, хранящееся в ЕВХ:ЕСХ.
sub eax,ecx
sbb edx,ebx
Если при вычитании младших двойных слов произошел заем, то он будет учтен при вычитании старших.
Пример: в регистр al поместить результат вычитания 5-10.
0000 0101
-
0000 1010
-----------------
1111 1011=FFFBh
0-1111 1011=0000 0101(neg)
Факт того, что в al записано отрицательное число, отражён в состоянии флага cf.
Вычитание двоичных чисел со знаком
Вычитание в микропроцессоре производится путём сложения. Результат вычитания нужно рассматривать как значение в дополнительном коде. Например:
-45-45=-90
-45=11010011
+
-45=11010011
=
-90=10100110 число в дополнительном коде.
01011001
+00000001
=010110102 =9010
Умножение двоичных чисел без знака
Для умножения чисел без знака предназначена команда:
MUL <источник>;
Выполняет умножение содержимого источника (регистр или переменная) и регистра AL, АХ, ЕАХ (в зависимости от размера источника) и помещает результат в АХ, DX:AX, EDX:EAX соответственно. Произведение имеет двойной размер.
Размер Источник Результат
Если АН, DX, EDX содержит только нули, то флаги CF=0 и OF=0, иначе — в 1.
Например, умножим содержимое регистра al (25) на 45.
Умножение двоичных чисел со знаком
– IMUL <операнд_1>[, операнд_2, операнд_3]; умножение чисел со знаком.
Эта команда имеет три формы, различающиеся числом операндов:
1) IMUL <операнд_1>: операнд_1 (регистр или переменная) умножается на AL, АХ или ЕАХ (в зависимости от размера операнда), и результат располагается в АХ, DX:AX или EDX:EAX соответственно.
2) IMUL <операнд_1>,<операнд_2>: операнд_2 (число, регистр или переменная) умножается на операнд_1 (регистр), и результат заносится в операнд_1.
3) IMUL <операнд_1>,<операнд_2>,<операнд_3>: операнд_2 (регистр или переменная) умножается на операнд_3 (число), и результат заносится в операнд_1 (регистр).
Произведение имеет двойной размер
В первом случае приемник (регистры АХ, DX:AX или EDX:EAX) всегда больше операнд_1.
Если результат мал и умещается в одном регистре (то есть если cf=of=0), то содержимое другого регистра (старшей части) является расширением знака – все его биты равны старшему биту (знаковому разряду) младшей части результата.
В противном случае (если cf=of=1) знаком результата является знаковый бит старшей части результата, а знаковый бит младшей части является значащим битом двоичного кода результата.
Пример: mul bl ;al*bl, результат в Ах.
Пример: mul bx ;ax*bx, результат Dx:Ax.
Деление двоичных чисел без знака.
Для деления чисел без знака предназначена команда:
– DIV <делитель> ;
Команда выполняет целочисленное деление без знака АХ, DX:AX или EDX:ЕАХ (в зависимости от размера делителя) на делитель (регистр или переменная) и помещает результат в AL, АХ или ЕАХ, а остаток — в АН, DX или EDX соответственно.
Расположение операндов и результата при делении
размер делителя |
деление |
частное в... |
остаток в... |
BYTE (8-bits) |
ax / делитель |
AL |
AH |
WORD (16-bits) |
dx:ax* / делитель |
AX |
DX |
DWORD (32-bits) |
edx:eax* / делитель |
EAX |
EDX |
Пример: div bl ;ax/bl, результат в Al,Ah.
Пример: div bx; Dx:Ax/Bx, результат Ax,Dx.
Источник может быть:
-
8-бит регистр (al, ah, cl,...)
-
16-бит регистр (ax, dx, ...)
-
32-бит регистр (eax, edx, ecx...)
-
8-бит значение из памяти (byte ptr [xxxx])
-
16-бит значение из памяти (word ptr [xxxx])
-
32-бит значение памяти (dword ptr [xxxx])
Прерывание 0 – «деление на 0» – при выполнении команды div может возникнуть по одной из следующих причин:
-
делитель равен 0;
-
частное не входит в отведённую под него разрядную сетку, что может случиться в следующих случаях:
– при делении слова на байт значение делимого в более чем 256 раз больше значения делителя;
– при делении двойного слова на слово делимое в более чем 65536 раз больше значения делителя;
– при делении учетверённое слова на двойное слово делимое в более чем 4 294 967 296 раз больше значения делителя.
Пример:
DIV BX ; Dx:Ax/Bx, результат Ax,Dx.
DIV MEM_BYTE ; AX/MEM_byte, результат Al,Ah
Пример1: необходимо выполнить деление 514/2, D=2d=2h, C=514d=202h.
.data
C dw 514
D db 2
.code
mov ax,C
НЕПРАВИЛЬНО!!!
mov bl,D
div bl ; Ax/Bl; 10 0000 0010/10; 2d*256d=512d<=514d
2*256=512<514
Пример2: необходимо выполнить деление 2 293 830/35, D=35d=23h, C=2293830d=0023 0046h.
.data
C dd 2 293 830 ; 00230046h
D
dw 35 ; 0023h
.code
mov eax, C ; ax=0046h
НЕПРАВИЛЬНО!!!
mov dx, word ptr [C+2] ; dx=0023h
НЕПРАВИЛЬНО!!!
mov bx,D
div bx ; Dx:Ax/Bx=00230046h/0023h; 35d*65536d=2 293 760d<2 293 830d
35*65536=2 293 760<2 293 830
Деление двоичных чисел со знаком
Для деления чисел со знаком предназначена команда:
– IDIV <делитель> ;
Команда выполняет целочисленное деление со знаком АХ, DX:AX или EDX:ЕАХ (в зависимости от размера делителя) на делитель (регистр или переменная) и помещает результат в AL, АХ или ЕАХ, а остаток — в АН, DX или EDX соответственно.
Для этой команды верно всё то же, что и для команды DIV.
Лекция №4. Арифметические операции над двоично-десятичными числами **********************
В приложениях, в которых числа должны быть большими и точными необходимо использовать BCD –числа. Отдельных команд сложения, вычитания, умножения и деления BCD-чисел нет. Складывать и вычитать можно BCD-числа как в упакованном формате, так и в неупакованном, а вот делить и умножать можно только неупакованные BCD-числа.
Неупакованные BCD-числа
Пример1: Результат сложения не больше 9. 6+3
6=0000 0110
+
3=0000 0011
=
9=0000 1001 – результат правильный.
Пример2: Результат сложения больше 9.
06=0000 0110
+
07=0000 0111
=
13=0000 1101 – результат неправильный. Правильный результат в неупакованном BCD-формате должен быть таким 0000 0001 0000 0011. В десятичном представлении это 13.
Специальных команд для работы с BCD-числами нет, но есть корректировочные команды. Для коррекции операции сложения двух однозначных неупакованных BCD-чисел в системе команд микропроцессора существует специальная команда:
ААА ; ASCII-коррекция после сложения для представления в символьном виде.
Команда работает с регистром AL и анализирует значение его младшей тетрады. Если это значение меньше 9, то флаг cf сбрасывается в 0, и осуществляется переход к следующей команде. Если это значение больше 9, то выполняются следующие действия:
-
к содержимому младшей тетрады al прибавляется 6, тем самым значение десятичного результата корректируется в правильную сторону;
-
флаг cf устанавливается в 1, тем самым фиксируется перенос в старший разряд для того, чтобы его можно было учесть в последующих действиях.
Например при суммировании 06+07 в al находится 0000 1101. После команды ааа в регистре будет 1101+0110=0011, то есть двоичное 0000 00112 =310, а флаг cf установится в 1, то есть запомнится перенос в старший разряд. Далее необходимо использовать команду сложения adc, которая учтёт перенос из предыдущего разряда.
Пример: сложим два неупакованных BCD-числа 71+54
Строки 14 и 15 складывают цифры в очередных разрядах BCD-чисел, при этом учитывается возможный перенос из младшего разряда. Команда ааа корректирует результат сложения, формируя в аl BCD-число и, при необходимости, устанавливая в 1 флаг cf. Строка 20 учитывает возможность переноса при сложении цифр из самых старших разрядов чисел. Результат сложения формируется в поле sum.
Вычитание неупакованных BCD-чисел
Пример1.
6=000 0110
-
3=0000 0011
=
3=0000 0011 – результат верный
Пример2.
6=0000 0110
-
7=0000 0111
=
-1=1111 1111 – результат не правльный. Правильный результат должен быть 0000 10012 =910 . При этом предполагается заём из старшего разряда, то есть в случае с BCD-числами должно быть выполнено вычитание 16-7. Таким образом, видно, что результат вычитания нужно корректировать. Для этого существует специальная команда:
AAS – коррекция результата вычитания для представления в символьном виде.
Команда работает с регистром al, анализируя его младшую тетраду: если её значение меньше 9, то флаг cf сбрасывается в 0, и управление передаётся следующей команде. Если значение тетрады в al больше 9, то команда aas выполняет следующие действия:
-
из содержимого младшей тетрады регистра al вычитается 6;
-
обнуляет старшую тетраду регистра al;
-
устанавливает флаг cf в 1, фиксируя воображаемый заём из старшего разряда.
Команда aas применяется вместе с основными командами вычитания sub и sbb.
Например: 1-4
.data
a db 01h
b db 04h
.code
xor ax,ax ; очистка ах
xor bx,bx ; очистка bx
mov al,a ; в al занесли 1
sbb al,b ; al=1-4 ; 0000 0001-0000 0100=1111 1101
aas ; 1101-0110=0111, al=0000 0111
Умножение
Для того, чтобы перемножить два одноразрядных BCD –числа необходимо:
-
поместить один из сомножителей в регистр al (этого требует команда mul);
-
поместить второй операнд в регистр или память, отведя байт;
-
перемножить сомножители командой mul (результат будет в ах);
-
результат получится в двоичном коде и его нужно корректировать.
Для коррекции результата после умножения применяется команда:
AAM – коррекция результата умножения для представления в символьном виде.
Команда не имеет операндов и работает с регистром ах следующим образом:
-
делит al на 10;
-
результат деления записывается так: частное – в al, остаток в ah.
В результате после выполнения команды aam в регистрах al и ah находятся правильные двоично-десятичные цифры произведения двух цифр.
Деление
Предварительно в регистре ах необходимо получить две неупакованные BCD –цифры делимого. Далее используется команда:
AAD – коррекция деления для представления в символьном виде.
Команда преобразует двузначное неупакованное BCD-число в регистре ах в двоичное число. Это двоичное число далее будет использоваться в качестве делимого в операции деления. Кроме преобразования команда aad помещает полученное двоичное число в регистр al. Делимое будет двоичным числом из диапазона 0…99. Алгоритм, по которому команда aad осуществляет его преобразование, состоит в следующем:
-
умножается старшая цифра исходного BCD –числа в ах (содержимое ah) на 10;
-
выполняется сложение ah+ al, результат которого (двоичное число) заносится в al;
-
обнуляется содержимое ah.
Далее необходимо использовать команду деления div для выполнения деления содержимого ах на одну BCD-цифру, находящуюся в байтовом регистре или байтовой ячейки памяти.
Команду aad можно также использовать для перевода неупакованных BCD-чисел из диапазона 0…99 в их двоичный эквивалент.
Например, разделим десятичное 25 на 5:
mov ax,0205h ; 25 в неупакованном формате
mov bl,5
aad ; теперь в АХ находится 19h
div bl ; АХ = 0005
Флаги SF, ZF и PF устанавливаются в соответствии с результатом, OF, AF и CF не определены.
Ah=0000 0010; al=0000 0101
1) 0000 0010 *0000 1010=0001 0100=ah
2) 0001 1010+0000 0101=0001 1001=al
3) ah=0000 0000 ; ax=0000 0000 0001 10012=2510
Упакованные BCD-числа
Сложение
Пример1:
67=0110 0111
+
75=0111 0101
=
142=1101 1100=22010 – это неверный результат. Правильный результат 0001 0100 0010 (14210)
Для корректировки результата микропроцессор предоставляет команду:
DAA – коррекция результата сложения для представления в десятичном виде.
Команда daa преобразует содержимое регистра al в две упакованные десятичные цифры по следующему алгоритму:
1) если младшие четыре бита AL больше либо равно 9 или флаг AF = 1, то AL увеличивается на 6, CF устанавливается, если при этом сложении произошел перенос, и AF устанавливается в 1.
2) иначе AF = 0.
3) если теперь старшие четыре бита AL больше 9 или флаг CF = 1, то AL увеличивается на 60h и CF устанавливается в 1.
4) иначе CF = 0.
Флаги AF и CF устанавливаются, если в ходе коррекции происходил перенос из первой или второй цифры соответственно, SF, ZF и PF устанавливаются в соответствии с результатом, флаг OF не определен.
Например, если AL содержит число 19h, последовательность команд:
inc al
daa
приведет к тому, что в AL окажется 20h (а не 1Ah, как было бы после INC).
1) 19h+1=1A
2) 1A16 =1 10102 +01102 =10 00002 =2016
Вычитание
Пример1: 67-75
67=0110 0111
+
-75=1011 0101 (75=1001011, 0110100+1=10110101=-75)
=
-8=0001 1100=28 – результат неверный. Верный результат 0000 1000=810. Контроль за знаком осуществляется с помощью флага cf, который фиксирует заём из старших разрядов.
Вычитание BCD-чисел осуществляется командами sub ил sbb. Коррекция результата осуществляется командой:
DAS – коррекция результата вычитания для представления в десятичном виде.
Команда работает по следующему алгоритму:
1) если младшие четыре бита AL больше 9 или флаг AF = 1, то AL уменьшается на 6, CF устанавливается, если при этом вычитании произошел заем, и AF устанавливается в 1.
2) иначе AF = 0.
3) если теперь старшие четыре бита AL больше 9 или флаг CF = 1, то AL уменьшается на 60h и CF устанавливается в 1.
4) иначе CF = 0.
Например, если AL содержит число 20h, последовательность команд
dec al
das
приведет к тому, что в AL окажется 19h (а не 1Fh, как было бы после DEC).