有一些問題/內聯彙編我不明白。手臂;內聯asm;使用臨時寄存器;
我有一個嵌入式彙編程序的功能。在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
已損壞,一切都只是土崩瓦解。
我應該如何定義scratch寄存器來避免這種情況?
當您添加'[reg]'時,val停止爲'%0'併成爲'%1'。 –
@DavidWohlferd,謝謝。順便說一句'[reg]「= r」(reg)'仍然無法正常工作。在某些情況下,編譯器對'val'和'reg'使用相同的寄存器,所以我得到'mrc r3 ...; orr r3,r3,r3; mcr r3 ...;'。 '[reg]「+ r」(reg)'實際上解決了這個問題,但是現在編譯器顯示錯誤''reg'被使用了未初始化...'並且需要爲'reg'指定一個轉儲值並且出現額外的指令。它可以修復嗎? – user3124812
我知道你已經解決了它,但是在第一個代碼塊中,我認爲你遇到的問題是根據ARM EABI調用約定,函數的第一個參數將在'r0'中,這樣代碼可能會用'mrc 15,0,r0,...'來破壞'uint32_t val'。同樣,在ARM EABI中,'r4-8,r10,r11'被認爲是「可變寄存器」,所以我認爲如果你使用了其中一個,那麼你會很好。 – rjp