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