C6_machine_lang_II

Download Report

Transcript C6_machine_lang_II

‫שפת מכונה – מבוא‬
‫ של‬3 ‫מבוסס על פרק‬
Computer Systems – a programmers perspective / Bryant & O’hallrron
‫נושאים‬
‫קוד מותנה‬

Setting 
Testing 
Control Flow
If-then-else 
Varieties of Loops 
Switch Statements 

‫קוד מותנה‬
‫רגיסטרים ייעודיים בני סיבית אחת‪:‬‬
‫‪Sign Flag‬‬
‫‪Overflow Flag‬‬
‫‪SF‬‬
‫‪OF‬‬
‫‪Carry Flag‬‬
‫‪Zero Flag‬‬
‫‪CF‬‬
‫‪ZF‬‬
‫מופעלים בעת חישוב פעולות אריתמטיות‪ .‬למשל‪:‬‬
‫‪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‬‬
‫–‪–2‬‬
‫קוד מותנה (השמה מפורשת)‬
‫ניתן להשים ערך לסיביות אלה גם באופן מפורש‪ ,‬על ידי פקודת‬
‫‪.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‬‬
‫–‪–3‬‬
jX Instructions
(jumping) ‫קפיצות‬
‫קפיצה מותנית‬
–4–

jX
Condition
Description
jmp
1
Unconditional
je
ZF
Equal / Zero
jne
~ZF
Not Equal / Not Zero
js
SF
Negative
jns
~SF
Nonnegative
jg
~(SF^OF)&~ZF
Greater (Signed)
jge
~(SF^OF)
Greater or Equal (Signed)
jl
(SF^OF)
Less (Signed)
jle
(SF^OF)|ZF
Less or Equal (Signed)
ja
~CF&~ZF
Above (unsigned)
jb
CF
Below (unsigned)
Conditional Branch :‫דוגמה‬
max:
int max(int x, int y)
{
if (x > y)
return x;
else
return y;
}
x
move 8(R1),R3
move 12(R1),R4
compare R4,R3
jle L9
move R3,R4
Body
L9:
x-y signed
‫המקרה של‬
return y
.R4 ‫תוצאת הפונקציה נשמרת ב‬
–5–
‫המשך דוגמה‬
!‫ לא מומלץ‬- goto ‫ מאפשר פקודת‬C
.‫נראה שִ כְתוב של התוכנית הקודמת בדומה יותר לקוד היעד‬
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;
}
–6–
move 8(R1),R3
move 12(R1),R4
compare R4,R3
jle L9
move R3,R4
L9:
#
#
#
#
#
#


R3 = x
R4 = y
x : y
if <= goto L9
R4 = x
Done:
‫דוגמה עם לולאה‬
C Code
int fact_do (int x)
{
int result = 1;
do {
result *= x;
x = x-1;
} while (x > 1);
return result;
}
–7–
Goto Version
int fact_goto(int x)
{
int result = 1;
loop:
result *= x;
x = x-1;
if (x > 1)
goto loop;
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;
}
Registers
R3
R4
–8–
x
result
fact_goto:
move $1,R4
move 8(R1),R3
# R4 = 1
# R3 = x
L11:
multiply R3,R4
decrement R3
compare $1,R3
jg L11
#
#
#
#
result *= x
x-Compare x : 1
if > goto loop
Do-While ‫התבנית הכללית לתרגום‬
Goto Version
C Code
do
Body
while (Test);
loop:
Body
if (Test)
goto loop
C ‫ של‬statement ‫הגוף יכול להיות כל‬

:(compound) ‫ בדר"כ פעולה מורכבת‬
{
}
Statement1;
Statement2;
…
Statementn;
‫ הוא ביטוי המחזיר מספר שלם‬test ‫ה‬
= 0 false
–9–
0 true

while ‫דוגמה ללולאת‬
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;
}
? do-while ‫האם שקול לתוכנית הקודמת שהייתה מבוססת על‬
.‫לא! בגלל האיטרציה הראשונה‬
– 10 –


while ‫התרגום האמיתי של‬
Second Goto Version
C Code
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;
}
‫אותה לולאה פנימית‬
.‫בדיקה נוספת בכניסה ללולאה‬
.‫ מלבד הבדיקה הראשונה‬do-while ‫ כמו‬,‫כלומר‬
– 11 –



while ‫התבנית הכללית לתרגום‬
C Code
while (Test)
Body
– 12 –
Do-While Version
Goto Version
if (!Test)
goto done;
do
Body
while(Test);
done:
if (!Test)
goto done;
loop:
Body
if (Test)
goto loop;
done:
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
– 13 –

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;
}
result
1
1
9
9
531441
– 14 –
x
3
9
81
6561
43046721
p
10
5
2
1
0
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
result = 1
Test
p != 0
{
if (p & 0x1)
result *= x;
x = x*x;
Body
}
– 15 –
Update
p = p >> 1
“For” “While”
For Version
for (Init; Test; Update )
Body
Do-While Version
Init;
if (!Test)
goto done;
do {
Body
Update ;
} while (Test)
done:
– 16 –
While Version
Init;
while (Test ) {
Body
Update ;
}
Goto Version
Init;
if (!Test)
goto done;
loop:
Body
Update ;
if (Test)
goto loop;
done:
“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:
Init
result = 1
Test
p != 0
Body
{
if (p & 0x1)
result *= x;
x = x*x;
Update
p = p >> 1
}
– 17 –
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 '?';
}
}
.‫ אין ברירת מחדל‬:‫באג בדוגמה‬
– 18 –

Jump Table ‫המבנה של ה‬
Switch Form
switch(op) {
case val_0:
Block 0
case val_1:
Block 1
• • •
case val_n-1:
Block n–1
}
Jump Table
jtab:
Targ0
Jump Targets
Targ0:
Targ1
Targ2
•
•
•
Targn-1
Targ1:
Targ2:
Code Block
1
Code Block
2
•
•
•
Approx. Translation
target = JTab[op];
goto *target;
Targn-1:
– 19 –
Code Block
0
Code Block
n–1
Switch :‫דוגמה‬
Branching Possibilities
Enumerated Values
ADD
MULT
MINUS
DIV
MOD
BAD
typedef enum
{ADD, MULT, MINUS, DIV, MOD, BAD}
op_type;
char unparse_symbol(op_type op)
{
switch (op) {
• • •
// returns ASCII of op
}
}
:‫תזכורת‬
R4 – 5 ‫ מבצע‬compare •
‫ אם יש גלישה על פי‬cf = 1 •
.unsigned
~cf & ~zf ‫ הוא‬ja ‫• התנאי של‬
– 20 –
unparse_symbol:
move 8(R1),R4
compare $5,R4
ja .L49
jmp *.L57(,R4,4)
#
#
#
#
0
1
2
3
4
5
R4 = op
Compare op : 5
If > goto done
goto Table[op]
‫הסבר‬
‫‪Labels‬‬
‫‪‬‬
‫תוויות מהצורה ‪ .Lxx‬מתורגם לכתובת על ידי ה ‪assembler‬‬
‫מבנה הטבלה‬
‫‪‬‬
‫‪‬‬
‫כל יעד דורש ‪ 4‬בתים‪.‬‬
‫הבסיס (‪ )Base address‬ב ‪L57‬‬
‫קפיצות‪:‬‬
‫‪jmp .L49‬‬
‫‪‬‬
‫היעד מסומן על ידי תוית ‪.L49‬‬
‫‪‬‬
‫כתובת תחילת הטבלה ‪.L57‬‬
‫‪‬‬
‫‪ R4‬מחזיק את ‪ .op‬משם ‪ -‬קפיצות של ‪4‬‬
‫היעד נמצא ב ‪.L57 + op*4‬‬
‫כלומר‪ :‬בפעולה אחת נמצא את הכתובת של הקוד לביצוע !‬
‫)‪jmp *.L57(,R4,4‬‬
‫‪‬‬
‫‪‬‬
‫– ‪– 21‬‬
Jump Table
Table Contents
Targets & Completion
.section .rodata
.align 4
.L57:
.long .L51 #Op =
.long .L52 #Op =
.long .L53 #Op =
.long .L54 #Op =
.long .L55 #Op =
.long .L56 #Op =
.L51:
move $43,R4
# ’+’
jmp .L49
43 is the
.L52:
ASCII value
of ‘+’
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
– 22 –
0
1
2
3
4
5
.R4 ‫הפרוצדורה תחזיר את הערך ב‬
‫חידה‬
‫חידה‬
‫‪‬‬
‫אם ‪ op‬לא נמצא בטבלה ואין ברירת מחדל – איזה ערך מוחזר ?‬
‫תשובה‬
‫‪‬‬
‫‪‬‬
‫הערך של ‪ op‬עצמו‪.‬‬
‫למה ? כי בהתחלת הפרוצדורה ביצענו השמה של ‪ op‬ל ‪.R4‬‬
‫– ‪– 23‬‬
‫‪ switch‬לעומת ‪if‬‬
‫היתרון של ‪Jump Table‬‬
‫‪‬‬
‫יכול לבצע ‪ k-way branch‬ב ‪.O(1) -‬‬
‫החיסרון של ‪Jump Table‬‬
‫‪‬‬
‫‪‬‬
‫גודל הטבלה כגודל הטווח בין הערך המינימאלי למקסימאלי‪.‬‬
‫כלומר‪ ,‬לא בהכרח פרופורציוני למספר הכניסות ב ‪.switch‬‬
‫שורה של תנאי ‪if‬‬
‫ טוב אם יש מספר קטן‬‫ איטי מדי אם יש מספר גדול של‬‫תנאים‪.‬‬
‫‪switch‬‬
‫ טוב כשהמקרים הם קבועים‬‫יחסית קטנים‬
‫‪ -‬נמנע מ ‪conditionals‬‬
‫אופטימיזציה של ‪ :GCC‬בוחר לבד לפי המבנה‬
‫– ‪– 24‬‬
'‫ 'דליל‬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;
}
}
– 25 –
jump table ‫ לא מעשי ליישם כ‬
.‫ כניסות‬1000 ‫ ידרוש טבלה של‬
‫ ידרוש‬if-then-else ‫ התרגום ל‬
.‫ בדיקות‬9
‫קוד של ‪' Switch‬דליל'‬
‫‪‬‬
‫‪‬‬
‫המהדר הפך לרשימת ‪if‬‬
‫משווה לערכים שונים של ‪ x‬וקופץ למקומות שונים בהתאם לתוצאה‪.‬‬
‫ללא אופטימיזציות‪jump table :‬‬
‫‪. . .‬‬
‫‪L5:‬‬
‫‪# get x‬‬
‫‪# x:444‬‬
‫‪L6:‬‬
‫‪# x:111‬‬
‫‪L7:‬‬
‫‪# x:0‬‬
‫‪move $1,R4‬‬
‫‪jmp L19‬‬
‫‪move $2,R4‬‬
‫‪jmp L19‬‬
‫‪move $3,R4‬‬
‫‪jmp L19‬‬
‫‪L8:‬‬
‫‪move $4,R4‬‬
‫‪jmp L19‬‬
‫‪. . .‬‬
‫קוד ‪ if‬בעקבות אופטימיזציה של המהדר‬
‫‪move 8(R1),R4‬‬
‫‪compare $444,R4‬‬
‫‪je L8‬‬
‫‪jg L16‬‬
‫‪compare $111,R4‬‬
‫‪je L5‬‬
‫‪jg L17‬‬
‫‪testl R4,R4‬‬
‫‪je L4‬‬
‫‪jmp L14‬‬
‫מדוע דווקא הסדר הזה ?‬
‫‪. . .‬‬
‫– ‪– 26‬‬
‫מבנה של קוד ‪ Switch‬דליל‬
‫>‬
‫=‬
‫‪4‬‬
‫‪777‬‬
‫>‬
‫‪444‬‬
‫<‬
‫‪111‬‬
‫>‬
‫<‬
‫=‬
‫‪1‬‬
‫‪7‬‬
‫‪888‬‬
‫>‬
‫=‬
‫‪555‬‬
‫<‬
‫‪‬‬
‫=‬
‫‪8‬‬
‫‪999‬‬
‫=‬
‫‪9‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪-1‬‬
‫=‬
‫<‬
‫‪222‬‬
‫‪‬‬
‫‪5‬‬
‫‪666‬‬
‫=‬
‫‪6‬‬
‫‪‬‬
‫‪-1‬‬
‫=‬
‫‪2‬‬
‫‪333‬‬
‫=‬
‫‪3‬‬
‫‪0‬‬
‫=‬
‫‪0‬‬
‫‪‬‬
‫‪-1‬‬
‫‪‬‬
‫‪-1‬‬
‫מארגן את המקרים לפי עץ בינארי‪.‬‬
‫זמן חיפוש לוגריתמי‪.‬‬
‫‪ ‬כיצד נוצר החיסכון ? המיון נעשה בשלב ההידור במקום בזמן ריצה‪.‬‬
‫– ‪– 27‬‬
1 ‫סיכום‬
C Control




if-then-else
do-while
while
switch
Assembler Control


jump
Conditional jump
‫ כדי לממש פקודות מורכבות‬assembly ‫• המהדר חייב לשלב פקודות‬
.‫יותר‬
– 28 –
‫סיכום ‪2‬‬
‫טכניקות סטנדרטיות‪:‬‬
‫‪‬‬
‫‪‬‬
‫כל הלולאות מתורגמות ל ‪do-while‬‬
‫פעולות ‪ switch‬מתורגמות ל ‪jump tables‬‬
‫תנאים ב ‪CISC‬‬
‫‪‬‬
‫בדר"כ מחשבי ‪ CISC‬מכילים רגיסטרים מיוחדים לתנאים‬
‫תנאים ב ‪RISC‬‬
‫‪‬‬
‫‪‬‬
‫משתמשים ברגיסטרים כלליים‬
‫פקודות מיוחדות להשוואה‬
‫‪ ‬למשל‪ ,‬על מחשבי ‪:Alpha‬‬
‫‪comparee $16,1,$1‬‬
‫‪ Sets register $1 to 1 when Register $16 <= 1‬‬
‫– ‪– 29‬‬