2015-04-23 135 views
2

在A64彙編程序中,有不同的方式來指定地址。內聯彙編中的內存偏移

/* 
[base{,#0}]     Simple register (exclusive) - Immediate Offset 
[base{,#imm}]    Offset - Immediate Offset 
[base,Xm{,LSL #imm}]  Offset - Register Offset 
[base,Wm,(S|U)XTW {#imm}] Offset - Extended Register Offset 
[base,#imm]!    Pre-indexed - Immediate Offset 
[base],#imm     Post-indexed - Immediate Offset 
label      PC-relative (literal) load - Immediate Offset 
*/ 

我想用 「偏移 - 直接偏移量」 的內聯彙編。

__asm__("ldp x8, x9, %0, 16 \n\t" 
     : 
     : "m" (*somePointer) 
     : "x8", "x9"); 

這被翻譯成

ldp x8, x9, [x0], 16 

我的目標是要達到

ldp x8, x9, [x0, 16] 

我怎麼能寫與內聯彙編這樣的指令?

+0

我不知道你如何使用1%,只有1個參數?怎麼樣使用寄存器約束?警告:我沒有嘗試過,但是'asm(「ldp x8,x9,[%0,%1]」::「r」(somePointer),「i」(16):「x8」 「X9」);'? –

+0

修正了這個問題 - 顯然應該讀取%0。從更長的語句中提取更多的輸入/輸出,並且忘記更新參數:-) 這些提示對於編譯器來說不重要,因此它知道哪些內存區域被我的代碼訪問?例如如果我在寫入上下文中使用它,編譯器可能需要知道哪些內存區域已被破壞 - 在這種情況下,寄存器約束不起作用? – Etan

+0

夠正確。因此,由於編譯器實際上沒有解析asm,因此可以這樣做:'asm(「ldp x8,x9,[%0,%1]」::「r」(somePointer),「i」(16),「m 「(* somePointer):」x8「,」x9「);'(即有約束,但不要引用它)。或者添加「內存」clobber。請注意,正如所寫,您只是告訴編譯器,asm *讀取*內存,而不是它改變它。 –

回答

0

我沒有一個ARM 64位工具鏈來進行測試,但你應該能夠做這樣的事情:

asm("ldp x8, x9, %0\n\t" 
    : 
    : "Ump" (*((__int128 *) somePointer + 1)) 
    : "x8", "x9"); 

Ump約束限制了存儲器的操作數那些允許整數LDP指令,否則它的工作方式類似於m約束。如果somePointer已經是指向128位類型的指針,則可以使用somePointer[1]作爲操作數。

如果以上不工作,那麼大衛Wohlferd的建議應該:

asm("ldp x8, x9, [%0, %1]" 
    : 
    : "r" (somePointer), "i"(16), "m" (*somePointer) 
    : "x8", "x9");