2010-02-18 4 views
3

По сути, я хотел бы быть в состоянии сделать что-то вроде этого:Как передать строку в качестве аргумента для команды «вызов» в встроенной сборке?

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

__asm{ 
    push a 
    call functionName 
} 

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

Edit: Мы говорим о x86 сборке

+0

Перефразируйте вопрос. Что вы подразумеваете под _single int как аргумент char * _? Вы пропустили важную деталь - на каком процессоре вы смотрите? Вам нужна общая идея или реальный x86-подобный ассемблерный код? – dirkgently

+0

Я не понимаю образец. Вызов не может быть для строки, это должен быть указатель на функцию. Вам нужно будет получить указатель на функцию, чтобы вызвать ее. Одна из возможностей - использовать GetProcAddr в своей собственной DLL. –

+0

Извините за путаницу, я имею в виду, что функция принимает один аргумент типа int: вызываемая функция не важна, я просто объясняю, почему я нажимаю «a: в стек.» –

ответ

1

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

вызов принимает адрес в качестве параметра. Даже если вы пишете «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.

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

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

+0

Я предполагаю, что мне нужно использовать . GetProcAddress затем Извините, если это глупый вопрос, но что exaclty это возвращаемое значение типа этой функции , например, будет 'Int а = GetProcAddress (dllHandle,«туРипсЫоп»);?' работа –

+0

Btw, что в коде предлагает __stdcall? Это просто факт, что вызывающий не выдает аргументы из стека, или есть что-то еще? –

+0

__stdcall - это соглашение о вызове - если вы пишете сборку, которая выполняет вызовы функций, вы необходимо понимать соглашения о вызовах. ресурсы доступны в сети для GetProcAddress и вызовов. MSDN даже имеет пример кода, показывающий, как использовать возвращаемое значение для GetProcAddress. – Michael

0

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

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

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

1

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

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

0

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

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