1. 程式人生 > >32 bit 與 64 bit 程序(2)比較

32 bit 與 64 bit 程序(2)比較

target 動態鏈接 指令 amd64 get 新的 應該 根據 poi

32 bit 與 64 bit 程序(2)區別

  由於操作系統內存分配的不同,導致軟件開發過程中,需要編譯不同版本的軟件。

幾個重要概念:

(1)這裏所說的的32位與64位程序,是指經過編譯器編譯後的可執行文件,例如像Windows上的exe文件,而最初編寫的源碼並沒有32位和64位之說

(2)不是所有的程序需要區分32位和64位,對於原生語言例如C語言編寫的程序需要區分64位與32位,但是對於像Java這樣的語言,就不需要這樣了,因為Java編寫的程序是在JVM(Java虛擬機)上運行的,JVM屏蔽了具體的硬件細節。

(3)32位與64位的程序的本質區別在於:兩者最終在處理器CPU

上運行的指令是不一樣的

  

  平臺的所指的是:CPU +OS + 軟件

  軟件: 【源碼】 + 編譯器 【64/32】= exe【64/32】

一、處理器CPU的不同(64bit, 32bit):

  主要是指:64位CPU,32位CPU, 對於歷史中的16bit的處理器,則不是當今主流不講。

  註意:CPU的不同bit ,內部的指令集,操作位數,寄存器名稱和個數都不同

一、比如一條mov eax,1指令,可能在32bCPU上對應的機器指令是0x1201;在64位機器上就是0x123401。
二、64位CPU裏的寄存器是64位的,這樣CPU每次處理的數據量也就更大,32位CPU寄存器是32位的
。 三、64位CPU裏的寄存器數量也多於32位CPU。 四、32位CPU的地址總線不一定是32位的,還有可能是48位的,同樣64位的CPU地址總線也不一定是64位,往往都是48位。 五、現在對於主流的處理器,64位的CPU是能夠兼容32位指令架構的!!!!!!

(1)從上面可以看到64位CPU的運算能力理論上比32位CPU強很多。

(2)現在32位的CPU一般是X86架構的,從80386開始就是32位的CPU,也對應他的32位指令集。

(3)後來發展出64位CPU,從X86擴展出64位的指令集,一般我們就叫做X64,也叫AMD64架構,因為最早是AMD推出64位CPU的。

 

二、操作系統OS(64bit, 32bit):

1. OS與CPU的關系

(1)32位的操作系統是專門為32位CPU設計的,同樣64位的操作系統是為64位的CPU設計的。

(2)前面也說了,64位的CPU能夠兼容32位指令架構,因此在64位CPU上也可以安裝32位操作系統

(3)32bit的操作系統安裝再32bit CPU, 64bit 的OS安裝再64bit CPU才能將OS發揮最大優勢。

(4)32bit的編譯器也可以編譯64bit 的程序

2. 尋址空間的影響

   64bit CPU擁有更大的尋址能力,使用最大為192GB內存,而32bit只支持4G內存.

  64位CPU一次可提取64位數據,比32位提高了一倍,理論上性能會提升1倍。但這是建立在64bit操作系統,64bit軟件的基礎上的。

    技術分享圖片

  之所以叫做“64位處理器”,是因為電腦內部都是實行2進制運算,處理器(CPU)一次處理數據的能力也是2的倍數。8位處理器、16位處理器、32位處理器和64位處理器,其計數都是2的倍數。一次處理的數據越大,該電腦處理信息的能力越來越大;因此64位處理在先天就比32位處理器具有快速的能力。那為什麽不用更高級的128位處理器呢?因為位數越高,處理器芯片的設計也就越復雜,目前的技術水平暫時無法制造這麽復雜的芯片。

3. 程序軟件【32bit, 64bit】

(1)32位的程序就是將源碼32位的編譯器編譯的,64位的程序就是將源碼用64位的編譯器編譯的。

(2)應用程序只接觸邏輯地址,並不接觸真實的物理地址

  32位的程序理論上可以申請利用4GB的地址空間,64位的程序則可以申請利用大於4GB 的地址空間,這也是64位程序的一個巨大優勢。

  我們知道應用程序的運行是需要操作系統作為支撐的,這些程序在運行時常常需要進行一些系統調用,還有各種庫函數等。

這些可執行文件【exe】能否順利運行有著兩個最重要的地方。 1)動態鏈接庫。
2)系統API。

  對於Windows系統而言,64位的系統往往還具有32位系統的庫,因此在64位系統上能夠運行32位的程序,但是反過來就不行了,因為32位系統一般沒有64位系統的庫。

  可以通過博客:https://www.cnblogs.com/icmzn/p/10269911.html

  再64bit 的 Window系統中,32bit 的exe 調用的是目錄下的系統dll:C:\ Window\SysWOW64\....,這裏的SysWOW64,表示的意思是: 32bit 的軟件在Window 64 位OS上運行的32bit 的dll 系統文件。

  64bit 的exe則調用的目錄的系統dll: c:、Window\Win32\...

  註意:這裏的Win32可能是歷史遺留問題,這樣對於Window 64 的改動較小,我猜測的,哈哈哈

  技術分享圖片

  64exe 調用的64bit OS的系統dll文件

  技術分享圖片

  

64bit 處理器優勢:

(1)硬件, 執行速度更快, 更大的內存管理。

(2)軟件, 最新的尖端軟件首選64bit 操作系統作為開發平臺。

64bit處理器劣勢:

(1)硬件, 部分的驅動程序對64bit 的系統支持不高, 例如對於工業控制領域,更多的模塊提供了32bit 的控制庫文件,而沒有64bit的版本。

(2)軟件, 由於操作系統是64bit 的,導致很多歷史中的32bit 的exe 不能再64系統上兼容,可能出現計算誤差。

2. 代碼中的基本的數據類型,會根據操作系統的位數分配內存大小:

  因此在64位上對int型數據操作,編譯生成32的程序,有可能導致int型越界,軟件出現問題

不同的平臺上對不同數據類型分配的字節數是不同的,數據類型的字節數應該是由CPU決定的,但是實際上主要由編譯器決定(占多少位由編譯器在編譯期間說了算)

常用數據類型對應字節數:

 可用如sizeof(char),sizeof(char*)等得出

  測試程序:

#include "stdafx.h"  
#include <iostream>  
#include <string>  
using namespace std;  
 
//main  
int _tmain(int argc, _TCHAR* argv[])  
{  
    cout << "sizeof(char):" << sizeof(char) << endl;  
    cout << "sizeof(short):" << sizeof(short) << endl;  
    cout << "sizeof(int):" << sizeof(int) << endl;  
    cout << "sizeof(long):" << sizeof(long) << endl;  
    cout << "sizeof(long long):" << sizeof(long long) << endl;  
    cout << "sizeof(unsigned int):" << sizeof(unsigned int) << endl;  
    cout << "sizeof(float):" << sizeof(float) << endl;  
    cout << "sizeof(double):" << sizeof(double) << endl;  
    void* pointer;  
    cout << "sizeof(pointer):" << sizeof(pointer) << endl;  
  
    system("pause");  
    return 0;  
}  

  32bit 的編譯器下測試輸出:數據類型長度

  技術分享圖片

  64 bit 的編譯器下測試輸出:數據類型長度

  技術分享圖片

註意:

(1)32位和64位系統在Windows下基本數據類型的大小都是一樣的。只有指針的大小不一樣!32位指針大小為4byte,而64位的指針大小為8byte。

(2) Linux下,long型是64位的,這一點是和Windows不同的地方。

  

  為什麽Windowsx64下long也為4byte?

  正常標準的話,long應該也是64位即8byte。但是在Windows下,我們的結果卻是4byte。為什麽會這樣呢?

因為:

  我們編程時很少關註數據類型真正的大小,畢竟即使不關註這個也可以編程,而且我們習慣了Win32,到64位下,只有指針因為尋址需要是必須變成64位的,64位的指針尋址範圍是0~2^64-1,而其他的數據類型基本已經夠用,如果把所有數據類型變成64位,明顯是浪費空間。再者,為了讓32位和64位程序兼容運行,能少修改還是少修改,所以Windows僅將指針大小進行了修改。這樣,程序可以兼容運行。

  

 指針的大小比較?

  int類型指針,通用指針void*, 類指針, 函數指針的長度確定:

#include "stdafx.h"  
#include <iostream>  
#include <string>  
using namespace std;  
  
class Test  
{  
    int num;  
    string name;  
};  
//一個函數指針  
typedef void(*pFunc)(void);  
void PrintHello(void)  
{  
    cout << "hello world" << endl;  
}  
//main  
int _tmain(int argc, _TCHAR* argv[])  
{  
    int* pInt;  
    void* pVoid;  
    Test* pTest = new Test();  
    pFunc pfunc = PrintHello;  
    cout << "sizeof(pInt):" << sizeof(pInt) << endl;  
    cout << "sizeof(pVoid):" << sizeof(pVoid) << endl;  
    cout << "sizeof(pTest):" << sizeof(pTest) << endl;  
    cout << "sizeof(pFunc):" << sizeof(pfunc) << endl;  
  
    system("pause");  
    return 0;  
}  
結果:
Win32下:
sizeof(pInt):4
sizeof(pVoid):4
sizeof(pTest):4
sizeof(pFunc):4
請按任意鍵繼續. . .
x64下:
sizeof(pInt):8
sizeof(pVoid):8
sizeof(pTest):8
sizeof(pFunc):8
請按任意鍵繼續. . .

  不管指針指向張三李四還是王二麻子,都是一樣大的。能夠影響指針大小的,還是位數。32位下指針大小為4,64位下指針的大小為8.


總結:

(1)32位升級到64位不是簡單的重新編譯發布一下就可以了。舉個例子,在32位C語言環境裏一個指針可以放入一個int型的變量中,但在64位裏就不行了了,因為64位程序裏的指針為64位,這樣的話程序肯定就爆了,因此對於某些程序如果想要升級到64位,則需要修改源碼,這個工作是相當繁瑣的。

(2)由於64位操作系統的尋址和偏移的問題,也有可能導致程序在運行過程中,計算結果與32位系統不一致

(3)64位CPU可以運行32位或者64位的操作系統,64位操作系統可以運行32位或64位程序。

(4)32位CPU只能安裝32位的操作系統,而32位操作系統只能運行32位的程序。

(5),第一個64位的程序是怎麽來的,因為那個時候還沒有64位的編譯器,其實很簡單,32位的編譯器也可以編譯出64位的程序 ,當然這個問題就沒有必要深究了

endl;

32 bit 與 64 bit 程序(2)比較