[百度空間] [轉]將程式移植到64位Windows

來源:互聯網
上載者:User

標籤:

from : http://goooder.bokee.com/2000373.html (雷立輝 整理)

簡介:本文對如何將32位Windows程式平滑的支援和過渡到64位Windows作業系統做出了一個簡單而系統的介紹。包括對於64位作業系統的版本,編程模型,一些移植原則甚至包括對驅動程式的移植原則的介紹。

作者介紹:系統分析員,現在在北京工作。作者的blog:http://goooder.blogchina.com.

前言:

或許大家還對32位的CPU及作業系統使用還是覺得非常的合乎日常需要,但Windows 64位已經悄悄的來到了各位的身邊。不少軟體廠商也紛紛宣稱自己的軟體已經支援64位作業系統了。

筆者在幾個月之前就成功的實施了一個軟體的64位作業系統移植。大致方案是,上層應用程式仍然使用32位程式,但將該系統軟體的驅動程式統統的變成了64位。這也是讓應用程式支援64位的最小代價。整個過程前後不到一個月(兩個人月),就解決了大部分問題。而一些難啃的骨頭都是因為以前的編碼不太規範而引起的。因為這不是本文的主題,所以就此打住。

下面的內容就是我在工作過程中整理各種資料所得到的成果。為了文章的系統性,中間轉貼了一些MSDN中文網站的內容。希望能對大家的工作有所協助。

一.最有可能受益於64位的應用

l 需要大量的可定址記憶體,因而系統總體記憶體需求超過4GB 的應用。例如那些採用大型資料集的應用(金融和科學建模軟體)和基於主機的案頭應用(在不降低效能的情況下同時運行多個線程);

l 必須同時管理大量的使用者或者應用線程,例如大規模的瘦用戶端解決方案,大型資料庫,以及用於客戶關係管理(CRM)、供應鏈管理(SCM)、企業資源規劃(ERP)和數位版權管理(DRM)系統中的解決方案的資料倉儲應用;

l 需要通過即時加密和解密提高安全性的應用,包括電子商務應用和對專用或者分類資料的保護;

l 需要數學精度和浮點效能的應用,包括建模、類比、統計和金融分析、映像/視頻/訊號處理、物理、醫學研究、遠程通訊、加密和壓縮;

l 需要大規模的、強大的資料庫效能的應用,包括決策支援,搜尋和索引,文檔和內容管理,以及語音辨識;

l 需要64 位元計算的大記憶體定址功能的應用,包括很多Alibaba Cloud HPC群集應用;

l 需要提供數字內容建立功能,例如電腦輔助設計、製造和工程(CAD、CAM 和CAE)、數字音樂創作和視頻編輯,以及即時媒體流解決方案;

l 需要通過最大限度的效能實現逼真的影院級消費者體驗,包括電腦遊戲、數位視訊和協作;

l 需要將以前只限於64 位元工作站的功能移植到企業、消費者和電腦愛好者的台式機中,包括3D 建模、渲染、動畫、類比和軟體開發。

二.Windows XP的64位版分類

微軟在2003年3月28日發布了64位的Windows XP。64位的Windows XP稱Windows XP 64-Bit Edition。其實就是64位版本的Windows XP Professional。根據不同的微處理器架構,它分為兩個不同版本:

1.IA-64版的Windows XP

針對英特爾(Intel)的IA-64架構的安騰2(Itanium2)純64位微處理器的Windows XP 64-Bit Edition Version 2003 for Itanium-based Systems。它是擁有64位定址能力的強大的作業系統,主要面向頂級的高端IA-64架構的工作站,用在高端的科學運算,石油探測工藝,立體繪圖,複雜的動畫製作等等,是一種用在高效能運算(High Performance Computing)的強大的作業系統。估計它可能會改名為Windows XP Professional Itanium-based Edition。支援雙處理器;最低支援1GB的記憶體,最高支援16GB的記憶體。

2.x64版的Windows XP

針對超微(AMD)的x64架構的皓龍(Opteron)與速龍64(Athlon64)所屬的64位擴充微處理器的Windows XP 64-Bit Edition for 64-Bit Extended Systems。由於英特爾也發布了x64架構的Intel EM64T技術的至強(Xeon)與奔騰4(Pentium 4)的64位擴充微處理器,故微軟將該版本的的Windows XP 64-Bit Edition改為Windows XP Professional x64 Edition,它支援AMD與Intel的x64架構。可以使用在一般x64架構的工作站,案頭電腦以及膝上型電腦,用途與32位Windows XP Professional一樣,但具有64位定址能力。支援雙處理器;最低支援256MB的記憶體,最高支援16GB的記憶體。

 

Windows XP Professional x64 Edition與32位版本很相像

三.x64版的Windows作業系統的設計目標

x64版有5大特徵,即:

1. 同時輕鬆支援32位Win32程式及64位程式;

2. 在64位啟動並執行程式碼和32位啟動並執行程式應該是同一份代碼;

3. 使現有程式具有企業級應用效能;(Enable existing applications to scale to enterprise capacities)

4. 支援新的設計使之可以利用巨大地址空間及記憶體空間;

5. 支援32位既有程式。

 

x64 位元平台並沒有出現 Win64 API,它仍然是熟悉的 Win32 API(現在更合適的名稱為 Windows API)。但它出現了一些新的相容 64 位元的資料類型,所以可能需要對代碼進行少量的更改。這就意味著開發人員可以從單個程式碼程式庫構建代碼的 32 位和 64 位元版本,減少了由於維護兩個程式碼程式庫所帶來的維護開銷。

 

但是,在x64中,Microsoft 已經去除了一些舊的組件,如 Win16 子系統。所以Windows 64 位元代碼不支援16 位的Windows程式。也不支援 POSIX 和 OS/2 子系統。又出現了一個新的子系統,稱為 WOW64。

四.x64新出現的子系統―WOW64

WOW64 是 Windows-32-on-Windows-64 的縮寫。它為現有的 32 位應用程式提供了 32 位的類比環境,可以使大多數 32 位應用程式在無需修改而直接運行在 Windows 64 位元版本上。它類似於舊的 WOW32 子系統,負責在 Windows 32 位版本下運行 16 位的代碼。

 

 

儘管x64 CPU本身具有 32 位相容模式,可以處理 IA-32 指令的實際執行,但WOW 層仍然必不可少。WOW子系統負責諸如在32位和64位元模式之間進程切換以及類比32位系統的服務。例如,32位和64 位元程式具有不同的註冊表登錄區,還有一個用於 32 位二進位檔案的不同的系統目錄,而且64位二進位檔案仍然使用 System32 目錄。因此,當 32 位應用程式安裝到系統中時,WOW層會確保將32位二進位檔案置於一個新的目錄 SysWOW64中。這是通過如下方式實現的:根據應用程式是否運行在 WOW 下,截獲對 API 的調用(如 GetSystemDirectory)並返回適當的目錄。類似的問題可能會存在於註冊表中。因為 32 位和 64 位元的 COM 伺服器都可以安裝在系統上,並位於相同的類別識別項 (CLSID) 下,因此 WOW 層需要將對註冊表的調用重新導向到適當的32位或64位登錄區中。WOW 層也會處理註冊表中某些地區之間的鏡像更改,以便使其更簡單地支援32位和64位代碼之間的互動操作。

WOW64 非常重要,因為當不關注效能和延展性的問題時,它使開發人員可以利用大多數現有的32位代碼。它是兩種方法的最佳結合。開發人員可以將應用程式服務遷移到64位,同時將 Microsoft 管理主控台 (MMC) 組態管理單元保留為32位。Windows 64 位元版本包括 MMC的32位和64位的版本。當選擇保留管理工具為32位時,進程間的通訊可能會遇到某些問題,但是只要介面設計正確,諸如遠端程序呼叫 (RPC) 的協議應該可以在32位和64位進程之間運行。有關 WOW64 的另外一點需要牢記:它並不是為要求高效能的應用程式而設計的。至少,WOW64子系統需要將32位參數擴充到64位,並且需要將64位的傳回值截斷為32位。在最糟糕的情況下,WOW64 子系統將需要進行核心調用,涉及到的不僅僅是到核心的轉換,還有從處理器的32位相容模式到其本機64位元模式的轉換。在 WOW64 下運行時,應用程式將無法妥當地進行調整。對於那些要將其保留為32位的應用程式而言,必須在WOW64下測試它們。如果效能不能滿足期望,則需要考慮將應用程式遷移到64位。

WOW64是在使用者模式下實現的,作為ntdll.dll和核心之間的層。WOW64及其支援的一些 DLL僅僅是可以載入到32位進程中的64位的 DLL。對於所有其他情況,進程保持為純進程。32位的進程無法載入64位的DLL,反之亦然。所以,請檢查代碼中的所有“LoadLibrary”調用是否有效。

有關 WOW64 的詳細資料,請參閱 Microsoft_ Platform SDK 中的“64-bit Windows Programming - Running 32-bit Applications”。

五.64位windows記憶體位址空間映射

預設情況下,Windows 32位版本的地址空間限制在4GB,其中一半是為核心保留的。這限制了普通的應用程式只能使用2GB的有效虛擬記憶體。2 GB看起來好像很多,但是由於錯誤的分配演算法、大型檔案對應甚至過多的使用 DLL,地址空間很容易在應用程式中變得零碎。看一下工作管理員中的“VM Size”列,就會發現普通應用程式消耗的虛擬記憶體量。當然,就想過去的 DOS 時期(利用 XMS/EMS)一樣,有很多種方法可以使 32 位的應用程式訪問多於 4 GB 的實體記憶體。進入實體位址延伸 (PAE) 和地址視窗擴充(Address Windowing Extensions,AWE)。PAE 通過將地址位的數量從 32 擴充到 36 來工作,這樣使應用程式可以定址的空間達到 64 GB。AWE 使應用程式可以將大於 4 GB 的實體記憶體範圍映射到虛擬位址空間中。這兩種方法都引入了開銷並增加了代碼的複雜性。

Windows 64 位元版本提供 16 TB 的有效定址空間,其中一半可用於使用者模式的應用程式。這意味著整個資料庫可以移動到記憶體中,顯著地提高了效能,或者整個網站可以緩衝到記憶體中。它還可以使代碼保留並委託到巨型的鄰近虛擬記憶體塊中,無需實際地擔心虛擬記憶體片段問題。這也考慮到了巨型檔案對應物件或共用的記憶體部分。

下面是64 位元體繫結構和 32 位體繫結構的比較表格:

下面是Windows系列記憶體位址空間分配比較:

...

 

六.Windows 64 位元版本的 C/C++ 編程
1.64位編碼指導原則

Windows 64 位元版本使用 LLP64 資料模型。這意味著標準 C 類型 int 和 long 保持為 32 位整數。資料類型 size_t 將映射到處理器詞大小(IA32 為 32 位,IA64 為 64 位元),並且 __int64 是 64 位元整數。在協助遷移 32 位代碼時就會完成上述操作。意義在於您可以對應用程式的 32 位版本和 64 版本使用相同的程式碼程式庫。

還有一個稱為 LP64 的資料模型,它將標準的 C 類型 long 映射到 64 位元整數,並使 int 保持為 32 位的整數。這種資料模型常見於 Unix 平台,但從單個程式碼程式庫同時建立應用程式的 32 位和 64 位元版本時可能有一些困難。您可能注意到了此處的常見主題。32 位平台與 64 位元平台的思想就是應該能夠從單個程式碼程式庫中構建兩個版本的應用程式。如果無法做到,那麼您可能要重新審視您的設計。具有單個程式碼程式庫就是巨大的勝利,尤其是如果您計劃發行兩個版本。

綜合以上考慮,建議如下:

 

使用Windows64位或32位安全資料類型;

檢查所有的指標運算及使用指標的地方;

改寫所有嵌入的彙編代碼;使用intrinsics或者native assembly code;

對於X64相關代碼使用 #if defined (_AMD64__) 的先行編譯命令(沒有定義__IA64__宏);

對於IA64相關的代碼使用#if defined (__IA64__)命令;

編譯x64程式使用AMD64處理器;

 

 

 

用 Visual C++ 建立在 64 位元 Windows 作業系統中啟動並執行應用程式時,應注意以下問題:

 

在 64 位元 Windows 作業系統中,int 和 long 是 32 位值。

在 64 位元 Windows 作業系統中,size_t、time_t 和 ptrdiff_t 是 64 位元值。

在 32 位 Windows 作業系統中,time_t 是 32 位值。

應注意代碼在哪裡採用 int 值和將其作為 size_t 值或 time_t 值處理。數字有可能增長得比 32 位元大,並且資料在被傳遞迴 int 儲存時有可能被截斷。

%x(十六進位 int 格式)printf 修飾符在 64 位元 Windows 作業系統中不按預期的那樣工作;它只對傳遞給它的值的前 32 位進行操作。

Windows 32 位作業系統使用 %I32x 顯示整數。

Windows 64 位元作業系統使用 %I64x 顯示整數。

%p(指標的十六進位格式)在 64 位元 Windows 作業系統中按預期的那樣工作。

2./WP64:使編譯器警告您潛在的問題

Microsoft_ Visual C 和 Microsoft_ Visual C++_ .NET 2002 編譯器添加了 /WP64 開關,這使您可以測試 32 位代碼的 64 位元相容性問題。編譯器將發出有關指標截斷和不正確轉換的警告。將 32 位應用程式遷移到 Windows 64 位元版本中前面的一個步驟就是開啟這個標記,然後就像通常編譯代碼那樣來編譯您的代碼。第一次會有幾個錯誤。例如,請看下面這個程式碼片段:

 

 

 

 

DWORD i = 0;

size_t x = 100;

 

i = x; // C4267: warning C4267: ‘=‘ : conversion from

// ‘size_t‘ to ‘DWORD‘, possible loss of data.

 

在 32 位的平台上,這段代碼能夠很好的進行編譯,因為 size_t 是 32 位的,但是在 64 位元的平台上,size_t 就是 64 位元的整數。啟用 /WP64 後,編譯器將會警告您類似的情況。

其他樣本:

 

 

 

void func(DWORD context)

{

char* sz = (char*)context; // C4312: warning C4312:

// ‘type cast‘ : conversion

// from ‘DWORD‘ to ‘char *‘ of

// greater size

// Do something with sz..

}

 

char* string = "the quick brown fox jumped over the lazy dog.";

 

func((DWORD)string); // C4311: warning C4311: ‘type cast‘ :

// pointer truncation from ‘char *‘

// to ‘DWORD‘

 

在修複這些錯誤後,請測試您的 32 位代碼。您希望確保 32 位的代碼繼續按預期那樣工作。32 位和 64 位元二進位檔案應該從相同的程式碼程式庫中構建。這就是編寫不斷前進的 Windows 應用程式的關鍵概念。開始時,您需要考慮 32 位和 64 位元的問題,並且為應用程式編寫可以運行在這兩個平台上的代碼。

3.多態類型

由於 Win32 API 是針對 C 的,在很多情況下,您都需要將整數轉換成指標或者相反。在 32 位的硬體上不會有問題,其中指標的大小和整數的大小是相同的,但在 64 位元的硬體上卻完全不一樣。這就是多態類型出現的原因。

對於特定的精度,您可以使用固定精度的資料類型。不管處理器的詞大小如何,它們的大小都是一致的。大多數這些類型都在它們的名稱中包含精度,可以從下面的表中看出:

 

 

此外,當您需要資料類型的精度隨著處理器詞大小變化時,請使用指標精度資料類型。這些類型又稱為“多態”資料類型。這些類型通常以 _PTR 尾碼結尾,如下面的表格所示:

 

 

 

通過整數參數傳遞參數或上下文資訊的所有 Win32 API 都更改為使用這些新的類型。SetWindowLong 和 SetWindowLongPtr 函數都是很好的樣本:

舊方法:

 

 

LONG SetWindowLong(

HWND hWnd,

int nIndex,

LONG dwNewLong);

 

新的多態方法:

 

 

LONG_PTR SetWindowLongPtr(

HWND hWnd,

int nIndex,

LONG_PTR dwNewLong);

 

請注意,該函數的 xxxPtr 版本使用新的多態類型。對於開發人員而言,通過在視窗的額外資料區域中儲存指標來儲存視窗的上下文資訊是相當常見的。使用 SetWindowLong 函數在 Windows 32 位版本上儲存指標的任何代碼必須更改為調用 SetWindowLongPtr。該更改非常簡單並且很快就可以完成,因為大多數更改要求使用多態類型。

另外,WindowProc 和 GetQueuedCompletionStatus 也是很好的樣本:

 

 

 

LRESULT CALLBACK WindowProc(

HWND hWnd,

UINT uiMsg,

WPARAM wParam,

LPARAM lParam);

 

BOOL GetQueuedCompletionStatus(

HANDLE hCompletionPort,

LPDWORD lpNumberOfBytes,

PULONG_PTR lpCompletionKey,

LPOVERLAPPED* lpOverlapped,

DWORD dwMilliseconds);

 

WindowProc 使用 LPARAM,後者是多態類型。GetQueuedCompletionStatus 使用 ULONG_PTR,後者也是多態類型。這使那些假設整數的大小與指標大小相同的現有代碼可以在進行很少修改的情況下繼續工作。

 

Microsoft_ Visual Studio_ .NET 2002 的編譯器包含兩個新的最佳化模式:Link Time Code Generation(LTCG,又稱 Whole Program Optimization)和 Profile Guided Optimization (PoGO)。代碼最佳化在 Itanium 處理器上比在 x86 平台上更為重要,因為編譯器對生產高效代碼負有全部責任。對於編譯器方面的知識,請參考MSDN中文網站http://www.microsoft.com/china/MSDN/library/windev/Windows2003/NFdnnetservws0364bitdev.mspx來獲得更多此方面的內容。

 

 

 

七.將驅動移植到64位Windows作業系統

 

x64位作業系統和x32位作業系統的最大區別就是記憶體定址方式的不同。而64位作業系統不支援32位的驅動程式,因為驅動程式和windows核心同處於一個地址空間中。這是移植32位驅動到64位驅動的最大原因。當然,64位驅動程式可以使用更大的分頁記憶體,非分頁式記憶體及系統緩衝。而且,你的裝置從此就支援64位windows作業系統了。

1.在X64下的驅動程式安裝

除了要把應用程式的32位驅動程式變成64位程式之外,驅動的安裝程式和其它設定檔同樣需要修改。也就是說,對於要在x64上啟動並執行32位程式,它所依賴的驅動仍然需要是64位的。這些相關程式包括inf檔案,device installers, class installers和co-installers。相關資料可查看MSDN Libarary DDK:Porting Your Driver to 64-Bit Windows。

所以,要改造應用程式的安裝程式。方法是,讓32位版的驅動安裝為預設安裝選項,即使用者插入安裝光碟片之後,依然運行32位安裝程式。但當程式調用UpdateDriverForPlugAndPlayDevices傳回值為ERROR_IN_WOW64時,這說明該安裝程式正運行在64位Windows環境中。此時,這個安裝程式應該調用CreateProcess函數來啟動64位的安裝進程。這個64位的安裝進程通過調用64位驅動目錄下的inf檔案進行驅動安裝。

2.驅動要支援32位IOCTL

某些IOCTL可能包含含有指標的結構,所以,要特別小心的區別對待它,必鬚根據被調用者解析結構或者輸出結構。

有三種辦法可以解決這個問題:

1. 盡量避免使用IOCTL傳遞包含有指標的結構;

2. 通過API IoIs32bitProcess()來判斷上層調用者的程式類型;

3. 在64位程式中採用新的IOCTL命令;

例子:

IOCTL structure in header file

 

 

 

typedef struct _IOCTL_PARAMETERS {

PVOID Addr;

SIZE_T Length;

HANDLE Handle;

} IOCTL_PARAMETERS, *PIOCTL_PARAMETERS;

 

32-bit IOCTL structure

 

//

// This structure is defined

// inside the driver source code

//

typedef struct _IOCTL_PARAMETERS_32 {

VOID*POINTER_32 Addr;

INT32 Length;

VOID*POINTER_32 Handle;

} IOCTL_PARAMETERS_32, *PIOCTL_PARAMETERS_32;

 

 

 

32-Bit and 64-Bit IOCTL

 

#ifdef _WIN64

case IOCTL_REGISTER:

if (IoIs32bitProcess(Irp)) {
/* If this is a 32 bit process */ 
params32 = (PIOCTL_PARAMETERS_32)(Irp>AssociatedIrp.SystemBuffer);

if(irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(IOCTL_PARAMETERS_32)) {

status = STATUS_INVALID_PARAMETER;

} else {
LocalParam.Addr = params32->Addr;
LocalParam.Handle = params32->Handle; 
LocalParam.Length = params32->Length;

/* Handle the ioctl here */

status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(IOCTL_PARAMETERS);
}
} else { /* 64bit process IOCTL */

 

} else { /* 64bit process IOCTL */

params = (PIOCTL_PARAMETERS)
(Irp->AssociatedIrp.SystemBuffer);

if (irpSp->Parameters.DeviceIoControl.InputBufferLength
< sizeof(IOCTL_PARAMETERS)) {
status = STATUS_INVALID_PARAMETER;

} else { 
RtlCopyMemory(&LocalParam, params,
sizeof(IOCTL_PARAMETERS));

/* Handle the ioctl here */
status = STATUS_SUCCESS;
}
Irp->IoStatus.Information = sizeof(IOCTL_PARAMETERS);
}
break;

3.64-Bit INF 檔案要求

在Windows Server 2003SP1之後,64位驅動的安裝被提高了要求。這可以簡化使用者的操作及提高安全性。

Inf檔案中必須含有NTAmd64或者NTIA64之類的修飾符才行。具體做法是在[Manufacturer]和Models小節都需要添加此類的欄位。

 

 

[Manufacturer]

%mycompany% = MyCompanyModels

 

[MyCompanyModels]

%MyDev% = mydevInstall,mydevHwid

 

 

 

[Manufacturer]

%mycompany% = MyCompanyModels,NTx86,NTAmd64

 

[MyCompanyModels.NTx86]

%MyDev% = mydevInstallx86,mydevHwid

 

[MyCompanyModels. NTAmd64]

%MyDev% = mydevInstallAmd64,mydevHwid

 

 

如果只需要在WindowsX64系統上安裝,則只需要使用NTAmd64修飾符就可以了。更多請參考http://www.microsoft.com/whdc/driver/install/64INF_reqs.mspx。

4.編程中容易碰到的問題

1)指標的相關問題

如果原有項目的編程風格控制不嚴,指標類型混用,強制轉換使用過多等等可能對移植是一個巨大的考驗。另外,程式中存在結構之中根據具體資料類型來計算其它變數的位置此類的代碼也需要重新檢查。

 

使用指標的原則如下:

1. 不要將指標強制轉換為int, long, ULONG, DWORD等類型,而應該使用UINT_PTR和INT_PTR;

2. 使用PtrToUlong()和PtrToLong()來截斷指標;

3. 永遠不要將已經截斷的存貯在int或者ULONG中指標地址的重新合成一個新的指標地址;

4. 小心的計算緩衝區的大小,說不定緩衝區的長度比ULONG所能儲存的最大數都大!

5. 小心的調用那些傳出指標的函數;

 

對4可以舉個例子:比如說有兩個地址ptr2(高地址), ptr1(低地址),則len = ptr2 – ptr1 將有可能大於2的32次方。

2)結構的記憶體排列問題

在64位的作業系統上,結構的記憶體排列(structure alignment)也需要小心審查。記憶體排列的齊整有利於處理器的執行效率。如果開啟了一些編譯選項,為了對齊記憶體位址,編譯器可能會將某些位置填空。在移植過程中,對結構中的變數順序需要仔細檢查,特別是在同一個標頭檔中使用不同的pack選項。比如下面的代碼:

 

 

 

 

#pragma pack (1) /* 也可以使用編譯選項/Zp(結構成員對齊)*/

struct AlignSample {

ULONG size;

void *ptr;

};

struct AlignSample s;

void foo(void *p) {

*p = p; // 將會導致訪問異常

...

}

foo((PVOID)&s.ptr);

 

補救辦法就是使用宏UNALIGNED:

 

 

 

void foo(void *p) {

struct AlignSample s;

*(UNALIGNED void *)&s.ptr = p;

}

 

當然,更好的辦法就是首先將那些64位長度的資料類型變數放在結構的前端。

3)小心使用十六進位的常量,不帶正負號的整數

小心使用十六進位的常量,不帶正負號的整數等等。比如說下面的一些斷言在64位系統中是錯誤的:

 

 

 

 

~((UINT64)(PAGE_SIZE-1)) == (UINT64)~(PAGE_SIZE-1)

PAGE_SIZE = 0x1000UL // Unsigned Long - 32 bits

PAGE_SIZE - 1 = 0x00000fff

 

等式左邊:

 

 

// 無符號轉換

(UINT64)(PAGE_SIZE -1 ) = 0x0000000000000fff

~((UINT64)(PAGE_SIZE -1 ))= 0xfffffffffffff000

 

等式右邊:

 

 

~(PAGE_SIZE-1) = 0xfffff000
(UINT64)(~(PAGE_SIZE-1))=0x00000000fffff000

所以:

~((UINT64)(PAGE_SIZE-1))!= (UINT64)(~(PAGE_SIZE-1))

 

還有:

 

 

DWORD index = 0;

CHAR *p;

If (p[index – 1] == ‘0’)

 

上面的代碼將會在64位系統上出錯!因為在32位系統上

p[index-1] == p[0xffffffff] == p[-1]

這是對的。但在64位系統上:

p[index-1] == p[0x00000000ffffffff] != p[-1]

再如:

 

 

-1 != 0xFFFFFFFF

0xFFFFFFFF != invalid handle

 

DWORD總是32位,所以要尋找原有程式中所有用DWORD存貯指標的代碼。另外,別忘了使用 %I來列印指標地址,而且大於0x80000000的也未必是核心態地址了。

 

5.開發64位驅動的工具

64位的開發工具和32位的差不多,除了必須的Windows DDK 2003之外,Windbg,Driver Verifier等都是拿手的好工具。最後,下載一份最新的WHQL測試包進行WHQL測試也是值得推薦的。

目前,學會使用Windbg來調試64位使用者態和核心態程式的方法是尤為必要的。也可以購買支援64位的VC環境Visual Stdio 2005來進行64位程式開發。

[百度空間] [轉]將程式移植到64位Windows

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.