64位内核驱动.cpp调用同项目汇编函数致系统冻结无蓝屏排查
问题原因
你遇到的系统无蓝屏直接冻结,核心是x64 Windows内核栈对齐规则违反+全局异常拦截工具的共同作用,具体问题点如下:
- x64平台下所有函数调用执行前,栈指针
RSP必须保持16字节对齐。执行call ATest指令时,CPU会自动将8字节的返回地址压入栈,进入ATest函数时RSP已经比16对齐的位置偏移了8字节。你代码中直接SUB RSP, 40h,40h(64字节)是16的整数倍,执行完这条指令后RSP仍然偏移8字节,不满足对齐要求。此时调用DbgPrint,只要函数内部使用了要求16字节对齐的SSE/AVX指令,就会立刻触发内核访问异常。 - 你代码中调用了
ByePgInitialize注册了全局异常处理,这个框架会拦截内核未处理异常并直接挂起系统,不会走默认的蓝屏(KeBugCheckEx)流程,所以你看不到BSOD,只会表现为系统完全锁死。 - 汇编文件存在冗余风险代码:你定义了空的
main过程,MASM默认会将END关键字前的首个非空过程识别为模块入口,容易和KMDF驱动默认的GsDriverEntry入口点冲突,引发不可预期的执行流错误。 - 你注释掉的32位风格汇编调用逻辑完全不符合x64调用约定:x64下前4个参数通过
RCX/RDX/R8/R9传递,不是栈传参,那部分代码如果启用会直接破坏栈结构。
修正步骤
- 修正汇编文件代码,删除冗余过程,保证栈对齐,正确预留x64调用要求的32字节影子空间:
EXTERN DbgPrint:PROC .data dbgString byte "ATest() routine has been CALLED!\n", 0 .code ATest PROC PUBLIC ; 进入函数时RSP偏移8字节(call压入返回地址导致) ; 压入非易失性寄存器RBP,RSP再减8,刚好对齐到16字节边界 push rbp mov rbp, rsp ; 预留32字节影子空间供被调用函数使用,长度为16的倍数,不破坏对齐 sub rsp, 20h mov rcx, offset dbgString call DbgPrint ; 还原栈空间 add rsp, 20h pop rbp ret ATest ENDP END
- 检查VS项目配置:
- 右键
MyASM.asm文件→属性,确认项类型设置为Microsoft Macro Assembler (ml64.exe),目标平台匹配x64。 - 项目属性→链接器→高级→入口点,确认值为
GsDriverEntry(KMDF驱动默认入口),避免被汇编模块错误设置入口。
- 右键
- 调试阶段可以临时注释
ByePgInitialize的调用,此时如果还有栈错误,系统会正常抛出蓝屏,方便通过WinDbg分析调用栈排查问题,不会直接锁死。
额外说明
- 你之前写的
SUB RSP,40h的栈预留值是错误的:如果不用push rbp的方式对齐,需要预留的栈空间是28h(40字节,含32字节影子空间+8字节对齐填充),硬编码偏移很容易算错对齐值,优先用push/pop非易失性寄存器的方式自然对齐,出错概率更低。 - 内核模式下编写汇编必须严格遵守x64调用约定,非易失性寄存器(RBX/RBP/RSI/RDI/R12-R15)如果在函数中修改,必须在返回前还原,否则会引发调用者执行流混乱。
内容的提问来源于stack exchange,提问作者JbG
相关产品推荐
相关产品推荐

