- UID
- 1
- 精华
- 积分
- 76365
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
eflags的tf位,就是Trap Flag,陷阱标识,是用于给调试器进行单步调试用的。这个位设置为1以后,CPU每执行一条指令,都会产生单步中断。不同于int3(也就是“烫”)的断点中断,这个是硬断,中断号是int 1。
古代的debug.exe的t命令就是用这种方式进行单步调试的。当然还有p命令,这个p命令就是用“烫”来中断的了。
单步位是第8bit,我们看看intel的文档就知道了。
图1:Intel文档片段(1986)
首先我写下这样的代码。大家可以看到我直接读取了eflags的值,然后将第8个bit设置为1,并将其塞回eflags寄存器里面去,看看它会不会立即生效。- #include<stdint.h>
- #include<stdio.h>
- #include<conio.h>
- int main(int argc,char**argv)
- {
- uint32_t _eflags;
- _asm
- {
- pushfd;
- pop eax;
- mov _eflags,eax;//取得旧的eflags的值
- };
- printf("EFLAGS = 0x%.8X\n",_eflags);
- _asm
- {
- mov eax,_eflags;
- or eax,0x100;//设置tf位
- push eax;
- popfd;//然后将其装入eflags寄存器
- //跑几个指令
- nop;
- xchg eax,edx;
- xchg edx,eax;
- //取回eflags的值,显示一下。
- pushfd;
- pop eax;
- mov _eflags,eax;
- };
- printf("EFLAGS = 0x%.8X\n",_eflags);
- //暂停
- _getch();
- return 0;
- }
复制代码 我直接点了VS的运行按钮,它直接弹出了这样的窗口:
图2:VS捕获中断
喜闻乐见,它中断了,然后被VS捕获了。
那么我们让它不带调试器,自己单独运行,看是什么效果。
图3
图4
看样子不带调试器的话这个中断没人管,它就死了。
那这样,我们自己捕获它的中断试试。- #include<stdint.h>
- #include<stdio.h>
- #include<conio.h>
- #include<Windows.h>
- LONG WINAPI __int3catch(struct _EXCEPTION_POINTERS*pExceptionInfo)
- {
- switch(pExceptionInfo->ExceptionRecord->ExceptionCode)
- {
- case EXCEPTION_SINGLE_STEP:
- printf("单步\n");
- break;
- default:
- return EXCEPTION_CONTINUE_SEARCH;
- }
-
- return EXCEPTION_CONTINUE_EXECUTION;
- }
- int main(int argc,char**argv)
- {
- uint32_t _eflags;
- SetErrorMode(SEM_FAILCRITICALERRORS);
- SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)__int3catch);
- _asm
- {
- pushfd;
- pop eax;
- mov _eflags,eax;//取得旧的eflags的值
- };
- printf("EFLAGS = 0x%.8X\n",_eflags);
- _asm
- {
- mov eax,_eflags;
- or eax,0x100;//设置tf位
- push eax;
- popfd;//然后将其装入eflags寄存器
- //跑几个指令
- nop;
- xchg eax,edx;
- xchg edx,eax;
- //取回eflags的值,显示一下。
- pushfd;
- pop eax;
- mov _eflags,eax;
- };
- printf("EFLAGS = 0x%.8X\n",_eflags);
-
- //暂停
- _getch();
- return 0;
- }
复制代码 上面的代码运行了以后,它应该能在触发单步中断的时候,显示一个“单步”。
图5
还是会被VS捕获到。
然后我单独运行它(不附加调试器):
图6
它只显示了一个“单步”,并且事前事后显示的eflags数值没变。。估计是单步后,Windows对其进行了处理。Windows应该是确认没有单线程自己调试自己的情况的吧。。
参考资料:
https://en.wikipedia.org/wiki/Trap_flag |
|