我正在编写一个简单的c程序,我的要求是从程序的某些功能打印RIP(指令指针)。我不想使用ptrace。
我尝试使用内联asm的一件事是: asm(“movl %% rip,%0;”:“= r”(val)) 这应该将我的rip寄存器值复制到变量val,但是我收到了编译错误。
如果我使用ebp / esp作为32位机器的基本指针和堆栈指针,我不会得到任何编译错误,并且我的val已经分配了一些十六进制数。
我在这里几乎没有问题:
1)因为我的机器是63位,上面的指令怎么能读取32位寄存器?
2)为什么我无法读取64位的任何寄存器,是否有任何问题b'caz 'r'?
3)当我使用32位的eip时出现编译错误,是否意味着IP寄存器被限制读取?
答案 0 :(得分:9)
gcc
,请尝试使用-m64
标志,或阅读编译器文档以获取更多信息。rip
不同,无法直接访问eip
寄存器。您可以在答案中以 Jim 描述的方式获取eip
的值。[1]无论如何,您将能够从64位可执行文件读取32位寄存器; 32位寄存器仍可在64位模式下使用,就像您可以在32位模式下访问16位寄存器一样。
您的示例中仍存在一些问题:
首先,虽然可以在64位模式下访问rip
,但它可以作为寻址模式访问;这不是一个正常的登记册。如果要加载其值,则需要使用LEA
,而不是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;
}
这似乎在我的机器上运行得很好。
答案 1 :(得分:5)
您可以通过执行以下操作获取EIP寄存器的值:
call a ; this pushes the value of EIP onto the stack
a:
pop ebx ; pops the value of EIP into register ebx
然后你就可以阅读ebx了。