【问题标题】:ARM gcc inline assembler optimization problemARM gcc内联汇编优化问题
【发布时间】:2011-06-29 08:40:50
【问题描述】:

为什么当我有优化标志 -O3 但它与其他优化标志(-O0、-O1、-O2、-Os)一起工作时,我的内联汇编程序不工作?

我什至在我的所有汇编程序指令中添加了 volatile,我认为这会告诉编译器不要触摸或重新排序任何东西?

最好的问候

吉古先生

【问题讨论】:

  • 定义“不工作”。你期望它做什么,而不是发生了什么?例行公事在做什么?你怎么称呼它?可以发一下源码吗?你看过生成的二进制文件的反汇编吗?
  • 两年后重新审视我的问题后,我意识到我的问题在信息很少的情况下是多么荒谬。这让 FrankH 能够回答我的问题更加令人印象深刻。问题是我没有在我的内联汇编程序中指定任何破坏寄存器值的破坏列表。使用某些优化的原因可能是侥幸巧合。

标签: arm assembly


【解决方案1】:

GCC 内联汇编器对正确的规范非常敏感。

特别是,您必须非常精确地指定正确的约束,以确保编译器不会决定“优化”您的汇编代码。有几件事需要注意。举个例子吧。

以下两个:

 int myasmfunc(int arg) /* 肯定有问题 ... */
    {
        注册 int myval asm("r2") = arg;

        asm ("添加 r1, r0, #22\n" ::: "r1");
        asm ("添加 r0, r1, r0\n" ::: "r0", "cc");
        asm ("subeq r2, #123\n" ::: "r2");
        asm ("subne r2, #213\n" ::: "r2");
        返回myval;
    }

 int myasmfunc(int arg)
    {
        int myval = arg,加 = arg;

        asm ("添加 %0, #22\n\t" : "+r"(加号));
        asm ("添加 %1, %2\n\t"
             “子当量 %0,#123\n\t”
             “subne %0,#213\n\t”:“+r”(myval),“+r”(加号):“r”(arg):“cc”);
        返回myval;
    }

乍一看可能看起来很相似,但您会天真地认为它们也是如此;但他们离那还很远!

此代码的第一个版本存在多个问题。

  1. 一方面,如果您将其指定为单独的asm() 语句,编译器可以在其间插入任意代码。这尤其意味着 sub 指令,即使它们自己不修改条件代码,也可能与编译器选择插入的内容发生冲突。
  2. 其次,由于在指定单独的asm() 语句时指令的拆分,不能保证代码生成器在两次都选择相同的寄存器来放置myval,变量声明中的asm("r2") 规范尽管如此。
  3. 第三,第一个假设r0包含函数的参数是错误的;编译器在到达汇编块时可能已选择将此参数移动到其他任何地方。更糟糕的是,您再次使用了 split 语句,并且无法保证 两个 asm() 之间会发生什么。即使您指定__asm__ __volatile__(...);,编译器也会将两个这样的块视为独立实体。
  4. 第四,您没有告诉编译器您正在破坏/分配myval。它可能选择暂时将其移至别处,因为您正在破坏“r2”,并且在返回时,决定从...恢复它(???)。

只是为了好玩,这里是第一个函数的输出,针对以下四种情况:

  1. 默认 - gcc -c tst.c
  2. 优化 - gcc -O8 -c tst.c
  3. 使用一些不寻常的选项 - gcc -c -finstrument-functions tst.c
  4. 那加上优化 - gcc -c -O8 -finstrument-functions tst.c
段.text的反汇编:

00000000 :
   0: e52db004 推 {fp} ; (str fp, [sp, #-4]!)
   4: e28db000 添加 fp, sp, #0 ; 0x0
   8: e24dd00c sub sp, sp, #12 ; 0xc
   c: e50b0008 str r0, [fp, #-8]
  10:e51b2008 ldr r2,[fp,#-8]
  14: e2811016 添加 r1, r1, #22 ; 0x16
  18: e0910000 添加 r0, r1, r0
  1c: 0242207b subeq r2, r2, #123 ; 0x7b
  20: 124220d5 subne r2, r2, #213 ; 0xd5
  24: e1a03002 移动 r3, r2
  28: e1a00003 移动 r0, r3
  2c: e28bd000 添加 sp, fp, #0 ; 0x0
  30: e8bd0800 弹出 {fp}
  34:e12fff1e bx lr


部分.text的反汇编:

00000000 :
   0: e1a03000 移动 r3, r0
   4: e2811016 添加 r1, r1, #22 ; 0x16
   8: e0910000 添加 r0, r1, r0
   c: 0242207b subeq r2, r2, #123 ; 0x7b
  10: 124220d5 subne r2, r2, #213 ; 0xd5
  14: e1a00003 移动 r0, r3
  18: e12fff1e bx lr


部分.text的反汇编:

00000000 :
   0: e92d4830 推 {r4, r5, fp, lr}
   4: e28db00c 添加 fp, sp, #12 ; 0xc
   8: e24dd008 sub sp, sp, #8 ; 0x8
   c: e1a0500e mov r5, lr
  10: e50b0010 str r0, [fp, #-16]
  14:e59f0038 ldr r0,[pc,#56]; 54
  18: e1a01005 移动 r1, r5
  1c:ebffffffe bl 0
  20:e51b2010 ldr r2,[fp,#-16]
  24: e2811016 添加 r1, r1, #22 ; 0x16
  28: e0910000 添加 r0, r1, r0
  2c: 0242207b subeq r2, r2, #123 ; 0x7b
  30: 124220d5 subne r2, r2, #213 ; 0xd5
  34: e1a04002 移动 r4, r2
  38:e59f0014 ldr r0,[pc,#20]; 54
  3c: e1a01005 移动 r1, r5
  40:ebffffffe bl 0
  44: e1a03004 移动 r3, r4
  48: e1a00003 移动 r0, r3
  4c: e24bd00c sub sp, fp, #12 ; 0xc
  50: e8bd8830 pop {r4, r5, fp, pc}
  54: 00000000 .word 0x00000000


部分.text的反汇编:

00000000 :
   0: e92d4070 推 {r4, r5, r6, lr}
   4: e1a0100e mov r1, lr
   8: e1a05000 移动 r5, r0
   c: e59f0028 ldr r0, [pc, #40] ; 3c
  10: e1a0400e mov r4, lr
  14:ebffffffe bl 0
  18: e2811016 添加 r1, r1, #22 ; 0x16
  1c: e0910000 添加 r0, r1, r0
  20: 0242207b subeq r2, r2, #123 ; 0x7b
  24: 124220d5 subne r2, r2, #213 ; 0xd5
  28:e59f000c ldr r0,[pc,#12]; 3c
  2c: e1a01004 移动 r1, r4
  30:ebffffffe bl 0
  34: e1a00005 移动 r0, r5
  38: e8bd8070 弹出 {r4, r5, r6, 电脑}
  3c: 00000000 .word 0x00000000

如您所见,这些都没有达到您希望看到的效果;不过,gcc -c -O8 ... 上的代码的第二个版本最终是:

段.text的反汇编:

00000000 :
   0: e1a03000 移动 r3, r0
   4: e2833016 添加 r3, r3, #22 ; 0x16
   8: e0933000 添加 r3, r3, r0
   c: 0240007b subeq r0, r0, #123 ; 0x7b
  10: 124000d5 subne r0, r0, #213 ; 0xd5
  14: e12fff1e bx lr

这就是您在程序集中指定的内容以及您所期望的内容。

士气:明确和准确地处理您的约束、操作数分配,并在相同 asm() 块中保持相互依赖的汇编行(编写多行语句)。

【讨论】:

    【解决方案2】:

    这确实应该是一条评论,但由于某种原因我无法发表评论:(

    编译器优化不应该真的弄乱你的程序集。那么,正如伊戈尔所说,这在什么方面“不起作用”?也许您的 ASM 分支成一个函数,该函数已被编译器优化,给出了与您的汇编代码可能依赖的不同的结果?

    一些源文件或有关编译器的更多信息可能有用

    【讨论】:

    • 新手不能评论。 :-) 你首先需要 50 分。我会给你 10 个毫无根据的赞成票。
    • gcc 中,编译器优化非常重要的方式干扰你的内联汇编,除非你非常小心你的要求.这对许多人来说是可以理解的,但这是设计/意图,不太可能改变。
    • @FrankH - 哦,不知道 GCC 也会搞砸内联汇编,抱歉
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-18
    • 2012-10-20
    相关资源
    最近更新 更多