版權(quán)聲明:轉(zhuǎn)載時(shí)請(qǐng)以超鏈接形式標(biāo)明文章原始出處和作者信息及本聲明
http://dreamhead./logs/4840895.html
如何判斷棧的增長(zhǎng)方向?
對(duì)于一個(gè)用慣了i386系列機(jī)器的人來(lái)說(shuō),這似乎是一個(gè)無(wú)聊的問(wèn)題,因?yàn)闂>褪菑母叩刂废虻偷刂吩鲩L(zhǎng)。不過(guò),顯然這不是這個(gè)問(wèn)題的目的,既然把這個(gè)問(wèn)題拿出來(lái),問(wèn)的就不只是i386系列的機(jī)器,跨硬件平臺(tái)是這個(gè)問(wèn)題的首先要考慮到的因素。
在一個(gè)物質(zhì)極大豐富的年代,除非無(wú)路可退,否則我們堅(jiān)決不會(huì)使用匯編去解決問(wèn)題,而對(duì)于這種有系統(tǒng)編程味道的問(wèn)題,C是一個(gè)不錯(cuò)的選擇。那接下來(lái)的問(wèn)題就是如何用C去解決這個(gè)問(wèn)題。
C在哪里會(huì)用到棧呢?稍微了解一點(diǎn)C的人都會(huì)立刻給出答案,沒(méi)錯(cuò),函數(shù)。我們知道,局部變量都存在于棧之中。似乎這個(gè)問(wèn)題立刻就得到了解答,用一個(gè)函數(shù)聲明兩個(gè)局部變量,然后比較兩個(gè)變量的地址,這樣就可以得到答案。
等一下,怎么比較兩個(gè)變量的地址呢?
先聲明的先入棧,所以,它的第一個(gè)變量的地址如果是高的,那就是從上向下增長(zhǎng)?!跋嚷暶鞯南热霔!??這個(gè)結(jié)論從何而來(lái)?一般編譯器都會(huì)這么處理。要是不一般呢?這種看似正確的方法實(shí)際上是依賴于編譯器的,所以,可移植性受到了挑戰(zhàn)。
那就函數(shù)加個(gè)參數(shù),比較參數(shù)和局部變量的位置,參數(shù)肯定先入棧。那為什么不能局部變量先入棧?第一反應(yīng)是怎么可能,但仔細(xì)想來(lái)又沒(méi)有什么不可以。所以,這種方法也依賴于編譯器的實(shí)現(xiàn)。
那到底什么才不依賴于編譯器呢?
不妨回想一下,函數(shù)如何調(diào)用。執(zhí)行一個(gè)函數(shù)時(shí),這個(gè)函數(shù)的相關(guān)信息都會(huì)出現(xiàn)棧之中,比如參數(shù)、返回地址和局部變量。當(dāng)它調(diào)用另一個(gè)函數(shù)時(shí),在它棧信息保持不變的情況下,會(huì)把它調(diào)用那個(gè)函數(shù)的信息放到棧中。
似乎發(fā)現(xiàn)了什么,沒(méi)錯(cuò),兩個(gè)函數(shù)的相關(guān)信息位置是固定的,肯定是先調(diào)用的函數(shù)其信息先入棧,后調(diào)用的函數(shù)其信息后入棧。那接下來(lái),問(wèn)題的答案就浮出了水面。
比如,設(shè)計(jì)兩個(gè)函數(shù),一個(gè)作為調(diào)用方,另一個(gè)作為被調(diào)用方。被調(diào)用方以一個(gè)地址(也就是指針)作為自己的入口參數(shù),調(diào)用方傳入的地址是自己的一個(gè)局部變量的地址,然后,被調(diào)用方比較這個(gè)地址和自己的一個(gè)局部變量地址,由此確定棧的增長(zhǎng)方向。
給出了一個(gè)解決方案之后,我們?cè)倩剡^(guò)頭來(lái)看看為什么之前的做法問(wèn)題出在哪。為什么一個(gè)函數(shù)解決不了這個(gè)問(wèn)題。前面這個(gè)大概解釋了函數(shù)調(diào)用的過(guò)程,我們提到,函數(shù)的相關(guān)信息會(huì)一起送入棧,這些信息就包括了參數(shù)、返回地址和局部變量等等,在計(jì)算機(jī)的術(shù)語(yǔ)里,有個(gè)說(shuō)法叫棧幀,指的就是這些與一次函數(shù)調(diào)用相關(guān)的東西,而在一個(gè)棧幀內(nèi)的這些東西其相對(duì)順序是由編譯器決定的,所以,僅僅在一個(gè)棧幀內(nèi)做比較,都會(huì)有對(duì)編譯器的依賴。就這個(gè)問(wèn)題而言,參數(shù)和局部變量,甚至包括返回地址,都是相同的,因?yàn)樗鼈冊(cè)谕粋€(gè)棧幀內(nèi),它們之間的比較是不能解決這個(gè)問(wèn)題的,而它們就是一個(gè)函數(shù)的所有相關(guān)信息,所以,一個(gè)函數(shù)很難解決這個(gè)問(wèn)題。
好了,既然有了這個(gè)了解,顯然可以擴(kuò)展一下前面的解決方案,可以兩個(gè)棧幀內(nèi)任意的東西進(jìn)行比較,比如,各自的入口參數(shù),都可以確定棧的增長(zhǎng)方向。
狂想一下,會(huì)不會(huì)有編譯器每次專門留下些什么,等下一個(gè)函數(shù)的棧幀入棧之后,在把這個(gè)留下的東西入棧呢?這倒是個(gè)破壞的好方法。如果哪位知道有這么神奇的編譯器,不妨告訴我。我們可以把它的作者拉過(guò)來(lái)打一頓,想折磨死誰(shuí)?。?/p>