如何在NASM x64汇编中调用带SYSTEM_INFO结构体的函数
解决NASM中Windows SYSTEM_INFO结构体定义与GetSystemInfo调用问题
问题背景
需要在x64 NASM汇编中使用Windows SYSTEM_INFO结构体并调用GetSystemInfo函数,但未正确定义结构体,导致调用时出现内存访问错误。目标结构体的C语言定义如下:
typedef struct _SYSTEM_INFO { union { DWORD dwOemId; struct { WORD wProcessorArchitecture; WORD wReserved; } DUMMYSTRUCTNAME; } DUMMYUNIONNAME; DWORD dwPageSize; LPVOID lpMinimumApplicationAddress; LPVOID lpMaximumApplicationAddress; DWORD_PTR dwActiveProcessorMask; DWORD dwNumberOfProcessors; DWORD dwProcessorType; DWORD dwAllocationGranularity; WORD wProcessorLevel; WORD wProcessorRevision; } SYSTEM_INFO, *LPSYSTEM_INFO;
原代码中未定义sysinfo变量,调用GetSystemInfo时lea rcx, [sysinfo]指向无效地址,触发Windbg错误:
KERNELBASE!GetSystemInfoInternal+0xf: 00000000`006fdee7 410f1100 movups xmmword ptr [r8],xmm0 ds:ffffffff`ffffff78=????????????????????????????????
解决方案
1. 用NASM语法定义SYSTEM_INFO结构体
NASM通过struc/endstruc定义结构体,union通过共享内存偏移实现,同时要保证x64平台的内存对齐:
; 定义SYSTEM_INFO结构体,适配x64平台 struc SYSTEM_INFO ; 顶层union DUMMYUNIONNAME .DUMMYUNIONNAME: .dwOemId resd 1 ; DWORD(4字节) .DUMMYSTRUCTNAME: .wProcessorArchitecture resw 1 ; WORD(2字节) .wReserved resw 1 ; WORD(2字节) align 4 ; 保证union后续成员对齐到DWORD边界 ; 结构体其他成员 .dwPageSize resd 1 .lpMinimumApplicationAddress resq 1 ; LPVOID在x64为8字节 .lpMaximumApplicationAddress resq 1 .dwActiveProcessorMask resq 1 ; DWORD_PTR在x64为8字节 .dwNumberOfProcessors resd 1 .dwProcessorType resd 1 .dwAllocationGranularity resd 1 .wProcessorLevel resw 1 .wProcessorRevision resw 1 align 8 ; x64结构体默认对齐到8字节 endstruc
2. 在BSS段分配结构体内存
在.bss段添加结构体实例的内存分配,SYSTEM_INFO_size是NASM自动生成的结构体总大小:
section .bss sysinfo resb SYSTEM_INFO_size ; 分配SYSTEM_INFO大小的未初始化内存
3. 修正编译链接命令
原链接命令末尾多余的点需要移除,正确命令:
nasm -fwin64 shell.asm link /out:shell.exe /subsystem:console /ENTRY:main /LARGEADDRESSAWARE:NO shell.obj kernel32.Lib msvcrt.lib User32.Lib WS2_32.Lib
错误原因说明
未定义sysinfo变量时,链接器无法为其分配有效内存地址,导致lea rcx, [sysinfo]生成无效的内存地址(如错误中的ffffffffffffff78),GetSystemInfo尝试写入该地址时触发内存访问异常。
内容的提问来源于stack exchange,提问作者Zeblive
相关产品推荐
相关产品推荐

