Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Создание и управление исключениями внутри ассемблерного кода x64 на Delphi

Delphi , Синтаксис , Ошибки и Исключения

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

Проблема

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

Альтернативный ответ

Вопрос остается прежним, но упоминается, что использование ассемблера может быть вызвано необходимостью использовать инструкции SSE, для которых нет соответствующих интринсиков в Delphi.

Подтвержденный ответ

Для того чтобы исключение возникало внутри функции, где произошло условие для его генерации, необходимо передать в функцию RaiseError текущий индекс инструкции (IP), который можно получить с помощью команды lea rax, [rip]. Таким образом, код ассемблера будет выглядеть следующим образом:

or rcx,rcx
jz @error
....
@error:
mov ecx, 1
mov rdx, ErrorString
lea r8,[rip]
jmp RaiseError
....
function RaiseError(code: integer; const Msg: string; address: pointer);
begin
case code of
1: raise EEmptyArrayError.Create(Msg) at address;
end;

Также стоит отметить, что в Delphi XE2+ и выше можно использовать компиляторную интринику System.ReturnAddress, которая работает как в 32-битном, так и в 64-битном коде:

procedure RaiseError(code: integer; const Msg: string);
begin
case code of
1: raise EEmptyArrayError.Create(Msg) at ReturnAddress;
end;
end;

В случае использования call RaiseError вместо jmp RaiseError в версии RaiseError с использованием ReturnAddress, исключение будет указывать на ассемблерный код как на источник ошибки. Если же используется jmp, то исключение будет указывать на вызывающую функцию, что может быть правильным, если ошибка действительно в передаваемых параметрах.

Примеры кода

function Example(Values: array of integer): integer;
asm
  or rcx,rcx
  jz @error
  ....
@error:
  mov ecx, 1
  mov rdx, 'Array is empty'
  lea r8,[rip]
  jmp RaiseError
  ....
end;

function RaiseError(code: integer; const Msg: string; address: pointer);
begin
  case code of
    1: raise EEmptyArrayError.Create(Msg) at address;
  end;
end;

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

Создано по материалам из источника по ссылке.

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


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




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


:: Главная :: Ошибки и Исключения ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-02-05 12:59:22/0.0034768581390381/0