MASM x86 объявление функции fastcall... как?
Я пытаюсь заставить программу VisualStudio 2010 C вызывать подпрограмму ассемблера fastcall.
Это объявление в коде C:
extern boolean _fastcall InNonSuspendableCriticalRegion(DWORD);
Это объявление в коде сборки:
public @InNonSuspendableCriticalRegion@4
@InNonSuspendableCriticalRegion@4 proc near ; fastcall
<code>
@InNonSuspendableCriticalRegion@4 endp
Я получаю следующую ошибку компоновщика:
Assembling: C:\DMS\Domains\PARLANSE\Tools\RunTimeSystem\Source\PARLANSE0.asm
1>RuntimeSupport.obj : error LNK2001: unresolved external symbol @InNonSuspendableCriticalRegion@4
Я уверен, что делаю что-то глупое неправильно, но я не вижу этого.
Документация MS довольно сложна для понимания, так как она очень расплывчата. В тумане прошлого я вспоминаю, что ассемблер тоже делает некоторые искажения имен, поэтому я не уверен, как получаемые имена искажаются, если они есть.
Это самая явная ссылка на то, как это сделать, и я думаю, что точно следую этому; это говорит,
13. FASTCALL Caller and Callee Summary
The following sample illustrates the code generated in the calling function and in the called function to support __fastcall, the fastcall calling convention:
int __fastcall FastFunc( int a, int b );
calling function called function
-------------------------------------------
mov edx, b @FastFunc@8 PROC NEAR
mov ecx, a .
call @FastFunc@8 .
. .
. RET 8
. @FastFunc@8 ENDP
Есть какие-нибудь подсказки?
Спасибо...
2 ответа
Попробуйте запустить dumpbin в обоих объектных файлах, чтобы вывести таблицу символов. Это должно показать как испускаемое, так и имя ссылающейся функции. Это обычно помогает в диагностике подобных проблем.
Это объявление в коде сборки:
public @InNonSuspendableCriticalRegion@4 @InNonSuspendableCriticalRegion@4 proc near ; fastcall ;; code @InNonSuspendableCriticalRegion@4 endp
Я думаю, что вы близко. Единственное реальное понимание в этом ответе - ассемблер не искажает по умолчанию, поэтому, если вы вызываете свою процедуру InNonSuspendableCriticalRegion
тогда вот как это экспортируется. Чтобы получить искаженное имя для языка более высокого уровня, вы обычно можете делать то, что предлагает Алексей. Однако нет FASTCALL
так что просто используйте ALIAS
,
Сделайте что-то вроде этого:
title Really cool assembly routines
public InNonSuspendableCriticalRegion
.486
.MODEL FLAT
.CODE
ALIGN 8
ALIAS <@InNonSuspendableCriticalRegion@4> = <InNonSuspendableCriticalRegion>
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
InNonSuspendableCriticalRegion proc
;; code
InNonSuspendableCriticalRegion endp
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef
;; ...
end
Я думаю public @InNonSuspendableCriticalRegion@4
тоже неверно (но это не является причиной проблем с оформлением имени). Вы можете опустить его, или вы можете использовать неукрашенный InNonSuspendableCriticalRegion
название.
Вы можете найти документ для ALIAS
здесь Это не очень впечатляет.
Вы можете увидеть, какие символы экспортируются с dumpbin
, Ниже приведен пример из проекта Crypto++.
_IF_ вы получаете нежелательное нижнее подчеркивание в названии fastcall, например _@InNonSuspendableCriticalRegion@8
, то убедитесь, что у вас нет OPTION LANGUAGE:C
где-то.
Наконец я подумал SYSCALL
был в основном эквивалентен FASTCALL
, но я не мог заставить ассемблер принять это. Возможно, раньше это работало, но я не могу заставить MASM принять его в современной Visual Studio.
Проект Crypto++ использует код C++ для взаимодействия с кодом MASM с помощью fastcall (код вызывает RDRAND или RDSEED, и он должен работать быстро).
Код C++
Следующее объявление используется как для X86, так и для X64.
#if MASM_RDRAND_ASM_AVAILABLE
extern "C" void CRYPTOPP_FASTCALL MASM_RDRAND_GenerateBlock(byte*, size_t);
#endif
#if MASM_RDSEED_ASM_AVAILABLE
extern "C" void CRYPTOPP_FASTCALL MASM_RDSEED_GenerateBlock(byte*, size_t);
#endif
Dumpbin
Обратите внимание на символ MASM_RDRAND_GenerateBlock
экспортируется с External
и снова экспортируется с псевдонимом как @MASM_RDRAND_GenerateBlock@8
и появляется с WeakExternal
,
Если у вас нет линейных символов (меток), то обязательно соберите /Zi
, Это ваша отладочная информация с файлами MASM.
C:\>dumpbin /SYMBOLS rdrand-x86.obj
Dump of file rdrand-x86.obj
File Type: COFF OBJECT
COFF SYMBOL TABLE
000 00DF520D ABS notype Static | @comp.id
001 00000011 ABS notype Static | @feat.00
002 00000000 SECT1 notype Static | .text$mn
Section length 6F, #relocs 0, #linenums 0, checksum 0
004 00000000 SECT2 notype Static | .data
Section length 0, #relocs 0, #linenums 0, checksum 0
006 00000000 SECT3 notype Static | .debug$S
Section length 534, #relocs 26, #linenums 0, checksum 0
008 00000000 SECT4 notype Static | .debug$T
Section length 3C, #relocs 0, #linenums 0, checksum 0
00A 00000000 SECT1 notype () External | MASM_RDRAND_GenerateBlock
00B 00000000 UNDEF notype WeakExternal | @MASM_RDRAND_GenerateBlock@8
Default index A Alias record
00D 00000038 SECT1 notype () External | MASM_RDSEED_GenerateBlock
00E 00000038 UNDEF notype WeakExternal | @MASM_RDSEED_GenerateBlock@8
Default index D Alias record
010 00000000 SECT1 notype Static | $$000000
011 00000000 SECT1 notype Label | GenerateBlock_Top
012 00000005 SECT1 notype Label | Call_RDRAND_EAX
013 0000000A SECT1 notype Label | RDRAND_succeeded
014 0000000F SECT1 notype Label | Full_Machine_Word
015 00000019 SECT1 notype Label | Partial_Machine_Word
016 0000002A SECT1 notype Label | Bit_1_Not_Set
017 00000034 SECT1 notype Label | Bit_0_Not_Set
018 00000034 SECT1 notype Label | GenerateBlock_Return
019 00000038 SECT1 notype Label | GenerateBlock_Top
01A 0000003D SECT1 notype Label | Call_RDSEED_EAX
01B 00000042 SECT1 notype Label | RDSEED_succeeded
01C 00000047 SECT1 notype Label | Full_Machine_Word
01D 00000051 SECT1 notype Label | Partial_Machine_Word
01E 00000062 SECT1 notype Label | Bit_1_Not_Set
01F 0000006C SECT1 notype Label | Bit_0_Not_Set
020 0000006C SECT1 notype Label | GenerateBlock_Return