本文介绍了我怎样写从C在Linux上的64位简单的内联汇编指令?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写一个简单的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寄存器读取限制?


解决方案

  1. 您的机器的 64 的位,没有63位=)。你能因为你编译和运行程序作为32位可执行文件[1]。
  2. 来读取32位寄存器
  3. 您不能因为你编译和运行程序作为32位可执行文件读取64位寄存器。是的,你有一个64位处理器,但它仍然可以运行32位可执行文件(如果您的操作系统支持的话,这显然你不会),看样子你的编译器工具链构建默认32位。如果您在使用 GCC ,请尝试使用 -m64 标记,或读取更多信息,编译器文档。

  4. 裂口 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?

解决方案
  1. 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].
  2. 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.
  3. Unlike rip, the eip register cannot be directly accessed. You can get the value of eip 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位简单的内联汇编指令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-27 17:13