我正在研究 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_stdin
部分与 ebx
, ecx
或 edx
,二进制变大:$ wc -c main
268 main
比较目标文件的大小时,差异甚至更大(480 与 496 字节)。
eax
有什么特别之处注册发生这种情况?尽管-O0
NASM 是否在进行某种优化?已指定?
最佳答案
EAX 是累加器寄存器。它具有适用于所有九种基本操作(ADD、ADC、AND、CMP、OR、SBB、SUB、TEST 和 XOR)的特殊一字节操作码。此外,MOV 指令有一个一字节的操作码,用于将数据从一个常量内存位置移动到累加器中。
The Art of Picking Intel Registers
关于assembly - ASM 空间优化 : EAX vs EBX,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23413138/