我用VC编译一个多线程的c程序,发现release模式的时候总是出现0地址非法访问。
加 /FA选项查看汇编代码,发现使用了ebx,它是这样用的:
mov ebx, DWORD PTR __imp__WaitForSingleObject@8
push 1000 ; 000003e8H
push esi
call ebx
可是我查看ebx的值竟然是0,于是我在网上找到两篇文章:
1.“根据我的试验,在win2000以上操作系统对于ebx,esi,edi好像是拿来就用,没有进行保护和恢复,如果你的程序中使用了这几个寄存器,请一定先压栈,用完后恢复。否则会使程序在win98下正常,在win2000下出现莫名其妙的非法操作,一般是提示某个地址不能进行读写操作,而这个地址并不在你的程序的控制下。”
2.“如果你的程序98正常,而xp非法操作,进来看看
我经常玩游戏,特别喜好小游戏.经常把小游戏改动一下使之容易通关,或者汉化容易操作,以博女友欢心.我基本用winme,最近进XP发现玩改动后的小游戏时,出现莫名其妙的非法操作.说某某地址不能进行读写操作.
百思不得其解,辛苦很久才发现XP对ebx没有保护和恢复,如果你的程序也使用了ebx寄存器,请一定先压栈,用完后恢复
esi,edi好像也是.”
最后我在程序中加入以下代码:
__asm
{
mov ebx, 123
}
目的就是不让编译器使用ebx,问题解决了。
但是我觉得这是一个隐患,以前编程从来没有想到过还有这种问题,请各们大大来说说看。
------解决方案--------------------------------------------------------
这个要看具体的api大多数都作了:
push esi
push edi
push ebx
等的操作,但也有例外,这个要结合反汇编实际来看。
------解决方案--------------------------------------------------------
不能一概而论,具体函数具体对待,不过相信Windows的分层体制,这些地层操作也应该在地层实现,估计可以访问到edi、ebx、esi寄存器的只有个别的API而已。
------解决方案--------------------------------------------------------
win9x以及winme都是允许应用程序直接操纵硬件的,但是为了系统的稳定和安全,WinNT、2000、xp以及后继版本都对系统实行了一些保护措施,不再允许应用程序直接操作硬件,而只能通过调用API来安全的使用硬件。所以在windows9x在运行的程序未必可用在Win2000及其后续版本中运行。