C指標原理(6)-C內嵌彙編

lcc發表於2021-09-09


內聯彙編的重要性體現在它能夠靈活操作,而且可以使其輸出透過 C 變數顯示出來。因為它具有這種能力,所以 "asm" 可以用作彙編指令和包含它的 C 程式之間的介面。簡單得說,內聯彙編,就是可以讓程式設計師在C語言中直接嵌入彙編程式碼,並與彙編程式碼互動C程式中的C表示式,享受彙編的高執行效率。

 

 

內聯彙編的格式是直接在C程式碼中插入以下格式:

asm(

....

....

)

其中的"..."為彙編程式碼,比如下面例子中,在 result=a*b和printf("%dn",result)之間插入一段彙編,

     下面的這段彙編什麼都不做,每個nop指令佔用一個指令的執行時間

  result=a*b;

    asm("nopnt"

    "nopnt"

    "nopnt"

    "nop");//4個nop指令,nt表示換行,然後加上TAB行首空,因為每個彙編指令必須在單獨一行,需要換行,加上製表符是為了適應某些編譯器的要求。    

    printf("%dn",result);

可以很明顯地看到:

    彙編程式碼之間用“nt”間隔,並且每條彙編程式碼單獨佔用一行,共有4個nop指令,每個指令後的“nt”表示換行,然後加上TAB行首空,因為每個彙編指令必須在單獨一行,需要換行,加上製表符是為了適應某些編譯器的要求。

 下面是一個完整的例子,內嵌的彙編完成對2個C程式定義的全域性變數c和d的相加,並將相加結果存入全域性變數addresult中:

#include <stdio.h>

int c=10;

int d=20;

int addresult;

int main(void){

    int a=6;

    int b=2;

    int result;

    result=a*b;

    asm("nopnt"

    "nopnt"

    "nopnt"

    "nop");//4個nop指令,nt表示換行,然後加上TAB行首空,因為每個彙編指令必須在單獨一行,需要換行,加上製表符是為了適應某些編譯器的要求。    

    printf("%dn",result);

    asm("pushant"

    "movl c,%eaxnt"

    "movl d,%ebxnt"

    "add %ebx,%eaxnt"

    "movl %eax, addresultnt"

    "popa");//使用全域性C變數c和d    

    printf("%dn",addresult);    

    return 0;

}

編譯上述程式碼

$ gcc -o test test.c

$ ./test

12

30

在彙編程式碼中可以直接使用變數名稱操作C程式定義的全域性變數,比如c、d和addresult就是全域性變數:

    "movl c,%eaxnt"

    "movl d,%ebxnt"

    "movl %eax, addresultnt"

   內聯彙編部分如果不需要編譯器最佳化( 最佳化可能破壞彙編程式碼的內部結構,因為彙編程式碼直接操作暫存器,而暫存器使用最佳化是編譯器提供的功能), 可以在 "asm" 後使用關鍵字 "volatile"。

asm volatile(

....

....

)

如果程式必須與 ANSI C 相容,則應該使用 asm 和 volatile。

  __asm__ __volatile__(

   .........

    .........

 )

    下面的程式碼和剛才程式碼功能一樣,唯一的區別是不需要最佳化

 #include <stdio.h>

int c=10;

int d=20;

int addresult;

int main(void){

    int a=6;

    int b=2;

    int result;

    result=a*b;

    //ansi c標準的asm有其它用,所以用__asm__,__volatile__表示內聯彙編部分不用最佳化(可以用volatile,但是ansi c不行),以防最佳化破壞內聯程式碼組織結構

    __asm__ __volatile__("nopnt"

    "nopnt"

    "nopnt"

    "nop");//4個nop指令,nt表示換行,然後加上TAB行首空,因為每個彙編指令必須在單獨一行,需要換行,加上製表符是為了適應某些編譯器的要求。    

    printf("%dn",result);

    __asm__ __volatile__("pushant"

    "movl c,%eaxnt"

    "movl d,%ebxnt"

    "add %ebx,%eaxnt"

    "movl %eax, addresultnt"

    "popa");//使用全域性C變數c和d    

    printf("%dn",addresult);    

    return 0;

}

©著作權歸作者所有:來自51CTO部落格作者myhaspl的原創作品,如需轉載,請註明出處,否則將追究法律責任


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2331/viewspace-2819718/,如需轉載,請註明出處,否則將追究法律責任。

相關文章