1. 程式人生 > >64 位軟體和 32 位有什麼具體區別?

64 位軟體和 32 位有什麼具體區別?

1.32bCPU和64bCPU的區別?
首先二者的指令集合、運算元位數、暫存器名稱和個數等等都不相同;
比如一條mov eax,1指令,可能在32bCPU上對應的機器指令是0x1201;在64位機器上就是0x123401。程式對於機器CPU而言,僅僅是一系列順序躺在記憶體中的01程式碼而已,而硬體上直接執行的是作業系統,所以你馬上得出結論:32b的CPU只能執行32b的作業系統,64位亦然。
這麼設計的確在理論上沒什麼不妥,實際上intel IA 64架構的處理器就是這樣的,64b的CPU上只能執行64b的作業系統(作業系統本身也是軟體,也是一系列指令序列)。

但這樣問題就來了:我需要升級硬體來提速,難道買了CPU以後,要把上層的作業系統和應用軟體通通換掉?坑碟呢?這種軟硬體不相容帶來的問題就是,沒有多少客戶會去購買這種沒法相容32b原有軟體環境的CPU。所以,後來intel和amd都推出了相容32b原有軟體環境的CPU——intel 的x86——64和amd的amd64.
也就是說,現在主流的64b處理器,上面可以執行32b和64b的作業系統。


2.編譯器與程式位數?
通常情況下,編譯器也僅僅是一個應用軟體而已,64b機器上的64b編譯器編譯出來的也就是64b的應用軟體。但是有沒有例外呢?

想一想:第一個64的作業系統是怎麼來的?
我們都知道現在作業系統一般是用C語言實現的,然後像普通程式一樣經過編譯器編譯成可執行檔案,難道64b的作業系統不是用64b的編譯器編譯出來的?


很顯然,你的第一個64b的作業系統,需要用“64b”的編譯器來生成,但你的64b的編譯器執行在什麼作業系統上呢?當然,我肯定執行在64b的作業系統之上,那你64b的作業系統從哪裡來呢。。。。。。。。。。。。。。是不是覺得陷入迴圈了!!!!
所以,必然有一種編譯器,本身是32b的軟體,但是能夠將程式編譯成64b的可執行檔案,也就是作業系統。也只有這種情況下,編譯器本身位數和編譯出來程式的位數才不一致。


3.作業系統位數和軟體位數的關係


這裡,我們首先要弄清一個軟體是如何被執行的。


我們以C檔案為例,討論我們經典的hello word程式:
#include<stdio.h>
int main(){
printf("hello world")
}
一個源程式首先被預處理,尋找標頭檔案,將標頭檔案包括進來,裡面有printf的申明。

然後被編譯成目標檔案,注意目標檔案已經是二進位制檔案了,裡面的符號表中有main、printf等,但是很顯然,這個prinf不是我們自己寫的,我們僅僅有它的申明而已。此時如果我們檢視目標檔案,就會發現目標檔案中的printf函式是extern標記,表示這是一個外部符號,並不是我們定義的。
很顯然,目標檔案是沒法執行的,因為裡面有未知符號沒有解析。

目標檔案經過連結,形成可執行目標檔案。因為作業系統提供了已經編譯好的動態連結庫,所以此時我們僅僅經過連結,神奇的hello就能執行了。

這樣,你是不是沒有感覺到你的軟體有32b和64b的區別?你管它叫128b都沒問題。
但是,上述過過程有幾個非常重要的地方:
1)動態連結庫
2)系統API

首先,你32b的作業系統上一般是沒有64b的庫檔案的.如果你的應用程式原始碼中引用了只有64b的動態庫中才有的函式,很顯然你連結的時候就會出問題。

量外,我們很多程式肯定用到了read和write等C語言庫函式,而庫函式的實現是依賴於系統API的。

如果你工作在windows上,程式大多數是以exe形式釋出的,你得到的程式是目標檔案以後的結果,本身是帶有位數的;如果你工作在linux上,本身大部分軟體包rpm等也是已經編譯好的,就是說,它們本身就是具有“位數”的。如果你得到的是原始碼,那麼基本上你的應用程式還沒有“位數”的概念,你用多少位的編譯器去編譯它,它就是多少位的應用程式。我們這裡討論多少位的程式,都是針對已經編譯到目標檔案以後的狀態。


4.回到最初的問題:
1)64位的系統上是否能執行32b的應用程式?
2)32b的系統上是否能執行64位的應用程式?

1)對於win系統而言,64b的系統上往往有32b的庫和其他必要的資訊,基本上能相容32b的程式。想想,如果不能相容,那麼作業系統肯定比應用軟體先出來——畢竟軟體是在作業系統上開發的,這樣作業系統出來之後,上面32b的軟體都不能運行了?
顯然不是這樣的。也就是說,64b的系統上可以執行32b的程式。

2)32b的系統,一般情況下是沒有64b的庫的,也沒有相關係統api,
一般情況下,32b的系統上沒法執行64b的應用程式。