Presentation is loading. Please wait.

Presentation is loading. Please wait.

נושאים קוד מותנה Setting Testing Control Flow If-then-else Varieties of Loops Switch Statements שפת מכונה – מבוא מבוסס על פרק 3 של Computer Systems – a.

Similar presentations


Presentation on theme: "נושאים קוד מותנה Setting Testing Control Flow If-then-else Varieties of Loops Switch Statements שפת מכונה – מבוא מבוסס על פרק 3 של Computer Systems – a."— 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 – 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)

3 – 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 – 4 – קפיצות (jumping) jX Instructions קפיצה מותנית

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

6 – 6 – המשך דוגמה 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: 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; } C מאפשר פקודת goto - לא מומלץ! נראה שִכְתוב של התוכנית הקודמת בדומה יותר לקוד היעד.

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

8 – 8 – Goto Version int fact_goto (int x) { int result = 1; loop: result *= x; x = x-1; if (x > 1) goto loop; return result; } אחרי הידור... Registers R3x R4result 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 – 9 – C Code do Body while ( Test ); Goto Version loop: Body if ( Test ) goto loop התבנית הכללית לתרגוםDo-While הגוף יכול להיות כל statementשל C בדר"כ פעולה מורכבת (compound): ה test הוא ביטוי המחזיר מספר שלם = 0 false  0 true { Statement 1 ; Statement 2 ; … Statement n ; }

10 – 10 – C Code int fact_while(int x) { int result = 1; while (x > 1) { result *= x; x = x-1; }; return result; } First Goto Version 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; } דוגמה ללולאת while האם שקול לתוכנית הקודמת שהייתה מבוססת על do-while ? לא! בגלל האיטרציה הראשונה.

11 – 11 – C Code int fact_while(int x) { int result = 1; while (x > 1) { result *= x; x = x-1; }; return result; } Second Goto Version 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; } אותה לולאה פנימית בדיקה נוספת בכניסה ללולאה. כלומר, כמו do-while מלבד הבדיקה הראשונה. התרגום האמיתי של while

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

13 – 13 – לולאות for אלגוריתם סיבוכיות : O(log p) /* 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; } Example 3 10 = 3 2 * 3 8 = 3 2 * ((3 2 ) 2 ) 2

14 – 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 – 15 – דוגמה ללולאת For for ( Init ; Test ; Update ) Body int result; for (result = 1; p != 0; p = p>>1) { if (p & 0x1) result *= x; x = x*x; } צורה כללית Init result = 1 Test p != 0 Update p = p >> 1 Body { if (p & 0x1) result *= x; x = x*x; }

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

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

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

20 – 20 – דוגמה: Switch Branching Possibilities 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] Enumerated Values ADD0 MULT1 MINUS2 DIV3 MOD4 BAD5 typedef enum {ADD, MULT, MINUS, DIV, MOD, BAD} op_type; char unparse_symbol(op_type op) { switch (op) { // returns ASCII of op } תזכורת: compare מבצע R4 – 5 cf = 1 אם יש גלישה על פי unsigned. התנאי של ja הוא ~cf & ~zf

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

22 – 22 – Jump Table.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 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 Targets & Completion 43 is the ASCII value of ‘+’ הפרוצדורה תחזיר את הערך ב R4.

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

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

25 – 25 – דוגמה לSwitch 'דליל' לא מעשי ליישם כ jump table ידרוש טבלה של 1000 כניסות. התרגום ל if-then-else ידרוש 9 בדיקות. /* Return x/111 if x is multiple && <= 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; }

26 – 26 – קוד של Switch 'דליל' המהדר הפך לרשימת if משווה לערכים שונים של xוקופץ למקומות שונים בהתאם לתוצאה. 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... L5: move $1,R4 jmp L19 L6: move $2,R4 jmp L19 L7: move $3,R4 jmp L19 L8: move $4,R4 jmp L19... קוד if בעקבות אופטימיזציה של המהדר ללא אופטימיזציות: jump table מדוע דווקא הסדר הזה ?

27 – 27 – מבנה של קוד Switch דליל מארגן את המקרים לפי עץ בינארי. זמן חיפוש לוגריתמי. כיצד נוצר החיסכון ? המיון נעשה בשלב ההידור במקום בזמן ריצה <  = > = <> = <> = <> =  =  =  =  =  =

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

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


Download ppt "נושאים קוד מותנה Setting Testing Control Flow If-then-else Varieties of Loops Switch Statements שפת מכונה – מבוא מבוסס על פרק 3 של Computer Systems – a."

Similar presentations


Ads by Google