仅通过系统调用在汇编中获取 printf?

Getting printf in assembly with only system calls?

我想了解汇编级别的 printf() 语句。然而,大多数汇编程序会做一些事情,比如调用外部打印函数,其依赖性由链接器添加的其他目标文件满足。我想知道在系统调用和非常基本的汇编代码方面打印函数内部是什么。我想要一段汇编代码,其中唯一的外部调用是 printf 的系统调用。我在想类似反汇编目标文件的东西。我在哪里可以买到这样的东西??

函数 printf() 在标准 C 库中,因此它链接到您的程序中,而不是复制到其中。动态链接库可以节省内存,因为您不会为每个使用它的程序在常驻内存中复制完全相同的代码。

想想 printf() 是做什么的。解释格式化字符串并生成正确的输出是相当复杂的。 printf()所属的一系列函数也缓冲了输出。您可能真的不想 re-implement 所有这些都在汇编中。标准 C 库无处不在,您可能也可以使用。

也许您正在寻找 write(2), which is the system call for unbuffered writes of just bytes to a file descriptor. You'd have to generate the string to print beforehand and format it yourself. (See also open(2) 来打开文件。)

要反汇编二进制文件,您可以使用objdump:

    objdump -d binary

其中 binary 是一些已编译的二进制文件。这给出了操作码和人类可读的指令。您可能想重定向到一个文件并在其他地方阅读。

您可以在您的系统上反汇编标准 C 二进制文件,如果您愿意,可以尝试解释它(强烈不推荐)。问题是它太复杂了,难以理解。 printf() 之类的东西是用 C 写的,然后编译和汇编。您不能(在合理的几十年内)从已编译 (non-trivial) 程序的汇编中恢复高级结构。如果你真的想试试这个,祝你好运。

更简单的方法是查看 printf() 本身的 C 源代码。真正的工作实际上是在 GNU C 库 source code.

stdio-common/vfprintf.c 中完成的 vfprintf()

我建议先停留在 C 级别,然后研究一些现有 C 标准库的源代码 free software implementation on Linux. Look into the source code of musl-libc or of GNU libc (a.k.a. glibc). You'll understand that several intermediate (usually internal) functions are useful between printf and the basic system calls (listed in syscalls(2) ...). Use also strace(1) 在示例 C 程序上执行 printf(例如通常的 hello-world 示例)。

特别是,musl-libc 有一个非常可读的 stdio/printf.c implementation, but you'll need to follow several other C functions there before reaching the write(2) syscall. Notice that some buffering is involved. See also setvbuf(3) & fflush(3). Several answers (e.g. and that 解释函数之间的链 printf 和系统调用(直到内核代码)。

I want a piece of assembly code where the only external calls are the system calls, for printf

如果你真的想要那个,你可以从musl-libcstdio/printf.c, add any additional source file from musl-libc开始,直到你没有更多的外部未定义符号,然后编译所有它们带有 gcc -flto -O2,也许还有 -S,您可能会以对象(或程序集)形式的 musl-libc 的重要部分结束(因为 printf 可能会调用 malloc 和许多其他函数!)...我不确定这是否值得。

您也可以静态 link 您的 libc(例如 libc.a)。然后 linker 将 link 仅 printf(以及您正在调用的任何其他函数)所需的静态库成员。


为了挑剔,system calls are not actually external calls (your libc write function is actually a tiny wrapper around the raw system call). You could make them using SYSENTER machine instructions (but using vdso(7) 更可取:更便携,也许更快),您甚至不需要有效的堆栈指针(在 x86_64 上)来进行系统调用。

你甚至可以不使用 libc 编写 Linux user-level 程序; bones Scheme 的实现就是这样一个程序(你会找到其他程序)。