爲什麼64位進程不能調用32位dll

我想把它標爲原創, 因爲這不是一篇合格的翻譯; 我最終把它標爲翻譯, 因爲這更不是一篇合格的原創。

在此之前, 告訴你一個祕密:16位代碼是可以調入32位代碼的, 注意, 是可以。聰明的同學知道這個祕密後會問既然這樣子爲什麼32b代碼不能調入64b代碼呢?更聰明的同學會做出如下解釋(摳鼻, 我只是個翻譯, 哈哈):

地址空間, 16位系統和32位系統都住在一個線性空間地址, 16和32倆個數字是什麼意思呢? 對你我就真是個數字, 對於選擇器來說它代表相對偏移量。 那麼問題來了, 選擇器又是什麼?(我喜歡愛問爲什麼的同學, 打住, 我只喜歡愛問爲什麼的女同學, 暴露性取向了, 狂吐)。 在16位系統中, 地址是被選擇器和偏移量按某種格式被指定, 舉個栗子:一個的地址0x0123:0x4567, 意思是相對選擇器0x0123偏移0x4567字節, 每個選擇器在一個描述符表有一個相對入口表達了它是哪種類型的選擇器(它可用於讀數據? 寫數據? 執行代碼?), 但是對於現在這個問題我們更關心它所包含的另外倆個信息:基地址和限制。再舉個栗子:0x0123入口對於選擇器可能想說, 0x0123是一個只讀數據選擇器, 它起始於線性地址0x00524200(不要問我這個數字是哪來的, 我只是個翻譯, 作爲一個優秀的翻譯不會表達自己的意見, 但我不是, 隨手拿來的一個數字唄)和一個0x7fff的限制。這意味着0x0123:n指向線性地址0x00524200+n, 其中n<=0x7fff。

隨着80386引入, 一個選擇器的最高限制從0xffff提高到0xffffffff。 聰明的你會不會創造一個選擇器呢, 設置起始地址爲0x00000000和0xffffffff的限制, 使用這個選擇器我們可以訪問整個32位線性地址空間, 我們不在需要把它切分爲64KB塊的16位的日子裏, 我們聲明所有的地址都是這種格式, 也不需要糾結用哪個限制的選擇器, 因爲它隱含了可訪問所有位置。

你造嗎, 你發明了32位尋址方案! 當然並不是說沒有了選擇器, 只是變成了唯一。
現在是時候看看這種trunk模式帶來的後果。

首先, 你有沒有注意到16位全指針需要一個16位段地址(基地址)和一個16位偏移量, 共32位, 而32位指針需要一個32位大小的值; 所以0x0123:0x4567 可以表示一個16位全指針, 亦可表達一個32位指針, 我們壓根不需要改變它們結構, 它們就如此相像, 是不是一個很神奇的發現。

接下來, 注意到16位地址空間完全有能力指向32位的每個地址, 因爲倆個系統底層有相同的線性地址空間; 區別僅僅是16位的一次只能看到64KB, 需要多次看完所有, 而32位的一目十行, 雖然聰明的32位這麼牛逼, 但勤奮的16位分多次也可以達到相同效果, 好像說的真的勤能補拙一樣。  只是16位需要一個本本(臨時地址)計算並記錄。

說了這麼多貌似跑題了, 因爲上面說的這些不適用與32位到64位, 首先指針大小變了, 意味着32位和64位轉換會改變結構, 而64位的地址訪問能力爲32位的40億倍。 如果內存中存在64位偏移:0x0000 06fb 0123 4567, 32位根本沒法訪問。 不要問我爲什麼, 因爲他們沒有一個本本(臨時地址)來計算並記錄, 32爲放棄了選擇器, 你造嗎?

倆個人用不同的詞描述同一事物時, 如果一方甚至沒有談論那事物的能力, 作爲一個翻譯聳聳肩雙手一攤未嘗不可。

http://blogs.msdn.com/b/oldnewthing/archive/2008/10/20/9006720.aspx



ps:後續會補充64位進程調用32位dll的解決方案
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章