MASM32编程完善SysInfo遇到奇怪故障,真切感受全局变量和局部变量之别……

简介: MASM32编程完善SysInfo遇到奇怪故障,真切感受全局变量和局部变量之别……

SysInfo主要是通过WMI来获取系统信息的,但是WMI获取的操作系统信息中没有Windows操作系统是32位还是64位的内容,所以需要另外想办法编程获取,比较常见的方法是调用Windows API函数GetNativeSystemInfo()或IsWow64Process()。之前分别用MASM32和VC分别编写了调用GetNativeSystemInfo()的代码。

今天把32or64.asm中的相关代码移植到SysInfo中来显示,主要是把32or64.asm中的相关代码改为一个函数showOsType(),原来的一些全局变量相应改成函数内部的局部变量,代码如下:

g_szOsType                  db    "系统类型:", 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

showOsType proc
    LOCAL lpSI: dword
    LOCAL lpfnGetNativeSystemInfo: _LPFNGetNativeSystemInfo

    invoke editCatStr, OFFSET g_szOsType

    invoke GetModuleHandle, OFFSET g_szkernel32Dll
    .if    eax==NULL
        push OFFSET g_szFailGetModuleHandle 

    .else
        invoke GetProcAddress, eax, OFFSET g_szGetNativeSystemInfo
        .IF eax==NULL
            push   OFFSET g_szFailGetProcAddress ; for call editCatStr()
        .ELSE
            mov    lpfnGetNativeSystemInfo, eax 

            invoke lpfnGetNativeSystemInfo, ADDR lpSI                               

            lea    eax, lpSI
            movzx eax, (_SYSTEM_INFO ptr [eax]).wProcessorArchitecture
            .if (eax==PROCESSOR_ARCHITECTURE_IA64) || (eax==PROCESSOR_ARCHITECTURE_AMD64) || (eax==PROCESSOR_ARCHITECTURE_ARM64)
                push OFFSET g_sz64Bit
            .else
                push OFFSET g_sz32Bit
            .endif
        .ENDIF
    .endif

    call editCatStr ;invoke editCatStr, eax
    
    ret
showOsType endp

修改的程序汇编连接正常,运行时可以正常显示Windows操作系统类型是32位还是64位的,但显示完这行信息后停滞了一下,随后SysInfo窗口就没有任何提示地自动关闭了。

image.png

用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 _GetNativeSystemInfo
 
showOsType           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
;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss

    g_szOsType                  db    "系统类型:", 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

showOsType proc
    LOCAL lpSI: dword
    LOCAL lpfnGetNativeSystemInfo: _LPFNGetNativeSystemInfo

    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   lpfnGetNativeSystemInfo, eax

            invoke lpfnGetNativeSystemInfo, ADDR lpSI
                               
            lea   eax, 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   ; push OFFSET g_sz64Bit
            .else
                mov eax, OFFSET g_sz32Bit   ; push OFFSET g_sz32Bit
            .endif
        .ENDIF
    .endif

push eax
      invoke MessageBox, NULL, eax, OFFSET g_szOsType, MB_OK
pop eax
    ret
showOsType endp


main  proc
      invoke showOsType
      invoke MessageBox, NULL, eax, OFFSET g_szOsType, MB_OK
      invoke ExitProcess, NULL
 main endp
 
end main

代码汇编连接成功,运行时正常显示showOsType()中

invoke MessageBox, NULL, eax, OFFSET g_szOsType, MB_OK

image.png

然后就出现问题了:

E xception 000006BA . exception is non-continuable

image.png

main()函数中的

invoke MessageBox, NULL, eax, OFFSET g_szOsType, MB_OK

1.

并没有得到执行,显示出信息框来。

开始百思不得其解,后面重新研究了GetNativeSystemInfo的参数说明:

参数

[out] lpSystemInfo

指向接收信息的  SYSTEM_INFO 结构的指针。

我代码中传递GetNativeSystemInfo()的参数dword类型变量lpSI,其值没有初始化,而不是指向一个SYSTEM_INFO结构的地址(指针)。这样GetNativeSystemInfo函数返回的SYSTEM_INFO结构信息数据覆盖了函数返回信息数据,导致函数结束返回时跳到了错误的地址,引发异常。

原来如此,看来lpSI定义为全局变量没有出现问题纯属侥幸。写代码一定要看清楚函数原型和说明。

参考:

GetNativeSystemInfo 函数 (sysinfoapi.h)


相关文章
|
8天前
|
存储 程序员 开发者
《深入理解变量的生存期:揭开程序世界中的神秘面纱》
在编程中,变量的生存期是指变量从创建到销毁的过程。理解变量的生存期对于编写高质量、无错误的程序至关重要。本文将探讨局部变量、全局变量和静态局部变量的生存期特点及其对程序的影响,并提供管理变量生存期的最佳实践。
|
测试技术 编译器 C++
栈局部变量优化探究,意外发现了 vs 的一个 bug ?
栈局部变量优化探究,意外发现了 vs 的一个 bug ?
|
C++
【纠结】全局变量啊!!!!!!
【纠结】全局变量啊!!!!!!
56 0
|
存储 编译器 C++
C++模拟面试:宏、lambda、智能指针闲谈
C++模拟面试:宏、lambda、智能指针闲谈
210 0
C++模拟面试:宏、lambda、智能指针闲谈
|
自然语言处理 编译器
进入编译器后,一个函数经历了什么?
进入编译器后,一个函数经历了什么?
92 0
进入编译器后,一个函数经历了什么?
|
C语言 C++
c语言几个松散的地方(不足的地方,不严谨的地方,它容易出错的地方)。
c语言是面向过程的语言,是弱类型语言,c语言的源代码基本就是无数个函数的堆砌。即很多函数就组成c语言源代码了,也即它的源代码基本就是函数构成的。 C语言里面的test()和test(void)是不一样的。
980 0