Carmi Merimovich

כרמי מרימוביץ

אתר אישי

רוטינות

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

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

הפקודה הראשונה הינה Jump And Link

jal rd, offset  // jump and link
``
פקודה זו מבצעת את שתי הפעולות הבאות:

rd ← pc + 4 pc ← pc + sext(offset)

המבנה הבינרי של הפקודה הוא כזה:
![jal](jal.png)
ראשית נשים לב ששדה ההיסט הוא ברוחב 20 ביטים.
אותו טריק כמו בפקודות branch
מאפשר לנו לקפוץ $2^{20}$ בתים אחורה
ועד $2^{20}-2$ בתים קדימה.
אם רוצים לבצע קפיצה לא מותנה עם הפקודה הזו ללא תופעות לוואי אזי נבצע:

jal x0, offset

^15.wav^אם נרצה לבצע קפיצה מותנית למרחק ש branch לא מאפשר
אבל jump
כן מאפשר, נאמר
beq x2, x3, 10000   // אי אפשר
אזי נבצע
bne x2, x3, L
jal x0, 10000  

L:

כמובן שנשתמש בתוויות ולא במספרים.

## הפקודה השניה הינה Jump And Link Register

jalr rd, offset(rs1) // jump and link register

פקודה זו מבצעת את שתי הפעולות הבאות:
rd ← pc + 4
pc ← rs1 + sext(offset)
המבנה הבינרי של הפקודה הוא כזה:
![jalr](jalr.png)
ישנן שתי סיבות טובות מאוד לכך שצריך פקודה זו.
ראשית, הקפיצה בפקודה זו אינה מוגבלת במרחק.
זו אינה קפיצה יחסית אלא קפיצה לכתובת מוחלטת.
(כמובן שנשאלת השאלה איך נכניס לאוגר כתובת מוחלטת...)
הסיבה השניה היא כדי לתמוך בפוינטרים לפונקציות.
כלומר אם יש ב-C
את הקוד הבא:

(*p)()

ללא פקודה כמו jalr לא היינו מסוגלים לייצר קוד עם אותה משמעות!

לכן הפקודה jalr נקראת גם קפיצה עקיפה (indirect jump).

### איך כל זה עוזר לנו עם שגרות?

ובכן נסתכל בדוגמא הבאה:
jal x7, fun  // first call
.
.
.
jal x7, fun  // second call
.
.
.
jal x7, fun  // third call
.
.
.
.
.
.

fun: jalr x0,0(x7)

בקוד שלמעלה נגיע שלוש פעמים לקוד בתווית fun
ובכל פעם נחזור לפקודה שאחרי ה-jal
שבגלל הגענו ל-fun.

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

התיאום הזה נקרא *הסכם קריאה* (calling convention).
והסכם הקריאה הנהוג ב-rv64 הוא שכתובת החזרה תהיה באוגר x1.
ולכן בשפת סף האוגר x1 נקרא גם ra (return address).