获取x86的当前指令的地址

时间:2011-10-28 16:49:38

标签: c linux assembly 64-bit x86

我正在使用带有x86的Linux(准确地说是64位)。有没有办法可以得到当前指令的地址。其实我想编写自己的 setjmp / longjmp 的简化版本。 Here,R ..发布了 longjmp 的简化版本。不知道如何实现 setjmp 。一个简化的版本,没有考虑异常和信号等......

4 个答案:

答案 0 :(得分:25)

我相信64位代码,您只需lea rax, [rip]

32位成语是:

      call next
next: pop eax

答案 1 :(得分:9)

如果使用GCC,您还可以使用__builtin_return_address

答案 2 :(得分:6)

通常无法访问偏移到当前段寄存器(EIP)。然而,间接读取它有一种hackish方式 - 你欺骗程序将EIP的值推入堆栈,然后只是读取它。您可以创建一个如下所示的子例程:

GetAddress:
    mov eax, [esp]
    ret
...
    call GetAddress     ; address of this line stored in eax

或者,甚至更简单:

    call NextLine
NextLine:
    pop eax             ; address of previous line stored in EAX

如果您使用CALL FAR指令,则段值(CS)也将被推入堆栈。


如果您正在使用C,则可以在this page上使用各种特定于编译器的C扩展。另请参阅this interesting article

答案 3 :(得分:1)

This site提供了一个简单版本的setjmp和longjmp,如下所示。

#include "setjmp.h"

#define OFS_EBP   0
#define OFS_EBX   4
#define OFS_EDI   8
#define OFS_ESI   12
#define OFS_ESP   16
#define OFS_EIP   20

__declspec(naked) int setjmp(jmp_buf env)
{
  __asm
  {
    mov edx, 4[esp]          // Get jmp_buf pointer
    mov eax, [esp]           // Save EIP
    mov OFS_EIP[edx], eax
    mov OFS_EBP[edx], ebp    // Save EBP, EBX, EDI, ESI, and ESP
    mov OFS_EBX[edx], ebx
    mov OFS_EDI[edx], edi
    mov OFS_ESI[edx], esi
    mov OFS_ESP[edx], esp
    xor eax, eax             // Return 0
    ret
  }
}

__declspec(naked) void longjmp(jmp_buf env, int value)
{
  __asm
  {
    mov edx, 4[esp]          // Get jmp_buf pointer
    mov eax, 8[esp]          // Get return value (eax)

    mov esp, OFS_ESP[edx]    // Switch to new stack position
    mov ebx, OFS_EIP[edx]    // Get new EIP value and set as return address
    mov [esp], ebx

    mov ebp, OFS_EBP[edx]    // Restore EBP, EBX, EDI, and ESI
    mov ebx, OFS_EBX[edx]
    mov edi, OFS_EDI[edx]
    mov esi, OFS_ESI[edx]

    ret
  }
}