דלג לתוכן הראשי

הרכבה מוטמעת

מבוא

האינטגרציה של הרכבה מוטמעת ב-Wave נעשית באמצעות asm { ... נכתבת בתוך בלוק }. ניתן לשלוט ישירות ברגיסטרים, בזיכרון ובמסלולי קריאת מערכת בתוך קוד Wave.

כרגע מטרות נתמכות:

  • Linux x86_64
  • macOS (Darwin) arm64

Windows עדיין לא נתמך.


צורה בסיסית

asm יכול לשמש הן כמשפט והן כביטוי.

asm {
"instruction"
in("constraint_or_reg") value
out("constraint_or_reg") target
clobber("item")
}

רכיבים:

  • שורת מחרוזת: פקודות אסמבלר בפועל
  • in(...): אופרנד קלט
  • out(...): אופרנד פלט
  • clobber(...): רמזים לרגיסטרים/מצב/זיכרון שנפגעים

asm משפט

כאשר אין צורך בהחזרת ערך, נעשה שימוש כמשפט רגיל.

var ret: i64 = 0;
asm {
"mov rax, 1"
"syscall"
in("rdi") 1
in("rsi") msg_ptr
in("rdx") 20
out("rax") ret
}

ניתן לכלול מספר out(...).


asm ביטוי

ניתן להשתמש כביטוי ליצירת ערך ישירות.

var result: i64 = asm {
"mov rax, 123"
out("rax") result
};

הערה:

  • ביטוי asm מאפשר בדיוק יציאה אחת של out(...) בלבד.

מגבלת in(...) / out(...)

המחרוזות של in("..."), out("...") הן אחת מהשתים הבאות.

  1. רשומת מדויקת
  • לדוגמה: "rax", "rdi", "x0", "w1"
  1. מעמד מגבלות (constraint class)
  • לדוגמה: "r", "m", "rm"

דוגמה:

in("r") &buf
out("rax") ret

יעד הפלט (`out(...) מכוון) היעד נוכחית לפי ההמלצה על הדפוס החולף.

  • משתנה: out("rax") ret
  • דיירקציה של מצביע: out("rax") deref p

clobber(...)

clobber(...) יכול לקבל מספר פריטים בבת אחת וניתן לשימוש מספר פעמים.

asm {
"xor rax, rax"
clobber("rax")
clobber("rcx", "rdx")
clobber("memory")
}

פריטים עיקריים:

  • רשם: "rax", "x0" וכו'
  • מיוחד: "memory", "cc" (נרמול פנימי לפי יעד)

המהדר מוסיף את ברירת המחדל של clobber במצב שמירה שמרני. (memory, flags/cc וכולי)


מציין מיקום אופראנד ($0, $1, ...)

בעת התייחסות לאופרנד במחרוזת פקודה, השתמש ב-$N.

asm {
"mov QWORD PTR [$0], 777"
in("r") &buf
clobber("memory")
}

הערה:

  • גם אם תשתמש בסגנון %0 הוא יומר לסגנון $0 באופן אוטומטי.

טווח תמיכה נוכחי לאופרנד קלט

ערכי in(...) תומכים כיום בצורות הבאות.

  • מזהה משתנה
  • לות אינטגריות
  • מחרוזות כיתוב
  • &identifier
  • deref identifier
  • ולצי כיתוב שליליים / נקודת צפות

מכיוון שבהצהרות כלליות מורכבות ייתכנו מגבלות, מומלץ להשתמש במשתנה זמני להעברה במקרה הצורך.


אזהרות

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

המלצות:

  • ראשית, לאשר את ה-ABI והסכמת הקריאה טרגטית
  • ניהול מפורש של רשומות קלט/פלט ו-clobber
  • אם נגיעה בזיכרון ישיר, להפצה גם ל-clobber("memory")