1

I want to jump to a function and pretend I had just called it. So I push the arguments to the stack, I load the address of the label I want to jump to when I return from the function I "call" and push it to the stack, I set ebp to esp ... now what?

Can I just

__asm__(
    "jmp %0;"
    :
    :"rm"(&my_func)
    );

or what would be the proper way to do this?

User1291
  • 7,664
  • 8
  • 51
  • 108
  • 1
    The _proper_ way to do this is actually calling the function. If you need to change the return address, the proper way to do it is through a jump right after the call. If you're worried about efficiency, I bet the difference is not as great as you think. If, after all this, there's still some reason to really, _really_ want to do this ("just to learn" could be one), I'd use ASM to make a copy of the stack to a static array and try to make sense of what it looks like, so I'd know what to push there to simulate a call. Expect the unexpected (e.g. an space for return value). – Jojonete May 11 '16 at 08:55
  • @Jojonete Thank you. What I'm trying to do is "store" a(n arbitrary) function call in a struct in order to later (potentially MUCH later) use that struct to actually make the "call" on a different stack. Using "call + jump after" should do the trick IF I can figure out what I need to store and later pass as argument to the inline assembly ``call`` instruction. Any suggestions? – User1291 May 11 '16 at 09:13
  • 1. I'm supposing the "other stack" is in the same process, even if MUCH later (otherwise pointers are useless, even pointers to code). 2. Are you _sure_ you want the return address to be the same as the first call? That would be quite dangerous as that address expects the stack below to be consistent, which is not necessarily so in the new stack. In other words, can you elaborate a bit more on the context for this? What is the use of repeating a function call in a different stack? – Jojonete May 11 '16 at 10:21
  • @Jojonete 1.)Yes, same process just different execution context. 2.) I'm sure I don't. We want communicating subroutines that can yield control to each other. Each subroutine is executing on its own "stack" and our scheduler keeps track of what we need to switch in-between them. To START a subroutine, though, we switch stack to the new subroutine, then call it and jump (when the call returns) to some exit code that will select and resume next subroutine. Or at least that's the idea. Problem is, we don't yet know what we need to keep track of in order to actually be able to call the subroutine. – User1291 May 11 '16 at 10:52
  • 1
    Okay, I see the problem now and I'm afraid I have no ideas beyond my first suggestion: write a small piece of ASM that copies (say, the top 16 KB of) the stack into a static (global) array, then write a trivial program declaring three such global arrays (call them `before`, `during` and `after`), then one function `f()` with the asm snippet using array `during`, then function `main()` with (1) the asm snippet for `before` (2) a call to `f()` (3) the asm snippet for `after` (4) code to compare/dump all three arrays in a suitable format. That should give an idea of what is needed. – Jojonete May 11 '16 at 11:29
  • Yes, you can just use a `jmp` after pushing a return address. `ebp` has nothing to do with anything, though. The code at the return address is going to have to restore your caller's registers, if you've modified any. But beware that having a `jmp` to another function in inline asm has non-obvious dangers. Jumping out of an `asm` statement (and not coming back) probably needs `asm goto ("jmp ...")`. – Peter Cordes Sep 01 '17 at 03:40

0 Answers0