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
これが起こるレジスターの何が特別なのですか?NASM は指定されていますが、何らかの最適化を行っ-O0
ていますか?