assembly - 这个 Linux/32 位 x86 程序集 "Hello, World"还能做得更小吗?

标签 assembly code-golf

以下 32 位 x86 Linux 程序打印任意长度的字符串(只要程序可以,无论如何)并执行 exit(0)然后:

.global _start             ; notice on entry here, all regs but %esp are zero
_start:
    call  .L0              ; offset == strlen, provided by your assembler
.byte 'H','e','l','l','o',',',' ','W','o','r','l','d'
.L0:
    pop   %ecx             ; ret addr is starting addr of string
    mov   -4(%ecx),%edx    ; argument to `call`, 4 bytes: strlen
    inc   %ebx             ; stdout == 1
    movb  $4, %al          ; SYS_write == 4
    int   $0x80
    xchg  %eax,%ebp        ; %ebp is still zero
    xchg  %eax,%ebx        ; SYS_exit == 1, return value == 0
    int   $0x80

如果愿意牺牲位置独立性(相反,强制链接器插入字符串地址),而不关心程序返回零,则可以将其归结为:
.global _start
_start:
    movb  $4, %al
    inc   %ebx
    mov   $.L0, %ecx       ; this address is calculated when linking
    movb  $.Lend-.L0, %dl  ; strlen, calculated by assembler
    int   $0x80
    xchg  %eax,%ebx
    int   %0x80
.L0:
.byte 'H','e','l','l','o',',',' ','W','o','r','l','d'
.Lend:

这两者都可以通过 as --32 -o x.o x.S; ld -s -m elf_i386 x.o 组装/链接,并且运行得很好。第二个是 26 字节的代码。如果您在打印后允许崩溃 Hello, World然后留下最后两条指令,23 字节。这是我所能达到的最低限度。

一直困扰着我的问题是,是否有可能从中挤出更多字节?我的纯推测给出了这些可能的线索:
  • 以某种方式使用“Hello, World”本身的部分作为代码?
  • 有人知道一个可用的系统调用复活节彩蛋吗?
  • 欺骗链接器使入口点成为 16 位地址,以便 movw $.L0, %cx可以使用(节省一个字节)?
  • 做一个 8 位偏移 jmp到一个已知的地方(或通过汇编程序/链接器调用魔术创建)包含 exit(...) 的必要指令系统调用,在 xchg; int 上节省了一个字节序列 ?

  • 或者,能否证明这实际上是最小的表现良好(无崩溃/返回码为零)Linux/x86“Hello, World”?

    编辑

    澄清一下,问题不在于最小化 ELF 可执行文件的大小;这方面的技术早已为人所知。我正在明确询问 Linux 32 位 x86 汇编程序的大小,该程序执行的编译代码相当于:
    int main(int argc, char **argv)
    {
        puts("Hello, World");
        exit(0); /* or whatever code */
    }
    

    会做。
    事实上,我会对不需要手动编辑 ELF header 的任何内容感到高兴。如果你找到一种方法,例如东西"Hello, World"进入一些 ELF 对象并从汇编源引用它,仅使用汇编器/链接器命令行和/或映射文件输入,我认为它足够有效,即使这会增加 ELF 可执行文件的大小。我只想知道打印“Hello, World”和exit()的指令序列是否之后仍然可以缩小。
    问题是关于代码大小,而不是可执行文件大小。

    最佳答案

    早在 1999 年就已经完成了。看看 this page (剧透:最终结果是一个 45 字节的 ELF 文件)。请务必阅读 the postscript也。

    关于assembly - 这个 Linux/32 位 x86 程序集 "Hello, World"还能做得更小吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7434333/

    相关文章:

    assembly - 堆栈大小的使用上限是否有限制?

    assembly - 为什么编译器要在寄存器分配中构造图?

    code-golf - Code Golf : find all anagrams

    javascript - 将 Coffeescript 中的 true 和 false 分别转换为 1 和 -1

    language-agnostic - Code Golf - π 天

    c - 在 Linux : unconsumed input is sent to bash 中使用系统调用 READ 读取 STDIN

    assembly - 是否真的需要RBP/EBP寄存器来支持可变大小堆栈帧?

    algorithm - Code Golf : Validate Sudoku Grid

    language-agnostic - 高尔夫代码:1x1黑色像素

    c - 循环组件 x86