winapi assembly nasm

winapi - Vinculación a Kernel32.lib en ensamblador



assembly nasm (1)

¡Empecé a aprender ensamblaje hoy y realicé muchas pruebas en Linux que funcionaron muy bien! Me mudé a mi PC y comencé a intentar escribir algunos aquí. Me encontré con un problema al intentar llamar a funciones externas (que una vez más, funcionó bien en Linux) donde obtendría LINK 2001 Errores externos no resueltos que me indicaban que WriteConsoleA no está definido cuando después de compilar con nasm:

nasm -f win32 test.asm -o test.obj

y con cl.exe:

cl test.obj /link libcmt.lib kernel32.lib

Obtengo estos errores:

test.obj : error LNK2001: unresolved external symbol ExitProcess test.obj : error LNK2001: unresolved external symbol GetStdHandle test.obj : error LNK2001: unresolved external symbol WriteConsoleA test.exe : fatal error LNK1120: 3 unresolved externals

La Asamblea:

extern ExitProcess, GetStdHandle, WriteConsoleA NULL equ 0 STD_OUTPUT_HANDLE equ -11 section .data msg db "Hello world!",0xa msgLen equ $-msg section .bss dummy resd 1 section .text global _main _main: push STD_OUTPUT_HANDLE call GetStdHandle push NULL push dummy push msgLen push msg push eax call WriteConsoleA push NULL call ExitProcess

Copiado casi exactamente desde aquí . ¡Cualquier ayuda es muy apreciada! ¡Gracias!


En primer lugar, cl no es un enlazador sino un compilador. ¿Por qué no simplemente usar GoLink como lo mostré en la publicación a la que se vinculó? Es mucho más fácil de usar. Podría usar ld como el enlazador, pero sus externos cambiarán un poco.

Las funciones de API de Windows usan decoraciones de nombre de función - un guión bajo + Nombre de Función + @ tamaño de parámetros, esta es una cosa enlazadora.

Entonces, ExitProcess se exporta realmente como _ExitProcess @ 4 ya que toma 1 parámetro DWORD. WriteConsoleA toma 5 parámetros de tamaño DWORD, por lo que sería _WriteConsole @ 20

Cambia tu código a:

extern _ExitProcess@4, _GetStdHandle@4, _WriteConsoleA@20 %define ExitProcess _ExitProcess@4 %define GetStdHandle _GetStdHandle@4 %define WriteConsoleA _WriteConsoleA@20 NULL equ 0 STD_OUTPUT_HANDLE equ -11 section .data msg db "Hello world!",0xa msgLen equ $-msg section .bss dummy resd 1 section .text global _main _main: push STD_OUTPUT_HANDLE call GetStdHandle push NULL push dummy push msgLen push msg push eax call WriteConsoleA push NULL call ExitProcess

Para vincular con ld, dígale dónde está el directorio lib, una buena apuesta es: -L "C: / Archivos de programa / Microsoft SDKs / Windows / v6.0 / Lib"

entonces solo usa la bandera -l con la biblioteca -l kernel32

Mi archivo make usando NASM y ld para su código de muestra:

APP= Sample all: $(APP) clean $(APP): $(APP).obj "C:/MinGW/bin/ld" $(APP).obj -o $(APP).exe -L "C:/Program Files/Microsoft SDKs/Windows/v6.0/Lib" -l kernel32 $(APP).obj: $(APP).asm nasm -f win32 $(APP).asm -o $(APP).obj clean: rm $(APP).obj

Si utilizara GoLink como en la otra publicación, podría simplemente usar los nombres de la Función API tal como aparecen en los documentos.