לדלג לתוכן

1.3 בקרת זרימה ולולאות הרצאה

דגלים (Flags), השוואות (CMP) ופקודות קפיצה (JMP, Jcc)


רגיסטר FLAGS – מהו?

לצד הרגיסטרים הרגילים, למעבד יש רגיסטר מיוחד בשם FLAGS שמכיל דגלים – ביטים שמתעדכנים אוטומטית לאחר כל פעולה אריתמטית או לוגית.
הדגלים משמשים את המעבד להחלטות כמו האם לקפוץ, להמשיך או לעצור.

למה זה חשוב?

נוכל לבדוק את מצב הדגלים בעזרת פקודות קפיצה מותנית, וכך לבצע לוגיקה בתוכנית – לולאות, תנאים, בחירות.


הדגלים העיקריים

שם קיצור מתעדכן מתי? משמעות
Carry Flag CF חיבור/חיסור/כפל/חילוק נשיאת ביט – overflow ב־unsigned, נדלק כאשר תוצאת החיבור, חיסור, כפל או חילוק ביצעה overflow
Zero Flag ZF אם תוצאה = 0 שווה לאפס?
Sign Flag SF אם הביט העליון = 1 תוצאה שלילית (Signed)
Overflow Flag OF חרג מהטווח של signed חריגת Overflow ב־signed
Parity Flag PF אם יש מספר זוגי של ביטים = 1 בדיקת זוגיות ביטים
Auxiliary Carry AF ב־BCD נדיר לשימוש

מצב הoverflow קורה, כאשר למשל אנחנו מכפילים שני מספרים בעלי 8 ביט למספר 16 ביט. ותוצאת החיבור היא גדולה יותר ממספרי 16 ביט.
כאשר המצב קורה במספרים signed- ידלק דגל הoverflow.
כאשר המצב קורה במספרים unsigned- ידלק דגל הcarry

כאשר נבצע פעולת חיסור בין שני מספרים ונקבל 0, דגל הzero ידלק.
כאשר נבצע פעולת חיסור בין שני משתנים ונקבל מספר שלילי, דגל הsign ידלק.

פקודת השוואה CMP

מה היא עושה?

פקודת cmp משווה בין שני ערכים כאילו עשתה חיסור – אך לא משנה את הערכים עצמם.
המטרה: לעדכן את הדגלים בהתאם להשוואה.

cmp ax, bx   ; כמו ax - bx

כלומר, אם ax פחות bx יצא אפס, משמע ax וbx בעל אותו ערך (שווים) ודגל הzero ידלק.

מה נבדק בפועל?

  • הדגל ידלוק ZF = 1 אם התוצאה היא 0 (כלומר: שווים)
  • הדלק ידלוק SF = 1 אם התוצאה שלילית (כלומר: ax < bx עבור signed)

פקודות קפיצה

פקודות קפיצה מתחלקות ל־2 סוגים עיקריים:

  1. קפיצה ללא תנאי – תמיד תקפוץ

  2. קפיצה מותנית – תקפוץ רק אם דגלים מסוימים מופעלים

קפיצה ללא תנאי – JMP

jmp label_name

קופצת באופן מיידי לתווית (Label) מסוימת בקוד – בלי קשר לדגלים.

למשל בקטע קוד הבא יש לנו 2 label-ים.

start:
  mov ax, 1
  jmp end
  mov ax, 2    ; לא יקרה לעולם
end:

באמצע הlabel של start, נתו הוראת jmp לend. כך שההוראה "mov, ax, 2 בחיים לא תקרה."

קפיצות מותנות – Jcc (Jump on Condition Code)

מתבצעות רק אם תנאי מסוים מתקיים לפי מצב הדגלים.
שם הפקודה מתחיל ב־J, ואחריו 2 אותיות שמייצגות תנאי.

השוואת שוויון

פקודה קיצור תנאי דגל
JE label Jump if Equal אם שווה ZF = 1
JNE label Jump if Not Equal אם שונה ZF = 0
JZ label Jump if Zero תוצאה = 0 ZF = 1
JNZ label Jump if Not Zero תוצאה ≠ 0 ZF = 0
### קפיצות על סמך גדול/קטן – Unsigned
פקודה תנאי הסבר
JA Jump if Above CF=0 ו־ZF=0 (A > B)
JAE Jump if Above or Equal CF=0 (A ≥ B)
JB Jump if Below CF=1 (A < B)
JBE Jump if Below or Equal CF=1 או ZF=1 (A ≤ B)

קפיצות על סמך גדול/קטן – Signed

פקודה תנאי הסבר
JG Jump if Greater ZF=0 ו־SF=OF
JGE Jump if Greater or Equal SF=OF
JL Jump if Less SF≠OF
JLE Jump if Less or Equal ZF=1 או SF≠OF

קפיצות כלליות לפי דגלים

פקודה דגל הסבר
JC CF = 1 Carry – הייתה נשיאה
JNC CF = 0 No Carry
JO OF = 1 Overflow – חריגה signed
JNO OF = 0 No Overflow
JS SF = 1 Sign – שלילי
JNS SF = 0 חיובי

דוגמה מלאה – השוואת מספרים

mov ax, 10
mov bx, 20
cmp ax, bx      ; משווה: 10 - 20

jl is_less      ; אם ax < bx (signed)
je is_equal     ; אם ax == bx
jg is_greater   ; אם ax > bx (signed)

is_less:
  ; כאן נטפל במקרה ש־ax קטן מ־bx
  jmp end

is_equal:
  ; כאן נטפל במקרה ששווים
  jmp end

is_greater:
  ; כאן נטפל במקרה ש־ax גדול
  jmp end

end:

דוגמה – לולאה עם cmp ו־jne

mov cx, 5

loop_start:
  dec cx
  cmp cx, 0
  jne loop_start

הלולאה תרוץ בדיוק 5 פעמים.


פקודה חשובה: TEST

ממש כמו AND, אך לא משנה ערכים, רק מעדכנת דגלים.

test al, al     ; בודק אם AL == 0
jz zero_case    ; אם כן → קפוץ