GCC 内联 asm NOP 循环在编译时未展开

发布于 2024-10-09 19:03:34 字数 264 浏览 9 评论 0原文

走出我通常的 VC++ 领域,进入 GCC 的世界(通过 MINGW32)。试图创建一个主要由 NOP 组成的 Windows PE,唉:

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

但是要么我使用了错误的语法,要么编译器正在通过它们进行优化,因为这些 NOP 无法在编译过程中幸存下来。

我使用 -O0 标志,否则使用默认值。关于如何让编译器保持 NOP 完好无损,有什么想法吗?

Venturing out of my usual VC++ realm into the world of GCC (via MINGW32). Trying to create a Windows PE that consists largely of NOPs, ala:

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

But either I'm using the wrong syntax or the compiler is optimising through them because those NOPs don't survive the compilation process.

I'm using the -O0 flag, otherwise defaults. Any ideas on how I can coax the compiler into leaving the NOPs intact?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

唠甜嗑 2024-10-16 19:03:34

获得 1000 个内联 nop 的便捷方法是使用 GNU 汇编器的.rept指令

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

尝试godbolt

A convenient way to get 1000 inline nops is to use the .rept directive of the GNU assembler:

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

Try on godbolt.

锦欢 2024-10-16 19:03:34

您是否期望它将循环展开到 1000 nop 秒?我使用 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< /code> 我看到它展开循环 8 次(因此 8 nop),但我认为如果你想要 1000,这将是最容易做到的:

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

然后使用 NOP10(); ...

Are you expecting it to unroll the loop in to 1000 nops? I did a quick test with gcc and I don't see the (one) nop disappear:

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

With gcc -S -O3 -funroll-all-loops I see it unroll the loop 8 times (thus 8 nop) but I think if you want 1000 it's going to be easiest to do:

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

And then use NOP10(); ...

只等公子 2024-10-16 19:03:34

最近关于不带条件循环到 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

This recent question about looping to 1000 without conditionals resulted in a clever answer using template recursion which can actually be used to produce your 1000 nop function without repeating asm("nop") at all. There are some caveats: If you don't get the compiler to inline the function you will end up with a 1000-deep recursive stack of individual nop functions. Also, gcc's default template depth limit is 500 so you must specify a higher limit explicitly (see below, though you could simply avoid exceeding 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>();
}

Compiled with:

 g++ -O2 -ftemplate-depth=1000 ctr.c
他夏了夏天 2024-10-16 19:03:34

除了@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"); }

in addition to the answer by @BenJackson, it can recurse with way less depth by (binary) division.

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"); }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文