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 STRUCTUNIONdwOemId DWORD ?STRUCTwProcessorArchitecture WORD ?wReserved WORD ?ENDSENDSdwPageSize 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==NULLmov eax, OFFSET g_szFailGetModuleHandle.elseinvoke GetProcAddress, eax, OFFSET g_szGetNativeSystemInfo.IF eax==NULLmov eax, OFFSET g_szFailGetProcAddress.ELSEmov g_lpfnGetNativeSystemInfo, eaxpush offset g_lpSIcall g_lpfnGetNativeSystemInfomov eax, g_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.elsemov eax, OFFSET g_sz32Bit.endif.ENDIF.endifinvoke MessageBox, NULL, eax, OFFSET g_szCaption, MB_OKinvoke 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 _GetNativeSystemInfogetCpuArcInfo 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 STRUCTUNIONdwOemId DWORD ?STRUCTwProcessorArchitecture WORD ?wReserved WORD ?ENDSENDSdwPageSize 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失败", 0if c_showMoreInfo eq 0g_sz32Bit db "32位",0g_sz64Bit db "64位",0
elseg_szPROCESSOR_ARCHITECTURE_INTEL db "x86", 0 ; equ 0g_szPROCESSOR_ARCHITECTURE_ARM db "ARM", 0 ; equ 5g_szPROCESSOR_ARCHITECTURE_IA64 db "IA64",0 ;equ 6,基于 Intel Itanium 的g_szPROCESSOR_ARCHITECTURE_AMD64 db "x64 (AMD 或 Intel)", 0; equ 9g_szPROCESSOR_ARCHITECTURE_ARM64 db "ARM64", 0 ;equ 12g_szPROCESSOR_ARCHITECTURE_UNKNOWN db "Unknown", 0 ;equ 0ffffh,未知体系结构。
endif ;c_showMoreInfog_lpfnGetNativeSystemInfo lpfnGetNativeSystemInfo ? ; dword ?
g_lpSI dword ? ; SYSTEM_INFO;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
.code
;sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
start:invoke 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 g_lpfnGetNativeSystemInfo, eax;push OFFSET g_lpSI;call g_lpfnGetNativeSystemInfoinvoke g_lpfnGetNativeSystemInfo, OFFSET g_lpSImov eax, OFFSET g_lpSI ; mov eax, g_lpSI will cause an exception!movzx eax, [eax+SYSTEM_INFO.wProcessorArchitecture] ;movzx eax, (SYSTEM_INFO ptr [eax]).wProcessorArchitectureinvoke getCpuArcInfo.ENDIF.endifinvoke MessageBox, NULL, eax, OFFSET g_szCaption, MB_OKinvoke ExitProcess, NULLgetCpuArcInfo 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.elsemov eax, OFFSET g_sz32Bit.endif
ELSE.if eax==PROCESSOR_ARCHITECTURE_INTELmov eax, OFFSET g_szPROCESSOR_ARCHITECTURE_INTEL.elseif eax==PROCESSOR_ARCHITECTURE_ARMmov eax, OFFSET g_szPROCESSOR_ARCHITECTURE_ARM.elseif eax==PROCESSOR_ARCHITECTURE_IA64mov eax, OFFSET g_szPROCESSOR_ARCHITECTURE_IA64.elseif eax==PROCESSOR_ARCHITECTURE_AMD64mov eax, OFFSET g_szPROCESSOR_ARCHITECTURE_AMD64.elseif eax==PROCESSOR_ARCHITECTURE_ARM64mov eax, OFFSET g_szPROCESSOR_ARCHITECTURE_ARM64.elsemov eax, OFFSET g_szPROCESSOR_ARCHITECTURE_UNKNOWN.endif
ENDIF ;c_showMoreInfo ret
getCpuArcInfo endpend 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编程访问结构体成员要注意的一点相关推荐
- C/C++ 中访问结构体成员的方法
先看例子: 1#include <stdio.h> 2void main(){ 3 typedef struct { 4 int int_field; 5 ...
- C语言中访问结构体成员时 点 . 和 箭头 - 的区别
点(.)是用于结构体变量访问成员,箭头(->)是用于结构体指针访问成员. 例如: #include <stdio.h>int main(void) {struct Smy {int ...
- C语言结构体变量 指针以及对结构体成员的访问
文章目录 结构体 结构体变量访问成员的方法 结构体指针变量访问成员的方法 结构体 struct AGE {int year;int month;int day; }; struct STUDENT { ...
- c语言结构体成员变量私有化,C语言中结构体变量私有化详解
C语言中结构体变量私有化详解 背景介绍 操作系统 : CentOS7.3.1611_x64 gcc版本 :4.8.5 什么是结构体? 在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚 ...
- Go的反射是如何获取结构体成员信息的?
前言 哈喽,大家好,今天这篇文章的目的主要是解答一位读者的疑问,涉及知识点是反射和结构体内存布局.我们先看一下读者的问题: img 我们通过两个问题来解决他的疑惑: 结构体在内存中是如何存储的 反射获 ...
- C语言:指针的偏移步长、结构体成员的偏移量、嵌套结构体成员的偏移量、结构体的内存对齐
文章目录 1 不同类型指针的偏移步长 2 结构体成员的偏移量 3 嵌套结构体成员的偏移量 4 结构体的内存对齐 4.1 内存对齐的原因与优点 4.2 结构体内存对齐的规则 4.3 结构体嵌套结构体时的 ...
- 结构体成员的引用方法
结构体成员变量的引用 结构体变量名.成员名 student.num=10010; "."是成员运算符,它在所有的运算符中优先级最高. 结构体指针:指向结构体变量的指针,一个结构体变 ...
- 宏定义来实现一个结构体成员相对于该结构体首地址的偏移量
#define my_offerset(type , exp) ((int)&(((type*)0)->exp))//因为是求结构体的成员内存偏移.结构体会定义一种新的数据类型 所以ty ...
- 结构体成员数组不定长如何实现
[目的] 定义一个结构体类,其中的成员变量数组长度不定,根据实例化的对象指定长度,所以想到用指针实现 [现状] 指针可以指向任意长度数组,但结构体类只分配指针本身4字节长度,所以无法扩展 1 /** ...
最新文章
- 为什么有些老板要注册很多家公司
- 8个必备的PHP功能开发
- CPU 有个禁区,内核权限也无法进入!
- linux下单节点oracle数据库间ogg搭建
- mvn 打包项目到eclipse
- 3.6 mkpasswd命令
- SpringBoot启动banner更改
- python导入模块报错_Python 导入上层目录模块报错
- LeetCode 98. 验证二叉搜索树 思考分析
- html服务器框架,一种类似http/html的分布式GUI程序设计框架
- 斐波那契数列 青蛙跳台阶 变态跳台阶
- C++学习之CodeBlocks安装与调试
- node.js用get方式获取网页中的链接
- Macbook pro笔记本键盘失灵了(u,i,o,j,k,l,k,m无效了)解决办法
- 对于 Redux 的理解
- python关键词提取_如何从Python格式字符串中提取关键字? - python
- 喜欢的数字:使用一个字典来_数字证书:何时何地使用它们
- 我靠这个数据分析利器,3年当上运营主管
- 安装自己写的插件时,报插件版本过高,请升级JAR包或者安装低版本插件的问题
- 解决git 命令出现end问题