導航:首頁 > 源碼編譯 > vc編譯x64程序

vc編譯x64程序

發布時間:2025-08-12 06:50:00

A. 如何編譯64位dll程序,有幾種情況,在32位XP上用VC++6.0或者VS2010該怎麼編譯64位的dll。

在64位的操作系統上用vs軟體編譯的dll默認就是64位。
在32位XP上用VC++6.0編譯64位的dll,需要安裝sdk(最新版本是sdk2003),在開始菜單——sdk——open build environment window——windows server 2003 64-bit build environment——set win svr 2003 x64 build env進入命令行,從命令行調用msdev,將vc選項里的include和lib的第一個默認路徑設為sdk目錄下64位頭文件和庫的路徑,編譯出的dll似乎就是64位的了。這個是從網頁上看到的,沒實踐過。
在32位XP上使用vs2010就簡單多了,新建一個項目(解決方案),加入代碼,設置X64,編譯生成即可。

B. 如何在各個版本的VC及64位下使用CPUID指令

一、推薦使用__cpuid、__cpuidex等Intrinsics函數

在32位模式下,我們可以使用內嵌匯編來調用cpuid指令。但在64位模式下,VC編譯器不支持內嵌匯編。
於是微軟提供了Intrinsics函數——編譯器會將Intrinsics函數編譯為對應的機器指令,而且同時支持32位和64位。
例如CPUID指令的對應Intrinsics函數是——

[cpp] view plain
// http://msdn.microsoft.com/en-us/library/hskdteyh.aspx
void __cpuid(
int CPUInfo[4],
int InfoType
);

void __cpuidex(
int CPUInfo[4],
int InfoType,
int ECXValue
);

__cpuidex函數的InfoType參數是CPUID指令的eax參數,即功能ID。ECXValue參數是CPUID指令的ecx參數,即子功能ID。CPUInfo參數用於接收輸出的eax, ebx, ecx, edx這四個寄存器。
早期的CPUID功能只需要一個功能ID參數(eax),這時可以使用__cpuid函數。
後來CPUID的功能越來越強大,一個功能ID參數(eax)參數不夠用,於是加了一個子功能ID(ecx)參數,這時應該採用__cpuidex。

二、用條件編譯判斷VC編譯器對Intrinsics函數的支持性(_MSC_VER)

在__cpuid、__cpuidex等Intrinsics函數時,會遇到以下問題——
1.低版本的VC編譯器沒有intrin.h頭文件。【注】:只有VC2005(或更高)才擁有intrin.h,支持__cpuid。
2.低版本的VC編譯器不支持__cpuidex。【注】:只有VC2008的部分版本及VS2010(或更高)的intrin.h中才有__cpuidex。

這時可以使用條件編譯來判斷VC編譯器的版本。
_MSC_VER是微軟C/C++編譯器——cl.exe編譯代碼時預定義的一個宏,它的值表示cl的版本,它的類型是「int」。例如——
#if _MSC_VER >=1200 // VC++6.0以上
#if _MSC_VER >=1300 // VC2003以上
#if _MSC_VER >=1400 // VC2005以上
#if _MSC_VER >=1500 // VC2008以上
#if _MSC_VER >=1600 // VC2010以上

例如發現_MSC_VER大於等於1400時,我們可以#include <intrin.h>。然後再利用_MSC_VER進一步判斷__cpuid、__cpuidex的支持性。

三、用條件編譯判斷64位模式(_WIN64)

使用_WIN64這個預處理宏可用來判斷目標平台是不是64位。
雖然在編譯x64平台的程序時,編譯器會自動推導出_WIN64。但是Visual Studio的語法高亮不清楚這些,它有可能仍是按32位代碼來做語法高亮。所以,建議還是手動在項目的預處理宏中增加_WIN64。

四、32位下用內嵌匯編實現__cpuidex函數

在32位模式下,我們可以使用內嵌匯編來實現__cpuidex函數。代碼如下——

[cpp] view plain
void __cpuidex(INT32 CPUInfo[4], INT32 InfoType, INT32 ECXValue)
{
if (NULL==CPUInfo) return;
_asm{
// load. 讀取參數到寄存器
mov edi, CPUInfo; // 准備用edi定址CPUInfo
mov eax, InfoType;
mov ecx, ECXValue;
// CPUID
cpuid;
// save. 將寄存器保存到CPUInfo
mov [edi], eax;
mov [edi+4], ebx;
mov [edi+8], ecx;
mov [edi+12], edx;
}
}

五、全部代碼

全部代碼——

[cpp] view plain
#include <Windows.h>
#include <stdio.h>
#include <tchar.h>

#if _MSC_VER >=1400 // VC2005才支持intrin.h
#include <intrin.h> // 所有Intrinsics函數
#endif

char szBuf[64];
INT32 dwBuf[4];

#if defined(_WIN64)
// 64位下不支持內聯匯編. 應使用__cpuid、__cpuidex等Intrinsics函數。
#else
#if _MSC_VER < 1600 // VS2010. 據說VC2008 SP1之後才支持__cpuidex
void __cpuidex(INT32 CPUInfo[4], INT32 InfoType, INT32 ECXValue)
{
if (NULL==CPUInfo) return;
_asm{
// load. 讀取參數到寄存器
mov edi, CPUInfo; // 准備用edi定址CPUInfo
mov eax, InfoType;
mov ecx, ECXValue;
// CPUID
cpuid;
// save. 將寄存器保存到CPUInfo
mov [edi], eax;
mov [edi+4], ebx;
mov [edi+8], ecx;
mov [edi+12], edx;
}
}
#endif // #if _MSC_VER < 1600 // VS2010. 據說VC2008 SP1之後才支持__cpuidex

#if _MSC_VER < 1400 // VC2005才支持__cpuid
void __cpuid(INT32 CPUInfo[4], INT32 InfoType)
{
__cpuidex(CPUInfo, InfoType, 0);
}
#endif // #if _MSC_VER < 1400 // VC2005才支持__cpuid

#endif // #if defined(_WIN64)

// 取得CPU廠商(Vendor)
//
// result: 成功時返回字元串的長度(一般為12)。失敗時返回0。
// pvendor: 接收廠商信息的字元串緩沖區。至少為13位元組。
int cpu_getvendor(char* pvendor)
{
INT32 dwBuf[4];
if (NULL==pvendor) return 0;
// Function 0: Vendor-ID and Largest Standard Function
__cpuid(dwBuf, 0);
// save. 保存到pvendor
*(INT32*)&pvendor[0] = dwBuf[1]; // ebx: 前四個字元
*(INT32*)&pvendor[4] = dwBuf[3]; // edx: 中間四個字元
*(INT32*)&pvendor[8] = dwBuf[2]; // ecx: 最後四個字元
pvendor[12] = '\0';
return 12;
}

// 取得CPU商標(Brand)
//
// result: 成功時返回字元串的長度(一般為48)。失敗時返回0。
// pbrand: 接收商標信息的字元串緩沖區。至少為49位元組。
int cpu_getbrand(char* pbrand)
{
INT32 dwBuf[4];
if (NULL==pbrand) return 0;
// Function 0x80000000: Largest Extended Function Number
__cpuid(dwBuf, 0x80000000);
if (dwBuf[0] < 0x80000004) return 0;
// Function 80000002h,80000003h,80000004h: Processor Brand String
__cpuid((INT32*)&pbrand[0], 0x80000002); // 前16個字元
__cpuid((INT32*)&pbrand[16], 0x80000003); // 中間16個字元
__cpuid((INT32*)&pbrand[32], 0x80000004); // 最後16個字元
pbrand[48] = '\0';
return 48;
}

int _tmain(int argc, _TCHAR* argv[])
{
//__cpuidex(dwBuf, 0,0);
//__cpuid(dwBuf, 0);
//printf("%.8X\t%.8X\t%.8X\t%.8X\n", dwBuf[0],dwBuf[1],dwBuf[2],dwBuf[3]);

cpu_getvendor(szBuf);
printf("CPU Vendor:\t%s\n", szBuf);

cpu_getbrand(szBuf);
printf("CPU Name:\t%s\n", szBuf);

return 0;
}

六、兼容性說明

VC編譯器對32/64位的支持性——
32位:VC6是最早支持編譯32位Intrinsics函數的。
64位:VC2005是最早支持編譯64位Intrinsics函數的。

本文方法在32位編譯器下的兼容性——
__cpuid:兼容VC6(或更高)。
__cpuidex:兼容VC6(或更高)。

本文方法在64位編譯器下的兼容性——
__cpuid:兼容VC2005(或更高)。
__cpuidex:兼容VC2010(或更高)。

C. vc判斷是32位編譯還是64位編譯判斷是debug編譯還是release編譯

1.判斷是debug編譯還是release編譯。
如果_DEBUG定義了表示是debug編譯,否則是release編譯。

2.判斷是32位編譯還是64位編譯。
在 Win32 配置下,_WIN32 有定義,_WIN64 沒有定義。在 x64 配置下,兩者都有定義。即在 VC 下,_WIN32 一定有定義。
因此,WIN32/_WIN32 可以用來判斷是否 Windows 系統(對於跨平台程序),而 _WIN64 用來判斷編譯環境是 x86 還是 x64。附一個表:

常量\定義 預定義選項 Windows.h VC編譯器
WIN32 Win32 √(minwindef.h) ×
_WIN32 × × √
_WIN64 × × x64

最後附上根據相應編譯情況,進行有條件的鏈接相應靜態庫的示例代碼,其實就是一些宏定義語句的使用:

[cpp] view plain在CODE上查看代碼片派生到我的代碼片
#include "json/json.h"
#ifdef _DEBUG
#ifndef _WIN64
#pragma comment(lib,"json/json_mtd.lib")
#else
#pragma comment(lib,"json/json_mtd_x64.lib")
#endif
#else
#ifndef _WIN64
#pragma comment(lib,"json/json_mt.lib")
#else
#pragma comment(lib,"json/json_mt_x64.lib")
#endif
#endif
using namespace Json;

閱讀全文

與vc編譯x64程序相關的資料

熱點內容
自動化交易演算法 瀏覽:689
單片機編譯過程 瀏覽:375
空氣的壓縮率 瀏覽:431
android定製ui 瀏覽:965
魔獸世界任務命令 瀏覽:175
阿里程序員聖誕彩蛋 瀏覽:583
列印機打不了pdf文件 瀏覽:966
家用空調什麼壓縮機好 瀏覽:2
雲伺服器免費社區 瀏覽:378
圖片加密解密c語言 瀏覽:910
排序演算法的面試題 瀏覽:428
加密的密碼轉換 瀏覽:509
解壓失敗c盤還能用嗎 瀏覽:347
可以封裝app的影視網站源碼 瀏覽:607
cn2伺服器有什麼優化 瀏覽:175
電腦如何上ftp伺服器地址 瀏覽:39
單片機程序框架圖 瀏覽:277
輕加app減肥效果怎麼樣 瀏覽:794
懶懶app怎麼注銷 瀏覽:792
密目網計演算法規則 瀏覽:743