San*_*p P 4 x86 assembly x86-64 cpu-registers
我正在写一个简单的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寄存器被限制读取?
Ste*_*non 10
gcc,请尝试使用该-m64标志,或阅读编译器文档以获取更多信息.rip,eip无法直接访问寄存器.你可以得到的值eip中所描述的方式吉姆在他的回答.[1]无论如何,你将能够从64位可执行文件读取32位寄存器; 32位寄存器仍然可以在64位模式下使用,就像在32位模式下可以访问16位寄存器一样.
您的示例中仍存在一些问题:
首先,虽然rip可以在64位模式下访问,但它可以作为寻址模式访问; 这不是一个正常的登记册.如果要加载其值,则需要使用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;
}
Run Code Online (Sandbox Code Playgroud)
这似乎在我的机器上工作得很好.
小智 5
您可以通过执行以下操作获取EIP寄存器的值:
call a ; this pushes the value of EIP onto the stack
a:
pop ebx ; pops the value of EIP into register ebx
Run Code Online (Sandbox Code Playgroud)
然后你就可以阅读ebx了.