【问题标题】:x86 Assembly - printf doesn't print without "\n"x86 程序集 - printf 不打印没有“\n”
【发布时间】:2025-12-25 16:30:11
【问题描述】:

所以我很困惑。我正在阅读“从头开始编程”一书,并且正在使用库。

只要我在字符串中包含一个“\n”,printf 就可以正常工作,但是没有它,它绝对不会打印任何内容。

知道为什么会这样吗?

代码:

.section .data 我的字符串: .ascii "Jimmy Joe 已经 %d 岁了!\n\0" 我的号码: .long 76 .section .text .globl _start _开始: pushl my_num 推力 $my_str 调用 printf 移动 $1, %eax 移动 $0, %ebx 诠释 $0x80

另外,当我将 -m elf_i386 用于 32 位模式并使用 -dynamic-linker /lib/ld-linux.so.2 -lc 进行链接时,我会收到警告

ld:搜索 -lc 时跳过不兼容的 /usr/lib64/libc.so

如果这有什么不同,或者如果有人对如何让它直接加载 32 位库有任何建议。

谢谢!

【问题讨论】:

  • 您的printf 代码在哪里?如果它在库中,您检查过 API 文档吗?
  • @MikeW 老实说,我不确定如何检查它是从哪里加载的。我附加了如何将库链接到 OP。我已经尝试寻找任何类似的问题或如何修复链接警告,但我发现不足。我发现很难搜索所有不同版本的汇编帮助。
  • 在C语言中,如果程序结束时没有输出\n,是否出现输出到stdout的字符是由实现定义的。由于您可能从 C 库中调用 printf,您可能会得到相同的行为
  • 由于您正在调用exit 系统调用,标准库无法知道该进程即将被拆除,所以如果它还没有刷新它的缓冲区,它是永远不会。

标签: linux assembly x86 printf


【解决方案1】:

问题是printf 默认情况下只是将内容打印到标准输出缓冲区中。在刷新缓冲区之前,实际上不会打印内容。取决于标准输出的缓冲模式,但默认情况下,它是行缓冲的,这意味着每次打印换行符时都会刷新。

要在 C 中显式刷新,请调用 fflush;您可以在 asm 代码中使用

pushl stdout
call fflush
addl $4, %esp

或者,您可以调用 stdlib exit 函数(在实际退出之前刷新所有 I/O 缓冲区),而不是使用 _exit 系统调用,后者不会。

【讨论】:

    【解决方案2】:

    您似乎试图将您的 32 位程序与(系统默认)64 位 c 库链接。 检查您是否安装了 libs32 软件包。 要找出程序或其他从 LD_LIBRARY_PATH 动态加载的库,请使用 ldd <name_of_your_binary> 至于为什么需要换行符,我只能推测它会刷新输出缓冲区。 另见Why does printf not flush after the call unless a newline is in the format string?

    【讨论】: