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
Другие вопросы по тегам