我正试图在某个执行阶段读取寄存器的值。 例如: 寄存器ESI由insn设置为值0x80487a0。
获取ESI值的代码是:
__asm{
mov dword ptr [pBasePointer],esi
};
但是当运行此代码时,ESI的值已设置为不同的值,我需要在设置为0x80487a0时获取ESI的值
有什么见解?
答案 0 :(得分:1)
现在问题最终通过评论澄清了:
我不确定你为什么要这个,或者你希望获得什么。由于您可以使用跟踪代码显然重新编译程序,因此您应该弄清楚如何跟踪您要跟踪的内容。
给定代码行的最终地址在链接时间之前不会被修复,所以谈论绝对地址对我来说没有意义。编译器做出的寄存器分配决策对小的源更改和优化级别也很敏感。
所以“由固定地址的insn设置的ESI”不是一个有用的记录,除非二进制文件已经编译,并且无法重新编译。即使源是asm,你只需在你感兴趣的那个之后添加一个insn,作为一些 source 行,而不是在某个二进制地址。
您最好的选择可能是使用与调试器相同的功能来停止您感兴趣的指令后的执行。记录ESI的值然后继续执行。
在Linux上,您将使用ptrace
接口(或在其上构建的库)并设置断点。 Windows显然有一些API用于跟踪另一个进程的进程。我不知道如何使用,甚至是Windows的名称,对不起。
我怀疑如果您有一个单独的进程“调试”您要跟踪的进程,那么您将编写更少的代码。如果API不是为它设计的,那么让一个进程“调试”本身可能会更难。
请注意,x86可变长度指令使以编程方式查找下一条指令的开头非常复杂。
据我了解,断点是通过用0xCC
替换指令的第一个字节来设置的,int 3
是CD 03
的特殊单字节编码,在执行时也有一些特殊情况的差异来自int 3
(String trimmed = string.trim();
的双字节形式)。
如果有人想改进这个答案,请编辑此内容或将您喜欢的内容复制到自己的答案中。我所能做的就是将OP指向调试工具,没有任何特定的代码建议。我对编写自己的调试器感兴趣,或者更详细地了解它是如何工作的,我自己去阅读文档来解决OP的问题。