معمولاً گفته میشود تبدیل یک کد به زبان C به کد قابل اجرا توسط پردازنده سه مرحله دارد:
اما این مراحل به طور جزئیتر به ترتیب به صورت ذیل هستند:
۱- نوشتن کد (Editing)
که به اصطلاح به این مرحله Editing میگویند و محیطی که در آن کد زده میشود Editor و اگر حرفهای باشد Integrated Development Environment یا همان IDE. خروجی این گام، یک یا چند پرونده متنی به زبان C است.
۲- پیشپردازش (Preprocessing)
در این مرحله دستورات پیشپردازشی (preprocessor directives) به کمک نویسه # میتوانند دستوراتی را به کامپایلر بدهند. به عنوان مثال با کمک دستورات پیشپردازشی، میتوانیم ماکرو (macro) بنویسیم.
#include <stdio.h> int main() { printf("Line Number %s -> %s: %d\n", __FILE__, __FUNCTION__, __LINE__); return 0; }
گام پیشپردازش، قرار است کد را برای مرحله کامپایل آماده کند. سه وظیفه در این گام انجام میشود: اول از همه، پیشپردازنده تمامی کامنتهای موجود در کد را حذف میکند. در مرحله دوم، پیشپردازنده تمامی پروندههای شامل شده (این کار با کمک دستور #include انجام میشود) را در بر میگیرد. در نهایت، در مرحله سوم، هر کدام از ماکروهای تعریف شده در کد، با مقدارش جایگزین میشود. خروجی این گام را میتوان با کمک دستور زیر دید
razian@hp:~/sample$ gcc -E sample.c > sample.i
razian@hp:~/sample$ cat sample.i
میتونیم خروجی این گام را در پروندهی به نام sample.i قرار دهیم.
۳- ترجمه (Compiling)
گام بعدی، ترجمه پرونده sample.i به یک پرونده خروجی ترجمه شده میانی با نام sample.s است. این پرونده حاول دستوراتی در سطح اسمبلی است. به عبارت دیگر، خروجی این مرحله دستورات اسمبلی است (اغلب به اختصار asm) که اسمبلر یا سرهمساز (اسمبلر) میتواند آن را بفهمد. برای مشاهده این خروجی دستور زیر را میتوانید اجرا نمایید.
razian@hp:~/sample$ gcc -S sample.c
خروجی این دستور پروندهی با نام sample.s است که محتویات آن به صورت زیر است.
۴- سرهمسازی (Assembling)
در این گام، با کمک سرهمساز، پرونده sample.s به عنوان ورودی دریافت میشود و پرونده sample.o که حاوی کد ماشینفهم است تولید میشود. این پرونده، شامل دستورات در سطح ماشین است.
البته اینگونه نیست که همه کامپایلرها مرحله تبدیل به اسمبلی و بعد اسمبلی به زبان ماشین را انجام دهند؛ مثلاً، کامپایلرهای MS مستقیماً کد ماشین تولید می کنند، هر چند امکان تولید خروجی اسمبلی را هم دارند. جالب است بدانید برخی از کامپایلرها، کدهای زبان سطح بالا دیگری را به عنوان خروجی تولید می کنند - به عنوان مثال، cfront، اولین کامپایلر C++، زبان C را به عنوان خروجی تولید می کند که سپس توسط یک کامپایلر C به کد ماشین کامپایل می شود. دستور زیر پرونده اسمبلی را به پرونده ماشینفهم (زبان ماشین) تبدیل میکند
razian@hp:~/sample$ gcc -c sample.s
خروجی این دستور یک پرونده sample.o است که محتویات آن به صورت زیر است.
۵- پیوندسازی (Linking)
به بیان فنی، در مرحله ترجمه، مترجم به جای توابعی که فراخوانی شدهاند اما پیادهسازی نشدهاند یک نشانه قرار میدهد. در گام پیوند، پیوند دهنده، نام توابع را دریافت و در میان پروندههای ماشینفهم موجود (Object files) به دنبال پیادهسازی آن توابع میگردد و پس از یافتن، پیادهسازی آنها را در محل نشانه، جایگذاری میکند. خروجی گام پیوندسازی، یک پرونده قابل اجرا (Executable file) است. برای ایجاد این پرونده دستور زیر را اجرا نمایید (در این مثال، پرونده خروجی، sample نام دارد).
razian@hp:~/sample$ gcc sample.s -o sample
razian@hp:~/sample$ ./sample
The value of PI is defined as 3.141590
razian@hp:~/sample$
۶- بارگذاری در حافظه اصلی (Loading)
مرحله بعدی، انتقال پرونده اجرایی ایجاد شده از درایو به حافظه اصلی جهت انتقال به واحد پردازنده مرکزی (CPU) است.
۷- اجرا (Executing)
مرحله آخر، اجرای پرونده اجرایی توسط واحد محاسبه و منطق (ALU) است.
برای اینکه به صورت یکجا تمامی پروندههای میانی تولید شده را ببینید میتوانید از دستور زیر استفاده کنید
razian@hp:~/sample$ gcc --save-temps sample.c -o sample