SysInfo主要是通过WMI来获取系统信息的,但是WMI获取的操作系统信息中没有Windows操作系统是32位还是64位的内容,所以需要另外想办法编程获取,比较常见的方法是调用Windows API函数GetNativeSystemInfo()或IsWow64Process()。之前分别用MASM32和VC分别编写了调用GetNativeSystemInfo()的代码。详见:MASM32编程访问结构体成员要注意的一点https://blog.csdn.net/Purpleendurer/article/details/128063894?spm=1001.2014.3001.5501
今天把32or64.asm中的相关代码移植到SysInfo中来显示,主要是把32or64.asm中的相关代码改为一个函数showOsType(),原来的一些全局变量相应改成函数内部的局部变量,代码如下:
g_szOsType db "系统类型:", 0g_sz32Bit db "32位",0g_sz64Bit db "64位",0g_szGetNativeSystemInfo db "GetNativeSystemInfo", 0g_szkernel32Dll db "kernel32.dll", 0g_szFailGetModuleHandle db "GetModuleHandle失败", 0g_szFailGetProcAddress db "GetProcAddress失败", 0g_szFailGetNativeSystemInfo db "GetNativeSystemInfo失败", 0showOsType procLOCAL lpSI: dwordLOCAL lpfnGetNativeSystemInfo: _LPFNGetNativeSystemInfoinvoke editCatStr, OFFSET g_szOsTypeinvoke GetModuleHandle, OFFSET g_szkernel32Dll.if eax==NULLpush OFFSET g_szFailGetModuleHandle .elseinvoke GetProcAddress, eax, OFFSET g_szGetNativeSystemInfo.IF eax==NULLpush OFFSET g_szFailGetProcAddress ; for call editCatStr().ELSEmov lpfnGetNativeSystemInfo, eax invoke lpfnGetNativeSystemInfo, ADDR lpSI lea eax, lpSImovzx eax, (_SYSTEM_INFO ptr [eax]).wProcessorArchitecture.if (eax==PROCESSOR_ARCHITECTURE_IA64) || (eax==PROCESSOR_ARCHITECTURE_AMD64) || (eax==PROCESSOR_ARCHITECTURE_ARM64)push OFFSET g_sz64Bit.elsepush OFFSET g_sz32Bit.endif.ENDIF.endifcall editCatStr ;invoke editCatStr, eaxret
showOsType endp
修改的程序汇编连接正常,运行时可以正常显示Windows操作系统类型是32位还是64位的,但显示完这行信息后停滞了一下,随后SysInfo窗口就没有任何提示地自动关闭了。
用OllyDbg跟踪了代码运行情况,代码运行正常,可以获得正确的操作系统类型信息,但是在函数执行结束返回时出现了访问异常。
还是第一次遇到这种情况,为了弄清楚原因,把showOsType()代码拿出来单独测试,代码如下:
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; FileName: WinBit.asm
; Function: Show windows bit with API GetNativeSystemInfo
; Author: PurpleEndurer
; DevEnv: Windows 10 + MASM32
;
; Log:
;---------------------------------------------------------------
; 20221216 Created
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
.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 _GetNativeSystemInfoshowOsType 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 ;未知体系结构。;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
;.data
;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
.code
;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssg_szOsType db "系统类型:", 0g_sz32Bit db "32位",0g_sz64Bit db "64位",0g_szGetNativeSystemInfo db "GetNativeSystemInfo", 0g_szkernel32Dll db "kernel32.dll", 0g_szFailGetModuleHandle db "GetModuleHandle失败", 0g_szFailGetProcAddress db "GetProcAddress失败", 0g_szFailGetNativeSystemInfo db "GetNativeSystemInfo失败", 0showOsType procLOCAL lpSI: dwordLOCAL lpfnGetNativeSystemInfo: _LPFNGetNativeSystemInfoinvoke GetModuleHandle, OFFSET g_szkernel32Dll.if eax==NULLmov eax, OFFSET g_szFailGetModuleHandle .elseinvoke GetProcAddress, eax, OFFSET g_szGetNativeSystemInfo.IF eax==NULLmov eax, OFFSET g_szFailGetProcAddress.ELSEmov lpfnGetNativeSystemInfo, eaxinvoke lpfnGetNativeSystemInfo, ADDR lpSIlea eax, lpSImovzx eax, (SYSTEM_INFO ptr [eax]).wProcessorArchitecture.if (eax==PROCESSOR_ARCHITECTURE_IA64) || (eax==PROCESSOR_ARCHITECTURE_AMD64) || (eax==PROCESSOR_ARCHITECTURE_ARM64)mov eax, OFFSET g_sz64Bit ; push OFFSET g_sz64Bit.elsemov eax, OFFSET g_sz32Bit ; push OFFSET g_sz32Bit.endif.ENDIF.endifpush eaxinvoke MessageBox, NULL, eax, OFFSET g_szOsType, MB_OK
pop eaxret
showOsType endpmain procinvoke showOsTypeinvoke MessageBox, NULL, eax, OFFSET g_szOsType, MB_OKinvoke ExitProcess, NULLmain endpend main
代码汇编连接成功,运行时正常显示showOsType()中
invoke MessageBox, NULL, eax, OFFSET g_szOsType, MB_OK
显示的信息框:
然后就出现问题了:
E xception 000006BA . exception is non-continuable
main()函数中的
invoke MessageBox, NULL, eax, OFFSET g_szOsType, MB_OK
并没有得到执行,显示出信息框来。
开始百思不得其解,后面重新研究了GetNativeSystemInfo的参数说明:
参数
[out] lpSystemInfo
指向接收信息的 SYSTEM_INFO 结构的指针。
我代码中传递GetNativeSystemInfo()的参数dword类型变量lpSI,其值没有初始化,而不是指向一个SYSTEM_INFO结构的地址(指针)。这样GetNativeSystemInfo函数返回的SYSTEM_INFO结构信息数据覆盖了函数返回信息数据,导致函数结束返回时跳到了错误的地址,引发异常。
原来如此,看来lpSI定义为全局变量没有出现问题纯属侥幸。写代码一定要看清楚函数原型和说明。
参考: