2016-10-13 15 views
0

Как я вижу, extern Функции WinAPI в коде сборки имеют имена, такие как [email protected].Win32 Assembly - Именование функций extern (значение «@»)

В чем смысл части @4 и как определить, какой номер использовать после @?

Я знаю, что это связано с DLL, с которой мы связываемся, но во многих случаях неизвестно, какой номер использовать после @, и это приводит к множеству неприятных ошибок undefined reference.

ответ

4

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

Если вы хотите, чтобы перепроверить, что вы получили правильный номер, и у вас есть Microsoft Visual Studio установлена, вы можете найти декорированное имя символа из командной строки Developer, как это:

C:\> dumpbin /headers kernel32.lib | find "ExitProcess" 
    Symbol name : [email protected] 
    Name   : ExitProcess 

Если вы» повторно с помощью инструментов компилятора MinGW, чтобы связать код сборки, вы можете сделать это вместо того, чтобы:

C:\> nm C:\MinGW\lib\libkernel32.a | find "ExitProcess" 
00000000 I [email protected] 
00000000 T [email protected] 

Вам нужно заменить C:\MinGW с каталогом установлен MinGW.

Поскольку не все API Windows находятся в библиотеке импорта kernel32, вам необходимо заменить kernel32 именем библиотеки импорта, указанной в документации Windows SDK для функции API, к которой вы хотите установить ссылку. Например, с MessageBoxA вам нужно будет использовать user32.lib с Visual Studio и libuser32.a вместо MinGW.

Обратите внимание, что существует несколько редких API Windows, которые не используют соглашение о вызове stdcall. Это такие функции, как wsprintf, которые принимают переменное количество аргументов, которое не поддерживает соглашение о вызове stdcall. Эти функции имеют только знак подчеркивания _ перед их именами, а не @ или номер после. Они также требуют, чтобы вызывающий объект удалял аргументы из стека.

+0

Этот метод действительно работает. – hakeris1010

1

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

Как:

srv*https://msdl.microsoft.com/download/symbols 

или

srv*c:\MyServerSymbols*https://msdl.microsoft.com/download/symbols 

Например (в cmd.exe, окна командной строки):

set _NT_SYMBOL_PATH=srv*https://msdl.microsoft.com/download/symbols 

Затем используйте:

dumpbin /exports /symbols kernel32.dll | grep -i ExitProcess 

Вы должны быть в каталоге, где находится kernel32, и вам придется иметь grep.

Возможно, это способ использовать встроенную команду find. Вы также можете перенаправить его в файл, а затем просмотреть его в своем редакторе.

+0

Не работает для меня. Я просто получаю '289 120 ExitProcess (перенаправляется на NTDLL.RtlExitUserProcess)'. –

+0

Исправлено это ... нужно добавить/символы тоже –

+0

По-прежнему не повезло, я получаю тот же результат с '/ exports/symbols'. –

3

Символ @, как ведущее подчеркивание, является частью имени функции, когда для функции задано соглашение о вызове stdcall.

Число указывает количество байтов, которое функция удаляет из стека.

Компилятор генерирует это число.

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

Смотрите также https://msdn.microsoft.com/de-de/library/zxk0tw93.aspx