{"id":53,"date":"2006-10-20T23:31:37","date_gmt":"2006-10-21T04:31:37","guid":{"rendered":"http:\/\/www.nynaeve.net\/?p=53"},"modified":"2019-12-13T17:41:46","modified_gmt":"2019-12-13T22:41:46","slug":"win32-calling-conventions-__stdcall-in-assembler","status":"publish","type":"post","link":"http:\/\/www.nynaeve.net\/?p=53","title":{"rendered":"Win32 calling conventions: __stdcall in assembler"},"content":{"rendered":"<p>It&#8217;s been awhile since my last post, unfortunately, primarily due to my being a bit swamped with work and a couple of other things as of late. With that said, I&#8217;m going to start by picking up where I had previously left off with the Win32 calling conventions series. Without further ado, here&#8217;s the stuff on __stdcall as you&#8217;ll see it in assembler&#8230;<\/p>\n<p>Like <a title=\"Win32 calling conventions: __cdecl in assembler\" href=\"http:\/\/www.nynaeve.net\/?p=41\">__cdecl<\/a>, __stdcall\u00c2\u00a0is completely stack-based.\u00c2\u00a0 The semantics of __stdcall are very similar to __cdecl, except that the arguments are cleaned off the stack by the callee instead of the caller.\u00c2\u00a0 Because the number of arguments removed from the stack is burned into the target function at compile time, there is no support for <em>variadic<\/em> functions (functions that take a variable number of arguments, such as printf) that use the __stdcall calling convention.\u00c2\u00a0 The rules for register usage and return values are otherwise identical to __cdecl.<\/p>\n<p>In practice, this typically means that an __stdcall function call will look much like a __cdecl function call until you examine the <em>ret<\/em> instruction that returns transfer to the caller at the end of the __stdcall function in question.\u00c2\u00a0 (Alternatively, you can look to see if it appears as if stack arguments are cleaned after the function call.\u00c2\u00a0 However, the compiler\/optimizer sometimes likes to be tricky with __cdecl functions, and defer argument removal until several function calls later, so this method is less reliable.)<\/p>\n<p>Because the callee cleans the arguments off the stack in an __stdcall function, you will always[1] see a <em>ret <\/em>instruction terminating a __stdcall function.\u00c2\u00a0 For most functions, this count is four times the number of arguments to the function, but this can vary if arguments that are larger than 32-bits are passed.\u00c2\u00a0 On Win32, this argument count in bytes value is virtually always[2] a multiple of four, as the compiler will always generate code that aligns the stack to at least four bytes for x86 targets.<\/p>\n<p>Given this information, it is usually fairly easy to distinguish an __stdcall function from a __cdecl function, as a __cdecl function will never use an argument to <em>ret<\/em>.\u00c2\u00a0 Note that this does imply, however, that it is generally not possible to disinguish between an __stdcall function and a __cdecl function in the case that both take zero arguments (without any other outside information other than disassembly); in this special case, the calling conventions have the same semantics.\u00c2\u00a0 This also means that if you have a function that does not clean any bytes off the stack with <em>ret<\/em>, you&#8217;ll technically\u00c2\u00a0have to examine any callers of the function to see if any pass more than zero arguments (or the actual function implementation itself, to see if it ever expects more than zero arguments) in order to be absolutely sure if the function is __cdecl or __stdcall.<\/p>\n<p>Here&#8217;s an example of a simple __stdcall function call for the following\u00c2\u00a0C function:<br \/>\n\u00c2\u00a0<\/p>\n<pre>__declspec(noinline)\r\nint __stdcall StdcallFunction1(int a, int b, int c)\r\n{\r\n\u00c2\u00a0return (a + b)\u00c2\u00a0* c;\r\n}<\/pre>\n<p>If we call the function like this:<\/p>\n<pre>StdcallFunction1(1, 2, 3);<\/pre>\n<p>&#8230; we can expect to see something like so, for the call:<\/p>\n<pre>push\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 3\r\npush\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 2\r\npush\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 1\r\ncall\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 StdcallFunction1<\/pre>\n<p>(There will be no <em>add esp<\/em> instruction after the call.)<\/p>\n<p>This is quite similar to a __cdecl declared function with the same implementation.\u00c2\u00a0 The only difference is the lack of an <em>add esp<\/em> instruction following the call.<\/p>\n<p>Looking at the function implementation, we can see that unlike the <a title=\"Win32 calling conventions: __cdecl in assembler\" href=\"http:\/\/www.nynaeve.net\/?p=41\">__cdecl version of this function<\/a>, StdcallFunction1 removes the arguments from the stack:<\/p>\n<pre>StdcallFunction1 proc near<\/p>\r\na= dword ptr\u00c2\u00a0 4\r\nb= dword ptr\u00c2\u00a0 8\r\nc= dword ptr\u00c2\u00a0 0Ch\r\n\r\nmov\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 eax, [esp+8] ; eax = b\r\nmov\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 ecx, [esp+4] ; ecx = a\r\nadd\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 eax, ecx\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 ; eax = eax + ecx\r\nimul\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 eax, [esp+c] ; eax = eax * c\r\nretn\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 0Ch\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0\u00c2\u00a0 ; (return value = eax)\r\nStdcallFunction1 endp<\/pre>\n<p>As expected, the only difference here is that the __stdcall version of the function cleans the three arguments off the stack.\u00c2\u00a0 The function is otherwise identical to the __cdecl version, with the return value stored in <em>eax<\/em>.<\/p>\n<p>With all of this information, you should be able to rather reliably identify most __stdcall functions.\u00c2\u00a0 The key things to look out for are:<\/p>\n<ul>\n<li>All arguments are on the stack.<\/li>\n<li>The\u00c2\u00a0<em>ret<\/em> instruction terminating the\u00c2\u00a0function\u00c2\u00a0has a non-zero argument count if the number of arguments for the function is non-zero.<\/li>\n<li>The <em>ret<\/em> instruction terminating the function has an argument count that is at least four times the number of arguments for the function.\u00c2\u00a0\u00c2\u00a0(If the count is less than four, then the function might be a __fastcall function with three or more arguments.\u00c2\u00a0 The __fastcall calling convention passes the first two 32-bit or smaller arguments in registers.)<\/li>\n<li>The function does not depend on the state of the <em>ecx<\/em> and <em>edx<\/em> volatile variables.\u00c2\u00a0 (If the function expects these registers to have a\u00c2\u00a0meaningful value initially, then\u00c2\u00a0the function is probably a __fastcall or __thiscall function, as those calling conventions pass arguments in the <em>ecx<\/em> and <em>edx<\/em> registers.)\u00c2\u00a0<\/li>\n<\/ul>\n<p>In the next\u00c2\u00a0post in this series, I&#8217;ll cover the __fastcall calling convention (and hopefully it won&#8217;t be such a long wait this time).\u00c2\u00a0 Stay tuned&#8230;<\/p>\n<p>\u00c2\u00a0<\/p>\n<p>[1]: For functions declared as __declspec(noreturn) or that otherwise never normally return execution control directly to the caller\u00c2\u00a0(i.e. a function that\u00c2\u00a0always throws an exception),\u00c2\u00a0the <em>ret<\/em> instruction is typically omitted.\u00c2\u00a0 There are a couple of other rare cases where you may see no terminating <em>ret<\/em>, such as if there are two functions, where one function calls the second, and both have\u00c2\u00a0very similar prototypes\u00c2\u00a0(such as argument ordering or an additional defaulted argument).\u00c2\u00a0\u00c2\u00a0In this case, the compiler may combine two functions by having one perform minor adjustments to the stack and then &#8220;falling through&#8221; directly to the second function.<\/p>\n<p>[2]: If you see a function with a <em>ret<\/em> instruction that does not take a multiple of four as its argument, then the function was most likely hand-written in assembler.\u00c2\u00a0 The Microsoft compiler will never, to my knowledge, generate code like this (and neither should any sane Win32 compiler).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;s been awhile since my last post, unfortunately, primarily due to my being a bit swamped with work and a couple of other things as of late. With that said, I&#8217;m going to start by picking up where I had previously left off with the Win32 calling conventions series. Without further ado, here&#8217;s the stuff [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[2,4,8,5],"tags":[],"_links":{"self":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts\/53"}],"collection":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=53"}],"version-history":[{"count":1,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts\/53\/revisions"}],"predecessor-version":[{"id":682,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts\/53\/revisions\/682"}],"wp:attachment":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=53"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=53"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=53"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}