I am working on a puzzle to build x86 code. I compile the source file using NASM:
nasm -f elf32 -O0 main.s
ld -m elf_i386 -s -O0 -o main main.o
Using -O0, all optimizations should be disabled. The goal is to reduce the size of the ELF binary.
While working on the "reference implementation" for the puzzle, I came across strange behavior. This is a sample code:
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
The binary file is 264 bytes:
$ wc -c main
264 main
Now, when I just replace all the occurrences eaxin a section read_stdin ebx, ecxor edx, the binary becomes larger:
$ wc -c main
268 main
When comparing the sizes of object files, the difference is even greater (480 versus 496 bytes). What is so special about eaxregistering that this is happening? Is NASM some kind of optimization although it has been specified -O0?