內聯彙編

1.gcc編譯程序支持的另一種編碼形式是內聯彙編(inline assembly)代碼。內聯彙編不需要調用單獨編譯的彙編程序。我們可以通過特定的結構告訴編譯程序將代碼組合到一起,而不是要編譯該代碼塊。雖然這樣做會生成體系結構相關的文件,但能大大提高C函數的可讀性並提高其執行效率。

內聯彙編程序的結構:

asm ( assembler instruction (s)

 :output operands (optional)

 :input operands(optioanl)

 : clobbered registers (optional)

);

 

內聯彙編程序最基本的形式是:

asm ("movl %eax,%ebx");

也可以寫成:

asm ("movl %eax,%ebx" : : :);

輸出操作數:是一個C表達式列表,其後的圓括號中是約束條件。約束條件通常用“=”來表示,表示“只寫”;“&”表示這是一個已經被修改過的操作數

輸入操作數:語法同上,只是不用“=”修飾

修改過的寄存器:列出修改過的寄存器和內存

2.參數的編號方式

所有參數從0開始統一編號

例如,若有一個輸出參數和2個輸入參數,則%0是輸出參數,%1和%2都是輸入參數

3.約束條件

a:寄存器eax

b:寄存器ebx

c:寄存器ecx

d: 寄存器edx

S:寄存器esi

D:寄存器edi

I:常數(0....31)

q:從eax,ebx,ecx,edx動態分配一個寄存器

r:與q+esi,edi一樣

m:內存定位

A:與a+b的作用一樣。同時分配eax和ebx,形成一個64位寄存器

。。。。。

_volatile_:不要優化

例1:

int foo(void)

{

    int ee=0x4000,ce=0x8000,reg;

    _asm_  _volatile_("movl %1,%%eax",//將ce的值傳給eax

    "movl %2,%%ebx";//將ee的值傳給ebx

    "call setbits";//在彙編程序中調用函數

    "movl %%eax,%0"//將返回值存儲到eax中,並將其複製給reg

    : "=r"(reg)//輸出參數列表,reg屬性爲只寫

    : "r"(ce),"r"(ee)//輸入參數列表,ce和ee是寄存器變量

    : "%eax","%ebx"//寄存器修改列表,

)

printf("reg=%x",reg);

 

}

例2:

#define switch_to(prev,next,last) do{

 unsigned long esi,edi;//局部變量

 asm volatile(

"pushfl /n/t"

"pushl %%ebp/n/t"

 "movl %%esp,%0/n/t"//把esp值複製給prev->thread.esp

" movl %5,%%esp/n/t"//將next->thread.esp賦值給esp

" movl $1f,%1/n/t"//保存eip的值

"pushl  %6/n/t"//重新給eip賦值

"jmp _switch_to /n"

"1:/t"//參數被用作返回地址

"popl %%ebp/n/t"

"popfl"

:"=m" (prev->thread.esp),"=m"(prev->thread.eip),"=a"(last),"=S"(esi),"=D"(edi)//輸出參數列表

:"m"(next->thread.esp),"m"(next->thread.eip),"2"(prev),"d"(next)//輸入參數列表

);

}while(0)

/n/t與彙編程序的接口有關。每條彙編指令都應該在各自的線路上運行

輸出參數列表:

[%0]=(prev->thread.esp),只寫內存

[%1]=(prev->thread.eip),只寫內存

[%2]=(last),對寄存器eax只寫

[%3]=(esi),對寄存器esi只寫

[%4]=(edi),對寄存器edi只寫

輸入參數列表:

[%5]=(next->thread.esp),內存

[%6]=(next->thread.eip),內存

[%7]=(prev),重新使用2號參數(寄存器eax)作爲輸入

[%8]=(next),是賦給寄存器edx的一個輸入

此處沒有已修改寄存器列表

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章