【问题标题】:arm; inline asm; use scratch register;手臂;内联汇编;使用暂存器;
【发布时间】:2016-07-21 01:53:41
【问题描述】:

我无法理解内联汇编程序的一些问题。

我有一个内联汇编器的功能。在 ASM 块内,我需要使用一些临时寄存器来修改一些系统值。

void setHW(uint32_t val) {
    asm volatile (
        mrc 15, 0, r0, ...
        orr r0, r0, %0 
        mcr 15, 0, r0, ...
        : :"r"(val) :"r0"
    );
}

实际上函数是由编译器内联的,没关系,代码仍然运行良好。

当我尝试用一​​些存根变量替换硬编码的r0 时出现问题,因此编译器可以选择最好的寄存器来使用。看起来是这样的

void setHW(uint32_t val) {
    uint32_t reg;
    asm volatile (
        mrc 15, 0, %[reg], ...
        orr %[reg], %[reg], %0 
        mcr 15, 0, %[reg], ...
        :[reg]"=r"(reg) :"r"(val) :
    );
}

现在编译器自己选择寄存器,但实际上破坏了setHW调用函数的值。 在反汇编程序中它看起来像

        add r2, r4, r5       ; caller part, r2 contain some intermedia result
        mrc 15, 0, r2, ...   ; inlined setHW(), r2 is choosen as scratch reg
        orr r2, r2, r0 
        mcr 15, 0, r2, ...
        ; caller continue

如您所见,r2 已损坏,一切都崩溃了。

我应该如何定义暂存器以避免这种情况?

【问题讨论】:

  • 当您添加[reg] 时,val 不再是%0,而是变成了%1
  • @DavidWohlferd,是的,谢谢。顺便说一句[reg]"=r"(reg) 仍然无法正常工作。在某些情况下,编译器对valreg 使用相同的寄存器,所以我得到mrc r3...; orr r3, r3, r3; mcr r3...;[reg]"+r"(reg) 实际上解决了问题,但现在编译器显示错误 'reg' is used uninitialized... 并且有必要将转储值分配给 reg 并出现额外的指令。能修好吗?
  • 我知道你已经解决了,但是在第一个代码块中,我相信你遇到的问题是根据 ARM EABI 调用约定,函数的第一个参数将是在r0 中,因此该代码可能会破坏uint32_t valmrc 15, 0, r0, ...。同样,在 ARM EABI 中,r4-8,r10,r11 被认为是“变量寄存器”,所以我认为如果你使用其中之一,你会很好。
  • @rjp ,1) 问题不在于第一个块。 2)当r0被选中编译器将在asm volatile 987654343 @之前保留值@并在后面恢复。 span>

标签: gcc assembly arm inline-assembly


【解决方案1】:

这样的事情怎么样:

void setHW(uint32_t val) {
    uint32_t reg;
    asm volatile (
        mrc 15, 0, %[reg], ...
        orr %[reg], %[reg], %[val] 
        mcr 15, 0, %[reg], ...
        :[reg]"=&r"(reg) :[val] "r"(val) :
    );
}

注意=&r 以解决早期破坏问题(有关& 的说明,请参阅https://gcc.gnu.org/onlinedocs/gcc/Modifiers.html)。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-02
  • 1970-01-01
  • 2013-07-23
  • 1970-01-01
  • 2019-05-11
  • 2012-10-20
  • 2013-02-05
相关资源
最近更新 更多