שפת סף
שפת סף או אַסֶמבּלי (באנגלית: Assembly) היא שפת התכנות הבסיסית והקרובה ביותר לשפת מכונה.
בשפת הסף, בצורתה הבסיסית, קיימת התאמה בין ההוראות שכותב המתכנת ובין ההוראות המופקות מהן בשפת מכונה, כלומר, כל הוראה יחידה באסמבלי מתורגמת להוראה אחת או יותר בשפת מכונה. לכן, כמו שפת המכונה, גם שפת הסף פועלת באופן ישיר על תאי הזיכרון של המחשב, על האוגרים הפנימיים של המעבד ועל יציאות הקלט/פלט של המחשב, ובפרטנות רבה. כתוצאה מכך, לכל סדרת מעבדים יש שפת סף משלה, כתלות בסט הפקודות של המעבד.
![](http://up.wiki.x.io/wikipedia/commons/thumb/f/f3/Motorola_6800_Assembly_Language.png/220px-Motorola_6800_Assembly_Language.png)
תכנות בשפת סף נחשב לקשה הרבה יותר מבשפות התכנות העיליות, בין היתר משום ששפת סף אינה אינטואיטיבית וקלה לקריאה כמו השפות העיליות. תכנות בשפת סף, במיוחד כזה הנחשב ליעיל, מחייב להכיר היטב את חומרת המחשב, בעוד שבשפות עיליות המהדר דואג להתאימן לחומרה. מעבר לכך, לשם ביצוע כל פעולה, ולו הפשוטה ביותר, עשויות להידרש הוראות שפת סף רבות. לדוגמה, כדי להציב במשתנה A את סכומם של המשתנים B ו־C, מספיקה בשפה עילית פקודה יחידה מצורה דומה ל־ A := B + C. באסמבלי, לעומת זאת, הפעולה תהיה ארוכה יותר, לדוגמה:
mov ax, B
– העבר את הערך B אל אוגר ax
add ax, C
– הוסף את הערך C לערך שנמצא באוגר ax
mov A, ax
– העבר את הערך שנמצא באוגר ax אל הכתובת של המשתנה A
התכנות בשפת סף היה נפוץ למדי ואפילו דומיננטי, למרות הקושי שבו, עד לתחילת שנות ה־70 של המאה העשרים, וזאת בשל משאבי המחשב המוגבלים שעמדו לרשות המתכנתים ובשל היכולת ליצור קוד יעיל במהירות־הביצוע וחסכוני בזיכרון, יותר מקוד שנוצר בשפות עיליות. בעקבות השתכללות המהדרים של השפות העיליות, לא נותר עוד הבדל משמעותי שיצדיק את הטרחה שבכתיבה בשפת סף, והשימוש בה נדיר כיום. כיום היא משמשת בעיקר כותבי מערכות הפעלה, מפתחים של חלקי תוכנה שדרושים להם ביצועים מהירים במיוחד או תקשורת ישירה עם רכיבי חומרה (כמו מנהלי התקנים), וכן כותבי וירוסים מתוחכמים.
המהדר של שפת הסף, המתרגם את קובצי ההוראות לשפת מכונה, נקרא אסמבלר (Assembler).
בגלל ששפת סף תלויה בקוד המכונה שספציפי למערכות מחשוב שונות, כל שפת סף יכולה לשמש רק לארכיטקטורת מחשב מסוימת.
אסמבלי במעבדי 8086
עריכההקדמה
עריכהנכון לשנת 2020, חלק גדול מהמעבדים בשוק מבוססים על סדרת 8086 של אינטל, וגם שפת הסף שלהם מבוססת על שפת הסף של המעבד אינטל 8086.
היות ששפת אסמבלי עוסקת בגישה ישירה לזיכרון ולהתקנים חיצוניים (באמצעות out
ו־in
), רצוי להכיר מספר עקרונות מנחים בסיסים:
ארכיטקטורת פון נוימן – על פי ארכיטקטורה זו, אשר פותחה על ידי מדען המחשב והמתמטיקאי ג'ון פון נוימן במאה ה־20, הנתונים וההוראות מאוחסנים באותו זיכרון. המחשב עצמו מחולק ל־4 רכיבים מרכזיים:
- זיכרון – מכיל נתונים, כתובות, והוראות
- מעבד – מקבל, מפרש ומריץ את ההוראות מהזיכרון
- התקנים חיצוניים (I/O – Input/Output) – כגון מקלדת, עכבר, רמקול, מיקרופון או דיסק און קי.
- אפיקי נתונים (Busses) – פסים אלו אחראים להעברת נתונים, הוראות, ופקודות בקרה בין המעבד, הזיכרון, וההתקנים החיצוניים. בעבר, רוחב של אפיק נתונים היה בגודל "מילה" (16 סיביות) או 32 סיביות ("מילה כפולה" – Double Word), אך במחשבים רבים היום הוא כבר 64 סיביות.
הגדרת סביבת עבודה
עריכהכתיבת הקוד בשפת סף מחולקת למספר שדות הנקראים מקטעים (segments). במקטע אשר מיועד ליצירת משתנים, יש ליצור משתנים. במקטע אשר נועד להגדרת מחסניות, יש להגדיר מחסניות. במקטע אשר מיועד לכתיבת קוד, יש לכתוב קוד, וכן הלאה. המקטעים נקראים בשמות שונים בסביבות עבודה שונות. טקסט זה יכיל את 3 המקטעים העיקריים:
- מקטע המידע –
data segment
, נקרא לעיתיםDATASEG
- מקטע המחסנית –
stack segment
- מקטע הקוד –
Code Segment
, אשר נקרא לעיתיםCODESEG
אחת מסביבות העבודה הנוחות ביותר ללמידת שפת סף היא Emu8086 אשר פועלת במערכת ההפעלה Windows. סביבה זו היא בעצם אמולציה של המעבד הישן 8086 של אינטל (אשר פתח את סדרת מעבדי x86).
אוגרים
עריכהאוגרים (Registers) הם יחידות זיכרון של המעבד שבאמצעותן מתבצעות פעולות שונות. למעבד לוקח זמן מאוד קצר לגשת אליהם ולכן שימוש בהם הוא יעיל.
האוגרים בטבלה להלן נכונים לדור הבסיסי של מעבד 8086 – כיום נעשו שינויים – הוסיפו ושינו אוגרים בהתאם להתפתחות הטכנולוגיה. למשל ax, שגודלו 16 סיביות הוא חלק מאוגר eax שגודלו 32 סיביות (Double Word). עם זאת, האוגרים המצוינים בטבלה עדיין תקפים מפאת עקרון התאימות לאחור של מעבדי אינטל (קוד שנכתב למעבד ישן יותר יהיה ניתן להרצה על מעבד חדיש יותר). כל אחד מארבעת האוגרים ax
, bx
, cx
ו־dx
מורכב מ־2 אוגרים של 8 ביט – h (high) ו־l (low). שינוי של אחד מהאוגרים הקטנים יוביל לשינוי אוגר גדול, ולהפך – שינוי של אוגר גדול יוביל לשינוי של האוגרים הקטנים. לדוגמה, אם נשנה את al, ערך ax ישתנה בהתאם, ולהפך.
האוגר | מספר סיביות | תפקיד |
---|---|---|
ax (Accumulator Register – צובר)
מורכב משני אוגרים של 8 ביט: al, ah |
16 | משמש לפעולות אריתמטיות ולוגיות. ניתן לבצע זאת באוגרים אחרים, אך השימוש ב־ax בדרך כלל יעיל יותר. |
bx (Base Address Register – כתובת בסיס)
מורכב משני אוגרים של 8 ביט: bl, bh |
16 | משמש לשמירת כתובות בזיכרון |
cx (Count Register – מונה)
מורכב משני אוגרים של 8 ביט: cl, ch |
16 | המונה מונה דברים, כגון כמות הפעמים שהלולאה בוצעה, או כמות תווים בקובץ או במחרוזת. |
dx (Data Register – מידע)
מורכב משני אוגרים של 8 ביט: dl, dh |
16 | משמש לפעולות אריתמטיות מסוימות וכן לשמירת כתובות של התקנים חיצוניים |
si (Source Index – מצביע מקור) | 16 | ניתן להשתמש בו כמצביע כדי לפנות לכתובת בזיכרון, ובטיפול במחרוזות |
di (Destination Index – מצביע יעד) | 16 | כמו si, ניתן להשתמש בו כמצביע כדי לפנות לכתובת בזיכרון, ובטיפול במחרוזות |
bp (Base Pointer – מצביע בסיס) | 16 | שומר את המיקום האחרון של מקטע המחסנית |
sp (Stack Pointer – מצביע מחסנית) | 16 | מצביע על הכתובת בזיכרון שמכילה את ראש המחסנית. שינוי אוגר זה יגרום לתקלות בתוכנית. אין לשנותו. |
ip – קיצור של Instruction Pointer | מצביע על כתובת הזיכרון שתוכנה עומד לעיבוד. פקודות קפיצה (jump) משתמשות באוגר זה על מנת לקפוץ לכתובת שונה בקוד התוכנה. | |
ds – קיצור של data segment | מצביע על הכתובת של מקטע המידע | |
ss – קיצור של stack segment | מצביע על הכתובת של מקטע המחסנית | |
cs – קיצור של code segment | מצביע על הכתובת של מקטע הקוד | |
es – קיצור של extra segment | מצביע על הכתובת של מקטע הזיכרון העודף | |
FLAGS – אוגר הדגלים | 16 | מייצג שורה של ״דגלים״ אשר נדלקים בהתאם להתרחשותם של אירועים שונים בתוכנה. לדוגמה, דגל האפס (zero flag) "יוּרם" (יהפוך מ־0 ל־1) כאשר תוצאה של פקודה כלשהי תהיה 0. |
פקודות בסיסיות
עריכהפקודות מובנות באסמבלי יכולות לקבל בין 0 ל־2 ערכים. הן מבצעות פעולות לוגיות ואריתמטיות כגון השמה, חיבור, חיסור, כפל, חילוק, השוואה, קפיצות (jmp), קפיצות מותנות (je, jne, jb, ja וכו׳).
הפקודה | מספר האופרנדים | מה היא עושה | דוגמאות |
---|---|---|---|
mov a, b | 2 (פעולה בינארית) | השמה
a = b |
mov ax,5
|
add a, b | 2 (פעולה בינארית) | חיבור
a = a + b |
add bl,al
|
sub a, b | 2 (פעולה בינארית) | חיסור
a = a - b |
sub al,ah
|
inc a | 1 (פעולה אונארית) | הוספת 1 (increment)
a = a + 1 |
inc cx
|
dec a | 1 (פעולה אונארית) | חיסור 1 (decrement)
a = a - 1 |
dec bx
|
neg a | 1 (פעולה אונארית) | מינוס
a = - a |
neg ch
|
mul a | 1 (פעולה אונארית) | כפל, ושמירה של התוצאה באוגר ax
ax = ax * a |
|
imul a | 1 (פעולה אונארית) | כפל של מספרים לא מסומנים (unisigned)
ax = ax * a |
|
div a | 1 (פעולה אונארית) | חילוק, ושמירה של התוצאה באוגר ax
|
|
idiv a | 1 (פעולה אונארית) | חילוק מספרים לא מסומנים (unsinged)
|
|
not a | 1 (פעולה אונארית) | ||
and a b | 2 (פעולה בינארית) | ||
or a b | 2 (פעולה בינארית) | ||
jmp label | 1 (פעולה אונארית) | קפיצה לתווית מסוימת בקוד (לשורה אחרת) | mov ax,6 jmp skip inc bx sub cx,4 :skip
|
je label | 1 (פעולה אונארית) | קפיצה לתווית מסוימת אם שני ערכים שווים בערכם | cmp al, 6 je after inc bl :after
|
jne label | 1 (פעולה אונארית) | קפיצה לתווית מסוימת אם שני ערכים לא שווים בערכם | |
ja label | 1 (פעולה אונארית) | קפיצה לתווית מסוימת אם הערך הראשון גדול מהשני | |
jb label | 1 (פעולה אונארית) | קפיצה לתווית מסוימת אם הערך הראשון קטן מהשני | |
loop label | 1 (פעולה אונארית) | לולאה לתווית מסוימת, חוזרת CX פעמים בכך שמורידה
את ערכו כל ריצה ב-1. |
דוגמאות קוד
עריכהמאקרו למעבר שורה:
macro move_line
pusha
mov dl,10
mov ah,2
int 21h
mov dl,13
int 21h
popa
endm
מאקרו להדפסת ספרה כתו:
macro print_digit digit
pusha
mov dl,digit
add dl,30h
mov ah,2h
int 21h
popa
endm
לסיקור מקיף יותר של שפת סף, ניתן לגשת למדריך בוויקיספר העברי.[1]
ראו גם
עריכהקישורים חיצוניים
עריכה- מדריך לאסמבלי (באנגלית)
- מבוא למערכות מחשב ואסמבלי (בעברית)
- שפת סף, באתר אנציקלופדיה בריטניקה (באנגלית)
- שפות סף (מחשבים אלקטרוניים), דף שער בספרייה הלאומית