MASM32编程访问结构体成员要注意的一点
Posted 紫郢剑侠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MASM32编程访问结构体成员要注意的一点相关的知识,希望对你有一定的参考价值。
今天继续用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 "64位",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 文件
运行结果如下:
以上是关于MASM32编程访问结构体成员要注意的一点的主要内容,如果未能解决你的问题,请参考以下文章