PDA

View Full Version : سوال: تفاوت و طرز استفاده __stdcall ، __cdecl، __fastcall، __thiscall ؟



djsohrab2007
یک شنبه 06 شهریور 1390, 05:29 صبح
ببخشید اینقدر سوال می پرسما !

من تفاوت و طرز استفاده __stdcall ، __cdecl، __fastcall، __thiscall را بلد نیستم، در MSDN نگاه کردم ظاهرا کامل توضیح داده بود من کلمه کلمه ترجمه کردم ولی آخرش نفهمیدم چی شد، یعنی متوجه نشدم دقیقا وقتی از این ها استفاده می کنی چه اتفاقی می افته ؟ یا یکسری جاها گفته بود اگر در چنین وضعیتی باشید ف استفاده از این بهتره زیرا . . ..
من نه شرطش را متوجه شدم و نه دلیلش را.
من توضیحات انگلیسی MSDN را در اینجا ( با لینک کاملش ) قرار می دم ، هرکس که فهمید چی گفته لطفا توضیح بده ( بی زحمت توضیح کامل )
با تشکر از لطف دوستان
__thiscall :

The __thiscall calling convention is used on member functions and is the default calling convention used by C++ member functions that do not use variable arguments. Under __thiscall, the callee cleans the stack, which is impossible for vararg functions. Arguments are pushed on the stack from right to left, with the this pointer being passed via register ECX, and not on the stack, on the x86 architecture.
One reason to use __thiscall is in classes whose member functions use __clrcall by default. In that case, you can use __thiscall to make individual member functions callable from native code.
When compiling with /clr:pure (http://msdn.microsoft.com/en-US/library/k8d11d4s%28v=VS.80%29.aspx), all functions and function pointers are __clrcall unless specified otherwise.
In releases before Visual C++ 2005, the thiscall calling convention could not be explicitly specified in a program, because thiscall was not a keyword.
vararg member functions use the __cdecl calling convention. All function arguments are pushed on the stack, with the this pointer placed on the stack last
Because this calling convention applies only to C++, there is no C name decoration scheme.
On Itanium Processor Family (IPF) and x64 machines, __thiscall is accepted and ignored by the compiler; on an IPF chip, by convention, parameters are passed in register.
For non-static class functions, if the function is defined out-of-line, the calling convention modifier does not have to be specified on the out-of-line definition. That is, for class non-static member methods, the calling convention specified during declaration is assumed at the point of definition.
http://msdn.microsoft.com/en-US/library/ek8tkfbw%28v=VS.80%29.aspx
__fastcall :
The __fastcall calling convention specifies that arguments to functions are to be passed in registers, when possible. The following list shows the implementation of this calling convention.
http://msdn.microsoft.com/en-US/library/6xa169sk%28v=VS.80%29.aspx
__cdecl :
This is the default calling convention for C and C++ programs. Because the stack is cleaned up by the caller, it can do vararg functions. The __cdecl calling convention creates larger executables than __stdcall (http://msdn.microsoft.com/en-US/library/zxk0tw93%28v=VS.80%29.aspx), because it requires each function call to include stack cleanup code. The following list shows the implementation of this calling convention.
On Itanium Processor Family (IPF) and x64 processors, __cdecl is accepted and ignored by the compiler; on IPF, by convention, parameters are passed in register.
Place the __cdecl modifier before a variable or a function name. Because the C naming and calling conventions are the default, the only time you need to use __cdecl is when you have specified the /Gz (stdcall) or /Gr (fastcall) compiler option. The /Gd (http://msdn.microsoft.com/en-US/library/46t77ak2%28v=VS.80%29.aspx) compiler option forces the __cdecl calling convention.
For non-static class functions, if the function is defined out-of-line, the calling convention modifier does not have to be specified on the out-of-line definition. That is, for class non-static member methods, the calling convention specified during declaration is assumed at the point of definition. Given this class definition,
http://msdn.microsoft.com/en-US/library/zkwh89ks%28v=VS.80%29.aspx
__stdcall:
The __stdcall calling convention is used to call Win32 API functions. The callee cleans the stack, so the compiler makes vararg functions __cdecl. Functions that use this calling convention require a function prototype.
The /Gz (http://msdn.microsoft.com/en-us/library/46t77ak2%28v=VS.80%29.aspx) compiler option specifies __stdcall for all functions not explicitly declared with a different calling convention.
Functions declared using the __stdcall modifier return values the same way as functions declared using __cdecl (http://msdn.microsoft.com/en-us/library/zkwh89ks%28v=VS.80%29.aspx).
On Itanium Processor Family (IPF) and x64 processors, __stdcall is accepted and ignored by the compiler; on IPF, by convention, parameters are passed in register.
For non-static class functions, if the function is defined out-of-line, the calling convention modifier does not have to be specified on the out-of-line definition. That is, for class non-static member methods, the calling convention specified during declaration is assumed at the point of definition
http://msdn.microsoft.com/en-us/library/zxk0tw93%28v=VS.80%29.aspx

djsohrab2007
یک شنبه 06 شهریور 1390, 05:40 صبح
اگر لطف کنید ترجمه دقیق فارسی آن را بگذارید ، من کم کم یاد می گیرم متن انگلیسی را هم بخوانم.
می دونی ترجه کلمه کلمه با بابیلون انجام می دم ، مشکلم 2 تاست :
1. بعضی از کلمات معنای لغوی نمی دهند ، و اصطلاح هستند
2.جمله بندی به طوری که معنی بده
برای همینه که از شما خواستم معنای دقیق را هم بنویسید تا بتوانم هی با متن انگلیسیش مقایسه کنم تا دستم بیاد.

ممنون

djsohrab2007
یک شنبه 13 شهریور 1390, 11:01 صبح
کسی جواب نمی ده ؟
ثواب داره بخدا

AMIBCT
یک شنبه 13 شهریور 1390, 11:23 صبح
این‌ها شیوه‌هایی هستند برای ارسال پارامترها هنگام فراخوانی توابع

در ظاهر شما تفاوتی احساس نمی‌کنید

مگر در موارد خاصی مثل فراخوانی توابع با تعداد متغیر پارامتر( تعداد بسیار کمی از توابع این طور هستند )
هنگامی که بخواهید از تابعی به صورت بازگشتی استفاده کنید( موارد کارایی )
و هنگامی که با کتابخانه‌های خارجی سر و کار داشته باشید

برای فهم اینکه این شیوه‌های فراخوانی هر یک چه طور کار می‌کنند
لازمه که با زبان اسمبلی آشنایی سطحی داشته باشید
علت اینکه از متن چیزی سر در نیاوردید هم احتمالا همین بوده

شرح این موضوع به زبان فارسی هم خیلی طولانی می‌شه و از حوصله‌ی من و شما خارجه

تنها به این موضوع دقت کنید که توابعی که تعداد متغیر پارامتر دارن رو باید با شیوه‌ی cdecl تعریف و فراخوانی کنید
و برای بقیه‌ی توابع بهتره که از stdcall استفاده کنید( کاهش حجم خروجی )
شیوه‌ی fastcall هم در سیستم‌های 64 بیتی روش پیش‌فرض است و خودش مدل‌های مختلفی دارد( برای ارسال پارامترها از رجیسترها استفاده می‌کنه )

اگه به این موضوع علاقه دارید ابتدا باید اصول برنامه‌نویسی اسمبلی رو مطالعه کنید

vasilopita
یک شنبه 13 شهریور 1390, 12:58 عصر
آقای مدیر جناب آقای salar ashgi د بیا تحویل بگیر. شما که گفتید فقط دو نوع فراخوانی داریم پس اینا چی میگن ....

http://barnamenevis.org/showthread.php?300727-%D8%A7%D9%86%D9%88%D8%A7%D8%B9-%D9%81%D8%B1%D8%A7%D8%AE%D9%88%D8%A7%D9%86%DB%8C-%D8%AA%D8%A7%D8%A8%D8%B9-%D8%9F%D8%9F&highlight=

AMIBCT
یک شنبه 13 شهریور 1390, 15:27 عصر
اون تاپیک که شما بهش اشاره کردید

در مورد یه موضوع دیگه صحبت می‌کنه

موضوع این تاپیک «شیوه‌ی ارسال پارامترها به توابع»
و موضوع اون تاپیک «شیوه‌ی ارسال مقدار پارامترها»

این دو به صورت سری هستند نه موازی

هر چند که در برخی از موارد با هم سازگاری ندارند

djsohrab2007
پنج شنبه 24 شهریور 1390, 10:59 صبح
با تشکر از شما دوست عزیز

pswin.pooya
دوشنبه 28 شهریور 1390, 13:18 عصر
تنها به این موضوع دقت کنید که توابعی که تعداد متغیر پارامتر دارن رو باید با شیوه‌ی cdecl تعریف و فراخوانی کنید
و برای بقیه‌ی توابع بهتره که از stdcall استفاده کنید( کاهش حجم خروجی )
شیوه‌ی fastcall هم در سیستم‌های 64 بیتی روش پیش‌فرض است و خودش مدل‌های مختلفی دارد( برای ارسال پارامترها از رجیسترها استفاده می‌کنه )این درست نیست این مساله کاملا به زمان لینک که قراره از چند زبان کنار هم استفاده بشه ربط داره. هر کامپایلر و هر زبانی از یکی از این موارد استفاده میکنه. این پیش پردازنده ها به این دلیل گذاشته شدند که شما زمان استفاده از C/C++ بتونید از زبانهای دیگه برنامه نویسی هم مثل پاسکال و بیسیک و ... کنارش استفاده بکنن. من خودم از این موضوع داخل سیستم عامل هم استفاده کردم. البته فقط برای توابع داخل اسمبلی ( از استاندارد _cdcel )

در مورد توابع با تعداد متغییر باید بگم که هر روشی که اول پارامترها رو داخل پشته و یا چیزی شبیه اون قرار بده و بعد تابع رو فراخوانی کنه و بعد خود فراخوانی کننده تابع همونها رو از روی پشته برداره (نه تابع ) این قابلیت رو داره.