如何link Windows universal CRT to obj file compiled with nasm

How to link Windows universal CRT to obj file compiled with nasm

环境:Windows 10. 我碰巧使用 ld 的 MinGW 版本进行 linking,但我很高兴使用 visual studio link.exe 如果它能让事情变得更简单。

我在nasm中有以下基本程序:

    global  _main
    extern  _printf

    section .text
_main:
    push    message
    call    _printf
    add     esp, 4
    ret
message:
    db  'Hello, World', 10, 0

并且使用

构建良好
nasm -f win32 test.nasm

当试图 link 它到 windows CRT (ucrt.lib) 时,我收到以下错误:

$ ld -o test.exe test.obj
test.obj:test.nasm:(.text+0x6): undefined reference to `printf'

好的,所以我需要将 linker 指向 ucrt 库:

$ ld -o test.exe /c/Program\ Files\ \(x86\)/Windows\ 
Kits/10/Lib/10.0.14393.0/ucrt/x86/ucrt.lib test.obj
test.obj:test.nasm:(.text+0x6): undefined reference to `printf'

尝试使用 visual studio linker 的等价物:

d:\Code\nasm>link -out:test.exe -entry:main -subsystem:console test.obj
Microsoft (R) Incremental Linker Version 14.10.25017.0
Copyright (C) Microsoft Corporation.  All rights reserved.

test.obj : error LNK2001: unresolved external symbol _printf
test.exe : fatal error LNK1120: 1 unresolved externals

这提出了几个问题:

  1. 为什么其中一个试图找到 printf 而另一个 _printf?我知道有一个下划线约定,但 link 两个人似乎都不理解。

  2. 我用objdump -t查看了ucrt.lib文件中的符号。我不会粘贴整个列表,但它包含如下条目:

[ 4](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 __imp____conio_common_vcprintf

[ 5](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 ___conio_common_vcprintf

[ 4](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 __imp____conio_common_vcprintf_p

printf_printf 均未出现在列表中。这是否意味着它不是由该库导出的?如果不是,我应该 linking 哪个图书馆?

根据this MS articleucrt.lib是c运行时和C标准库的实际库。

感谢 Michael Petch 的评论,看来我需要手动 link 1 个或多个额外的库,这些库位于与 ucrt.lib 库完全不同的位置。与 printf 相关的是 legacy_stdio_definitions.lib,我在 VS2017 安装目录的子目录深处找到了它,而不是 Windows SDK 安装目录中的 ucrt.lib

printf 的定义在 stdio.h 中内联提供,除非定义了宏 _NO_CRT_STDIO_INLINE,我猜这通常是在 VS 工具链内部构建时定义的。