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 一般用這個
- = : Write-only (通常所有的 output operand 都會加這個符號)
- + : Read-Write (inline assemnly 不支援這個符號)
- & : Output only - 這個register 只做 output 使用
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" ,範例:大概可以這樣說: assembly code 中,要引用 C 宣告的部份,就要寫在 operand (in/out) 欄位,並且寫號 constrain. 然後用 %0, %1...來使用。 如果是直接存取 register,就直接用 r1, r2, r3... 但是要記得寫在 clobber 欄位。asm ("fsinx %[angle],%[output]" : [output] "=f" (result) : [angle] "f" (angle));在operand 前可以用 [name] 寫出''將會用這'name'名字稱呼''。 然後在 code 區域就可以直接用 %[name] 來引用
ref:
沒有留言:
張貼留言