色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
电子发烧友
开通电子发烧友VIP会员 尊享10大特权
海量资料免费下载
精品直播免费看
优质内容免费畅学
课程9折专享价
創(chuàng)作中心

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

3天內不再提示

嵌入式系統(tǒng)中函數如何調用

jf_78858299 ? 來源:汽車控制與人工智能 ? 作者:Demu ? 2023-02-13 14:15 ? 次閱讀

1 程序的內存分布

嵌入式系統(tǒng)中,一個函數調用時,它的內部機理是什么,執(zhí)行了哪些步驟?如圖1所示,先看 看 一個程序在運行時,它的內存分布狀況。

圖片

*** 圖1 系統(tǒng)中的內存分布***

當程序運行時,它的代碼會被裝入內存,保存在代碼區(qū),包括主函數和其他函數。主要有三塊內存區(qū)域用來存放數據:

第一塊是全局變量區(qū)域,存放了程序當中的所有全局變量。由于全局變量的個數和大小是已知的,所以這一塊區(qū)域所占用的內存大小在開始就確定下來,它們被稱為是靜態(tài)分配。位于此區(qū)域內的變量,它們在程序的整個運行過程當中,都一直存在,只有當整個程序運行結束了, 這一塊內存區(qū)域才會被釋放。

第二塊區(qū)域是棧(stack)區(qū)域,它包含了所有的棧幀。所謂的棧幀( stack frame),就是在調用函數時,系統(tǒng)自動地為該函數分配一塊內存區(qū)域,用來保存它的運行上下文、形參和局部變量等信息,這樣的一塊內存區(qū)域,就叫做一個棧幀。棧幀是在函數調用時分配,當函數調用結束,相應的棧幀則被釋放。所以,對于一個函數的局部變量來說,只有當函數調用發(fā)生時,系統(tǒng)才會給這個函數的形參和局部變量分配存儲空間;當函數調用結束后,這些局部變量就被釋放掉了。另外,棧區(qū)是由系統(tǒng)自動分配,用戶不需要關心,所以也稱為是自動分配。

第三塊區(qū)域是堆(heap) 區(qū)域,它主要是用作動態(tài)分配的內存。

舉個例子對應起來看,直觀一些。

圖片

*** 圖2 內存分布示例***

如圖2所示,程序開始運行,demudashu()這個函數會被裝入到內存。它的代碼存放在內存的代碼區(qū)域。由于在這段程序中定義了一個全局變量z,所以內存的全局變量區(qū)域分配了一個存儲單元給它。

接下來,系統(tǒng)調用函數運行,當這個函數調用發(fā)生,系統(tǒng)就會在棧中給它分配一塊內存空間,即一個棧幀,用來存放函數當中所定義的局部變量,即x和y。

隨后,程序計數器PC就跳轉到函數的第一條語句,開始執(zhí)行。

當函數執(zhí)行結束,首先要把它所占用的棧幀釋放掉。對于任何一次函數調用而言,在函數調用結束后,都要把相應的棧幀釋放掉,所以x和y這兩個局部變量所占用的存儲空間就被釋放掉了。

當一次函數調用發(fā)生時,它的執(zhí)行過程可以歸納為以下5個步驟:

  1. 在內存的棧空間當中為其分配一個棧幀,用來存放該函數的形參變量和局部變量。
  2. 把實參變量的值復制到相應的形參變量中。
  3. 控制流轉移到該函數的起始位置。
  4. 該函數開始執(zhí)行。
  5. 當這個函數執(zhí)行完以后,控制流和返回值返回到函數調用點。

下面用一個例子來總結下變量的存儲與作用域。

/* 全局變量,固定地址,其他源文件可見*/
int  demu_global_static;
/* 靜態(tài)全局變量,固定地址,但只在本文件可見*/
static int demu_static;
/* 函數參數:位于棧幀中,動態(tài)創(chuàng)建,動態(tài)釋放*/
int foo(int auto_parameter)
{   
  /* 靜態(tài)局部變量 ,固定地址,只在本函數中可見*/   
  static int func_static;
  /* 普通局部變量,位于棧幀中,只在本函數中可見*/   
  int auto_i,auto_a[10];   
  /* 動態(tài)申請的內存空間,位于堆中*/   
  double *auto_d = malloc(sizeof (double)*2020);   
  return auto_i; 
}

2 函數的調用

有了上面的內存分配理解再來看看函數的調用。

函數調用過程分五個步驟:

①程序先執(zhí)行函數調用之前的語句;

②流程的控制轉移到被調用函數入口處,同時進行參數傳遞;

③執(zhí)行被調用函數中函數體的語句;

④流程返回調用函數的下一條指令處,將函數返回值帶回;

⑤接著執(zhí)行主調函數未執(zhí)行的語句。

圖片

*** 圖3 函數調用過程***

這樣就要求在轉到被調用函數之前,要記下當時執(zhí)行的指令的地址,還要 “保護現場” (記下當時有關的信息),方便在函數調用之后繼續(xù)執(zhí)行。在函數調用之后,流程返回到先前記下的地址處,并且根據記下的信息 “恢復現場” ,然后繼續(xù)執(zhí)行。這些過程都會花費一定的時間。如果有的函數需要頻繁的使用,則所用時間會很長,從而降低程序的執(zhí)行效率。有些實用程序對效率是有要求的,要求系統(tǒng)的響應世間短,這就需要盡量壓縮調用過程的時間。

2.1 內置函數

C語言提供了一種提高函數調用效率的方法,即在編譯時將所調用的代碼直接嵌入到主調函數中,而不是將流程轉出去。這種嵌入到主調函數中的函數稱為 內置函數 (inline function),又稱內嵌函數。有些人把它稱為內聯函數。

用法:在函數首行的左端加一個關鍵字inline即可。

還是舉個例子來看,明晰一些。

int main()
{  int i = 3, j = 5, k =8, m;
  m = max(i, j, k);
  cout << "max=" << m = endl;
  return 0;
}
inline int max(int a, int b, int c);//定義max為內置函數
{
  if (b > a)
  a = b;
  if (c > a)
  a = c;
  return a;
}

由于定義函數時指定它為內置函數,因此編譯系統(tǒng)在遇到函數調用“max(i,j,k)”時,就用max函數體的代碼代替“max(i,j,k)”,同時將實參代替形參。在聲明函數和定義函數時可以同時寫inline,也可以只在其中一處聲明inline,效果相同,都能按內置函數處理。

使用內置函數可以節(jié)省運行時間,但卻增加了目標程序的長度。假設要調用10次max函數,則編譯時先后10次將max代碼復制并插入main函數,這就增加了目標文件main函數的長度。因此一般只將規(guī)模很小而使用頻繁的函數(如定時采集數據的函數聲明為內置函數)。在函數規(guī)模很小的情況下,函數調用的時間可能相當于甚至超過執(zhí)行函數本身的時間,把它定義為內置函數,可大大減少程序的運行時間。

內置函數中不能包括復雜的控制語句,如循環(huán)語句和switch語句。

對函數做inline聲明,只是程序設計者對編譯系統(tǒng)提出的一個建議,是建議性的,而不是指令性的。并非指定為inline,編譯系統(tǒng)必須這樣做。它是根據具體情況決定的。例如對前面提到的包含循環(huán)語句和switch語句的函數或一個遞歸函數是無法進行代碼置換的,又如一個上萬行的函數,也不太可能在調用點展開。此時編譯系統(tǒng)就會忽略inline聲明,而按普通函數處理。

所以,只有規(guī)模較小而又頻繁調用的簡單函數,才適合于聲明為inline函數。

2.2 函數調用過程

前文,如圖3,已經描述到,當執(zhí)行到某一個函數時,系統(tǒng)就會跳轉過去執(zhí)行該函數,執(zhí)行完畢后接著再去執(zhí)行下一條指令。在執(zhí)行調用函數的過程中,系統(tǒng)還要根據函數完成一些工作,這些操作通過形成一個棧幀來完成。棧幀是編譯器用來實現函數調用過程的一種數據結構。C語言中,每個棧幀對應著一個未運行完的函數。

下面通過debug,看看Add()函數的執(zhí)行過程。

int Add(int a, int b)
{
  int z = 0;
  z = a + b;
  return z;
}
int main()
{
  int a = 10;
  int b = 20;
  int ret;
  ret = Add(a, b);
  printf("%d", ret);
  system("pause");
  return 0;
}

以下調試過程大家定性看一下調用過程,實際過程和嵌入式系統(tǒng)略有差異。

調用main函數之前在VC6.0編輯器可以看到main函數在_tmainCRTStartup 函數中調用的,而 _tmainCRTStartup 函數是在 mainCRTStartup 被調用的。這個過程要為函數開辟棧空間, 這塊棧空間我們稱之為函數棧幀。

圖片

棧幀的需要ebp和esp兩個寄存器。在函數調用的過程中這兩個寄存器存放了維護這個棧的棧底和棧頂指針 。ebp指向當前位于系統(tǒng)棧最上邊一個棧幀的底部,而不是系統(tǒng)棧的底部。嚴格說來,“棧幀底部”和“棧底”是不同的概念;ESP所指的棧幀頂部和系統(tǒng)棧的頂部是同一個位置。

開始調用main函數

展開main函數的調用就得為main函數創(chuàng)建棧幀,可以看到過程:

圖片

執(zhí)行上圖第一條指令:

圖片

1.壓棧,把ebp放入棧頂,而esp始終指向棧頂

2.將esp值傳給ebp,也就是讓esp,ebp移在一起

3.sub為減的意思,即將esp-0E4h賦給esp,且函數調用分配由高地址向低地址增長,因此esp向上移動,即開辟了新空間,也就是為main函數開辟空間

4.三個push壓榨分別將ebx,esi,edi按順序壓入棧頂,而esp也會指向棧頂

5.lea指令,加載有效地址;將ebp-0E4h的地址放入edi中,也就是edi指向ebp-0E4h,把39h放到ecx中,把0cccccccch放到eax中,從edi所指向的地址開始向高地址進行拷貝,拷貝的次數為ecx內容,拷貝的內容為eax內。

圖片

6.創(chuàng)建變量a與b并初始化10和20.

圖片

Add函數的調用

1.把b放入eax中,然后對eax壓棧(形參a)

2.把a放入ecx中,然后對ecx壓棧(形參b)

3.call作用:將下一條指令地址壓棧,然后進入add函數里面

圖片

注意:call語句push的是下一條指令的地址,為了函數返回時知道從哪兒接著執(zhí)行

接下來進入add函數:

A. 先把main函數ebp壓棧,保存指向main()函數棧幀底部的ebp的地址,目的是當返回時能找到main函數棧底,此時esp指向新的棧頂位置。將main函數的ebp壓棧,也是為了返回時找到main函數棧底。

B. 將esp的值賦給ebp,產生新的ebp,即Add()函數棧幀的ebp;

C. 給esp減去一個16進制數0CCh(為Add()函數預開辟空間);

D. push ebx、esi、edi;

E. lea指令,加載有效地址;

F. 初始化預開辟的空間為0xcccccccc;

圖片

G. 創(chuàng)建變量z并為其賦值;

H. 把形參a放到eax,即把10,放入eax把形參b加到eax中,即把20加到eax中再把eax放到z的位置,即把兩數之和放到z中;

I. 把z的值放到寄存器eax中返回,因為z為函數臨時開辟的變量空間等函數執(zhí)行完會銷毀,因此放寄存器中返回;

K .接下來執(zhí)行pop出棧操作,edi esi ebx依次從上向下出棧,esp 會向下移動,棧的特點:先進后出,后進先出;

L. 將ebp值賦給esp,也就是esp向下移動指向ebp位置,此時add開辟的棧空間已經銷毀;

M. pop將棧頂的元素彈出放到ebp中,也就是說將main函數的ebp放入ebp中,即ebp現在指向main函數ebp;

圖片

N. 在執(zhí)行ret后,會把之前push的地址彈出去,這時就要返回main函數,這也就是為什么之前要push這個地址,這樣call指令就完成了,接下來從那個call指令繼續(xù)執(zhí)行;

圖片

O. 把esp+8,即esp向下移,把形參銷毀;

最后就是對main函數棧幀的銷毀,方法類似。

棧幀的總結:

1.堆棧是C語言程序運行時必須的一個記錄調用路徑和參數的空間:

  • 函數調用框架;
  • 傳遞參數;
  • 保存返回地址;
  • 提供局部變量空間;
  1. 堆棧寄存器和堆棧操作

堆棧相關的寄存器

  • esp,堆棧指針(stack pointer)
  • ebp,基址指針(base pointer)

堆棧操作

  • push 棧頂地址減少4個字節(jié)(32位)
  • pop 棧頂地址增加4個字節(jié)
  • ebp在C語言中用作記錄當前函數調用基址

3 AUTOSAR中Runnable

Runnable(可運行實體)就是SWC中的函數,而在AUTOSAR架構中,使用工具生成時,Runnable是空函數,需要手動添加代碼來實現它的實際功能。Runnable可以被觸發(fā),比如被定時器觸發(fā)、被操作調用觸發(fā)或者被接受數據觸發(fā)等。

圖片

這里的函數就是Send接口,發(fā)送的數據由RTE進行管理。然而,由于這個SWCn.c文件中并未包含BSW中的.h文件,通過這個方式將AppL和BSW隔離開。所以如果假如必要的.h文件,其實也可以調用BSW中的函數,但是不建議這么做,該過程 應由RTE來完成觸發(fā)和調度。

圖片

RTE給runnables提供觸發(fā)條件,也就是runnable在設計的時候,需要有觸發(fā)條件,不然無法運行,也就沒有意義了。觸發(fā)條件就是一些特定的事件,AUTOSAR中主要規(guī)定了以下一些觸發(fā)條件:

  • 初始化事件:初始化自動觸發(fā)
  • 定時器事件:給一個周期定時器,時間到了就觸發(fā)
  • 接收數據事件(S/R):Receiver Port 一旦收到數據觸發(fā)
  • 接收數據錯誤事件(S/R)
  • 數據發(fā)送完成事件(S/R):Send Port 發(fā)送完成觸發(fā)
  • 操作調用事件(C/S):當調用到了該函數時觸發(fā)
  • 異步服務返回事件(C/S):C/S可以在異步下運行,即當異步調用一個Server函數,那么該被調函數作為一個線程和當前的運行程序并行運行,當被調函數運行結束返回(Return)時,這時觸發(fā)異步服務返回事件。
  • 模式切換事件
  • 模式切換應答事件

圖片

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯系本站處理。 舉報投訴
  • 嵌入式系統(tǒng)

    關注

    41

    文章

    3668

    瀏覽量

    130950
  • 程序
    +關注

    關注

    117

    文章

    3824

    瀏覽量

    82498
  • 函數
    +關注

    關注

    3

    文章

    4372

    瀏覽量

    64292
收藏 0人收藏

    評論

    相關推薦
    熱點推薦

    嵌入式系統(tǒng)的代碼優(yōu)化與壓縮技術

    調用的開銷。但要注意,內聯函數不宜過長,否則會導致代碼膨脹,占用過多內存。 三、代碼壓縮技術的意義 除了優(yōu)化,代碼壓縮技術也在嵌入式系統(tǒng)中發(fā)揮著關鍵作用。有限的存儲空間需要我們盡
    發(fā)表于 02-26 15:00

    嵌入式系統(tǒng)U盤實時啟動技術

    。這為嵌入式實時系統(tǒng)的啟動提供了一種嶄新的思路,即從優(yōu)盤啟動。這種方法對嵌入式實時系統(tǒng)板上的程序存儲空間要求不高,只要在Flash存儲
    發(fā)表于 09-05 11:36

    嵌入式開發(fā)的優(yōu)缺點是什么?

    一.嵌入式開發(fā)概述:嵌入式:在已有硬件上移植操作系統(tǒng),解決軟硬件耦合度高導致的問題。(打個比方:軟件的實現是為了調用open()函數,那么
    發(fā)表于 11-08 07:42

    開發(fā)基本的嵌入式應用程序

    開發(fā)基本的嵌入式應用程序 一、 實驗目的讀懂main.c 文件調用函數,了解uCOS-II 系統(tǒng)的啟動過程。學習使用SourceIns
    發(fā)表于 12-25 23:17 ?1587次閱讀
    開發(fā)基本的<b class='flag-5'>嵌入式</b>應用程序

    汽車電子嵌入式軟件接口庫設計

    軟件平臺由微型系統(tǒng)內核和應用編程接口庫組成。嵌入式操作系統(tǒng)內核負責任務調度及事件處理等,編程接口庫負責將開發(fā)常用的算法和 MPC555 底層硬件的驅動函數進行控件級封裝,供用戶
    發(fā)表于 01-23 17:32 ?42次下載
    汽車電子<b class='flag-5'>嵌入式</b>軟件接口庫設計

    基于Chirp函數的Nios Ⅱ嵌入式實現

    分析Chirp函數在頻域上的一般特性,提出利用FPGA的嵌入式軟核NiosⅡ處理器在嵌入式操作系統(tǒng)μC/OS-Ⅱ上實現Chirp的方法
    發(fā)表于 06-15 11:02 ?1299次閱讀
    基于Chirp<b class='flag-5'>函數</b>的Nios Ⅱ<b class='flag-5'>嵌入式</b>實現

    如何在嵌入式FreeRTOS系統(tǒng)接口調用API?

    1.在最近的嵌入式工作很多都是學習FreeRTOS系統(tǒng),由于只是會對RTOS的接口進行調用,但是很多時候都是知其然而不知其所以然,所以現在對API進行總結。
    的頭像 發(fā)表于 08-04 10:39 ?5894次閱讀
    如何在<b class='flag-5'>嵌入式</b>FreeRTOS<b class='flag-5'>系統(tǒng)</b>接口<b class='flag-5'>調用</b>API?

    為什么中斷處理函數不能直接調用不可重入函數

    中斷丟失和系統(tǒng)位置錯誤,這里直接導致嵌入式 linux 系統(tǒng)應用進程的所有線程停掉,進而導致看門狗進程得不到喂狗,設備重啟。 那什么是不可重入函數
    的頭像 發(fā)表于 02-17 09:33 ?6378次閱讀

    嵌入式系統(tǒng)

    在我們的日常生活,我們經常使用許多使用嵌入式系統(tǒng)技術設計的電氣和電子電路和套件。計算機,手機,平板,筆記本電腦,數字電子系統(tǒng)以及其他電子和電子設備都是使用
    發(fā)表于 10-21 10:51 ?1次下載
    <b class='flag-5'>嵌入式</b><b class='flag-5'>系統(tǒng)</b>

    嵌入式開發(fā)概述(20190325小結)

    一.嵌入式開發(fā)概述:嵌入式:在已有硬件上移植操作系統(tǒng),解決軟硬件耦合度高導致的問題。(打個比方:軟件的實現是為了調用open()函數,那么
    發(fā)表于 11-02 21:05 ?15次下載
    <b class='flag-5'>嵌入式</b>開發(fā)概述(20190325小結)

    嵌入式軟件的延時函數

    延時函數嵌入式軟件開發(fā)必不可少的功能函數,在每個工程里都能找到它的蹤影。雖然看起來不起眼,但在有些時序控制的場合,使用了一點點delay,往往能解決大問題。下面描述一下delay
    發(fā)表于 11-24 19:21 ?19次下載
    <b class='flag-5'>嵌入式</b>軟件<b class='flag-5'>中</b>的延時<b class='flag-5'>函數</b>

    函數調在嵌入式應用設計如何實現

      函數調用很好理解,即使剛學沒多久的朋友也知道函數調用是怎么實現的,即調用一個已經封裝好的函數
    的頭像 發(fā)表于 11-28 09:16 ?814次閱讀

    嵌入式軟件架構設計之函數調用

    函數調用很好理解,即使剛學沒多久的朋友也知道函數調用是怎么實現的,即調用一個已經封裝好的函數,實
    的頭像 發(fā)表于 02-15 14:48 ?1324次閱讀
    <b class='flag-5'>嵌入式</b>軟件架構設計之<b class='flag-5'>函數</b><b class='flag-5'>調用</b>

    嵌入式open函數的使用

    嵌入式系統(tǒng)是指嵌入到其他設備或系統(tǒng),用于控制和管理硬件資源的計算機系統(tǒng)。在
    的頭像 發(fā)表于 01-04 15:51 ?1004次閱讀

    嵌入式系統(tǒng)堆棧監(jiān)控的作用

    在微控制器或微處理器,堆棧是內存的一個保留區(qū)域,用于存儲臨時數據和函數調用信息,管理函數的執(zhí)行,跟蹤返回地址、局部變量和函數參數。堆棧監(jiān)控
    的頭像 發(fā)表于 01-05 11:13 ?748次閱讀
    主站蜘蛛池模板: 国产成人免费网站在线观看 | 99在线观看免费视频 | 亚洲AV成人片色在线观看网站 | 97免费视频在线观看 | 麻豆文化传媒一区二区 | 一一本之道高清手机在线观看 | 少妇无码吹潮久久精品AV网站 | 亚洲人日本人jlzzy | 亚洲精品乱码久久久久久中文字幕 | 久久综合狠狠综合久久综合88 | 亚洲男人天堂2018av | yellow片在线观看免费观看动漫 | 国产成人综合高清在线观看 | 忘忧草在线影院WWW日本动漫 | 语文老师扒开胸罩喂我奶 | 久久人妻少妇嫩草AV蜜桃35I | 亚洲精品国产第一区第二区 | 最近2018年手机中文字幕 | 荡公乱妇HD中文字幕 | 少妇的肉体AA片免费 | 日日干夜夜爱 | 日本69xxxxx| 亚洲熟伦熟女专区 | 亚洲精品国偷拍自产在线 | 玖玖爱在线播放 | 国模沟沟一区二区三区 | 一级做a爰片久久免费 | 亚洲精品AV无码喷奶水糖心 | 久久久无码精品一区二区三区 | 欧美高清视频www夜色资源网 | 在线免费观看国产视频 | 一级毛片皇帝 宫女 | 午夜亚洲动漫精品AV网站 | 亚洲天堂2017无码 | 久色乳综合思思在线视频 | 中文字幕国产视频 | 我要女人的全黄录像 | 久章草一区二区 | 久久国产高清字幕中文 | 亚洲AV精品无码喷水直播间 | 日本色高清 |

    電子發(fā)燒友

    中國電子工程師最喜歡的網站

    • 2931785位工程師會員交流學習
    • 獲取您個性化的科技前沿技術信息
    • 參加活動獲取豐厚的禮品