Как передать строку в качестве аргумента инструкции call в встроенной сборке? - PullRequest
3 голосов
/ 18 февраля 2010

По сути, я хотел бы иметь возможность сделать что-то вроде этого:

//assume myFunction is defined and takes one argument that is an int
char * functionName = "myFunction";
int arg = 5;

__asm{
    push a
    call functionName
}

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

Edit: Речь идет о сборке х86

Ответы [ 4 ]

1 голос
/ 18 февраля 2010

Это невозможно, вы пытаетесь выполнить операцию по имени.Ассемблер имеет только вызов по значению, где значение является адресом.Вам нужно преобразовать имя в адрес и передать адрес ассемблеру, что означает, что вам нужна какая-то перекрестная ссылка между именами и адресами.Здесь вам поможет компилятор, в C и C ++ вам нужно найти указатели на функции, чтобы увидеть необходимый синтаксис для получения адреса функции, который затем можно передать ассемблеру.Да, иногда компилятор может вставлять символы в исполняемый файл, который затем можно найти, но этот метод полон проблем.Формат данных может меняться в зависимости от версии компилятора, информация может быть удалена компоновщиком и т. Д.

1 голос
/ 18 февраля 2010

Вы не можете, по крайней мере, не напрямую.

вызов принимает адрес в качестве параметра. Даже если вы напишите «call functionName», компоновщик заменяет имя функции фактическим адресом функции. Вам нужно сначала сопоставить эту строку с ее адресом. В общем, C и C ++ не поддерживают какие-либо метаданные времени выполнения о сопоставлениях имен функций, которые позволили бы это Если функция экспортируется из DLL, вы можете использовать GetProcAddress, чтобы найти ее адрес.

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

Что-то вроде:

std:map<string, PVOID> functionMappings;
functionMappings["MyFunction"] = MyFunction;


// Later


PVOID function = functionMappings["MyFunction"];

__asm
{
    push a;
    call [function]
}

Некоторые заметки:

Я полагаю, что стандарт говорит, что указатель на функцию может быть больше, чем PVOID. Это должно работать на платформах Windows x86 / x64.

Вы не сказали, какое соглашение о вызовах вы использовали - этот код предполагает стандартный вызов.

Это очень, очень странная вещь, которую нужно решить - какую проблему вы пытаетесь решить?

0 голосов
/ 18 февраля 2010

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

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

0 голосов
/ 18 февраля 2010

Краткий ответ: Забудьте об этом, если это допустимо, это, скорее всего, будет слишком сложно реализовать.

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

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

...