手臂;内联汇编;使用暂存器;
arm; inline asm; use scratch register;
内联汇编程序存在一些我无法理解的问题。
我有一个内联汇编程序的函数。在 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
已损坏,一切都崩溃了。
我应该如何定义临时寄存器来避免这种情况?
这样的事情怎么样:
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)。
内联汇编程序存在一些我无法理解的问题。
我有一个内联汇编程序的函数。在 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
已损坏,一切都崩溃了。
我应该如何定义临时寄存器来避免这种情况?
这样的事情怎么样:
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)。