首页 新闻 会员 周边 捐助

在C++函数中使用__asm int 3和__debugbreak的编译问题

0
悬赏园豆:50 [已解决问题] 解决于 2014-04-16 16:17

      环境VS08,在测试中有时候会使用__asm int 3 设置断点,下面的函数是可以通过编译并执行的。

int test(){          
        __asm int 3
}

      考虑到64位的问题,尝试用intrinsics中的__debugbreak代替,但是下面的函数显然通不过编译,因为函数没有返回值。

int test(){          
        __debugbreak();
}

      这样一来,在一些测试问题中,对于某些分支正常情况下是不会被执行到的,为捕捉异常情况时常常在认为不可能执行到的分支上触发断点方便调试。用__asm int 3是没有问题的,但是用__debugbreak总是会得到警告或错误,说分支缺少返回值。

    请教熟悉的同仁们,这两种方式在编译层面的原理,能否像__asm int 3那样无编译错误或警告的使用__debugbreak?

adanus的主页 adanus | 初学一级 | 园豆:144
提问于:2014-04-15 23:22
< >
分享
最佳答案
0

不能。__asm 相当于在机器码中嵌入一条语句,而 __debugbreak 是一个 C/C++ 语法下定义的方法,先要经过 C/C++ 语法分析的。我们可以这样来看:

void __debugbreak()

{

#if defined(_M_IX86)

    __asm {

           int 3

    }

#else

.........

#endif
}

收获园豆:50
Launcher | 高人七级 |园豆:45050 | 2014-04-16 09:44

感谢您的回复,我对编译不太熟,下面的函数当然也不能通过编译,

int test(){

}

 

我更想知道的是为何嵌入机器码__asm int 3后就能编译通过,它并没有返回值啊。

adanus | 园豆:144 (初学一级) | 2014-04-16 12:50

@cai870808: 嵌入汇编后,在函数出口处,编译器会自动添加复栈指令,返回值从 EAX 寄存器中读取。比如:

int power(int num, int power)
{
    __asm {
        MOV EAX, num;
        MOV ECX, power;
        SHL EAX, CL; EAX = EAX * CL
    }

    // 在函数中,返回值是由 EAX 负责往回传递的,所以我们无需显示提供返回值。
}
Launcher | 园豆:45050 (高人七级) | 2014-04-16 13:13

@Launcher: 楼主正解啊,跟踪了一下函数,返回值确实是寄存器EAX读出的。

adanus | 园豆:144 (初学一级) | 2014-04-16 16:16
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册