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)


相关文章
|
5月前
|
存储 开发者 Python
探索代码的奥秘:从变量到函数的编程之旅
【8月更文挑战第31天】本文将带你走进编程的世界,从基础的变量概念出发,逐步深入到复杂的函数设计。我们将通过实际的代码示例,探讨如何高效地组织和复用代码,以及在面对复杂问题时如何应用模块化思维来简化解决方案。无论你是初学者还是有经验的开发者,这篇文章都将为你提供新的视角和启发,帮助你更好地理解编程语言的内在逻辑和美学。
|
测试技术 编译器 C++
栈局部变量优化探究,意外发现了 vs 的一个 bug ?
栈局部变量优化探究,意外发现了 vs 的一个 bug ?
|
存储 编译器 C++
c++ 有趣的动态转换之 delete 崩溃探究兼谈基类虚析构的重要性
c++ 有趣的动态转换之 delete 崩溃探究兼谈基类虚析构的重要性
|
C语言
【c语言进阶】三分钟教会你终极套娃:指向函数指针数组的指针,让你真正理解如何解读一个变量的类型
【c语言进阶】三分钟教会你终极套娃:指向函数指针数组的指针,让你真正理解如何解读一个变量的类型
105 0
|
C语言 C++
初始C语言——梦启程的地方
选择语句 if语句 if 单分支 if 多分支 循环语句 while 循环 函数 数组 操作符 关键字 typedef static #define定义常量和宏 结构体 总结
80 0
初始C语言——梦启程的地方
|
存储 Java 编译器
【重学C/C++系列(四)】:函数体hack过程详解
首先来说下**什么是hack**? hack字面意思“**非法入侵**”,那么在C/C++中其实就是**使用反汇编查看C/C++代码对应的汇编代码**
【重学C/C++系列(四)】:函数体hack过程详解
|
C++
【纠结】全局变量啊!!!!!!
【纠结】全局变量啊!!!!!!
63 0
|
存储 C语言
【C语言程序设计】知识点汇总2——局部变量与全局变量、编译预处理
【C语言程序设计】知识点汇总2——局部变量与全局变量、编译预处理
138 0
|
存储 编译器 C++
C++模拟面试:宏、lambda、智能指针闲谈
C++模拟面试:宏、lambda、智能指针闲谈
222 0
C++模拟面试:宏、lambda、智能指针闲谈
|
编译器 C++
<C++>一篇文章搞懂类和对象中常函数和常对象的实质以及避免空指针访问的小妙招
<C++>一篇文章搞懂类和对象中常函数和常对象的实质以及避免空指针访问的小妙招
173 0