Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the x86 "ret" instruction equivalent to?

Tags:

Say I'm writing a routine in x86 assembly, like, "add" which adds two numbers passed as arguments.

For the most part this is a very simple method:

push ebp
mov ebp, esp
mov eax, [ebp+8]
add eax, [ebp+12]
mov esp, ebp
pop ebp
ret

But, is there any way I could rewrite this method to avoid the use of the "ret" instruction and still have it produce the exact same result?

like image 687
Govind Parmar Avatar asked Nov 21 '13 18:11

Govind Parmar


2 Answers

Sure.

push ebp
mov ebp, esp
mov eax, [ebp+8]
add eax, [ebp+12]
mov esp, ebp
pop ebp

pop ecx  ; these two instructions simulate "ret"
jmp ecx

This assumes you have a free register (e.g, ecx). Writing an equivalent that uses "no registers" is possible (after all the x86 is a Turing machine) but is likely to include a lot of convoluted register and stack shuffling.

Most current OSes offer thread-specific storage accessible by one of the segment registers. You could then simulate "ret" this way, safely:

 pop   gs:preallocated_tls_slot  ; pick one
 jmp   gs:preallocated_tls_slot
like image 164
Ira Baxter Avatar answered Sep 24 '22 03:09

Ira Baxter


This does not need any free registers to simulate ret, but it needs 4 bytes of memory (a dword). Uses indirect jmp. Edit: As noted by Ira Baxter, this code is not reentrant. Works fine in single-threaded code. Will crash if used in multithreaded code.

push ebp
mov  ebp, esp
mov  eax, [ebp+8]
add  eax, [ebp+12]
mov  ebp, [ebp+4]
mov  [return_address], ebp
pop  ebp

add  esp,4
jmp  [return_address]

.data
return_address dd 0

To replace only the ret instruction, without changing the rest of the code. Not reentrant. Do not use in multithreaded code. Edit: fixed bug in below code.

push ebp
mov  ebp, esp
mov  ebp, [ebp+4]
mov  [return_address], ebp
pop  ebp

add  esp,4
jmp  [return_address]

.data
return_address dd 0
like image 30
nrz Avatar answered Sep 25 '22 03:09

nrz