Материал: Системное программирование

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

Совместно регистр и смещение используются в двух случаях:

  • При индексации в массивах, элементы которых имеют размер, отличный от 2, 4 и 8 бит. Смещение кодирует относительный адрес начала массива, а регистр определяет смещение элемента внутри массива.

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

Косвенная индексная адресация со смещением.Особенностью адресации является возможность масштабирования содержимого индексного регистра, что обеспечивает эффективное индексирование в массивах, элементы которых имеют размер 2, 4 или 8 бит (поле масштаба SS байта SIB). Смещение указывает адрес начала массива, а индексный регистр содержит порядковый номер нужного элемента.

Микропроцессор преобразует номер элемента в его смещение относительно начала массива, используя коэффициент масштабирования. Например, по командеMOVAX, M[SI*2] значение исполнительного адреса второго операнда будет вычислено как сумма значения идентификатора M и регистра SI, умноженного на 2.

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

Например, команда ADDAX, M[SI][BX] производит сложение содержимого регистраAXс содержимым слова по адресу: значение идентификатора M плюс содержимое регистровSIиBX. Для эффективного индексирования в двумерном массиве используют масштабирование содержимого индексного регистра (если элементы массива имеют размер 2, 4 или 8 битов).

Контрольные вопросы

  1. Какие существуют способы представления числовой информации в ЭВМ?

  2. Перечислите и опишите назначение регистров общего назначения.

  3. Опишите структуру машинной команды.

  4. Перечислите основные режимы адресации и приведите примеры.

3. Основные понятия языка ассемблера

3.1. Предложения

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

<предложение>

...

<предложение>

Каждое предложение состоит из лексем, наименьших значащих элементов, которые включают специальные символы, зарезервированные слова, идентификаторы и метки.

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

  • длина идентификатора может быть любой, но значащими являются первые 31 символ;

  • идентификатор не должен начинаться с цифры (A7 – разрешено, 7А – ошибка);

  • точка может быть только первым символом идентификатора (.А – разрешено, А. – ошибка);

  • в идентификаторах одноименные строчные и прописные буквы эквивалентны.

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

Целые числамогут быть записаны в десятичной, двоичной, восьмеричной или шестнадцатеричной системе счисления. Для различения используемой системы счисления в конце числа ставится спецификатор: в конце двоичного числа символ b (binary), в конце восьмеричного числа – о (octal) или q (символ «о» похож на ноль, поэтому допускается использовать «q»), в конце шестнадцатеричного числа – h (hexadecimal), а в конце де­сятичного числа – d (decimal).

Для различения чисел от идентификаторов перед буквенной цифрой (A-F), например A1h, должен быть указан незначащий ноль: 0A1h – число, А1h – идентификатор. Спецификаторы (b,d,h) и буквенные цифры (A-F) можно записывать строчными или прописными. Как правило, буквенные цифры записы­вают прописными, а спецификаторы – строчными.

Символьные данные.Символы и строки при записи заключаются в одинарные или двойные кавычки. В качестве символов можно использовать русские буквы. Если символ или строка заключена в одинарные кавычки, то одинарная кавычка удваивается, но двойную кавычку не удваивают: don"t 'don"t'. Если внешние кавычки двойные, то двойная кавычка удваивается, а одинарная не удваивается: "don't" don""t".

Переносить предложение на следующую строку или записывать в одной строке два предложения запрещено. При записи предложений действуют правила расстановки пробелов:

  • пробел обязателен между рядом стоящими идентификаторами и (или) числами чтобы отделить их друг от друга;

  • внутри идентификаторов и чисел пробелы недопустимы;

  • в остальных местах пробелы можно ставить или не ставить;

  • где допустим один пробел, допустимо любое число пробелов.

Все предложения делятся на три группы: комментарии,командыидирективы.

Комментариемсчитается любая строка, начинающаяся с символа «;». При трансляции программы ассемблер игнорирует все комментарии. В комментариях можно использовать любые символы, в том числе и русские. Допустим многострочный комментарий:

COMMENT <маркер> <текст>

В качестве маркера выбирается первый за словом COMMENT символ, отличный от пробела. Окончанием комментария считается позиция исходного текста программы, где снова встретился такой же маркер, например:

COMMENT * все это комментарий *

Командыпредставляют символьную форму записи машинных команд. Синтаксис команд следующий:

[<метка>:] <мнемокод> [<операнды>] [;<комментарий>]

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

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

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

Комментарий.В конце каждой команды можно помещать комментарий.

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

[<имя>] <название директивы> [<операнды>] [;<комментарий>]

3.2. Директивы определения данных

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

Директива DB(DefineByte, определить байт) определяет данные разме­ром в байт:

[<имя>] DB <операнд> {,<операнд>}

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

Существует два основных способа задания операндов директивы DB:

  • неинициализированное начальное значение ? (знак неопределенного значения);

  • константное выражение со значением от -128 до 255.

XDB?

По этой директиве переменной X отводится один байт памяти, в который ничего не записывается. Ассемблер запомнит адрес переменной и когда он встретится в тексте, заменит его на дан­ный адрес (выполнит трансляцию имен). Адрес ячейки, выделенной переменной с именем X, принято называть значе­нием имени X (в отличие от содержимого ячейки по этому адресу).

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

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

TYPE <имя>

Значением оператора является размер (в байтах) ячейки, выделенной под переменную с указанным именем. Если переменная описана по директиве DB, то для ее имени значение оператора равно 1. В языке ассемблера есть стандартная константа с именем BYTE и значением 1:

ТУРЕ X = BYTE = 1

Для определения переменной с начальным значением в качестве операнда в директиве DB указывается выражение, которое ассемблер вычислит, и значение которого запишет в ячейку памяти. В наиболее распространенном случае начальное значение байтовой переменной задается в виде числа с величиной от -128 до 255:

A DB 254 ; 0FEh

В DB -2 ; 0FEh (256-2=254)

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

В качестве начального значения перемен­ной можно указать символ, записав его чис­ловой код, либо сам символ в кавычках. Например, в кодировке ASCII код символа «*» равен 2Ah, поэтому следующие две директивы эквивалентны:

S DB 2Ah

S DB "*"

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

С помощью директивы DB можно описать двоично-десятичные числа:

PACK DB 01h, 23h ; число 123 в упакованном формате

UNPACK DB 1, 2, 3 ; число 123 в неупакованном формате

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

Другим более удобным способом описания является применение ASCII-чисел – записи чисел в виде символьных строк (например, ‘123’). В кодировке ASCII символьные цифры от ‘0’ до ‘9’ имеют коды от 30h до 39h. Поэтому преобразования таких символьных чисел в двоично-десятичные выполняется путем выделения младшего полубайта кода, а обратное преобразование – путем сложением с 30h.

С помощью директивы DB можно описать массив. Например, байтовый массив A из 8 элементов с начальным значением 0 для каждого из них можно определить так:

A db 0, 0, 0, 0, 0, 0, 0, 0

Директиву можно записать иначе:

A DB 8 DUP(0)

В качестве операнда здесь использована конструкция повторе­ния, в которой сначала указывается коэффициент повторения, а затем служебное слово DUP (duplicate, копировать) и в круглых скобках повторяемая величина:

k DUP (p1, р2,..., pn)

где

k - константное выражение с положительным значением, n 1;

рi- любой допустимый операнд директивы DB (возможна вновь конструкция повторения).

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

Вложенность конструкций DUP позволяет задать многомерные массивы. Например, байтовая матрица А размера 5x10 (10 байт в строке, 5 строк) имеет вид:

A DB 5 DUP(10 DUP(?))

Директива DW(DefineWord, определить слово) определяет переменную размером в слово.

Рассмотрим допустимые виды ее операндов.

Определение неинициализированной переменной:

A DW ?

В примере ассемблер отводит под переменную А слово памяти и переменная не получает начального значе­ния. Тип переменной равен 2, т.е. занимает два байта.

В языке ассемблера есть стандартная константа с именем WORD и значением 2:

TYPEа =WORD= 2

Операндом директивы может быть константное выражение со значением от -32768 до 65535.

B DW1234b

Под переменную B отводится слово памяти, и в ячейку записывается число, которые становится ее начальным значени­ем. Как для директивы DB, неотрицательные числа записываются в память как числа без знака, а отрицательные числа – в дополнительном коде. Поэтому числа, которые могут быть заданы как операнды директивы DW, должны быть в диапазоне [-215, 216-1]. Числа размером в слово хранятся в памяти в обратном порядке.

Источник: https://files.student-it.ru/previewfile/284711