今天继续用MASM32编写调用Windows API函数GetNativeSystemInfo来检测Windows操作系统是32位还是64位的程序。
修改完善形成了下面的代码:
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ; 32or64.asm ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< .586 .model flat, stdcall option casemap:none include \masm32\include\windows.inc include \masm32\include\kernel32.inc includelib \masm32\lib\kernel32.lib include \masm32\include\user32.inc includelib \masm32\lib\user32.lib ;sssssssssssssssssssssssssssssssssssssss ;.const ;sssssssssssssssssssssssssssssssssssssss ;PROCESSOR_ARCHITECTURE_INTEL equ 0 ;x86 ;PROCESSOR_ARCHITECTURE_ARM equ 5 ;ARM ;PROCESSOR_ARCHITECTURE_IA64 equ 6 ;基于 Intel Itanium 的 ;PROCESSOR_ARCHITECTURE_AMD64 equ 9 ;x64 (AMD 或 Intel) PROCESSOR_ARCHITECTURE_ARM64 equ 12 ;ARM64 ;PROCESSOR_ARCHITECTURE_UNKNOWN equ 0ffffh ;未知体系结构。 _SYSTEM_INFO STRUCT UNION dwOemId DWORD ? STRUCT wProcessorArchitecture WORD ? wReserved WORD ? ENDS ENDS dwPageSize DWORD ? lpMinimumApplicationAddress DWORD ? lpMaximumApplicationAddress DWORD ? dwActiveProcessorMask DWORD ? dwNumberOfProcessors DWORD ? dwProcessorType DWORD ? dwAllocationGranularity DWORD ? wProcessorLevel WORD ? wProcessorRevision WORD ? _SYSTEM_INFO ENDS ;sssssssssssssssssssssssssssssssssssssss .data ;sssssssssssssssssssssssssssssssssssssss g_szCaption db "Windows",0 g_sz32Bit db "32位",0 g_sz64Bit db "64位",0 g_szGetNativeSystemInfo db "GetNativeSystemInfo", 0 g_szkernel32Dll db "kernel32.dll", 0 g_szFailGetModuleHandle db "GetModuleHandle失败", 0 g_szFailGetProcAddress db "GetProcAddress失败", 0 g_szFailGetNativeSystemInfo db "GetNativeSystemInfo失败", 0 g_lpfnGetNativeSystemInfo dword ? g_lpSI dword ? ; SYSTEM_INFO ;sssssssssssssssssssssssssssssssssssssss .code ;sssssssssssssssssssssssssssssssssssssss start: invoke GetModuleHandle, OFFSET g_szkernel32Dll .if eax==NULL mov eax, OFFSET g_szFailGetModuleHandle .else invoke GetProcAddress, eax, OFFSET g_szGetNativeSystemInfo .IF eax==NULL mov eax, OFFSET g_szFailGetProcAddress .ELSE mov g_lpfnGetNativeSystemInfo, eax push offset g_lpSI call g_lpfnGetNativeSystemInfo mov eax, g_lpSI movzx eax, (SYSTEM_INFO ptr [eax]).wProcessorArchitecture .if (eax==PROCESSOR_ARCHITECTURE_IA64) || (eax==PROCESSOR_ARCHITECTURE_AMD64) || (eax==PROCESSOR_ARCHITECTURE_ARM64) mov eax, OFFSET g_sz64Bit .else mov eax, OFFSET g_sz32Bit .endif .ENDIF .endif invoke MessageBox, NULL, eax, OFFSET g_szCaption, MB_OK invoke ExitProcess, NULL end start
代码顺利汇编和连接,生成了EXE,但运行时出错:
用OllDbg跟踪调试:
引发问题的代码是:
movzx eax, (SYSTEM_INFO ptr [eax]).wProcessorArchitecture
回溯起来问题出在上一行代码:
mov eax, g_lpSI
根源则在于汇编程序中的寻址方式,由于SYSTEM_INFO结构体的定义是公开透明的,我们可以手工算出成员的偏移地址来进行访问,但为了保证通用性和灵活性,一般我们是用基址+变址的方式来访问结构体成员的,把代码改成:
mov eax, offset g_lpSI
这样程序就能顺利运行并给出结果:
再进一步完善:
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ; FileName: CpuArch.asm ; Function: Show CPU Architecture with API GetNativeSystemInfo ; Author: PurpleEndurer ; DevEnv: Windows 7 Ultimate 64bit + MASM32 ; ; Log: ;--------------------------------------------------------------- ; 20221126 Created ; 20221127 Added c_showMoreInfo, getCpuArcInfo(), OK! ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< .586 .model flat, stdcall option casemap:none include \masm32\include\windows.inc include \masm32\include\kernel32.inc includelib \masm32\lib\kernel32.lib include \masm32\include\user32.inc includelib \masm32\lib\user32.lib ;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss ;proto ;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss _GetNativeSystemInfo TYPEDEF proto :DWORD lpfnGetNativeSystemInfo TYPEDEF Ptr _GetNativeSystemInfo getCpuArcInfo proto ;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss ;.const ;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss ;PROCESSOR_ARCHITECTURE_INTEL equ 0 ;x86 ;PROCESSOR_ARCHITECTURE_ARM equ 5 ;ARM ;PROCESSOR_ARCHITECTURE_IA64 equ 6 ;基于 Intel Itanium 的 ;PROCESSOR_ARCHITECTURE_AMD64 equ 9 ;x64 (AMD 或 Intel) PROCESSOR_ARCHITECTURE_ARM64 equ 12 ;ARM64 ;PROCESSOR_ARCHITECTURE_UNKNOWN equ 0ffffh ;未知体系结构。 c_showMoreInfo equ 1 _SYSTEM_INFO STRUCT UNION dwOemId DWORD ? STRUCT wProcessorArchitecture WORD ? wReserved WORD ? ENDS ENDS dwPageSize DWORD ? lpMinimumApplicationAddress DWORD ? lpMaximumApplicationAddress DWORD ? dwActiveProcessorMask DWORD ? dwNumberOfProcessors DWORD ? dwProcessorType DWORD ? dwAllocationGranularity DWORD ? wProcessorLevel WORD ? wProcessorRevision WORD ? _SYSTEM_INFO ENDS ;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss .data ;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss g_szCaption db "Windows",0 g_szGetNativeSystemInfo db "GetNativeSystemInfo", 0 g_szkernel32Dll db "kernel32.dll", 0 g_szFailGetModuleHandle db "GetModuleHandle失败", 0 g_szFailGetProcAddress db "GetProcAddress失败", 0 g_szFailGetNativeSystemInfo db "GetNativeSystemInfo失败", 0 if c_showMoreInfo eq 0 g_sz32Bit db "32位",0 g_sz64Bit db "32位",0 else g_szPROCESSOR_ARCHITECTURE_INTEL db "x86", 0 ; equ 0 g_szPROCESSOR_ARCHITECTURE_ARM db "ARM", 0 ; equ 5 g_szPROCESSOR_ARCHITECTURE_IA64 db "IA64",0 ;equ 6,基于 Intel Itanium 的 g_szPROCESSOR_ARCHITECTURE_AMD64 db "x64 (AMD 或 Intel)", 0; equ 9 g_szPROCESSOR_ARCHITECTURE_ARM64 db "ARM64", 0 ;equ 12 g_szPROCESSOR_ARCHITECTURE_UNKNOWN db "Unknown", 0 ;equ 0ffffh,未知体系结构。 endif ;c_showMoreInfo g_lpfnGetNativeSystemInfo lpfnGetNativeSystemInfo ? ; dword ? g_lpSI dword ? ; SYSTEM_INFO ;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss .code ;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss start: invoke GetModuleHandle, OFFSET g_szkernel32Dll .if eax==NULL mov eax, OFFSET g_szFailGetModuleHandle .else invoke GetProcAddress, eax, OFFSET g_szGetNativeSystemInfo .IF eax==NULL mov eax, OFFSET g_szFailGetProcAddress .ELSE mov g_lpfnGetNativeSystemInfo, eax ;push OFFSET g_lpSI ;call g_lpfnGetNativeSystemInfo invoke g_lpfnGetNativeSystemInfo, OFFSET g_lpSI mov eax, OFFSET g_lpSI ; mov eax, g_lpSI will cause an exception! movzx eax, [eax+SYSTEM_INFO.wProcessorArchitecture] ;movzx eax, (SYSTEM_INFO ptr [eax]).wProcessorArchitecture invoke getCpuArcInfo .ENDIF .endif invoke MessageBox, NULL, eax, OFFSET g_szCaption, MB_OK invoke ExitProcess, NULL getCpuArcInfo proc ; dwCpuArc: dword ; input : eax=CpuArchitecture ; Output: eax=offset address of Cpu Architecture infomation string IF c_showMoreInfo eq 0 .if (eax==PROCESSOR_ARCHITECTURE_IA64) || (eax==PROCESSOR_ARCHITECTURE_AMD64) || (eax==PROCESSOR_ARCHITECTURE_ARM64) mov eax, OFFSET g_sz64Bit .else mov eax, OFFSET g_sz32Bit .endif ELSE .if eax==PROCESSOR_ARCHITECTURE_INTEL mov eax, OFFSET g_szPROCESSOR_ARCHITECTURE_INTEL .elseif eax==PROCESSOR_ARCHITECTURE_ARM mov eax, OFFSET g_szPROCESSOR_ARCHITECTURE_ARM .elseif eax==PROCESSOR_ARCHITECTURE_IA64 mov eax, OFFSET g_szPROCESSOR_ARCHITECTURE_IA64 .elseif eax==PROCESSOR_ARCHITECTURE_AMD64 mov eax, OFFSET g_szPROCESSOR_ARCHITECTURE_AMD64 .elseif eax==PROCESSOR_ARCHITECTURE_ARM64 mov eax, OFFSET g_szPROCESSOR_ARCHITECTURE_ARM64 .else mov eax, OFFSET g_szPROCESSOR_ARCHITECTURE_UNKNOWN .endif ENDIF ;c_showMoreInfo ret getCpuArcInfo endp end start
程序运行结果:
如果用C++来完成,就没有这么折腾了,用Microsoft Visual Studio 2019来实现的代码如下:
// 32or64.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include "pch.h" #include "windows.h" #include <iostream> #include "sysinfoapi.h" int main() { SYSTEM_INFO si; int iCpuArc; GetNativeSystemInfo(&si); iCpuArc = si.wProcessorArchitecture; std::cout << "si.wProcessorArchitecture="; std::cout << iCpuArc; std::cout << "\nArchitecture:"; switch (iCpuArc) { case PROCESSOR_ARCHITECTURE_INTEL: std::cout << "x86\n"; break; case PROCESSOR_ARCHITECTURE_ARM: std::cout << "ARM\n"; break; case PROCESSOR_ARCHITECTURE_IA64: std::cout << "IA64\n"; break; case PROCESSOR_ARCHITECTURE_AMD64: std::cout << "x64 (AMD 或 Intel)\n"; break; case PROCESSOR_ARCHITECTURE_ARM64: std::cout << "ARM64\n"; break; default: std::cout << "UNKNOWN\n"; } } // 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单 // 调试程序: F5 或调试 >“开始调试”菜单 // 入门使用技巧: // 1. 使用解决方案资源管理器窗口添加/管理文件 // 2. 使用团队资源管理器窗口连接到源代码管理 // 3. 使用输出窗口查看生成输出和其他消息 // 4. 使用错误列表窗口查看错误 // 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目 // 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
运行结果如下: