ld MinGW链接到标准C库

时间:2013-09-14 17:57:42

标签: windows assembly x86 mingw nasm

我遇到以下代码问题。

extern printf
global _main
main:
push msg
call printf
ret
msg db "Hello world",0

我使用nasm -fwin32 test.asm将其与NASM组合在一起然后我使用ld test.obj链接它。 它告诉我“test.obj:test.asm:(text+0x6): undefined reference to 'printf'

如何将我的文件链接到标准C库?我来自最新的MinGW。

3 个答案:

答案 0 :(得分:4)

汇编代码:

nasm -fwin32 test.asm

Microsoft将使用带有下划线的cdecl调用约定为函数添加前缀 要与C调用约定printf匹配,应为_printf 这同样适用于_main而非main

并链接:

  

ld test.obj -lmsvcrt -entry = _main -subsystem = console -o test.exe

此处-entry命令行选项用于调用 ld 以指定程序的入口点。
然后使用-l选项将msvcrt库传递给 ld 链接器,否则会收到错误消息,(对'printf'的未定义引用 )这意味着链接器未在NASM生成的指定目标文件中找到符号printf。

以下是完整的来源:

global  _main
extern  _printf
section .text
_main:
push msg
call _printf
add esp, 4 ;adjust the stack
ret
msg db "Hello world",0

答案 1 :(得分:1)

我可以看到您的代码有几个问题。首先,您在global _main上有一个下划线,但在main:上没有。这些应该匹配。您可以在整个过程中使用下划线,或者 - 我会做什么 - 根本不使用...而对于Windows,汇编为nasm -f win32 --prefix _ test.asm。这将使其“可移植”,对于Linux来说,它会组装,没有--prefix _没有下划线。 Linux不会在globalextern符号上使用下划线。如果您有可能使用OpenWatcom C,则可以使用--postfix _。是的,OpenWatcom使用尾随下划线。是的,我知道他们告诉我们C是标准化的。但是一旦你陷入困境,这就不是真的了。

另一个大问题是,在调用_printf之后,您需要add esp, 4(或pop虚拟寄存器)来“清理堆栈”。如果您使用的是Windows API,它们会使用“callee清理”的STDCALL调用约定,因此您不希望这样做。混合C调用(CDECL调用约定)和Windows API可能会让人感到困惑,但应该可以正常工作。

我认为卡尔有正确的想法使用gcc链接它。没有什么可以“编译”,但是gcc知道ld的正确命令行。 gcc -o test.exe test.obj可能就足够了(如果最新的MinGW希望使用64位代码,可能会添加-m32)。这将链接一些调用_main的“启动代码”。这会稍微增加你的可执行文件的大小,你可能“没有它”就可以相处,但是这样做更容易。

在Linux中,我们可以直接使用ld(命令行是可怕的),但是ld正在寻找_start而不是main作为入口点。我们可以告诉ld -e main,但是这个入口点没有被调用(!),并且没有办法从它ret开始! Windows中的情况可能有所不同。你需要 - 至少 - -lc告诉ld我们想要那些C库。最容易“让gcc这样做” - 它不会触及您的.asm代码(但会链接到“启动代码”)。快乐的Hello World! :)

答案 2 :(得分:0)

使用编译器前端链接:

cc test.obj

如果您确实想直接使用ld(而您不应该),请使用-v标记cc来确定完整的命令你需要的线。例如,在我的机器上,它是:

ld -demangle -dynamic -arch x86_64 -macosx_version_min 10.8.0 \
  -o a.out test.obj -lSystem                                  \
  /usr/bin/../lib/clang/4.2/lib/darwin/libclang_rt.osx.a

如果我使用GCC而不是Clang,它甚至更疯狂:

ld -dynamic -arch x86_64 -macosx_version_min 10.8.4 -weak_reference_mismatches                             \
  non-weak -o a.out -lcrt1.10.6.o                                                                          \
  -L/usr/llvm-gcc-4.2/bin/../lib/gcc/i686-apple-darwin11/4.2.1/x86_64                                      \
  -L/Applications/Xcode.app/Contents/Developer/usr/llvm-gcc-4.2/lib/gcc/i686-apple-darwin11/4.2.1/x86_64   \
  -L/usr/llvm-gcc-4.2/bin/../lib/gcc/i686-apple-darwin11/4.2.1                                             \
  -L/usr/llvm-gcc-4.2/bin/../lib/gcc                                                                       \
  -L/Applications/Xcode.app/Contents/Developer/usr/llvm-gcc-4.2/lib/gcc/i686-apple-darwin11/4.2.1          \
  -L/usr/llvm-gcc-4.2/bin/../lib/gcc/i686-apple-darwin11/4.2.1/../../..                                    \
  -L/Applications/Xcode.app/Contents/Developer/usr/llvm-gcc-4.2/lib/gcc/i686-apple-darwin11/4.2.1/../../.. \
  test.obj -lgcc -lSystem