51堆棧的安全(精確)設(shè)置
哈哈, 冷漠同學(xué)高深莫測(cè),意識(shí)流的運(yùn)用堪比大師. 好吧, 為了清晰起見, 我替冷漠同學(xué)總結(jié)一下:
1) "假定項(xiàng)目中有3個(gè)匯編程序模塊A.a51,B.a51,C.a51,它們當(dāng)然每個(gè)模塊都有自己的私有堆棧"
"BL51 A.OBJ,B.OBJ,C.OBJ
C51下的公有堆棧指針是?STACK ,而每個(gè)模塊的私有堆棧指針是STACK,一個(gè)公有?STACK里包含一個(gè)或者多個(gè)私有STACK,?STACK指針由編譯器確定分配在 idata 內(nèi)所有段的最后面"
2) "只有PUSH / POP指令才能操作STACK,硬件自動(dòng)壓入的屬于不可控的系統(tǒng)控制棧,STACK根本不指向!2字節(jié)壓入PC根本不影響STACK指針"
3) "C程序中硬件自動(dòng)壓入的PC在私有STACK指向下面就完成了,用戶程序根本看不見的。好像稱為系統(tǒng)控制棧內(nèi)容"
4) " 私有堆棧(每個(gè)后臺(tái)函數(shù)的私有STACK,和C編譯器中的?STACK是兩回事)被編譯器分配在RAM低端,從全局靜態(tài)變量區(qū)(包括共享覆蓋區(qū))后面開始,即初始SP所指向區(qū)域,直到?STACK所指向?yàn)榻Y(jié)束。
?STACK所指向的是前臺(tái)堆棧,被編譯器默認(rèn)自動(dòng)分配在所有段(包括所有私有STACK段)的最后面(RAM高端)——棧頂部分!關(guān)鍵的是從這里開始,直到棧頂,才存在溢出危險(xiǎn)。——它是一個(gè)獨(dú)立ISR函數(shù)(不是多個(gè)后臺(tái)函數(shù))的堆棧"
5)"對(duì)于interrupt 屬性函數(shù),C51為其分配中斷函數(shù)私有堆棧……還有硬件堆棧hardware
引用結(jié)束.
假設(shè):
有A.obj, B.obj, C.obj 三個(gè)模塊構(gòu)成的一個(gè)8051單片系統(tǒng), 使用了一個(gè)定時(shí)中斷, 簡(jiǎn)單起見, 沒有使用 reentrant。其中a調(diào)用了b中的函數(shù), b調(diào)用了c, c調(diào)用了a, 期間有中斷,而且沒有重新設(shè)置過sp。
請(qǐng)問冷漠同學(xué):
1) 按照冷漠同學(xué)的解釋, 此系統(tǒng)有: 中斷函數(shù)私有堆棧, abc模塊私有堆棧, 還有硬件堆棧hardware
2) 如果不是 5個(gè)棧, 這個(gè)系統(tǒng)總共有多少個(gè)棧? 請(qǐng)給出明確的數(shù)字。
3)每個(gè)棧是如何操作的? 請(qǐng)給出說明。
冷漠修正一些錯(cuò)誤:
1) "假定項(xiàng)目中有3個(gè)匯編程序模塊A.a51,B.a51,C.a51,它們當(dāng)然每個(gè)模塊都有自己的私有堆棧"
"BL51 A.OBJ,B.OBJ,C.OBJ
C51下的公有堆棧指針是?STACK ,而每個(gè)模塊的私有堆棧指針是STACK,一個(gè)公有?STACK里包含一個(gè)或者多個(gè)私有STACK,?STACK指針由編譯器確定分配在 idata 內(nèi)所有段的最后面"
——呵呵,這種概念所長(zhǎng)還不如老許理解透徹:一會(huì)給你抄抄操作系統(tǒng)的書。highgear是精通555時(shí)基的,怎 么可能理解這么深刻的機(jī)制?所長(zhǎng)從裸奔和匯編的概念出發(fā)當(dāng)然不可能理解。不妨跟老許學(xué)學(xué):什么叫軟堆棧?如若誰再提出個(gè)“軟中斷”,所長(zhǎng)該不會(huì)大呼小叫 吧。要不要冷漠給你注明哪本書上寫的?你不可能比書作者還高明。
2) "只有PUSH / POP指令才能操作STACK,硬件自動(dòng)壓入的屬于不可控的系統(tǒng)控制棧,STACK根本不指向!2字節(jié)壓入PC根本不影響STACK指針"
3) "C程序中硬件自動(dòng)壓入的PC在私有STACK指向下面就完成了,用戶程序根本看不見的。好像稱為系統(tǒng)控制棧內(nèi)容"
——呵呵,硬件自動(dòng)壓入堆棧的PC影響的是?STACK,(幸虧冷漠前面沒有寫問號(hào),也即SP指針。這稱為“Hardware
4) " 私有堆棧(每個(gè)后臺(tái)函數(shù)的私有STACK,和C編譯器中的?STACK是兩回事)被編譯器分配在RAM低端,從全局靜態(tài)變量區(qū)(包括共享覆蓋區(qū))后面開始,即初始SP所指向區(qū)域,直到?STACK所指向?yàn)榻Y(jié)束。
——冷漠的錯(cuò)誤,先說對(duì)不起了:“即初始SP所指向區(qū) 域,”這句話應(yīng)該是……“從共享覆蓋區(qū)后面開始,直到?STACK所指向?yàn)榻Y(jié)束。”這正是老許說的后臺(tái)軟堆棧區(qū),它是人們匯編語言概念上的堆棧么?別以為 一個(gè)STACK命令分配區(qū)就認(rèn)為是堆棧了??磿稽c(diǎn)聯(lián)想里都沒有。難怪學(xué)不會(huì)操作系統(tǒng)。要不要我貼張圖講得更清楚一點(diǎn),文章出處當(dāng)然就是P640啦,再回 家好好看看這一段。你不可能比書作者還高明。
待續(xù)……
TACK所指向的是前臺(tái)堆棧,被編譯器默認(rèn)自動(dòng)分配在所有段(包括所有私有STACK段)的最后面(RAM高端)——棧頂部分!關(guān)鍵的是從這里開始,直到棧頂,才存在溢出危險(xiǎn)。——它是一個(gè)獨(dú)立ISR函數(shù)(不是多個(gè)后臺(tái)函數(shù))的堆棧"
5)"對(duì)于interrupt 屬性函數(shù),C51為其分配中斷函數(shù)私有堆棧……還有硬件堆棧hardware
引用結(jié)束.
哈哈, 冷漠同學(xué)概念混亂, 從頭到尾含糊其辭。冷漠同學(xué)既不敢明確回答有多少個(gè)棧, 也不敢***具體詳細(xì)*** 的解釋stack的原作過程。
我先把這里 stack 的具體化一些,
*) stack 操作是指影響 8051 sp 的操作, 如函數(shù)調(diào)用, push/pop.
*) sp 的活動(dòng)區(qū)域?yàn)?stack 區(qū)。
這樣, 計(jì)算機(jī)軟件算法的 stack 就不在此例。(呵呵, 在我面前賣弄 軟件stack和軟中斷, 如同賣弄bios 一樣可笑)。
我下面會(huì)把 ?stack 和 stack, 什么“私有模塊棧“ 講解清楚。 我不會(huì)比書作者還高, 但 keil 會(huì)。
書作者的問題是沒有講清楚, 而冷漠的問題是不清楚卻胡說八道。
我先給出keil 關(guān)于 bl51 stack 的說明, 對(duì)照 p640, 認(rèn)真的看看, 就會(huì)知道原委.
http://www.keil.com/support/man/docs/bl51/bl51_stack.htm
■Use of the STACK directive to locate the ?STACK segment is typically not required.
■The STACK directive is typically used with assembly programs that have several stack segments.
■Use extreme caution when using the STACK directive. Improper use may result in a target program that crashes or that corrupts DATA and IDATA variables.
keil 從頭到尾沒有提出 "私有堆棧" (private stack) 的概念, 冷漠同學(xué)硬生生造出了很多的“術(shù)語“。
在講解 "私有堆棧" 來龍去脈前, 還是請(qǐng)冷漠明確的說明有多少個(gè)涉及硬件棧指針的stack ? 2個(gè), 3個(gè)還是 5個(gè)?
“模塊私有棧“:
這個(gè)術(shù)語在徐愛鈞編著P640里以及 keil 的網(wǎng)站里都沒有, 顯然是冷漠杜撰的, 如同"遞歸可重入“
Bl51 stack 命令參數(shù)看似可以設(shè)定一個(gè)”模塊私有棧”, 其實(shí)這個(gè)stack 命令參數(shù)的作用是為了匯編模塊,而且是需要重新設(shè)置 sp 的匯編模塊。 C 程序不需要關(guān)心 sp, 更不鼓勵(lì)用戶設(shè)置 sp. 只有匯編不得不這么做。匯編不得不自己設(shè)置 sp,不得不自己控制push/pop.
假設(shè)某個(gè)第三方的匯編模塊里改寫 sp (由于特殊的應(yīng)用),此人為了通用,沒有直接設(shè)置 sp 為一個(gè)固定值,而是提供了一個(gè)sp地址的命名名稱, 如?ID?MEASURE,以便可以讓最終用戶在連接時(shí)由 linker 為?ID?MEASURE確定地址 。模塊結(jié)構(gòu)大致如下:
Linker 在連接時(shí),可以自動(dòng)也可以手工用 stack參數(shù)設(shè)定?ID?MEASURE的具體位置, 并可以保留若干字節(jié)(8086 匯編里經(jīng)常有這種需求,為了不污染原來的stack). 這種 sp 被更改所產(chǎn)生的數(shù)據(jù)區(qū)域, 徐愛鈞的書以及 keil 稱為棧段(stack segment), 沒有稱為 "模塊私有棧".
因此, 只要模塊中沒有設(shè)置 sp, 那么就不會(huì)有stack segment, 也就是冷漠所說的“模塊私有棧".
而 ?stack 僅僅是一個(gè)命名名稱,作用是在startup 初始化sp,即:
?stack 的值在連接時(shí)確定, 此外,別無特殊意義。當(dāng)在某個(gè)模塊里重設(shè)sp 后,其后所有的棧活動(dòng)(call, interrupt, push, pop,ret,reti)都會(huì)從新棧點(diǎn)開始。
.
.
.
結(jié)論:
a) 如果程序中, 用戶沒有重新設(shè)置 sp, 而且排除另一個(gè)概念---計(jì)算機(jī)軟件算法中的棧, 那么
b) 如果程序員在程序中多次設(shè)置 sp, 這些sp的活動(dòng)數(shù)據(jù)區(qū)被稱為 stack segment, 而不是一個(gè)獨(dú)立的“stack"
如果對(duì)上述內(nèi)容不能理解,請(qǐng)仔細(xì)閱讀鏈接中的內(nèi)容
http://www.keil.com/support/man/docs/bl51/bl51_stack.htm
評(píng)論