娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

首先來看,51的系統棧(又叫系統棧,或者硬件棧),就是SP所指向的棧,他是一個滿增棧(注釋1),位于片內RAM的128 bytes之中,上電之后系統堆棧指針SP的初值等于多少呢?這個要從51的啟動文件來分析,啟動文件中有這樣的匯編代碼:


?STACK SEGMENT IDATA ;定義一個片內數據段,段名:?STACK


RSEG ?STACK ;選擇之前定義過的一個可重定位的段?STACK,下面的匯編語句將會被放置到該段,直到遇到下一個段定位指令,例如CSEG/RSEG。


DS 1 ;預留存儲區命令。聲明先占用一個字節的空間,在編譯時,這個預留的空間不會被其他變量所使用。在這里的意義是,給硬件棧分配1個byte(實際這樣是有問題的,應該為硬件棧預留更多空間)


還有:


MOV SP,#?STACK-1


由上可見,SP被初始化為#?STACK-1,在#?STACK地址處,DS指令預留了N個字節的空間,這些空間就是硬件棧的空間


但啟動文件的代碼中,DS 1相當于只給硬件棧預留了1個字節,這實際上會出問題,原因如下:片內RAM中會有多個數據段,只要使用XX SEGMENT IDATA指令即可在片內RAM中聲明一個數據段XX,如果整個工程程序中,聲明了多個數據段,?STACK數據段就只是片內RAM中眾多數據段中的一個,如果只給?STACK段預留1個字節,而?STACK數據段后面又有別的數據段,那么我們的硬件棧就只有1個字節了,一旦發生中斷,CPU寄存器自動入棧立即導致棧溢出,溢出后踩了別的變量的內存,程序基本崩潰;對于這個問題,keil是這樣處理的:keil在鏈接階段總是把?STACK數據段鏈接為片內RAM中的最后一個數據段,即使我們只給他預留了1個字節,那也不要緊,反正該段后面沒有別的變量占用,只要SP別超出0X7F(片內RAM地址的上限)就行了。通過觀察.m51(map文件)我們發現,keil確實是把?STACK數據段放到了片內RAM的最后,下面是某個51工程生成的map文件摘抄:


* * * * * * * D A T A M E M O R Y * * * * * * *


REG 0000H 0008H ABSOLUTE "REG BANK 0"


DATA 0008H 0002H UNIT ?C?LIB_DATA


IDATA 000AH 000DH UNIT ?ID?UCOS_II


0017H 0009H *** GAP ***


BIT 0020H.0 0000H.1 UNIT ?BI?SERIAL


0020H.1 0000H.7 *** GAP ***


IDATA 0021H 0041H UNIT ?STACK ; 作者注:就是這一行!


* * * * * * * X D A T A M E M O R Y * * * * * * *


XDATA 0000H 080EH UNIT ?XD?SERIAL


XDATA 080EH 0804H UNIT ?XD?MAIN


XDATA 1012H 0490H UNIT ?XD?UCOS_II


XDATA 14A2H 005CH UNIT _XDATA_GROUP_


為避免系統棧不夠用,一個比較穩妥的辦法就是,用匯編指令DS給?STACK數據段預留更多的空間,上面這個51工程中在另一個匯編文件中又給?STACK數據留出了40H個字節,這樣總共就有41H個字節了。這樣做的好處是可以在編譯鏈接階段即可排查堆棧錯誤,舉個例子: 假設片內RAM中的數據段有很多,以至于,除了?STACK數據段之外,片內RAM只剩2個字節了,而?STACK數據段我們只默認采用了啟動文件中的配置預留一個字節,這樣編譯沒有任何問題,keil給編譯通過了,但是運行過程中系統棧只有2個字節,肯定是分分鐘就發生棧溢出,然后崩潰;假設片內RAM中的數據段有很多,以至于,除了?STACK數據段之外,片內RAM只剩2個字節了,而如果我們給?STACK數據段用DS指令分配40H個字節,這樣keil在編譯時就會發現51的片內RAM不足而報錯,無法編譯,從而在編譯鏈接階段幫助我們發現堆棧問題。


繼續上面的問題,SP復位后的初值是多少,SP復位后等于0X07,但是立即就被啟動文件通過語句MOV SP,#?STACK-1給改掉了,所以在進入main函數時SP的值是啟動文件修改后的值,也即#?STACK-1(注,很好理解,這里-1是滿增棧的特性),那么#?STACK的值又是多少呢?看上面的匯編語句?STACK SEGMENT IDATA,這一句聲明?STACK段為一個可重定位的段,也就是說,?STACK段的首地址(#?STACK)在編譯器進行程序鏈接時才能確定下來,也就是說,#?STACK的值是在鏈接時由編譯器自動分配的,編譯階段不分配。仍然以上面摘抄的這段map文件為例,我們發現,?STACK段的起始地址是0021H,也就是說,#?STACK就等于21H。


仿真棧是keil為51生成可重入函數時用的(通過給函數使用關鍵詞 REENTRANT限定,可使該函數具備可重入特性),對于STM32來說,默認生成的函數(不含全局變量和靜態局部變量的函數)就是可重入的,而keil為51生成的函數,即使這個函數不含全局變量和靜態局部變量,默認情況下keil也不會把這個函數匯編成可重入的,我認為keil主要是考慮到51的片內RAM匱乏,在不外接RAM的情況下,函數如果被編譯為可重入的,可重入函數的執行需要占用一定的棧空間(尤其是由可重入函數嵌套調用產生的長的調用鏈,所需的棧更多)。


可重入函數在執行過程中是需要使用棧的,那么51的可重入函數使用的棧在哪呢?是SP指向的那個系統棧嗎?答案是:不是。下面是解釋:


當我們給51外擴了大的片外RAM時,就不用擔心RAM不夠的問題了,但是還有一個問題,系統棧指針SP只能尋址0~7FH共128字節的空間,可重入函數肯定不允許被編譯成使用系統棧,否則,就算外擴了RAM,這個外擴RAM又無法供系統棧來使用,外擴RAM就沒有意義了,所以keil為51打造了一個仿真棧的概念,keil在啟動文件中聲明了一個1或2字節的變量作為棧指針,這個棧指針的名字和大小根據編譯模式的不同而不同,以大編譯模式(注釋2)為例,大編譯模式下,啟動文件中的XBPSTACK常量需要程序員手動設置為1,這樣啟動文件中使用到的條件編譯,將會引用到一個2字節的仿真棧指針?C_XBP,由于keil把仿真棧作為滿減棧,所以這個仿真棧指針?C_XBP被初始化為片外RAM地址的最大值加1,若我們外接了一個64K的片外RAM,該RAM的最大地址是0XFFFF,那么棧指針?C_XBP被初始化為0XFFFF 1=溢出為0x0000。再舉一個小編譯模式的例子,小編譯模式是用來給沒有外擴RAM的51用的,這樣51只能使用片內0~127共128字節的RAM(這128RAN中還有一部分是Rn等,留給程序可用的RAM就更少了),在小編譯模式下,keil給51生成的仿真棧指針名叫?C_IBP,同時需要程序員手動把IBPSTACK常量設置為1,指針?C_IBP的初值被初始化為可用RAM的最大地址(127)加1,也即0x7f 1。關于小編譯模式small、壓縮編譯模式compact、大編譯模式large在堆棧處理上方面的不同,可參考這篇文章點擊打開鏈接,如果鏈接掛了,可自行搜索:《Keil模式設置和編程事項》。


注釋1:滿增棧,滿指的是SP總是指向最后一個入棧的字節的地址,增指的是每入棧一次,SP變大。相應的,還有空增棧、空減棧、滿減棧,空指的是SP總是指向棧中下一個空閑位置的地址。


注釋2:如何選擇大編譯模式:以keil5為例,依次選擇->魔術棒->Target選項卡,Memory Model選擇Large:var...,Code Rom Size選擇Large....


附:舉一個不可重入函數使用中可能發生的陷阱,假設有分別有如下兩個函數,第一個可重入,第二個不可重入


int add5_re(char a1,char a2,char a3,char a4,char a5) REENTRANT


{


int sum;


sum=a1 a2 a3 a4 a5;


return sum;


}


int add5(char a1,char a2,char a3,char a4,char a5)


{


int sum;


sum=a1 a2 a3 a4 a5;


return sum;


}


這兩個函數的形參以及局部變量分配等信息我們查閱.m51文件,分別如下(分號后面的注釋是博主自己加上的):


[plain] view plain copy------- PROC _?ADD5_RE


x:0002H SYMBOL a1 ;注意,地址標號前為小x,指a1倍分配到了仿真棧中


x:0003H SYMBOL a2


x:0004H SYMBOL a3


x:0005H SYMBOL a4


x:0006H SYMBOL a5


------- DO


x:0000H SYMBOL sum


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


------- PROC _ADD5


D:0007H SYMBOL a1 ;R7


D:0005H SYMBOL a2 ;R5


D:0003H SYMBOL a3 ;R3


X:14ABH SYMBOL a4 ;注意地址標號前為大X,指外部RAM


X:14ACH SYMBOL a5


------- DO


D:0006H SYMBOL sum ;R6


我們發現,add5中的形參和局部變量a1/a2/a3/sum分到了Rn中,a4/A5分到了外部RAM xdata的絕對地址處,如果我們在main的調用鏈中和中斷函數中都調用了add5這個函數,就會發生錯誤,假設恰好在main的調用鏈中執行add5時發生了中斷,切換到中斷函數中去執行add5,那么main調用鏈中的a1/a2/a3/sum因為被分到了Rn中,進入中斷會切換register BANK,使得main調用鏈中的a1/a2/a3/sum沒有被破壞,得以幸免,但是a4/a5因為被分配到了絕對地址中,在中斷執行完add5以后,main鏈條中的add5的a4/a5肯定會被破壞!!


對于可重入的add5_re函數,即使main調用鏈和中斷同時調用它也不會出現上述被破壞的情形,因為add5_re的形參和局部變量全部都被定義到了仿真棧中(見上述代碼注釋),main調用鏈中使用add5_re函數會申請棧空間,中斷時add5_re又會申請新的棧空間。


還要注意的是,因為keil編譯51程序時,使用了覆蓋技術(不同函數的形參和局部變量可分時共享同一個絕對內存單元),這也有可能產生陷阱,假設這樣一種情況:有一個函數func2( )的局部變量b在編譯后被分配到了絕對xdata的地址14ABH處,和上文的add5的a4變量共享內存,這種情況下,即使 { func2( )僅在中斷中被調用,main調用鏈中不調用func2( )}、且{ add5僅在main調用鏈中被調用,中斷中不調用add5 },也會出問題,原因是顯而易見的,如果在add5執行過程中發生中斷,中斷中使用過變量b之后,會破壞add5中的變量a4。究其原因在于,共享地址的編譯方式生成的函數,只要分時調用就不會產生被破壞的情形,但是發生中斷導致了分時機制被破壞,以至于產生了同時調用。


結論:中斷中使用的函數,要么是可重入的,要么是該函數的局部變量全部是獨享內存單元的。


關鍵字:51單片機  仿真棧  模擬棧  可重入棧 引用地址:51單片機的仿真棧(模擬棧/可重入棧)

上一篇:51單片機定時器使用經驗總結
下一篇:51單片機存儲器小結

推薦閱讀

瑞薩電子針對智能家電、服務機器人及工業機械領域,推出可實現高速圖像處理和嵌入式人工智能應用的RZ/A2M微處理器全球領先的半導體解決方案供應商瑞薩電子株式會社(TSE:6723)今日宣布,擴展其嵌入式人工智能(e-AI)解決方案,將AI整合到嵌入式系統,從而實現終端設備的智能化。全球10多個國家的約150家公司正在基于這項技術開展包括工具等在內的試驗,...
車東西10月9日消息,瑞典皇家科學院今天下午宣布,2019年諾貝爾化學獎授予約翰·B·古迪納夫(John B. Goodenough)、斯坦利·威廷漢(M. Stanley Whittingham) 和吉野彰(Akira Yoshino)三人,以表彰他們在開發鋰離子電池方面作出的杰出貢獻。威廷漢曾用二硫化鈦作為鋰電池陰極材料,古迪納夫于1980年證明嵌入鋰離子電池的氧化鈷可產生4伏電壓,成為...
集微網消息 10月6日,隨著國慶假期臨近收尾,再加上近來美國特朗普得新冠肺炎的消息,市場最為關心的是節后A股半導體概念股的走勢如何。10月6日,盡管中芯國際近來遭遇美國出口管制,但港股中芯國際盤中卻依然大漲超10%,帶動整個半導體板塊上揚,收盤依然大漲超7%。此外,上海復旦更是盤中大漲近17%,收盤依然大漲近15%,消息層面,國慶假期前消息,上海...
芯歷史──縱覽國內外半導體產業發展歷程,挖掘行業奇聞趣事,以古鑒今,探尋產業未來發展之道。集微網報道,自AMD于今年3月份發布第三代EPYC霄龍服務器處理器后,便頻頻有消息稱英特爾將為其服務器CPU重新定價以應對沖擊。其實CPU領域這兩大巨頭自成立之初起便由于產品線雷同而形成了競爭關系,在過去的五十余年中不斷上演著“相愛相殺”的戲碼。早期:被...

史海拾趣

問答坊 | AI 解惑

尋cp2102驅動

定制CP2102的windows驅動程序 CP2102 是Silicon公司的USB轉UART的芯片,UART端支持所有modem接口信號,波特率最高可以達到1Mbits,內部有576Byte 的接收緩沖區和640Byte的發送緩沖區。 硬件電路方面,所需要元件少之又少,僅需兩個104的瓷片 ...…

查看全部問答∨

產品試用報告

誰有產品使用報告格式了??…

查看全部問答∨

7塊PSP主板所見證的破解歷史

PSP發售至今,其內部也經歷了數次更新換代,由最初的TA-79的主板到現在最新的TA88主板,在破解的玩家眼中每款都有著鮮明的“個性”;這每一塊主版的出現,都伴隨這一段段PSP的破解歷史。現在就讓我來帶大家看看至今7款PSP主板。 TA-79   &n ...…

查看全部問答∨

mobisys無線視頻監控技術及應用

mobisys無線視頻監控技術及應用…

查看全部問答∨

怎么樣將控件設置成半透明啊??

我想把PictureBox設置成半透明狀,不知道在WinCE下,是不是可以?? 我用的是vb.net!! 謝謝大家了!!!…

查看全部問答∨

遇到個電源電路,請教高手幫忙分析一下

圖1有兩個地方我沒明白:1.N203B運放的作用,我測得N203B 7腳電壓為2.5V,不知道怎么算出來,這個運放的接法我沒遇到過。2.從我的觀點看N202A基本上是一個跟隨器,但正如問題1中所說,N203B的7腳是2.5V,那么N202A的1腳也應為2.5V,而我實際測得1腳 ...…

查看全部問答∨

單片機與pc機通信

我用cvavr編寫單片機與pc機通信的程序,編譯的時候總是報錯 undefined symbol \'blt\' undefined symbol \'amt\' undefined symbol \'cli\' undefined symbol \'sei\' 請高手幫助 …

查看全部問答∨

新人報到 too,望各位多多關照。

扒拉了半天,終于找到了組織的根據地。。。…

查看全部問答∨

大家建議是DIY一塊149還是5438的430板子?

我趨向于DIY5438的片子,畢竟現在是TI力推的新核心,板子資源如下: 1、包含USB接口的BSL下載器,提供下載代碼用但是BSL不能仿真 2、SPI的93C46存儲器 3、3個串口或TTL 4、1路RS485 5、RTC時鐘芯片DS1302 6、溫度采集18B20 7、1路AD采集 8 ...…

查看全部問答∨
小廣播
設計資源 培訓 開發板 精華推薦

最新單片機文章
何立民專欄 單片機及嵌入式寶典

北京航空航天大學教授,20余年來致力于單片機與嵌入式系統推廣工作。

 
EEWorld訂閱號

 
EEWorld服務號

 
汽車開發圈

 
機器人開發圈

電子工程世界版權所有 京ICP證060456號 京ICP備10001474號-1 電信業務審批[2006]字第258號函 京公網安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 织金县| 固始县| 东光县| 建平县| 勃利县| 兴仁县| 阿城市| 神农架林区| 贺兰县| 建宁县| 金山区| 辽阳县| 义马市| 逊克县| 社旗县| 浦县| 杭锦后旗| 宜章县| 碌曲县| 兰西县| 滨州市| 扎囊县| 迁西县| 龙游县| 衡阳市| 炉霍县| 西宁市| 华坪县| 工布江达县| 诏安县| 通城县| 尼玛县| 恭城| 襄汾县| 卓资县| 如皋市| 建瓯市| 密山市| 乌拉特前旗| 寻乌县| 温州市|