What is the default register state when program launches (asm, linux)?

This depends entirely on the ABI for each platform. Since you mention eax and ebx let’s see what’s the case for x86 (as of Linux v5.17.5). In fs/binfmt_elf.c, inside load_elf_binary(), the kernel checks if the ABI specifies any requirements for register values at program loading:

/*
 * The ABI may specify that certain registers be set up in special
 * ways (on i386 %edx is the address of a DT_FINI function, for
 * example.  In addition, it may also specify (eg, PowerPC64 ELF)
 * that the e_entry field is the address of the function descriptor
 * for the startup routine, rather than the address of the startup
 * routine itself.  This macro performs whatever initialization to
 * the regs structure is required as well as any relocations to the
 * function descriptor entries when executing dynamically links apps.
 */

It then calls ELF_PLAT_INIT, which is a macro defined for each architecture in arch/xxx/include/elf.h. For x86, it does the following:

#define ELF_PLAT_INIT(_r, load_addr)        \
    do {                                    \
        _r->bx = 0; _r->cx = 0; _r->dx = 0; \
        _r->si = 0; _r->di = 0; _r->bp = 0; \
        _r->ax = 0;                         \
    } while (0)

So, when your statically-linked ELF binary is loaded on Linux x86, you could count on all register values being equal to zero. Doesn’t mean you should, though. 🙂


Dynamic linking

Note that executing a dynamically linked binary actually runs dynamic linker code in your process before execution reaches your _start (ELF entry point). This can and does leave garbage in registers, as allowed by the ABI. Except of course for the stack pointer ESP/RSP and atexit hook EDX/RDX.

Leave a Comment