Get address of current instruction for x86
Solution 1
I believe in 64-bit code you can simply do lea rax, [rip]
.
The 32-bit idiom is:
call next
next: pop eax
Solution 2
If using GCC, you could also use __builtin_return_address
Solution 3
The offset-into-the-current-segment register (EIP
) is not normally accessible. However, there is a hackish-way to read it indirectly - you trick the program into pushing the value of EIP onto the stack, then just read it off. You could create a subroutine that looks like this:
GetAddress:
mov eax, [esp]
ret
...
call GetAddress ; address of this line stored in eax
Or, even simpler:
call NextLine
NextLine:
pop eax ; address of previous line stored in EAX
If you use a CALL FAR
instruction, the segment value (CS
) will be pushed on the stack as well.
If you're using C, there are various compiler-specific C-extensions you could use on this page. See also this interesting article.
Solution 4
This site gives a simple version of setjmp and longjmp, which is as follows.
#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
}
}
MetallicPriest
Updated on October 29, 2020Comments
-
MetallicPriest over 3 years
I am using Linux with x86 (64 bit to be precise). Is there a way I can get the address of the current instruction. Actually I want to write my own simplified versions of setjmp/longjmp. Here, R.. posted a simplified version of longjmp. Any idea how setjmp is implemented. A simplified version that is, without taking into account of exceptions and signals etc...
-
MetallicPriest over 12 yearsAnd is it possible to do something like that in 32 bit?
-
NPE over 12 years@MetallicPriest: Answer updated.
-
karlphillip over 12 yearsIS this the answer of your question, @MetallicPriest ?
-
MetallicPriest over 12 yearsNot necessarily, I may tick your answer, if its good :-p!
-
Jason over 12 yearsKeep in mind you'll need to wrap that in a function in order to have the intended effect, otherwise you'll end up with the return address for the current stack frame rather than the address of the current instruction.
-
Polynomial over 12 yearsI often require the address repeatedly during a block of code, so I do
call next
and access the value using[esp]
rather than by popping it into a register. It gives you an extra free register to use and you can just doadd esp, 4
(on a downward growing stack) to clean up the stack when you're done. -
Alexey Frunze over 11 yearsAnother option in assembly
mov (r|e)ax, $
ormylabel: mov (r|e)ax, offset mylabel
. -
phuclv over 10 yearsif using GCC it's easier to use
somelabel: return &&somelabel;
-
phuclv over 10 yearsthe OP asks about x86_64, which has relative addressing, so there are instructions "accessible" to RIP
-
phuclv over 9 yearsthis idiom is actually not recommended blogs.msdn.com/b/oldnewthing/archive/2004/12/16/317157.aspx
-
Ciro Santilli OurBigBook.com about 9 years
lea rax, [rip]
did not work in NASM 2.10. It seems that RIP can only be used indirectly withrel
as inlea rax, [rel _start]
? -
Michal Fapso almost 7 years@Jason is right and also make sure the definition of the wrapping function containing the __builtin_return_address is not in a header file and will never be inlined.
-
Ciro Santilli OurBigBook.com almost 5 years@phuclv yes, see also: stackoverflow.com/questions/1777990/…