מ C לבינארית: פותחים את הקופסא השחורה של המהדר
תהליך ההידור: מצד אחד כולנו יודעים מה הוא, אך מצד שני הוא לרוב קופסה שחורה שמסתתרת מאחורי כפתור בIDE האהוב עלינו או פקודת BASH יחידה. אז איך בעצם קורה התהליך? איך הופך טקסט בשפת תכנות, שלרוב קרובה לאנגלית, לקוד מכונה בינארי?
במאמר זה נעבור על שלבי ההידור במובן הרחב של המילה (מיד נבין מה הכוונה), ונראה טעימה קטנה מהתהליך המסובך הזה.
אנחנו נשתמש בשפת C. רמתה הנמוכה משמעותה שתהליך ההידור יחסית קצר ופשוט. אם C אינה בחירת לבכם, אל דאגה, עקרונות התהליך דומים בכל שפה.
נעבוד עם הקטע example.c:
קטע הקוד הזה כמובן לא יתהדר תחת תנאים רגילים מאחר והוא לא כולל פונקציית main, אך הוא מושלם למטרות שלנו.
המרכיב הראשון בתהליך הוא ה - Preprocessor, שתפקידו להכין את הקובץ להידור. הוראות המתחילות ב - #, כגון define ו - include, הן הוראות PP. נשתמש בדגל E כדי לעצור את תהליך ההידור לאחר פעולות אלו, וזו התוצאה:
במקרה הזה, ההערות נמחקו, והמופע של של הביטוי המוגדר שלנו הוחלף. אם היינו כוללים עוד קבצים בעזרת הוראת include, היינו רואים את הקוד מהם "מודבק" בראש הקובץ.
השלב הבא הוא שלב ההידור במובן הצר של המילה, כלומר המרה של הקוד משפת C לשפת Assembly. זהו תהליך מורכב מאוד בפני עצמו, וההסבר בהתאם ידרוש מאמר נפרד וארוך הרבה יותר. בכל זאת, יש הרבה ללמוד מהתוצאה:
מי שלא מכיר קוד Assembly יתקשה להבין את החלק התחתון, שכולל את הלוגיקה של הקוד שלנו, אך שימו לב להוראת ADD שמוסיפה 1, כמו בפונקציה שלנו. בשלב הזה המהדר כבר בצע את כל האופטימיזציה הדרושה וקוד ה - C הומר, בתקווה, לקוד Assembly קרוב לאידיאלי על פי הארכיטקטורה שבה אנו עובדים.
כעת נאסף את את קבצי ה - Assembly (אחד, במקרה שלנו) לקבצי object בינארים. זו כבר אינה המרה מסובכת, שפת Assembly מתרגמת כמעט ישירות להוראות מכונה. ניתן לראות את התוצאות למטה, אבל כמובן שאין מה להבין מהן:
השלב האחרון יהיה לקשר את כל קבצי ה - object וליצור מהם קובץ הרצה סופי, אבל כפי שציינתי קודם החוסר בפונקציית main לא יאפשר את זה.
נסכם בקצרה את השלבים שעברנו:
- ה - Preprocessor מכין את הקבצים להידור, מבצע החלפת טקסט לפי הגדרות define ומעתיק קוד לקבצים על פי הוראות include
- הקובץ המוכן מהודר לשפת Assembly
- קובץ ה - Assembly מאוסף להוראות מכונה בקובץ object
- קבצי ה - object מקושרים לקובץ ההרצה הבינארי הסופי
תהליך ההידור של שפת C הוא יחסית ישיר ופשוט. C# למשל מהודרת לשפת ביניים בשם Common Runtime Language ורק אז לקוד מכונה, וjava רצה בתוך Java Runtime Environment, אך בסופו של דבר העקרונות הם אותם עקרונות. קוד בשפת תכנות מאורגן לצורה שמהדר יכול לעבוד אתה, בין אם זה קובץ אחד שכולל את כל הקוד או סדרה של תיקיות שיחד מרכיבות חבילה, ואז הקוד בתהליך כזה או אחר מתורגם להוראות מכונה.
אם מאמר זה עניין אתכם, אני ממליץ להמשיך לקריאה נוספת בנושא הידור במובן הצר, כלומר פרסור של קובץ טקסט, "הבנה" שלו, ויצירת קוד Assembly בהתאם.