Offset assembler что это
Перейти к содержимому

Offset assembler что это

  • автор:

Оператор OFFSET

OFF SET можно перевести как “вне набора”. Применительно к языку ассемблера ещё более вольный перевод может звучать так: за пределами набора команд. Почему этот оператор назвали именно так, поймёте, прочитав эту статью. Ну а вообще слово OFFSET переводится как “смещение”. И это, конечно, настоящий перевод. Но я позволил себе немного пофилософствовать )))

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

В защищённом режиме работы процессора смещения всегда являются 32-разрядными числами без знака. В реальном и виртуальном режимах адресации смещения всегда 16-разрядные.

С помощью оператора OFFSET в ассемблере можно объявлять переменные, то есть связывать адрес в памяти с именем переменной. По этой ссылке вы найдёте пример объявления строки. Но переменные могут быть, разумеется, не только строковыми.

.model tiny .code ORG 100h start: MOV AX, wVar ; AX = 65535 MOV DX, OFFSET wVar ; DX = 107 RET wVar DD 65535 ; Объявляем переменную типа WORD END start

Здесь мы объявили переменную wVar и назначили сразу ей какой-то значение (в нашем случае 65535). В программе мы записали ЗНАЧЕНИЕ этой переменной в регистр АХ. А вот потом, с помощью оператора OFFSET, мы получаем адрес (смещение) переменной wVar , относительно начала сегмена (в нашем случае это 100h). И в нашем случае смещение будет равно 107 в шестнадцатеричной системе, потому что:

  • Сегмент начинается с адреса 100h ( ORG 100h )
  • Команда MOV AX, wVar занимает 3 байта с адресами: 100h, 101h, 102h
  • Команда MOV DX, OFFSET wVar занимает следующие 3 байта с адресами: 103h, 104h, 105h
  • Команда RET занимает 1 байт по адресу: 106h

Ну и получается, что наша переменная wVar находится по адресу 107h.

Таким вот нехитрым образом можно получить адрес первого байта любой объявленной переменной. Соответственно, чтобы получить адрес следующего байта, надо просто прибавить 1 к смещению. Это обычно используется при работе со строками, когда надо получить отдельный символ строки. Пример:

.model tiny .code ORG 100h start: MOV AH, 09h ;Номер функции 09h MOV DX, OFFSET stroka+7 ;Адрес строки записываем в DX INT 21h RET stroka DB 'Hello, World. $' ;Строка для вывода END start END start

Здесь мы выводим не всю строку, а начиная с 8-го символа, потому что к смещению адреса переменной stroka мы прибавили 7. Но прибавили мы 7, а не 8, потому что адресация начинается с нуля, а не с единицы. Таким образом на экран будет выведено:

то есть только нужная нам часть строки.

На этом пока всё. Подключайтесь к группе Основы программирования в Телеграм, или к другим каналам (ссылки ниже), чтобы ничего не пропустить.

Offset assembler что это

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

offset переменная

Поскольку адрес в архитектуре x86-64 занимает 8 байт, то для хранения адреса нам надо определить переменную с типом qword . Например, определим переменную и получим ее адрес:

.data n dword 22 pn qword ? .code main proc ; установка указателя mov rax, offset n ; загружаем адрес переменной n mov pn, rax ; сохраняем адрес в переменную pn ; получение данных по указателю mov rbx, pn ; в rbx помещаем адрес из переменной pn mov rax, [rbx] ; обращаемся по адресу из rbx ret main endp end

Здесь определена переменная-указатель pn, которая представляет тип qword и которая будет хранить адрес переменной n. Сначала получаем адрес в регистр RAX и затем передаем его в указатель pn:

mov rax, offset n mov pn, rax

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

mov rbx, pn ; в rbx помещаем адрес из переменной p mov rax, [rbx] ; обращаемся по адресу из rbx

В итоге в регистре RAX окажется число 22 — значение переменной n.

При этом мы можем получить адрес уже при определении переменной-указателя:

.data n dword 11 pn qword offset n ; получаем адрес переменной n .code main proc ; получение данных по указателю mov rbx, pn ; в rbx помещаем адрес из переменной pn mov rax, [rbx] ; в RAX число 11 ret main endp end

Указатель необязательно должен представлять переменную — это может быть и константа:

pn equ offset n ; константа pn указывает на переменную n .data n dword 12 .code main proc ; получение данных по указателю mov rbx, pn ; в rbx помещаем адрес из переменной pn mov rax, [rbx] ; в RAX число 11 ret main endp end

Операции с адресом

При получении адреса мы можем использовать ряд операций:

offset переменная [смещение] offset переменная + смещение offset переменная - смещение

В этом случае мы можем получить адрес, который смещен относительно адреса переменной на несколько байтов вперед или назад. Выражение переменная [смещение] фактически эквивалентно выражению переменная + смещение . Например:

.data nums dword 11, 12, 13, 14, 15, 16 p qword ? .code main proc ; установка указателя mov rax, offset nums + 4 ; загружаем адрес переменной nums + 4 mov p, rax ; сохраняем адрес в переменную p ; получение данных по указателю mov rbx, p ; в rbx помещаем адрес из переменной p mov rax, [rbx] ; обращаемся по адресу из rbx ret main endp end

Здесь переменная nums представляет набор 32-битных чисел. Выражение offset nums возвращает адрес перемнной num — адрес первого числа из этого набора. Соответственно чтобы получить адрес второго числа из этого набора, нам надо прибавить размер одного элемента в байтах, то есть 4 байта — offset nums + 4

подскажите по ассемблер простыми словами. Что делает команда Offset? и почему символьная константа внутри продолжение.

offset означает что берётся адрес переменной, а не её значение. Например, есть переменная:

Предположим, что она размещена по адресу 20FFFh. Тогда:

mov eax, X ;eax = 7
mov eax, offset X ;eax = 20FFFh

Остальные ответы
dx это параметр для прерывания 21h, в регистре записано смещение начала строки, все просто.

+ Почему метка позже и внутри — у Вас судя по виду .com файл, где сегмент данных и сегмент кода (впрочем как и сегмент стека) — один и тот-же и точка входа у него всегда по адресу со смещением 100h

=> Если данные объявлять до начала кода — нужен будет дополнительный прыжок (jmp) чтобы эти данные обогнуть

Оператор OFFSET

Возвращает смещение в соответствующий сегмент выражения.

Синтаксис

См. также

Дополнительные ресурсы

Значок отказа согласно Закону Калифорнии о защите конфиденциальности потребителей (CCPA)

  • Светлая
  • Темная
  • Высокая контрастность
  • Предыдущие версии
  • Блог
  • Участие в доработке
  • Конфиденциальность
  • Условия использования
  • Товарные знаки
  • © Microsoft 2024

Дополнительные ресурсы

Значок отказа согласно Закону Калифорнии о защите конфиденциальности потребителей (CCPA)

  • Светлая
  • Темная
  • Высокая контрастность
  • Предыдущие версии
  • Блог
  • Участие в доработке
  • Конфиденциальность
  • Условия использования
  • Товарные знаки
  • © Microsoft 2024

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

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