قراردادهای فراخوانی اکس۸۶
پاک شدن توسط فراخوانی کننده > قرارداد cdecl

cdecl (که بر پایه تعریف C است) یک قرارداد فراخوانی است که از زبان برنامه‌نویسی C سرچشمه می‌گیرد و توسط بسیاری از کامپایلرهای C برای معماری x86 استفاده می‌شود. در cdecl، آرگومان‌های تابع به پشته منتقل می‌شوند. مقادیر اعداد صحیح و آدرس‌های حافظه به وسیلهٔ ثبات (رجیستر) EAX و مقادیر اعشاری در ثبّات ST0 x87 بازگردانده می‌شوند. ثبّات‌های EAX, ECX، و EDX ذخیره شده توسط فراخوانی‌کننده (به انگلیسی: caller-saved) و بقیه ذخیره شده توسط فراخوانی شونده (به انگلیسی: callee-saved) هستند. ثبّات‌های اعشاری x87 T ST0 تا ST7، هنگام فراخوانی یک تابع جدید باید خالی (برداشته شده یا آزاد) باشند و ST1 تا ST7 باید در هنگام خروج از یک تابع خالی باشد. ST0 نیز باید زمانی خالی باشد که برای بازگشت مقدار مورد استفاده قرار نگیرد.
در چارچوب زبان برنامه‌نویسی C، آرگومان‌های تابع بر روی پشته از راست به چپ قرار می‌گیرند، یعنی اول آخرین آرگومان قرار داده می‌شود. در لینوکس، GCC استانداردهای واقعی را برای قراردادهای فراخوانی تنظیم می‌کند. از زمان GCC نسخه ۴٫۵، هنگام فراخوانی یک تابع، پشته باید به یک مرز ۱۶ بایت برسد (نسخه‌های قبلی فقط یک تراز ۴ بایت نیاز داشتند)
قطعه کد مرجعِ C زیر را در نظر بگیرید:
int callee(int, int, int);

int caller(void)
{
return callee(1, 2, 3) + 5;
}
در x86، ممکن است کد اسمبلی (به روش نوشتاری اینتل) زیر تولید کند:
caller:
; make new call frame
; (some compilers may produce an 'enter' instruction instead)
push    ebp       ; save old call frame
mov     ebp, esp  ; initialize new call frame
; push call arguments, in reverse
; (some compilers may subtract the required space from the stack pointer,
; then write each argument directly, see below.
; The 'enter' instruction can also do something similar)
; sub esp, 12      : 'enter' instruction could do this for us
; mov [ebp-4], 3   : or mov [esp+8], 3
; mov [ebp-8], 2   : or mov [esp+4], 2
; mov [ebp-12], 1  : or mov [esp], 1
push    3
push    2
push    1
call    callee    ; call subroutine 'callee'
add     eax, 5    ; modify subroutine result
                  ; (eax is the return value of our callee,
                  ; so we don't have to move it into a local variable)
; restore old call frame
; (some compilers may produce a 'leave' instruction instead)
; add   esp, 12   ; remove arguments from frame, ebp - esp = 12.
                  ; compilers will usually produce the following instead,
                  ; which is just as fast, and, unlike the add instruction,
                  ; also works for variable length arguments
                  ; and variable length arrays allocated on the stack.
mov     esp, ebp  ; most calling conventions dictate ebp be callee-saved,
                  ; i.e. it's preserved after calling the callee.
                  ; it therefore still points to the start of our stack frame.
                  ; we do need to make sure
                  ; callee doesn't modify (or restores) ebp, though,
                  ; so we need to make sure
                  ; it uses a calling convention which does this
pop     ebp       ; restore old call frame
ret               ; return
فراخوانی‌کننده پس از اتمام فراخوانی کردن تابع، پشته را پاک می‌کند.
برخی تغییرات در بیان cdecl, به ویژه در نحوه بازگشت مقادیر وجود دارد. در نتیجه، برنامه‌های کامپایل شده توسط x86 با سیستم عامل‌های مختلف یا کامپایلرهای مختلف می‌تواند ناسازگار باشد، حتی اگر آن‌ها هر دو از قراردادهای "cdecl" استفاده کنند و به محیط زیر وابسته نباشند. بعضی از کامپایلرها ساختار داده‌های ساده را با طول ۲ ثبّات یا کمتر در جفت ثبّات EAX: EDX برمی‌گردانند، و ساختارهای بزرگتر و اشیاء کلاس‌ها که نیاز به رفتار ویژه توسط رسیدگی کنندهٔ استثنا دارند (مانند سازندهٔ تعریف شده، تخریب‌کننده یا اختصاص دادن) به حافظه برگرداننده می‌شوند. برای انتقال "در حافظه"، فراخوانی‌کننده حافظه را اختصاص می‌دهد و یک اشاره گر به آن را به عنوان پارامتر پنهان می‌دهد؛ فراخوانی شده حافظه را پر می‌کند و اشاره گر را برمی‌گرداند (هنگام بازگشت اشاره گر پنهان برداشته می‌شود).
در لینوکس / GCC، مقادیر اعداد اعشاری هشت بایتی(double) / چهار بایتی(float) باید به وسیلهٔ شبه پشتهٔ x87 روی پشته قرار بگیرند. مثل این:
sub     esp, 8          ; make room for the double
fld     [ebp + x]       ; load our double onto the floating point stack
fstp    [esp]           ; push our double onto the stack
call    funct
add     esp, 8
با استفاده از این روش تضمین می‌شود که این در پشته به فرم صحیح قرار داده شده‌است.
قراردادهای فراخوانی cdecl معمولاً قرارداد فراخوانی پیش فرض برای کامپایلر‌های x86 C است، اگر چه بسیاری از کامپایلرها مجهز به گزینه‌هایی برای تغییر خودکار قراردادهای فراخوانیِ استفاده شده هستند. برای تعریف کردن دستی تابع به عنوان cdecl، برخی نحو زیر را پشتیبانی می‌کند:
return_type _cdecl func_name();
اصلاح‌کننده cdecl_ باید در نمونه اولیه تابع (به انگلیسی: function prototype) و در تعریف تابع گنجانده شود تا هر تنظیمات دیگری را که ممکن است در جای خود باشد را لغو کند.