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
).