Операнды в языке ассемблера

Язык ассемблера / Операнды в языке ассемблера

Операнд – объект, над которым выполняется машинная команда.

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

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

Способы адресации операндов

Под способами адресации понимаются существующие способы задания адреса хранения операндов:


Операнд задается на микропрограммном уровне (операнд по умолчанию): в этом случае команда явно не содержит операнда, алгоритм выполнения команды использует некоторые объекты по умолчанию (регистры, признаки и т.д.).

mul ebx   ; eax = eax*ebx, неявно использует регистр eax


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

mov eax, 5 ; eax = 5;
add ebx, 2  ; ebx = ebx + 2;


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

  • 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.
add eax, ebx        ; eах = eax + ebх
dec esi            ; esi = esi - 1

Операнд располагается в памяти. Данный способ позволяет реализовать два основных вида адресации:
  • прямую адресацию;
  • косвенную адресацию.

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

mov eax,  sum   ; eax = sum

Ассемблер заменяет sum на соответствующий адрес, хранящийся в сегменте данных (по умолчанию адресуется регистром ds) и значение, хранящееся по адресу sum, помещает в регистр eax.

Косвенная адресация в свою очередь имеет следующие виды:

  • косвенная базовая (регистровая) адресация;
  • косвенная базовая (регистровая) адресация со смещением;
  • косвенная индексная адресация;
  • косвенная базовая индексная адресация.

Косвенная базовая (регистровая) адресация. При такой адресации эффективный адрес операнда может находиться в любом из регистров общего назначения, кроме sp/esp и bp/ebp (это специфические регистры для работы с сегментом стека). Синтаксически в команде этот режим адресации выражается заключением имени регистра в квадратные скобки [].

mov eax, [esi] ; eax = *esi; *esi значение по адресу esi

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

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

mov eax, [esi+4]   ; eax = *(esi+4)

 

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

mov eax, mas[esi*4]

Значение эффективного адреса второго операнда вычисляется выражением mas+(esi*4) и представляет собой смещение относительно начала сегмента данных.

Наличие возможности масштабирования существенно помогает в решении проблемы индексации при условии, что размер элементов массива постоянен и составляет 1, 2, 4 или 8 байт.

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

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

mov  eax, [esi][edx]

Эффективный адрес второго операнда формируется как esi+edx. Значение по этому адресу помещается в регистр eax.

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


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

in al,60h ; ввести байт из порта 60h

Регистры, адресуемые с помощью порта ввода-вывода, могут иметь разрядность 8, 16 или 32 бит, но для конкретного порта разрядность регистра фиксирована. В качестве источника информации или получателя применяются регистры-аккумуляторы eax, ax, al. Выбор регистра определяется разрядностью порта. Номер порта может задаваться непосредственным операндом в командах in и out или значением в регистре dx. Последний способ позволяет динамически определить номер порта в программе.

mov  dx,20h    ; записать номер порта 20h в регистр dx
mov  al,21h    ; записать значение 21h в регистр al
out  dx,al     ; вывести значение 21h в порт 20h


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

jmp $+3 ;безусловный переход на команду mov
nop     ; длина команды nop составляет 1 байт
mov al,1

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


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

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

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

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

Приоритет Оператор
1 length, size, width, mask, ( ), [ ], < >
2 .
3 :
4 ptr, offset, seg, this
5 high, low
6 +, - (унарные)
7 *, /, mod, shl, shr
8 +, -, (бинарные)
9 eq, ne, lt, le, gt, ge
10 not
11 and
12 or, xor
13 short, type

Характеристика основных операторов.

Арифметические операторы. К ним относятся унарные операторы + и -, бинарные + и -, операторы умножения *, целочисленного деления /, получения остатка от деления mod. Например,

size    equ    48    ;размер массива в байтах
el    equ    4    ;размер элемента
;вычисляется количество элементов
mov    ecx, size / el    ;оператор /

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

msk    equ    10111011 ; константа
mov al, msk shr 3    ; al=00010111 /

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

size        equ    30    ;размер таблицы
...
mov    al, tab_size ge 50 ;al = 0
cmp    al, 0        ;если size < 50, то
je     m1       ;переход на m1
...
m1: ...

Если значение size больше или равно 50, то результат в аl равен 1, в противном случае - 0. Команда cmp сравнивает значение аl с нулем и устанавливает соответствующие флаги в EFLAGS. Команда je на основе анализа этих флагов передает или не передает управление на метку m1.

Назначение операторов сравнения приведено в таблице

Оператор Условие
eq ==
ne !=
lt <
le <=
gt >
ge >=

Логические операторы выполняют над выражениями побитовые операции. Выражения должны быть константными. Например,

L1    equ    10010011
...
mov    al, L1
xor al, 01h    ;al=10010010

Индексный оператор [ ]. Транслятор воспринимает наличие квадратных скобок как указание сложить значение выражения за [] со значением выражения, заключенным в скобки. Например,

mov    eax, mas[esi]    ;eax=*(mas+(esi))

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

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

Тип Пояснение Назначение
byte 1 байт переменная
word 2 байта переменная
dword 4 байта переменная
qword 8 байт переменная
tword 10 байт переменная
near ближний указатель функция
far дальний указатель функция

Например,

str1    db  "Привет", 0
...
lea esi, str1
cmp byte ptr[esi], 0 ; [esi]==0?

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

Оператор переопределения сегмента : (двоеточие) вычисляет физический адрес относительно конкретно задаваемой сегментной составляющей, в качестве которой могут выступать:

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

Для выборки на выполнение очередной команды микропроцессор анализирует содержимое сегментного регистра CS, в котором содержится физический адрес начала сегмента кода. Для получения адреса конкретной команды микропроцессор складывает промасштабированное (умноженное на 16) значение сегментного регистра CS с содержимым регистра EIP. Запись CS:EIP содержит адрес текущей выполняемой команды. Аналогично обрабатываются операнды в машинных командах.

Оператор именования типа структуры . (точка) также заставляет транслятор производить определенные вычисления, если встречается в выражении.

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

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

.data
str1   db "Привет",0
.code
mov    esi, offset str1
mov al, [esi] ; al = 'П'

Оператор определения длины массива length возвращает число  элементов,  определенных  операндом dup. Если операнд dup отсутствует, то оператор length возвращает значение 1.Например,

tabl    dw    10 dup(?)
...
mov    edx, length tabl        ; edx=10

Оператор type возвращает число  байтов,  соответствующее  определению указанной переменной:

fldb        db   ?
tabl    dw   10 dup(?)
...
mov  eax, type fldb     ;eax = 1
mov  eax, type tabl  ;eax = 2

Оператор size возвращает произведение длины length и типа type и используется при ссылках на переменную с операндом dup.
Для предыдущего примера

mov  edx, size tabl      ;edx = 20 байт

Оператор short –модификация атрибута near в команде jmp, если переход не превышает границы +127 и -128 байт. Например,

jmp    short метка

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

Оператор width возвращает размер в битах объекта типа RECORD или его поля.

Назад


Назад: Язык ассемблера

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

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