# Linux Assambly code文件 https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html # Extended Asm - Assembler Instructions with C Expression Operands extended asm讓妳可以從assembler去讀寫C變數 也可以讓你從assemly code jump去 C labels,作用就是把low-level instructions從input para轉換成output para,一個簡單的例子如下 ![](https://i.imgur.com/KMGCd8D.png) Extended asm syntax uses colons (‘:’) to delimit the operand parameters after the assembler template: ![](https://i.imgur.com/dgQRZHK.png) Qualifiers (限定詞) * volatile * inline * goto Parameters * Assembler Template * https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#AssemblerTemplate * assembly code的樣板,就是一串input, output, goto的結合體 * OutputOperands * InputOperands * Clobbers (通知compiler inputs operands可能會改變) * While the compiler is aware of changes to entries listed in the output operands, the inline asm code may modify more than just the outputs. For example, calculations may require additional registers, or the processor may overwrite a register as a side effect of a particular assembler instruction. In order to inform the compiler of these changes, list them in the clobber list. * Clobber list裡面放的 * 都是些register names或 * special clobbers * cc * 代表assembly code修改了flags register. * memory * 代表assembly code有去read/write input/output operands之外的地方(for example, accessing the memory pointed to by one of the input parameters) * 為了保證memory有正確的值,GCC需要把register值flush到memory在asm執行之前 * Clobber不能overlap input/output operand * clobber list不能放stack pointer register * compiler必須保持sp前後一致 ![](https://i.imgur.com/YGY1DTP.png) * GotoLabels * asm goto allows assembly code to jump to one or more C labels > The total number of input + output + goto operands is limited to 30. 備註: *asm* statement讓妳可以assembly instructions直接跟c code互動,注意asm 只能在function裡面使用,只有Basic Asm可以在function外使用 # 6.47.2.1 Volatile GCC 可能會因為這些情況而自動做最佳化 * GCC’s optimizers sometimes discard asm statements if they determine there is no need for the output variables * the optimizers may move code out of loops if they believe that the code will always return the same result using volatile可以關掉這些最佳化程序 (就是告訴compiler我的變數是容易變動的,不要隨便忽略) asm statements沒有output operands的話,包括asm goto statements, 都是implicitly宣告成volatile的 這是一個i386的例子,沒用volatile的 這個case在做assertion checking, 用asm來做validation. dwRes沒有被其他的code用到,optimizers可以完全把asm statement丟掉,甚至把DoCheck整個拿掉 ![](https://i.imgur.com/TkyQBEY.png) 這個case是optimizers覺得the input(dwSomeValue)在這個function裡面永遠不會變,所以可以把asm移出loop外面來產生更有效率的assembly code. 你可以加個volatile前綴詞來避免這件事情發生 ![](https://i.imgur.com/J7PqHO5.png) 下面這個case就是需要用到volatile的時候 他用到了 x86 rdtsc指令,用來讀cpu's time-stamp counter.如果妳沒宣告volatile, optimizers可能會假設asm block會一直回傳same value然後就把這段code用簡單的變數replace掉了 ![](https://i.imgur.com/WIO0NAY.png) # 6.47.2.2 Assembler Template An assembler template is a literal string containing assembler instructions compiler會把template內的tokens(inputs, outputs, goto labels) replace掉然後output成assembler code. (30bytes內) combo技 用newline to break the line, 然後加上一個tab(\n\t)來移到instruction field. 有些assemblers使用分號(;)來當作line separator. 但有些用分號來當作start a comment. 注意: 在assembler template內使用global c symbols可能會有不正確的結果,建議還是要用 input/output operands. GCC不會去檢查assembler template. 他不會知道你給他的這些symbols的正確性,除非你給他的是用input,output, or goto operands # Special format strings(符號意義) * %% * Outputs a single ‘%’ into the assembler code. * %= * Outputs a number that is unique to each instance of the asm statement in the entire compilation. This option is useful when creating local labels and referring to them multiple times in a single template that generates multiple assembler instructions * %{ * %| * %} * %後面都是output出來的符號 # 6.47.2.3 Output Operands asm statement裡面有0個或多個operands來代表C變數在assembly code裡的符號 ![](https://i.imgur.com/PG5wIew.png) * outputs * old * %0 * Base * %1 * inputs * Offset * %2 Operands用 , 分開,每個operand has this format: ![](https://i.imgur.com/kcUn9Xv.png) * asmSymbolicName * 用來代表C變數的符號 * 用 %[Value] 來表示 * 如果沒有特別定義,用0號開始往上加來代表output * %0代表first * %1代表second * %2代表third * constraint * A string constant代表要被operand取代的字串 * 前綴要加 * = * + * 前綴後面還要加上一些constraint來說明value是存在哪裡的 * =r * 代表存在register * =m * 代表存在memory * =rm * compiler自己會去選去哪拿比較有效率 * cvariablename * c變數名稱 這個例子沒有用asmSymbolicName,所以他references的first output operand會是%0(如果有第二個的話就是%1),然後第一個input operand的號碼會是最後一個output operand的+1 (下面這個例子的input operand就是%1) ![](https://i.imgur.com/IWeJh98.png) * input * Mask * %1 * output * index * %0 這段code overwrites the variable Index (=), 然後把值放到register( r ) 下面這個例子是有用 asmSymbolicName的版本,效果跟上面這個是一樣的,但就可讀性來講比較好。aIndex and aMask只用在這裡而且很清楚表達了哪個names要用在哪裡 ![](https://i.imgur.com/goqfctn.png) 更多例子 ![](https://i.imgur.com/o2bSLZB.png) 這裡 d可能在register或memory裡, # 6.47.2.4 Flag Output Operands # ARM ![](https://i.imgur.com/6j6IQtX.png) ![](https://i.imgur.com/iWWKra6.png) ![](https://i.imgur.com/NPYsSz2.png) # X86 ![](https://i.imgur.com/zDnjAKJ.png) ![](https://i.imgur.com/q5H3dlZ.png) ![](https://i.imgur.com/XKtaxtT.png) ![](https://i.imgur.com/kBRgMvV.png) # 6.47.2.5 Input Operands Input operands make values from C variables and expressions available to the assembly code. ![](https://i.imgur.com/gO1ok3e.png) 編號順序緊跟在output operands後面 constraint: * Input constraint strings前綴不用加上 = 或 + * Input constraints can also be digits (for example, "0") * 如果沒有output operands,放兩個連續的冒號裡面不要放東西代表沒有。 ![](https://i.imgur.com/Rqeq0iU.png) > Warning: Do not modify the contents of input-only operands (except for inputs tied to outputs). In this example using the fictitious combine instruction, the constraint "0" for input operand 1 says that it must occupy the same location as output operand 0. Only input operands may use numbers in constraints, and they must each refer to an output operand. Only a number (or the symbolic assembler name) in the constraint can guarantee that one operand is in the same place as another. The mere fact that foo is the value of both operands is not enough to guarantee that they are in the same place in the generated assembler code. ![](https://i.imgur.com/KSGphuw.png) Here is an example using symbolic names. ![](https://i.imgur.com/rXjhuAa.png) # 6.47.2.6 Clobbers and Scratch Registers # 6.47.2.7 Goto Labels ![](https://i.imgur.com/KJIIa82.png) ![](https://i.imgur.com/QPgihjM.png)