visual-studio assembly linker-errors masm

Llame a la función de biblioteca estándar C desde asm en Visual Studio



visual-studio assembly (3)

Tengo un problema al llamar a la función C desde un proyecto asm creado en Visual Studio (Win10 x64, Visual Studio 2015). El proyecto consta de un archivo 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

Cuando construyo el proyecto, el enlazador genera el error:

Error LNK2019 símbolo externo sin resolver _printf referenciado en la función _main @ 0

Parámetros de salida del enlazador:

/OUT:"C:/Users/apple/Documents/SP_Lab7/Debug/SP_Lab7_Demo.exe "/ MANIFEST: NO / NXCOMPAT /PDB:"C:/Users/apple/Documents/SP_Lab7/Debug/SP_Lab7_Demo.PdBB" "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" / MÁQUINA: X86 / SAFESEH: NO / INCREMENTAL: NO /PGD:"C:/Users/apple/Documents/SP_Lab7/Debug/SP_Lab7_Demo.pgd "/ SUBSYSTEM: WINDOWS / MAN: "level = ''asInvoker'' uiAccess = ''false''" /ManifestFile:"Debug/SP_Lab7_Demo.exe.intermediate.manifest "/ ERRORREPORT: PROMPT / NOLOGO / TLBID: 1

Si comento call print , todo se ejecuta normalmente (incluso la función API de Windows). ¿Hay alguna forma de llamar a la función C desde un archivo asm sin crear un archivo cpp que incluya <cstdio> ? Es posible de hacer?


Microsoft refactorizó gran parte del tiempo de ejecución C y las bibliotecas en VS 2015. Algunas funciones ya no se exportan desde la biblioteca C (algunas se definen en un archivo de encabezado C ). Microsoft tiene algunas bibliotecas de compatibilidad como legacy_stdio_definitions.lib y legacy_stdio_wide_specifiers.lib , pero también puede optar por usar el conjunto de herramientas de la plataforma Visual Studio 2013 anterior con las bibliotecas C más antiguas.

Para cambiar el conjunto de herramientas de la plataforma: despliegue el menú Project ; seleccione Properties... ; vaya a Configuration Properties / General y cambie Platform Toolset a Visual Studio 2013 (v120)


Parece que es posible usar el conjunto de herramientas de Visual Studio 2015 con algunas modificaciones.

  • Deberá agregar estas bibliotecas a sus dependencias: libcmt.lib , libvcruntime.lib , libucrt.lib , legacy_stdio_definitions.lib . Alternativamente, podría usar includelib para incluir estas bibliotecas en su archivo de ensamblaje.
  • Especifique la convención de llamada C para su procedimiento main usando PROC C
  • Al final de su archivo (y esto es importante) no use end main , use end only. No solucionar esto puede causar bloqueos inesperados.
  • Aunque podemos usar ExitProcess para salir de nuestra aplicación, también podemos poner el código de retorno en EAX y hacer un ret para volver. El tiempo de ejecución de C llama a nuestra función main y llamará al código de apagado cuando regresemos.

El código podría verse así:

.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


Puede llamar a las funciones de C, pero luego deberá vincular con la biblioteca de C. Exactamente cómo se hace eso dependerá de con qué biblioteca de C desee vincular. Sugeriría encontrar un tiempo de ejecución C mínimo, como la biblioteca WCRT .

La biblioteca probablemente requerirá inicialización, y puede requerir que defina un grupo de buffers en algún lugar para su contabilidad.

En lugar de pasar por todo este problema, te sugiero que solo te quedes con la API de Windows y, en tu caso, uses la función WriteConsole .