Значение заполнения функции GCC - PullRequest
6 голосов
/ 20 декабря 2010

Всякий раз, когда я компилирую код C или C ++ с включенной оптимизацией, d GCC выравнивает функции по 16-байтовой границе (в IA-32).Если функция короче 16 байтов, GCC дополняет ее некоторыми байтами, которые не кажутся случайными вообще:

19:   c3                      ret
1a:   8d b6 00 00 00 00       lea    0x0(%esi),%esi

Кажется, что всегда либо 8d b6 00 00 00 00 ..., либо 8d 74 26 00.

Имеют ли значение байты заполнения функции?

Ответы [ 3 ]

7 голосов
/ 20 декабря 2010

Обивка создается ассемблером, а не gcc. Он просто видит директиву .align (или эквивалентную) и не знает, находится ли пространство, которое должно быть дополнено, внутри функции (например, выравнивание цикла) или между функциями, поэтому он должен вставить NOP s некоторого вида. Современные ассемблеры x86 используют как можно больше операционных кодов NOP с намерением потратить как можно меньше циклов, если заполнение предназначено для выравнивания циклов.

Лично я крайне скептически отношусь к выравниванию как к технике оптимизации. Я никогда не видел, чтобы это сильно помогало, и это может определенно повредить, если значительно увеличить общий размер кода (и использование кэша). Если вы используете уровень оптимизации -Os, он по умолчанию отключен, так что вам не о чем беспокоиться. В противном случае вы можете отключить все выравнивания с соответствующими параметрами -f.

2 голосов
/ 09 сентября 2011

Ассемблер сначала видит директиву .align. Поскольку он не знает, находится ли этот адрес в теле функции или нет, он не может вывести NULL 0x00 байтов и должен генерировать NOP s (0x90).

Тем не менее:

lea    esi,[esi+0x0] ; does nothing, psuedocode: ESI = ESI + 0

выполняется за меньшее количество тактов, чем

nop
nop
nop
nop
nop
nop

Если бы этот код попал в тело функции (например, выравнивание цикла), версия lea была бы намного быстрее, но при этом "ничего не делала".

2 голосов
/ 20 декабря 2010

Инструкция lea 0x0(%esi),%esi просто загружает значение в %esi в %esi - это бездействие (или NOP), что означает, что если оно выполнится, оно не будет иметь эффекта.

Это просто одна инструкция, 6-байтовая NOP. 8d 74 26 00 - это всего лишь 4-байтовая кодировка той же инструкции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...