電子發(fā)燒友App

硬聲App

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示
創(chuàng)作
電子發(fā)燒友網(wǎng)>電子資料下載>C語言|源代碼>高效的C編程之函數(shù)調用

高效的C編程之函數(shù)調用

2017-10-17 | rar | 0.5 MB | 次下載 | 1積分

資料介紹

14.9 函數(shù)調用
  函數(shù)設計的基本原則是使其函數(shù)體盡量的小。這樣編譯器可以對函數(shù)做更多的優(yōu)化。
  14.9.1 減少函數(shù)調用開銷
  ARM上的函數(shù)調用開銷比非RISC體系結構上的調用開銷?。?br />   · 調用返回指令“BL”或“MOV pc,lr”一般只需要6個指令周期(ARM7上)。
  · 在函數(shù)的入口和出口使用多寄存器加載/存儲指令LDM和STM(Thumb指令使用PUSH和POP)提高函數(shù)體的執(zhí)行效率。
  ARM體系結構過程調用標準AAPCS定義了如何通過寄存器傳遞參數(shù)和返回值。函數(shù)中的前4個整型參數(shù)是通過ARM的前4個寄存器r0、r1、r2和r3來傳遞的。傳遞參數(shù)可以是與整型兼容的數(shù)據(jù)類型,如字符類型char、半字類型short等。
  注意如果是雙字類型,如long long型,只能通過寄存器傳遞兩個參數(shù)。
  不能通過寄存器傳遞的參數(shù),通過函數(shù)堆棧來傳遞。這樣不論是函數(shù)的調用者還是被調用者都必須通過訪問堆棧來訪問參數(shù),使程序的執(zhí)行效率下降。
  下面的例子顯示了函數(shù)調用是傳遞4個參數(shù)和多于4個參數(shù)的區(qū)別。
  傳遞4個參數(shù)的函數(shù)調用源文件如下。
  int func1(int a, int b, int c, int d)
  {
  return a+b+c+d;
  }
  int caller1(void)
  {
  return func1(1,2,3,4);
  }
  編譯的結果如下。
  func1
  ADD r0,r0,r1
  ADD r0,r0,r2
  ADD r0,r0,r3
  MOV pc,lr
  caller1
  MOV r3,#4
  MOV r2,#3
  MOV r1,#2
  MOV r0,#1
  B func1
  如果程序需要傳遞6個參數(shù),變?yōu)槿缦滦问健?br />   int func2(int a, int b, int c, int d,int e,int f)
  {
  return a+b+c+d+e+f;
  }
  int caller2(void)
  {
  return func1(1,2,3,4,5,6);
  }
  則編譯后的匯編文件如下。
  func2
  STR lr, [sp,#-4]!
  ADD r0,r0,r1
  ADD r0,r0,r2
  ADD r0,r0,r3
  LDMIB sp,{r12,r14}
  ADD r0,r0,r12
  ADD r0,r0,r14
  LDR pc,{sp},#4
  caller2
  STMFD sp!,{r2,r3,lr}
  MOV r3,#6
  MOV r2,#5
  STMIA sp,{r2,r3}
  MOV r3,#4
  MOV r2,#3
  MOV r1,#2
  MOV r0,#1
  BL func2
  LDMFD sp!,{r2,r3,pc}
  綜上所述,為了在程序中高效的調用函數(shù),最好遵循以下規(guī)則。
  · 盡量限制函數(shù)的參數(shù),不要超過4個,這樣函數(shù)調用的效率會更高。
  · 當傳遞的參數(shù)超過4個時,要將多個相關參數(shù)組織在一個結構體中,用傳遞結構體指針來代替多個參數(shù)。
  · 避免將傳遞的參數(shù)定義為long long型,因為傳遞一個long long型的數(shù)據(jù)將會占用兩個32位寄存器。
  · 函數(shù)中存在浮點運算時,避免使用double型參數(shù)。
  14.9.2 使用__value_in_regs返回結構體
  編譯選項__value_in_regs指示編譯器在整數(shù)寄存器中返回4個整數(shù)字的結構或者在浮點寄存器中返回4個浮點型或雙精度型值,而不使用存儲器。
  下面的例子顯示了__value_in_regs選項的用法。
  typedef struct { int hi; uint lo; } int64; // 注意該結構中,高位為有符號整數(shù),低位為無符號整數(shù)
  __value_in_regs int64 add64(int64 x, int64 y)
  { int64 res;
  res.lo = x.lo + y.lo;
  res.hi = x.hi + y.hi;
  if (res.lo 《 y.lo) res.hi++; // carry from low word
  return res;
  }
  void test(void)
  { int64 a, b, c, sum;
  a.hi = 0x00000000; a.lo = 0xF0000000;
  b.hi = 0x00000001; b.lo = 0x10000001;
  sum = add64(a, b);
  c.hi = 0x00000002; c.lo = 0xFFFFFFFF;
  sum = add64(sum, c);
  }
  編譯后的結果如下所示。
  add64
  ADDS a2,a2,a4
  ADC a1,a3,a1
  MOV pc,lr
  test
  STMDB sp!,{lr}
  MOV a1,#0
  MOV a2,#&f0000000
  MOV a3,#1
  MOV a4,#&10000001
  BL add64
  MOV a3,#2
  MVN a4,#0
  LDMIA sp!,{lr}
  B add64
  當使用__value_in_regs定義結構體時,編譯的代碼大小為52字節(jié),如果不使用__value_in_regs選項,則編譯出的結果為160字節(jié)(本書中沒有列出未使用__value_in_regs時的編譯結果,讀者有興趣可以自己上機試驗)。
  14.9.3 葉子函數(shù)
  所謂葉子函數(shù)(leaf function)就是在其函數(shù)體內不存在對其他函數(shù)調用,它也常被稱為終級函數(shù)。因為葉子函數(shù)不需要調用其他函數(shù),所有沒有保存/恢復寄存器的操作,因此執(zhí)行效率比一般函數(shù)要高。
  當函數(shù)中必須對一些寄存器進行保存時,可以使用高效率的多寄存器存儲指令STM,對需要保存的寄存器內存一次性存儲。
  正是由于葉子函數(shù)執(zhí)行的高效性,所以在編程時,盡量將子程序編寫為葉子函數(shù),這樣即使程序中多次調用也不會影響代碼性能。
  為了高效的調用函數(shù),可以遵循下面函數(shù)調用原則。
  · 避免在被頻繁調用的函數(shù)中調用其他函數(shù),以保證被頻繁調用的函數(shù)被編譯器編譯為葉子函數(shù)。
  · 把比較小的被調用函數(shù)和調用函數(shù)放在同一個源文件中,并且要先定義后調用,編譯器就可以優(yōu)化函數(shù)調用或內聯(lián)較小的函數(shù)。
  · 對性能影響較大的重要函數(shù)可使用關鍵字_inline進行內聯(lián)。
  14.9.4 嵌套優(yōu)化
  注意嵌套優(yōu)化(Tail-Call optimization)只適用于armcc。編譯時如果使用-g或-debug選項,編譯器自動關閉該功能。
  一個函數(shù)如果在其結束時調用了另一個函數(shù),則編譯器使用B指令調轉到被調用函數(shù),而非BL指令。這樣就避免了一級不必要的函數(shù)返回。圖14.3顯示了嵌套優(yōu)化的調用過程。
  高效的C編程之函數(shù)調用
  圖14.3 嵌套優(yōu)化函數(shù)調用過程
  當編譯時使用-O1或-O2選項時,編譯器都執(zhí)行這種嵌套優(yōu)化。需要注意的是,當函數(shù)中引用了局部變量地址,由于指針別名問題的影響,即使函數(shù)在返回時調用了其他函數(shù),編譯器也不會使用嵌套優(yōu)化。
  下面通過一個例子來分析嵌套優(yōu)化是如何提高代碼執(zhí)行效率的。
  extern int func2(int);
  int func1 (int a, int b)
  { if (a 》 b)
  return (func2(a - b));
  else
  return (func2(b - a));
  }
  編譯后的代碼如下所示。
  func1
  CMP a1,a2
  SUBLE a1,a2,a1
  SUBGT a1,a1,a2
  B func2
  首先,func1中使用B指令代替BL指令,不用擔心lr寄存器被破壞,減少了對寄存器壓棧保護操作。另外,程序直接從func2返回到調用func1的函數(shù),減少一次函數(shù)返回。如果說正常的指令調用過程為:
  BL + BL+ MOV pc,lr + MOV pc,lr
  那么經過嵌套優(yōu)化的函數(shù)調用過程就可以表示為:
  BL + BL+ MOV pc,lr
  這樣,總的開銷將減少25%。
  14.9.5 單純子函數(shù)
  所謂單純子函數(shù)(Pure Functions)是指那些函數(shù)返回值只和調用參數(shù)有關。換句話說,就是如果調用函數(shù)的參數(shù)相同,那么函數(shù)的返回結果也相同。如果程序中存在這樣的函數(shù),可以在函數(shù)定義時使用_pure進行聲明,這樣在程序編譯時編譯器會根據(jù)函數(shù)的調用情況對其進行優(yōu)化。
  下面的例子顯示了當函數(shù)用_pure聲明時,編譯器對其所做的優(yōu)化。
  程序源碼文件如下。
  int square(int x)
  {
  return x * x;
  }
  int f(int n)
  {
  return square(n) + square(n)
  }
  編譯后的結果如下。
  square
  MOV a2,a1
  MUL a1,a2,a2
  MOV pc,lr
  f
  STMDB sp!,{lr}
  MOV a3,a1
  BL square
  MOV a4,a1
  MOV a1,a3
  BL square
  ADD a1,a4,a1
  LDMIA sp!,{pc}
  上面的程序中,square函數(shù)為“單純子函數(shù)”,當使用_pure聲明該函數(shù)時編譯器在調用該函數(shù)時,將對程序進行優(yōu)化。
  聲明的方法和編譯后的結果如下所示。
  __pure int square(int x)
  {
  return x * x;
  }
  f
  STMDB sp!,{lr}
  BL square
  MOV a1,a1,LSL #1
  LDMIA sp!,{pc}
  從編譯后的代碼中可以看到,用_pure聲明的函數(shù)在f函數(shù)中只調用了一次。
  雖然“單純子函數(shù)”可以提高代碼執(zhí)行效率,但同時也會帶來一些負面影響。比如,在“單純子函數(shù)”中,不能直接或間接訪問內存地址。所以在程序中使用“單純子函數(shù)”時要特別小心。
  另外,還可以使用#pragma聲明“單純子函數(shù)”,下面的代碼顯示了它的聲明過程。
  #pragma no_side_effects
  /* function definition */
  #pragma side_effects
下載該資料的人也在下載 下載該資料的人還在閱讀
更多 >

評論

查看更多

下載排行

本周

  1. 1電子電路原理第七版PDF電子教材免費下載
  2. 0.00 MB  |  1490次下載  |  免費
  3. 2單片機典型實例介紹
  4. 18.19 MB  |  92次下載  |  1 積分
  5. 3S7-200PLC編程實例詳細資料
  6. 1.17 MB  |  27次下載  |  1 積分
  7. 4筆記本電腦主板的元件識別和講解說明
  8. 4.28 MB  |  18次下載  |  4 積分
  9. 5開關電源原理及各功能電路詳解
  10. 0.38 MB  |  10次下載  |  免費
  11. 6基于AT89C2051/4051單片機編程器的實驗
  12. 0.11 MB  |  4次下載  |  免費
  13. 7藍牙設備在嵌入式領域的廣泛應用
  14. 0.63 MB  |  3次下載  |  免費
  15. 89天練會電子電路識圖
  16. 5.91 MB  |  3次下載  |  免費

本月

  1. 1OrCAD10.5下載OrCAD10.5中文版軟件
  2. 0.00 MB  |  234313次下載  |  免費
  3. 2PADS 9.0 2009最新版 -下載
  4. 0.00 MB  |  66304次下載  |  免費
  5. 3protel99下載protel99軟件下載(中文版)
  6. 0.00 MB  |  51209次下載  |  免費
  7. 4LabView 8.0 專業(yè)版下載 (3CD完整版)
  8. 0.00 MB  |  51043次下載  |  免費
  9. 5555集成電路應用800例(新編版)
  10. 0.00 MB  |  33562次下載  |  免費
  11. 6接口電路圖大全
  12. 未知  |  30320次下載  |  免費
  13. 7Multisim 10下載Multisim 10 中文版
  14. 0.00 MB  |  28588次下載  |  免費
  15. 8開關電源設計實例指南
  16. 未知  |  21539次下載  |  免費

總榜

  1. 1matlab軟件下載入口
  2. 未知  |  935053次下載  |  免費
  3. 2protel99se軟件下載(可英文版轉中文版)
  4. 78.1 MB  |  537791次下載  |  免費
  5. 3MATLAB 7.1 下載 (含軟件介紹)
  6. 未知  |  420026次下載  |  免費
  7. 4OrCAD10.5下載OrCAD10.5中文版軟件
  8. 0.00 MB  |  234313次下載  |  免費
  9. 5Altium DXP2002下載入口
  10. 未知  |  233045次下載  |  免費
  11. 6電路仿真軟件multisim 10.0免費下載
  12. 340992  |  191183次下載  |  免費
  13. 7十天學會AVR單片機與C語言視頻教程 下載
  14. 158M  |  183277次下載  |  免費
  15. 8proe5.0野火版下載(中文版免費下載)
  16. 未知  |  138039次下載  |  免費