ARM内联汇编基础
匯編代碼一般會與C函數的代碼有數據交換,需要通過匯編代碼來操作C代碼中的一些變量數據,而C代碼中的數據存放在內存還是寄存器,或者存放在哪個寄存器我們在寫C代碼的時候并不知道,所以匯編規定了一些形式來讓編譯器知道數據的交換情況,如下:
asm( "mov %[result], %[value], ror #1" : [result] "=r" (y) : [value] "r" (x) : );內聯匯編通過冒號將內容分成了四個部分,內聯匯編和C操作數之前的關聯性體現在上面的input和out操作數上:?
asm( code ? ?/*匯編指令*/ : output operand list ? ? /*輸出操作數列表*/ : input operand list ? ? ?/*輸入操作數列表*/ : clobber list ? ? ? ? ? ? ? /*被改變資源列表*/ ); ??對前面的代碼段分析,有四個組成部分:
1. 匯編指令
mov %[result], %[value], ror #12. 輸出操作數列表,可選,每個輸出數的符號名用方括號包圍,后面跟一個約束串,然后再加上一個括號包圍的C表達式,這個括號里的符號就是C語言代碼中的變量。
[result] "=r" (y) /*result:符號名 ? "=r":約束串* ? ?(y):C表達式/ ?3. 輸入操作數列表,可選,語法上與輸入操作數列表一樣。括號中的x是C語言代碼中的變量。
[value] "r" (x)4. 被改變資源列表,這里是空的,它主要是告訴編譯器哪些資源發生了改變,需要去更新。
那么上面的"r"和"=r"是什么意思呢?請看下面兩個圖:
?
"=" 表示只寫,通常用于所有輸出操作數的屬性
"+" 表示讀寫,只能被列為輸出操作數的屬性,否則編譯會報錯。
下表是寄存器類型的代表符號,r為通用寄存器,w是向量寄存器:
從圖中可以看出,除了最常應用到的 "r" 屬性(使用通用寄存器處理操作數),還有其他的很多特性,包括使用浮點寄存器 ("f"),或者使用立即數("I")等等,對于 arm 和 thumb 指令集也有較大的區別。
如果你曾經讀過一些別人寫的內聯匯編代碼就會發現與我們上面寫的略有不同,是下面這種形式的:
asm( "mov %0, %1, ror #1"? : "=r" (result)? : "r" (value) : ); ?實際上是同一種形式,只不過第一段匯編代碼是從GCC 3.1版本開始才支持的,而在此之前一直是上面的形式。上述0%和1%分別表示第一個、第二個操作數。GCC的最新版本仍然支持上述語法,但明顯,上述語法更容易出錯,且難以維護:假設你寫一個較長的內聯匯編,然后需要在某個位置插入一個新的輸出操作數,此時,之后的操作數都需要重新編號
總結
- 上一篇: git修改.gitignore
- 下一篇: linux下源码安装cmake