1 / 29

שפת מכונה – מבוא

שפת מכונה – מבוא. נושאים קוד מותנה Setting Testing Control Flow If-then-else Varieties of Loops Switch Statements. מבוסס על פרק 3 של Computer Systems – a programmers perspective / Bryant & O’hallrron. קוד מותנה. רגיסטרים ייעודיים בני סיבית אחת: CF Carry Flag SF Sign Flag

yoshi
Download Presentation

שפת מכונה – מבוא

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. שפת מכונה – מבוא • נושאים • קוד מותנה • Setting • Testing • Control Flow • If-then-else • Varieties of Loops • Switch Statements מבוסס על פרק 3 של Computer Systems – a programmers perspective / Bryant & O’hallrron

  2. קוד מותנה • רגיסטרים ייעודיים בני סיבית אחת: CF Carry Flag SF Sign Flag ZF Zero Flag OF Overflow Flag • מופעלים בעת חישוב פעולות אריתמטיות. למשל: add Src,Dest C analog: t = a + b • CF = 1 אם יש גלישה בחישוב Unsigned • ZF = 1 אם t == 0 • SF = 1 אם t < 0 • OF = 1 אם גלישה בחישוב signed • למשל, ראינו שבחיבור יש גלישה אם: (a>0 && b>0 && t<0) || (a<0 && b<0 && t>=0)

  3. קוד מותנה (השמה מפורשת) • ניתן להשים ערך לסיביות אלה גם באופן מפורש, על ידי פקודת compare. compare Src2,Src1 • compare b,a – כמו חישובa-bבלי יעד. test Src2,Src1 • test b,a - כמו חישובa&bבלי יעד • ZF כאשר a&b == 0 • SF כאשר a&b < 0

  4. קפיצות (jumping) • jX Instructions • קפיצה מותנית

  5. דוגמה:Conditional Branch max: move 8(R1),R3 move 12(R1),R4 compare R4,R3 jle L9 move R3,R4 L9: x int max(int x, int y) { if (x > y) return x; else return y; } Body x-y signed המקרה של return y תוצאת הפונקציה נשמרת ב R4.

  6. המשך דוגמה • C מאפשר פקודת goto - לא מומלץ! • נראה שִכְתוב של התוכנית הקודמת בדומה יותר לקוד היעד. int goto_max(int x, int y) { int tmp = x; int return_val = y; int ok = (x <= y); if (ok) goto done; return_val = x; done: return return_val; } move 8(R1),R3 # R3 = x move 12(R1),R4 # R4 = y compare R4,R3 # x : y jle L9 # if <= goto L9 move R3,R4 # R4 = x L9: # Done:

  7. דוגמה עם לולאה C Code Goto Version int fact_do (int x) { int result = 1; do { result *= x; x = x-1; } while (x > 1); return result; } int fact_goto(int x) { int result = 1; loop: result *= x; x = x-1; if (x > 1) goto loop; return result; }

  8. אחרי הידור... • Registers R3 x R4 result Goto Version int fact_goto (int x) { int result = 1; loop: result *= x; x = x-1; if (x > 1) goto loop; return result; } fact_goto: move $1,R4 # R4 = 1 move 8(R1),R3 # R3 = x L11: multiply R3,R4 # result *= x decrement R3 # x-- compare $1,R3 # Compare x : 1 jg L11 # if > goto loop

  9. התבנית הכללית לתרגוםDo-While Goto Version C Code • הגוף יכול להיות כל statementשל C • בדר"כ פעולה מורכבת (compound): • ה test הוא ביטוי המחזיר מספר שלם = 0 false 0 true do Body while (Test); loop: Body if (Test) goto loop { Statement1; Statement2; … Statementn; }

  10. דוגמה ללולאת while First Goto Version C Code • האם שקול לתוכנית הקודמת שהייתה מבוססת על do-while ? • לא! בגלל האיטרציה הראשונה. int fact_while(int x) { int result = 1; while (x > 1) { result *= x; x = x-1; }; return result; } int fact_while_goto(int x) { int result = 1; loop: if (!(x > 1)) goto done; result *= x; x = x-1; goto loop; done: return result; }

  11. התרגום האמיתי של while Second Goto Version C Code • אותה לולאה פנימית • בדיקה נוספת בכניסה ללולאה. • כלומר, כמו do-while מלבד הבדיקה הראשונה. int fact_while(int x) { int result = 1; while (x > 1) { result *= x; x = x-1; }; return result; } int fact_while_goto2(int x) { int result = 1; if (!(x > 1)) goto done; loop: result *= x; x = x-1; if (x > 1) goto loop; done: return result; }

  12. התבנית הכללית לתרגום while C Code while (Test) Body Goto Version Do-While Version if (!Test) goto done; loop: Body if (Test) goto loop; done: if (!Test) goto done; do Body while(Test); done:

  13. לולאות for /* Compute x raised to nonnegative power p */ int pwr(int x, unsigned p) { int result; for (result = 1; p != 0; p = p>>1) { if (p & 0x1) result *= x; x = x*x; } return result; } • אלגוריתם • סיבוכיות: O(log p) Example 310 = 32 * 38 = 32 * ((32) 2) 2

  14. דוגמה לחישוב של pwr /* Compute x raised to nonnegative power p */ int pwr(int x, unsigned p) { int result; for (result = 1; p != 0; p = p>>1) { if (p & 0x1) result *= x; x = x*x; } return result; }

  15. דוגמה ללולאת For צורה כללית int result; for (result = 1; p != 0; p = p>>1) { if (p & 0x1) result *= x; x = x*x; } for (Init; Test; Update ) Body Init Test Update result = 1 p != 0 p = p >> 1 { if (p & 0x1) result *= x; x = x*x; } Body

  16. “For” “While” For Version While Version for (Init; Test; Update ) Body Init; while (Test ) { Body Update ; } Do-While Version Goto Version Init; if (!Test) goto done; do { Body Update ; } while (Test) done: Init; if (!Test) goto done; loop: Body Update ; if (Test) goto loop; done:

  17. Init Test result = 1 p != 0 Update p = p >> 1 הידור של לולאת“for” Goto Version result = 1; if (p == 0) goto done; loop: if (p & 0x1) result *= x; x = x*x; p = p >> 1; if (p != 0) goto loop; done: Init; if (!Test) goto done; loop: Body Update ; if (Test) goto loop; done: Body { if (p & 0x1) result *= x; x = x*x; }

  18. פקודות Switch typedef enum {ADD, MULT, MINUS, DIV, MOD, BAD} op_type; char unparse_symbol(op_type op) { switch (op) { case ADD : return '+'; case MULT: return '*'; case MINUS: return '-'; case DIV: return '/'; case MOD: return '%'; case BAD: return '?'; } } • באג בדוגמה: אין ברירתמחדל.

  19. Targ0: Code Block 0 jtab: Targ0 Targ1 Targ2 Targ1: Code Block 1 • • • Targ2: Code Block 2 Targn-1 • • • Targn-1: Code Block n–1 המבנה של הJump Table Jump Targets Switch Form Jump Table switch(op) { case val_0: Block 0 case val_1: Block 1 • • • case val_n-1: Blockn–1 } Approx. Translation target = JTab[op]; goto *target;

  20. תזכורת: • compare מבצע R4 – 5 • cf = 1 אם יש גלישה על פי unsigned . • התנאי של ja הוא ~cf & ~zf דוגמה: Switch • Enumerated Values • ADD 0 • MULT 1 • MINUS 2 • DIV 3 • MOD 4 • BAD 5 • Branching Possibilities typedef enum {ADD, MULT, MINUS, DIV, MOD, BAD} op_type; char unparse_symbol(op_type op) { switch (op) { • • • // returns ASCII of op } } unparse_symbol: move 8(R1),R4 # R4 = op compare $5,R4 # Compare op : 5 ja .L49 # If > goto done jmp *.L57(,R4,4) # goto Table[op]

  21. הסבר • Labels • תוויות מהצורה .Lxx מתורגם לכתובת על ידי ה assembler • מבנה הטבלה • כל יעד דורש 4 בתים. • הבסיס (Base address) ב L57 • קפיצות: jmp .L49 • היעד מסומן על ידי תוית .L49 jmp *.L57(,R4,4) • כתובת תחילת הטבלה .L57 • R4 מחזיק את op. משם - קפיצות של 4 • היעד נמצא ב .L57 + op*4 • כלומר: בפעולה אחת נמצא את הכתובת של הקוד לביצוע !

  22. Jump Table Targets & Completion Table Contents .L51: move $43,R4 # ’+’ jmp .L49 .L52: move $42,R4 # ’*’ jmp .L49 .L53: move $45,R4 # ’-’ jmp .L49 .L54: move $47,R4 # ’/’ jmp .L49 .L55: move $37,R4 # ’%’ jmp .L49 .L56: move $63,R4 # ’?’ # Fall Through to .L49 .section .rodata .align 4 .L57: .long .L51 #Op = 0 .long .L52 #Op = 1 .long .L53 #Op = 2 .long .L54 #Op = 3 .long .L55 #Op = 4 .long .L56 #Op = 5 43 is the ASCII value of ‘+’ הפרוצדורה תחזיר את הערך ב R4.

  23. חידה • חידה • אם op לא נמצא בטבלה ואין ברירת מחדל – איזה ערך מוחזר ? • תשובה • הערך שלop עצמו. • למה ? כי בהתחלת הפרוצדורה ביצענו השמה של op ל R4.

  24. switch לעומת if • היתרון של Jump Table • יכול לבצע k-way branch ב - O(1). • החיסרון של Jump Table • גודל הטבלה כגודל הטווח בין הערך המינימאלי למקסימאלי. • כלומר, לא בהכרח פרופורציוני למספר הכניסות ב switch. • switch • - טוב כשהמקרים הם קבועים יחסית קטנים • - נמנע מ conditionals • שורה של תנאי if • - טוב אם יש מספר קטן • - איטי מדי אם יש מספר גדול של תנאים. • אופטימיזציה שלGCC : בוחר לבד לפי המבנה

  25. דוגמה לSwitch 'דליל' /* Return x/111 if x is multiple && <= 999. -1 otherwise */ int div111(int x) { switch(x) { case 0: return 0; case 111: return 1; case 222: return 2; case 333: return 3; case 444: return 4; case 555: return 5; case 666: return 6; case 777: return 7; case 888: return 8; case 999: return 9; default: return -1; } } • לא מעשי ליישם כ jump table • ידרוש טבלה של 1000 כניסות. • התרגום ל if-then-else ידרוש 9 בדיקות.

  26. קוד של Switch 'דליל' • המהדר הפך לרשימת if • משווה לערכים שונים של xוקופץ למקומות שונים בהתאם לתוצאה. ללא אופטימיזציות:jump table קוד if בעקבות אופטימיזציה של המהדר . . . L5: move $1,R4 jmp L19 L6: move $2,R4 jmp L19 L7: move $3,R4 jmp L19 L8: move $4,R4 jmp L19 . . . move 8(R1),R4 # get x compare $444,R4 # x:444 je L8 jg L16 compare $111,R4 # x:111 je L5 jg L17 testl R4,R4 # x:0 je L4 jmp L14 . . . מדוע דווקא הסדר הזה ?

  27. 444 111 777 0 222 555 888 -1 -1 -1 -1 333 666 999 מבנה של קוד Switch דליל • מארגן את המקרים לפי עץ בינארי. • זמן חיפוש לוגריתמי. • כיצד נוצר החיסכון ? המיון נעשה בשלב ההידור במקום בזמן ריצה. < > = 4 < > < > = = 1 7 < >  =  = =  = 2 5 8 0    = = = 3 9 6

  28. C Control if-then-else do-while while switch סיכום 1 • Assembler Control • jump • Conditional jump • המהדר חייב לשלב פקודות assembly כדי לממש פקודות מורכבות יותר.

  29. סיכום 2 • טכניקות סטנדרטיות: • כל הלולאות מתורגמות ל do-while • פעולות switch מתורגמות ל jump tables • תנאים ב CISC • בדר"כ מחשבי CISC מכילים רגיסטרים מיוחדים לתנאים • תנאים ב RISC • משתמשים ברגיסטרים כלליים • פקודות מיוחדות להשוואה • למשל, על מחשבי Alpha: comparee $16,1,$1 • Sets register $1 to 1 when Register $16 <= 1

More Related