问题描述
我写一个简单的C计划,我的要求是从程序的某些功能,打印RIP(指令指针)。我不想使用ptrace的。
一件事,我试图用内联汇编是:
ASM(MOVL %% RIP,%0;:= R(VAL))
这应该我裂口寄存器的值复制到变量val,但我收到编译错误。
如果我使用EBP / ESP这对32位机的基指针和堆栈指针,我没有得到任何编译错误,我的VAL有一些分配的十六进制数。
我有几个问题在这里:
1)我的机器是63位的,怎么着上述指令能够读取32位的寄存器?
2),为什么我不能够读取任何寄存器64位,有b'caz 'R'
中的任何问题3)当我使用EIP这是32位的,我收到编译错误,这是否意味着IP寄存器读取限制?
- 您的机器的 64 的位,没有63位=)。你能因为你编译和运行程序作为32位可执行文件[1]。 来读取32位寄存器
- 您不能因为你编译和运行程序作为32位可执行文件读取64位寄存器。是的,你有一个64位处理器,但它仍然可以运行32位可执行文件(如果您的操作系统支持的话,这显然你不会),看样子你的编译器工具链构建默认32位。如果您在使用
GCC
,请尝试使用-m64
标记,或读取更多信息,编译器文档。 - 与
裂口
的EIP
寄存器不能直接访问。您可以通过吉姆在他的回答中描述的方式获得EIP
的值。
[1]你将能够读取64位可执行反正32位寄存器; 32位寄存器仍然在64位模式下可用的,就像你可以访问16位寄存器的32位模式。
有在你的例子有几个问题依然:
首先,虽然裂口
在64位模式下访问,这是作为一个寻址方式访问;这不是一个正常的寄存器。如果你想加载它的价值,你需要使用 LEA
,而不是 MOV
。
第二,因为裂口
是一个64位寄存器,你需要使用①
后缀上你的指令而不是→
。下面是一个示例程序这两个问题解决:
的#include<&stdio.h中GT;
#包括LT&;&inttypes.h GT;INT主(INT ARGC,CHAR *的argv []){
uint64_t中的IP;
ASM(leaq(%% RIP),0%;:= R(IP));
的printf(哧是为0x%016PRIx64\\ n,IP);
返回0;
}
这似乎只是正常工作在我的机器上。
i am writing a simple c program and my requirement is to print RIP(Instruction Pointer) from some function of the program. i dont want to use ptrace.
the one thing i tried with inline asm is:asm("movl %%rip, %0;" : "=r"(val) )this should copy my rip register value to variable val, but i am getting compilation error.
if i use ebp/esp which are base pointer and stack pointers for 32 bit machine, i dont get any compilation error and my val has some hexadecimal number assigned.
i have few questions here:
1) as my machine is 63 bit, how was above instruction able to read 32 bit registers?
2) why i am not able to read any register for 64 bit, is there any issue b'caz of 'r'?
3) when i use eip which is for 32 bit i get compilation error, does it mean IP registers are restricted for reading?
- Your machine is 64 bit, not 63 bit =). You were able to read the the 32-bit registers because you are compiling and running your program as a 32-bit executable[1].
- You are unable to read the 64-bit registers because you are compiling and running your program as a 32-bit executable. Yes, you have a 64-bit processor, but it can still run 32-bit executables (if your OS supports it, which yours clearly does), and evidently your compiler tool chain builds 32-bit by default. If you are using
gcc
, try using the-m64
flag, or read the compiler documentation for more information. - Unlike
rip
, theeip
register cannot be directly accessed. You can get the value ofeip
in the manner described by Jim in his answer.
[1] you would be able to read the 32-bit registers from a 64-bit executable anyway; the 32-bit registers are still available in 64-bit mode, just like you can access the 16-bit registers in 32-bit mode.
There are a few problems still in your example:
First, although rip
is accessible in 64-bit mode, it's accessible as an addressing mode; it's not a normal register. If you want to load its value, you need to use LEA
, not MOV
.
Second, because rip
is a 64-bit register, you need to use the q
suffix on your instructions instead of l
. Here's a sample program with these two issues addressed:
#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;
}
which seems to work just fine on my machine.
这篇关于我怎样写从C在Linux上的64位简单的内联汇编指令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!