编写汇编顺序查找程序时触发特权指令错误求助
排查汇编程序特权指令错误及数组检查异常的思路
我来分享几个针对你这个问题的实用排查方向,毕竟用Irvine32库写汇编时碰到这类内存和特权指令问题是挺常见的坑:
回溯特权指令错误的核心原因
特权指令错误本质是程序执行了只有内核态才能访问的指令,但你用的都是Irvine32的封装函数,所以大概率是调用库函数时的栈帧未对齐或参数传递违规。比如:- 确认是否遵循了Irvine32的调用约定:大部分函数是
stdcall,调用后不需要手动平衡栈,但如果是cdecl则需要自己清理参数。比如调用带参数的WriteString时,有没有把字符串地址正确放到edx,而不是错误地压栈? - 检查调用库函数前的
esp是否对齐到4字节(32位程序的硬性要求),如果栈未对齐,库函数内部的某些操作可能触发非法指令。
- 确认是否遵循了Irvine32的调用约定:大部分函数是
排查数组检查功能引入的问题
- 检查边界检查代码是否破坏了栈/寄存器状态:比如你在写数组越界判断时,有没有不小心修改了
ebp、esp这类栈指针?或者是否错误地覆盖了栈上的返回地址(比如数组索引计算错误,导致访问到[ebp+4]区域)? - 验证数组的基地址和长度是否正确:比如定义数组时是否用了正确的伪指令(如
DWORD arr 10 dup(0)),计算长度时是否用了$ - arr这种可靠的方式?如果长度算错,边界检查会完全失效,甚至导致越界访问内存。
- 检查边界检查代码是否破坏了栈/寄存器状态:比如你在写数组越界判断时,有没有不小心修改了
用调试器逐行追踪(最有效的手段)
- 用VS调试器或MASM自带工具单步执行,重点观察调用库函数前后的栈帧变化:比如调用
ReadInt前,栈上有没有多余的数据?调用后eax的返回值是否符合预期? - 当触发错误时,定位当前执行的指令是你的代码还是库函数内部代码:如果是库函数里触发的,90%是你传递的参数有问题——比如给
WriteXXX传了一个非字符串的内存地址,或者长度参数是负数。
- 用VS调试器或MASM自带工具单步执行,重点观察调用库函数前后的栈帧变化:比如调用
检查寄存器的保存与恢复
Irvine32库会保留ebp、ebx、esi、edi这些寄存器,但如果你在自己的代码中修改了它们,一定要在调用库函数前用push保存,调用后用pop恢复。比如你修改了esi却没保存,库函数使用esi时就会拿到错误值,进而触发内部操作异常。排查隐蔽的栈损坏情况
有些栈损坏不会立刻显现,比如你定义的局部数组空间不足,写入时越界覆盖了栈上的返回地址或保存的寄存器,但可能要等到调用库函数或返回时才触发错误。调试时可以查看ebp指向的栈帧,检查返回地址([ebp+4])是否为合法的代码段地址,有没有被篡改。验证库函数的使用正确性
再仔细核对你用到的几个库函数:Clrscr(你写的Crfl应该是笔误吧?)不需要参数,直接call Clrscr即可,若误传参数会破坏栈平衡;ReadInt的返回值存在eax中,确保你没有把这个值写到错误的内存区域;WaitMsg也不需要参数,调用后栈状态要保持正常。
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

