关于第三章Fault演示程序的疑问

《软件调试》答疑

关于第三章Fault演示程序的疑问


whislter 2008-10-16, 17:56 下午

      第三章的fault演示小程序,VS2008 SP1下出现了问题——异常总是消除不掉,导致程序不断循环。看了下下载的bin里用VC6编译的,是不是较高版本的VC都有这个问题??发现是编译器在idiv指令上使用了寄存器,禁用编译器优化并且为除数加了volatile 都没用。直接修改生成的二进制文件后正常了。

修改前:
/*1291078*/  mov     ecx, dword ptr [ebp-1C]
/*129107B*/  cdq
/*129107C*/  idiv    ecx

修改后:
/*1291078*/  cdq
/*1291079*/  idiv    dword ptr [ebp-1C]
/*129107C*/  nop
/*129107D*/  nop

有没有什么办法让编译器不要把除数放到寄存器里?

Re: 关于第三章Fault演示程序的疑问


格蠹老雷 2008-10-16, 20:55 下午

可以使用嵌入式汇编,改成下面的样子:

        // nResult=nDividend / nDivisor;
        __asm{
            mov eax, nDividend
            cdq
            idiv nDivisor
            mov nResult, eax
        };

我在VS2005上测试了一下是可以的。

Re: 关于第三章Fault演示程序的疑问


whislter 2008-10-16, 22:24 下午
谢谢张老师!
同样是改汇编,我第一反应居然没想到嵌入式汇编。。。

Re: 关于第三章Fault演示程序的疑问


笨笨 2009-06-14, 12:08 下午
关于这个问题
我想请教一下为什么把nDivisor 定义为volatile int nDivisor=0;依然会失败?

volatile是告诉cl该变量可能会以cl不知道的方式被改变,所以对该变量的访问不要做优化,要老老实实地按照programmer的指示去访问相应的memory.
编译,链接完成后,volatile已经体现在binary code中了,从binary中可以看到,对nDivisor的访问确实都没有被优化掉.
volatile是语言层面的keyword,它作用的对象是c/c++中的语句(sentence),是语句级的.
而本例乃异常(exception),是指令(instruction)级的,所以volatile起不了作用,只能用嵌入汇编.

请问我的理解对不?

ps:对于IA-32,有没有指令级的,作用与volatile相近的指令或compiler directive?

谢谢

Powered by Community Server Powered by CnForums.Net