{"id":30403,"date":"2006-07-24T10:00:00","date_gmt":"2006-07-24T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2006\/07\/24\/how-a-less-naive-compiler-calls-an-imported-function\/"},"modified":"2006-07-24T10:00:00","modified_gmt":"2006-07-24T10:00:00","slug":"how-a-less-naive-compiler-calls-an-imported-function","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20060724-00\/?p=30403","title":{"rendered":"How a less naive compiler calls an imported function"},"content":{"rendered":"<p>\nIf a function is declared with the <code>dllimport<\/code>\ndeclaration specifier,\nthis instructs the Visual Studio C\/C++ compiler\nthat the function in question is an imported function rather\nthan a normal function with external linkage.\nWith this additional information, the compiler generates\nslightly different code when it needs to reference an imported\nfunction, since the compiler is aware of the special way\nimported functions are implemented.\n<\/p>\n<p>\nFirst, there is no need for the stub function any more,\nbecause the compiler can generate the special\n<code>call [__imp__FunctionName]<\/code> instruction inline.\nFurthermore, the compiler knows that the address of an\nimported function never changes, and consequently it can\noptimize away multiple loads of the function pointer:\n<\/p>\n<pre>\n    mov   ebx, [__imp__FunctionName]\n    push  1\n    call  ebx ; FunctionName(1)\n    push  2\n    call  ebx ; FunctionName(2)\n<\/pre>\n<p>\n(Note to crazy people:\nThis optimization means that you can run into problems\nif you patch a module&#8217;s import table once it has started\nrunning, because the function pointer may have been\noptimized into a register before you patched the import.\nConsider, in the above example. that you patched the\n<code>__imp__FunctionName<\/code> table entry after the\n<code>mov ebx, [__imp__FunctionName]<\/code> instruction:\nYour replacement import table entry won&#8217;t be called since\nthe old function address was cached in the <code>ebx<\/code> register.)\n<\/p>\n<p>\nSimilarly, if your program tries to take the address of an imported\nfunction that has been declared with the <code>dllimport<\/code>\ndeclaration specifier, the compiler recognizes this and converts it to\na load from the imported function address table.\n<\/p>\n<p>\nAs a result of this extra knowledge imparted to the compiler,\nthe stub function is no longer needed; the compiler knows to\ngo straight to the imported function address table.\n<\/p>\n<p>\nNote that there are still occasional circumstances wherein\nyou can induce the stub function to be created.\nWe&#8217;ll take a look at them (and related dangers) next time.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If a function is declared with the dllimport declaration specifier, this instructs the Visual Studio C\/C++ compiler that the function in question is an imported function rather than a normal function with external linkage. With this additional information, the compiler generates slightly different code when it needs to reference an imported function, since the compiler [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[26],"class_list":["post-30403","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>If a function is declared with the dllimport declaration specifier, this instructs the Visual Studio C\/C++ compiler that the function in question is an imported function rather than a normal function with external linkage. With this additional information, the compiler generates slightly different code when it needs to reference an imported function, since the compiler [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/30403","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=30403"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/30403\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=30403"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=30403"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=30403"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}