GCC с опцией -fomit-frame-pointer - PullRequest
       8

GCC с опцией -fomit-frame-pointer

0 голосов
/ 08 августа 2010

Я использую GCC с опциями -fomit-frame-pointer и -O2. Когда я посмотрел сгенерированный код ассемблера,

push %ebp
movl %esp, %ebp

в начале и pop %ebp в конце удаляется. Но некоторые избыточные инструкции subl / addl для esp остаются в - subl $12, %esp в начале и addl $12, %esp в конце.

Как я смогу удалить их, поскольку некоторые встроенные сборки будут jmp работать с другой функцией до того, как addl будет выполнена.

Ответы [ 3 ]

3 голосов
/ 08 августа 2010

Вы, вероятно, не хотите их удалять - обычно это код, который распределяет и освобождает ваши локальные переменные. Если вы удалите их, ваш код будет растоптан по всем адресам возврата и тому подобное.

Единственный безопасный способ избавиться от них - не использовать локальные переменные. Даже в макросах. И будьте очень осторожны с встроенными функциями, поскольку у них часто есть свои собственные местные жители, которые будут вставлены вместе с вашими. Возможно, вы захотите явно отключить встраивание функции для этого раздела кода, если можете.

Если вы абсолютно уверены, что дополнения и сабвуферы не нужны (и я имею в виду действительно, действительно уверен), на моей машине GCC выполняет некоторые манипуляции со стеком, чтобы выровнять стек на границах 16 байт. Вы можете сказать «-mpreferred-stack-border = 2», что будет выравнивать по 4-байтовым границам - что в любом случае любят делать процессоры x86, поэтому код для его выравнивания не генерируется. Работает на моей коробке с моим GCC; int main() { return 0; } превратился в

main: 
    xorl %eax, %eax
    ret

но код выравнивания выглядел по-другому с самого начала ... так что, возможно, это не проблема для вас.

Просто, чтобы вы были предупреждены: оптимизация вызывает много странных вещей, подобных этому. Будьте осторожны с языком ассемблера, написанным вручную, и оптимизированным кодом , особенно когда вы делаете что-то неструктурированное, например, переход из середины одной функции в другую.

1 голос
/ 18 января 2012

Я решил проблему, дав прототип функции, а затем определив ее вручную следующим образом:

void my_function();

asm (
    ".globl _my_function\n"
"_my_function:\n\t"
/* Assembler instructions go here */
);

Позже я также хотел экспортировать функцию, поэтому добавил это в конец исходного файла:

asm (
    ".section  .drectve\n\t"
    ".ascii \" -export:my_function\"\n"
);
0 голосов
/ 08 августа 2010

Как я смогу удалить их, поскольку некоторые встроенные сборки передадут jmp другой функции перед выполнением addl.

Это повредит ваш стек, так что вызывающая сторона ожидает указатель стека набыть исправлено при возврате функции.Другая функция возвращает по инструкции ret ?Что именно вы пытаетесь достичь?может быть, есть другое возможное решение?

Пожалуйста, покажите нам линии вокруг вызова функции (в вызывающей стороне) и вашей части входа / выхода из вашей функции.

...