Какое состояние регистра по умолчанию при запуске программы (asm, linux)?

Когда программа запускается (linux, elf) - есть ли нули в eax, ebx и т.д. или может быть что угодно (я не делаю никаких вызовов и не использую внешние библиотеки)? На моей машине это действительно так, могу ли я использовать такое поведение при написании asm-программ?


person Community    schedule 05.02.2012    source источник
comment
При нормальных обстоятельствах вы должны инициализировать их явно. Следовательно, не имеет значения, каково их исходное состояние.   -  person Brent Bradburn    schedule 05.02.2012
comment
Я пытаюсь сэкономить несколько байтов в своем исполняемом файле, и я не хочу переносить нули в eax, если я могу этого избежать. Мне нужно поставить 1 в eax, если я использую команду movl, она будет переведена в 5 байтов. Итак, я хочу использовать movb и поставить 1 на al. Результат тот же, команда переведена на 2 байта. Получаю 3 байта выигрыша. Но это можно сделать, только если по умолчанию в eax стоят нули.   -  person    schedule 05.02.2012
comment
При каких обстоятельствах можно сэкономить такое количество кода? Просто инициализируйте их. Если старшие биты EAX не имеют значения, вы можете инициализировать его с помощью movb al, 1, но не беспокойтесь о пробеле.   -  person Ira Baxter    schedule 15.05.2012
comment
Демо-сцена, например) Я знаю о movb al, 1 или что-то вроде xor - но это несколько байтов в кодах операций - так что нет, если я смогу этого избежать - я сделаю так.   -  person    schedule 15.05.2012
comment
Аналогичный вопрос для ARM: stackoverflow.com/questions/1802783/   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 20.04.2015
comment
точно так же, как вы никогда не должны ожидать, что неинициализированная переменная будет равна нулю, вы никогда не должны ожидать, что регистры будут в каком-то состоянии перед использованием, или ram будет в каком-то состоянии. за исключением четко определенных переданных параметров, вы никогда не должны читать что-либо перед записью в это.   -  person old_timer    schedule 17.02.2016


Ответы (3)


Это полностью зависит от ABI для каждой платформы. Поскольку вы упомянули eax и ebx, давайте посмотрим, что происходит с x86. В fs/binfmt_elf.c строке # 972 внутри load_elf_binary() ядро ​​проверяет, указывает ли ABI какой-либо требования к значениям регистров при загрузке программы:

/*
 * 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.
 */

Затем он вызывает ELF_PLAT_INIT, который является макросом, определенным для каждой архитектуры в arch/xxx/include/elf.h. Для x86 он выполняет следующие:

#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)

Итак, когда ваш статически связанный двоичный файл ELF загружается в Linux x86, вы можете рассчитывать, что все значения регистров будут равны нулю. Однако это не значит, что вам следует. :-)


Динамическое связывание

Обратите внимание, что выполнение динамически связанного двоичного файла фактически запускает код динамического компоновщика в вашем процессе до того, как выполнение достигнет вашей _start (точки входа ELF). Это может и действительно оставляет мусор в регистрах, как разрешено ABI. За исключением, конечно, указателя стека ESP / RSP и atexit перехватчика EDX / RDX.

person Michael Foukarakis    schedule 05.02.2012
comment
Это обнуление все еще происходит (2015 г.), но НЕ требуется ABI. (См. Комментарий Чиро к ответу Базиля). - person Peter Cordes; 12.07.2015
comment
Также обратите внимание, что в динамически связанном исполняемом файле динамический компоновщик запускается до _start и оставляет мусор в регистрах, как это разрешено ABI. Регистры только статически связанных исполняемых файлов обнуляются, когда выполнение достигает _start. - person Peter Cordes; 18.09.2017

Для систем AMD64 или x86-64 (64 бит) в Linux x86-64 ABI определяет исходное содержимое регистров.

Аналогичные спецификации существуют для i386 ABI, ARM ABI и т. д.

См. Страницы википедии в ELF и ABI

person Basile Starynkevitch    schedule 05.02.2012

x86-64 System V ABI

3.4.1 Начальный стек и состояние регистрации (Basile связан с PDF-версией этого):

  1. # P3 #
    # P4 #
  2. # P5 #
    # P6 #
  3. # P7 #
    # P8 #
  4. Все остальное не определено.

Затем за ним следует Linux, потому что так сказано в LSB.

person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 06.10.2015
comment
%rdx может быть NULL, а в текущем Linux это 0 в новом процессе из статически связанного исполняемого файла. Но динамический компоновщик запускается до _start при выполнении динамически связанного исполняемого файла, поэтому он может установить значение в %rdx (и это делает, согласно gdb /bin/bash). Я не уверен, должен ли _start по-прежнему рассматривать его как указатель на функцию в этот момент, но, вероятно, да, потому что все остальное в этот момент следует за ABI. - person Peter Cordes; 18.09.2017
comment
ABI i386 (sco.com/developers/devspecs/abi386-4.pdf) предъявляет идентичные требования к соответствующим 32-битным регистрам: %esp, %edx, %ebp, а все остальное не определено. - person pts; 05.01.2018