ARM gcc内联汇编程序优化问题

MrG*_*igu 1 assembly arm

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

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

最好的祝福

吉古先生

Fra*_*kH. 6

GCC内联汇编程序对正确的规范非常敏感.

特别是,您必须非常精确地指定正确的约束,以确保编译器不会决定"优化"汇编程序代码.有几点需要注意.举个例子.

以下两个:

    int myasmfunc(int arg)    /* definitely buggy ... */
    {
        register int myval asm("r2") = arg;

        asm ("add r1, r0, #22\n" ::: "r1");
        asm ("adds r0, r1, r0\n" ::: "r0", "cc");
        asm ("subeq r2, #123\n" ::: "r2");
        asm ("subne r2, #213\n" ::: "r2");
        return myval;
    }

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

        asm ("add %0, #22\n\t" : "+r"(plus));
        asm ("adds %1, %2\n\t"
             "subeq %0, #123\n\t"
             "subne %0, #213\n\t" : "+r"(myval), "+r"(plus) : "r"(arg) : "cc");
        return myval;
    }

乍一看可能看起来很相似,你会天真地认为他们也是这样做的; 但他们离这个很远!

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

  1. 例如,如果将其指定为单独的asm()语句,编译器可以在其间插入任意代码.这尤其意味着sub指令,即使它们自己不修改条件代码,也可能违反编译器选择插入的内容.
  2. 其次,由于在指定单独的asm()语句时分离了指令,所以不能保证代码生成器会选择同一个寄存器来放入myval两个时间,asm("r2")尽管变量声明中的规范.
  3. 第三,第一个r0包含函数参数的假设是错误的; 编译器到达汇编块时,可能会选择将此参数移动到其他任何位置.更糟的是,甚至因为你再有分裂声明,并不能保证作出对发生的事情之间 2 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
Disassembly of section .text:

00000000 :
   0:   e52db004    push    {fp}        ; (str fp, [sp, #-4]!)
   4:   e28db000    add 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    add r1, r1, #22 ; 0x16
  18:   e0910000    adds    r0, r1, r0
  1c:   0242207b    subeq   r2, r2, #123    ; 0x7b
  20:   124220d5    subne   r2, r2, #213    ; 0xd5
  24:   e1a03002    mov r3, r2
  28:   e1a00003    mov r0, r3
  2c:   e28bd000    add sp, fp, #0  ; 0x0
  30:   e8bd0800    pop {fp}
  34:   e12fff1e    bx  lr


Disassembly of section .text:

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


Disassembly of section .text:

00000000 :
   0:   e92d4830    push    {r4, r5, fp, lr}
   4:   e28db00c    add 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    mov r1, r5
  1c:   ebfffffe    bl  0 
  20:   e51b2010    ldr r2, [fp, #-16]
  24:   e2811016    add r1, r1, #22 ; 0x16
  28:   e0910000    adds    r0, r1, r0
  2c:   0242207b    subeq   r2, r2, #123    ; 0x7b
  30:   124220d5    subne   r2, r2, #213    ; 0xd5
  34:   e1a04002    mov r4, r2
  38:   e59f0014    ldr r0, [pc, #20]   ; 54 
  3c:   e1a01005    mov r1, r5
  40:   ebfffffe    bl  0 
  44:   e1a03004    mov r3, r4
  48:   e1a00003    mov r0, r3
  4c:   e24bd00c    sub sp, fp, #12 ; 0xc
  50:   e8bd8830    pop {r4, r5, fp, pc}
  54:   00000000    .word   0x00000000


Disassembly of section .text:

00000000 :
   0:   e92d4070    push    {r4, r5, r6, lr}
   4:   e1a0100e    mov r1, lr
   8:   e1a05000    mov r5, r0
   c:   e59f0028    ldr r0, [pc, #40]   ; 3c 
  10:   e1a0400e    mov r4, lr
  14:   ebfffffe    bl  0 
  18:   e2811016    add r1, r1, #22 ; 0x16
  1c:   e0910000    adds    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    mov r1, r4
  30:   ebfffffe    bl  0 
  34:   e1a00005    mov r0, r5
  38:   e8bd8070    pop {r4, r5, r6, pc}
  3c:   00000000    .word   0x00000000

正如你所看到的,这些都不是你希望看到的; 但是,代码的第二个版本gcc -c -O8 ...最终为:

Disassembly of section .text:

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

更确切地说,就是你在装配中指定的内容以及你期望的内容.

士气:明确而精确地使用约束,操作数赋值,并在相同的 asm()块中保持相互依赖的汇编行(制作多行语句).