
הטקסט המלא של הדקות הראשונות בהרצאה «אוגרים במעבד - Stack & Register» בקורס הווידאו של PracticU – כתוביות בעברית עם זמן התחלה לכל פסקה. כך תוכלו לקרוא ולחפש את הנושאים לפני שמתחילים ללמוד.
שלום לכולם, ברוכים הבאים להרצאה על סטאק. אנחנו נראה מה קורה בתוך הסטאק הזה ונבין איפה החולשה שלו ולמה דרכו אפשר לפרוץ למחשב. אז בואו נתחיל מזה שנעשה חזרה קצרה.
ברגע שאנחנו עושים דאבל קליק על התוכנית, היא מקבלת הקצאת זיכרון, כל זה זיכרון שהיא קיבלה, כאשר בכתובות הנמוכות יש לה את החלק שנקרא טקסט, שאני מזכיר לכם שטקסט הוא בכלל לא טקסט, זה קוד סגמנט, זה קוד, זה הפקודות שיש לו.
משום מה קראו לו טקסט סגמנט או טקסט וזה למעשה מה שיושב בתוך הקובץ אקזה זה הפקודות שיושבות בקובץ אקזה שהן מועתקות לזיכרון הזה לכתובות הנמוכות ומשם המעבד מתחיל לבצע אותם והאזור הזה בזיכרון הוא לרוב במצב read only ובגודל קבוע אחריו הולך להיות החלק של הדאטה של הנתונים אבל לא סתם נתונים נתונים שהם גלובליים שכולם יכולים לראות אותם
כל החלקים של התוכנה נגישים לנתון הזה, ויש לו ערך, לדוגמה, נתון שהוא val, זה השם שלו, שם של המשתנה val, והוא ישר, המשתנה הזה מקבל ערך 3. זאת אומרת, משתנה מסוג בשם val, value, כאילו לא משנה, זה השם שלו, יכלו גם לקרוא לו יוני או יוסי, או אייג' או כל שם שתרצו.
אז המשתנה הזה ישר קיבל ערך. במעמד ההכרזה, מה זה אומר? הכרזה הכריזו שהוא הולך להיות מסוג אינטג'ר. אינטג'ר, אני מזכיר לכם זה מספרים בגודל של 32 סיביות שזה אומר 4 מיליארד מספרים אפשר להכניס ב-32 סיביות אבל אנחנו לא מתחילים מ-0 עד 4 מיליארד אנחנו מתחילים מ-2 מיליארד עד פלוס 2 מיליארד
זה האינטג'ר מי שלא צריך כל כך הרבה כתובות אז הוא יכול להסתפק בסוגי נתונים אחרים אבל העיקר שזה יהיה גודל קבוע גודל קבוע תמיד זה יהיה 32 סיביות ויהיה לו ישר ערך במעמד ההכרזה ואז הוא ייכנס לדאטה.
אם לא יהיה לו ערך במעמד ההכרזה כמו פה אינטג'ר בשם I משתנה מסוג I אז המשתנה הזה הוא יהיה BSS ייכנס ל-BSSS. הדבר האחרון שאני רוצה להסביר לכם זה על היפ.
היפ זה הקצה דינמית שאנחנו מקצים עם פקודת מאלוק הקצה דינמית ואנחנו לא יודעים כמה כתובות נצטרך נניח שיש לנו פה רשימה של כל התלמידים בכיתה ואנחנו לא יודעים כמה תלמידים יהיו בכיתה בהרצאה הנוכחית, אז כל פעם מזינים עוד תלמיד והרשימה גדלה דינמית.
והתכנסנו כאן בשביל Stack, נכון? אז בואו נדבר מה זה Stack. Stack זה למעשה זיכרון מקומי, כמו של משתנים האלו. שימו לב, זה הכל משתנים, אין פה קוד. קוד רק בטקסט.
משתנים, אבל לא של כל הפונקציה כמו הדאטה הזה של כל התוכנית, אלא משתנים אך ורק של פונקציה נוכחית. כדי להבין לעומק איך הסטאק הזה עובד אנחנו צריכים להבין גם מה זה רגיסטרים בואו נעבור למכונה וירטואלית ואני רוצה להפעיל לכם תכלס את הדבאגר דבאגר זו תוכנה שמריצה תוכנה אחרת ואחרי כל פקודה היא מקבלת שליטה חזרה אליה אז דבאגר הזה אומר למעבד אחרי כל פקודה בתוכנה
אחרת תחזור אליי אני רוצה לראות מה קורה בזיכרון אז אנחנו יכולים לעשות פה אופן לפתוח בסיסטם ווינדוס סיסטם 32, כל תוכנה שאנחנו רוצים, נניח notepad, אני פותח, אתם יכולים לפתוח כל תוכנה שתרצו.
ואנחנו רואים כאן את כל הפקודות של התוכנה הזאת. מה קורה לנו פה בחלון הזה? אז ככה, אנחנו עכשיו נמצאים ב-view CPU, אנחנו נמצאים ב-CPU, מסתכלים על הזיכרון מנקודת המבט של המעבד, יש לנו כל מיני דברים שהדבאגר יודע להראות.
מה אנחנו רואים? רואים פה את כל הפקודות שזה מה שיושב בזיכרון. יושב שם E8, טה-טה-טה-טה-טה-טה-טה, זה מה שיושב בזיכרון, והפירוש של זה לפי התקן של פקודות x86, הפירוש נניח לקפוץ לתא זיכרון כזה וכזה, שזה למעשה שפת הסמבלר.
אז במקום להתעסק ב-E8, יש תקן ואז הם יודעים לפרש מה לעשות. דרך אגב, אני יכול, שימו לב, אני נמצא עכשיו בכתובת FF1860 בזיכרון של התוכנת Notepad.
אני כרגע הפעלתי אותה וישר עצרתי אותה, אתם רואים, היא בפאוזה. זאת אומרת שברגע שמפעילים אותה, אתם רואים פה החץ הזה, זה להפעיל אותה מחדש, לעשות ריסטארט, עושים ריסטארט, היא נטענת לזיכרון ולפני שתתבצע הפקודה הראשונה היא נכנסת למצב פאוזה.
ואז אם אני רוצה אני יכול להגיד למעבד לבצע רק פקודה אחת, ואחרי כל פקודה הוא חוזר אליי. מה זה אליי? לתוכנת הדבאגר. אז בזיכרון בתא FF1860 יושבת פקודת קול לכתובת כזאת וכזאת, שזה למעשה קריאה לפונקציה.
פונקציה זה מיני תוכנה שעוזרת. לדוגמה, אצלנו באתר יש פונקציה שמה יודעת לעשות? לבדוק האם המנוי בתוקף. זאת אומרת, התוכנה הראשית קוראת לפונקציית עזר, שואלת אותה האם המנוי הזה בתוקף?
אומרת לה כן. אחרי זה התוכנה הראשית קוראת לפונקציה אחרת, האם לבן אדם הזה מותר לראות את הסרט הזה? האם המנוי שלו כולל את הסרט הזה, כן או לא? אם היא אומרת לו כן, היא ממשיכה הלאה.
האם יש לו דפדפן כזה או דפדפן אחר? פונקציית עזר בודקת איזה דפדפן יש לו. האם הדפדפן תקין? זאת אומרת, התוכנה הראשית לרוב קוראת לפונקציות, ופונקציות זה קטעי קוד קטנים שמבצעים משימה מאוד מאוד קטנה.
והנה אנחנו רואים פה אפילו הפקודה הראשונה בנוטפד זה קול לפונקציה מסוימת שנמצאת בתא זיכרון כזה וכזה. אבל מה שמעניין אותי עכשיו זה הרגיסטרים. אתם רואים הרגיסטרים פה בצד ימין?
זה העוזרים הקטנים של המעבד, זה תאי זיכרון קטנים שנמצאים בצמוד למעבד ולמעשה הם העוזרים שלו. והם הכי מהירים, זה זיכרון הכי מהיר כי הוא יושב על המעבד. ומה מעניין?
יש פה כמה רגיסטרים מאוד מאוד מעניינים. הראשון זה EIP. אתם רואים EIP, הוא מצביע על כתובת FF1860, שימו לב מה זה הכתובת הזאת, זאת הכתובת של פקודה הבאה לביצוע.
אתם רואים? הפקודה הבאה לביצוע, איך המעבד יודע איזו פקודה לבצע? יש לו אוגר, תא קטן בזיכרון שצמוד אליו, שתמיד מצביע מה הפקודה הבאה שהמעבד אמור לבצע.
והמעבד אמור לבצע את הפקודה הזאת, ובפקודה הזאת כתוב להפעיל פונקציה שנמצאת בכתובת כזאת וכזאת. למעשה הוא יקפוץ לכתובת הזאת ויבצע אותה. בואו נראה, אני עושה פה למעבד, אני אומר לו step into, תראו, תראו פה למטה, אתם רואים פה, אני עובר כל מיני אופציות, step into, תעשה step אחד, צעד אחד לתוך הפונקציה.
אם אני אעשה פה step over, הוא יבצע את הפונקציה מהר ויחזור לפקודה הבאה, הג'אמפ הזאת. אני לא רוצה שיבצע מהר את כל הפונקציה, הפונקציה הזאת מעניינת אותי, אני רוצה לעשות צעד אחד ולהיכנס לתוך הפונקציה, לא מעניין אותי שאעשה אותה מהר, אני רוצה לראות צד צד.
שימו לב לפה, שזאת הכתובת FF-20C2, ואנחנו היינו ב-860, היינו ב-860, ואנחנו צריכים לקפוץ ל-20C2, והנה קפצנו ל-20C2. אתם רואים, זה באמת קפץ לתא הזיכרון ויבצע את הפקודה הזאת.
מוב להכניס משהו לתוך רגיסטר ECX, אתם רואים? זאת אומרת, זה למעשה מכניס ערכים. טוב, אנחנו לא נלמד עכשיו אסמבלר. מה שמעניין אותי פה ש-20C2, שימו לב, EIP השתנה ל-20C2.
זאת אומרת, זאת פקודה הבאה לביצוע, אוקיי? אם נעשה עוד פקודה, אתם רואים, ECX השתנה, לערך הוא נהיה בצבע אחר. למה הוא השתנה? בגלל שה-ECX הזה קיבל את מה שהיה בתוך תא FF4210.
דרך אגב, מה היה ב-FF4210? אנחנו יכולים לראות פה, פה יש גם דאמפ של זיכרון, צילום של כל הזיכרון, 4420, אתם רואים פה, זה זה, נכון?
FF4210, FF4210. הנה אנחנו רואים שהיה שם D4, אתם רואים? D4 הזה, E3, F0, 11. D4, E3, FF, 11. וזה דרך אגב זמן טוב להראות לכם שהמחשב מאחסן את זה בשיטה הפוכה.
הוא שם בכתובות הנמוכות, אתם רואים? את הספרות הפחות חשובות, 11 הזה, הם בכתובות הנמוכות. אחרי זה הולך F0, זה הכתובות היותר גבוהות.
איך אני יודע? הנה, הכתובות כאן גדלות. אתם רואים 10, 18, 20, הכתובות גדלות. כל אחד זה בית. אז את הבית הכי פחות חשוב הוא שם בתא הכי קטן.
אחרי זה F0, זה הבית הבא. אם אנחנו מסתכלים על זה מנקודת מבט שלנו, זה הולך להיות הפוך. זה נקרא Little Indian. ה-Little Indian זה למעשה תאים בזיכרון, נראים לנו הפוכים.
כי אנחנו קוראים מהנמוך לגבוה, ובגלל זה זה נראה לנו הפוך. אז תראו, 11 פה, זה נכנס לכאן, כי זה הכי פחות חשוב בכתובת הנמוכה.
בכתובת היותר גבוהה זה 0. ואתם רואים, מנקודת מבט של המחשב הוא לא יודע מה המשמעות, זה סתם מספרים. E3, מה זה לדוגמה E? A זה 10, B זה 11, C זה 12, D זה 13, E זה 14, אז E זה מספר 14. ו-3, הנה זה פה, ו-D4, D4 זה כאן.
אנחנו רואים, זה אקסה דאמפ, זה אומר, זה תצוגה של זיכרון באקסה. ופה הוא מנסה להציג את זה גם בקודי אסקי, שזה לא ממש מעניין, כי הפירוש של זה הוא חסר משמעות.
אני גם יכול לעשות פה right-click ולהגיד לו, תציג לי בצורות שונות, נניח של 16 בשורה, שזה לא ישנה כלום, הוא פשוט יציג לי את זה כ-16 בשורה.
אז הנה, בואו תראו. אז יהיה לי באותה כתובת, אותו דבר, רק 16 בתים בשורה. ואז 16 בתים זה קופץ ל-20, כי זה 10, 20, כל 16 זה עוד עשירייה באקסה.
תצוגות שונות של אותו המידע. אני יכול גם להגיד לו, תקשיב, תנסה לפרש את זה פה בצד ימין, לא באסקי, אלא ביוניקוד. סתם אפשר גם, כן, אפשר להגיד לא באסקי, בכל מיני דברים איך לפרש את הזיכרון הזה כאן בצד.
אני יכול להגיד לו, תפרש את זה בכל מיני צורות, לדוגמה, לפי תקן של אקזה. נניח שזה תקן של אקזה. טוב, אני מקווה שהבנתם שזה הזיכרון ויש לו תצוגות שונות, זה גם זיכרון וזה הפירוש שלו לפי שפת הסמבלר.
הנה דיזאסמבל, אני יכול לעשות ככה דיזאסמבל, ואז הוא מפרש את זה לפי אסמבלר. אתם רואים, הוא לא יודע באמת מה זה כל תא, אז הוא מנסה לעשות את זה לפי פקודות של אסמבלר.
אני יכול לעשות לו, תפרש את זה כאילו זה אקזה, ואז הוא מנסה לפרש את זה כאקזה, לא שזה מצליח לו, או שתפרש את זה כ-8 בייטס, כל 8 בתים תעבור שורה, או כל 16 בתים תעבור שורה.
בקיצור, איך לפרש את המספרים האלו בזיכרון, לפי איזה תא כן, ואנחנו ממש יכולים לראות. טוב, אז בואו נחזור לזה שלנו. אז מה רציתי להראות לכם כאן?
רציתי להראות לכם כאן, בואו נתחיל מההתחלה, נעשה פה ריסטארט. זה הכפתור שעושה ריסטארט, הנה הוא טען הכל לזיכרון, ומחכה לי לבצע את הפקודה הראשונה.
אז אנחנו כרגע הולכים לעשות פקודה ראשונה, עוד פעם הפעלנו את ה- notepad עוד פעם, זה נקרא הנדסה לאחור דרך אגב, כשלוקחים קובץ בשפת מכונה ומנסים להבין מה קורה. דרך הכלי הזה של דבאגר מנסים להבין איך עובד המחשב.
אז אנחנו רואים פה את כל תאי הזיכרון ואנחנו רואים פה את הכלים, את הרגיסטרים, את העוזרים של המעבד, את תאי הזיכרון הקטנים שנמצאים צמוד למעבד והוא כל הזמן משתמש בהם, לשם הוא שם את תוצאות החישוב שלו, כתובות של איזה פקודה לבצע.
דרך אגב, פה אחרי זה יש לו פלאגים, לדוגמה, האם מספר יצא מהגבולות שלו, האם יצא תוצאת 0, תוצאה של השוואה כלשהי זה פלאג עם דגלים שהוא יודע להדליק במקרה שלדוגמה התוצאה חורגת מגבולות המותר או שהתוצאה יוצאת 0 בפעולות מתמטיות טוב בואו נתמקד במה שרציתי רציתי להראות לכם את ה-EAP שמצביע על הכתובת הזאת ושימו לב עוד משהו
מעניין אם אני אעשה פה דאבל קליק אני יכול להגיד לו תקשיב אל תראה לי כתובת תראה לי כאילו כל העולם שלי בסיס הדולר זה הבסיס אז כאילו הבסיס הזה יחסית אליו אז פלוס 5 פלוס A A זה 10 פלוס B פלוס C כאילו תראה לי את הכתובות ביחס לבסיס
אני יכול גם להגיד לו שהבסיס מתחיל למעלה ואם הבסיס מתחיל למעלה אז אני נמצא בפלוס 2 ואני יכול להגיד לו שהבסיס מתחיל כאן או כאן או כאן למה הבסיס הזה כזה חשוב? כי הרבה פעמים לא נוח לנו לכתוב את הכתובת אנחנו יכולים להכריז על משהו כבסיס ויחסית אליו לזוז תכף אנחנו נראה את זה הדבר האחרון שאני רוצה להראות לכם, מבחינת המשתנים, מבחינת הרגיסטרים, זה ESP ו-EBP.
מה זה EBP? זה ההתחלה של הפונקציה הנוכחית, של הסטאק הנוכחי. ו-ESP זה הסוף שלו. זאת אומרת, זה הלמעלה והלמטה של הסטאק, של המשתנים המקומיים של הפונקציה הזאת, באזור זיכרון איפה הזיכרון של הפונקציה מתחיל ונגמר.
אז תסתכלו, אנחנו עושים עכשיו call ונכנסים לפונקציה כבר בפקודה הראשונה. שימו לב מה יקרה ל-ESP פה. אתם רואים ESP פה עכשיו? בואו נגדיל אותו טיפה, הכתב כאן מאוד מאוד קטן.
Eperions, פונט, נעשה כזה דבר, הנה. אנחנו רואים ESP פה זה 53-FEDC, הנה זה זה. זה כאן למטה בצד ימין, אנחנו רואים את הסטאק.
בואו נעשה גם כאן כתב יותר גדול, פונט. אתם רואים? זאת אומרת, העוזר הזה, הרגיסטר ESP, מצביע על 53-FEDC, זה זה וברגע שנעשה call תראו מה יקרה לכתובת הזאת תזכרו שזה fedc תסתכלו גם דרך אגב שזה נהיה יותר קטן ופה הוא נהיה יותר גדול הוא כלפי מעלה יזוז אנחנו קוראים לפונקציה הופה אתם זוכרים שהיינו ב-fedc וקפצנו עכשיו ל-fed8
הוא מצביע לסטאק הזה הנה היינו פה ב-fedc והוספנו פה נתון לכאן אתם רואים הסטאק ירד למטה והוסיף נתון מה מה שהכי מעניין זה מה נכנס לנו לתא הזיכרון הקודם, נכון?
הוא היה ב-FEDC, מה הוא הכניס פה? 1865. מה זה 1865? מוכר לכם? בואו נפעיל את כל התוכנה מההתחלה, נעשה פה ריסטארט לנוטפד.