2016-11-16 71 views
3

兩個問題:內聯彙編:澄清約束脩飾符

(1)如果我理解正確的ARM內聯彙編的「R」的約束說,指令操作數只能是一個核心寄存器,在默認情況下是一個只讀操作數。但是,我注意到,如果同一指令的輸出操作數的約束爲「= r」,編譯器可能會重新使用相同的寄存器。這似乎違反了「只讀」屬性。所以我的問題是:「只讀」引用寄存器還是引用它連接的C變量? (2)在約束「= &r」中是否存在「&」僅僅要求爲輸出操作數選擇的寄存器不能與輸入操作數寄存器中的一個相同?我的問題與下面用於計算整數冪函數的代碼有關:即,「&」約束脩飾符是否必要/合適?

asm (
" MOV %[power],1    \n\t" 
"loop%=:        \n\t" 
" CBZ %[exp],done%=    \n\t" 
" LSRS %[exp],%[exp],1   \n\t" 
" IT CS      \n\t" 
" MULCS %[power],%[power],%[base] \n\t" 
" MUL %[base],%[base],%[base] \n\t" 
" B  loop%=     \n\t" 
"done%=:         " 
: [power] "+&r" (power) 
    [base] "+&r" (base) 
    [exp] "+&r" (exp) 
: 
: "cc" 
) ; 

謝謝! Dan

+1

號, 「R」 並不意味着只讀的,它只是意味着 「通用寄存器」。您在輸入列表中指定的參數是隻讀的,無論您使用何種約束。 – Jester

+0

查看[this](https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#InputOperands)瞭解關於輸入參數和[this]的詳細信息(https://gcc.gnu.org/onlinedocs/ gcc/Simple-Constraints.html#Simple-Constraints)來獲得簡單約束的細節(比如''r「')。您可能還想看看[這裏](https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html)中關於「ARM系列」特定的約束。 –

回答

2

只讀是指在彙編代碼中使用操作數。彙編代碼只能從操作數讀取,並且必須在任何正常輸出操作數(不是早期的clobber或讀/寫操作數)被寫入之前這樣做。這是因爲,正如您所看到的,同一個寄存器可以分配給輸入和輸出操作數。假定輸入在輸出寫入之前被完全消耗,彙編指令通常是這種情況。

我不認爲使用具有讀/寫修飾符+的早期修改器&會產生任何影響,因爲分配給讀/寫操作數的寄存器不能用於其他任何操作。

這是我怎麼會寫代碼:

unsigned power = 1; 
asm (
    " CBZ %[exp],done%=    \n\t" 
    "loop%=:        \n\t" 
    " LSRS %[exp],%[exp],1   \n\t" 
    " IT CS      \n\t" 
    " MULCS %[power],%[power],%[base] \n\t" 
    " MUL %[base],%[base],%[base] \n\t" 
    " BNE loop%=     \n\t" 
    "done%=:         " 
    : [power] "+r" (power), 
     [base] "+r" (base), 
     [exp] "+r" (exp) 
    : 
    : "cc" 
    ) ; 

注意把環路測試在循環結束的改造,節約了一個指令。沒有它,代碼對編譯器可以生成的東西沒有任何明顯的改進。我還讓編譯器對用於power操作數的寄存器進行初始化。有一個很小的機會可以分配一個已經具有值1的寄存器。

+0

早期的clobber和讀寫的結合非常重要,就好像2個輸入具有相同的值,它們可以是相同的寄存器。 –

0

感謝大家的澄清。只是爲了確定我是否正確,說輸出操作數的「= r」和「+ r」之間的選擇取決於如何在組件中使用對應的寄存器第一個模板?即,

「= r」:該寄存器的第一次使用是作爲指令的只寫輸出。

該寄存器稍後可能被其他指令重新用作輸入或輸出。添加一個早期的clobber約束(例如,「= & r」)會阻止編譯器分配先前用作輸入操作數的寄存器。

「+ r」:寄存器的第一次使用是作爲指令的輸入,但寄存器稍後再次用作輸出。

最佳,

+1

我想我更喜歡「'」= r「(x)':輸入到asm時,這個寄存器的內容是未定義的(除非與匹配的輸入約束相結合),並且在輸出上,寄存器將包含變量'x'和''「+ r」(x)':'x'的現有值作爲輸入傳遞,可以通過asm指令進行更新。「和」另請參閱'&'修飾符防止來自共享寄存器的輸入和輸出限制。「 –

+0

大衛,我很困惑」(除非與一個匹配的輸入約束相結合)「。我認爲任何被列爲輸入操作數的東西都被定義爲」只讀「,因此會與輸出操作數列表相同,或者我誤解了你的意思? –

+0

正如[here](https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#InputOperands)所述, ,輸入約束可以是數字,所以'asm(「」:「= r」(x):「0」(y));''意味着'y'是一個輸入,參數#0。或者換句話說:在輸入時,寄存器將包含'y',並在輸出中包含'x'。這也意味着'asm(「」:「= r」(x):「0」(x));'是asm(「」:「+ r」(x));'的同義詞。 –