איך עובד מחשב? (מבוא למדעי המחשב שיעור ב)
איך בעצם מחשב עובד? ומה זה שפת תכנות

זה השיעור השני מתוך פרקי המבוא לקורס שהעברתי בתחילת 2021.
השיעור הראשון היה על היסטוריה של המחשוב, והגדרה של מה זה בכלל מחשב.
אני ממליץ לקרוא אותו קודם.
מה זה בכלל מחשב? [מבוא למדעי המחשב שיעור א]
כמו שראינו לכל מחשב יש מעבד וזיכרון.
תפקידו של המעבד
תפקידו של המעבד הוא, ובכן, לעבד מידע. המעבד הוא הליבה של המחשב, והוא הכוח החישובי שלו.
פעולות המעבד הן
לקרוא נתונים מהזיכרון
לבצע עליהם מניפולציה (שינוי, עיבוד)
לשמור את הנתונים החדשים בזיכרון
כדי לדעת אילו נתונים לקרוא ומה המניפולציה שצריכה להתבצע על הנתונים, המעבד מקבל סט של פקודות שאנחנו קוראים להם תוכנה.
המעבד קורא את הפקודות ומבצע אותן אחת אחרי השניה.
שפה בינארית
המעבד לא יודע ״לדבר״, גם לא לקרוא.
הדבר היחיד שהמעבד יודע זה לקרוא מספרים, ליתר דיוק מספרים בינארים. כלומר 0 או 1.
אלו שני התווים היחידים שהמעבד מכיר.
0 זה כשאין חשמל, ו1 זה כשיש חשמל.
יחידת העיבוד המרכזית (הCPU), מקבלת אותות חשמליים כאלה, ומפענחת אותם כדי לדעת מה לעשות.
אבל איך אפשר לייצג מספרים מורכבים יותר באמצעות שתי ספרות בלבד?
למעשה, זה לא כל כך מסובך, אתם לא שואלים איך אפשר לייצג מספרים מורכבים באמצעות ספרות מ0 ל9, נכון?
זה נראה לנו ברור שאפשר להרכיב כל מספר רק באמצעות אותן 10 ספרות. שיטת הספרות שלנו מכונה השיטה העשרונית או דצימלית.
זה עובד באותה מידה גם בשפה הבינארית (בינארי = 2, כלומר שפה שיש בה רק שתי ספרות).
חישוב דצימלי
אנחנו יודעים שבדצימלית המיקום של הספרות משפיע על המספר.
01 זה אחד, אבל 10 זה עשר.
למה? כי המיקום של הספרה מלמד בכמה אנחנו מכפילים אותה.
אם אנחנו רואים את המספר הזה 120
אנחנו לוקחים את הספרה הראשונה 0
ומכפילים אותה ב10 בחזקת 0 (=10)
קיבלנו 0
לוקחים את הספרה השניה 2
ומכפילים אותה ב10 בחזקת 1 (=10)
קיבלנו 20
ואז אנחנו לוקחים את הספרה השלישית 1
ומכפילים אותה ב10 בחזקת 2 (=100)
קיבלנו 100
100 + 20 + 0 שווה ל1 מאות, 2 עשרות ו0 יחידות, שהן מאה ועשרים יחידות.
חישוב בינארי
בינארי עובד בדיוק באותה צורה, רק שהפעם במקום להעלות בחזקה של 10, אנחנו מעלים בחזקת 2.
ניקח את המספר הבינארי 00000101.
אנחנו לוקחים את הספרה הראשונה 1
ומכפילים אותה ב2 בחזקת 0 (=1)
קיבלנו 1
לוקחים את הספרה השניה 0
ומכפילים אותה ב2 בחזקת 1 (=2)
קיבלנו 0
ואז אנחנו לוקחים את הספרה השלישית 1
ומכפילים אותה ב2 בחזקת 2 (=4)
קיבלנו 4
1 + 0 + 4 שווה ל5 יחידות בספירה הדצימלית.
(יש הסבר מצוין בWikiHow)
איך זה מיתרגם לפקודות?
טוב, אל תברחו עדיין, אנחנו כמובן לא כותבים בבינארי.
אבל חשוב שנבין איך זה עובד מבחינת המעבד.
המעבד אמרנו קורא את הפקודות מהתוכנה. לכל מעבד יש פקודות שמיוצגות על ידי מספרים בינארים מסויימים. הפקודות האלה נקראות Instruction set.
התוכנה נשמרת בזיכרון.
המעבד קורא פקודה אחת מהזיכרון, מעביר את ההוראה ליחידות העיבוד שלו, ואת התוצאה שומר בזיכרון.
כך הוא ממשיך עד שהוא מסיים לקרוא את כל פקודות התוכנה.
ביטים
אמרנו שמחשבים קוראים רק שפה בינארית.
ואמרנו שבינארית אלו ספרות שאפשר ליצור מהם מספרים.
כדי לפשט, משתמשים תמיד בגודל קבוע של מספר בינארי.
כל מספר בינארי מורכב תמיד מ8 ספרות.
למשל כדי לכתוב 0
נכתוב 00000000
וכדי לכתוב 1
נכתוב 00000001
ספרות בינאריות (0 או 1) נקראות ביט. ומספר בינארי (שמונה ספרות שמרכיבות מספר) נקרא בייט (לפי האקדמיה כותבים בית).
לפעמים מקובל להתייחס לזה כאל אותיות ומילים, שזה כמובן דרך אחרת להגיד ספרות ומספרים.
כשאנחנו מדברים על זיכרון של מחשב, אנחנו מודדים אותו בבייטים. כלומר בכמה מספרים הוא יכול לאגור.
היחידה הקטנה ביותר היא בייט כמובן.
קילובייט הוא 1024 בייטים.
מגהבייט או בקיצור מגה הוא 1024 קילובייט.
ג׳יגה הוא 1024 מגהבייט.
וכן על זה הדרך.
שימו לב שזה 1024 ולא 1000. זה מכיון שהמכפלות של בינארי שונות מהמכפלות של דצימלי.
בדצימלי אנחנו מעלים בחזקת עשר. לכן 1 כפול 10 בחזקת 3 הוא 1000.
בבינארי אנחנו מעלים בחזקת 2. ו1 כפול 2 בחזקת 10 זה 1024.
אסמבלי
טוב, אבל ברור לכולנו שלא הגיוני לכתוב ככה. אף אחד לא באמת כותב בבינארית. כלומר יש משוגעים כאלה, אבל אפילו הם מעטים.
כדי לכתוב פקודות למעבד, הומצאה שפה שנקראה אסמבלי.
את ההמצאה נהוג לייחס לקת׳לין בות׳ מאוניברסיטת לונדון משנת 1947, שלאחר מכן צירפה אליה את בעלה אנדרו, את המתמטיקאי ג׳ון פון ניומן (אחד המוחות הגדולים במדעי המחשב) והרמן גולדשטיין.
אסמבלי זו לא באמת שפה. לכל מעבד יש אסמבלי מעט שונה.
אסמבלי זה פשוט קוד מסוים שיצרנית מעבד מפרסמת למפתחים שרוצים לכתוב הוראות (instruction set) למעבדים שלה. המעבד יודע לקרוא את הקוד הזה ולתרגם אותו לבינארית.
יופיעו בו דברים כמו
גש לכתובת זו בזיכרון,
קרא את הכתוב בה,
השווה מול מחרוזת זו,
אם ההשוואה צלחה גש לכתובת אחרת בזיכרון ועשה את ההוראה הכתובה בה,
אחרת גש לכתובת שונה בזיכרון ועשה את הכתוב בה.
מדהים לחשוב על זה, אבל כך בדיוק כתבו תוכנות מדהימות כמו למשל משימת אפולו 11 להנחתת אדם על הירח.
עם הזמן אסמבלי עבר יותר ויותר אבסטרקציה (הפשטה), יצרניות כתבו אסמבלי שיותר קל לכתיבה, שמאפשר כתיבה של תנאים מורכבים יותר ועוד.
הומצא גם קוד שמאפשר כתיבת טקסט, הוא מכונה ASCII.
וכך למשל אם מישהו כתב באסמבלי STX המעבד ידע לתרגם את זה ל00000010 ולהבין שהכוונה היא שהבייט הבא יכיל טקסט.
אז היה אפשר לשלוח למשל ABC והמעבד היה מתרגם ושומר בזיכרון בתור הבייטים
01000001 (A)
01000010 (B)
01000011 (C)
בדרך הזו היה ניתן לכתוב מילים ממש כקלט וכפלט ולא רק מספרים.
שפות עיליות
עד כמה שזה נחמד ומתקדם, זה עדיין דורש כתיבה מאוד סיזיפית.
הקוד מאוד ארוך, כל דבר צריך להיאמר מפורשות ובצורה מאוד ברורה. ואם טעית אפילו בתו אחד היה נוצר לך באג, שסיכוי טוב שהיית מגלה רק אחרי שכבר הרצת את הקוד על המכונה.
ובואו נזכור שבאותה תקופה לא כתבו קוד במחשבים, אלא בסוג של מכונות כתיבה שהיו מדפיסות על כרטיס מיוחד שהמחשב ידע לקרוא ממנו את ההוראות ולטעון למעבד.
אם היה צריך לתקן היה צריך להעביר את הכרטיס במכונה אחרת לצורך תיקון ואז לחזור על הפעולה.
אז אפשר להבין שמדענים דגולים כמו גרייס הופר למשל חלמו על יצירת שפה ״עילית״, כלומר כזו שלא מכירה את הקוד של המכונה.
שפה שאני אומר לה אני רוצה לשמור את המחרוזת הזו, ואני לא ממש מתעניין באיזה תא בזיכרון, והיא יודעת לשמור אותו שם לבד, ואחר כך גם לחזור ולקרוא אותו מהתא הנכון, למשל.
הרעיונות שלה הובילו ליצירה של שפה שתשלוט שליטה כמעט מוחלטת על מחשבים ותוכנות לעסקים במשך כמה עשורים, הלא היא שפת COBOL המפורסמת.
אבל עוד לפני קובול, הגיעה FORTRAN.
פורטרן
פורטרן הומצאה על ידי ג׳ון באקוס מIBM. הוא היה מתוסכל מכח האדם שהתבזבז על טיפול בבאגים ושאף ליצור שפה שתהיה קלה לכתיבה, ודומה כמה שאפשר לשפה אנושית.
IBM השתכנעה שיש פה פוטנציאל, ואיפשרה לבאקוס להקין צוות פיתוח שיעבוד על כתיבת השפה הזו.
באקוס והצוות שלו עבדו קשה מאוד, הם פיתחו קומפיילר או מהדר בעברית.
תוכנה שיודעת לקרוא את שפת FORTRAN ולהדר או לתרגם את מה שנכתב שם לשפת מכונה - לאסמבלי.
התוצאות היו לא פחות ממדהימות.
הקומפיילר של באקוס עשה עבודה מרשימה מאוד. ונאס״א אפילו השתמשה בשפה הזו כדי לכתוב את החישובים המורכבים שנדרשו לצורך הפעלת תכנית הנחיתה על הירח.
פורטביליות
אחד הדברים החשובים שהיו חסרים עדיין בפורטרן, היא היכולת לכתוב את אותו קוד ולהריץ אותו על מעבדים שונים.
פורטרן, מן הסתם רצה על מעבדים שמכרה IBM, אבל אפילו הם לא תמיד היו תואמים. הרבה פעמים מצא את עצמו המתכנת נאלץ לכתוב קוד שמותאם למעבד ספציפי, מה שכמובן גורר אחריו גם עוד באגים.
הניסיון הראשון לייצר סטנדריזציה, הייתה COBOL. שפה שפותחה בידי מחלקת ההגנה של ארה״ב.
בפיתוח השפה השתתפו לא רק נציגי הממשלה, אלא גם נציגים מ6 חברות מסחריות. המאמץ השתלם. קובול הייתה כתובה כולה אנגלית פשוטה.
כל פקודה, הייתה כתובה באנגלית מובנת, ומעבדים שרצו לתמוך בה היו צריכים להתאים קומפיילר (מהדר) שיתאים לInstruction set שלהם, אבל המתכנתת לא הייתה צריכה לשנות שום דבר בקוד השפה.
הקוד היה כל כך יפה וקריא ביחס למה שהכירו עד אז, שמדען מחשב בשם אדסחר דייקסטרה, טען ש״השימוש בקובול גורם לנכות של המחשבה; לפיכך על הוראת השפה להיחשב לעבירה פלילית״. כן, עד כדי כך.
C
ב1959 דניס ריצ׳י ממעבדות בל, התחיל לפתח את שפת C, המהפכה הבאה בעולם התכנות.
הוא פיתח את השפה על גבי סביבת UNIX במטרה לכתוב שפה שתאפשר למעבדות בל לייצר מערכת הפעלה.
C הציגה לעולם כמה חשיבות חדישות ומקוריות, כמו השימוש בטיפוסי משתנים, struct - הגרסה המוקדמת ביותר של object oriented programming, רשימות, מערכים ועוד.
מלבד זה שמדובר בשפה מאוד קלה לכתיבה וזורמת, היא גם ממש ממש יעילה. למרות כל שכבות האבסטרקציה שלה.
למעשה הרבה שפות תכנות מודרניות (פייתון למשל) לא מתקמפלות לאסמבלי, אלא רק לC.
סי ייצגה פרדיגמה כל כך חדישה בעולם התכנות שעשרות שפות שבאו אחריה נחשבות להשפעה ישירה שלה, ומכונות ״שפות C״.
בין היתר ניתן למנות את c++, java, c#, perl, objective-c, PHP ועוד.
Java
בתחילת שנות ה90 Sun Microsystems, פיתחה שפת תכנות לממירי טלוויזיה.
את השפה פיתח ראיין גוסלינג, והיא הושפעה רבות מc ומc++.
ההבטחה של ג׳אווה הייתה מהפכנית, ג׳אווה יצאה תחת הסיסמה ״Write once, Run everywhere״.
כלומר, זה לא משנה על מה תריץ ווינדוס, מק, לינוקס, אינטל, AMD, snapdragon. לא משנה. התוכנה תרוץ אותה דבר על כל מכשיר שתומך ג׳אווה.
איך זה עובד?
קוד ג׳אווה לא מתקמפל ישירות לאסמבלי או לc. הוא מתקמפל לקוד ביניים שנקרא bytecode.
את התוכנה מריצים על מחשב שבו מותקנת jre, סביבת הריצה של java.
הסביבה הזאת יודעת לקרוא את הבייטקוד ולהריץ אותו בסביבה וירטואלית שמכונה JVM ולפענח אותו בהתאם לתצורה של המחשב שבו הוא רץ.
בדרך הזו יכול המפתח לכתוב את הקוד רק פעם אחת, לקמפל, ולהריץ על כל מחשב שבו יש jre.
סיכום
אז זו הייתה סקירה של התפתחות עולם התוכנה.
אחרי שאתם מכירים מה זו שפת תכנות, הגיע הזמן לדבר על קוטלין, השפה שבה מתכנתים לאנדרואיד.
ובינתיים, כמו תמיד, אשמח לשמוע מכם מה אתם חושבים.
כתבו לי בתגובות!

