שאלה ASSEMBLY 86

dor_ian

New member
שאלה ASSEMBLY 86

יש איזה דרך נוחה לעבוד עם משתנים לוקאלים בתוך שגרה? במקום להקצות מקום במחסנית ולהתייחס לכתובות? אני מחפש דרך לעבוד עם שמות של משתנים במקום לזכור כתובות. אשמח לשמוע טיפים בנוגע לעבודה נכונה עם משתנים לוקאלים. האם זה נכון לגשת ספציפית למיקום כלשהו במחסנית? זה לא מקלקל את כל הרעיון של עבודה עם מחסנית? עוד שאלה. נניח יש לי תוכנית ב C. עכשיו יש בה כל מיני פונקציות ובהן יש משתנים לוקאלים. האם הקומפיילר בעוברו על התוכנית מקצה מראש מקום לכל המשנים הלוקאלים. אבל מנגנון כלשו מונע ממני לגשת אליהם אלא אם אני בסקופ המתאים? כלומר משתנים לוקאלים בפנקציות הם בעצם גלובלים אבל עם גישה מוגבלת. או שבעצם כל המשתנים הלוקאלים יושבים בתוך המחסנית? איך זה מתנהל? כי אני משתמש בשמות שלהם באופן אקראי. רוצה שיהיה לי משהו דומה בASM אם זה אפשרי. תודה.
 

erezsh

New member
איך זה עובד ב-C

לפחות במהדרים שאני ראיתי - משתנים לוקאליים הם כמו משתנים גלובליים, אבל הם בעצם משותפים. מה זה אומר? נניח פונקציה א' הגדירה 10 שלמים, ופונקציה ב' הגדירה 10 שלמים (כולם לוקאליים). במקום ליצור 20 משתנים גלובאליים ושכל פונקציה תיגש ל-10 אחרים, המהדר מאחד את הכל ל-10 שלמים, כלומר שתי הפונקציות קוראות וכותבות לאותו הזיכרון. למה זה לא מפריע? כי כשפונקציה א' רצה, פונקציה ב' לא רצה, ולהיפך (והנתונים לא חייבים להישאר אותו הדבר אחרי סוף ריצת הפונקציה). יש רק שני מצבים של התנגשות: 1) רקורסיה. כפתרון יש שימוש במחסנית. 2) קורה רק ב-MultiTasking: כמה Threads שמנסים לגשת לאותו זיכרון (רצים "בו-זמנית"). הפתרון פה הוא ארוך ומורכב, ולמען האמת אני לא מכיר אותו טוב מספיק כדי להסביר.
 

erezsh

New member
הערה :

מן הסתם אפשרי שפונקציה אחת תקרא לשנייה ולשתיהן אותו הזיכרון. הטיפול בכך יכול להתבצע כמו ברקורסיה - ע"י מחסנית, אבל אני די בטוח שהמהדר נזהר שלא לשתף זיכרון בין פונקציה קוראת לנקראת.
 
כן

אשתדל לכתוב דוגמה ברורה. הרעיון הוא להשתמש בקבועים, ובמחסנית כמובן. ד"א, אין מצב שלא משתמשים היום במחסנית, אלא במערכות ייעודיות, שבהן מחסניות ממומשות בחומרה או שאין בהן צורך במחסנית. אתה צודק שזו לא בדיוק מחסנית, כי ניגשים לאיבריה באופן ישיר. אבל ככה ב-8086... וזה גם הגיוני, הרי מחסנית "רגילה" לא היתה מבנה הנתונים הכי טוב לבעייה הזו. למעשה, מחסנית-ווקטור (מחסנית שמתנהגת גם כמו מערך) היא מבנה נתונים מוכר והרבה יותר טוב לצורך הנ"ל.
; AddThreeNumbers simply adds its 3 arguments and returns ; the result in EAX. ; C prototype: ; int AddThreeNumbers(int Num1, int Num2, int Num3) ; declare some integer constants for the arguments ; (similar to #define in C): Num1 = 8 ; first arg is always 8 Num2 = Num1 + 4 ; 2nd arg is 32 bits after arg1 on the stack Num3 = Num2 + 4 ; 3rd arg is 32 bits after arg2 on the stack AddThreeNumbers PROC push ebp mov ebp, esp ; standard entry mov eax, Num1[ebp] add eax, Num2[ebp] add eax, Num3[ebp] ret 12 AddThreeNumbers endp ; how to call this from your application: ; I want to do: EAX = AddThreeNumbers(10,15,20) push 20 ; always pass arguments from last to first push 15 push 10 call AddThreeNumbers​
 
שכחתי שם

POP EBP לפני ה-RET אבל אתה תסלח לי.... ד"א, הפתרון שנתתי הוא בהנחה שכל הפונקציות של כתובות ע"פ STANDARD CALLING CONVENTION של C.
 

roterl

New member
משתנים באסמבלי

בפועל אין דבר כזה "משתנה לוקאלי", כשאתה בשפה עילית יוצר משתנה לוקאלי הקומפיילר ממיר את השם לכתובת אופסט במחסנית - כלומר כאשר הפונקציה לא רצה, ה"משתנה" לא קיים. אין טעם בלהקצות משתנה גלובאלי , כיוון שאז נוצרות בעיות ברקורסיה ו Mutli-Threads. גם משתנים גלובאלים הם במחסנים (אלא אם מקצים דינאמית, אבל אז הגישה הרבה יותר איטית, ולכן קומפיילרים לא עושים זאת) כשאתה כותב באסמבלי אתה צריך לעשות זאת. מותר ואף צריך לגשת למקומות בפציפים במחסנית, ובשביל זה בדיוק יש לך רגיסרט מחסנית נוסף.
 

roterl

New member
מה אני יגיד לך ..?.. - אתה צודק !

קצת חלודים אחרי כל כך הרבה זמן...
 
למעלה