1. 程式人生 > >32位與64位程式設計注意事項總結

32位與64位程式設計注意事項總結

---------------------------------------------------------------------------------------------

新近的64位平臺在二進位制上與32位應用程式相容,這意味著可以非常簡單地移植現有的程式。許多目前在32位平臺上執行良好的程式也許不必移植,除非程式有以下要求:
·需要多於4GB的記憶體。
·使用的檔案大小常大於2GB。
·密集浮點運算,需要利用64位架構的優勢。
·能從64位平臺的優化數學庫中受益。
否則,只需簡單地重新編譯一下,就已經足夠了。大多數編寫良好的程式不費吹灰之力就可移植到64位平臺之上,在此假定你的程式編寫良好,並熟悉本文將要討論的問題。 
ILP32和LP64資料模型


32位環境涉及"ILP32"資料模型,是因為C資料型別為32位的int、long、指標。而64位環境使用不同的資料模型,此時的long和指標已為64位,故稱作"LP64"資料模型。
現今所有64位的類Unix平臺均使用LP64資料模型,而64位Windows使用LLP64資料模型,除了指標是64位,其他基本型別都沒有變。我們在此主要探討ILP32到LP64的移植問題,表1顯示了ILP32與LP64資料模型的差異。
向64位移植程式碼時的所有問題差不多都可以總結出一個簡單的規律:千萬不要認為int、long、指標的長度一樣。任何違反這條規律的程式碼,當執行在 LP64資料模型下時,都會出現不同的問題,而且很難找出原因所在。例1中有許多違反這條規律的地方,其在移植到64位平臺上時都需要重寫。
例1:

1 int *myfunc(int i)
2 {
3  return(&i);
4 }
5
6 int main(void)
7 {
8  int myint;
9  long mylong;
10 int *myptr;
11
12  char *name = (char * ) getlogin();
13
14  printf("Enter a number %s: ", name);
15  (void) scanf("%d", &mylong);
16  myint = mylong;
17  myptr = myfunc(mylong);
18  printf("mylong: %d pointer: %x \n", mylong, myptr);
19  myint = (int)mylong;
20  exit(0);
21
22 }


第一步是要求編譯器捕捉到移植時的問題,因所用編譯器的不同,選項可能也有所不同,但對IBM XL編譯器系列,可用的選項有-qwarn64-qinfo=pro,為了得到64位可執行檔案,可使用選項-q64(如果使用GCC,選項應為-m64,表2中列出了其他可用的GCC選項)。圖1是編譯例1中程式碼時的情況。


編譯例1中程式碼時的情況

缺少原型的截斷
如果一個函式被呼叫時沒有指定函式原型,返回值將是32位的int。不使用原型的程式碼可能會發生意料之外的資料截斷,由此導致一個分割錯誤。編譯器捕捉到了例1中第12行的這個錯誤。
char *name = (char *) getlogin();
編譯器假定函式返回一個int值,並截短結果指標。這行程式碼在ILP32資料模型下工作正常,因為此時的int和指標是同樣長度,換到LP64模型中,就不一定正確了,甚至於型別轉換都不能避免這個錯誤,因為getlogin()在返回之後已經被截斷了。
要修正這個問題,需包括標頭檔案<unistd.h>,其中有getlogin()的函式原型。
格式指定符
如果對64位long、指標使用了32位格式指定符,將導致程式錯誤。編譯器捕捉到了例1中第15行的這個錯誤。
(void) scanf("%d", &mylong);
注意,scanf將向變數mylong中插入一個32位的值,而剩下的4位元組就不管了。要修正這個問題,請在scanf中使用%ld指定符。
第18行也演示了在printf中的一個類似的問題:
printf("mylong: %d pointer: %x \n", mylong, myptr);
要修正此處的錯誤,mylong應使用%ld,對myptr使用 %p而不是%x。
賦值截斷
有關編譯器發現賦值截斷的一個例子在第16行中:
myint = mylong;
這在ILP32模型下不會有任何問題,因為此時的int、long都是32位,而在LP64中,當把mylong賦值給myint時,如果數值大於32位整數的最大值時,數值將被截短。
被截斷的引數
編譯器發現的下一個錯誤在第17行中,雖然myfunc函式只接受一個int引數,但呼叫時卻用了一個long,引數在傳遞時會悄無聲息地被截斷。
轉換截斷
轉換截斷髮生在把long轉換成int時,比如說例1中的第19行:

myint = (int) mylong;


導致轉換截斷的原因是int與long非同樣長度。這些型別的轉換通常在程式碼中以如下形式出現:

int length = (int) strlen(str);


strlen返回size_t(它在LP64中是unsigned long),當賦值給一個int時,截斷是必然發生的。而通常,截斷只會在str的長度大於2GB時才會發生,這種情況在程式中一般不會出現。雖然如此,也應該儘量使用適當的多型型別(如size_t、uintptr_t等等),而不要去管它最下面的基型別是什麼。
一些其他的細小問題
編譯器可捕捉到移植方面的各種問題,但不能總指望編譯器為你找出一切錯誤。
那些以十六進位制或二進位制表示的常量,通常都是32位的。例如,無符號32位常量0xFFFFFFFF通常用來測試是否為-1:

#define INVALID_POINTER_VALUE 0xFFFFFFFF


然而,在64位系統中,這個值不是-1,而是4294967295;在64位系統中,-1正確的值應為0xFFFFFFFFFFFFFFFF。要避免這個問題,在宣告常量時,使用const,並且帶上signed或unsigned。

const signed int INVALID_POINTER_VALUE = 0xFFFFFFFF;


這行程式碼將會在32位和64位系統上都執行正常。
其他有關於對常量硬編碼的問題,都是基於對ILP32資料模型的不當認識,如下:

int **p; p = (int**)malloc(4 * NO_ELEMENTS);


這行程式碼假定指標的長度為4位元組,而這在LP64中是不正確的,此時是8位元組。正確的方法應使用sizeof():

int **p; p = (int**)malloc( sizeof(*p) * NO_ELEMENTS);


注意對sizeof()的不正確用法,例如:

sizeof(int) = = sizeof(int *);


這在LP64中是錯誤的。
符號擴充套件
要避免有符號數與無符號數的算術運算。在把int與long數值作對比時,此時產生的資料提升在LP64和ILP32中是有差異的。因為是符號位擴充套件,所以這個問題很難被發現,只有保證兩端的運算元均為signed或均為unsigned,才能從根本上防止此問題的發生。
例2:

long k;
int i = -2;
unsigned int j = 1;
k = i + j;
printf("Answer: %ld\n", k);


你無法期望例2中的答案是-1,然而,當你在LP64環境中編譯此程式時,答案會是4294967295。原因在於表示式(i+j)是一個 unsigned int表示式,但把它賦值給k時,符號位沒有被擴充套件。要解決這個問題,兩端的運算元只要均為signed或均為unsigned就可。像如下所示:

k = i + (int) j

聯合體問題(Union)
當聯合本中混有不同長度的資料型別時,可能會導致問題。如例3是一個常見的開原始碼包,可在ILP32卻不可在LP64環境下執行。程式碼假定長度為2的unsigned short陣列,佔用了與long同樣的空間,可這在LP64平臺上卻不正確。
例3:

typedef struct {
 unsigned short bom;
 unsigned short cnt;
 union {
unsigned long bytes;
unsigned short len[2];
 } size;
} _ucheader_t;


要在LP64上執行,程式碼中的unsigned long應改為unsigned int。要在所有程式碼中仔細檢查聯合體,以確認所有的資料成員在LP64中都為同等長度。
位元組序問題(Endian)
因64位平臺的差異,在移植32位程式時,可能會失敗,原因可歸咎於機器上位元組序的不同。Intel、IBM PC等CISC晶片使用的是Little-endian,而Apple之類的RISC晶片使用的是Big-endian;小尾位元組序(Little- endian)通常會隱藏移植過程中的截斷bug。
例4:

long k;
int *ptr;
int main(void)
{
 k = 2 ;
 ptr = &k;
 printf("k has the value %ld, value pointed to by ptr is %ld\n", k, *ptr);
 return 0;
}


例4是一個有此問題的明顯例子,一個宣告指向int的指標,卻不經意間指向了long。在ILP32上,這段程式碼打印出2,因為int與long長度一樣。但到了LP64上,因為int與long的長度不一,而導致指標被截斷。不管怎麼說,在小尾位元組序的系統中,程式碼依舊會給出k的正確答案2,但在大尾位元組序(Big-endian)系統中,k的值卻是0。


找出64位移植問題的可用的GCC鄙夷選項

表3說明了為什麼在不同的位元組序系統中,會因截斷問題而產生不同的答案。在小尾位元組序中,被截斷的高位地址中全為0,所以答案仍為2;而在大尾位元組序中,被截斷的高位地址中包含值2,這樣就導致結果為0,所以在兩種情況下,截斷都是一種 bug。但要意識到,小尾位元組序會隱藏小數值的截斷錯誤,而這個錯誤只有在移植到大尾位元組序系統上時才可能被發現。

移植到64位平臺之後的效能降低
當代碼移植到64位平臺之後,也許發現效能實際上降低了。原因與在LP64中的指標長度和資料大小有關,並由此引發的快取命中率降低、資料結構膨脹、資料對齊等問題。 
由於64位環境中指標所佔用的位元組更大,致使原來執行良好的32位程式碼出現不同程度的快取問題,具體表現為執行效率降低。可使用工具來分析快取命中率的變化,以確認效能降低是否由此引起。
在遷移到LP64之後,資料結構的大小可能會改變,此時程式可能會需要更多的記憶體和磁碟空間。例如,圖2中的結構在ILP32中只需要16位元組,但在 LP64中,卻需要32位元組,整整增長了100%。這緣於此時的long已是64位,編譯器為了對齊需要而加入了額外的填充資料。
通過改變結構中資料排列的先後順序,能將此問題所帶來的影響降到最小,並能減少所需的儲存空間。如果把兩個32位int值放在一起,會因為少了填充資料,儲存空間也隨之減少,現在儲存整個結構只需要24位元組。
在重排資料結構之前,在根據資料使用的頻度仔細衡量,以免因降低快取命中率而帶來效能上的損失。
如何生成64位程式碼
在一些情況中,32位和64位程式在原始碼級別的介面上很難區分。不少標頭檔案中,都是通過一些測試巨集來區分它們,不幸的是,這些特定的巨集依賴於特定的平臺、特定的編譯器或特定的編譯器版本。舉例來說,GCC 3.4或之後的版本都定義了__LP64__,以便為所有的64位平臺通過選項-m64編譯產生64位程式碼。然而,GCC 3.4之前的版本卻是特定於平臺和作業系統的。 
也許你的編譯器使用了不同於 __LP64__的巨集,例如IBM XL的編譯器當用-q64編譯程式時,使用了__64bit__巨集,而另一些平臺使用_LP64,具體情況可用__WORDSIZE來測試一下。請檢視相關編譯器文件,以便找出最適合的巨集。例5可適用於多種平臺和編譯器:
例5:

#if defined (__LP64__) || defined (__64BIT__) || defined (_LP64) || (__WORDSIZE == 64)
printf("I am LP64\n");
#else
printf("I am ILP32 \n");
#endif


共享資料
在移植到64位平臺時的一個典型問題是,如何在32位和64位程式之間讀取和共享資料。例如一個32位程式可能把結構體作為二進位制檔案儲存在磁碟上,現在你要在64位程式碼中讀取這些檔案,很可能會因LP64環境中結構大小的不同而導致問題。
對那些必須同時執行在32位和64位平臺上的新程式而言,建議不要使用可能會因LP64和ILP32而改變長度的資料型別(如long),如果實在要用,可使用標頭檔案<inttypes.h>中的定寬整數,這樣不管是通過檔案還是網路,都可在32位和64位的二進位制層面共享資料。
例6:

#include <stdio.h>
#include <inttypes.h>
struct on_disk
{
 /* ILP32|LP64共享時,這個應該使用int32_t */
 long foo;
};
int main()
{
 FILE *file;
 struct on_disk data;
 #ifdef WRITE
file=fopen("test","w");
data.foo = 65535;
fwrite(&data, sizeof(struct on_disk), 1, file);
 #else
file = fopen("test","r");
fread(&data, sizeof(struct on_disk), 1, file);
printf("data: %ld\n", data.foo);
 #endif
 fclose(file);
}


來看一下例6,在理想的情況下,這個程式在32位和64位平臺上都可正常執行,並且可以讀取對方的資料。但實際上卻不行,因為long在ILP32和 LP64之中長度會變化。結構on_disk裡的變數foo應該宣告為int32_t,這個定寬型別可保證在當前ILP32或移植到的LP64資料模型下,都生成相同大小的資料。
混合Fortran和C的問題
許多科學運算程式從C/C++中呼叫 Fortran的功能,Fortran從它本身來說並不存在移植到64位平臺的問題,因為Fortran的資料型別有明確的位元大小。然而,如果混合 Fortran和C語言,問題就來了,如下:例7中C語言程式呼叫例8中Fortran語言的子例程。
例7:

void FOO(long *l);
main ()
{
 long l = 5000;
 FOO(&l);
}


例8:

subroutine foo( i )
integer i
write(*,*) 'In Fortran'
write(*,*) i
return
end subroutine foo


例9:

% gcc -m64 -c cfoo.c
% /opt/absoft/bin/f90 -m64 cfoo.o foo.f90 -o out
% ./out
In Fortran
0


當連結這兩個檔案後,程式將打印出變數i的值為"5000"。而在LP64中,程式打印出"0",因為在LP64模式下,子例程foo通過地址傳遞一個 64位的引數,而實際上,Fortran子例程想要的是一個32位的引數。如果要改正這個錯誤,在宣告Fortran子例程變數i時,把它宣告為 INTEGER*8,此時和C語言中的long為一樣長度。
結論
64位平臺是解決大型複雜科學及商業問題的希望,大多數編寫良好的程式可輕鬆地移植到新平臺上,但要注意ILP32和LP64資料模型的差異,以保證有一個平滑的移植過程。

linux原始碼包,是不是不分64位包和32位包啊?在64位伺服器上,可以安裝;在32位伺服器上也可以安裝?

樓主你想累死開發人員啊?現在的 Linux 下面程式的原始碼都是一套,不管是 64 還是 32 ,也不管是在 PowerPC 上還是在 SUN 的伺服器上,還是在手機上還是在你的計算機上,都是隻一套原始碼。不過這一套原始碼要看是不是真的能用,一些老軟體只能字啊 32 位系統下面編譯,有的新軟體可能針對 64 位有優化。跨架構和跨位元組數,一般都需要原始碼裡面有相應的處理的。尤其是大型軟體。

Linux
是遵循 POSIX 規範的,所以這種一個原始碼支援全部的架構理論上是存在的,但實際上各種條件都可能影響原始碼的可移植性其中的各種原因什麼的一句話兩句話說不清楚。

對,原始碼包是不分3264位的。

如果是RPM包,就是已經編譯的那種有分64位和32位,二進位制型別的可執行檔案一般也有分6432位,但是原始碼包沒有分,都可以用來編譯安裝,但是部分原始碼包64位和32位編譯的時候加的引數有點區別而已

第一講什麼是64位系統

截至本課程編寫的時間為止,市場上有兩種受歡迎的64位微處理器體系結構:IA64 Intel64

1.   IA-64是由 Intel HP 合作開發的64位微處理機體系結構。Itanium Itanium2 微處理機中就是用了這種體系結構。如想了解更多關於IA-64的資訊,請檢視Itanium

2.   Intel 64 (EM64T / AMD64 / x86-64 / x64)x86體系的繼承,同時保持向後相容。這種體系結構的名字有不同變型,因而導致了一些疑惑,但是以下這些名字所指的都是同樣的事物:x86-64, AA-64,Hammer Architecture, AMD64, Yamhill Technology, EM64T, IA-32e, Intel 64, x64想了解更多為什麼會有這麼多不同的名字,請參看文章

你需要了解到IA-64Intel64是完全不同、不能相互相容的微處理機體系結構。在本文的範圍內,我們僅討論在Windows軟體開發人員中比較受歡迎的Intel64x64/AMD64)結構。相對應的,當我們說起Windows 作業系統的時候,我們指的對應Intel64體系的64位作業系統。例如,Windows XP Professional x64 Edition,Windows Vista x64, Windows 7 x64 Intel64所對應的程式設計模型,對於基於64windows開發的程式設計師來說,簡稱為Win64

Intel 64 體系結構

Intel64 體系結構,在我們看來,就是一個簡單但是非常有效的對於現有的商用x86體系結構的反向相容。Intel64 加入了64位地址定址的內容,同時擴充套件了資源來更好支援高效能的64位程式。陳舊的16位和32位的應用和作業系統,不需要進行額外的修改或者是重新編譯,就可以在64位體系結構上執行。

64位體系結構出現的原因在於應用需要更大的定址空間。這些應用可能是高效能的伺服器,資料管理系統,CAD或者遊戲。這些應用將從64位地址空間和更多地暫存器中得到大量的效能提升。在陳舊的x86系統中,只有少量的暫存器存在,因而限制了計算任務的效能。暫存器數量的增加使得能夠進一步提高應用的效能。

讓我們首先來看一下x64體系的優勢。

l  64位定址空間

擴充套件的暫存器組

開發者熟悉的命令集

可以在64位結構的作業系統上執行32位程式

可以直接使用32位作業系統

64位作業系統

基本上所有現在的作業系統都有支援64位體系結構的版本。例如,Mircosoft就釋出了Windows XP x64。大型的UNIX的開發者也釋出了64位版,例如Linux Debian 3.5x86-64,但是這不代表著這些系統的全部程式碼是64位的。因為64位系統提供反向相容,有些作業系統和許多應用仍然是32位。因此,64位版的Windows 使用了一個特殊的模型WoW64 (Windows-on-Windows64),這個模型能夠翻譯32位應用的呼叫來使用64位作業系統的資源。

地址空間

雖然64位處理器理論上能夠支援16 Ebytes (2^64)的記憶體空間,Win64現在僅僅支援16Tbytes (2^44)的空間。造成這個現象的原因有一些:現代的處理器僅僅能夠提供1Tbyte (2^40)的物理儲存的定址。這個體系(不是這個硬體部分)可以擴充套件到支援4 Pbytes (2^52)的空間,但是在這種情況下你需要大量的記憶體來儲存分頁表。

除了上述描述的侷限以外,每一種64Windows版本的上記憶體的大小取決於Mircosoft的商業決定。不同的Windows版本有不同的限制如下表所示。

1 不同Windows版本所支援的地址空間

Win64 程式設計模型

Win32類似的,Win64的頁面大小也是4 Kbyte。最靠前的64Kbyte 地址空間是不開放的,所以最低的正確的地址是0x10000。而不像在Win32中,系統的DLL佔據了超過4 Gbyte的空間。

Intel64 的編譯器有一個特性:它們可以用暫存器來更有效率的傳遞引數給函式,而不是使用堆疊。這就使得使用Win64體系的開發人員可以丟棄呼叫約定(calling convention)的概念。在Win32中,你可以使用許多約定,比如__stdcall, __cdecl, __fastcall。在Win64種,只有一個呼叫約定。下面的例子,是來描述4個整型引數是怎樣通過暫存器的。

l  RCX: 第一個引數

l  RDX: 第二個引數

l  R8: 第三個引數

l  R9: 第四個引數

在第四個引數之後的引數通過堆疊來傳遞。如果是要傳遞浮點型的引數,需要使用XMM0-XMM3 暫存器和堆疊。

在呼叫約定方面的區別,使得開發人員不能夠在同一個程式中同時使用64位和32位的內容。用另一句話來說,如果一個應用是通過64位來編譯的,所有的動態連結庫也要是64位。

通過暫存器來傳遞引數,是使得64位程式比32位程式快的一個創新。你可以通過64位的資料結構來取得進一步的效能提升。在下一講中我們將討論這方面的問題。

第二講 64Windows環境對32位應用的支援

在我們開始討論64位程式前,讓我們談論一下64Windows系統對32位應用的反向相容。反向相容是通過WoW64中的機制來實現的。

WoW64(Windows-on-Windows 64-bit) Windows作業系統的一個子系統,它使得能夠在64Windows系統上執行32位應用。

WoW64子系統不支援以下程式:

1.   16位作業系統所編譯的程式

2.   32位作業系統所編譯的核心(kernel-mode)程式

間接費用

不同處理器體系的WoW64 有一些不同。例如,為Intel Itanium 2 開發的64Windows版本,使用WoW64來模擬x86 指令。這個模擬比起Intel64 WoW64體系需要更多資源,因為系統在執行32位程式的時候需要從64位模式轉換到相容模式。

Intel 64 (AMD64/ x64) 上的WoW64 不需要指令模擬。在這個系統上,WoW64子系統僅僅是通過在32位應用和64Windows API之間新增額外的一層,來模擬32位的環境。在有些地方,這新加的一層可能比較薄,在另一些地方這一層比較厚。平均來說,對於一個程式,你需要期待因為這一個層次所帶來效能上2%的損失。對於有些程式來說,這個數值可能更大。2%可能並不是一個很大的數字,但是你需要銘記在心的是32位程式在64位系統中比它們在32位系統中執行的要慢。

把程式編譯為64位的程式碼,不僅使你避免使用WoW64,同時能使你得到了效能上提升。這個可以通過體系結構上的改變,如更多的通用暫存器來解釋。平均來說,對於一個程式,通過簡單的重新編譯,你可以期待著在效能上有5%-15%的提升。

64位環境上執行32位程式的好處

因為WoW6432位程式在64位系統中比它們在32位系統中執行的要慢。但是簡單的32位程式可以從在64位系統上執行獲得一個好處。或許你知道,如果在32Windows系統選擇“/3gb”, 程式編譯時選擇"/LARGEADDRESSAWARE:YES",它可以分配到最高達3 Gbytes的記憶體空間。同樣的32位程式在64位系統可以分配大最高達4Gbytes的記憶體空間(現實中大約是3.5 Gbytes的記憶體空間)。

重定位

WoW64子系統是通過將呼叫重定位至檔案和暫存器,從而將32位程式與64位程式分離開來。這樣使得32位程式不會意外的接觸64程式的資料。例如,一個從"%systemroot%\System32"中呼叫了DLL檔案的32位應用程式,如果不進行隔離,那麼它可能呼叫了一個32位程式無法相容的64DLL檔案。為了避免這樣的情況發生,WoW64位子系統將進入"%systemroot%\System32"資料夾的呼叫重定位到呼叫"%systemroot%\SysWOW64"資料夾中的檔案。這種重定位使得開發者能避免相容性的問題,因為32位應用程式需要能與它們相容的特殊的DLL檔案。

為什麼32DLL不能在64位程式中使用?是否有方式可以避免這種侷限?

現在是不能夠在64位程序中呼叫32DLL並執行它的程式碼。這種不可行是因為64位系統的設計造成的。所以說是從根本上的不可能。沒有任何技術,也沒有任何文件沒有記錄的方式可以幫助到你。為了做到這個,你必須要裝載並初始化WoW64,更不用說核心結構的不同了。這代表著64位的處理器必須在執行中被處理為32位。這個話題在"Why can't you thunk between 32-bit and 64-bitWindows?".中有更為詳盡的描述。有一件事情是我建議可以嘗試的,就是建立一個使用COM技術建立一個替代程式,你可以閱讀"Accessing32-bit DLLs from 64-bit code".

但是,從32DLL 將資源匯入到64位程序中去,是比較容易的,你所需要的就是在呼叫LoadLibraryEx 的時候制定以下的flagLOAD_LIBRARY_AS_DATAFILE

逐漸放棄對32位程式的支援

微軟公司為了進一步促程序序向64位遷移,會逐漸在一些版本的Windows作業系統中取消對32位程式的支援。這是一個自然的過程。當然這個過程會比較緩慢,但這個行為已經開始了。

許多管理員可能會知道一個較新的作業系統上的伺服器安裝和操作模式,叫做Server Core這個模組正是在持久的“Windows VS Linux”大戰中被廣泛提起。其中一個支援使用Linux的原因就是Linux支援不需要影象介面就可以安裝伺服器操作。但是,現在Windows Server

也有了這種能力。如果你在這種模式中安裝系統,你將只獲得系統的命令列,而不需要使用者介面。

這種能力(Server Core安裝)出現在Windows Server 2008. 但是在 Windows Server2008 R2 中,另外一種創新出現使得系統更接近64位。在Windows Server 2008 R2 (Server Core )中,你可以啟動或者禁用系統對32位應用程式的支援。更重要的是對32位應用程式的支援預設是被禁用的。所以當你嘗試在Server Core mode中啟動32位程式的時候,你會得到一條系統訊息告訴你,這是不可以的。如果你需要額外手動啟用這種支援,可以通過以下命令實現:

start /w ocsetupServerCore-WOW64

在普通的模式(完全安裝),執行32位程式的支援預設是啟用的。

這種趨勢是十分明顯的,因而現在開始建立64位版本的應用是理智的,因為64位的程式能保證在更多的作業系統版本上使用。

額外資訊

Alexey PahunovRussian blog也是獲取WoW64資料的好地方。AlexeyMicrosoft 的員工,他參與了WoW64子系統的開發。

第三講將程式碼匯入64位系統的優缺點

你需要帶著以下的問題來學習64位系統:64位系統重新編譯專案的合理性有多少?回答這個問題,你需要花費一些時間和精力來思考。在一方面,你可能會因為要提供64位系統的應用支援,使得你在市場上落後於你的對手。在另一方面,你可能會花費了時間在開發64位系統應用上,而這一努力並不能給你帶來競爭優勢。

以下是一些建議可以用來幫助你做出選擇。

應用的生命期

當你的應用有一個比較短的生命期,你暫時還沒有必要開發應用的64位版本。WoW64子系統使得陳舊的32位應用在64位機上也能取得比較好的表現。如果你在兩年內會停止運營你的產品,你是不需要現在建立一個64位版本的。實踐證明向64位系統的遷移是一個非常緩慢平和的過程。可能你的大多數使用者在未來的一段時間裡還是會僅僅使用你係統的32位版本。你需要知道,本教程是在2009年編寫的,這時候大部分使用者都還是在使用32位系統。但是很快32位程式,就會變得越來越不自然,會變得落伍的。

如果你的專案有一比較長的開發和維護時間,你需要開始建立你產品的64位版本。當然你可以慢慢來,但是你要記住的是,越遲擁有產品的64位版本,在64位系統上維護32 位版本所帶來的問題將越來越多。

程式效能要求

當一個程式重新編譯以適應64位版本後,程式可以應用大量的記憶體資源,它的速度將提高5%-15%5%-10%的系統提升是因為64位體系結構的特點,如更多的暫存器,所導致的。另外的1%-5%的效能提升是因為拋棄了翻譯32位應用使之在64位系統環境執行的WoW64層所帶來。

例如,Adobe公司稱新版本64位的"Photoshop CS4"32位版本的快了12%

需要大量的記憶體的應用可以期待著有更高的效能提升。比如說,影象編輯器,CAD系統,GSI CAD,資料庫和其他的模型包。能將所有的資料儲存在記憶體中,而避免了多餘的從硬碟中匯入的工作,使得這些應用的速度,可能不是提升了幾個百分點,而是成倍的提高。

例如,Alfa-Bank 曾經在他們的IT 基礎設施中使用了基於Itanium 2的平臺。原因在於他們業務的發展使得現有系統無法支援不斷增長的資料量。每個使用者的服務延遲變得非常嚴重。分析顯示,系統的瓶頸不在於處理器的表現,而在於32位體系結構與記憶體子系統的關係上,因為32位體系結構使得只能使用4 Gbyte的伺服器地址空間。而它們的資料庫卻大於9 Gbyte。因而導致了子系統的輸入輸出的臨界負荷。Alfa-Bank決定購買一個由2個伺服器組成的叢集。這兩個伺服器都擁有4處理器、是基於Itanium 2的、擁有12Gbyte記憶體的。這個決定使得他們的效能要求達到了可以容忍的程度。這個公司的代表稱,引入基於Itanium2 的伺服器使得他們解決了重要問題,同時也節約了花費。

在專案中使用第三方庫

在決定是否開發你產品的64位版本前,請先確認你所依賴的第三方庫是否有64位版本。你需要找出第三方軟體64位版本的定價是多少。這些你都可以在庫開發者的網站上找到。如果,沒有依賴庫的64位版本的支援,可以尋找其他支援64位的庫作為替代。

你所開發的庫的第三方開發者

如果你在開發庫,元件,或者其他需要給第三方開發者使用的程式時,你需要儘快的開發一個你的庫的64位版本。否則需要64位支援的你的客戶會轉向其它的替代產品。例如,一些軟體和硬體安全方面的開發者,都非常遲的開發64位版本,使得他們的一些客戶轉向了其他工具來保護自己的產品。

釋出你所開發庫的64位版本有另一個好處,你可以把它作為一個單獨模組來出售。因而想要開發32 位和64位的客戶會要購買2個不同的授權。例如Spatial Corporation,就是按這個方式來賣他們的Spatial ACIS庫的。

16位應用

如果你的應用仍然有16位的模組,你需要丟棄它們。64位的Windows版本完全不支援16位的應用。

關於使用16位安裝程式的人員,我需要解釋一個事情。這樣的安裝程式仍然在被使用於安裝一些32位應用程式。因為對於一些比較流行的16位的安裝程式,它們之中包含了一些機制,使得它們能夠在執行中被更新的32位安裝程式。這可能使得你覺得16位的程式,在64位的系統環境中仍能使用,但這是錯誤的,請牢記。

彙編器程式碼

不要忘記了,大量的彙編器程式碼片是使得建立應用的64位版本更為困難的原因之一。

工具箱

如果考慮以上提到各種因素後,你決定建立一個你的應用的64位版本,成功不是一定的。你還需要一些必要的工具,以下就是一些你可能會碰到的不愉快的事情。

首先最令人不開心的事情,就是缺少64位的編譯器。當我們寫本教程的時候(2009),Embarcadero還沒有64C++編譯器,它有期望在2009年年底釋出一個。除非你重新編寫你自己的部署部分,如使用Microsoft Visual Studio

相關推薦

3264程式設計注意事項總結

----------------------------------------------------------------------------------

linux驅動編寫3264設備註意事項

  Linux 64 位體系結構     不幸的是,C 程式語言並沒有提供一種機制來新增新的基本資料型別。因此,提供 64 位的定址和整數運算能力必須要修改現有資料型別的繫結或對映,或者向 C 語言中新增新的資料型別。     表 1. 32 位和 64 位資料模型 ILP32 LP64 LLP64

3264作業系統以及CPU的關係

32位和64位的區別:  從硬體看,  1、目前32位和64位是指CPU的通用暫存器位寬(資料匯流排的位寬),所以64位的CPU資料處理位寬是32位CPU的2倍;  2、可定址範圍擴充套件,32位系統支援最大記憶體位4G(地址匯流排位寬已經是32位),64位系

nasm 彙編輸出 helloworld-windows 3264測試通過

使用nasm彙編,然後用visual studio的link連線成exe 選安裝nasm與visual studio // hello.asm STD_OUTPUT_HANDLE equ -11 NULL equ 0 global GobleyGo

3264 CPU、編譯器、作業系統、應用程式、arm和X86關係

一:arm和X86的區別 arm:對應精簡指令集 X86:對應複雜指令集 arm上的和X86上編譯過的的東西是不能相互使用的,因為指令集不一樣嘛。指令集可以通俗的理解為,溝通語言。arm和X86之間東西不能直接用,類似於一個美國人和一箇中國人各自只說自己的語言,那麼這兩個人是沒法溝通的。

32 64 區別 : CPU 作業系統 應用程式

https://www.cnblogs.com/mlgjb/p/8385658.html   原文連結 1.64位CPU與32位CPU 這兩者的指令集合、運算元位數、暫存器名稱和個數等等都不相同。 一、比如一條mov eax,1指令,可能在32bCPU上

關於VS中區分debugrelease,3264編譯的巨集定義

在vs程式設計中,常常涉及到32位和64位程式的編譯,怎麼判斷當前編譯是32位編譯還是64位編譯?如何判斷 是debug下編譯還是release下編譯?因為之前用到,這裡記錄一下,省的忘了又要瘋狂的google。 1.判斷是debug編譯還是release編譯。 如

關於程式碼中區分debugrelease、3264、xp還是win7編譯的巨集定義

在寫程式碼的過程中,我們經常需要考慮這樣的一些問題:有一部分程式碼片段只有在32位編譯環境下編譯才能通過,在64位編譯環境下是無法編譯通過的,那麼怎樣才能判斷當前編譯環境是32位編譯還是64位編譯?還有,如何判斷當前編譯是debug編譯還是release編譯?再者,有些AP

cocos2dx lua轉luac的問題(3264不相容問題)

兩種思路: 1、LuaJit 轉luac,生成的bytecode,是按照32位生成的。在64位的機器上是不支援的。(新版本的LuaJit 已經支援了64位。可更新新版本的LuaJit, 用新版本LuaJit生成對應的luajit-mac) 2、原生的Lua5.1.4 生成

iOS開發3264的坑

  眾所周知,蘋果是從iPhone 5s開始對全線移動產品使用64位架構,那麼如果App需要相容32位和64位的機型,就需要注意它們之間的區別。   下面我們首先看看基本資料型別的區別: 32位編譯器 char :1個位元組 char*(即指標變數): 4個位元組(32位

linux 3264系統下資料型別長度的區別

近日在centos下用c寫東西,這個程式的服務端執行在64位的centos下,客戶端有可能是32機,也有可能是64位的。 為了保證資料傳輸的一致性制定了一套協議,用struct實現。為了保證輸出過程中,資料的完整性,特別針對系統的不同對struct裡變數的型別進行了優化。為了

32程序下調用64函數——進程32模式64模式切換

always imu tab 之間 pointer icm bool list ack 之前學習的32位進程中調用64位進程函數的知識整理一下,也就是32位模式與64位模式之間的切換。 相關博客:http://www.cnblogs.com/lanrenxinxin/p/4

3264機數據大小

spa 數據大小 存儲 器) api 編譯器 itl 根據 程序員 32位機與64位機數據大小32位編譯器: char :1個字節 char*(即指針變量): 4個字節(32位的尋址空間是2^32, 即32個bit,也就是4個字節。同理64位編譯器)

32系統64系統對內存的支持

windows系統 筆者最早用的筆記本是HP CQ45-M02TU,內存僅2G(DDR3_1333MHZ),安裝的WIN7_32位操作系統。最近它運行緩慢,通過升級內存提升性能。網購了一條2G同頻內存,安裝後啟動系統,按鍵WIN+PauseBreak,內存顯示為4G,可用內存僅為2.66G,另外1

64平臺C/C++開發注意事項(轉載)

Lesson 01. What 64-bit systems are.Lesson 02. Support of 32-bit applications.Lesson 03. Porting code to 64-bit systems. The pros and cons.Lesson 04.

163264程式設計各資料型別佔的位元組數

全文參考:平安,幸福美滿! 的日誌,網址http://blog.163.com/hbu_lijian/blog/static/126129153201212892143856/ 16位  1位元組8位,2位元組16位  4位元組32位  8位元組64位 char  1位元組

32作業系統64作業系統的區別

//.......................................................................... 在Win7下:32位系統和64位系統的區別有:

iOS armv7, armv7s, arm64區別應用3264配置

轉載註明出處:https://www.jianshu.com/p/567d3b730608 iOS armv7, armv7s, arm64區別與應用32位、64位配置 歷程 2015年2月1日不允許不支援arm64的應用的提交; iOS10釋出後,如果你的應用中使用到了32

程式設計確定系統是32還是64

本文參考《深入理解計算機系統》 每臺計算機都有一個字長(word size)指明整數和指標資料的標稱大小(nominal size)。因為虛擬地址是以這樣的一個字來編碼的,所以字長決定的最重要的系統引數就是虛擬地址空間的最大大小。也就是說,對於一個字長位n的機

C++32系統64系統基本資料型別

32位與64位系統資料型別不同的平臺上對不同的資料型別分配的位元組數是不同的,一般的,資料型別的位元組數是由編輯器決定的(編譯期間決定資料型別長度)。簡單來說,平臺就是CPU+OS+Compiler,cpu的位是指一次性可處理的資料量是多少,1位元組=8位,32位處理器可以一