4

我正在研究一个 x86 汇编代码高尔夫拼图。我正在使用 NASM 组装源文件:

nasm -f elf32 -O0 main.s
ld -m elf_i386 -s -O0 -o main main.o

使用-O0,应关闭所有优化。目标是减小 ELF 二进制文件的大小。

在为这个谜题开发“参考实现”时,我偶然发现了一个奇怪的行为。这是一个简化的代码示例:

section .text
    global _start        ; Must be declared for linker

_start:                  ; Entry point for linker

read_stdin:
    add    esp, 8        ; Ignore argc and argv[0] on stack
    pop    eax           ; Store pointer to 'argv[1]' into EAX
    mov    eax, [eax]    ; Dereference pointer
    and    eax, 0xff     ; We only want the least significant byte
    add    eax, -0x30    ; Subtract ascii offset

exit:
    mov    eax, 1        ; Syscall: sys_exit
    mov    ebx, 0        ; Exit code 0
    int    0x80          ; Invoke syscall

二进制是 264 字节:

$ wc -c main
264 main

现在,当我简单地将部分eax中的所有出现替换为,或时,二进制文件会变大:read_stdinebxecxedx

$ wc -c main
268 main

在比较目标文件的大小时,差异更大(480 对 496 字节)。发生这种情况的寄存器有什么特别之处eax?NASM 是否在进行某种优化,即使-O0已指定?

4

1 回答 1

10

EAX 是累加器寄存器。它具有用于所有九种基本操作(ADD、ADC、AND、CMP、OR、SBB、SUB、TEST 和 XOR)的特殊一字节操作码。MOV 指令还有一个单字节操作码,用于将数据从一个恒定的内存位置移动到累加器中。

挑选英特尔寄存器的艺术

于 2014-05-01T17:45:08.097 回答