Visual studio 在Visual Studio中从asm调用C标准库函数
我在调用visual studio(Win10 x64,visual studio 2015)中创建的asm项目中的C函数时遇到问题。项目由一个asm文件组成:Visual studio 在Visual Studio中从asm调用C标准库函数,visual-studio,assembly,x86,linker-errors,masm,Visual Studio,Assembly,X86,Linker Errors,Masm,我在调用visual studio(Win10 x64,visual studio 2015)中创建的asm项目中的C函数时遇到问题。项目由一个asm文件组成: .586 .model flat, stdcall option casemap:none includelib msvcrt.lib ExitProcess PROTO return:DWORD extern printf:near .data text BYTE "Text", 0 .code main PROC pu
.586
.model flat, stdcall
option casemap:none
includelib msvcrt.lib
ExitProcess PROTO return:DWORD
extern printf:near
.data
text BYTE "Text", 0
.code
main PROC
push offset text
call printf
add esp,4
invoke ExitProcess,0
main ENDP
end main
生成项目时,链接器输出错误:
错误LNK2019中引用的未解析外部符号\u printf
作用_main@0
链接器输出参数:
/输出:“C:\Users\apple\Documents\SP_Lab7\Debug\SP_Lab7\u Demo.exe”
/清单:否/NXCOMPAT
/PDB:“C:\Users\apple\Documents\SP_Lab7\Debug\SP_Lab7\u Demo.PDB”
/DYNAMICBASE“kernel32.lib”“user32.lib”“gdi32.lib”“winspool.lib”
“comdlg32.lib”“advapi32.lib”“shell32.lib”“ole32.lib”“oleaut32.lib”
“uuid.lib”“odbc32.lib”“odbccp32.lib”/MACHINE:X86/SAFESEH:NO
/增量:没有
/PGD:“C:\Users\apple\Documents\SP_Lab7\Debug\SP_Lab7\u Demo.PGD”
/子系统:WINDOWS/MANIFESTUAC:“level='asInvoker'uiAccess='false'”
/清单文件:“Debug\SP_Lab7_Demo.exe.intermediate.manifest”
/ERRORREPORT:PROMPT/NOLOGO/TLBID:1
如果我注释调用print
,则所有操作都会正常执行(即使是Windows API函数)。有没有办法从asm文件调用C函数而不创建包含
的cpp文件?
可以这样做吗?您可以调用C函数,但随后需要链接到C库。具体如何实现这一点将取决于您希望链接到哪个C库。我建议找到一个最小的C运行时,比如 该库可能需要初始化,并且可能需要您在某个地方为其簿记定义一组缓冲区
与其麻烦重重,我建议您还是坚持使用Windows API,在您的情况下使用该函数。Microsoft在VS 2015中重构了大部分C运行时和库。有些函数不再从C库导出(有些是在C头文件中定义的)。Microsoft有一些兼容库,如legacy_stdio_definitions.lib和legacy_stdio_wide_specifiers.lib,但您也可以选择将旧的Visual Studio 2013平台工具集与旧的C库一起使用
要更改平台工具集,请下拉
项目
菜单;选择属性…;转到配置属性
/常规
,并将平台工具集
更改为Visual Studio 2013(v120)似乎可以通过一些修改来使用Visual Studio 2015工具集
- 您需要将这些库添加到依赖项中:libcmt.lib、libvcruntime.lib、libucrt.lib、legacy_stdio_definitions.lib。或者,您可以使用
将这些库包括在程序集文件中includelib
- 使用
PROC
- 在文件末尾(这一点很重要),不要使用
,只使用end main
。不解决此问题可能会导致意外的崩溃李>end
- 虽然我们可以使用ExitProcess退出应用程序,但我们也可以将返回代码放入EAX中,并执行
返回。C运行时调用我们的ret
函数,并在返回时为我们调用关闭代码main
.586
.model flat, stdcall
option casemap:none
includelib libcmt.lib
includelib libvcruntime.lib
includelib libucrt.lib
includelib legacy_stdio_definitions.lib
ExitProcess PROTO return:DWORD
extern printf:NEAR
.data
text BYTE "Text", 0
.code
main PROC C ; Specify "C" calling convention
push offset text
call printf
add esp, 4
; invoke ExitProcess,0 ; Since the C library called main (this function)
; we can set eax to 0 and use ret`to have
; the C runtime close down and return our error
; code instead of invoking ExitProcess
mov eax, 0
ret
main ENDP
end ; Use `end` on a line by itself
; We don't want to use `end main` as that would
; make this function our program entry point
; effectively skipping by the C runtime initialization
感谢您指向使用WinAPI函数,因为我想要的主要函数是
strcspn
,类似的函数StrSpn
。但我仍然不明白,为什么includelib msvcrt.lib
不加载C库。解决方法是将平台工具集设置为VS2013。为此,请下拉项目
菜单,选择属性…
。转到配置属性
/常规
,并将平台工具集
更改为Visual Studio 2013(v120)@MichaelPetch它真的很有效,谢谢Microsoft重构了C运行时的大部分。有些函数不再在库中导出(有些在C头文件中定义)。MS有一些兼容库legacy_stdio_definitions.lib和legacy_stdio_wide_specifiers.lib,但我还没有让printf使用它们,所以我选择使用VS 2013工具集。可能还有其他的解决方法,但我还没有看到。我已经添加了一个新的答案和一个您可能有兴趣尝试的解决方案。它使用Visual Studio 2015工具集。在尝试之前,您必须从Visual Studio 2013工具集切换到2015。如果这对你有用的话,我会很生气的。