4

When I try to make an immediate call or jump in VC++ 2010 inline assembler

_asm 
{
    call 00405B90h;
    jmp 00405B90h;
    jmp far 00405B90h;
}

it generates an error

C2415: improper operand type

Is it possbile and how to do this?

So far I have a work around:

_asm 
{
    push 00405B90h; // This is a jump work around
    call 00405B90h;        
}
starblue
  • 55,348
  • 14
  • 97
  • 151
Max
  • 19,654
  • 13
  • 84
  • 122

2 Answers2

7

depending on what you want to call, either set a var to the address and do:

DWORD var = 0xDEADBEEF;
__asm jmp [var]

or, what I do:

__asm
{
    mov eax,ModuleBase
    add eax,RVA
    call eax ;obviously call can be jmp
}

you can easily macro this(probably a good idea to add a register param):

#define JMP_IMM(x) __asm mov eax,x \
                   __asm jmp eax

Unfortunately MASM doesn't support relative calls to absolute addresses, and other assemblers like NASM can't do it for COFF object files either. So toolchain limitations force you to use this less efficient machine code with an indirect call or jmp.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Necrolis
  • 25,836
  • 3
  • 63
  • 101
  • Thanks. That would work. I'm still wondering why the immediate jump/call instructions do not compile. – Max Oct 14 '10 at 14:46
  • @Max: more than likely due to the fact that the compiler cannot deduce whether its a short, local or far jump/call(due to it not being able to know the address of the outputted binary when virtualised) – Necrolis Oct 14 '10 at 16:20
  • I've tried putting 'far' modifier. Anyway I think it's just not possible. At least in VC++. Thanks. – Max Oct 14 '10 at 17:14
  • Why not simply call [var] ? – Heyji Jan 31 '15 at 21:27
  • @Heyji: Its interchangeable, JMP just happened to be the example I used (see the second example). – Necrolis Feb 01 '15 at 09:24
  • This gives you an indirect CALL/JMP. I (and the OP) want to know the syntax for getting MSVC to calculate the right `E8 rel32` direct call to reach a given absolute address from wherever the linker puts the code. In NASM or GAS, `call 0x00405B90` just works. Making less efficient machine code because your tools suck isn't much of an answer, IMO. – Peter Cordes Apr 27 '18 at 07:53
  • Posted [How to write an absolute target for a near direct relative call/jmp in MASM](//stackoverflow.com/q/50058523) to limit the question to answers that produce a direct relatve jmp or call. – Peter Cordes Apr 27 '18 at 08:41
  • @PeterCordes Less efficient code? the speed difference when looked at in a "dumb" manner is about 1-4 cycles depending, and if you are using it in a manner where this slight difference is an issue, you should rather rethink design. Have you benchmarked both types before making this assertion, or are you assuming? Secondly, this is the best you will get in MSVC, because it quite simply doesn't support this (and AFAIK neither does MASM), the only alternative is self-modifying-code, using `__asm {call $}` and `WriteProcessMemory`. – Necrolis Apr 30 '18 at 21:04
  • It's hard to benchmark indirect-call mispredict penalties, because any microbenchmark will tend to predict well. I don't know for sure if `call reg` mispredicts more often than `call rel32`, but from my understanding of CPU internals the mispredict penalty will be higher when it does happen. And yeah, 1-4 more cycles sounds like a reasonable guess. It might be more. So this is larger code size and definitely not ever faster, so it's less efficient and you're only doing it as a workaround for tools that can't do what you want. – Peter Cordes May 01 '18 at 00:21
  • If you're pretty sure that MASM has no syntax to do this, I'd be happy to upvote this if you edit to say so to justify using this obviously slightly worse machine code. (Would it work to create a `.obj` with a symbol definition for that absolute address, like `org 0deadbeefH` / `global my_target` /`my_target:` in NASM or however you do that in MASM, and then in MASM or MSVC inline-asm you can use `jmp my_target` and link with that `.obj`?) – Peter Cordes May 01 '18 at 00:25
  • 1
    @PeterCordes that might possibly work, I was trying to do that with MSVC's assembler as it supports "MASM directives", but no dice; I'd need to fiddle a bit and dig up a copy of MASM and see what I can produce (the big issue here is that the documentation for the MSVC inline assembler is shockingly poor, on purpose I suspect). – Necrolis May 01 '18 at 10:31
  • @Necrolis: If you have time, it'd be great if you could write up your findings as an answer on [How to write an absolute target for a near direct relative call/jmp in MASM](//stackoverflow.com/q/50058523). – Peter Cordes May 01 '18 at 10:49
0

__asm jmp fword ptr cs:[00405B90h]

plan9assembler
  • 2,862
  • 1
  • 24
  • 13