GCC NOPs компилируется

Выход из моего обычного царства VC++ в мир GCC (через MINGW32). Попытка создать Windows PE, которая состоит в основном из NOP, аля:

for(i = 0; i < 1000; i++)
{
    asm("nop");
}

Но либо я использую неправильный синтаксис, либо компилятор оптимизирует их, потому что эти NOP не выживают в процессе компиляции.

Я использую флаг -O0, в противном случае по умолчанию. Любые идеи о том, как я могу уговорить компилятор оставить нетронутыми NOP?

4 ответа

Решение

Ожидаете ли вы, чтобы развернуть цикл до 1000 nops? Я сделал быстрый тест с gcc и я не вижу (один) nop исчезают:

        xorl    %eax, %eax
        .p2align 4,,7
.L2:
#APP
        nop
#NO_APP
        addl    $1, %eax
        cmpl    $1000, %eax
        jne     .L2

С gcc -S -O3 -funroll-all-loops Я вижу это развернуть цикл 8 раз (таким образом, 8 nop) но я думаю, что если вы хотите 1000, это будет проще всего сделать:

#define NOP10() asm("nop;nop;nop;nop;nop;nop;nop;nop;nop;nop")

А потом использовать NOP10(); ...

Удобный способ получить 1000 инлайн nops - использовать .reptдиректива ассемблера GNU:

void thousand_nops(void) {
    asm(".rept 1000 ; nop ; .endr");
}

Примерьте Godbolt.

Этот недавний вопрос о цикличности до 1000 без условий привел к умному ответу с использованием рекурсии шаблона, который фактически может быть использован для создания вашей 1000 nop функция без повторения asm("nop") совсем. Есть несколько предостережений: если вы не получите компилятор для встроенной функции, вы получите 1000-глубокий рекурсивный стек отдельных nop функции. Также, gccПредельное значение глубины шаблона по умолчанию равно 500, поэтому вы должны явно указать более высокий предел (см. ниже, хотя вы можете просто избежать превышения nop<500>()).

// compile time recursion
template<int N> inline void nop()
{
    nop<N-1>();
    asm("nop");
}

template<> inline void nop<0>() { }

void nops()
{
    nop<1000>();
}

Составлено с:

 g++ -O2 -ftemplate-depth=1000 ctr.c

в дополнение к ответу @BenJackson, он может рекурсировать с гораздо меньшей глубиной за счет (двоичного) деления.

      template<unsigned int N> inline void nop()
{
    nop<N/2>();
    nop<N/2>();
    nop<N-2*(N/2)>();
}

template<> inline void nop<0>() { }
template<> inline void nop<1>() { asm("nop"); }
Другие вопросы по тегам