[这才是孩子的天花板,可惜大部分父母不懂]1、最近听一位姑娘小C抱怨自己的父母,语气里满满是绝望和难过。小C大学毕业两年多,工作和薪水在同龄人中属于“刚刚及格”的水平。亲戚家的女儿留学归来,工作半年就给亲戚买了...+阅读
理论:
如果你以前使用过调试器,那么你应对跟踪比较熟悉。当"跟踪"一个程序时,程序在每执行一条指令后将会停止,这使你有机会去检查寄存器/内存中的值。这种单步运行的官方定义为跟踪(tracing)。
单步运行的特色是由CPU本身提供的。标志寄存器的第8位称为陷阱标志trap flag。如果该位设置,则CPU运行于单步模式。CPU将在每条指令后产生一个debug异常。当debug 异常产生后,陷阱标志自动清除。利用win32调试api,我们也可以单步运行被调试程序。方法如下:
调用GetThreadContext, 指定 ContextFlags为CONTEXT_CONTROL, 来获得标志寄存器的值
设置CONTEXT结构成员标志寄存器regFlag中的陷阱标志位
调用 SetThreadContext
等待调式事件。被调试程序将按单步模式执行,在每执行一条指令后,我们将得到调试 事件,u.Exception.pExceptionRecord.ExceptionCode值为EXCEPTION_SINGLE_STEP
如果要跟踪下一条指令,需要再次设置陷阱标志位。
例:
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\dlg32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\dlg32.lib
includelib \masm32\lib\user32.lib
.data
AppName db "Win32 Debug Example no.4",0
ofn OPENFILENAME
FilterString db "Executable Files",0,"*.exe",0
db "All Files",0,"*.*",0,0
ExitProc db "The debuggee exits",0Dh,0Ah
db "Total Instructions executed : %lu",0
TotalInstruction dd 0
.data?
buffer db 512 dup(?)
startinfo STARTUPINFO
pi PROCESS_INFORMATION
DBEvent DEBUG_EVENT
context CONTEXT
.code
start:
mov ofn.lStructSize,SIZEOF ofn
mov ofn.lpstrFilter, OFFSET FilterString
mov ofn.lpstrFile, OFFSET buffer
mov ofn.nMaxFile,512
mov ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetOpenFileName, ADDR ofn
.if eax==TRUE
invoke GetStartupInfo,addr startinfo
invoke CreateProcess, addr buffer, NULL, NULL, NULL, FALSE, DEBUG_PROCESS+ DEBUG_ONLY_THIS_PROCESS, NULL, NULL, addr startinfo, addr pi
.while TRUE
invoke WaitForDebugEvent, addr DBEvent, INFINITE
.if DBEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT
invoke wsprintf, addr buffer, addr ExitProc, TotalInstruction
invoke MessageBox, 0, addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION
.break
.elseif DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT .if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT
mov context.ContextFlags, CONTEXT_CONTROL
invoke GetThreadContext, pi.hThread, addr context
or context.regFlag,100h
invoke SetThreadContext,pi.hThread, addr context
invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE
.continue
.elseif DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_SINGLE_STEP
inc TotalInstruction
invoke GetThreadContext,pi.hThread,addr context or context.regFlag,100h
invoke SetThreadContext,pi.hThread, addr context
invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId,DBG_CONTINUE
.continue
.endif
.endif
invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED
.endw
.endif
invoke CloseHandle,pi.hProcess
invoke CloseHandle,pi.hThread
invoke ExitProcess, 0
end start
分析:
该程序先显示一个打开文件对话框,当用户选择了一个可执行文件,它将单步执行该程序,并记录执行的指令数,直到被调试程序退出运行。
.elseif DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT .if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT
利用该机会来设置被调试程序为单步运行模式。记住,在执行被调试程序的第一条指令前 windows将发送一个EXCEPTION_BREAKPOINT消息。
mov context.ContextFlags, CONTEXT_CONTROL
invoke GetThreadContext, pi.hThread, addr context
调用GetThreadContext,以被调试程序的当前寄存器内容来填充CONTEXT 结构 特别地,我们需要标志寄存器的当前值。
or context.regFlag,100h
设置标志寄存器映象的陷阱位(第8位)
invoke SetThreadContext,pi.hThread, addr context
invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE
.continue
然后调用SetThreadContext去覆盖CONTEXT的值。再以DBG_CONTINUE调用 ContinueDebugEvent 来恢复被调试程序的运行。
.elseif DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_SINGLE_STEP
inc TotalInstruction
当调试程序中一条指令执行后,我们将接收到EXCEPTION_DEBUG_EVENT的调试事件, 必须要检查u.Exception.pExceptionRecord.ExceptionCode的值。如果该值为 EXCEPTION_SINGLE_STEP,那么,该调试事件是单步运行模式造成的。在这种情况 下,TotalInstruction加一,因为我们确切地知道此时被调试程序执行了一条指令。
invoke GetThreadContext,pi.hThread,addr context or context.regFlag,100h
invoke SetThreadContext,pi.hThread, addr context
invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId,DBG_CONTINUE
.continue
由于陷阱标志在debug异常后自动清除了,如果我们需要继续保持单步运行模式,则必须设置陷阱标志位。
警告: 不要用本教程中的此例子来调试大程序: 跟踪是很慢的。你或许需要等待10 多分钟才能关闭被调试程序。
以下为关联文档:
夫妻吵架关系调试的妙招电子邮件的妙用电子邮件有一个很具人情味的名字,伊妹儿。伊妹儿在我们家还有另外一个功能──我们小俩口间的缓冲带。我和妻属于吵出感情的那类。一次,我们为一点小事争了起...
宝宝的第一次发热,大部分都是因为它相信不少爸妈都听说过「幼儿急疹」这个疾病,很多宝宝第一次发热就是因为它,宝宝的体温突然就飙上 39℃,甚至 40℃,把爸妈们吓个不轻。不过,幼儿急疹虽然来势汹汹,但却属于「纸老...
部分淘宝写给客户的道歉信淘宝写给客户的道歉信范文一亲:您好。我是xxxx的店主。看到您对我们的评价,非常抱歉,我们店铺有让您感到不满意的地方,给您带来不便,在此表示真诚的歉意请您谅解。小店的中评...
宝宝肚子胀气怎么办大部分妈妈都不知道的应对方法由于各种各样的原因,婴儿是很容易肚子胀气的。奶瓶喂养的宝宝如果在吃完奶后,没有及时拿开奶瓶,宝宝就会吞食过多的空气,引起胀气;母乳喂养的宝宝,如果等到宝宝很饿的时候再喂奶,也...
大部分公众对法律知识有一定程度了解调查结果显示,我国大部分公众对法律知识有一定程度了解。调查显示,有7.7%的社会公众表示“知道很多”法律知识,72.5%的人表示“知道一些”。 全国妇联权益部和司法部法制宣传司...
安微部分儿童出现血铅超标,家长怀疑是污染所致前言:儿童的健康一直都是父母所关心的重大问题,近些年来,虽然人民的经济水平提高了,但是相对的对于环境的污染比例也呈显直线上升,血铅超标对于孩子的健康危害极大,以下就让我们详...
是不是大部分的血管瘤都会自行消退小儿出生三天后,左鼻孔外侧出现红斑,后逐渐长大.经医生确认是草莓状血管瘤.有医生建议观察至两岁后若无消退再做手术 毛细血管瘤:又被称为草莓状血管瘤,出生时或新生儿期出现...
学习压力和家长期望导致部分青少年“童年恐慌”中新社北京十月二十六日电中国青少年研究中心的最新调查显示,严重扭曲的儿童学习动机和人格发展,使现代的孩子失去了本该拥有的快乐和轻松,在紧张不安中过早地告别童年时代。青...
《认识除法的各部分名称》反思本节课是在上节课学生充分理解了 平均分 以及怎样 平均分 的方法的基础上引出除法和除法意义的。在教学时,由于上节课学生已经经历了大量平均分的过程,有了充分的亲身实践。因...