עיצוב כללי
- מודל המכונה וכללי הקריאה מיועדים לחקות באופן גס ארכיטקטורות אמיתיות נפוצות וכללי קריאה בסגנון C:
- המכונה מבוססת על מרשם, והפריימים קבועים בגודל בזמן היצירה.
כל פריים מורכב ממספר מסוים של מרשם (שצוין על ידי השיטה) וכן מנתוני עזר שנדרשים להפעלת השיטה, כמו (בין היתר) מונה התוכנית והפניה לקובץ
.dex
שמכיל את השיטה. - כשמשתמשים ברשמים לערכים של ביטים (כמו מספרים שלמים ומספרים בספרות עשרוניות צפות), רוחב הרשמים נחשב ל-32 ביט. צמדי מרשם צמודים משמשים לערכים של 64 ביט. אין דרישה ליישור של זוגות של רשומות.
- כשמשתמשים ברשמים להפניות לאובייקטים, הם נחשבים רחבים מספיק כדי להכיל בדיוק הפניה אחת כזו.
- במונחים של ייצוג בייט-בייט,
(Object) null == (int) 0
. - הארגומנטים N של השיטה נשמרים בN הרשומות האחרונות של מסגרת ההפעלה של השיטה, לפי הסדר. ארגומנטים רחבים תופסים שני מרשמים. לשיטות של מופעים מועברת הפניה ל-
this
בתור הארגומנט הראשון שלהן.
- המכונה מבוססת על מרשם, והפריימים קבועים בגודל בזמן היצירה.
כל פריים מורכב ממספר מסוים של מרשם (שצוין על ידי השיטה) וכן מנתוני עזר שנדרשים להפעלת השיטה, כמו (בין היתר) מונה התוכנית והפניה לקובץ
- יחידת האחסון במאגר ההוראות היא כמות של 16 ביט ללא סימן. חלק מהביטים בהוראות מסוימות מתעלמים או חייבים להיות אפס.
- ההוראות לא מוגבלות באופן מיותר לסוג מסוים. לדוגמה, הוראות שמעבירות ערכים של מרשם 32 ביט ללא פרשנות לא צריכות לציין אם הן מעבירות מספרים שלמים או מספרים עשרוניים.
- יש מאגרי קבועים נפרדים עם מספרים ואינדקסים להפניות למחרוזות, לסוגי נתונים, לשדות ולשיטות.
- נתונים ליסטים ביטיים מיוצגים בשורה בזרם ההוראות.
- בפועל, נדיר שמתודולוגיה זקוקה ליותר מ-16 מרשם, וגם נדיר שמתודולוגיה זקוקה ליותר מ-8 מרשם, ולכן הרבה הוראות מוגבלות רק לטיפול ב-16 המרשמים הראשונים. כשהדבר אפשרי באופן סביר, ההוראות מאפשרות הפניות ל-256 הרשומות הראשונות. בנוסף, להוראות מסוימות יש וריאנטים שמאפשרים מספרים גדולים בהרבה של מרשם, כולל זוג הוראות
move
לכל מקרה אפשרי שיכולות לטפל במרשמים בטווחv0
עדv65535
. במקרים שבהם וריאנט של הוראה לא זמין כדי לטפל ברשומה הרצויה, תוכן הרשומה אמור לעבור מהרשומה המקורית לרשומה נמוכה (לפני הפעולה) ו/או לעבור מרשומת תוצאה נמוכה לרשומה גבוהה (אחרי הפעולה). - יש כמה "הוראות פסאודו" שמשמשות לאחסון עומסי נתונים באורך משתנה, שמפנים אליהן באמצעות הוראות רגילות (לדוגמה,
fill-array-data
). אסור לעולם להיתקל בהוראות כאלה במהלך תהליך הביצוע הרגיל. בנוסף, ההוראות צריכות להיות ממוקמות במרווחים של בייטים בקוד בינארי בספרות זוגיות (כלומר, מותאמות ל-4 בייטים). כדי לעמוד בדרישות האלה, כלים ליצירת קובצי dex חייבים להפיק הוראהnop
נוספת כמפריד, אם הוראה כזו לא תהיה מותאמת אחרת. לבסוף, למרות שזה לא נדרש, צפוי שרוב הכלים יבחרו להפיק את ההוראות האלה בסוף השיטות, כי אחרת סביר להניח שיהיה צורך בהוראות נוספות כדי לבצע ניתוח נתונים סביבן. - כשמתקינים את הספרייה במערכת שפועלת, יכול להיות שחלק מההוראות ישתנו, ושינוי הפורמט שלהן יתבצע כאופטימיזציה של קישור סטטי בזמן ההתקנה. המטרה היא לאפשר ביצוע מהיר יותר ברגע שהקישור ידוע. תוכלו למצוא את הווריאציות המוצעות במסמך הנחיות הפורמטים המשויך. המילה 'הצעות' כתובה בכוונה תחילה, כי לא חובה להטמיע אותן.
- תחביר אנושי ומונחי mnemotechnic:
- סדר הארגומנטים הוא 'יעד ואז מקור'.
- לחלק מקוד הפקודה יש סיומת שם שמאפשרת להבחין בין סוגי הנתונים שהוא פועל עליהם:
- אופקודים כלליים מסוג 32 ביט לא מסומנים.
- קוד הפקודה הכללי של 64 ביט מסתיים ב-
-wide
. - קוד הפקודה הספציפי לסוג מסוים מקבל סיומת עם הסוג שלו (או עם קיצור פשוט), אחד מהערכים הבאים:
-boolean
-byte
-char
-short
-int
-long
-float
-double
-object
-string
-class
-void
.
- לחלק מקוד הפקודה יש סיומת להסרת עמימות כדי להבדיל בין פעולות זהות לחלוטין שיש להן פריסות או אפשרויות שונות של הוראות. הסיומת הזו מופרדת מהשמות הראשיים באמצעות קו נטוי (
/
), והיא קיימת בעיקר כדי ליצור מיפוי אחד-לאחד עם קבועים סטטיים בקוד שיוצר ומפרש קובצי הפעלה (כלומר, כדי לצמצם את הבלבול אצל בני אדם). - בתיאורים שבהמשך, רוחב הערך (שמציין, למשל, את הטווח של קבוע או את מספר הרשומות שאפשר לטפל בהן) מודגש באמצעות שימוש בתו לכל ארבעת הביטים של רוחב.
- לדוגמה, בהוראה
"
move-wide/from16 vAA, vBBBB
":move
הוא קוד הפקודה הבסיסי, שמציין את הפעולה הבסיסית (העברת הערך של רישום).wide
הוא הסיומת של השם, שמציינת שהוא פועל על נתונים רחבים (64 ביט).from16
הוא הסיומת של קוד הפקודה, שמציינת וריאנט שיש לו הפניה למרשם של 16 ביט כמקור.vAA
הוא מרשם היעד (הוא משתמע מהפעולה. שוב, הכלל הוא שהארגומנטים של היעד תמיד מופיעים קודם), והוא חייב להיות בטווחv0
עדv255
.- '
vBBBB
' הוא מרשם המקור, שצריך להיות בטווחv0
עדv65535
.
- במסמך בנושא פורמטים של הוראות מפורט מידע נוסף על הפורמטים השונים של ההוראות (רשימת הפורמטים מופיעה בקטע 'Op & Format'), וכן פרטים על תחביר קוד הפקודה.
- למידע נוסף על המקום שבו קוד בייטקס נכנס לתמונה הגדולה, אפשר לעיין במסמך בנושא פורמט הקובץ
.dex
.
סיכום של קבוצת קוד באקס (bytecode)
פעולה ופורמט | שיטות לזכירה / תחביר | ארגומנטים | תיאור |
---|---|---|---|
00 10x | nop | מחזורי פסולת.
הערה: הוראות פסאודו שמכילות נתונים מתויגות באמצעות קוד הפקודה הזה. במקרה כזה, הבית הבכיר של יחידת קוד הפקודה מציין את אופי הנתונים. מידע נוסף זמין בקטע 'פורמט |
|
01 12x | move vA, vB | A: מרשם היעד (4 ביט)B: מרשם המקור (4 ביט) |
העברת התוכן של מרשם לא אובייקט אחד למרשם אחר. |
02 22x | move/from16 vAA, vBBBB | A: מרשם היעד (8 ביט)B: מרשם המקור (16 ביט) |
העברת התוכן של מרשם לא אובייקט אחד למרשם אחר. |
03 32x | move/16 vAAAA, vBBBB | A: מרשם היעד (16 ביט)B: מרשם המקור (16 ביט) |
העברת התוכן של מרשם לא אובייקט אחד למרשם אחר. |
04 12x | vA, vB ברמת התנועה | A: צמד מרשם יעד (4 ביט)B: צמד מרשם מקור (4 ביט) |
העברת התוכן של זוג מרשם אחד למשנהו.
הערה: מותר לעבור מ- |
05 22x | move-wide/from16 vAA, vBBBB | A: זוג מרשם יעד (8 ביט)B: זוג מרשם מקור (16 ביט) |
העברת התוכן של זוג מרשם אחד למשנהו.
הערה: השיקולים להטמעה זהים לאלה שמפורטים בקטע |
06 32x | move-wide/16 vAAAA, vBBBB | A: זוג מרשם יעד (16 ביט)B: זוג מרשם מקור (16 ביט) |
העברת התוכן של זוג מרשם אחד למשנהו.
הערה: השיקולים להטמעה זהים לאלה שמפורטים בקטע |
07 12x | move-object vA, vB | A: מרשם יעד (4 ביט)B: מרשם מקור (4 ביט) |
העברת התוכן של מרשם אחד שמכיל אובייקטים למרשם אחר. |
08 22x | move-object/from16 vAA, vBBBB | A: מרשם היעד (8 ביט)B: מרשם המקור (16 ביט) |
העברת התוכן של רשם אחד שמכיל אובייקטים לרשום אחר. |
09 32x | move-object/16 vAAAA, vBBBB | A: מרשם יעד (16 ביט)B: מרשם מקור (16 ביט) |
העברת התוכן של רשם אחד שמכיל אובייקטים לרשום אחר. |
0a 11x | move-result vAA | מרשם היעד A: (8 ביט) |
מעבירים את התוצאה של invoke-kind האחרונה, שהיא מילה אחת שאינה אובייקט, למרשם שצוין.
צריך לעשות זאת כהוראה מיד אחרי invoke-kind שהתוצאה שלו (מילה אחת, לא אובייקט) לא מתעלמת. בכל מקום אחר, הפעולה לא חוקית. |
0b 11x | move-result-wide vAA | זוג של מרשם יעד A: (8 ביט) |
העברת התוצאה של המילה הכפולה של invoke-kind האחרון לזוג הרישום שצוין.
צריך לעשות זאת כהוראה מיד אחרי invoke-kind שהתוצאה (מילה כפולה) שלה לא מתעלמת. בכל מקום אחר, הפעולה לא חוקית. |
0c 11x | move-result-object vAA | מרשם היעד A: (8 ביט) |
העברת תוצאת האובייקט של invoke-kind העדכני ביותר למרשם שצוין. צריך לעשות זאת כהוראה
מייד אחרי invoke-kind או
filled-new-array
שאין להתעלם מהתוצאה (האובייקט) שלו. בכל מקום אחר זה לא תקין. |
0 ימים 11x | move-exception vAA | מרשם היעד A: (8 ביט) |
שמירת חריגה שנלכדה ביומן הנתון. זו צריכה להיות ההוראה הראשונה של כל מנהל חריגות שלא מתעלם מהחריגה שנלכדה, וההוראה הזו חייבת להופיע רק כהוראה הראשונה של מנהל חריגות. בכל מקום אחר היא לא חוקית. |
0e 10x | return-void | חזרה משיטה void . |
|
0f 11x | return vAA | מרשם הערך המוחזר A: (8 ביט) |
חזרה מפונקציה ברוחב יחיד (32 ביט) שלא מחזירה ערך אובייקט. |
10 11x | vAA ברמת ההחזרה | A: צמד מרשם של ערך המוחזר (8 ביט) |
יציאה חזרה משיטה שמחזירה ערך ברוחב כפול (64 ביט). |
11 11x | return-object vAA | מרשם הערך המוחזר של A: (8 ביט) |
חזרה משיטה שמחזירה אובייקט. |
12 11n | const/4 vA, #+B | A: מרשם יעד (4 סיביות)B: signed int (4 סיביות) |
העברת הערך הלטרלי הנתון (עם הרחבת סימן ל-32 ביט) למרשם שצוין. |
13 21s | const/16 vAA, #+BBBB | A: מרשם יעד (8 ביט)B: signed int (16 ביט) |
העברת הערך הלטרלי הנתון (עם הרחבת סימן ל-32 סיביות) למרשם שצוין. |
14 31i | const vAA, #+BBBBBBBB | A: מרשם יעד (8 ביט)B: קבוע שרירותי של 32 ביט |
העברת הערך הלטרלי שצוין למרשם שצוין. |
15 21h | const/high16 vAA, #+BBBB0000 | A: מרשם יעד (8 ביט)B: signed int (16 ביט) |
העברת הערך הלטרלי הנתון (עם הרחבה של אפסים בצד שמאל ל-32 סיביות) למרשם שצוין. |
16 21s | const-wide/16 vAA, #+BBBB | A: מרשם יעד (8 ביט)B: signed int (16 ביט) |
העברת הערך הלטרלי הנתון (עם הרחבת סימן ל-64 ביט) לצמד הרשומות שצוין. |
17 31i | const-wide/32 vAA, #+BBBBBBBB | A: מרשם יעד (8 ביט)B: signed int (32 ביט) |
העברת הערך הלטרלי הנתון (עם הרחבת סימן ל-64 ביט) לצמד הרשומות שצוין. |
18 51l | const-wide vAA, #+BBBBBBBBBBBBBBBB | A: מרשם יעד (8 ביט)B: קבוע שרירותי ברוחב כפול (64 ביט) |
העברת הערך הליליטרלי שצוין לזוג הרשומות שצוין. |
19 21h | const-wide/high16 vAA, #+BBBB000000000000 | A: מרשם יעד (8 ביט)B: signed int (16 ביט) |
העברת הערך הלטרלי הנתון (מורחב לאפסים מימין ל-64 סיביות) לצמד הרשומות שצוין. |
1a 21c | const-string vAA, string@BBBB | A: מרשם היעד (8 ביט)B: אינדקס המחרוזת |
העברת הפניה למחרוזת שצוינה על ידי האינדקס הנתון למרשם שצוין. |
1b 31c | const-string/jumbo vAA, string@BBBBBBBB | A: מרשם היעד (8 ביט)B: אינדקס המחרוזת |
העברת הפניה למחרוזת שצוינה על ידי האינדקס הנתון למרשם שצוין. |
1c 21c | const-class vAA, type@BBBB | A: מרשם יעד (8 ביט)B: אינדקס סוג |
העברת הפניה לכיתה שצוינה על ידי האינדקס הנתון למרשם שצוין. במקרה שהסוג שצוין הוא פרימיטיבי, יישמר כאן הפניה לקלאס המנוון של הסוג הפרימיטיבי. |
1d 11x | monitor-enter vAA | A: מרשם עם ערך הפניה (8 ביט) |
מקבלים את המוניטור של האובייקט שצוין. |
1e 11x | monitor-exit vAA | A: מרשם עם ערך הפניה (8 ביט) |
משחררים את המעקב אחרי האובייקט שצוין.
הערה: אם צריך להפעיל חריגה מההוראה הזו, צריך לעשות זאת כאילו המחשב כבר התקדם מעבר להוראה.
אפשר לחשוב על זה ככה: ההוראה בוצעה בהצלחה (במובן מסוים), וההודעת החריגה הושלחה אחרי ההוראה, אבל לפני שההוראה הבאה תקבל הזדמנות לפעול. ההגדרה הזו מאפשרת לשיטה להשתמש ב-catch-all לניקוי של צגים (למשל, |
1f 21c | check-cast vAA, type@BBBB | A: מרשם עם הפניה (8 ביט)B: אינדקס סוג (16 ביט) |
גורם להשלכת ClassCastException אם לא ניתן להמיר את ההפניה ברשומה הנתונה לסוג שצוין.
הערה: מכיוון ש- |
20 22c | instance-of vA, vB, type@CCCC | A: מרשם יעד (4 ביט)B: מרשם עם הפניה (4 ביט)C: אינדקס סוג (16 ביט) |
שומרים ברשומת היעד שצוינה את הערך 1 אם ההפניה שצוינה היא מופע מהטיפוס שצוין, או את הערך 0 אם לא.
הערה: מכיוון ש- |
21 12x | array-length vA, vB | A: מרשם יעד (4 ביט)B: מרשם שמכיל את ההפניה למערך (4 ביט) |
שמירת האורך של המערך שצוין, ברשומות, במרשם היעד |
22 21c | new-instance vAA, type@BBBB | A: מרשם יעד (8 ביט)B: אינדקס סוג |
יוצרים מכונה חדשה מהסוג שצוין, ושומרים הפניה אליה ביעד. הטיפוס חייב להפנות לסוג של כיתה שאינה מערך. |
23 22c | new-array vA, vB, type@CCCC | A: מרשם היעד (4 ביט)B: מרשם הגודלC: אינדקס הסוג |
יצירת מערך חדש מהסוג והגודל שצוינו. הסוג חייב להיות מערך. |
24 35c | filled-new-array {vC, vD, vE, vF, vG}, type@BBBB |
A: גודל המערך ומספר המילים של הארגומנט (4 ביט)B: מדד הסוג (16 ביט)C..G: מרשם הארגומנטים (4 ביט כל אחד)
|
יצירה של מערך מהסוג והגודל שצוינו, ומילוי שלו בתוכן שסופק. הסוג חייב להיות מערך. התוכן של המערך חייב להיות מילה אחת (כלומר, אסור להשתמש במערכים של long או double , אבל מותר להשתמש בסוגים של הפניות). המכונה שנוצרה מאוחסנת בתור 'תוצאה' באותו אופן שבו ההוראות להפעלת השיטות מאחסנות את התוצאות שלהן, כך שצריך להעביר את המכונה שנוצרה למרשם באמצעות הוראה move-result-object מיידית לאחר מכן (אם רוצים להשתמש בה). |
25 3rc | filled-new-array/range {vCCCC .. vNNNN}, type@BBBB | A: גודל המערך ומספר המילים של הארגומנט (8 ביט)B: מדד הסוג (16 ביט)C: מרשם הארגומנט הראשון (16 ביט)N = A + C - 1 |
יצירה של מערך מהסוג והגודל שצוינו, ומילוי שלו בתוכן שסופק. ההבהרות וההגבלות זהות לאלה של filled-new-array , כפי שמתואר למעלה. |
26 31t | fill-array-data vAA, +BBBBBBBB (עם נתונים משניים כפי שמפורט בהמשך בקטע 'פורמט fill-array-data-payload ') |
A: הפניה למערך (8 ביט)B: היסט חתום של 'הסתעפות' להוראת פסאודו של נתוני טבלה
(32 ביט)
|
ממלאים את המערך הנתון בנתונים שצוינו. ההפניה חייבת להיות למערך של פרימיטיבים, וטבלת הנתונים חייבת להתאים לה מבחינת סוג ולא לכלול יותר רכיבים ממה שאפשר להכניס למערך. כלומר, המערך יכול להיות גדול יותר מהטבלה, ואם זה המצב, רק הרכיבים הראשונים של המערך מוגדרים, והשאר נשאר ללא שינוי. |
27 11x | throw vAA | A: מרשם שמכיל חריגה (8 ביט) |
השלכת החריגה שצוינה. |
28 10t | goto +AA | A: היסט של הסתעפות חתומה (8 ביט) |
מעבר ללא תנאי להוראה שצוינה.
הערה:
אסור שההיסט של ההסתעפות יהיה |
29 20t | goto/16 +AAAA | A: signed branch offset (16 bits) |
מעבר ללא תנאי להוראה שצוינה.
הערה:
אסור שההיסט של ההסתעפות יהיה |
2a 30t | goto/32 +AAAAAAAA | A: signed branch offset (32 bits) |
מעבר ללא תנאי להוראה שצוינה. |
2b 31t | packed-switch vAA, +BBBBBBBB (עם נתונים משניים כפי שמפורט בהמשך בקטע 'packed-switch-payload פורמט') |
A: register to testB: signed "branch" offset to table data pseudo-instruction
(32 bits)
|
מעבר להוראה חדשה על סמך הערך ברשומה הנתונה, באמצעות טבלה של שינויי מיקום (offsets) שתואמים לכל ערך בטווח שלם מסוים, או מעבר להוראה הבאה אם אין התאמה. |
2c 31t | sparse-switch vAA, +BBBBBBBB (עם נתונים משלימים כפי שמפורט בהמשך בקטע 'פורמט sparse-switch-payload ') |
A: register to testB: signed "branch" offset to table data pseudo-instruction
(32 bits)
|
מעבר להוראה חדשה על סמך הערך ברשומה הנתונה, באמצעות טבלה מסודרת של צמדי ערך-היסט, או מעבר להוראה הבאה אם אין התאמה. |
2d..31 23x | cmpkind vAA, vBB, vCC 2d: cmpl-float (lt bias) 2e: cmpg-float (gt bias) 2f: cmpl-double (lt bias) 30: cmpg-double (gt bias) 31: cmp-long |
A: מרשם יעד (8 ביט)B: מרשם המקור או הצמד הראשוןC: מרשם המקור או הצמד השני |
מבצעים את ההשוואה של long או הנקודה הצפה שצוינה, ומגדירים את a לערך 0 אם b == c , לערך 1 אם b > c או לערך -1 אם b < c .
הערך 'bias' שמופיע לפעולות של נקודת צפה מציין את האופן שבו מתבצעת הטיפול בהשוואות של NaN : הוראות 'gt bias' מחזירות את הערך 1 בהשוואות של NaN , והוראות 'lt bias' מחזירות את הערך -1 .
לדוגמה, כדי לבדוק אם הערך של |
32..37 22t | if-test vA, vB, +CCCC 32: if-eq 33: if-ne 34: if-lt 35: if-ge 36: if-gt 37: if-le |
A: הרישום הראשון לבדיקה (4 ביט)B: הרישום השני לבדיקה (4 ביט)C: היסט של ענף חתום (16 ביט) |
מעבר ליעד שצוין אם הערכים של שני הרשומות הנתונות תואמים כמצוין.
הערה:
אסור שההיסט של ההסתעפות יהיה |
38..3d 21t | if-testz vAA, +BBBB 38: if-eqz 39: if-nez 3a: if-ltz 3b: if-gez 3c: if-gtz 3d: if-lez |
A: register to test (8 bits)B: signed branch offset (16 bits) |
מעבר ליעד שצוין אם הערך של המרשם הנתון משווה ל-0 כפי שצוין.
הערה:
אסור שההיסט של ההסתעפות יהיה |
3e..43 10x | (לא בשימוש) | (לא בשימוש) | |
44..51 23x | arrayop vAA, vBB, vCC 44: aget 45: aget-wide 46: aget-object 47: aget-boolean 48: aget-byte 49: aget-char 4a: aget-short 4b: aput 4c: aput-wide 4d: aput-object 4e: aput-boolean 4f: aput-byte 50: aput-char 51: aput-short |
מרשם ערך או צמד של A: ; יכול להיות מקור או יעד
(8 ביט)מרשם מערך של B: (8 ביט)מרשם אינדקס של C: (8 ביט) |
ביצוע הפעולה במערך שזוהתה באינדקס שזוהה במערך הנתון, טעינה או אחסון ברשומת הערך. |
52..5f 22c | iinstanceop vA, vB, field@CCCC 52: iget 53: iget-wide 54: iget-object 55: iget-boolean 56: iget-byte 57: iget-char 58: iget-short 59: iput 5a: iput-wide 5b: iput-object 5c: iput-boolean 5d: iput-byte 5e: iput-char 5f: iput-short |
מרשם או זוג ערכים של A: ; יכול להיות מקור או יעד
(4 ביט)מרשם אובייקט של B: (4 ביט)אינדקס הפניה לשדה של מכונה של C: (16 ביט) |
ביצוע הפעולה בשדה של מופע האובייקט המזוהה עם השדה המזוהה, טעינה או אחסון ברשומת הערך.
הערה: קוד הפקודות הזה מתאים לקישור סטטי, שבו משנים את ארגומנט השדה כך שיהיה שינוי ישיר יותר. |
60..6d 21c | sstaticop vAA, field@BBBB 60: sget 61: sget-wide 62: sget-object 63: sget-boolean 64: sget-byte 65: sget-char 66: sget-short 67: sput 68: sput-wide 69: sput-object 6a: sput-boolean 6b: sput-byte 6c: sput-char 6d: sput-short |
A: register or pair of values; may be source or dest
(8 bits)B: static field reference index (16 bits) |
ביצוע הפעולה בשדה הסטטי של האובייקט המזוהה עם השדה הסטטי המזוהה, טעינה או אחסון ברשומת הערך.
הערה: קוד הפקודות הזה מתאים לקישור סטטי, שבו משנים את ארגומנט השדה כך שיהיה שינוי ישיר יותר. |
6e..72 35c | invoke-kind {vC, vD, vE, vF, vG}, meth@BBBB 6e: invoke-virtual 6f: invoke-super 70: invoke-direct 71: invoke-static 72: invoke-interface |
A: מספר מילים של ארגומנטים (4 ביט)B: מדד הפניה לשיטה (16 ביט)C..G: מרשם ארגומנטים (4 ביט כל אחד)
|
קוראים ל-method שצוין. התוצאה (אם יש כזו) יכולה להיות מאוחסנת עם וריאנט מתאים של move-result* כהוראה הבאה.
כשה- בקובצי Dex בגרסה
הערה: קוד הפקודות הזה מתאים לקישור סטטי, שבו משנים את ארגומנט השיטה כך שיהיה שינוי ישיר יותר (או זוג של שינוי כזה). |
73 10x | (לא בשימוש) | (לא בשימוש) | |
74..78 3rc | invoke-kind/range {vCCCC .. vNNNN}, meth@BBBB 74: invoke-virtual/range 75: invoke-super/range 76: invoke-direct/range 77: invoke-static/range 78: invoke-interface/range |
A: מספר מילות הארגומנט (8 ביט)B: מדד של הפניה לשיטה (16 ביט)C: מרשם הארגומנט הראשון (16 ביט)N = A + C - 1 |
קוראים ל-method שצוין. פרטים, אזהרות והצעות מופיעים בתיאור הראשון של invoke-kind למעלה.
|
79..7a 10x | (לא בשימוש) | (לא בשימוש) | |
7b..8f 12x | unop vA, vB 7b: neg-int 7c: not-int 7d: neg-long 7e: not-long 7f: neg-float 80: neg-double 81: int-to-long 82: int-to-float 83: int-to-double 84: long-to-int 85: long-to-float 86: long-to-double 87: float-to-int 88: float-to-long 89: float-to-double 8a: double-to-int 8b: double-to-long 8c: double-to-float 8d: int-to-byte 8e: int-to-char 8f: int-to-short |
A: מרשם או צמד של יעד (4 ביט)B: מרשם או צמד של מקור (4 ביט) |
ביצוע הפעולה החד-ערךית שזוהתה ברגולטור המקור, ושמירת התוצאה ברגולטור היעד. |
90..af 23x | binop vAA, vBB, vCC 90: add-int 91: sub-int 92: mul-int 93: div-int 94: rem-int 95: and-int 96: or-int 97: xor-int 98: shl-int 99: shr-int 9a: ushr-int 9b: add-long 9c: sub-long 9d: mul-long 9e: div-long 9f: rem-long a0: and-long a1: or-long a2: xor-long a3: shl-long a4: shr-long a5: ushr-long a6: add-float a7: sub-float a8: mul-float a9: div-float aa: rem-float ab: add-double ac: sub-double ad: mul-double ae: div-double af: rem-double |
A: מרשם או צמד יעד (8 ביט)B: מרשם או צמד מקור ראשון (8 ביט)C: מרשם או צמד מקור שני (8 ביט) |
ביצוע הפעולה הבינארית שזוהתה בשני מרשם המקור, ושמירת התוצאה במרשם היעד.
הערה: בניגוד לפעולות מתמטיות אחרות של |
b0..cf 12x | binop/2addr vA, vB b0: add-int/2addr b1: sub-int/2addr b2: mul-int/2addr b3: div-int/2addr b4: rem-int/2addr b5: and-int/2addr b6: or-int/2addr b7: xor-int/2addr b8: shl-int/2addr b9: shr-int/2addr ba: ushr-int/2addr bb: add-long/2addr bc: sub-long/2addr bd: mul-long/2addr be: div-long/2addr bf: rem-long/2addr c0: and-long/2addr c1: or-long/2addr c2: xor-long/2addr c3: shl-long/2addr c4: shr-long/2addr c5: ushr-long/2addr c6: add-float/2addr c7: sub-float/2addr c8: mul-float/2addr c9: div-float/2addr ca: rem-float/2addr cb: add-double/2addr cc: sub-double/2addr cd: mul-double/2addr ce: div-double/2addr cf: rem-double/2addr |
A: יעד ומרשם או צמד מקור ראשון (4 ביט)B: מרשם או צמד מקור שני (4 ביט) |
ביצוע הפעולה הבינארית שזוהתה בשני מרשם המקור, ושמירת התוצאה במרשם המקור הראשון.
הערה: בניגוד לפעולות מתמטיות אחרות של |
d0..d7 22s | binop/lit16 vA, vB, #+CCCC d0: add-int/lit16 d1: rsub-int (חיסור הפוך) d2: mul-int/lit16 d3: div-int/lit16 d4: rem-int/lit16 d5: and-int/lit16 d6: or-int/lit16 d7: xor-int/lit16 |
A: מרשם יעד (4 ביט)B: מרשם מקור (4 ביט)C: קבוע של int signed (16 ביט) |
ביצוע הפעולה הבינארית שצוינה ברגולטור שצוין (הארגומנט הראשון) ובערך הלטרלי (הארגומנט השני), ושמירת התוצאה ברגולטור היעד.
הערה: ל- |
d8..e2 22b | binop/lit8 vAA, vBB, #+CC d8: add-int/lit8 d9: rsub-int/lit8 da: mul-int/lit8 db: div-int/lit8 dc: rem-int/lit8 dd: and-int/lit8 de: or-int/lit8 df: xor-int/lit8 e0: shl-int/lit8 e1: shr-int/lit8 e2: ushr-int/lit8 |
A: מרשם יעד (8 ביט)B: מרשם מקור (8 ביט)C: קבוע של int signed (8 ביט) |
ביצוע הפעולה הבינארית שצוינה ברגולטור שצוין (הארגומנט הראשון) ובערך הלטרלי (הארגומנט השני), ושמירת התוצאה ברגולטור היעד.
הערה: בהמשך מוסבר על הסמנטיקה של |
e3..f9 10x | (לא בשימוש) | (לא בשימוש) | |
fa 45cc | invoke-polymorphic {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH |
A: מספר מילים של ארגומנט (4 ביט) B: מדד הפניה לשיטה (16 ביט) C: מקלט (4 ביט) D..G: מרשם ארגומנטים (4 ביט כל אחד) H: מדד הפניה לפרוטוטיפ (16 ביט)
|
קוראים ל-method הפולימורפית של החתימה שצוינה. התוצאה (אם יש כזו) יכולה להישמר עם וריאנט מתאים של move-result* כהוראה הבאה.ההפניה לשיטה חייבת להיות לשיטה עם חתימה פולימורפית, כמו java.lang.invoke.MethodHandle.invoke או
java.lang.invoke.MethodHandle.invokeExact .הנמען חייב להיות אובייקט שתומך בשיטה הפולימורפית של החתימה שנקראת. בתיעוד של אב הטיפוס מתוארים סוגי הארגומנטים שסופקו וסוג ההחזרה הצפוי. הקוד הבינארי של invoke-polymorphic עשוי להעלות חריגות במהלך הביצוע שלו. החריגים מתוארים במסמכי העזרה של ה-API של השיטה הפולימורפית עם החתימה שמפעילים.נמצא בקובצי Dex מגרסה 038 ואילך.
|
fb 4rcc | invoke-polymorphic/range {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH |
A: מספר מילות הארגומנט (8 ביט) B: מדד הפניה לשיטה (16 ביט) C: מקלט (16 ביט) H: מדד הפניה לפרוטוטיפ (16 ביט) N = A + C - 1
|
קריאה למטמון ה-method שצוין. פרטים נוספים מופיעים בתיאור של invoke-polymorphic למעלה.הקוד הזה נמצא בקובצי Dex מגרסה 038 ואילך.
|
fc 35c | invoke-custom {vC, vD, vE, vF, vG}, call_site@BBBB |
A: מספר מילות הארגומנט (4 ביט) B: מדד הפניה של אתר הקריאה (16 ביט) C..G: מרשם הארגומנטים (4 ביט כל אחד)
|
פותר את אתר הקריאה שצוין ומפעיל אותו.
התוצאה מהקריאה (אם יש כזו) עשויה להישמר עם וריאנט מתאים של move-result* בתור ההוראה הבאה.ההוראה הזו מתבצעת בשני שלבים: פתרון של אתר הקריאה והפעלה של אתר הקריאה. פתרון של אתר קריאה בודק אם לאתר הקריאה שצוין יש מכונה משויכת של java.lang.invoke.CallSite .
אם לא, מתבצעת קריאה לשיטת הקישור של ה-bootstrap לאתר הקריאה שצוין באמצעות ארגומנטים שנמצאים בקובץ ה-DEX (ראו call_site_item). השיטה של ה-bootstrap linker מחזירה מופע של java.lang.invoke.CallSite , שישויך לאתר הקריאה שצוין אם אין שיוך. יכול להיות ששרשור אחר כבר ביצע את השיוך קודם, ואם כן, ביצוע ההוראה ימשיך עם המכונה הראשונה של java.lang.invoke.CallSite שמשויכת.הקריאה לאתר מתבצעת ביעד java.lang.invoke.MethodHandle של המופע java.lang.invoke.CallSite שהתקבל. היעד מופעל כאילו מבצעים את invoke-polymorphic (כפי שמתואר למעלה) באמצעות ה-method handle והארגומנטים של הוראה invoke-custom , בתור הארגומנטים להפעלה מדויקת של ה-method handle.חריגים שה-method של ה-bootstrap linker מעלה עוטפים ב- java.lang.BootstrapMethodError . הערך BootstrapMethodError מופיע גם במקרים הבאים:
038 ואילך.
|
fd 3rc | invoke-custom/range {vCCCC .. vNNNN}, call_site@BBBB |
A: מספר מילות הארגומנט (8 ביט) B: אינדקס הפניה של אתר הקריאה (16 ביט) C: מרשם הארגומנט הראשון (16 ביט) N = A + C - 1
|
פתרון והפעלה של אתר קריאה. פרטים נוספים מופיעים בתיאור של invoke-custom למעלה.הקוד הזה נמצא בקובצי Dex מגרסה 038 ואילך.
|
fe 21c | const-method-handle vAA, method_handle@BBBB | A: מרשם היעד (8 ביט)B: אינדקס של טיפולי שיטות (16 ביט) |
העברת הפניה למטמון השיטה שצוין על ידי האינדקס הנתון למרשם שצוין. הקוד הזה נמצא בקובצי Dex מגרסה 039 ואילך.
|
ff 21c | const-method-type vAA, proto@BBBB | A: מרשם היעד (8 ביט)B: הפניה לפרוטוטיפ של השיטה (16 ביט) |
העברת הפניה לפרוטוטיפ השיטה שצוין על ידי האינדקס הנתון למרשם שצוין. הקוד הזה נמצא בקובצי Dex מגרסה 039 ואילך.
|
פורמט packed-switch-payload
שם | פורמט | תיאור |
---|---|---|
ident | ushort = 0x0100 | זיהוי פסאודו-קוד פעולה |
size | ushort | מספר הרשומות בטבלה |
first_key | INT | הערך הראשון (והנמוך ביותר) של מקרה המעבר |
יעדים | int[] | רשימה של size יעדי ההסתעפות היחסיים. היעדים הם יחסיים לכתובת של קוד הפקודה של המתג, ולא לטבלה הזו.
|
הערה: המספר הכולל של יחידות הקוד למכונה של הטבלה הזו הוא (size * 2) + 4
.
פורמט sparse-switch-payload
שם | פורמט | תיאור |
---|---|---|
ident | ushort = 0x0200 | זיהוי פסאודו-קוד פעולה |
size | ushort | מספר הרשומות בטבלה |
מפתחות | int[] | רשימה של ערכי מפתח size , ממוינים מערכים נמוכים לערכים גבוהים |
יעדים | int[] | רשימה של size יעדי הסתעפות יחסיים, שכל אחד מהם תואם לערך המפתח באותו אינדקס. היעדים הם יחסיים לכתובת של קוד הפקודה של המתג, ולא לטבלה הזו.
|
הערה: המספר הכולל של יחידות הקוד למכונה של הטבלה הזו הוא (size * 4) + 2
.
פורמט fill-array-data-payload
שם | פורמט | תיאור |
---|---|---|
ident | ushort = 0x0300 | זיהוי פסאודו-קוד פעולה |
element_width | ushort | מספר הבייטים בכל רכיב |
size | uint | מספר הרכיבים בטבלה |
נתונים | ubyte[] | ערכי נתונים |
הערה: המספר הכולל של יחידות הקוד למכונה של הטבלה הזו הוא (size * element_width + 1) / 2 + 4
.
פרטי הפעולה המתמטית
הערה: פעולות של נקודות צפות חייבות לפעול לפי הכללים של IEEE 754, באמצעות עיגול לספרה הקרובה ביותר ותת-זרימה הדרגתית, אלא אם צוין אחרת.
קוד פעולה | סמנטיקה של C | הערות |
---|---|---|
neg-int | int32 a; int32 result = -a; |
משלימים בינאריים חד-ערךיים. |
not-int | int32 a; int32 result = ~a; |
משלימים חד-ערךיים. |
neg-long | int64 a; int64 result = -a; |
משלימים בינאריים חד-ערךיים. |
not-long | int64 a; int64 result = ~a; |
משלימים חד-ערךיים. |
neg-float | float a; float result = -a; |
ביטול של נקודה צפה (floating-point). |
neg-double | double a; double result = -a; |
ביטול של נקודה צפה (floating-point). |
int-to-long | int32 a; int64 result = (int64) a; |
הרחבת סימן של int32 ל-int64 . |
int-to-float | int32 a; float result = (float) a; |
המרה של int32 ל-float באמצעות עיגול לשיא הקרוב. כך פוחת הדיוק של ערכים מסוימים.
|
int-to-double | int32 a; double result = (double) a; |
המרה של int32 ל-double . |
long-to-int | int64 a; int32 result = (int32) a; |
חיתוך של int64 ל-int32 . |
long-to-float | int64 a; float result = (float) a; |
המרה של int64 ל-float באמצעות עיגול לשיא הקרוב. כך פוחת הדיוק של ערכים מסוימים.
|
long-to-double | int64 a; double result = (double) a; |
המרה של int64 ל-double באמצעות עיגול לשיא הקרוב. כך פוחת הדיוק של ערכים מסוימים.
|
float-to-int | float a; int32 result = (int32) a; |
המרה של float ל-int32 , באמצעות בחירת הערך הקרוב לאפס. הערכים NaN ו--0.0 (אפס שלילי) ממירים למספר השלם 0 . אינסופיות וערכים עם עוצמה גדולה מדי שלא ניתן לייצג אותם מומרו לערך 0x7fffffff או לערך -0x80000000 , בהתאם לסימון.
|
float-to-long | float a; int64 result = (int64) a; |
המרה של float ל-int64 , באמצעות בחירת הערך הקרוב לאפס. כאן חלים אותם כללים לטיפול במקרים מיוחדים כמו float-to-int , מלבד העובדה שערכים מחוץ לטווח מומרים ל-0x7fffffffffffffff או ל--0x8000000000000000 בהתאם לסימון.
|
float-to-double | float a; double result = (double) a; |
המרה של float ל-double , תוך שמירה על הערך בדיוק.
|
double-to-int | double a; int32 result = (int32) a; |
המרה של double ל-int32 , באמצעות בחירת הערך הקרוב לאפס. כאן חלים אותם כללים לגבי מקרים מיוחדים כמו float-to-int .
|
double-to-long | double a; int64 result = (int64) a; |
המרה של double ל-int64 , באמצעות בחירת הערך הקרוב לאפס. כאן חלים אותם כללים לגבי מקרים מיוחדים כמו float-to-long .
|
double-to-float | double a; float result = (float) a; |
המרה של double ל-float באמצעות עיגול לשיא הקרוב. כך פוחת הדיוק של ערכים מסוימים.
|
int-to-byte | int32 a; int32 result = (a << 24) >> 24; |
קיצור של int32 ל-int8 , סימן
להארכת התוצאה.
|
int-to-char | int32 a; int32 result = a & 0xffff; |
חיתוך של int32 ל-uint16 , ללא הרחבת סימן.
|
int-to-short | int32 a; int32 result = (a << 16) >> 16; |
קיצור של int32 ל-int16 , סימן
להארכת התוצאה.
|
add-int | int32 a, b; int32 result = a + b; |
חיבור של משלימים בשניים. |
sub-int | int32 a, b; int32 result = a - b; |
חיסור לפי משלימים של 2. |
rsub-int | int32 a, b; int32 result = b - a; |
חיסור הפוך של השלמה לשניים. |
mul-int | int32 a, b; int32 result = a * b; |
כפל של השלמה לשניים. |
div-int | int32 a, b; int32 result = a / b; |
חילוק לפי השלמה לשניים, מעוגל לכיוון האפס (כלומר, חותכים אותו למספר שלם). הפונקציה מפעילה את ArithmeticException אם
b == 0 .
|
rem-int | int32 a, b; int32 result = a % b; |
השארית של השלמה לשניים אחרי החילוק. סימן התוצאה זהה לסימן של a , והוא מוגדר בצורה מדויקת יותר בתור result == a - (a / b) * b . הפונקציה מפעילה את היוצא ArithmeticException אם b == 0 .
|
and-int | int32 a, b; int32 result = a & b; |
ערך AND ברמת הביטים. |
or-int | int32 a, b; int32 result = a | b; |
ערך OR ברמת הסיביות. |
xor-int | int32 a, b; int32 result = a ^ b; |
ערך XOR ברמת הביטים. |
shl-int | int32 a, b; int32 result = a << (b & 0x1f); |
הזזה ביתית שמאלה (עם ארגומנט מוסתר). |
shr-int | int32 a, b; int32 result = a >> (b & 0x1f); |
הזזה ימינה עם סימן בינארי (עם ארגומנט מוצפן). |
ushr-int | uint32 a, b; int32 result = a >> (b & 0x1f); |
הזזה ימינה ללא סימן בייט (עם ארגומנט מוצפן). |
add-long | int64 a, b; int64 result = a + b; |
חיבור של משלימים בשניים. |
sub-long | int64 a, b; int64 result = a - b; |
חיסור לפי משלימים של 2. |
mul-long | int64 a, b; int64 result = a * b; |
כפל של השלמה לשניים. |
div-long | int64 a, b; int64 result = a / b; |
חילוק לפי השלמה לשניים, מעוגל לכיוון האפס (כלומר, חותכים אותו למספר שלם). הפונקציה מפעילה את ArithmeticException אם
b == 0 .
|
rem-long | int64 a, b; int64 result = a % b; |
השארית של השלמה לשניים אחרי החילוק. סימן התוצאה זהה לסימן של a , והוא מוגדר בצורה מדויקת יותר בתור result == a - (a / b) * b . הפונקציה מפעילה את היוצא ArithmeticException אם b == 0 .
|
and-long | int64 a, b; int64 result = a & b; |
ערך AND ברמת הביטים. |
or-long | int64 a, b; int64 result = a | b; |
ערך OR ברמת הסיביות. |
xor-long | int64 a, b; int64 result = a ^ b; |
ערך XOR ברמת הביטים. |
shl-long | int64 a; int32 b; int64 result = a << (b & 0x3f); |
הזזה ביתית שמאלה (עם ארגומנט מוסתר). |
shr-long | int64 a; int32 b; int64 result = a >> (b & 0x3f); |
הזזה ימינה עם סימן בינארי (עם ארגומנט מוצפן). |
ushr-long | uint64 a; int32 b; int64 result = a >> (b & 0x3f); |
הזזה ימינה ללא סימן בייט (עם ארגומנט מוצפן). |
add-float | float a, b; float result = a + b; |
חיבור של נקודה צפה (floating-point). |
sub-float | float a, b; float result = a - b; |
חיסור של נקודה צפה. |
mul-float | float a, b; float result = a * b; |
כפל של נקודה צפה (floating-point). |
div-float | float a, b; float result = a / b; |
חלוקה של נקודה צפה (floating-point). |
rem-float | float a, b; float result = a % b; |
השארית אחרי החילוק בנקודה צפה. הפונקציה הזו שונה מהיתרה של IEEE 754 ומוגדרת בתור result == a - roundTowardZero(a / b) * b .
|
add-double | double a, b; double result = a + b; |
חיבור של נקודה צפה (floating-point). |
sub-double | double a, b; double result = a - b; |
חיסור של נקודה צפה. |
mul-double | double a, b; double result = a * b; |
כפל של נקודה צפה (floating-point). |
div-double | double a, b; double result = a / b; |
חלוקה של נקודה צפה (floating-point). |
rem-double | double a, b; double result = a % b; |
השארית אחרי החילוק בנקודה צפה. הפונקציה הזו שונה מהיתרה של IEEE 754 ומוגדרת בתור result == a - roundTowardZero(a / b) * b .
|