3

Say I have a call function which returns, can I make it so that it returns to x lines before the return address? eg.

call foo --> line 72 - calling bar will return here.
mov ax,1
call bar --> line 74

bar:
mov ax,2
ret (-2)

My goal is to create a callable function that will always return to 2 lines before the call address without having to use a billion flags and labels.

llinvokerl
  • 1,029
  • 10
  • 25
J Xkcd
  • 383
  • 2
  • 10

1 Answers1

6

You can't, x86 instructions are variable length. There's no way to know how much to decrement your return address by to go backward 2 instructions before the call.

Even if you were willing to write a disassembler / decoders, there's no way to unambiguously decode x86 instructions backwards. e.g. if you go back one byte and see a 0x90, you don't know if that's a NOP or the last byte of add dx, 0x9000.

Decoding forwards from known function-start labels is what debuggers like GDB do. But scanning a symbol table and disassembling is way too heavy-weight to be practical for whatever you're doing, I assume.


The only thing that occurs to me is being very rigid in your calling sequences so that's always a fixed number of bytes; e.g. here you used two 3-byte instructions (call rel16 and mov ax, imm16) before call bar. And the call bar itself is also 3 bytes.

Or to just always go back by a fixed number of bytes before the return address, and leave it up to callers to choose which / how many instructions to put in that window.


And BTW, the way you'd do this is by modifying the return address on the stack:

pop ax            ; could use any register that your function destroys
sub ax, 9
push ax
ret

Or address it relative to BP if you've set up BP as a frame pointer, like sub word [bp+2], 9.


See What methods can be used to efficiently extend instruction length on modern x86? for techniques to make instructions longer without adding more instructions, in case you want to use a shorter instruction like mov cx, bx before a call. e.g. you can instead use lea cx, [byte 0 + bx] (NASM syntax: byte 0 forces a disp8 of 0, so the encoding is 8D 4F 00).

Community
  • 1
  • 1
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847