Программирование на языке ассемблера 8086

Emu8086

Если вы скачали и установили эмулятор процессора 8086 (см. раздел ВВЕДЕНИЕ), то вы можете использовать его для создания ваших первых программ на языке ассемблера. На текущий момент (ноябрь 2011 г) доступна версия программы 4.08. Справку на русском языке вы можете найти здесь: Справка Emu8086.

Программа Emu8086 платная. Однако в течение 30 дней вы можете использовать её для ознакомления бесплатно.

Итак, вы скачали и установили программу Emu8086 на свой компьютер. Запускаем её и создаём новый файл через меню FILE – NEW – COM TEMPLATE (Файл – Новый – Шаблон файла COM). В редакторе исходного кода после этого мы увидим следующее:

Программирование на языке ассемблера 8086. Смотреть фото Программирование на языке ассемблера 8086. Смотреть картинку Программирование на языке ассемблера 8086. Картинка про Программирование на языке ассемблера 8086. Фото Программирование на языке ассемблера 8086

Рис. 1.1. Создание нового файла в Emu8086.

Здесь надо отметить, что программы, создаваемые с помощью Ассемблеров для компьютеров под управлением Windows, бывают двух типов: COM и EXE. Отличия между этими файлами мы рассмотрим позже, а пока вам достаточно знать, что на первое время мы будем создавать исполняемые файлы с расширением COM, так как они более простые.

Также отметим, что регистр символов в языке ассемблера роли не играет. Вы можете написать RET, ret или Ret – это будет одна и та же команда.

Вы можете сохранить этот файл куда-нибудь на диск. Но можете и не сохранять. Чтобы выполнить программу, нажмите кнопку EMULATE (с зелёным треугольником) или клавишу F5. Откроется два окна: окно эмулятора и окно исходного кода (рис. 1.2).

Программирование на языке ассемблера 8086. Смотреть фото Программирование на языке ассемблера 8086. Смотреть картинку Программирование на языке ассемблера 8086. Картинка про Программирование на языке ассемблера 8086. Фото Программирование на языке ассемблера 8086

Рис. 1.2. Окно эмулятора Emu8086.

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

В окне эмулятора вы можете запустить вашу программу на выполнение целиком (кнопка RUN) либо в пошаговом режиме (кнопка SINGLE STEP). Пошаговый режим удобен для отладки. Ну а мы сейчас запустим программу на выполнение кнопкой RUN. После этого (если вы не сделали ошибок в тексте программы) вы увидите сообщение о завершении программы (рис. 1.3). Здесь вам сообщают о том, что программа передала управление операционной системе, то есть программа была успешно завершена. Нажмите кнопку ОК в этом окне и вы увидите, наконец, результат работы вашей первой программы на языке ассемблера (рис. 1.4).

Программирование на языке ассемблера 8086. Смотреть фото Программирование на языке ассемблера 8086. Смотреть картинку Программирование на языке ассемблера 8086. Картинка про Программирование на языке ассемблера 8086. Фото Программирование на языке ассемблера 8086

Рис. 1.3. Сообщение о завершении программы.

Программирование на языке ассемблера 8086. Смотреть фото Программирование на языке ассемблера 8086. Смотреть картинку Программирование на языке ассемблера 8086. Картинка про Программирование на языке ассемблера 8086. Фото Программирование на языке ассемблера 8086

Рис. 1.4. Ваша первая программа выполнена.

Как мы уже говорили, наша первая программа выводит на экран английскую букву «А». Результат оправдал наши ожидания – буква «А» выведена на экран.

Здесь стоит отметить, что Emu8086 – это ЭМУЛЯТОР, то есть он эмулирует работу компьютера с процессором 8086. Поэтому в описанном выше примере программа выполняется не операционной системой, а эмулятором. Emu8086 может создавать и реальные программы, которые могут самостоятельно выполняться на компьютере. Но описание работы с Emu8086 не входит в наши планы. Читайте справку и экспериментируйте – всё у вас получится.

В нашем случае пока не важно, как выполняется программа – эмулятором или операционной системой. Главное – разобраться с вопросом создания программ на языке ассемблера. Поэтому разберём нашу простенькую программку подробно.

ORG 100h – 2-ая строка. Эта команда устанавливает значение программного счетчика в 100h, потому что при загрузке СОМ-файла в память, DOS выделяет под блок данных PSP первые 256 байт (десятичное число 256 равно шестнадцатеричному 100). Код программы располагается только после этого блока. Все программы, которые компилируются в файлы типа СОМ, должны начинаться с этой директивы.

MOV AH, 02h – 3-я строка. Инструкция (или команда) MOV помещает значение второго операнда в первый операнд. То есть значение 02h помещается в регистр АН. Для чего это делается? 02h – это ДОСовская функция, которая выводит символ на экран. Мы пишем программу для DOS, поэтому используем команды этой операционной системы (ОС). А записываем мы эту функцию (а точнее ее номер) именно в регистр АН, потому что прерывание 21h использует именно этот регистр.

MOV DL, 41h – 4-я строка. Код символа «A» заносится в регистр DL. Код символа «A» по стандарту ASCII – это 41h.

INT 21h – 5-я строка. Это и есть то самое прерывание 21h – команда, которая вызывает системную функцию DOS, заданную в регистре АН (в нашем примере это функция 02h). Команда INT 21h – основное средство взаимодействия программ с ОС.

INT 20h – 6-я строка. Это прерывание, которое сообщает операционной системе о выходе из программы и о передаче управления консольному приложению. Значит, при использовании INT 20h в нашем примере, управление будет передаваться программе Emu8086. А в том случае, если программа уже откомпилирована и запущена из ОС, то команда INT 20h вернет нас в ОС (например, в DOS). В принципе, в случае с Emu8086 эту команду можно было бы пропустить, так как эту же функцию выполняет команда RET, которая вставляется в исходный текст автоматически при создании нового файла по шаблону (как это сделали мы ранее). Но я решил использовать INT 20h и здесь для совместимости с другими ассемблерами.

Тем, кому не все понятно из этих объяснений, рекомендую почитать книгу Как стать программистом, а также следующие главы.

Источник

1. Первая программа на ассемблер (i8086)

Статья основана на материале xrnd с сайта asmworld (из учебного курса по программированию на ассемблер 16-битного процессора 8086 под DOS).

В качестве инструментов для разработки я рекомендую этот, но примеры статьи написаны в FASM, а для отладки исопльзовался Turbo Debugger из пакета TASM.

Для того, чтобы написать программу, нам надо запустить fasmw.exe. Откроется окошко, в которое можно смело набивать код:

Программирование на языке ассемблера 8086. Смотреть фото Программирование на языке ассемблера 8086. Смотреть картинку Программирование на языке ассемблера 8086. Картинка про Программирование на языке ассемблера 8086. Фото Программирование на языке ассемблера 8086

В это окошко надо ввести следующее (я подробно объясню ниже, что значит каждая строчка):

Первая строка « use16 » сообщает FASM’у, что нужно генерировать 16-битный код. Нам нужен именно такой для нашей первой программы. Точка с запятой — это символ комментария. Все что идет после «;» до конца строки игнорируется компилятором. Там можно писать все что угодно.

Вторая строка org 100h объясняет FASM’у, что следующие команды и данные будут располагаться в памяти, начиная с адреса 100h. Дело в том, что при загрузке нашей программы в память, DOS размещает в первых 256 байтах (с адресов 0000h — 00FFh ) свои служебные данные. Нам эти данные изменять нежелательно.

Далее идут непосредственно команды! Программа на ассемблере состоит из команд процессора. Каждая команда обозначается мнемоникой (символическим именем). Например «mov», «inc», «nop» и т.д. После мнемоники могут идти операнды. Они отделяются одним или несколькими пробелами (или табуляцией).

Команды бывают без операндов, с одним или несколькими операндами. Если операндов больше одного, то они отделяются друг от друга запятыми.

Отступы не обязательны, но желательны — с ними код гораздо легче читать. Пустые строки игнорируются. Регистр символов значения не имеет. Можно писать большими буквами, или маленькими, или в перемешку.

Четвертая строка определяет команду «поместить число 255 в регистр AX ». «mov» — это мнемоника команды (от английского «MOVe»). AX — первый операнд — приёмник. 255 — второй операнд — источник. Первый операнд является регистром. Второй операнд — константа 255.

Пятая строка. Тут команда « inc » с одним операндом. Она заставит процессор выполнить инкремент, то есть увеличение на единицу. Единственный операнд — это регистр AX, содержимое которого и будет увеличено на 1.

Две последние строки — это стандартное завершение процесса в DOS. Так мы будем завершать все наши программы. Команда «mov» должна быть вам понятна, а про команду «int» я ещё расскажу, это отдельная тема.

Программирование на языке ассемблера 8086. Смотреть фото Программирование на языке ассемблера 8086. Смотреть картинку Программирование на языке ассемблера 8086. Картинка про Программирование на языке ассемблера 8086. Фото Программирование на языке ассемблера 8086

В общем, наша программа ничего не делает, а в следующий раз мы научимся работать с отладчиком. Загляните сюда если работаете в Tubro Debugger, или туда — если выбрали SimpleASM.

Источник

21. Ввод чисел с консоли в ассемблере i8086

Статья основана на материале xrnd с сайта asmworld (из учебного курса по программированию на ассемблер 16-битного процессора 8086 под DOS).

В прошлой части мы научились преобразовывать числа в строку и выводить на консоль. А в этой займёмся обратной задачей — вводом чисел с консоли и преобразованием строки в число. Поскольку ввод в двоичном и восьмеричном виде используется редко, я рассмотрю только примеры ввода чисел в десятичном виде (со знаком и без знака) и в шестнадцатеричном.

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

Ввод строки с консоли

Для ввода строки можно использовать функцию MS-DOS 0Ah. Функция позволяет ввести строку длиной от 1 до 254 символов. При вызове в DX передаётся адрес буфера, первый байт которого должен содержать максимально допустимую длину строки. Длина считается вместе с символом конца строки CR (0dh). В результате работы функции во второй байт буфера записывается фактическая длина введённой строки (не считая символа CR). Начиная с третьего байта в буфер записываются символы строки. Подробнее о работе функции можно узнать в раритетном справочнике по DOS.

Программирование на языке ассемблера 8086. Смотреть фото Программирование на языке ассемблера 8086. Смотреть картинку Программирование на языке ассемблера 8086. Картинка про Программирование на языке ассемблера 8086. Фото Программирование на языке ассемблера 8086

Чтобы удобнее было использовать эту функцию, можно написать небольшую процедуру. Например, такую:

Процедура использует отдельно объявленный буфер. В качестве единственного параметра ей передаётся максимальная длина строки в регистре AL. После возврата из процедуры в этот регистр записывается фактическая длина строки, а в регистр DX — адрес начала строки. Старшая часть AX сохраняется.

Ввод десятичных чисел без знака

Для преобразования числа в строку используется так называемая схема Горнера. Любое число в десятичной системе можно представить в следующем виде:

34710 = 3·102 + 4·101 + 7·100 = (3·10 + 4)·10 + 7

Это очень удобно запрограммировать в цикле: результат сначала умножается на 10, а потом к нему прибавляется очередная цифра и так далее для всех цифр. Кстати, это верно не только для десятичной системы счисления, но и для других, разница только в множителе, который должен быть равен основанию системы счисления.

Следующая процедура преобразует строку в слово в регистре AX. Адрес строки передаётся в DX, длина строки передаётся в AL. Если строка не корректна, процедура возвращает 0 и устанавливает флаг CF. Ошибка возвращается в следующих случаях:

Для установки флага CF используется команда STC. Сбросить флаг CF можно командой CLC. В коде данной процедуры она не используется, так как в случае успешного завершения цикла флаг CF всегда будет равен 0.

На основе этой процедуры несложно написать ещё одну для ввода чисел размером 1 байт. Сначала строка преобразуется в слово без знака, а затем выполняется проверка старшей части на равенство нулю. Обратите внимание, что команда TEST всегда сбрасывает флаг CF.

Следующие две процедуры совмещают ввод строки с преобразованием строки в число. Для слова нужно ввести максимум 5 символов, а для байта — максимум 3.

Ввод десятичных чисел со знаком

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

Наконец, ещё две процедуры совмещают ввод строки с преобразованием её в слово и байт со знаком.

В случае некорректной строки программа выводит сообщение об ошибке и повторяет запрос ввода числа:

Программирование на языке ассемблера 8086. Смотреть фото Программирование на языке ассемблера 8086. Смотреть картинку Программирование на языке ассемблера 8086. Картинка про Программирование на языке ассемблера 8086. Фото Программирование на языке ассемблера 8086

Ввод шестнадцатеричных чисел

Преобразование шестнадцатеричной строки в число несколько проще. Удобно реализовать в виде отдельной процедуры преобразование одной цифры. Процедура воспринимает символы ‘A’-‘F’ независимо от регистра. Так как перед вычитанием выполняются проверки, флаг CF всегда будет равен нулю после успешного преобразования.

Теперь легко можно написать преобразование шестнадцатеричной строки в слово. Вместо умножения на 16 в процедуре используется сдвиг на 4 бита влево, а вместо сложения — операция ИЛИ. Проверки диапазона значения не нужны, достаточно проверить длину строки и преобразовать цифры.

Для ввода байта используется та же процедура, но дополнительно проверяется длина строки — она должна быть не больше 2.

Ещё две процедуры для ввода и преобразования строки, также как для десятичного ввода:

Как и в примере с десятичными числами, программа повторяет запрос ввода, пока не будут введены корректные данные:
Программирование на языке ассемблера 8086. Смотреть фото Программирование на языке ассемблера 8086. Смотреть картинку Программирование на языке ассемблера 8086. Картинка про Программирование на языке ассемблера 8086. Фото Программирование на языке ассемблера 8086

Упражнение

Напишите программу для ввода байта с консоли в двоичном виде. Желательно с проверкой корректности ввода. Результаты можете писать в комментариях.

Источник

Программирование на языке ассемблера 8086

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

Если же Вы хотите приобрести бумажную копию представленных здесь
материалов, обращайтесь в наш книжный магазин.

С уважением,
команда разработчиков eManual.ru

ЯЗЫК АССЕМБЛЕРА МИКРОПРОЦЕССОРА 8086

ЯЗЫК АССЕМБЛЕРА МИКРОПРОЦЕССОРА 8086

Язык ассемблера представляет собой машинный язык в символи­ческой форме, которая более понятна и удобна человеку.

Язык ассемблера микропроцессора Intel 8086 является довольно сложным, что в первую очередь объясняется сегментной организацией памяти и одновременной адресацией четырех сегментов. В языке имеется более 100 базовых символических команд, в соответствии с которыми ассемблер генерирует более 3800 машинных команд. Кроме того, в распоряжении программиста имеется более 20 директив, предназначенных для распределения памяти, инициализации перемен­ных, условного ассемблирования и т.д.

Исходная программа на языке ассемблера представляет собой последовательность операторов. Операторы обычно занимают одну строку. Ассемблер воспринимает операторы в свободном формате, т.е. элементам операторов не назначены фиксированные столбцы и между ними может быть любое число пробелов там, где это необходи­мо.

Операторы в исходной программе классифицируются как команд­ные операторы, операторы распределения данных и директивы ассемб­лера.

Командные операторы определяют генерируемые ассемблером ма­шинные команды; они содержат мнемонику и, при необходимости, один или два операнда. Каждый командный оператор порождает одну машин­ную команду, формат которой зависит от способа задания операндов.

Операторы распределения данных резервируют ячейки памяти для данных программы.

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

Формат командных операторов

Командные операторы записываются в следующем формате:

Метка: Префикс Мнемоника Операнд1,Операнд2 ;Комментарий

где фигурные скобки обозначают необязательные поля.

Рассмотрим назначение отдельных полей данного формата:

1) Метка представляет собой определяемое пользователем имя, заканчивающееся двоеточием. Значением метки является текущее значение счетчика ячеек (адресов) в текущем сегменте кода, т.е. адрес отмеченной команды. Метки как операнды используются только в командах передачи управления, и при этом двоеточие в конце ссылки на метку не ставится.

3) Мнемоника кода операции представляет собой заранее опреде­ленное и неизменяемое имя, которое идентифицирует тип генерируе­мой машинной команды.

4) Операнды задают адреса данных или сами данные, необходимые в данной команде.

5) Комментарий предназначен только для документирования прог­раммы. Он всегда начинается с точки с запятой.

Формат директив ассемблера

и операторов распределения данных

Директивы ассемблера и операторы распределения данных имеют несколько иной формат:

Имя Директива Операнды ;Комментарий

Рассмотрим назначение отдельных полей данного формата:

1) Имя директивы, в отличие от метки, никогда не заканчивается двоеточием. Некоторые директивы требуют обязательного наличия метки.

2) Директива является одним из ключевых неизменяемых слов ассемблера и определяет его действия в процессе ассемблирования. Директивы используются программистом для распределения памяти, обеспечения связи между программными модулями и работы с символи­ческими именами.

3) Операнды конкретизируют действия, выполняемые по данной директиве.

4) Поле комментария аналогично такому же полю в командных опе­раторах.

Дадим определения основных терминов, которые будут использо­ваны в дальнейшем.

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

Ассемблер процессора 8086 является жестко типизированным языком. Это означает, что операнды команд (регистры, переменные,

метки, константы) имеют связанный с ними атрибут типа, который

сообщает ассемблеру некоторую информацию об операнде. Атрибут

типа обычно подразумевается по умолчанию, но при необходимости

может быть задан явно.

8-разрядным регистрам AL, AH, BL, BH, CL, CH, DL, DH при­писан тип BYTE, а 16-разрядным регистрам AX, BX, CX, DX, BP, SP, SI, DI и сегментным регистрам CS, DS, SS, ES приписан тип WORD.

Разряды регистра флажков представляют собой однобитные ре­гисты, для установки и сброса каждого из которых используются отдельные машинные команды.

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

Операторы распределения данных имеют следующий формат:

Таким образом, каждая директива может инициировать одну или несколько переменных соответствующего типа.

Для задания начальных значений могут использоваться числовые константы и символьные цепочки. Если не нужно задавать начальное значение переменной, то вместо константы ставится вопросительный знак.

Например, оператор alpha DW 0Ah

резервирует слово памяти, присваивает ему идентификатор alpha и

заносит в него код 000A;

резервирует 6 байт памяти и заносит в них строку символов и

присваивает этой строке идентификатор string.

Чтобы точно определить тип переменной, на которую произво­дится ссылка, ассемблер использует операторы BYTE PTR, WORD PTR и DWORD PTR (указатель на байт, слово и двойное слово соответствен­но).

Для инициализации массивов применяется конструкция DUP, которая в общем случае имеет вид:

где параметр n задает число повторений элементов, находящихся в

Например, оператор Addr DD 20 DUP (?)

резервирует место для 20 полных адресов и присваивает этому

массиву идентификатор Addr.

Метка представляет собой символическое имя для адреса ячейки памяти и предназначена для использования в качестве операнда в командах управления.

СЕГМЕНТЫ И ПРОЦЕДУРЫ

Программы, написанные на языке ассемблера процессора 8086, могут быть разделены на один или несколько сегментов. Каждый логический сегмент имеет уникальное имя и однозначно отображается в сегментах памяти при загрузке программы для ее выполнения. Для определения начальной и конечной ячеек логического сегмента в макроассемблере предусмотрены директивы SEGMENT (начало сегмента) и ENDS (конец сегмента).

Обычно часть программы, содержащая коды машинных команд,

объединяется в кодовый сегмент. Переменные, константы, таблицы и

другие данные объединяются в сегмент данных. Для хранения проме­жуточных данных и при вызове подпрограмм используется сегмент стека. Иногда для хранения данных может использоваться четвертый, дополнительный сегмент.

Директива ASSUME указывает ассемблеру, к какому сегментному регистру относится тот или иной логический сегмент. Если вся программа размещается в одном сегменте памяти, то эта директива указывает, что все сегментные регистры адресуют один и тот же сегмент.

В зависимости от используемой модели памяти в программе могут использоваться один или несколько сегментов кода и один или несколько сегментов данных. Стековый сегмент как правило один.

СТЕМА КОМАНД МИКРОПРОЦЕССОРА 8086

Систему команд процессора 8086 образуют 113 базовых команд, многие из которых допускают использование разнообразных режимов адресации.

По функциональному назначению выделяют спедующие группы ко­манд:

— команды передачи данных;

— команды арифметических операций;

— команды логических операций и сдвигов;

— команды передачи управления;

— команды управления микропроцессором.

КОМАНДЫ ПЕРЕДАЧИ ДАННЫХ

Команды передачи данных разделяют на 4 подгруппы:

— общие команды передачи данных;

— команды передачи цепочек байт или слов.

Команды передачи данных не модифицируют состояния флажков. Исключение составляют команды POPF и SAHF, прямо воздействующие на регистр флажков.

ОБЩИЕ КОМАНДЫ ПЕРЕДАЧИ ДАННЫХ

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

Эта команда имеет следующее обобщенное представление:

Допустимые форматы команды:

MOV mem/reg1, mem/reg2

Команда обмена XCHG

Команда обмена XCHG позволяет обменивать содержимое любого общего регистра и ячейки памяти, а также любой пары общих регист­ров.

Команды LEA, LDS и LES

Команды LEA, LDS и LES предназначены для загрузки эффектив­ного адреса.

Команда LEA извлекает из памяти 16-битовый адрес и помещает его в один из общих регистров. Практически эта команда дублирует один из вариантов команды MOV, но выполняется быстрее.

Обычно в команде LDS указывается регистр SI, а в команде LES регистр DI.

Команды LAHF и SAHF

До выполнения стековых команд регистры SP и SS должны быть инициализированы.

Команда PUSH включает в стек содержимое адресуемого регистра или ячейки памяти, а команда POP извлекает содержимое вершины стека и передает его в регистр или ячейку памяти.

Команды POSHF и POPF предназначены для временного запомина­ния в стеке и последующего восстановления из стека содержимого регистра флагов. С их помощью можно изменять состояние флага трассировки TF, так как команд прямого воздействия на этот флаг нет.

PUSH mem/reg POP mem/reg

PUSH sreg POP sreg

Команда ввода IN и команда вывода OUT допускают работу как с байтами, так и со словами. Команда IN загружает данные из задан­ного порта в аккумулятор, а команда OUT выполняет передачу из аккумулятора в порт. Для портов ввода-вывода в диапазоне 00-FF можно использовать прямую укороченную адресацию, а остальные порты в диапазоне 100-FFFF можно адресовать только косвенно через регистр DX.

IN ac,port OUT port,ac (прямая укороченная адресация)

IN ac,DX OUT DX,ac (косвенная адресация)

КОМАНДЫ АРИФМЕТИЧЕСКИХ ОПЕРАЦИЙ

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

Арифметические операции выполняются над целыми числами четы­рех типов: беззнаковыми двоичными, знаковыми двоичными, упакован­ными десятичными и неупакованными десятичными. Длина чисел может быть 8 или 16 бит.

Команды арифметических операций влияют на состояние флажков OF, SF, ZF, AF, PF и CF.

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

Команда ADD позволяет производить сложение 8- или 16-битовых двоичных чисел в режиме регистр-регистр, регистр-память и память­регистр, причем адресация памяти осуществляется в любом допусти­мом режиме. Общее представление команды имеет вид

т.е. первый операнд складывается со вторым и результат операции

замещает первый операнд.

Команда ADC выполняет сложение с переносом: в отличие от команды ADD в операции сложения участвует флажок CF, значение которого прибавляется к младшему биту результата сложения операн­дов.

Команда INC позволяет увеличить на 1 содержимое любого обще­го регистра или ячейки памяти.

Команда SUB позволяет производить вычитание 8- или 16-битных двоичных чисел. Общее представление команды имеет вид

т.е. второй операнд вычитается из первого и результат операции

замещает первый операнд.

Команда SBB выполняет вычитание с переносом: в отличие от команды SUB в операции вычитания участвует флажок CF, значение которого вычитается из младшего бита результата вычитания операн­дов.

Команда DEC позволяет уменьшить на 1 содержимое любого обще­го регистра или ячейки памяти.

Команда NEG изменяет знак числа, находящегося в регистре или ячейке памяти, на противоположный.

Команда сравнения CMP выполняет вычитание второго операнда из первого, но нигде не запоминает результат операции и влияет только на состояние флажков.

Микропроцессор 8086 имеет две команды умножения: для беззна­ковых и для знаковых двоичных чисел. Умножение десятичных чисел требует использования специальных команд коррекции, которые будут рассматриваться позднее.

Команда умножения беззнаковых целых чисел MUL выполняет умножение адресуемого операнда на содержимое аккумулятора. Общее представление команды имеет вид

При операции над байтами функции аккумулятора выполняет регистр AL, а 16-битный результат операции помещается в регистр AX. При операции над словами функции аккумулятора выполняет регистр AX, а произведение длиной 32 бита формируется в регистрах DX (старшее слово) и AX (младшее слово).

Команда IMUL аналогична команде MUL, но сомножители и произ­ведение интерпретируются как знаковые двоичные числа в дополни­тельном коде.

Микропроцессор 8086 имеет две команды деления: для беззнако­вых и для знаковых двоичных чисел. Деление десятичных чисел также требует использования специальных команд коррекции.

Команда деления беззнаковых чисел DIV производит деление содержимого аккумулятора и его расширения на содержимое адресуе­мого операнда.

При делении на 0 автоматически происходит прерывание и пере­ход к специальной программе обработки.

Команда IDIV аналогична команде DIV, но делимое, делитель и частное интерпретируются как знаковые двоичные числа в дополни­тельном коде.

Команда преобразования байта в слово CBW расширяет знак содержимого регистра AL в регистр AH. Команда преобразования сло­ва в двойное слово CWD передает знак содержимого регистра AX во все биты регистра DX.

Команды преобразования не влияют на состояния флагов.

КОМАНДЫ ДЕСЯТИЧНОЙ АРИФМЕТИКИ

Микропроцессор 8086 допускает два представления десятичных чисел: упакованный формат (BCD-формат) и неупакованный (ASCII- формат). В формате BCD байт содержит две десятичные цифры (по одной в каждой тетраде). В ASCII-формате байт содержит одну десятичную цифру в коде ASCII. В обоих форматах многоразрядные десятичные числа представляются последовательностями байт.

Команды десятичной арифметики оперируют только с байтами, причем основным рабочим регистром во всех десятичных операциях является регистр AL.

Операции с числами в форматах BCD и ASCII выполняются в два этапа: сначала над 8-битными операндами выполняются обычные операции двоичной арифметики, а затем осуществляется коррекция результата. Команды коррекции являются безадресными, так как работают с содержимым аккумулятора AL.

Команды для формата BCD

Команда десятичной коррекции для сложения DAA выполняет кор­рекцию суммы, полученной в результате выполнения команд ADD и ADC и должна следовать непосредственно за ними.

Команда десятичной коррекции для вычитания DAS выполняет коррекцию разности, полученной в результате выполнения команд SUB и SBB и должна следовать непосредственно за ними.

Команды для формата ASCII

Команда десятичной коррекции для сложения AAA выполняет кор­рекцию суммы, полученной в результате выполнения команд ADD и ADC и должна следовать непосредственно за ними.

Команда десятичной коррекции для вычитания AAS выполняет коррекцию разности, полученной в результате выполнения команд SUB и SBB и должна следовать непосредственно за ними.

Команда десятичной коррекции для деления AAD отличается тем, что должна выполняться перед командой деления DIV.

КОМАНДЫ ЛОГИЧЕСКИХ ОПЕРАЦИЙ И КОМАНДЫ СДВИГОВ

КОМАНДЫ ЛОГИЧЕСКИХ ОПЕРАЦИЙ

Логические операции представлены командами NOT (инверсия), AND (конъюнкция), OR (дизъюнкция), XOR (исключающее ИЛИ) и коман­дой TEST, которая выполняет конъюнкцию операндов, но не изменяет их значений. Все логические операции являются поразрядными, т.е. выполняются независимо для всех бит операндов.

Бинарные команды AND, OR, XOR и TEST воздействуют на флажки OF, SF, ZF, PF и CF. Унарная операция NOT не влияет на состояние флажков.

Команды сдвигов подразделяются на команды простых сдвигов и команды циклических сдвигов. Циклические сдвиги влияют только на флаги OF и CF, а обычные изменяют пять флажков: OF, SF, ZF, PF и

CF. Команды сдвигов могут работать как с байтами, так и со слова­ми.

Команды ROL и ROR реализуют простой циклический сдвиг влево и вправо соответственно, помещая значение из выдвигаемого бита в освобождающийся бит.

Команды RCL и RCR называются командами циклического сдвига влево и вправо через перенос, так как флажок CF расширяет сдвига­емый операнд на один бит. Таким образом, значение из CF загружа­ется в освобождающийся бит, а выдвигаемый бит помещается в CF.

Команды SHL и SHR реализуют логический сдвиг влево и вправо соответственно. Для логического сдвига характерно, что в освобож­дающийся бит загружается нуль, а выдвигаемый бит теряется.

Команды SAL и SAR предназначены для арифметического сдвига влево и вправо. Арифметический сдвиг вправо отличается от логи­ческого сдвига тем, что знаковый бит не сдвигается, а дублируется в соседнем правом бите, сохраняя тем самым знак числа. Арифмети­ческий сдвиг влево эквивалентен логическому, поэтому мнемоники SAL и SHL обозначают одну и ту же машинную команду. Команды арифметического сдвига по существу реализуют умножение и деление чисел без знака на степень числа 2.

Поле операнда команд сдвига имеет вид mem/reg,count. Опреанд count определяет число сдвигов и может быть указан как констан­та 1 или как регистр CL. В первом случае выполняется сдвиг на один бит, а во втором число сдвигов определяется содержимым регистра CL, которое воспринимается как беззнаковое число.

ROL mem/reg,1 ROL mem/reg,CL

ROR mem/reg,1 ROR mem/reg,CL

RCL mem/reg,1 RCL mem/reg,CL

RCR mem/reg,1 RCR mem/reg,CL

SHL mem/reg,1 SHL mem/reg,CL

SHR mem/reg,1 SHR mem/reg,CL

SAL mem/reg,1 SAL mem/reg,CL

SAR mem/reg,1 SAR mem/reg,CL

КОМАНДЫ ПЕРЕДАЧИ УПРАВЛЕНИЯ

Команды передачи управления процессора 8086 подразделяются на команды безусловных переходов, условных переходов, вызовов, возвратов, управления циклами и команды прерываний.

Команды передачи управления не изменяет состояние регистра флагов (за исключением команды IRET).

КОМАНДЫ БЕЗУСЛОВНЫХ ПЕРЕХОДОВ

Команда дальнего безусловного перехода реализует прямой и

косвенный межсегментнные переходы.

КОМАНДЫ УСЛОВНЫХ ПЕРЕХОДОВ

В системе команд процессора 8086 имеется 19 двухбайтных команд условных переходов. При выполнении этих команд анализиру­ется некоторое условие, закодированное текущими состояниями фла­гов, и если оно выполняется, то осуществляется переход, а если нет, то выполняется следующая по побядку команда.

Все условные переходы являются короткими. Некоторые команды для удобства программирования могут иметь несколько различных мнемонических обозначения.

Мнемонические обозначения команд:

Форматы команд такие же, как у короткого безусловного пере­хода.

КОМАНДЫ ВЫЗОВОВА ПОДПРОГРАММ

Команда вызова подпрограммы CALL передает управление с авто­матическим сохранением адреса возврата в стеке. В поле операнда этой команды находится метка первой команды вызываемой подпрог-

При переходе к подпрограмме необходимо временно запомнить адрес команды, находящейся после команды CALL. Этот адрес называ­ется адресом возврата. После того, как подпрограмма закончит свои действия, завершающая ее команда возврата RET передает управление по запомненному адресу возврата. Адрес возврата запоминается в стеке.

Команды внутрисегментного перехода производят декремент SP на 2, включают в стек содержимое IP, а затем прибавляют к IP 16-битное смещение, которое интерпретируется как знаковое целое.

КОМАНДЫ ВОЗВРАТА ИЗ ПОДПРОГРАММ

Каждая подпрограмма должна содержать минимум одну команду возврата RET, которая возвращает управление вызывающей программе. Такая передача управления осуществляется путем извлечения из стека адреса возврата, включенного в него командой вызова под­программы.

Команды внутрисегментного и межсегментного возврата имеют одну и ту же мнемонику RET. Тип команды, соответствующей этой мнемонике, определяется ассемблером автоматически.

Однобайтная команда RET с кодом операции C3 реализует внут­рисегментный возврат. Она передает слово из вершины стека в IP и увеличивает SP на 2.

Однобайтная команда RET с кодом операции CB осуществляет межсегментный возврат. Она передает слово из вершины стека в IP, увеличивает SP на 2. передает слово из вершины стека в CS и снова увеличивает SP на 2.

Трехбайтные варианты команд возврата осуществляют те же действия, что и однобайтные, а затем прибавляют содержащиеся в них данные к указателю стека. Эти команды предназначены для упро­щения возврата из тех подпрограмм, параметры которых передаются в стеке. Прибавление к SP данных из RET эквивалентно удалению пара-

КОМАНДЫ УПРАВЛЕНИЯ ЦИКЛАМИ

Три команды управления циклами применяются для организации программных циклов. В них предусматривается использование регист­ра CX в качестве счетчика цикла.

Команда LOOP производит декремент регистра CX и, если содер­жимое CX не равно нулю, происходит переход к началу цикла. В противном случае выполняется следующая по порядку команда.

Мнемоники LOOPE/LOOPZ определяют одну и ту же машинную команду, которая производит декремент регистра CX, а затем пере­дает управление в начало цикла, если содержимое CX не равно нулю и ZF=1. В противном случае выполняется следующая по порядку команда.

Мнемоники LOOPNE/LOOPNZ также определяют одну и ту же машин­ную команду, которая производит декремент регистра CX, а затем передает управление в начало цикла, если содержимое CX не равно нулю и ZF=0. В противном случае выполняется следующая по порядку команда.

В процессоре 8086 имеются 3 команды, относящиеся к прерыва­ниям.

Команда программного прерывания INT вызывает программу обра­ботки, определяемую типом прерывания.

Команда INT выполняется следующим образом:

1) декремент указателя стека на 2;

2) включение в стек содержимого регистра флажков;

3) сброс флажков IF и TF;

4) декремент указателя стека на 2;

5) включение в стек содержимого регистра CS;

6) определение адреса вектора прерывания ADDRESS путем умноже­ния кода типа прерывания на 4;

7) загрузка в регистр CS слова памяти, расположенного по адресу ADDRESS+2;

8) декремент указателя стека на 2;

9) включение в стек содержимого IP;

10) загрузка в регистр IP слова памяти, расположенного по адресу ADDRESS.

В результате этих действий осуществляется межсегментный кос-

венный вызов подпрограммы обработки прерывания.

Команда прерывания при переполнении INTO генерирует прог­раммное прерывание только в том случае, если установлен флаг переполнения. Она вызывает прерывание с номером 4.

Команда возврата из прерывания IRET предназначена для выхода из подпрограммы обработки прерываний, инициированной аппаратно или программно.

Команда IRET выполняется следующим образом:

1) слово из вершины стека передается в IP;

2) производится инкремент SP на 2;

3) слово из вершины стека передается в CS;

4) производится инкремент SP на 2;

5) слово из вершины стека передается в регистр флагов;

6) производится инкремент SP на 2.

Под цепочкой понимается последовательность любых контекстно связанных байт или слов, находящихся в смежных ячейках памяти.

В системе команд процессора 8086 имеется 5 команд, предназ­наченных для обработки одного элемента цепочки. Цепочечной команде может предшествовать специальный однобайтный префикс повторения REP, который вызывает повторение действия команды над следующими элементами цепочки. Повторение расчитано на максималь­ную длину цепочек 64 Кбайт и выполняется значительно быстрее цикла LOOP.

Необходимые в команде индексные и сегментные регистры должны быть инициализированы до ее выполнения.

При выполнении цепочечной команды содержимое регистров SI и DI автоматически изменяется, чтобы адресовать следующие элементы цепочек. Флаг направления DF определяет автоинкремент (DF=0) или автодекремент индексных регистров.

Если команде предшествует префикс повторения, то после каждого ее выполнения производится декремент регистра-счетчика CX, поэтому его необходимо предварительно инициализировать на

требуемое число повторений. Когда содержимое CX достигает нуля,

управление передается следующей команде.

Префикс повторения имеет 5 мнемокодов: REP, REPE, REPZ, REPNE, REPNZ.

Префикс REP используется с командами MOVS и STOS и вызывает повторение операции до тех пор, пока содержимое CX не равно 0.

Префиксы REPE и REPZ соответствуют тому же коду команды, что и мнемоника REP, но используются совместно с командами CMPS и SCAS. Они вызывают повторение операции до тех пор, пока ZF=1 и содержимое CX не равно 0.

Префиксы REPNE и REPNZ соответствуют одному коду команды, и используются совместно с командами CMPS и SCAS. Они вызывают повторение операции до тех пор, пока ZF=0 и содержимое CX не рав­но 0.

Команда MOVS передает байт или слово из цепочки, адресуемой регистром SI, в цепочку, адресуемую регистром DI. Команда переда­чи цепочки байт MOVSB после пердачи байта увеличивает содержимое регистров SI и DI на 1, а команда передачи цепочки слов MOVSW после передачи слова увеличивает их содержимое на 2.

Команда сканирования цепочки SCAS вычитает элементы цепочки, адресуемой регистром DI, из содержимого аккумулятора AL (при работе с байтами) или AX (при работе со словами). В зависимости от результата вычитания устанавливаются флаги, но сами операнды

КОМАНДЫ УПРАВЛЕНИЯ МИКРОПРОЦЕССОРОМ

Команды данной группы обеспечивают программное управление различными функциями процессора. Они делятся на две подгруппы: команды установки флагов и команды синхронизации.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *