2

Here is a simple program:

void func()
{
    printf("hello");
}

int main()
{
    printf("%p",func);
    func();
    return 0;
}

Stepping over the line printf("%p",func), I get 00F811AE printed on the console.

Disassembling the line func(), gives me call _func (0F811AEh) - so far so good.

But disassembling the contents of func, the first instruction appears at address 00F813C0.

So I "went to see" what's on address 00F811AE, and there I found jmp func (0F813C0h).

To summarize this, it appears that the function-call is compiled as two instructions:

call _func (0F811AEh)
jmp   func (0F813C0h)

Why does the VS2013 compiler use two instructions instead of just one?

It appears that a single jmp would do the the job. I am asking even this because I have a feeling that the other compilers do it in a similar manner (depending on the underlying HW architecture of course).

Thanks

barak manos
  • 29,648
  • 10
  • 62
  • 114
  • 4
    Is [this](http://stackoverflow.com/questions/10859188/in-visual-studio-debugmode-compiled-executable-jmp-to-function-body-instead-of) related ? – quantdev Aug 14 '14 at 10:19
  • I don't know the answer, but there must be a cast for `"%p"`: `printf("%p", (void *)func);` – David Ranieri Aug 14 '14 at 10:22
  • 1
    @AlterMann: You are right that "%p" is for object pointers and not function pointers. However, what you are suggesting also leads to undefined behaviour. See accepted answer for http://stackoverflow.com/questions/2741683/how-to-format-a-function-pointer – Klas Lindbäck Aug 14 '14 at 10:28
  • @KlasLindbäck, true! – David Ranieri Aug 14 '14 at 10:29
  • 1
    @quantdev: Thanks! Your link leads to http://stackoverflow.com/q/2485336/1382251, which in turn leads to http://msdn.microsoft.com/en-us/library/4khtbfyf%28VS.80%29.aspx, and there are some good explanations there on how to change it from two instructions to one instructions (if I understand correctly)... Will give it a try... – barak manos Aug 14 '14 at 10:32
  • Do you disassemble the code with an external program? – sharptooth Aug 14 '14 at 10:47
  • @sharptooth: No, with the VS2013 debugger. – barak manos Aug 14 '14 at 10:50
  • Good, that's the optimal way. – sharptooth Aug 14 '14 at 10:51

1 Answers1

6

Learn about "thunking": http://en.wikipedia.org/wiki/Thunk

One benefit with "thunking" in your example is that the rest of your code will always call func, but any function performing the same role could be injected into the call at address 0x00F811AE.

Try making func a static one and find out if anything changes.

Shao
  • 537
  • 3
  • 7
  • +1 specifically, if `printf()` is loaded from a dll dynamically, then the address can be patched in at one place in memory and all the calls to it will find it from there.... – Tony Delroy Aug 14 '14 at 10:26
  • barak manos: You're welcome. Also worth considering is that the thunk might be dealing with calling convention differences, if it is indeed a thunk. – Shao Aug 14 '14 at 10:42
  • 1
    Also worth mentioning (according to links provided in some of the comments to my question), that you can reduce it from two instructions to one instruction through the linker-settings of your project. – barak manos Aug 14 '14 at 10:49
  • so does this only happen when you link to dynamic RTL? – M.M Aug 14 '14 at 10:52
  • Matt McNabb: I don't think so. This wouldn't be an example of thunking for an RTL function, but for barak manos' external-linkage function: func. It could be more related to calling convention. – Shao Aug 14 '14 at 10:55
  • @MattMcNabb: I have no idea what you mean by that. I have not linked to any DLL (besides what comes along in the VS-project's default configuration). – barak manos Aug 14 '14 at 10:57
  • OK. The other links suggest that it is to enable incremental linking (my understanding of which is that it's a technique to improve link times for large projects) – M.M Aug 14 '14 at 10:58
  • @MattMcNabb: So what you're saying is - improve linkage performance over runtime performance??? – barak manos Aug 14 '14 at 11:44
  • @barakmanos Yeah, it's useful for debugging but for a final release you would disable it – M.M Aug 14 '14 at 11:47
  • 1
    Yep, declaring the function `static` reduces it from two instructions to one instruction, which proves that it's a linkage issue, since `static` functions can be resolved before linkage (i.e., during compilation). – barak manos Aug 14 '14 at 14:08