DR7
DR7被称为“调试控制寄存器”,允许对每个硬件断点进行精细控制。其中,前8位控制是否启用了特定的硬件断点。偶数位(0、2、4、6)称为L0-L3,在本地启用了断点,这意味着仅在当前任务中检测到断点异常时才会触发。奇数位(1、3、5、7)称为G0-G3,在全局启用了断点,这意味着在任何任务中检测到断点异常时都会触发。如果在本地启用了断点,则在发生硬件任务切换时会删除相应的位,以避免新任务中出现不必要的断点。在全局启用时不会清除这些位。
在cpu中,单位执行往往是“任务”,这相当于操作系统中的线程
第8位和第9位分别称为LE和GE,是沿用的传统功能,在现代处理器上无法执行任何操作。这些位用于指示处理器检测断点发生的确切指令。在现代处理器上,所有断点条件都是精确的。为了与旧硬件兼容,建议始终将这两个位都设置为1。
第13位被称为GD,这一位非常值得关注。如果这一位被启用,则当每一条指令尝试访问调试寄存器时,都会生成调试异常。为了将这种类型的异常与普通的硬件断点异常区分开来,在调试寄存器DR6中设置了BD标志。这一位通常用于阻止程序干扰调试寄存器。关键点在于,异常发生在指令执行之前,并且当进入调试异常处理程序时,该标志会被处理器自动删除。但是,这样的解决方案并不完美,因为它只能使用MOV指令来访问调试寄存器。
第16-31位用于控制每个硬件断点的条件和大小。每个寄存器有4位,分为4个2位字段。前2位用于确定硬件断点的类型。仅能在指令执行、数据写入、I/O读写、数据读写时才能生成调试异常。仅有在启用了控制寄存器CR4的DE字段时,才启用I/O读写功能,否则这种情况是不确定的。大小可以使用后2位来控制,并用于指定特定地址处内存位置的大小。可用的大小有1字节、2字节、4字节和8字节。
这里还需要特别说一下的是读写位的问题:读写可执行:
其中00 执行时触发。01写入时触发,11读写时触发。
长度位:
00 1字节。01 2字节。10 8字节。11 4字节。
调试寄存器的读写
这里肯定是不能使用mov一类指令的,可以使用windows的两个api:SetThreadContext和GetThreadContextAPI.