繁体   English   中英

如何在 godbolt.org 上使用 NASM 程序集调用 printf()?

[英]How to call printf() using NASM assembly on godbolt.org?

尝试在https://godbolt.org/z/G66bdzoof上运行 linux NASM printf() ,但它返回此错误:

ASM 生成编译器返回:0 /usr/bin/ld: /app/example.o:/app/example.asm:14: undefined reference to `printf' 执行构建编译器返回:1

extern printf

global _start

section .data
    message db "Hello World!", 10, 0

section .text

_start:

    ; print message
    push dword message
    call printf 
    add esp, 4 

    ; exit with code 0
    mov eax,1
    mov ebx,0
    int 80h

问题

是否缺少某种编译器选项?

Godbolt 示例使用以下编译选项:

-g -f elf -F stabs /tmp/compiler-explorer-compiler2022626-8227-fdi87r.9yqas/example.asm

问题不在于组装,NASM 执行良好。 问题是与ld链接 编译器资源管理器构建链接到没有库的 static 可执行文件,大概只是ld -m elf_i386 -o foo foo.o

Compiler Explorer UI 只能让您控制nasm选项,而不是ld选项,因此您不能通过-lc链接 C 库。 如果您使用 Godbolt 上的“库”下拉菜单,它会显示“没有为此语言配置库”。(与 C++ 相比,您可以添加诸如 Google::Benchmark 之类的库,告诉它链接;一些库不是仅标题,因此必须实际生成 linker 选项)。


无论如何,您都将希望使用调试器来单步执行您的代码,因此请在本地安装开发设置。 https://www.onlinegdb.com/具有汇编支持,但仅支持 GCC(因此 GAS 语法,AT&T 或 Intel,但不支持 NASM 指令)。

是的,使用调试器基本上是必不可少的。 否则,您只是在浪费自己的时间(如果您要求其他人花时间查看您自己没有单步执行的代码,那么其他人也是如此)。 这就像试图制造一个蒙着眼睛的机器人。 有关 Linux 或 Windows 的 asm 调试技巧,请参阅x86 标签 wiki的底部。 (您当前的程序只能在 Linux 上运行;它使用 32 位int 0x80系统调用 ABI 退出。)


通常,如果您使用 C 库函数,您会想要编写一个main ,并且如果使用像 printf 这样的 stdio 函数,则不要使用原始的_exit系统调用。 使用 output 到 pipe 或网络套接字(不是终端),stdout 将是全缓冲而不是行缓冲,所以当你调用_exit时你不会得到 Z78E6221F6393D1356681DB_exDZ.

但是,即使您编写自己的_start (跳过 CRT 启动代码),与 libc 的链接也可以工作,如果您动态链接,而不是 static。 Linux 上的 glibc 具有动态 linker 钩子,可以让它在_start运行之前自行初始化(与其他一些系统不同,例如 cygwin),但是如果您静态链接,那么您的_start确实是在用户空间中运行的第一条指令。 调用 printf 等依赖于全局stdout等数据结构的函数将崩溃。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM