C 获取x86的当前指令的地址
我正在使用Linux和x86(准确地说是64位)。有没有办法得到当前指令的地址。实际上,我想编写自己的简化版的setjmp/longjmp,R发布了一个简化版的longjmp。任何关于如何实现setjmp的想法。一个简化版本,即不考虑异常和信号等。我相信64位代码可以简单地执行C 获取x86的当前指令的地址,c,linux,assembly,64-bit,x86,C,Linux,Assembly,64 Bit,X86,我正在使用Linux和x86(准确地说是64位)。有没有办法得到当前指令的地址。实际上,我想编写自己的简化版的setjmp/longjmp,R发布了一个简化版的longjmp。任何关于如何实现setjmp的想法。一个简化版本,即不考虑异常和信号等。我相信64位代码可以简单地执行lea-rax、[rip] 32位习惯用法是: call next next: pop eax 站点提供了setjmp和longjmp的简单版本,如下所示 #include "setjmp.h" #defi
lea-rax、[rip]
32位习惯用法是:
call next
next: pop eax
站点提供了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
}
}
当前段寄存器(
EIP
)中的偏移量通常不可访问。然而,有一种黑客的方式可以间接读取它——你欺骗程序将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
如果使用调用FAR
指令,那么段值(CS
)也将被推送到堆栈上
如果您使用的是C,那么您可以在上使用各种特定于编译器的C扩展。另请参见。如果使用GCC,您也可以使用并且可以在32位中执行类似操作吗?@MetallicPrist:答案已更新。我经常在代码块期间重复要求地址,因此我使用
调用next
并使用[esp]
访问值,而不是将其弹出到寄存器中。它为您提供了一个额外的免费寄存器供您使用,您只需执行添加esp,4
(在向下增长的堆栈上)即可在完成后清理堆栈。汇编mov(r | e)ax,$
或mylabel:mov(r | e)ax,offset mylabel
中的另一个选项在NASM 2.10中不起作用。似乎RIP只能间接地与rel
一起使用,如lea-rax,[rel\u start]
?这是你问题的答案吗,@metallicpaprest?不一定,我可以勾选你的答案,如果好的话:-p!请记住,为了达到预期效果,您需要将其包装在函数中,否则,您将得到当前堆栈帧的返回地址,而不是当前指令的地址。如果使用GCC,则更容易使用@Jason是正确的,并且还要确保包含_builtin_return_地址的包装函数的定义不在头文件中,并且永远不会内联。@phuclv yes,另请参见:OP询问有关x86_64的信息,它具有相对寻址,因此RIP有“可访问”的指令