我正在编写一个简单的 C 程序,我的要求是从程序的某些函数中打印 RIP(指令指针)。我不想使用 ptrace。
我用内联汇编尝试的一件事是:asm("movl %%rip, %0;" : "=r"(val) )这应该将我的 rip 寄存器值复制到变量 val,但我收到编译错误。
如果我使用 ebp/esp(它们是 32 位机器的基指针和堆栈指针),我不会收到任何编译错误,并且我的 val 分配了一些十六进制数字。
我这里有几个问题:
1)由于我的机器是63位,上面的指令如何能够读取32位寄存器?
2)为什么我无法读取 64 位的任何寄存器,有什么问题吗?'r'?
3) 当我使用 32 位的 eip 时,出现编译错误,这是否意味着 IP 寄存器的读取受到限制?
- 你的机器是64位,不是 63 位 =)。您能够读取 32 位寄存器,因为您正在将程序编译并作为 32 位可执行文件运行[1]。
- 您无法读取 64 位寄存器,因为您正在将程序编译并作为 32 位可执行文件运行。是的,您有一个 64 位处理器,但它仍然可以运行 32 位可执行文件(如果您的操作系统支持它,您的操作系统显然支持它),并且显然您的编译器工具链默认构建 32 位。如果您正在使用
gcc
,尝试使用-m64
标志,或阅读编译器文档以获取更多信息。
- Unlike
rip
, the eip
不能直接访问寄存器。你可以获得的值eip
以描述的方式Jim在他的回答中。
[1] 无论如何,您都可以从 64 位可执行文件中读取 32 位寄存器; 32 位寄存器在 64 位模式下仍然可用,就像您可以在 32 位模式下访问 16 位寄存器一样。
您的示例中仍然存在一些问题:
首先,虽然rip
可在 64 位模式下访问,可作为寻址模式访问;这不是一个普通的寄存器。如果你想加载它的值,你需要使用LEA
, not MOV
.
其次,因为rip
是一个64位寄存器,你需要使用q
您的说明上的后缀而不是l
。这是解决这两个问题的示例程序:
#include <stdio.h>
#include <inttypes.h>
int main(int argc, char *argv[]) {
uint64_t ip;
asm("leaq (%%rip), %0;": "=r"(ip));
printf("rip is 0x%016" PRIx64 "\n", ip);
return 0;
}
这似乎在我的机器上运行得很好。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)