您的位置:首页 > 其它

GCC下使用Inline Assembly的初步心得

2013-01-17 18:52 471 查看
以前主要手写汇编,今天尝试用了下内联汇编(Inline Assembly),出了点问题,特此做个总结。

=====================================================================

开发环境:Xilinx ISE 14.4 EDK

编译器版本:gcc version 4.6.3 (Sourcery CodeBench Lite 2012.03-83)

用于测试的C源代码:

void dummy1(void)

{

}

unsigned int dummy2(void)

{

}

unsigned int dummy3(void)

{

    return 0x12345678;

}

unsigned int dummy4()

{

    asm (

    "MRC p15,0,r0,c0,c0,5\n\t"

    "AND r0, r0, #3\n\t"

    "BX  lr\n\t"

    );

}

unsigned int dummy5()

{

    register int x, y;

    asm (

    "MRC p15,0,%[value],c0,c0,5\n\t"

    "AND %[result], %[value], #3\n\t": [result] "=r" (y): [value] "r" (x)

    );

    return y;

}

在-O0优化级别下的编译结果:

void dummy1(void)

{

  1003c0:    e52db004     push    {fp}        ; (str fp, [sp, #-4]!)

  1003c4:    e28db000     add    fp, sp, #0

}

  1003c8:    e28bd000     add    sp, fp, #0

  1003cc:    e8bd0800     pop    {fp}

  1003d0:    e12fff1e     bx    lr

001003d4 <dummy2>:

unsigned int dummy2(void)

{

  1003d4:    e52db004     push    {fp}        ; (str fp, [sp, #-4]!)

  1003d8:    e28db000     add    fp, sp, #0

}

  1003dc:    e1a00003     mov    r0, r3

  1003e0:    e28bd000     add    sp, fp, #0

  1003e4:    e8bd0800     pop    {fp}

  1003e8:    e12fff1e     bx    lr

001003ec <dummy3>:

unsigned int dummy3(void)

{

  1003ec:    e52db004     push    {fp}        ; (str fp, [sp, #-4]!)

  1003f0:    e28db000     add    fp, sp, #0

    return 0x12345678;

  1003f4:    e3053678     movw    r3, #22136    ; 0x5678

  1003f8:    e3413234     movt    r3, #4660    ; 0x1234

}

  1003fc:    e1a00003     mov    r0, r3

  100400:    e28bd000     add    sp, fp, #0

  100404:    e8bd0800     pop    {fp}

  100408:    e12fff1e     bx    lr

0010040c <dummy4>:

unsigned int dummy4()

{

  10040c:    e52db004     push    {fp}        ; (str fp, [sp, #-4]!)

  100410:    e28db000     add    fp, sp, #0

    asm (

  100414:    ee100fb0     mrc    15, 0, r0, cr0, cr0, {5}

  100418:    e2000003     and    r0, r0, #3

  10041c:    e12fff1e     bx    lr

    "MRC p15,0,r0,c0,c0,5\n\t"

    "AND r0, r0, #3\n\t"

    "BX  lr\n\t"

    );

}

  100420:    e1a00003     mov    r0, r3

  100424:    e28bd000     add    sp, fp, #0

  100428:    e8bd0800     pop    {fp}

  10042c:    e12fff1e     bx    lr

00100430 <dummy5>:

unsigned int dummy5()

{

  100430:    e92d0810     push    {r4, fp}

  100434:    e28db004     add    fp, sp, #4

    register int x, y;

    asm (

  100438:    ee104fb0     mrc    15, 0, r4, cr0, cr0, {5}

  10043c:    e2044003     and    r4, r4, #3

    "MRC p15,0,%[value],c0,c0,5\n\t"

    "AND %[result], %[value], #3\n\t": [result] "=r" (y): [value] "r" (x)

    );

    return y;

  100440:    e1a03004     mov    r3, r4

}

  100444:    e1a00003     mov    r0, r3

  100448:    e24bd004     sub    sp, fp, #4

  10044c:    e8bd0810     pop    {r4, fp}

  100450:    e12fff1e     bx    lr

注意:

1. 函数dummy4()的编译结果运行时会出问题:首先取到的CP15寄存器的值不会被返回;fp寄存器被改写但是没有恢复;没有和push相匹配的pop,stack会完全乱掉。

2. 函数dummy5()中给两个临时变量声明了register关键字,如果不加,对这两个变量的访问会直接编译成对stack memory的访问。

3. -O0下GCC会在函数进入和退出的时候加上固定的wrapper。

在-O3优化级别下的编译结果:

void dummy1(void)

{

}

  1003c0:    e12fff1e     bx    lr

001003c4 <dummy2>:

unsigned int dummy2(void)

{

}

  1003c4:    e12fff1e     bx    lr

001003c8 <dummy3>:

unsigned int dummy3(void)

{

    return 0x12345678;

}

  1003c8:    e3050678     movw    r0, #22136    ; 0x5678

  1003cc:    e3410234     movt    r0, #4660    ; 0x1234

  1003d0:    e12fff1e     bx    lr

001003d4 <dummy4>:

unsigned int dummy4()

{

    asm (

  1003d4:    ee100fb0     mrc    15, 0, r0, cr0, cr0, {5}

  1003d8:    e2000003     and    r0, r0, #3

  1003dc:    e12fff1e     bx    lr

    "MRC p15,0,r0,c0,c0,5\n\t"

    "AND r0, r0, #3\n\t"

    "BX  lr\n\t"

    );

}

  1003e0:    e12fff1e     bx    lr

001003e4 <dummy5>:

unsigned int dummy5()

{

    register int x, y;

    asm (

  1003e4:    e3a00000     mov    r0, #0

  1003e8:    ee100fb0     mrc    15, 0, r0, cr0, cr0, {5}

  1003ec:    e2000003     and    r0, r0, #3

    "MRC p15,0,%[value],c0,c0,5\n\t"

    "AND %[result], %[value], #3\n\t": [result] "=r" (y): [value] "r" (x)

    );

    return y;

}

  1003f0:    e12fff1e     bx    lr

注意:

1. 函数dummy4():执行结果会碰巧对了,但是两条BX指令明显不对。

2. 函数dummy5():功能没有问题,但是不是最有效的,第一条指令完全没有必要。

小结:

1. 使用内联汇编(Inline Assembly)的时候没有必要加返回指令BX

2. 不要在内联汇编中使用指定寄存器,因为编译器在不同的编译选项下对寄存器的处理方式不同。

3. 比较好的办法是在内联汇编中使用临时变量,临时变量前面最好加上register关键字,方便编译器优化。

4. 如果只是写些简单的使用特殊指令的函数,直接写汇编比使用内联汇编(Inline Assembly)方便快捷。

[END]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: