使用 NASM 进行 Windows x64 汇编编程中未解析的外部符号 printf [英] Unresolved external symbol printf in Windows x64 Assembly Programming with NASM

查看:182
本文介绍了使用 NASM 进行 Windows x64 汇编编程中未解析的外部符号 printf的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近一直在尝试学习汇编,遇到了这个帖子.作者使用NASM和微软链接器搭建汇编环境.我按照相同的步骤安装了 NASM.然后我开始编译 hello world 应用程序.编译成功,但是在链接阶段出现错误.错误如下:

hello_world.obj : error LNK2001: 未解析的外部符号 printfhello_world_basic.exe:致命错误 LNK1120:1 未解析的外部

这是微软链接器(link.exe)的输出.我按照帖子中的描述从开发人员命令提示符运行链接命令,因为 hello world 是一个 64 位应用程序,所以我正确设置了 LIB 环境变量(尽管帖子中没有提到).

hello_world.asm

位 64默认关系段.datamsg db "Hello world!", 0xd, 0xa, 0.text 段全球主要外部退出进程外部输出主要的:推RBPmov rbp, rsp子 rsp, 32lea rcx,[味精]调用 printf异或 rax, rax调用 ExitProcess

在 windows 命令提示符下编译程序.

nasm -f win64 -o hello_world.obj hello_world.asm

设置LIB环境变量.

set LIB=LIB=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\ATLMFC\lib\x86;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\lib\x64;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\lib\um\x86;C:\Program Files (x86)\Windows Kits\10\lib\10.0.19041.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\lib\10.0.19041.0\um\x64>

并链接到可执行文件.

link hello_world.obj/subsystem:console/entry:main/out:hello_world_basic.exe KERNEL32.LIB"

有什么问题?有什么我错过的吗?

解决方案

根据链接 Microsoft 已将一些标准 C 内容移至另一个库中 @Jester 共享.

<块引用>

所有 printf 和 scanf 函数的定义已内联移动到 <stdio.h>、<conio.h> 和其他 CRT 头文件中.对于在本地声明这些函数而不包含适当的 CRT 标头的任何程序,此重大更改会导致链接器错误(LNK2019,未解析的外部符号).如果可能,您应该更新代码以包含 CRT 标头(即,添加 #include<stdio.h>) 和内联函数,但如果您不想修改代码以包含这些头文件,另一种解决方案是在链接器输入中添加一个额外的库 legacy_stdio_definitions.lib.

因此您需要链接 legacy_stdio_definitions.lib 以实现 printf 并且还需要初始化 CRT,因此将源代码更改为,

位 64默认关系段.datamsg db "Hello world!", 0xd, 0xa, 0.text 段全球主要外部退出进程外部_CRT_INIT外部输出主要的:推RBPmov rbp, rsp子 rsp, 32调用_CRT_INITlea rcx,[味精]调用 printf异或 rax, rax调用 ExitProcess

最后,按如下方式运行链接器.

link hello_world.obj/subsystem:console/entry:main/out:hello_world_basic.exe kernel32.lib legacy_stdio_definitions.lib msvcrt.lib

I've been trying to learn assembly lately, and came across this post. The author used NASM and Microsoft linker to set up the assembly environment. I followed the same steps and installed NASM. Then I started to compile the hello world application. The compilation is successful, but I get an error at the link stage. The error is as follows:

hello_world.obj : error LNK2001: unresolved external symbol printf
hello_world_basic.exe : fatal error LNK1120: 1 unresolved external

This is the output of microsoft linker(link.exe). I run the link commands from Developer Command Prompt as described in the post, and because hello world is a 64-bits application I set the LIB environment variable correctly (even though not mentioned on the post ).

hello_world.asm

bits 64
default rel

segment .data
   msg db "Hello world!", 0xd, 0xa, 0

segment .text
global main
extern ExitProcess
extern printf




main:
   push    rbp
   mov     rbp, rsp
   sub     rsp, 32

   lea     rcx, [msg]
   call    printf

   xor     rax, rax
   call    ExitProcess

To compile the program on windows command prompt.

nasm -f win64 -o hello_world.obj hello_world.asm

To set LIB environment variable.

set LIB=LIB=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\ATLMFC\lib\x86;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\lib\x64;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\lib\um\x86;C:\Program Files (x86)\Windows Kits\10\lib\10.0.19041.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\lib\10.0.19041.0\um\x64

And to link into an executable.

link hello_world.obj /subsystem:console /entry:main /out:hello_world_basic.exe "KERNEL32.LIB"

What is the problem? Is there anything I missed?

解决方案

According to the link Microsoft has moved some standard C stuff into another library @Jester shared.

The definitions of all of the printf and scanf functions have been moved inline into <stdio.h>, <conio.h>, and other CRT headers. This breaking change leads to a linker error (LNK2019, unresolved external symbol) for any programs that declared these functions locally without including the appropriate CRT headers.If possible, you should update the code to include the CRT headers (that is, add #include <stdio.h>) and the inline functions, but if you do not want to modify your code to include these header files, an alternative solution is to add an additional library to your linker input, legacy_stdio_definitions.lib.

Thus you need to link legacy_stdio_definitions.lib for the implementation of printf and also need to initialize CRT so change source code to,

bits 64
default rel

segment .data
    msg db "Hello world!", 0xd, 0xa, 0

segment .text
global main
extern ExitProcess
extern _CRT_INIT

extern printf

main:
    push    rbp
    mov     rbp, rsp
    sub     rsp, 32

    call    _CRT_INIT

    lea     rcx, [msg]
    call    printf

    xor     rax, rax
    call    ExitProcess

And finally, run the linker as follow.

link hello_world.obj /subsystem:console /entry:main /out:hello_world_basic.exe kernel32.lib legacy_stdio_definitions.lib  msvcrt.lib

这篇关于使用 NASM 进行 Windows x64 汇编编程中未解析的外部符号 printf的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆