How do i write Simple inline asm instruction from C on Linux 64 bit?
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) ) t开发者_StackOverflow中文版his 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.
You can get the value of the EIP register by doing:
call a ; this pushes the value of EIP onto the stack
a:
pop ebx ; pops the value of EIP into register ebx
and then you can just read ebx.
精彩评论