在使用gcc編譯的時候,可以在c語言程式中巢狀彙編指令,這樣極大的方便在高階語言中使用跟配件相關的指令。
(1) 在gcc中巢狀的彙編指令跟純彙編檔案的語法有一點不一樣,在gcc中巢狀指令的格式是固定的:
__asm__(code : output operand list : input operand list : clobber list);
__asm__(彙編語句模板 : 輸出部分 : 輸入部分 : 破壞描述部分);
其中包括四個部分,每個部分之間使用":"分開
彙編語句模板是彙編命令的字串,
輸出部分
是需要輸出到c變數引數列表,
輸入部分
是需要從c變數輸入到asm彙編的引數列表,
破壞描述部分
是指執行彙編指令會破壞的暫存器描述。
第一部分是必須寫的,後面三部分是可以省略,但是分號":"不能省略!
例如:__asm__("cli":::);
乙個巢狀彙編塊裡面可以寫多條彙編指令,指令之間需要換行符隔開 「
\n" 或分號"
;"隔開,如:
__asm__("mrs r0, cpsr \n"
"orr r0, r0, #128\n"
"msr cpsr_c, r0\n"
:
:
:);
(2) 巢狀彙編裡面可以訪問c語言所定義的變數,
可以在輸入部分,給彙編指令傳遞c語言定義的引數,也可以在輸出部分把彙編指令中得到的值傳遞到c語言所定義的變數中。
例如:
上面**中,
%0 表示第乙個引數,
%1 表示第二個引數,依此類推,可以得到其它的引數,
這是老版本的gcc的方法了,好像只可以支援到10個引數。
新版本的是可以直接在彙編中使用引數名來訪問的,不過大部分原始碼還是使用%0的方法,這裡也只看這個方法。
-->"=r" (x), "=r" (temp)
這裡是輸出的列表,每個引數是以逗號","隔開的,
"=r"(x)表示asm中第乙個引數的值儲存到變數x中;
"=r"(temp)表示asm中第二個引數的值儲存到變數temp中.
-->如果是需要輸入引數的話,則輸入部分,把"="號去除,
unsigned long x;
__asm__ __volatile__(
"msr cpsr_c, %0 \n"
: : "r" (x)
: "memory", "cc");
上面**就是把變數x傳入到彙編指令當中去,後面的破壞描述符會告訴編譯器哪個暫存器被使用了,避免暫存器使用衝突。
(3) "memory"描述符 表示
1.將不重新排序該段內嵌彙編指令與前面的指令。
2.不使用暫存器作為快取。
嵌入式中C和彙編的一些技巧
arm彙編部分 a.條件執行 cmp r0,5 beq bypass add r1,r1,r0 sub r1,r1,r2 bypass 可以替代為 cmp r0,5 addne r1,r1,r0 subne r1,r1,r2 如果被跳過的指令序列並不進行複雜的操作,使用條件執行都要比使用轉移好,因為...
嵌入式C中volatile和const的用法
volatile本意為 易變的 在嵌入式環境中用volatile關鍵字宣告的變數,在每次對其值進行引用的時候都會從原始位址取值,而不會將值儲存在棧或其他位置。由於該值 易變 的特性所以,針對其的任何賦值或者獲取值操作都會被執行 而不會被優化 由於這個特性,所以該關鍵字在嵌入式編譯環境中經常用來消除c...
嵌入式中C語言的位操作
位運算構建特定的二進位制數 技術公升級 使用巨集定義完成位運算 總結在操作中使用 將暫存器某些 特定位變成0,但是不影響其他位,可以進行如下操作,假設原來的暫存器reg1中的值為0xaaaaaaaa,希望將bit8 bit15清零並且其他位不進行改變,將這個數和0xffff00ff進行位與即可。re...