【问题标题】:Getting printf in assembly with only system calls?仅通过系统调用将 printf 组装成汇编?
【发布时间】:2016-04-30 01:28:31
【问题描述】:

我希望了解汇编级别的 printf() 语句。然而,大多数汇编程序都执行类似调用外部打印函数的操作,该函数的依赖关系由链接器添加的其他目标文件来满足。我想知道打印函数内部的系统调用和非常基本的汇编代码。我想要一段汇编代码,其中唯一的外部调用是系统调用,用于 printf。我正在考虑类似反汇编目标文件的东西。我在哪里可以买到这样的东西??

【问题讨论】:

  • 在大多数情况下,printf() 代码只是通过 putchar() 调用 OS write()。
  • 但是我怎么可能在我的 linux 上反汇编一些东西,看看它是如何完成的......???所以 putchar() 只是一个 write()??

标签: c operating-system system-calls object-files


【解决方案1】:

我建议先停留在 C 级别,然后研究一些现有 C 标准库 free software 在 Linux 上的实现的源代码。查看musl-libcGNU libc(又名glibc)的源代码。您将了解在printf 和基本系统调用(在syscalls(2) ...中列出)之间有几个中间(通常是内部)函数很有用。在执行 printf 的示例 C 程序上也使用 strace(1)(例如,通常的 hello-world 示例)。

特别是,musl-libc 有一个非常易读的stdio/printf.c 实现,但是在到达write(2) 系统调用之前,您需要遵循其他几个C 函数。请注意,其中涉及一些buffering。另见setvbuf(3)fflush(3)。几个答案(例如thisthat 一个)解释了printf 等函数和系统调用(直至内核代码)之间的链。

我想要一段汇编代码,其中唯一的外部调用是系统调用,用于printf

如果你想要那样的话,你可以从 musl-libcstdio/printf.c 开始,从musl-libc 添加任何额外的源文件,直到你没有更多的外部未定义符号,然后编译所有其中gcc -flto -O2 可能还有-S,您可能会以对象(或程序集)形式完成musl-libc 的重要部分(因为printf 可能会调用malloc 和许多其他功能!)...我不确定这是否值得。

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


为了挑剔,system calls 实际上并不是外部调用(您的 libc write 函数实际上是原始系统调用的一个小包装器)。您可以使用SYSENTER 机器指令来制作它们(但最好使用vdso(7):更便携,也许更快),并且您甚至不需要有效的堆栈指针(在 x86_64 上)来进行系统调用。

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

【讨论】:

    【解决方案2】:

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

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

    也许您正在寻找write(2),这是系统调用,用于将仅字节的无缓冲写入文件描述符。您必须事先生成要打印的字符串并自行格式化。 (有关打开文件,另请参阅 open(2)。)

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

        objdump -d binary
    

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

    您可以在您的系统上反汇编标准 C 二进制文件,并尝试根据需要对其进行解释(强烈不推荐)。问题是它太复杂而无法理解。 printf() 之类的东西是用 C 语言编写的,然后编译和组装。您不能(在合理的几十年内)从已编译(非平凡)程序的程序集中恢复高级结构。如果你真的想试试这个,祝你好运。

    更简单的做法是查看printf() 本身的C 源代码。真正的工作实际上是在vfprintf() 中完成的,它位于GNU C 库source codestdio-common/vfprintf.c 中。

    【讨论】:

    • 我不想重新实现它,我知道为什么要这样做。我只是想看看它是如何实现的......
    • “在标准 C 库中,所以它链接到你的程序中而不是复制到它” 不一定正确。许多较旧的系统链接整个运行时库以构建可执行文件。可共享的动态链接库是一项相对较新的创新。由于 OP 没有指定任何特定环境,因此假设现代高效环境是不准确的。
    猜你喜欢
    • 2016-01-16
    • 2010-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-20
    • 1970-01-01
    • 1970-01-01
    • 2018-10-01
    相关资源
    最近更新 更多