欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

C指針原理之C內(nèi)嵌匯編的示例分析-創(chuàng)新互聯(lián)

這篇文章主要介紹了C指針原理之C內(nèi)嵌匯編的示例分析,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

成都創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),資溪企業(yè)網(wǎng)站建設(shè),資溪品牌網(wǎng)站建設(shè),網(wǎng)站定制,資溪網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷(xiāo),網(wǎng)絡(luò)優(yōu)化,資溪網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力??沙浞譂M(mǎn)足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專(zhuān)業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶(hù)成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。

內(nèi)聯(lián)匯編的重要性體現(xiàn)在它能夠靈活操作,而且可以使其輸出通過(guò) C 變量顯示出來(lái)。因?yàn)樗哂羞@種能力,所以 "asm" 可以用作匯編指令和包含它的 C 程序之間的接口。簡(jiǎn)單得說(shuō),內(nèi)聯(lián)匯編,就是可以讓程序員在C語(yǔ)言中直接嵌入?yún)R編代碼,并與匯編代碼交互C程序中的C表達(dá)式,享受匯編的高運(yùn)行效率。

內(nèi)聯(lián)匯編的格式是直接在C代碼中插入以下格式:

asm(
....
....
)

其中的"..."為匯編代碼,比如下面例子中,在 result=a*b和printf("%d\n",result)之間插入一段匯編,

    下面的這段匯編什么都不做,每個(gè)nop指令占用一個(gè)指令的執(zhí)行時(shí)間

 result=a*b;
 asm("nop\n\t"
 "nop\n\t"
 "nop\n\t"
 "nop");//4個(gè)nop指令,\n\t表示換行,然后加上TAB行首空,因?yàn)槊總€(gè)匯編指令必須在單獨(dú)一行,需要換行,加上制表符是為了適應(yīng)某些編譯器的要求。 
 printf("%d\n",result);

可以很明顯地看到:

   匯編代碼之間用“\n\t”間隔,并且每條匯編代碼單獨(dú)占用一行,共有4個(gè)nop指令,每個(gè)指令后的“\n\t”表示換行,然后加上TAB行首空,因?yàn)槊總€(gè)匯編指令必須在單獨(dú)一行,需要換行,加上制表符是為了適應(yīng)某些編譯器的要求。

下面是一個(gè)完整的例子,內(nèi)嵌的匯編完成對(duì)2個(gè)C程序定義的全局變量c和d的相加,并將相加結(jié)果存入全局變量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("nop\n\t"
 "nop\n\t"
 "nop\n\t"
 "nop");//4個(gè)nop指令,\n\t表示換行,然后加上TAB行首空,因?yàn)槊總€(gè)匯編指令必須在單獨(dú)一行,需要換行,加上制表符是為了適應(yīng)某些編譯器的要求。 
 printf("%d\n",result);
 asm("pusha\n\t"
 "movl c,%eax\n\t"
 "movl d,%ebx\n\t"
 "add %ebx,%eax\n\t"
 "movl %eax, addresult\n\t"
 "popa");//使用全局C變量c和d 
 printf("%d\n",addresult); 
 return 0;
}

編譯上述代碼

$ gcc -o test test.c
$ ./test
12
30

在匯編代碼中可以直接使用變量名稱(chēng)操作C程序定義的全局變量,比如c、d和addresult就是全局變量:

 "movl c,%eax\n\t"
 "movl d,%ebx\n\t"
 "movl %eax, addresult\n\t"

  內(nèi)聯(lián)匯編部分如果不需要編譯器優(yōu)化( 優(yōu)化可能破壞匯編代碼的內(nèi)部結(jié)構(gòu),因?yàn)閰R編代碼直接操作寄存器,而寄存器使用優(yōu)化是編譯器提供的功能), 可以在 "asm" 后使用關(guān)鍵字 "volatile"。

asm volatile(
....
....
)

如果程序必須與 ANSI C 兼容,則應(yīng)該使用 asm 和 volatile。

 __asm__ __volatile__(
 .........
 .........
 )

   下面的代碼和剛才代碼功能一樣,唯一的區(qū)別是不需要優(yōu)化

 #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標(biāo)準(zhǔn)的asm有其它用,所以用__asm__,__volatile__表示內(nèi)聯(lián)匯編部分不用優(yōu)化(可以用volatile,但是ansi c不行),以防優(yōu)化破壞內(nèi)聯(lián)代碼組織結(jié)構(gòu)
 __asm__ __volatile__("nop\n\t"
 "nop\n\t"
 "nop\n\t"
 "nop");//4個(gè)nop指令,\n\t表示換行,然后加上TAB行首空,因?yàn)槊總€(gè)匯編指令必須在單獨(dú)一行,需要換行,加上制表符是為了適應(yīng)某些編譯器的要求。 
 printf("%d\n",result);
 __asm__ __volatile__("pusha\n\t"
 "movl c,%eax\n\t"
 "movl d,%ebx\n\t"
 "add %ebx,%eax\n\t"
 "movl %eax, addresult\n\t"
 "popa");//使用全局C變量c和d 
 printf("%d\n",addresult); 
 return 0;
}

如何在內(nèi)聯(lián)匯編中訪(fǎng)問(wèn)C程序的局部變量呢,請(qǐng)看下面這段代碼。

#include <stdio.h>
int main(void){
  //不使用全局變量,必須使用擴(kuò)展GNU的asm
  //格式為:asm("匯編代碼":輸出位置:輸入位置:改動(dòng)的寄存器列表)
  //a為eax,ax,al;b為ebx等;c為ecx等;d為edx等;S為esi或si;D為edi或di
  //+讀和寫(xiě);=寫(xiě);%如果必要,操作數(shù)可以和下一個(gè)操作數(shù)切換;&在內(nèi)聯(lián)函數(shù)完成之前,可以刪除或重新使用操作數(shù)
  int xa=6;
  int xb=2;
  int result;
  //ansi c標(biāo)準(zhǔn)的asm有其它用,所以用__asm__,__volatile__表示內(nèi)聯(lián)匯編部分不用優(yōu)化(可以用volatile,但是ansi c不行),以防優(yōu)化破壞內(nèi)聯(lián)代碼組織結(jié)構(gòu)
  asm volatile(
  "add %%ebx,%%eax\n\t"
  "movl $2,%%ecx\n\t"
  "mul %%ecx\n\t"  
  "movl %%eax,%%edx"
   :"=d"(result):"a"(xa),"b"(xb):"%ecx");//注意擴(kuò)展方式使用2個(gè)%表示  
  printf("%d\n",result);
  return 0;
}

這個(gè)例子完成這個(gè)計(jì)算:(xa+xb)2=(6+2)2=16

    不使用全局變量與匯編代碼交互,我們必須使用擴(kuò)展GNU的asm ,格式為:

     asm("匯編代碼":輸出位置:輸入位置:改動(dòng)的寄存器列表)

      匯編代碼中涉及寄存器部分的使用2個(gè)“%”,如:使用%%eax表示eax寄存器

      輸出位置、輸入位置的特殊命名規(guī)則為:

     a為eax,ax,al;b為ebx等;c為ecx等;d為edx等;S為esi或si;D為edi或di

     +讀和寫(xiě)

     =寫(xiě)

     %如果必要,操作數(shù)可以和下一個(gè)操作數(shù)切換

     &在內(nèi)聯(lián)函數(shù)完成之前,可以刪除或重新使用操作數(shù)

   上述代碼中,匯編代碼部分為

   輸出位置、輸入位置、改動(dòng)的寄存器列表部分為:
     :"=d"(result):"a"(xa),"b"(xb):"%ecx"

    先來(lái)看匯編代碼部分,使用雙%號(hào)表示寄存器,比如:

    "add %%ebx,%%eax\n\t"

     關(guān)于輸出位置、輸入位置部分,可以這么理解:將變量與寄存器綁定,綁定后,對(duì)寄存器的操作就是對(duì)變量的操作。

      :"=d"(result):"a"(xa),"b"(xb)

      將result與寄存器edx綁定,xa與寄存器eax綁定,xb與寄存器ebx綁定。
       %ecx屬于需要改動(dòng)的寄存器

#include <stdio.h>
int main(void){
  int xa=6;
  int xb=2;
  int result;
  //使用占位符,由r表示,編譯器自主選擇使用哪些寄存器,%0,%1。。。表示第1、2。。。個(gè)變量
  asm volatile(
  "add %1,%2\n\t" 
  "movl %2,%0"
   :"=r"(result):"r"(xa),"r"(xb));  
  printf("%d\n",result);
  return 0;
}

result、xa、xb綁定的寄存器由編譯器決定,前面的例子中我們采用直接指定的方式,在這里我們改成由編譯器

自主選擇,"r"是占位符,表示由編譯器自主選擇使用哪些寄存器,不指定哪個(gè)變量綁定在哪個(gè)寄存器上,

:"=r"(result):"r"(xa),"r"(xb)

那我們?nèi)绾沃肋@些變量綁定在哪些寄存器上呢,不知道綁定的寄存器,如何對(duì)變量進(jìn)行操作呢,可以使用

%0,%1這樣的符號(hào)來(lái)代替要操作的寄存器,%后的數(shù)字表示第幾個(gè)變量,如:%0,%1。。。表示第1、2。。。個(gè)變量。

:"=r"(result):"r"(xa),"r"(xb)

上面這個(gè)輸出和輸入列表已經(jīng)指定了變量的順序,

result是第0個(gè),xa是第1個(gè),xb是第2個(gè)

  下面的例子完成   xb=xb-xa的計(jì)算,問(wèn)題出現(xiàn)了,可能會(huì)導(dǎo)致xb被分配了2個(gè)寄存器:

   :"=r"(xb):"r"(xa),"r"(xb));

   使用引用占位符能有效地使用可用寄存器,在這里我們指定xb使用第0個(gè)變量綁定的寄存器

   :"=r"(xb):"r"(xa),"0"(xb));

   第0個(gè)變量就是xb,即xb綁定的寄存器被修改后,結(jié)果仍寫(xiě)回原寄存器

   下面是完整例子

#include <stdio.h>
int main(void){
int xa=2;
int xb=6;
asm volatile(
"subl %1,%0\n\t" 
:"=r"(xb):"r"(xa),"0"(xb)); 
printf("%d\n",xb);
return 0;
}

我們編譯運(yùn)行一下

  $ gcc -o test test.c
  $ ./test

  4

  用數(shù)字來(lái)表示變量的順序也許很麻煩,我們可以使用更簡(jiǎn)單的方法,使用“[標(biāo)識(shí)]”的格式標(biāo)記綁定后的變量。  下面的代碼完成xb=xb+xa的計(jì)算

#include <stdio.h>
int main(void){
  int xa=6;
  int xb=2;
  asm volatile(
  "add %[mya],%[myb]\n\t" 
   :[myb]"=r"(xb):[mya]"r"(xa),"0"(xb));  
  printf("%d\n",xb);
  return 0;
}

我們使用m標(biāo)記可以直接在內(nèi)存中對(duì)數(shù)進(jìn)行操作,前面的例子對(duì)變量進(jìn)行操作時(shí)都需要將變量值存儲(chǔ)在要修改的寄存器中,然后將它寫(xiě)回內(nèi)存位置中.

#include <stdio.h>
int main(void){
  int xa=2;
  int xb=6;
   asm volatile(
  "subl %1,%0\n\t" 
   :"=r"(xb):"m"(xa),"0"(xb));  
  printf("%d\n",xb);
  return 0;
}

我們直接從xa的內(nèi)存地址中將xa取出,而不需要再將xa先存儲(chǔ)在一個(gè)寄存器。

首先,我們看一下AT&T匯編各段的意義

節(jié) 含義
.text 已編譯程序的機(jī)器代碼
.rodata 只讀數(shù)據(jù),如pintf和switch語(yǔ)句中的字符串和常量值
.data 已初始化的全局變量
.bss 未初始化的全局變量
.symtab 符號(hào)表,存放在程序中被定義和引用的函數(shù)和全局變量的信息
.rel.text 當(dāng)鏈接器吧這個(gè)目標(biāo)文件和其他文件結(jié)合時(shí),.text節(jié)中的信息需修改
.rel.data 被模塊定義和引用的任何全局變量的信息
.debug 一個(gè)調(diào)試符號(hào)表。
.line 原始C程序的行號(hào)和.text節(jié)中機(jī)器指令之間的映射
.strtab 一個(gè)字符串表,其內(nèi)容包含.systab和.debug節(jié)中的符號(hào)表

上面列表也許比較抽象,我們從一個(gè)C程序生成的中間匯編代碼分析:

#include <stdio.h>

void main(){

  char *x="xxxx";

  char y[]="yy";//y的16進(jìn)制ASCII碼是97,9797的十進(jìn)制為31097

  printf("%s-----%s",x,y);

  exit(0);

}

我們使用gcc -S testcr.c,查看編譯生成的匯編代碼(為便于理解,將生成的匯編代碼進(jìn)行了注釋?zhuān)?/p>

.file  "testcr.c"

  .section  .rodata

.LC0:

  .string "xxxx"#使用char *分配

.LC1:

  .string "%s-----%s"

  .text

.globl main

  .type  main, @function

main:

  pushl  %ebp

  movl  %esp, %ebp

  andl  $-16, %esp

  subl  $32, %esp#分配32字節(jié)棧空間,根據(jù)變量情況分配

  movl  $.LC0, 24(%esp)#x變量使用指針(4個(gè)字節(jié)大小),放入棧中,可以看到,變量分配靠近??臻g的尾部

  movw  $31097, 29(%esp)#字符'yy'移到main程序的棧中,直接將y變量的值放入棧中

  movb  $0, 31(%esp)#加上NULL標(biāo)志,表示字符結(jié)束 

  movl  $.LC1, %eax

  leal  29(%esp), %edx

  movl  %edx, 8(%esp)

  movl  24(%esp), %edx

  movl  %edx, 4(%esp)

  movl  %eax, (%esp)

  call  printf

  movl  $0, (%esp)

  call  exit

  .size  main, .-main

  .ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"

  .section  .note.GNU-stack,"",@progbits

在MAIN函數(shù)中char *分配在只讀數(shù)據(jù)段中,實(shí)際使用時(shí),只在程序棧中分配一個(gè)指針的空間。char[] 在程序棧中分配空間,然后直接使用movl、movw之類(lèi)的匯編直接把值放入棧中空間。那么在其它函數(shù)中聲明的呢,可以從以下程序中看出,仍然如此。

#include <stdio.h>

void myprinf(){

  char *x="xxxx";

  char y[]="yy";//y的16進(jìn)制ASCII碼是97,9797的十進(jìn)制為31097

  printf("%s-----%s",x,y);

}

void main(){

  int num=1;

  myprint();

  exit(0);

}

生成的中間匯編代碼為:

.file "testcr.c"


  .section  .rodata

.LC0:

  .string "xxxx"

.LC1:

  .string "%s-----%s"

  .text

.globl myprinf

  .type  myprinf, @function

myprinf:

  pushl  %ebp

  movl  %esp, %ebp

  subl  $40, %esp

  movl  $.LC0, -16(%ebp)

  movw  $31097, -11(%ebp)

  movb  $0, -9(%ebp)

  movl  $.LC1, %eax

  leal  -11(%ebp), %edx

  movl  %edx, 8(%esp)

  movl  -16(%ebp), %edx

  movl  %edx, 4(%esp)

  movl  %eax, (%esp)

  call  printf

  leave

  ret

  .size  myprinf, .-myprinf

.globl main

  .type  main, @function

main:

  pushl  %ebp

  movl  %esp, %ebp

  andl  $-16, %esp

  subl  $32, %esp

  movl  $1, 28(%esp)

  call  myprint

  movl  $0, (%esp)

  call  exit

  .size  main, .-main

  .ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"

  .section  .note.GNU-stack,"",@progbits

內(nèi)存的常用分配方式有:

第一,靜態(tài)分配,所有名字在編譯時(shí)綁定某個(gè)存儲(chǔ)位置。不能在運(yùn)行時(shí)改變
第二,棧分配,活動(dòng)時(shí)壓入系統(tǒng)棧。
第三,堆分配,以任意次序分配

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“C指針原理之C內(nèi)嵌匯編的示例分析”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián)建站,關(guān)注創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)建站chinadenli.net,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線(xiàn),公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性?xún)r(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿(mǎn)足用戶(hù)豐富、多元化的應(yīng)用場(chǎng)景需求。

網(wǎng)頁(yè)標(biāo)題:C指針原理之C內(nèi)嵌匯編的示例分析-創(chuàng)新互聯(lián)
分享路徑:http://chinadenli.net/article2/dcjjoc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供域名注冊(cè)網(wǎng)站設(shè)計(jì)公司、Google、網(wǎng)站營(yíng)銷(xiāo)響應(yīng)式網(wǎng)站、定制開(kāi)發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁(yè)設(shè)計(jì)
黄片在线免费观看全集| 国产黑人一区二区三区| 爱在午夜降临前在线观看| 日韩欧美国产高清在线| 91欧美亚洲视频在线| 欧美成人黄色一区二区三区| 亚洲午夜精品视频观看| 日本高清二区视频久二区| 国产精品亚洲精品亚洲| 国产三级不卡在线观看视频| 日韩人妻免费视频一专区| 一区中文字幕人妻少妇| 国产中文字幕久久黄色片| 国产精品日韩精品一区| 人妻熟女欲求不满一区二区| 东京热男人的天堂社区| 久久大香蕉一区二区三区| 国产一区一一一区麻豆| 在线观看视频成人午夜| 日韩精品一区二区三区四区| 亚洲国产四季欧美一区| 婷婷色网视频在线播放| 台湾综合熟女一区二区| 麻豆精品视频一二三区| 91亚洲国产—区=区a| 欧美日韩精品综合在线| 欧美日韩综合在线第一页| 亚洲国产婷婷六月丁香| 亚洲男人天堂网在线视频| 亚洲一区二区三区三区| 大伊香蕉一区二区三区| 人人妻人人澡人人夜夜| 日本人妻丰满熟妇久久| 一区二区欧美另类稀缺| 日韩午夜福利高清在线观看| 高清在线精品一区二区| 九九热这里只有精品视频| 少妇熟女精品一区二区三区| 国产综合香蕉五月婷在线| 美国黑人一级黄色大片| 久久精品国产亚洲av麻豆尤物|