我在Visual Studio中创建的asm项目调用C函数时出现问题(Win10 x64,Visual Studio 2015)。项目由一个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
push offset text
call printf
add esp,4
invoke ExitProcess,0
main ENDP
end main
当我构建项目时,链接器输出错误:
错误LNK2019未解析的外部符号_printf在中引用 function _main @ 0
链接器输出参数:
/ OUT:" C:\用户\苹果\文件\ SP_Lab7 \调试\ SP_Lab7_Demo.exe" / MANIFEST:NO / NXCOMPAT /PDB:"C:\Users\apple\Documents\SP_Lab7\Debug\SP_Lab7_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" /机器:X86 / SAFESEH:没有 /增量:NO /PGD:"C:\Users\apple\Documents\SP_Lab7\Debug\SP_Lab7_Demo.pgd" / SUBSYSTEM:WINDOWS / MANIFESTUAC:" level =' asInvoker' uiAccess ='假'" /ManifestFile:"Debug\SP_Lab7_Demo.exe.intermediate.manifest" / ERRORREPORT:PROMPT / NOLOGO / TLBID:1
如果我评论call print
,那么一切都正常执行(甚至是Windows API函数)。有没有办法从asm文件调用C函数而不创建包含<cstdio>
的cpp文件?
有可能吗?
答案 0 :(得分:9)
Microsoft在VS 2015中重构了大部分 C 运行时和库。某些函数不再从 C 库中导出(某些函数在 C中定义) 头文件)。 Microsoft有一些兼容性库,如 legacy_stdio_definitions.lib 和 legacy_stdio_wide_specifiers.lib ,但您也可以选择使用较旧的Visual Studio 2013平台工具集和较旧的 C < / em> libraries。
更改平台工具集:下拉Project
菜单;选择Properties...
;转到Configuration Properties
/ General
,然后将Platform Toolset
更改为 Visual Studio 2013(v120)
答案 1 :(得分:7)
它似乎是&#39;可以使用Visual Studio 2015 Toolset进行一些修改。
includelib
将这些库包含在程序集文件中。main
PROC C
程序指定 C 调用约定
end main
,仅使用end
。不修复此问题可能会导致意外崩溃。 ret
返回。 C 运行时调用我们的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
答案 2 :(得分:1)
您可以调用C函数,但是您需要链接C库。具体如何完成将取决于您想要链接的C库。我建议找一个最小的C运行时,例如WCRT library。
该库可能需要初始化,并且可能需要您在某处定义一堆缓冲区以便保存。
我建议您坚持使用Windows API,而不是遇到所有这些麻烦,在您的情况下使用WriteConsole函数。