使用vs2019编译32位Vdisk驱动时,提示Crypto.lib库的几个函数符号为找到实现,编译64位没问题,错误如下所示:
2>Crypto.lib(blake2s_SSE2.obj) : warning LNK4257: 未对内核模式编译对象文件;映像可能不会运行
2>Crypto.lib(blake2s_SSSE3.obj) : warning LNK4257: 未对内核模式编译对象文件;映像可能不会运行
2>Crypto.lib(blake2s_SSE41.obj) : warning LNK4257: 未对内核模式编译对象文件;映像可能不会运行
2>Crypto.lib(rdrand.obj) : warning LNK4257: 未对内核模式编译对象文件;映像可能不会运行
2>Crypto.lib(kuznyechik_simd.obj) : warning LNK4257: 未对内核模式编译对象文件;映像可能不会运行
2>Crypto.lib(SerpentFast_simd.obj) : warning LNK4257: 未对内核模式编译对象文件;映像可能不会运行
2>Crypto.obj : error LNK2019: 无法解析的外部符号 _aes_hw_cpu_decrypt_32_blocks@8,函数 _DecipherBlocks@16 中引用了该符号
2>Crypto.obj : error LNK2019: 无法解析的外部符号 _aes_hw_cpu_encrypt_32_blocks@8,函数 _EncipherBlocks@16 中引用了该符号
2>Sha2.obj : error LNK2019: 无法解析的外部符号 _sha512_compress_nayuki@8,函数 _SSE2Transform@16 中引用了该符号
2>Sha2.obj : error LNK2019: 无法解析的外部符号 _sha256_compress_nayuki@8,函数 _Sha256AsmTransform@16 中引用了该符号
为什么找不到函数实现? 经过查看相关函数实现的asm源码,发现声明函数的时候都会有一个条件编译判断,如果定义了MS_STDCALL宏,则使用cpp的调用约定声明函数
sha256-x86-nayuki.S源码:
/* void sha256_compress_nayuki(uint32_t state[8], const uint8_t block[64]) */
.ifdef MS_STDCALL
.globl _sha256_compress_nayuki@8
_sha256_compress_nayuki@8:
.else
.globl sha256_compress_nayuki
.globl _sha256_compress_nayuki
sha256_compress_nayuki:
_sha256_compress_nayuki:
.endif
根据错误提示_sha256_compress_nayuki@8
明显,这是一个带有名称粉碎的函数,也就是cpp的调用约定;
发现这个问题后,直接在vs项目属性的预处理器里面新增MS_STDCALL
,尝试编译,还是报同样错误,说明这个宏定义没有生效;
最后发现,上面报错的几个函数实现都在不同的asm文件中,在编译时通过通过nasm和yasm来编译成obj文件,然后vs编译的时候直接将obj链接进去。
因为编译asm文件的时候是通过yasm.exe 或者nasm.exe编译的,无法读取vs项目属性中定义的宏;
解决方案:
在对应asm文件属性中,修改命令行,传入asm编译工具的-D参数,指定MS_DTDCALL,这样asm文件中的条件编译就可以生效了