1. Главная страница » Компьютеры » Offset assembler что это

Offset assembler что это

Автор: | 16.12.2019
Что такое JavaScript

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

Команда LEA в Ассемблере вычисляет эффективный адрес ИСТОЧНИКА и помещает его в ПРИЁМНИК. Синтаксис:

LEA ПРИЁМНИК, ИСТОЧНИК

После выполнения этой команды флаги не изменяются.

Обратите внимание, что ИСТОЧНИКОМ может быть только переменная (ячейка памяти), а ПРИЁМНИКОМ — только регистр (но не сегментный).

Что такое эффективный адрес

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

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

Так вот, слово “эффективный” можно перевести на русский как “действенный”, “действующий”, “настоящий”. Что касается программистской терминологии, то в некоторых источниках вместо “эффективный адрес” встречается словосочетание “текущий адрес” или даже “виртуальный адрес”.

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

Ну а если кратко, то эффективный (текущий) адрес — это

БАЗА + СМЕЩЕНИЕ + ИНДЕКС

где БАЗА — это базовый адрес, находящийся в регистре (при 16-разрядной адресации могут использоваться только регистры BX или BP); СМЕЩЕНИЕ (или ОТКЛОНЕНИЕ — displacement) — это константа (число со знаком), заданная в команде; ИНДЕКС — значение индексного регистра (при 16-разрядной адресации могут использоваться только регистры SI или DI).

Любая из частей эффективного адреса может отсутствовать (например, необязательно указывать СМЕЩЕНИЕ или ИНДЕКС), но обязательно должна присутствовать хотя бы одна часть (например, только БАЗА).

Вычисление эффективного адреса

Ну а теперь чуть подробнее о самой команде LEA. Как уже было сказано, она выполняет вычисление адреса в Ассемблере. В итоге в ПРИЁМНИК записывается адрес памяти (точнее, только смещение).

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

Если адрес 32-разрядный, а ПРИЁМНИК — 16-разрядный, то старшая половина вычисленного адреса теряется. Если наоборот, ПРИЁМНИК — 32-разрядный, а адрес 16-разрядный, то вычисленное смещение дополняется нулями.

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

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

Оператор OFFSET позволяет определить смещение только при компиляции, и в отличие от него команда LEA может сделать это во время выполнения программы. Хотя в остальных случаях обычно вместо LEA используют MOV и OFFSET, то есть

LEA ПРИЁМНИК, ИСТОЧНИК

это то же самое, что и

MOV ПРИЁМНИК, offset ИСТОЧНИК

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

Ещё один пример:

После выполнения этой программы в AX будет записано значение 0104h. Команда LEA занимает 3 байта, команда RET занимает 1 байт. Мы начинаем с адреса 100h, поэтому адрес переменной Х — это 104h (100h + 3 + 1 = 104h). Команда LEA вычислила этот адрес и записала его в указанный регистр (в нашем случае в АХ).

Команда LEA в арифметических операциях

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

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

Напоследок, как всегда, о происхождении аббревиатуры LEA.

LEALoad Effective Address (загрузить эффективный адрес).

Для каждой закодированной команды ассемблер генерирует одну команду на машинном языке. Но для каждого закодированного оператора компиляторного языка Pascal или C генерируется один или более (чаще много) команд машинного языка. В этом отношении можно считать, что компиляторный язык состоит из макрооператоров.

Ассемблер FASM ( MASM так же как и другие) также имеет макросредства, но макросы здесь определяются программистом. Для этого задается директива MACRO ,имя макроса, открываеться фигурная скобка, различные ассемблерные команды, которые должен генерировать данный макрос и для завершения макроопределения — закрываеться фигурная скобка. Затем в любом месте программы, где необходимо выполнение определенных в макрокоманде команд, достаточно закодировать имя макроса. В результате ассемблер сгенерирует необходимые команды. Использование макрокоманд позволяет:

  • упростить и сократить исходный текст программы;
  • сделать программу более понятной;
  • уменьшить число возможных ошибок кодирования.
Читайте также:  Gin white lace отзывы

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

Пример простого макроса:

Как видим создали простой макрос который упрощает наглядно вид программы. Вместо макроса endprogram вставляется его тело(то есть его код).

Давайте создадим еще один макрос который принимает параметры:

Мы создали макрос который принимает переменную и выводит ее на экран. Это переменная (str) для макроса является локальной, и она видна только внутри макроса. также в макросе можно создавать свои локальные метки и переменные:

Так же все макросы можно написать в отдельном файле а затем подключить его с помощью директивы include. К примеру создадим два файла main.asm и my_macro.as m со следующим содержимым:

my_macro.asm:

main.asm:

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

OFFSET

  • Опубликовано 19.03.2014 10:57
  • Автор: Админ
  • Просмотров: 803
  • Категория: Разное

Оператор OFFSET возвращает относительный адрес переменной или метки внутри сегмента данных или кода. Оператор имеет следующий формат:

устанавливает в регистре DX относительный адрес (смещение) поля TABLEA в сегменте данных. (Заметим, что команда LEA выполняет аналогичное действие, но без использования оператора OFFSET.)

  • Опубликовано 19.03.2014 10:22
  • Автор: Админ
  • Просмотров: 611
  • Категория: Разное

Оператор PTR используется совместно с атрибутами типа BYTE, WORD или DWORD для локальной отмены определенных типов (DB, DW или DD) или с атрибутами NEAR или FAR для отмены значения дистанции по умолчанию. Формат оператора следующий:

В поле "тип" указывается новый атрибут, например BYTE. Выражение имеет ссылку на переменную или константу. Приведем несколько примеров оператора PTR:

  • Опубликовано 19.03.2014 10:42
  • Автор: Админ
  • Просмотров: 818
  • Категория: Разное

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

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

Имя, связанное с некоторым значением с помощью директивы EQU, может использоваться в командах, например:

Ассемблер заменяет имя COUNTR в команде MOV на значение 05, cоздавая операнд с непосредственным значением, как если бы было закодировано

Здесь преимущество директивы EQU заключается в том, что многие команды могут использовать значение, определенное по имени COUNTR. Если это значение должно быть изменено, то изменению подлежит лишь одна директива EQU. Естественно, что использование директивы EQU разумно лишь там, где подстановка имеет смысл для ассемблера. В директиве EQU можно использовать символические имена:

Первый пример предполагает, что в сегменте данных программы опpеделено имя TOTALPAY. Для любой команды, содержащей операнд TP, ассемблер заменит его на адрес TOTALPAY. Второй пример показывает возможность использования в программе слова MPY вместо обычного мнемокода MUL.

Linux

  • Опубликовано 19.03.2014 08:42
  • Автор: Админ
  • Просмотров: 576
  • Категория: Разное

Данный пост я хочу посвятить тому как написать простую программу на ассемблере для Linux. И так начнем с того что все системные вызовы в линуксе осуществляются с помощью прерывания 80h. Номер системного вызова содержится в регистре ЕАХ, если системный вызов(прерывание) принимает параметры то они находятся в регистрах EBX,ECX, EDX, ESI и EDI. Результат прерывания будет находиться в регистре ЕАХ и если результат будет от fffff000h до ffffffffh то это говорит что прерывание совершилось с ошибкой. К примеру системная функция которая отвечает за ввод и вывод в консоли находиться под номером 4, а номер под функции будет находиться в регистре EBX. Теперь рассмотрим пример кода для FASM ассемблера:

Теперь все по порядку:
format ELF executable 3 — строка говорит нам что будет собран исполняем файл UNIX-подобных системах(linux к ним относиться).

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

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

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

Теперь давайте расмотрим как вводить символы для этого предназначен системный вызов под номером 3. Пример:

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

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

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

Читайте также:  Fossil smart watch gen 2 q wander
Способы адресации операндов

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

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

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

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

  • 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.
  • прямую адресацию;
  • косвенную адресацию.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Читайте также:  0X80070570 файл или папка повреждены чтение невозможно

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

Записи (аналогично структурному типу) используются для доступа к битовому полю некоторой записи. Для доступа к битовому полю записи используется директива 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. Например,

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

*

code