gcc、arm、内联汇编、BX 试图跳过 goto 部分会产生意想不到的结果

问题描述 投票:0回答:1

我正在使用 Cortex M0+;

我试图在常规代码流中保留一段代码,不要问我为什么:)
基本上稍后,我想跳转到MYCODE。

这是代码

    bool x = false; // defined somewhere globally 

    if (x) goto MYCODE; // prevents removal of MYCODE

    //goto MYJUMP; // this is working as expected
    __asm volatile("BX %0" : : "r" (&&MYJUMP) : ); // this crashes !!!

MYCODE:

    __asm volatile ("nop");
    __asm volatile ("nop");
    __asm volatile ("nop");

MYJUMP:
    __asm volatile ("nop"); // first NOP will crash !!!
    __asm volatile ("nop");
    __asm volatile ("nop");

现在首先,GCC 从 MYCODE 中删除任何东西,无论我使用 -Ox。
说服保留代码的一种方法是将“x”声明为全局并在之前制作一个假的 if()。

另一种方法是使用 jump in assembly with this

__asm volatile("BX %0" : : "r" (&&MYJUMP) : );

生成的代码为

 96           __asm volatile("BX %0" : : "r" (&&MYJUMP) : );
0800285e:   ldr     r3, [pc, #96]  
08002860:   bx      r3                    // value is 0800286c

使用内联跳转,老是撞到DefaultHandler! 这很好奇,NOP 看起来很好

08002864:   nop     ; (mov r8, r8)
100         __asm volatile ("nop");
08002866:   nop     ; (mov r8, r8)
101         __asm volatile ("nop");
08002868:   nop     ; (mov r8, r8)
102         __asm volatile ("nop");
0800286a:   nop     ; (mov r8, r8)
105         __asm volatile ("nop");
0800286c:   nop     ; (mov r8, r8)       // <-- the code reaches here just fine as expected
106         __asm volatile ("nop");      // but when executed this NOP will jump to DefaultHandler
0800286e:   nop     ; (mov r8, r8)
107         __asm volatile ("nop");
08002870:   nop     ; (mov r8, r8)  

知道发生了什么事吗?
我调试了几个小时,我就是不明白。

我想用汇编跳转,这样GCC就不会优化了

非常感谢!

c assembly gcc inline-assembly cortex-m0
1个回答
0
投票

跳出内联汇编需要特殊处理。它有额外的语法:

asm goto
.

简而言之,你的跳跃应该是这样的:

__asm goto("B %l0" : : : : MYJUMP);

试试godbolt

这编译成一个简单的

b label
。我没有测试它,但生成的 asm 看起来“显然是正确的”。

作为奖励,您无需将标签地址加载到临时寄存器中。它还会阻止优化

MYCODE
(不需要虚拟变量),因为编译器假定可能会或可能不会进行跳转。 (文档提到,如果你想通知编译器 asm 将 always 跳转,你可以在它后面加上
__builtin_unreachable()
。)

© www.soinside.com 2019 - 2024. All rights reserved.