לראות את תוכן ה-Flash בעיניים

לפני – ריבונו של עולם, שנה וחודש! – הבטחתי להסתכל לתוך זיכרון ה-Flash של מיקרו-בקר מצוי כדי למדוד את מידת האקראיות של קוד המכונה שנצרב עליו, ולבדוק אם אפשר להשתמש בו כמקור למספרים פסודו-אקראיים. הפוסט הזה לא יסגור את המעגל לגמרי, אבל כן ייתן לנו כמה כלים מעניינים…

256 גוונים של אפור: ייצוג ויזואלי של זיכרון ה-Flash בארדואינו
256 גוונים של אפור: ייצוג ויזואלי של זיכרון ה-Flash בארדואינו

התמונה למעלה מורכבת מבייטים אמתיים ששלפתי מזיכרון ה-Flash (איפה שקוד התוכנה מאוחסן) של ארדואינו Duemilanove פעיל. פרט למסגרת הכחולה שהתווספה בדיעבד, כל ריבוע קטן (2×2 פיקסלים על המסך, כשהתמונה בגודל מלא) הוא בייט יחיד, לפי סדר הבייטים בזיכרון, משמאל לימין ומלמעלה למטה. ערכי הבייטים מיוצגים על ידי גוון הפיקסל, החל משחור ל-0 ועד לבן ל-255.

את השליפה ביצעתי בעזרת המאקרו pgm_read_byte_near שמוגדר בקומפיילר, ושמסוגל לקרוא בייט מכל כתובת שהיא ב-Flash. הנה קוד הארדואינו המלא:

void setup() {
  Serial.begin(9600);
  while (!Serial.available());
}

void loop() {

  uint16_t x;
  byte b;

  for (x = 0; x < 32768; ++x) {
    b = pgm_read_byte_near(x);
    Serial.write(b);
  }
  while (1);

}

הוא מחכה לקלט כלשהו בסריאל, שופך דרכו את כל 32,768 הבייטים שבזכרון ה-Flash של ה-ATmega328P, ונכנס ללולאה אינסופית כדי להשתתק.

את הקריאה של המידע והצגתו בצורה גרפית – כולל החלוקה השרירותית לשורות באורך קבוע – ביצעתי בעזרת סביבת הפיתוח החמודה והנוחה-בדיוק-לדברים-כאלה BASIC256. כך זה נראה בשטח (לחצו להגדלה):

קוד ה-BASIC והפלט בסביבת הפיתוח
קוד ה-BASIC והפלט בסביבת הפיתוח

אז מה הייצוג הוויזואלי הזה אומר לנו?

קודם כל, אנחנו רואים שהקוד מחולק, בצורה שאינה משתמעת לשתי פנים, לשני חלקים עיקריים נפרדים, שביניהם חלל גדול מלא בערכי 255 רצופים. ניחשתם נכון – החלק התחתון הוא ה-Bootloader של הארדואינו, שממוקם בכתובות הגבוהות בזיכרון.

ממצא פחות בולט במבט ראשון, אך מעניין עוד יותר, הוא הגודל של החלק העליון. אם תקמפלו את קוד הארדואינו שלמעלה, סביבת הפיתוח תגיד לכם שהוא תופס 1706 בייטים, אבל אפילו בהערכה גסה ביותר רואים שהחלק העליון תופס הרבה יותר מזה – למעשה, למעלה מ-12K בייטים. הקוד העודף אינו אלא שיירים מתוכנות קודמות שנצרבו על המיקרו-בקר: סביבת הפיתוח של ארדואינו לא טורחת למחוק את כל ה-Flash בעת צריבה של קוד חדש. מה שכן אפשר לראות הוא רווח קטן יחסית בין הקוד הנוכחי לבין השאריות מקודם, ונדרש תחקיר נוסף כדי לגלות מהו – האם "טווח ביטחון" שמתווסף אוטומטית, או אזור שמוקדש לאתחול ערכי משתנים, או משהו אחר.

עד כמה הקוד הזה קרוב לאקראיות? בואו נסתכל תחילה על התפלגות ערכי הבייטים. גזרתי ברמת דיוק סבירה את ה"קוד" מהתמונה ונתתי לתוכנת הציור לבדוק מה הפרופורציה של כל ערך:

היסטוגרמה של התפלגות ערכי הבייטים
היסטוגרמה של התפלגות ערכי הבייטים

פיזור ערכי הבייטים, שהם הפקודות השונות בשפת המכונה, לחלוטין לא אחיד. גם אם נתעלם מ-255 החריג (כ-60% מהזיכרון, ושימו לב שההיסטוגרמה נקטעת בחלקה העליון), קל לראות שערכים מסוימים כמעט אינם מופיעים כלל, ואילו אחרים נפוצים מאד. כבר עכשיו, עוד לפני שדיברנו על דפוסים ניתנים-לחיזוי של פקודות, ברור שחילוץ ערכים פסודו-אקראיים מהקוד הגולמי ידרוש מספר חישובים נוספים, מהם רצינו להימנע מלכתחילה. כך שלא מצאנו פתרון קסם, ומצד שני, אקראיות חלשה שכזו אולי כן תספיק למשחקים ולאפקטים גרפיים מסוימים.

להרשמה
הודע לי על
4 Comments
מהכי חדשה
מהכי ישנה לפי הצבעות
Inline Feedbacks
הראה את כל התגובות

אני חושב שזו ויזואליזציה ממש מגניבה של המידע הזה. אני לא חושב שראיתי פעם את המידע בשבב מוצג בכזו דרך מעניינת. בעיני אגב כדאי לשים בדיאגרמת עוגה את 5-8 המילים הנפוצות ביותר בקוד ואת השכיחות שלהן.
חשבת לברר מה המשמעות של המילים הנפוצות בשפת המכונה של AVR?

ההימור שלי על הרווח הוא הצורה שבה ממומש זיכרון פלאש. לרוב הוא מגיע ב"עמודים" שצריך למחוק כגוש ואז ניתן לכתוב עליהם מחדש. בטח מחקו עד סוף הגוש ואז כתבו כמה שהיה צורך.