הרכבה מוטמעת
מבוא
האינטגרציה של הרכבה מוטמעת ב-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("...") הן אחת מהשתים הבאות.
- רשומת מדויקת
- לדוגמה:
"rax","rdi","x0","w1"
- מעמד מגבלות (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(...) תומכים כיום בצורות הבאות.
- מזהה משתנה
- לות אינטגריות
- מחרוזות כיתוב
&identifierderef identifier- ולצי כיתוב שליליים / נקודת צפות
מכיוון שבהצהרות כלליות מורכבות ייתכנו מגבלות, מומלץ להשתמש במשתנה זמני להעברה במקרה הצורך.
אזהרות
אסמבלר פנימי עוקף באופן חלקי את ההגנה של מערכת הסוג. הקצאה שגויה של רשם, התנגשות במגבלות, או היעדר clobber עלולים לגרום ליצירת קוד שגוי או תפקוד לא תקין בזמני ריצה.
המלצות:
- ראשית, לאשר את ה-ABI והסכמת הקריאה טרגטית
- ניהול מפורש של רשומות קלט/פלט ו-clobber
- אם נגיעה בזיכרון ישיר, להפצה גם ל-
clobber("memory")