Как связать универсальный ЭЛТ Windows с файлом obj, скомпилированным с помощью nasm

Окружение: Windows 10. Я использую версию MinGW ld для связи, но я счастлив использовать визуальную студию 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

При попытке связать его с Windows CRT (ucrt.lib), я получаю следующую ошибку:

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

Итак, мне нужно указать компоновщик на библиотеку 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'

Попробуем аналог с визуальным компоновщиком студии:

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? Я понимаю, что есть соглашение о подчеркивании, но оно не понимается обоими компоновщиками.

  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 появляется в списке. Значит ли это, что эта библиотека не экспортируется? Если нет, на какую библиотеку я должен ссылаться?

Согласно этой статье MS, ucrt.lib является де-факто библиотекой для среды выполнения c и стандартной библиотеки C.

1 ответ

Решение

Благодаря комментарию Майкла Петча, похоже, мне нужно вручную связать 1 или несколько дополнительных библиотек, которые находятся в совершенно отдельном месте от ucrt.lib библиотека. Соответствующим для printf является legacy_stdio_definitions.lib, который я нашел в поддиректории моего каталога установки VS2017, в отличие от ucrt.lib который находится в каталоге установки Windows SDK.

Определение printf предоставляется встроенным в stdio.h если макрос _NO_CRT_STDIO_INLINE определяется, что я думаю, это обычно при сборке внутри VS Toolchain.

Другие вопросы по тегам