C++ 在特定地址执行指令后返回寄存器的值

C++ Returning value of a register after executing an instruction at a specific address

本文关键字:返回 寄存器 指令 执行 地址 C++      更新时间:2023-10-16

我正在尝试在执行的某个阶段读取寄存器的值。例如:寄存器 ESI 由 insn 在0x80487a0处设置为一个值。

获取 ESI 值的代码是:

__asm{
    mov dword ptr [pBasePointer],esi
};

但是当运行此代码时,ESI 的值已设置为不同的值,我需要在 ESI 设置为 0x80487a0

有什么见解吗?

现在这个问题终于通过评论澄清了:

我不确定你为什么想要这个,或者你希望得到什么。 由于您显然可以使用跟踪代码重新编译程序,因此您应该弄清楚如何跟踪您尝试跟踪的内容。

给定代码行的最终地址直到链接时间才固定,因此谈论绝对地址对我来说没有意义。 编译器做出的寄存器分配决策对小的源更改和优化级别也很敏感。

因此,"由固定地址的insn设置的ESI"不是记录有用的东西,除非二进制文件已经编译并且无法重新编译。 即使源是asm,你也只需在你感兴趣的源行之后添加一个insn,作为某个行,而不是在某个二进制地址。


最好的办法可能是使用与调试器相同的工具,在您感兴趣的指令之后停止执行。 记录 ESI 的值,然后继续执行。

在 Linux 上,您将使用 ptrace 接口(或在其上构建的库(并设置断点。 Windows显然也有某种API用于跟踪另一个进程的进程。 我不知道如何使用,甚至不知道Windows叫什么,对不起。

我怀疑如果你有一个单独的进程"调试"你想要跟踪的进程,你会有更少的代码要写。 如果 API 不是为其设计的,那么进程"调试"本身可能会更难。

请注意,x86 可变长度指令使得以编程方式查找下一条指令的开头变得非常复杂。

据我了解,断点是通过用 0xCC 替换指令的第一个字节来设置的, 是一种特殊的int 3单字节编码,在执行方面也有一些特殊情况的差异CD 03(int 3的双字节形式(。

如果有人想改进这个答案,请编辑这个或复制尽可能多的你自己的答案。 我所能做的就是将 OP 指向调试工具,没有任何具体的代码建议。 我对编写自己的调试器或更详细地了解它的工作原理不够感兴趣,无法自己阅读文档来解决 OP 的问题。