ЯЗЫК АССЕМБЛЕРА МИКРОПРОЦЕССОРА 8086
Язык ассемблера представляет собой машинный язык в символической форме, которая более понятна и удобна человеку.
Язык ассемблера микропроцессора Intel 8086 является довольно сложным, что в первую очередь объясняется сегментной организацией памяти и одновременной адресацией четырех сегментов. В языке имеется более 100 базовых символических команд, в соответствии с которыми ассемблер генерирует более 3800 машинных команд. Кроме того, в распоряжении программиста имеется более 20 директив, предназначенных для распределения памяти, инициализации переменных, условного ассемблирования и т.д.
Исходная программа на языке ассемблера представляет собой последовательность операторов. Операторы обычно занимают одну строку. Ассемблер воспринимает операторы в свободном формате, т.е. элементам операторов не назначены фиксированные столбцы и между ними может быть любое число пробелов там, где это необходимо.
Операторы в исходной программе классифицируются как командные операторы, операторы распределения данных и директивы ассемблера.
Командные операторы определяют генерируемые ассемблером машинные команды; они содержат мнемонику и, при необходимости, один или два операнда. Каждый командный оператор порождает одну машинную команду, формат которой зависит от способа задания операндов.
Операторы распределения данных резервируют ячейки памяти для данных программы.
Директивы ассемблера содержат специальные указания для ассемблирующей программы и сами по себе не порождают никаких машинных кодов.
Формат командных операторов
Командные операторы записываются в следующем формате:
Метка: Префикс Мнемоника Операнд1,Операнд2 ;Комментарий
где фигурные скобки обозначают необязательные поля.
Рассмотрим назначение отдельных полей данного формата:
1) Метка представляет собой определяемое пользователем имя, заканчивающееся двоеточием. Значением метки является текущее значение счетчика ячеек (адресов) в текущем сегменте кода, т.е. адрес отмеченной команды. Метки как операнды используются только в командах передачи управления, и при этом двоеточие в конце ссылки на метку не ставится.
2) Префикс заставляет ассемблер сформировать один из префиксных байт - блокировки LOCK или повторения REP, который непосредственно предшествует команде.
3) Мнемоника кода операции представляет собой заранее определенное и неизменяемое имя, которое идентифицирует тип генерируемой машинной команды.
4) Операнды задают адреса данных или сами данные, необходимые в данной команде.
5) Комментарий предназначен только для документирования программы. Он всегда начинается с точки с запятой.
Формат директив ассемблера
и операторов распределения данных
Директивы ассемблера и операторы распределения данных имеют несколько иной формат:
Имя Директива Операнды ;Комментарий
Рассмотрим назначение отдельных полей данного формата:
1) Имя директивы, в отличие от метки, никогда не заканчивается двоеточием. Некоторые директивы требуют обязательного наличия метки.
2) Директива является одним из ключевых неизменяемых слов ассемблера и определяет его действия в процессе ассемблирования. Директивы используются программистом для распределения памяти, обеспечения связи между программными модулями и работы с символическими именами.
3) Операнды конкретизируют действия, выполняемые по данной директиве.
4) Поле комментария аналогично такому же полю в командных операторах.
Дадим определения основных терминов, которые будут использованы в дальнейшем.
Ключевые (зарезервированные) слова представляют собой имена, имеющие для ассемблера строго определенный смысл. Их нельзя использовать в качестве идентификаторов.
Идентификатор как общий термин для меток и имен переменных - это определяемая программистом последовательность символов. Первым символом в последовательности должна быть буква или один из символов @, подчеркивание или знак вопроса. В качестве последующих символов можно также использовать цифры. Максимальная длина идентификатора 31 символ.
Ассемблер процессора 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.
Разряды регистра флажков представляют собой однобитные регисты, для установки и сброса каждого из которых используются отдельные машинные команды.
При программировании может возникнуть необходимость многократного обращения к данным. Вместо того, чтобы оперировать громоздкими численными значениями адресов, удобно определять и применять символические имена, соответствующие адресам указанных элементов.
Переменная - это единица программных данных, имеющая символическое имя.
Большинство ассемблерных программ начинается с определения данных, которыми они будут оперировать. Распределение ячеек памяти и присвоение им идентификаторов осуществляется с помощью директив DB (Define Byte - определить байт), DW (Define Word - определить слово), DD (Define Doubleword - определить двойное слово), DQ (Define Quadword - определить 4 слова) или DT (Define Tenbyte - определить 10 байтов).
Операторы распределения данных имеют следующий формат:
Имя DB нач.значение, нач.значение, .
Имя DW нач.значение, нач.значение, .
Имя DD нач.значение, нач.значение, .
Имя DQ нач.значение, нач.значение, .
Имя DT нач.значение, нач.значение, .
Таким образом, каждая директива может инициировать одну или несколько переменных соответствующего типа.
Для задания начальных значений могут использоваться числовые константы и символьные цепочки. Если не нужно задавать начальное значение переменной, то вместо константы ставится вопросительный знак.
Например, оператор alpha DW 0Ah
резервирует слово памяти, присваивает ему идентификатор alpha и
заносит в него код 000A;
string DB 'Привет'
резервирует 6 байт памяти и заносит в них строку символов и
присваивает этой строке идентификатор string.
Чтобы точно определить тип переменной, на которую производится ссылка, ассемблер использует операторы BYTE PTR, WORD PTR и DWORD PTR (указатель на байт, слово и двойное слово соответственно).
Для инициализации массивов применяется конструкция DUP, которая в общем случае имеет вид:
n DUP (нач. значение, нач. значение, . )
где параметр n задает число повторений элементов, находящихся в
Например, оператор Addr DD 20 DUP (?)
резервирует место для 20 полных адресов и присваивает этому
массиву идентификатор Addr.
Метка представляет собой символическое имя для адреса ячейки памяти и предназначена для использования в качестве операнда в командах управления.
Константа - это численное значение, вычисляемое во время ассемблирования по заданному выражению.
Численные константы допускается представлять в системах счисления с основаниями 2, 8, 10 и 16. За младшей цифрой должен находиться однобуквенный дескриптор системы счисления: B - двоичная, O или Q - восьмеричная, D (необязательно) - десятичная, H-шестнадцатиричная. Шестнадцатиричная константа должна быть дополнена слева незначащим нулем.
Символьная константа - это любой символ в коде ASCII. Символьная строка может содержать до 255 символов и должна быть заключена в одиночные кавычки.
СЕГМЕНТЫ И ПРОЦЕДУРЫ
Программы, написанные на языке ассемблера процессора 8086, могут быть разделены на один или несколько сегментов. Каждый логический сегмент имеет уникальное имя и однозначно отображается в сегментах памяти при загрузке программы для ее выполнения. Для определения начальной и конечной ячеек логического сегмента в макроассемблере предусмотрены директивы SEGMENT (начало сегмента) и ENDS (конец сегмента).
Обычно часть программы, содержащая коды машинных команд,
объединяется в кодовый сегмент. Переменные, константы, таблицы и
другие данные объединяются в сегмент данных. Для хранения промежуточных данных и при вызове подпрограмм используется сегмент стека. Иногда для хранения данных может использоваться четвертый, дополнительный сегмент.
Директива ASSUME указывает ассемблеру, к какому сегментному регистру относится тот или иной логический сегмент. Если вся программа размещается в одном сегменте памяти, то эта директива указывает, что все сегментные регистры адресуют один и тот же сегмент.
В зависимости от используемой модели памяти в программе могут использоваться один или несколько сегментов кода и один или несколько сегментов данных. Стековый сегмент как правило один.
СТЕМА КОМАНД МИКРОПРОЦЕССОРА 8086
Систему команд процессора 8086 образуют 113 базовых команд, многие из которых допускают использование разнообразных режимов адресации.
По функциональному назначению выделяют спедующие группы команд:
- команды передачи данных;
- команды арифметических операций;
- команды логических операций и сдвигов;
- команды передачи управления;
- команды управления микропроцессором.
КОМАНДЫ ПЕРЕДАЧИ ДАННЫХ
Команды передачи данных разделяют на 4 подгруппы:
- общие команды передачи данных;
- команды передачи цепочек байт или слов.
Команды передачи данных не модифицируют состояния флажков. Исключение составляют команды POPF и SAHF, прямо воздействующие на регистр флажков.
Далее будут использоваться следующие обозначения: dst - получатель,
mem - адрес памяти (смещение), заданный любым методом адресации,
reg - регистр общего назначения,
sreg - сегментный регистр,
aс - регистр-аккумулятор (AL или AX),
data - непосредственные данные.
ОБЩИЕ КОМАНДЫ ПЕРЕДАЧИ ДАННЫХ
В эту подгруппу входят команды, осуществляющие передачу регистр-регистр, регистр-память и память-регистр. Наиболее мощной среди них является команда MOV.
Эта команда имеет следующее обобщенное представление:
т.е. первым указывается операнд-получатель, а вторым - операндисточник. Одним из операндов обязательно должен быть регистр.
Команда осуществляет передачу: регистр - регистр,
непосредственные данные - регистр,
непосредственные данные - память,
регистр - сегментный регистр,
память - сегментный регистр,
сегментный регистр - регистр,
сегментный регистр - память.
Допустимые форматы команды:
MOV mem/reg1, mem/reg2
MOV mem/reg, data
MOV sreg, mem/reg
MOV mem/reg, sreg
Команда обмена XCHG
Команда обмена XCHG позволяет обменивать содержимое любого общего регистра и ячейки памяти, а также любой пары общих регистров.
XCHG reg, mem/reg
Команда преобразования XLAT применяется для быстрого преобразования символов из одного кода в другой. Она заменяет содержимое аккумулятора AL на байт из 256-байтовой таблицы, начальный адрес которой находится в регистре BX, а восьмибитовое смещение - в регистре AL. В качестве сегментного используется регистр DS.
Команды LEA, LDS и LES
Команды LEA, LDS и LES предназначены для загрузки эффективного адреса.
Команда LEA извлекает из памяти 16-битовый адрес и помещает его в один из общих регистров. Практически эта команда дублирует один из вариантов команды MOV, но выполняется быстрее.
Команда LDS извлекает из памяти 32-битовый адрес и помещает первое считанное из памяти слово в заданный общий регистр, а второе - в сегментный регистр DS.
Команда LES извлекает из памяти 32-битовый адрес и помещает первое считанное из памяти слово в заданный общий регистр, а второе - в сегментный регистр ES.
Обычно в команде LDS указывается регистр SI, а в команде LES регистр DI.
Команды LAHF и SAHF
Команда LAHF передает младший байт регистра флажков в регистр AH, а команда SAHF реализует обратную передачу - содержимое регистра AH передается в младший байт регистра флажков (старший байт не изменяется).
Каждая команда занесения данных в стек PUSH имеет соответствующую ей команду извлечения из стека POP. Для адресации вершины стека используется стековый указатель SP. Все стековые команды манипулируют только словами и сопровождаются автоматической модификацией указателя стека: при включении в стек производится декремент, а при извлечении из стека - инкремент SP.
До выполнения стековых команд регистры 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 бит.
Диапазоны чисел: беззнаковое 8-битное: 0 - 255, беззнаковое 16-битное: 0 - 65535, знаковое 8-битное: -128 - +127, знаковое 16-битное: -32768 - +32767.
Команды арифметических операций влияют на состояние флажков 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 производит деление содержимого аккумулятора и его расширения на содержимое адресуемого операнда.
При делении 16-битного делимого на 8-битный делитель делимое помещают в регистр AX. В результате выполнения операции частное формируется в регистре AL, а остаток - в AH.
При делении 32-битного делимого на 16-битный делитель старшая часть делимого помещается в регистр DX, а младшая - в AX. В результате выполнения операции частное формируется в регистре AX, а остаток - в DX.
При делении на 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 и должна следовать непосредственно за ними.
Команда десятичной коррекции для умножения AAM выполняет коррекцию произведения, полученного в результате выполнения команды MUL и должна следовать непосредственно за ней. Старший разряд результата помещается в регистр AH, младший - в AL.
Команда десятичной коррекции для деления 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
КОМАНДЫ ПЕРЕДАЧИ УПРАВЛЕНИЯ
Сегментная организация программной памяти определяет две основные разновидности команд передачи управления. Передача управления в пределах текущего сегмента кода называется внутрисегментной - при этом модифицируется только регистр IP и адрес перехода может быть представлен одним словом. Такая передача управления называется ближней (тип NEAR), а ее вариант с сокращеннным диапазоном адресов переходов - короткой. Передача управления за пределы текущего сегмента кода называется межсегментной или дальней (тип FAR) - при этом необходимо модифицировать содержимое регистров IP и CS и адрес перехода представляется двумя словами (сегмент:смещение).
Команды передачи управления процессора 8086 подразделяются на команды безусловных переходов, условных переходов, вызовов, возвратов, управления циклами и команды прерываний.
Команды передачи управления не изменяет состояние регистра флагов (за исключением команды IRET).
КОМАНДЫ БЕЗУСЛОВНЫХ ПЕРЕХОДОВ
Команды безусловного перехода имеют общую мнемонику JMP. Команда короткого безусловного перехода содержит во втором байте смещение, которое интерпретируется как знаковое целое. Диапазон значений байта смещения составляет -128 - +127. Если смещение положительное, осуществляется переход вперед, а если отрицательное - переход назад.
Команда ближнего безусловного перехода может либо непосредственно содержать 16-битное смещение, либо косвенный адрес 16-битного смещения. Диапазон смещения составляет -32768 - +32767 байт относительно адреса команды, находящейся после команды JMP.
Команда дальнего безусловного перехода реализует прямой и
косвенный межсегментнные переходы.
JMP dispL - короткий переход
JMP disp - ближний прямой переход
JMP mem/reg - ближний косвенный переход
JMP addr - дальний прямой переход
JMP mem - дальний косвенный переход
КОМАНДЫ УСЛОВНЫХ ПЕРЕХОДОВ
В системе команд процессора 8086 имеется 19 двухбайтных команд условных переходов. При выполнении этих команд анализируется некоторое условие, закодированное текущими состояниями флагов, и если оно выполняется, то осуществляется переход, а если нет, то выполняется следующая по побядку команда.
Все условные переходы являются короткими. Некоторые команды для удобства программирования могут иметь несколько различных мнемонических обозначения.
Мнемонические обозначения команд:
1) Команды для работы с беззнаковыми числами: JA/JNBE - переход, если больше; JAE/JNB/JNC - переход, если больше или равно; JB/JNAE/JC - переход, если меньше; JBE/JNA - переход, если меньше или равно.
2) Команды для работы со знаковыми числами: JG/JNLE - переход, если больше; JGE/JNL - переход, если больше или равно; JL/JNGE - переход, если меньше; JLE/JNG - переход, если меньше или равно; JNS - переход, если больше нуля; JS - переход, если меньше нуля.
3) Команды, общие для знаковых и беззнаковых чисел: JE/JZ - переход, если равно / переход, если ноль; JNE/JNZ - переход, если не равно / переход, если не ноль;
JNO - переход, если нет переполнения;
JO - переход, по переполнению.
4) Прочие команды:
JCXZ - переход, если содержимое регистра CX равно нулю;
JNP/JPO - переход при отсутствии четности;
JP/JPE - переход по четности.
Форматы команд такие же, как у короткого безусловного перехода.
КОМАНДЫ ВЫЗОВОВА ПОДПРОГРАММ
Команда вызова подпрограммы CALL передает управление с автоматическим сохранением адреса возврата в стеке. В поле операнда этой команды находится метка первой команды вызываемой подпрог-
При переходе к подпрограмме необходимо временно запомнить адрес команды, находящейся после команды CALL. Этот адрес называется адресом возврата. После того, как подпрограмма закончит свои действия, завершающая ее команда возврата RET передает управление по запомненному адресу возврата. Адрес возврата запоминается в стеке.
Вызовы могут быть внутрисегментными (тип NEAR) или межсегментными (тип FAR). В первом случае вызываемая подпрограмма находится в текущем сегменте кода, а во втором - в произвольном.
Команды внутрисегментного перехода производят декремент SP на 2, включают в стек содержимое IP, а затем прибавляют к IP 16-битное смещение, которое интерпретируется как знаковое целое.
Команды межсегментного перехода производят декремент SP на 2, включают в стек содержимое CS, снова производят декремент SP на 2, включают в стек содержимое IP, затем в IP загружается значение смещения, а в CS - сегментный адрес.
CALL disp - непосредственный ближний вызов;
CALL mem/reg - косвенный ближний вызов;
CALL addr - непосредственный дальний вызов;
CALL mem - косвенный дальний вызов.
КОМАНДЫ ВОЗВРАТА ИЗ ПОДПРОГРАММ
Каждая подпрограмма должна содержать минимум одну команду возврата RET, которая возвращает управление вызывающей программе. Такая передача управления осуществляется путем извлечения из стека адреса возврата, включенного в него командой вызова подпрограммы.
Команды внутрисегментного и межсегментного возврата имеют одну и ту же мнемонику RET. Тип команды, соответствующей этой мнемонике, определяется ассемблером автоматически.
RET - однобайтный вариант,
RET data - трехбайтный вариант.
Однобайтная команда RET с кодом операции C3 реализует внутрисегментный возврат. Она передает слово из вершины стека в IP и увеличивает SP на 2.
Однобайтная команда RET с кодом операции CB осуществляет межсегментный возврат. Она передает слово из вершины стека в IP, увеличивает SP на 2. передает слово из вершины стека в CS и снова увеличивает SP на 2.
Трехбайтные варианты команд возврата осуществляют те же действия, что и однобайтные, а затем прибавляют содержащиеся в них данные к указателю стека. Эти команды предназначены для упрощения возврата из тех подпрограмм, параметры которых передаются в стеке. Прибавление к SP данных из RET эквивалентно удалению пара-
метров из стека.
КОМАНДЫ УПРАВЛЕНИЯ ЦИКЛАМИ
Три команды управления циклами применяются для организации программных циклов. В них предусматривается использование регистра CX в качестве счетчика цикла.
В поле операнда команд управления циклами находится метка первой команды цикла (8-битовое смещение). Диапазон переходов этих команд составляет -128 - +127 байт от следующей команды.
Команда LOOP производит декремент регистра CX и, если содержимое CX не равно нулю, происходит переход к началу цикла. В противном случае выполняется следующая по порядку команда.
Мнемоники LOOPE/LOOPZ определяют одну и ту же машинную команду, которая производит декремент регистра CX, а затем передает управление в начало цикла, если содержимое CX не равно нулю и ZF=1. В противном случае выполняется следующая по порядку команда.
Мнемоники LOOPNE/LOOPNZ также определяют одну и ту же машинную команду, которая производит декремент регистра CX, а затем передает управление в начало цикла, если содержимое CX не равно нулю и ZF=0. В противном случае выполняется следующая по порядку команда.
В процессоре 8086 имеются 3 команды, относящиеся к прерываниям.
Команда программного прерывания INT вызывает программу обработки, определяемую типом прерывания.
INT type - вызов прерывания с номером type (от 0 до 255),
INT - вызов прерывания контрольного останова (номер 3).
Команда 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 - смещением текущего элемента цепочки-получателя.
Необходимые в команде индексные и сегментные регистры должны быть инициализированы до ее выполнения.
При выполнении цепочечной команды содержимое регистров 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.
Команда сравнения цепочек CMPS производит вычитание байта или слово цепочки, адресуемой регистром DI, из байта или слова цепочки, адресуемой регистром SI. В зависимости от результата вычитания устанавливаются флаги, но сами операнды не изменяются. Команда сравнения цепочек байт CMPSB после каждой операции сравнения увеличивает содержимое регистров SI и DI на 1, а команда сравнения цепочек слов CMPSW - на 2.
Команда сканирования цепочки SCAS вычитает элементы цепочки, адресуемой регистром DI, из содержимого аккумулятора AL (при работе с байтами) или AX (при работе со словами). В зависимости от результата вычитания устанавливаются флаги, но сами операнды
не изменяются. Команда сканирования цепочки байт SCASB после каждой операции сканирования увеличивает содержимое регистра DI на 1, а команда сканирования цепочки слов SCASW - на 2.
Команда загрузки цепочки в аккумулятор LODS загружает элементы цепочки, адресуемой регистром SI, в аккумулятор AL или AX. Команда загрузки цепочки байт LODSB после выполнения каждой операции увеличивает содержимое регистра SI на 1, а команда загрузки цепочки слов LODSW - на 2.
Команда запоминания содержимого аккумулятора в цепочке STOS передает содержимое аккумулятора в элемент цепочки, адресуемый регистром DI. Команда запоманания цепочки байт STOSB после выполнения каждой операции увеличивает содержимое регистра DI на 1, а команда запоминания цепочки слов STOSW - на 2.
КОМАНДЫ УПРАВЛЕНИЯ МИКРОПРОЦЕССОРОМ
Команды данной группы обеспечивают программное управление различными функциями процессора. Они делятся на две подгруппы: команды установки флагов и команды синхронизации.