【KEIL·单片机·扫盲贴】关于ARM单片机程序内存使用情况的细致讨论。
接觸了兩年多時間的單片機編程本人對關(guān)于單片機程序內(nèi)存如何耗費的問題一直懵懵懂懂,直到在近日看到某篇有關(guān)于MDK?MAP文件介紹的帖子后才有種醍醐灌頂?shù)母杏X,這里我將分享在此之上的觀點與見解以供大家討論學(xué)習(xí)。
大家都知道ARM單片機的內(nèi)部存儲空間極其匱乏無論是從Flash還是RAM上,每每給單片機機編程都有一種惜字如金的感覺,工程師們一般會在容量有限的情況下規(guī)范其編程習(xí)慣簡化代碼避免冗余,那么首先我們?nèi)绾沃赖某绦蛳螺d到單片機上到底占用了多少Flash程序運行又會使用多少RAM?
首先上一張圖:
該圖是KEIL編譯某個單片機程序后生成的構(gòu)建信息,這里我們只關(guān)注其中的Program Size信息。
Program Size其意義是編譯后生成的代碼大小單位是字節(jié),Program Size的大小有四大決定因素:Code,RO-data,RW-data,ZI-data 。
?
Code :意義是代碼指令占用的空間;
RO-data? :是Read Only?Data的縮寫,意義是只讀常量占用的空間。如const型常量,常量字符串等等;
RW-data :是Read Write?Data的縮寫,意義是可讀可寫的已初始化 了的變量占用的空間。如全局變量,靜態(tài)變量等等;
ZI-data :是Zero?Initialize??Data的縮寫,意義是以0初始化的變量。如未初始化賦值的全局變量,靜態(tài)變量等等;
綜上來說?燒寫的時候是FLASH中的被占用的空間大小為:Code?+?RO?Data?+?RW?Data,而程序運行的時候數(shù)據(jù)使用到的RAM的空間大小為:RW?Data?+?ZI?Data。
?
Why?
FLASH中的被占用的空間很好理解,就是等于代碼指令+只讀數(shù)據(jù)的值+已初始化變量的值。那么運行時數(shù)據(jù)占用RAM空間大小==RW?Data?+?ZI?Data又作何理解?
我們都知道,在代碼運行機制上單片機不同于PC,單片機的程序通常是在FLASH中直接取指執(zhí)行,而PC是先把程序拷貝到RAM中再取指執(zhí)行。
由上說明單片機的RAM中至少不會存在Code拷貝(除非使用了特殊方法強行使程序拷貝到了RAM中執(zhí)行,本貼不討論此情況),
其次,單片機RAM中也不會存在RO-data拷貝,因為RO-data是只讀數(shù)據(jù),為了節(jié)省RAM空間,這種數(shù)據(jù)在執(zhí)行時直接從FLASH中取出使用,無需再復(fù)制到RAM。
那么剩下的?RW?Data?+?ZI?Data由于是可讀可寫的數(shù)據(jù),為了能夠供程序運行時正常讀寫,于是就會被放在單片機的RAM中(單片機的FLASH區(qū)不能被程序改寫)。
有人可能會問RW-data?與ZI-data都是指的全局變量或者靜態(tài)變量,那么程序中的局部變量去了哪兒?這里就要向大家澄清一個事實,在C或C++中全局變量或?靜態(tài)變量在RAM中都有一個特定地址(存在于靜態(tài)區(qū)),而局部變量卻沒有特定的地址
因為局部變量存在于棧中(存在于堆棧區(qū)),當(dāng)函數(shù)入棧時系統(tǒng)就會在棧頂之上開辟一段內(nèi)存供給局部變量使用,當(dāng)函數(shù)出棧時該內(nèi)存就會被釋放掉。
?
那么單片機在程序運行時RAM的使用量就等于RW?Data?+?ZI?Data了嗎,還有沒有其他因素會導(dǎo)致RAM占用變化?
玩過PC的都知道,一個程序在運行時它在內(nèi)存中的占用情況是會隨時改變的,這其中可能有壓棧入棧和堆塊的申請與釋放等事件發(fā)生,那么在單片機里難道就沒有這樣的過程了嗎?答案都是否定的。
單片機的RAM中也有堆棧區(qū),那么程序運行時RAM的使用量就不會再等于RW?Data?+?ZI?Data了,因為程序的堆棧區(qū)也是一段具體的內(nèi)存,那么堆棧區(qū)的內(nèi)存占用又有多大?
堆棧區(qū)大小的查詢方法,這里以STM32F1系列作為介紹,以航跡雲(yún)STF1驅(qū)動集合庫中的startup_stm32f10x_hd.s啟動文件為例:
(看不清圖片的朋友們,請右鍵查看圖片)
圖中有個Stack_Size(棧大小)與Heap_Size(堆大小)定義,這兩十六進制的數(shù)值之和就是你的單片機運行時RAM中的堆棧字節(jié)大小,其他單片機平臺的堆棧大小查詢方法請自行百度。
以上可以得出,一個arm架構(gòu)的單片機的程序在運行時將會占用到的RAM空間等于 RW?Data?+?ZI?Data +?Stack_Size + Heap_Size;
?
那么在程序運行時還有沒有其他因素會導(dǎo)致RAM被使用的空間發(fā)生變化?
在回答這個問題之前,我們先來討論何為 “在編譯時編譯器會為一個變量分配一段內(nèi)存” ?玩過匯編的都知道編譯器并不會給變量一個內(nèi)存,?而是編譯器在內(nèi)存中為變量指定了一個地址而已,然后讓其他變量不會重復(fù)指向該地址,在編譯時編譯器會把變量名由地址替換掉,這樣就達到了貌似"編譯器給變量分配了內(nèi)存"?的效果。
因為編譯器為每個變量分配地址且不會讓該地址被占用,由此得知RW?Data?+?ZI?Data這兩塊數(shù)據(jù)在被分配好內(nèi)存之后會一直處于無法被回收的狀態(tài),根據(jù)認知科學(xué)一一無法回收==占用,所以RAM中的RW?Data?+?ZI?Data區(qū)就會一直處于占用狀態(tài),如果沒有新的程序燒錄進來RW?Data?+?ZI?Data區(qū)占用的空間是不會變的。
那么堆棧區(qū)就更不用說了,堆棧區(qū)的大小是由單片機的啟動文件中Stack_Size?與?Heap_Size確定的,函數(shù)入棧出棧變的只是堆棧區(qū)內(nèi)的數(shù)據(jù)而不是變化堆棧區(qū)大小(?注:如果函數(shù)入棧的數(shù)量超出了堆棧區(qū)的大小限制則為爆棧),如果沒有新的程序燒錄進來Stack_Size?+ Heap_Size區(qū)占用的空間也是不會變的。
?
結(jié)論:ARM單片機中的FLASH的占用量取決于Code?+?RO?Data?+?RW?Data,程序運行時RAM的占用量取決于?RW?Data?+?ZI?Data +?Stack_Size + Heap_Size且在程序運行過程中該占用量幾乎不變;?
?
?
這是我的第一篇博客,以上皆為個人愚解,如有不周歡迎斧正。
?2017/9/11 航跡雲(yún)
轉(zhuǎn)載于:https://www.cnblogs.com/Contrail/p/7502066.html
《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的【KEIL·单片机·扫盲贴】关于ARM单片机程序内存使用情况的细致讨论。的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java web学习笔记-jsp篇
- 下一篇: 总结JS常用方法