翻譯這一篇 : arm gcc inline assembler cookbok
但是這一篇(GCC-inline assembly Howto)說得比較仔細。


 


GCC 的 inline assembly 基本格式是:


  asm(code : output operand list : input operand list : clobber list);

也就是一堆用 ':'分開的字串。
其中 'code' 的部份要存取 output operand list , input operand 的內容,是用 % 符號:


 %0 代表存取 output operand
%1 代表存去 input operand
最後的'clobber' 是要告訴 compiler 有哪些 register 被這段 assembly code 修改了。

為了防止 compiler 把這一段 inline assembly code optimize 掉,通常都會加上 volatilr:


 asm voltaile("mov %0, ror #01" : "-r" (result) : "r" (value));


這段 inline assembly,如果之後的部份都沒有資料,就可以不寫,舉例來說:


 asm volatile("mov r0, r0");

這只是用來delay的code,沒有input, output,也沒有 register 會被修改,所以後面的 部份都不用寫。

但是如果有資料一定要寫,他的前面部份就不可以省略,舉例來說:


 asm volatile("" : : : "memory");

這段inline assembly 不包含任何 code,只是告訴 compiler memory 有可能會被修改。

一般為了好看,建議將一堆 assembly 寫成這樣:


 asm volatile(
"mov r0,r0\n\t"
"mov r0,r0\n\t"
"mov r0,r0\n\t"
);

也就是說,分行寫,但是要記得加上 "\n\t" - 這是要讓 compiler listing 時,比較好看。


Input Output Operand

這兩個區域是要告訴 compiler operand 的資料,利用以下 "Constraint" 來通知:
Operand Register 的類型:



  • f : 是floating point register (有些 cpu 有專屬的 floating point register)
  • I : 立即定址 immediate operands

  • J : Indexing constants
  • K : negative value in rhs
  • L: negative value in rhs
  • M : for shift
  • r : General registers -- ARM 一般用這個

Operand Register 的 in/out:



  • = : Write-only (通常所有的 output operand 都會加這個符號)

  • + : Read-Write (inline assemnly 不支援這個符號)

  • & : Output only - 這個register 只做 output 使用

Output Operand 一定要是 Write-Only。
Input Operand 一定要是 Read-Only。

但是如果要把 input operand 修改後,作為 output operand 的話,要怎麼辦呢?
inline assembly 又不支援 '+' 符號..

用"數字" 來告訴 complier 這一個 operand 共用哪一個 operand,例如:


asm volatile("mov %0, %0, ror #1" : "=r" (value) : "0" (value));

這個 code 是將'value" right shit 1 bit。
但是用同一個 register 來作就可以。
input operand 用 "0" 告訴 compiler ,使用 第0個operand (就是 output operand)。
所以 input, output 都會用同一個 register (mov %0, %0..)。

Clobbers

把被修改的部份寫在這


asm volatile(
"amsd r3, %1, #3 \n\t"
"eor %0, %0, r3 \n\t"
"addne %0, #4"
: "=r" (len)
: "0" (len)
: "cc","r3"
);

例子使用了 r3 作scratch register,所以做完這段 code 後,r3的值會被修改,以在clobber的區域要列出 "r3"。
另外,作邏輯運算後,status 區域也會修改,所以要把"cc"也列上。

還有另一個例子:


asm volatile(
"ldr %0, [%1] \n\t"
"str %2, [%1, #4] \n\t"
: "=&r" (rdv)
: "r" (&table), "r" (wdv)
: "memory"
);

這一段code會update table 的內容,所以要在....





有一點沒寫到,就是 c variable name 都寫在 operand 後面,用括號( )括起來..


在 "Assembler Instruction with C expression operand" ,範例:
asm ("fsinx %[angle],%[output]"
: [output] "=f" (result)
: [angle] "f" (angle));
在operand 前可以用 [name] 寫出''將會用這'name'名字稱呼''。
然後在 code 區域就可以直接用 %[name] 來引用


大概可以這樣說:

assembly code 中,要引用 C 宣告的部份,就要寫在 operand (in/out) 欄位,並且寫號 constrain.
然後用 %0, %1...來使用。
如果是直接存取 register,就直接用 r1, r2, r3... 但是要記得寫在 clobber 欄位。


 


 


http://r40eubuntu.blogspot.com/2009/02/arm-gcc-inline-assembler.html


 


ARM GCC Inline Assembler Cookbook


http://www.ethernut.de/en/documents/arm-inline-asm.html


 


http://blog.yam.com/registry/article/16464253


 


 

創作者介紹
創作者 立你斯 的頭像
立你斯

立你斯學習記錄

立你斯 發表在 痞客邦 留言(1) 人氣()