1

我正在尝试让 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

有什么线索吗?

谢谢...

4

2 回答 2

1

尝试在两个目标文件上运行 dumpbin 以转储符号表。这应该同时显示发出的和引用的函数名称。这通常有助于诊断这类问题。

于 2012-08-15T09:24:01.933 回答
0

这是汇编代码中的声明:

public @InNonSuspendableCriticalRegion@4

@InNonSuspendableCriticalRegion@4 proc near ; fastcall
     ;; code
@InNonSuspendableCriticalRegion@4 endp

我认为你很接近。这个答案中唯一真正的见解是汇编程序默认情况下不会损坏,所以如果你调用你的过程InNonSuspendableCriticalRegion,那么它就是这样导出的。要为更高级别的语言获得一个错误的名称,您通常可以按照 Alexey 的建议进行操作。但是没有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++ 代码通过 fastcall与MASM 代码交互(代码调用 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

垃圾箱

请注意,该符号MASM_RDRAND_GenerateBlock是用 导出的External,它会再次以别名 as 导出,@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
于 2017-03-07T17:18:54.120 回答