חזור לתיקייה: תרגול

2 - קוד לגילוי שגיאות(ECC) בשפת אסמבלי

חיפוש בתיקיה
Ctrl K
לחץ כאן או הקש Ctrl K כדי לחפש בכל התיקיה
  • קודים לגילוי שגיאות
  • מוטיבציה
  • הגדרות
  • גילוי ותיקון שגיאות
  • בדיקת זוגיות
  • קוד חזרות
  • קוד X; out; of; Y.
  • אסמבלי
  • תרגול

2 - קוד לגילוי שגיאות(ECC) בשפת אסמבלי

00440252

מערכות ספרתיות ומבנה המחשב

רשימות תרגול לקריאה בשבת

קוד לגילוי שגיאות(ECC) בשפת אסמבלי

הופק מתוך תקיית התואר של שקד

uni-folder.vercel.app

קודים לגילוי שגיאות

מוטיבציה

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

הגדרות

הגדרה 1 (קוד)

קוד הוא אוסף של מילים מתוך אוסף כל המילים האפשריות.

דוגמה

עבור הקוד

011100001\begin{matrix} 011 \\ 100 \\ 001 \end{matrix}011100001​

במצב זה המילה 010010010 היא לא חלק מהקוד.

הגדרה 2 (מרחק המינג)

מרחק בין שתי מילים הוא מספר הביטים שיש לשנות על מנת לקבל מילה אחת מהשנייה.

הגדרה 3 (מרחק הקוד)

המרחק הכי קצר בין 2 מילות קוד.

דוגמה

בקוד 000111\begin{matrix}000\\111\end{matrix}000111​ מרחק הקוד הוא 3.

גילוי ותיקון שגיאות

המרחק המינימלי קובע את יכולת הגילוי והתיקון של שגיאות של קוד.

הערה

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

דוגמה

נניח יש לנו את הקוד:

111010101000000\begin{matrix} 11101 \\ 01010 \\ 00000 \end{matrix}111010101000000​

ונניח שהייתה טעות אחת וקיבלנו את המילה 000100001000010. במצב זה אנו יודעים כי נשלחה או המילה 000000000000000 או המילה 010100101001010.
אם המרחק המינימלי הוא 222 ובמילת הקוד נפלה טעות אחת ניתן לגלות אותה אך לא לתקנה.

אם המרחק המינימאלי הוא 222 ובמילת הקוד נפלו שתי טעויות, אזי לא נוכל להבטיח גילוי של השגיאה.
נניח אם היו שתי שגיאות וקיבלנו 010100101001010 - זוהי מילה שקיימת בקוד ולכן לא נדע על טעות.

דוגמה

אם המרחק המינימלי הוא 3. נניח בקוד הבא:

000111\begin{matrix} 000 \\ 111 \end{matrix}000111​
  • ניתן לגלות עד 2 טעויות.
  • אם מניחים שלכל היותר יש טעות 1 בלבד, ניתן לתקנה.

באופן כללי:

משפט

יהי קוד בעל מרחק קוד KKK. אזי, ניתן לגלות עד K−1K-1K−1 טעויות.
בהנחה שמספר הטעויות הוא לכל היותר ⌊K−12⌋\left\lfloor \frac{K-1}{2} \right\rfloor⌊2K−1​⌋ אז ניתן לתקנן.

ננסה לחפש דרך לשפר את יכולת התיקון בקוד מבלי לשנות את המידע המקורי.

בדיקת זוגיות

נניח עבור הקוד:

10011110\begin{matrix} 1001 \\ 1110 \end{matrix}10011110​

נוסיף ביט לקצה כך שמספר האחדים במילת הקוד(כולל סיבית הזוגיות) יהיה זוגי עבור even  parityeven\; parityevenparity. נניח עבור אותן מילים ממקודם נקבל:

1001011101\begin{matrix} \underbracket{1001}0 \\ \underbracket{1110}1 \end{matrix}1001011101​

ביט הזוגיות מתקבל מ-XORXORXOR שאר הסיביות:

1⊕0⊕0⊕1=01⊕1⊕1⊕0=11 \oplus 0 \oplus 0 \oplus 1 =0 \qquad \qquad 1 \oplus 1 \oplus 1\oplus 0=11⊕0⊕0⊕1=01⊕1⊕1⊕0=1
מסקנה

עבור קוד AAA עם מרחק קוד אי-זוגי, הוספת סיבית הזוגיות תגדיל את מרחק הקוד ב-111.
במידה ומרחק הקוד הינו זוגי, אזי מרחק הקוד לא ישתנה.

קוד חזרות

כל ביט משודר rrr פעמים.

דוגמה

עבור r=4r=4r=4 לדוגמה:

0  ⟹  00001  ⟹  1111\begin{matrix} 0 \implies 0000 \\ 1 \implies 1111 \end{matrix}0⟹00001⟹1111​

מינוח: להפעיל קוד חזרות על קוד AAA עם r=?r=?r=?.

דוגמה

עבור המילים:

010001\begin{matrix} 010 \\ 001 \end{matrix}010001​

נקבל בקוד חזרות עם r=3r=3r=3:

000111000000000111000111000 000000111000111000000000111

מרחק הקוד המקורי היה 2 ואילו לאחר השינוי מרחק הקוד הינו 2r2r2r כלומר 666.

קוד X  out  of  YX\; out\; of\; YXoutofY.

כל מילת הקוד באורך YYY מכילות בדיוק XXX אחדים.
מספר המילים בקוד יהיה (YX)=Y!X!(Y−X)!\begin{pmatrix}Y\\X\end{pmatrix}=\frac{Y!}{X!(Y-X)!}(YX​)=X!(Y−X)!Y!​.
מרחק הקוד: 2 (לכל XXX ו-YYY)
⇐ יכולת גילוי של שגיאה בודדת.

אסמבלי

כשאנחנו רוצים לקמפל קוד בשפת CCC או בשפה עילית אחרת - לרוב, המהדר לוקח את הקוד ומתרגם אותו לשפת אסמבלי, שאז האסמבלר(שבדרך כלל בנוי לתוך מערכת ההפעלה) יקח את האסמבלי ויהפוך אותו לקוד מכונה.
באסמבלי אין לנו משתנים. יש לנו רק רגיסטרים(אוגרים בעברית) אשר הם בנויים לתוך החומרה והם ממש ממש מהירים. הם סופיים ומסוגלים לאסחן רק מספר סופי של ביטים.
פעולות יכולות להתבצע רק על רגיסטרים.
​תרגול ספרתיות 2 - תמונה של איך עובדים רגיסטרים 111112524.png

כמה רגיסטרים יש לנו בריסק-5? יש לנו 323232 רגיסטרים שכל אחד מהם הוא בגודל של מילה(323232 ביטים בקורס זה).
הרגיסטר x0x0x0 הוא מיוחד וערכו תמיד 000.
מכיוון שיש לנו מספר מוגבל של רגיסטרים נשאף לבנות תוכנות שמשתמשות בזיכרון ביעילות.

הרגיסטרים שיש במערכת:

NameReg #UseSaver
$zero0Constant 0-
ra1Return AddressCaller
sp2Stack PointerCallee
gp3Global Pointer-
tp4Thread Pointer-
t0-t25-7TempCaller
s0-s18-9Saved RegistersCallee
a0-a710-17Function arguments/return valuesCaller
s2-s1118-27Saved RegistersCallee
t3-t628-31TempCaller
כשאנחנו רוצים לגשת לכתובת בזיכרון אנו נעשה זאת לפי בתים ולא לפי ביטים(כל בית הוא 8 ביטים):
​ספרתיות תרגול 2 תמונה184.png
אם נחתנו באמצע מילה אז הוא יספור 4 בתים מהנקודה בה נחתנו(ולכן מומלץ לא לעשות את זה)

תרגול

תרגיל

נניח שיש לנו מערך בזיכרון שמכיל:

int* arr = {1,2,3,4,5,6,0};

הערך של המערך arrarrarr הוא כפולה של 444 ומאוחסן ברגיסטר s0s_{0}s0​.
מה הקוד RISC−VRISC-VRISC−V הבא יבצע?

lw t0,12(s0)
slli t1,t0,2
add t2,s0,t1
lw t3,0(t2)
addi t3,t3,1
sw t3,0(t2)
lw t0,0(s0)
addi t1,x0,-1
xor t0,t0,t1
addi t0,t0,1

נסתכל על מה כל שורה עושה ולאחר מכן נגלה מה הקוד הזה עושה בכללותו.
השורה lw t0,12(s0) טוענת את הערך arr[3]=4arr[3]=4arr[3]=4 במערך לרגיסטר t0t_{0}t0​.
השורה slli t1,t0,2 מזיזה את הביטים ב-t0t_{0}t0​ ב-2 שמאלה ומציבה זאת ב-t1t_{1}t1​. כלומר, כעת t1=22t0=16t_{1}=2^2t_{0}=16t1​=22t0​=16.
השורה add t2,s0,t1 מחברת בין s0s_{0}s0​ שבו יש את הכתובת של arrarrarr ל-t1t_{1}t1​ ומציבה את הערך ב-t2t_{2}t2​. כלומר, ב-t2t_{2}t2​ תהיה את הכתובת של האיבר החמישי במערך.
השורה lw t3,0(t2) מציבה ב-t3t_{3}t3​ את הערך arr[4]=5arr[4]=5arr[4]=5.
השורה addi t3,t3,1 מציבה ב-t3t_{3}t3​ את t3+1=6t_{3}+1=6t3​+1=6.
השורה sw t3,0(t2) מציבה את הערך שנמצא ב-t3t_{3}t3​ במקום בזכרון שאליו מצביע t2t_{2}t2​ שהוא &arr[4]\&arr[4]&arr[4].
לכן, קטע הקוד הזה מבצע t0=4t_{0}=4t0​=4 ואז arr[t0]++arr[t_{0}]++arr[t0​]++.

השורה lw t0,0(s0) שמה ברגיסטר t0t_{0}t0​ את הערך arr[0]=1arr[0]=1arr[0]=1.
השורה addi t1,x0,-1 מציבה ברגיסטר t1t_{1}t1​ את הערך −1-1−1.
השורה xor t0,t0,t1 מבצעת את פעולת ה-XORXORXOR בין המילים ברגיסטרים ומאחסנת זאת ברגיסטר t0t_{0}t0​. מכיוון ש-t1t_{1}t1​ הוא −1-1−1 ולכן הוא בעצם רק אחדים, אז זה בעצם מבצע t0=not(t0)t_{0}=not(t_{0})t0​=not(t0​).
השורה addi t0,t0,1 מבצעת t0=t0+1t_{0}=t_{0}+1t0​=t0​+1.
קטע הקוד הזה שם ברגיסטר t0t_{0}t0​ את המשלים ל-222 של −arr[0]-arr[0]−arr[0].

תרגיל

כתבו את התנאי s0<s1s_{0}<s_{1}s0​<s1​ רק באמצעות beq ו-bne

הפקודה slt t0,s0,s1 מבצעת:

t0={1s0<s10elset_{0}=\begin{cases} 1 & s_{0}<s_{1} \\ 0 & else \end{cases}t0​={10​s0​<s1​else​

לכן, נוכל להשתמש בה לפי ההשוואה הבאה bne t0,x0,label. זאת מכיוון שאנו יודעים כי רגיסטר x0x_{0}x0​ הוא 000 תמיד ואין לנו דרך לדעת באיזה רגיסטר יש 111 אם לא השמנו בו את ערך זה.

תרגיל

כתבו את התנאי s0≤s1s_{0}\leq s_{1}s0​≤s1​ רק באמצעות beq ו-bne

נוכל להשתמש באותה פקודה ממקודם רק הפוך: slt t0,s1,s0 ואז נקבל את הערך 000 ב-t1t_{1}t1​ אם s1≥s0s_{1}\geq s_{0}s1​≥s0​.
לכן, נוכל עכשיו להשתמש בפקודת ההשוואה: beq t0,x0,label.

תרגיל

כתבו את הנתאי s0>1s_{0}>1s0​>1 רק באמצעות beq ו-bne

נציב ברגיסטר t1t_{1}t1​ את הערך 111 כך: addi t1,x0,1
כעת, נשתמש שוב בפקודה sltsltslt כך: slt t0,t1,s0 שתיתן לנו 111 אם 1<s01<s_{0}1<s0​.
לבסוף, נבצע את ההשוואה: bne t0,x0,label.

הערה (איך עשו את זה בתרגול)

ניתן להשתמש בפקודה slti t0,s0,2 כדי לקבל 111 אם מתקיים s0≥2s_{0}\geq 2s0​≥2 ואז להשתמש בפקודת ההשוואה beq t0,x0,label.
זה שימוש יותר טוב בזיכרון - אז זה טכנית יותר טוב.