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
usandoPROC C
-
Al final de su archivo (y esto es importante) no use
end main
, useend
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ónmain
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 .