ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 19.06.2021

Просмотров: 299

Скачиваний: 2

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Тема 2. Основные стадии выполнения команды


Лекция 3. Программирование на языке ассемблера.


1. Синтаксис ассемблера

2. Операнды

3. Виды адресация ассемблера



1. Синтаксис ассемблера


Программа на ассемблере представляет собой совокупность блоков памяти, называемых сегментами. Программа может состоять из одного или нескольких таких блоков-сегментов. Сегменты программы имеют определенное назначение, соответствующее типу сегментов: кода, данных и стека. Названия типов сегментов отражают их назначение. Деление программы на сегменты отражает сегментную организацию памяти процессоров Intel (архитектура IA-32). Каждый сегмент состоит из совокупности отдельных строк, в терминах теории компиляции называемых предложениями языка. Для языка ассемблера предложения, составляющие программу, могут представлять собой синтаксические конструкции четырех типов:

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

макрокоманды — это оформляемые определенным образом предложения текста программы, замещаемые во время трансляции другими предложениями;

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

комментарии содержат любые символы, в том числе и буквы русского алфавита. Комментарии игнорируются транслятором.

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

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


Рис. 1. Формат предложений ассемблера



Рис. 2. Формат директив



Рис.3. Формат команд и макрокоманд


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


Имя метки — символьный идентификатор. Значением данного идентификатора является адрес первого байта предложения программы, которому он предшествует.

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

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

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

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

Алфавит ассемблера включает в себя следующие символы допустимые для написания текста программ:

ASCII_символ_буква — все латинские буквы А - Z, а - z, причем прописные и строчные буквы считаются эквивалентными;

decdigit — цифры от 0 до 9;

специальные знаки _, ?, @, $, &;

разделители: „ ., [, ], (, ), <, >, {, }, +, /, *, %, !, ", ", ?, \, = #, ^.

Лексемами языка ассемблера являются ключевые слова, идентификаторы, цепочки символов и целые числа.

Ключевые слова — это служебные символы языка ассемблера. По умолчанию регистр символов ключевых слов не имеет значения. К ключевым словам относятся:

названия регистров (AL, АН, BL, ВН, CL, СН, DL, DH, АХ, ЕАХ, ВХ, ЕВХ, СХ, ЕСХ, DX, EDX, ВР, EBP, SP, ESP, DI, EDI, SI, ESI, CS, DS, ES, FS, GS, SS, CR0, CR2, CR3, DR0, DR1, DR2, DR3, DR6, DR7);

операторы (BYTE, SBYTE, WORD, SWORD, DWORD, SDWORD, FWORD, QWORD, TBYTE, REAL4, REAL8, REAL10, NEAR16, NEAR32, FAR16, FAR32, AND, NOT, HIGH, LOW, HIGHWORD, LOWWORD, OFFSET, SEG, LROFFSET, TYPE, THIS, PTR, WIDTH, MASK, SIZE, SIZEOF, LENGTH, LENGTHOF, ST, SHORT, TYPE, OPATTR, MOD, NEAR, FAR, OR, XOR, EQ, NE, LT, LE, GT, GE, SHR,

названия команд (КОП) ассемблера, префиксов.

Идентификаторы — последовательности допустимых символов, использующиеся для обозначения имен переменных и меток.

Приведенные формы говорят о том, что идентификатор может состоять из одного или нескольких символов. В качестве символов можно использовать буквы латинского алфавита, цифры и некоторые специальные знаки — _, ?, $, @. Идентификатор не может начинаться символом цифры. Длина идентификатора может составлять до 255 символов (247 в MASM), хотя транслятор воспринимает лишь первые 32, а остальные игнорирует. Регулировать длину возможных идентификаторов (в TASM) можно с использованием ключа командной строки /mv. Кроме того, существует возможность указать транслятору на необходимость различать прописные и строчные буквы либо игнорировать их различие (что и делается по умолчанию). Для этого (в TASM) применяются ключи командной строки /mu, /ml, /mx.


Цепочки символов — это последовательности символов, заключенные в одинарные или двойные кавычки.

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

<шестнадц_число><дес_шестнадц_число>h|0<сим_шестнадц_число>h;

<дес_шестнадц_число> <decdigit> <сим_шестнадц_число> | <decdigit>

<сим_шестнадц_число>

<hexdigit> <сим_шестнадц_число> | <дес_шестнадц_число> | <decdigit> |<hexdigit>

<decdigit> 0| 1 | 2 | 3 |4| 5 | 6 | 7 | 8| 9

<hexdigit> a|b|c|d|e|f|A|B|C|D|E|F

При этом наличие символов после (h) и перед (0) записью шестнадцатеричного числа. Это сделано для того, чтобы транслятор мог отличить в программе одинаковые по форме записи десятичные и шестнадцатеричные числа.

Для двоичных чисел все просто — после записи нулей и единиц, входящих в их состав, необходимо поставить латинскую букву «b».



2. Операнды


Операнды — это объекты, над которыми или при помощи которых выполняются действия, задаваемые инструкциями или директивами. Машинные команды могут либо совсем не иметь операндов, либо иметь один или два операнда. Большинство команд требует двух операндов, один из которых является источником, а другой — приемником (операндом, назначения). В двухоперандной машинной команде возможны следующие сочетания операндов:

регистр — регистр;

регистр — память;

память — регистр;

непосредственный операнд — регистр;

непосредственный операнд — память.

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

Для приведенных ранее правил сочетания типов операндов есть исключения, которые касаются:

команд работы с цепочками, которые могут перемещать данные из памяти в память;

команд работы со стеком, которые могут переносить данные из памяти в стек, также находящийся в памяти;

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

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

Классификация операндов, поддерживаемых транслятором ассемблера.

операнд задается неявно на микропрограммном уровне. В этом случае команда явно не содержит операндов. Алгоритм выполнения команды использует некоторые объекты по умолчанию (регистры, флаги в EFLAGS и т. д.). Например, команды CLI и STI неявно работают с флагом прерывания IF в регистре EFLAGS, а команда XLAT неявно обращается к регистру AL и строке в памяти по адресу, определяемому парой регистров DS:BX.


операнд задается в самой команде (непосредственный операнд). Это может быть число, строка, имя или выражение, имеющее некоторое фиксированное (константное) значение. Физически непосредственный операнд находится в коде команды, то есть является ее частью. Для его хранения в команде выделяется поле длиной до 32 битов. Непосредственный операнд может быть только вторым операндом (источником). Операнд-приемник может находиться либо в памяти, либо в регистре. Например, команда mov ax,0ffffh пересылает в регистр АХ шестнадцатеричную константу Offffh. Команда add sum,2 складывает содержимое поля по адресу sum с целым числом 2 и записывает результат по месту первого операнда, то есть в память. Если непосредственный операнд — имя, то оно не должно быть перемещаемым, то есть зависеть от адреса загрузки программы в память. Такое имя можно определить оператором EQU или =.

Адресные операнды задают физическое расположение операнда в памяти путем указания двух составляющих адреса: сегмента и смещения (рис. 4).

Рис. 4. Синтаксис адресных операндов


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

Счетчик адреса — специфический вид операнда. Он обозначается знаком $. Специфика этого операнда в том, что когда транслятор ассемблера встречает в исходной программе этот символ, то он подставляет вместо него текущее значение счетчика адреса. Значение счетчика адреса, или, как его иногда называют счетчика размещения, представляет собой смещение текущей машинной команды относительно начала сегмента кода. При обработке транслятором очередной команды ассемблера счетчик адреса увеличивается на длину сформированной машинной команды. Важно правильно это понимать. К примеру, обработка директив ассемблера не влечет за собой изменения счетчика, так как директивы ассемблера, в отличие от его команд, — это лишь указания транслятору на выполнение определенных действий по формированию машинного представления программы, и для них транслятором не генерируется никаких конструкций в памяти.

Регистровый операнд — это просто имя регистра. В программе на ассемблере можно использовать имена всех регистров общего назначения и некоторых системных регистров (СЛАЙД):

32-разрядные регистры ЕАХ, ЕВХ, ЕСХ, EDX, ESI, EDI, ESP, EBP;

16-разрядные регистры АХ, ВХ, СХ, DX, SI, DI, SP, ВР;

8-разрядные регистры АН, AL, BH, BL, CH, CL, DH, DL;

сегментные регистры CS, DS, SS, ES, FS, GS;


системные регистры CR0, CR2, CR3, CR4, DR0, DR1, DR2, DR3, DR6, DR7.

Операнд — порт ввода-вывода. Помимо адресного пространства оперативной памяти процессор поддерживает адресное пространство ввода-вывода, которое используется для доступа к устройствам ввода-вывода. Объем адресного пространства ввода-вывода составляет 64 Кбайт. Для любого устройства компьютера в этом пространстве выделяются адреса. Конкретное значение адреса в пределах этого пространства называется портом ввода-вывода. Физически порту ввода-вывода соответствует аппаратный регистр (не путать с регистром процессора), доступ к которому осуществляется с помощью специальных команд ассемблера IN и OUT.

Регистры, адресуемые с помощью порта ввода-вывода, могут иметь разрядность: 8, 16 или 32 бита, но для конкретного порта разрядность регистра фиксирована Команды IN и OUT работают с фиксированной номенклатурой объектов. В качестве источника информации или получателя применяются так называемые регистры-аккумуляторы ЕАХ, АХ, AL. Выбор регистра определяется разрядностью порта. Номер порта может задаваться непосредственным операндом в командах IN и OUT или значением в регистре DX. Последний способ позволяет динамически определить номер порта в программе.

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

Записи (аналогично структурному типу) используются для доступа к битовому полю некоторой записи.

Операнд находится в стеке.

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



3. Виды адресация ассемблера


Прямая адресация — это простейший вид адресации операнда в памяти, так как эффективный адрес содержится в самой команде и для его формирования не используется никаких дополнительных источников или регистров. Эффективный адрес берется непосредственно из поля смещения машинной команды, которое может иметь размер 8, 16, 32 бита. Это значение однозначно определяет байт, слово или двойное слово в сегменте данных. Прямая адресация может быть двух типов:

относительная прямая адресация используется в командах условных переходов для указания относительного адреса перехода. Относительность такого перехода заключается в том, что в поле смещения машинной команды содержится 8-, 16- или 32-разрядное значение, которое в результате работы команды будет складываться с содержимым регистра указателя команд IP/EIP. В результате такого сложения получается адрес, по которому и осуществляется переход;

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