Download presentation
Presentation is loading. Please wait.
1
فصل ششم روال ها
2
مطالب اين فصل بدنه يك روال دستورالعملهاي call , return دستورالعملهاي push , pop انتقال مقادير به يك روال و بالعكس بازگشت پذيري (recursion)
3
روالها کلمه روال در زبان پاسکال و ساير زبانهاي برنامهنويسي سطح بالا براي بيان زير برنامهاي که تقريباً يک واحد کاملي ميباشد، بکار ميرود.
4
آرگومانها بايستي متناظر با پارامترهاي مجازي روال مزبور باشند
آرگومانها بايستي متناظر با پارامترهاي مجازي روال مزبور باشند. در زبان پاسکال نوع ديگري از زير برنامه به نام تابع وجود دارد. يک تابع در زبان پاسکال شبيه يک روال ميباشد بجز اينکه آن را در داخل يک عبارتي با ذکر نام و آرگومانهاي مربوطه در داخل پرانتز، فراخواني ميکنيم. يک تابع مقداري را بر ميگرداند که اين مقدار در عبارت مربوطه مورد استفاده قرار ميگيرد.
5
آدرس برگشت به برنامه فراخواننده زير برنامه روي پشته ذخيره ميشود ميتوان مقادير ثباتها در زمان فراخواني يک زيربرنامه را روي پشته ذخيره نموده و در زمان برگشت به برنامه فراخواننده مقادير ثباتها را با استفاده از پشته بازسازي نمود، با استفاده از پشته ميتوان آرگومانها را به يک زيربرنامه انتقال داده و يا مقاديري را از يک زيربرنامه فراخواننده انتقال داد، و حتي ميتوان فضاي لازم براي متغيرهاي محلي را روي پشته تخصيص داد.
6
بدنه يک روال؛ دستورالعملهاي CALL و RETURN
بدنه يک رواي در داخل دستورات PROC و ENDR قرار ميگيرد و هر کدام از دستور العملها داراي بر چسبي است که برابر نام روال مزبور ميباشد. بعلاوه، دستور PROC شامل يکي از عملوندهاي NEAR يا FAR ميباشد. يک روال NEAR در همان سگمنت کدي که فراخواني مي شود تعريف ميگردد، و يک روال FAR معمولاً در يک سگمنت کد مجزايي تعريف ميشود.
7
اجراي يک برنامه لزوماً از اولين دستورالعمل سگمنت کد شروع نميشود، بلکه از دستورالعمل مشخص شده توسط عملوند دستور END که پايان برنامه را نشان ميدهد، شروع ميشود. بطور کلي، يک روال را ميتوان هر چند بار فراخواني کرد. دستور العمل برگشت کنترل اجرا را از روال به برنامه اصلي برميگرداند؛ معمولاً حداقل يک دستورالعمل ret در يک روال وجود دارد که البته ميتواند بيش از يک دستورالعمل ret وجود داشته باشد.
8
زماني که پشته براي ذخيره کردن مقاديري بکار ميرود، يک يا چند کلمه ذخيره ميشود، هرگز يک بايت تکي ذخيره نميشود. براي ذخيره کردن يک کلمه، ثبات SP باندازه 2 واحد (بايت) کاهش مييابد.
9
يک کلمه روي پشته ذخيره شده وضعيت اوليه پشته SP
** يک کلمه روي پشته ذخيره شده وضعيت اوليه پشته SP SS
10
توجه داشته باشيد که با ذخيره شدن کلمات روي پشته، مقدار ثابت SS تغيير نکرده بلکه تنها ثابت SP تغيير پيدا ميکند. زماني که دستورالعمل Call اجرا ميشود، افست دستورالعمل بعد از call را روي پشته ذخيره ميکند. سپس ثبات IP برابر افست روال قرار داد شده و اجراي برنامه از دستورالعمل واقع در آدرس CS:IP يعني اولين دستورالعمل روال مزبور ادامه مييابد. با توجه به اينکه برنامه اصلي و روال مزبور در داخل يک سگمنت قرار دارند، نيازي به تغيير شماره سگمنت واقع در ثبات CS وجود ندارد.
11
زماني که دستور العمل ret اجرا ميشود، کلمه واقع در بالاي پشته بازيابي شده و در ثبات IP ذخيره ميگردد. سپس اجراي برنامه از دستورالعمل واقع در آدرس IP:CS يعني از دستورالعمل بعد از call در برنامه اصلي ادامه پيدا ميکند. اين نوع فراخواني يا برگشت را فراخواني يا برگشت درون يک سگمنت گويند.
12
فرم دور(far) يک دستوالعمل فراخواني ابتدا محتواي ثبات CS را روي پشته ذخيره کرده و شماره سگمنت حاوي روال مورد نظر را داخل ثباتCS قرار ميدهد. سپس افست دستورالعمل بعدي را روي پشته ذخيره کرده و افست روال مزبور (در داخل سگمنت کد جديد) را در ثبات IP قرار ميدهد. جمعاً چهار بايت ناحيه پشته مورد استفاده قرار ميگيرد. فرم دور يک دستورالعمل ret عکس اين مراحل را انجام ميدهد، ابتدا ثبات IP را برابر افست دستورالعمل بعد از فراخواني اوليه قرار داده و سپس ثبات CS را برابر شماره سگمنت برنام فراخواننده قرار ميدهد؛ اين دو کلمه از داخل پشته کپي ميشوند.
13
Call procedure عملوند procedure معمولاً برابر نام روال مورد نظر ميباشد، ولي ميتواند با استفاده از آدرسي در داخل يک ثبات يا در حافظه بطور غير مستقيم بکار رود.
14
دستور العمل ret داراي دو فرم مختلف است
Ret pop –value (2 عملوند pop –value پس از اتمام ساير مراحل فرآيند برگشت (بازسازي ثبات IP و در مورد يک روال دور، بازسازي مقدار ثبات CS) به محتواي ثبات SP افزوده ميشود.
15
از اين فرم ميتوان در مواردي که کلماتي (بعضي مواقع مقادير پارامترها) روي پشته ذخيره شده و ميخواهيم آنها را در زمان خروج از روال بطور منطقي حذف کنيم، استفاده کرد.) براي ساختن بلوکهاي تشکيل دهنده برنامههاي بزرگ معمولاً يک روال يا گروهي از روالها را بطور مجزا اسمبل ميکنيم.
16
دستور PUBLIC Procedurel,Procedure2 به اسمبلر و لينکر ميگويد که برچسبهاي procedure1 و procedure2 ممکن است به وسيله برنامههايي که به طور مجزا اسمبل شدهاند، مورد استفاده قرار بگيرند.
17
برنامهاي که اين روالها را فراخواني ميکند بايستي شامل يک يا چند دستور EXTRN باشد که به اسمبلر بگويد که برچسبهاي Procedurel و Procedurel2 خارجي (exretnal) بوده و بطور محلي تعريف نشدهاند.
18
معمولاً دستورات EXTRN در ابتداي برنامه مربوطه ذکر ميشوند
معمولاً دستورات EXTRN در ابتداي برنامه مربوطه ذکر ميشوند. با استفاده از يک دستور، فرم دستور EXTRN بصورت زير است: EXTRN Procedure 1:FAR, procedure 2:FAR فرض کنيد که فايلهاي استفاده شده براي برنامه اصلي و روالها به ترتيب ASM.MAIN و PROCS.ASM باشند.
19
براي ساختن يک برنامه قابل اجرا مراحل زير لازم ميباشد:
با استفاده از MASM فايلهاي MAIN و PROCS را اسمبل کنيد (هر کدام را بخواهيد اول اسمبل کنيد) باين ترتيب دو فايل OBJ . بنامهاي OBJ. MAINو PROCS.OBJ ساخته ميشوند. با استفاده از LINK برنامه اصلي و روالها را با ذکر "main+procs+io" بعنوان ماژولهاي هدف به يکديگر پيونده دهيد (بطور کلي واحدهاي OBJ. مورد نظر را با کاراکتر «+» از يکديگر جدا کنيم. واحد io تنها زماني مورد نياز ميباشد که از ماکروهاي فايل IO.H استفاده کرده باشيد.) LINK معمولاً نام برنامه EXE را برابر نام اولين واحد OBJ قرار ميدهد؛ ميتوانيد نام واحدهاي OBJ. را به هر ترتيبي ذکر کنيد.
20
بدنبال اين مراحل، ميتوانيد با دادن نام فايل EXE
بدنبال اين مراحل، ميتوانيد با دادن نام فايل EXE. به سيستم عامل DOS آن را اجرا کنيد. ثباتهاي همگاني AX، BX، CXو DX بوسيله دستورالعملهاي call و ret تغيير پيدا نکرده و نه داراي وظائف مشخص ديگري ميباشند، از اين رو ميتوانيم از اين ثباتها براي انتقال مقادير باندازه کلمه به روالها و بالعکس، استفاده کنيم.
21
دستورالعملهاي PUSH و POP؛ دادههاي محلي
بمنظور ذخيره کردن محتواي يک ثبات يا کلمه حافظه اصلي، مقدار مورد نظر معمولاً بعد از شروع اجراي يک روال روي پشته ذخيره شده و قبل از اجراي دستور العمل برگشت از روال آن را روي پشته بازيابي ميکنيم.
22
Push Source عملوند Source ميتواند هر ثباتي بجز ثبات نشانهها و ثبات اشارهگر دستورالعملها يعني IP بوده و يا ميتواند کلمهاي در حافظه اصلي را ارجاع دهد. يک عملوند بلاواسطه مجاز نميباشد. دستورالعملهاي push و pop هيچکدام ثبات نشانهها را تغيير نميدهند.
23
دستورالعمل push از پشته دقيقاً مانند دستور العمل Call استفاده ميکند
دستورالعمل push از پشته دقيقاً مانند دستور العمل Call استفاده ميکند. اشارهگر پشته SP باندازه دو بايت کاهش يافته و سپس کلمه آدرس داده شده بوسيله عملوند منبع در دو بايت با آدرس SS:SP ذخيره ميشود. البته، اجراي برنامه بجاي اولين دستورالعمل روال مربوط در دستورالعمل Call، با دستور العمل بعدي ادامه پيدا ميکند.
24
POP destination که destination ميتواندکلمهاي در حافظه اصلي را ارجاع داده و يا ميتواند هر ثباتي بجز ثبات نشانهها و ثبات اشارهگر دستور العملها IP و ثبات سگمنت کد CS باشد. از دستورالعملهاي Push و POP معمولاً بصورت زوج استفاده ميشود.
25
دستورالعمل Pushf (ذخيره کردن نشانهها) 16 بيت نشانهها را (حتي آنهائي را که معني خاصي بعنوان نشانه ندارند) روي پشته ذخيره کرده و دستورالعمل popf (بازيابي نشانهها) نشانهها را از روي پشته بازيابي ميکند.
26
در روالهاي پيچيده غالباً نياز به دستيابي دادههاي ذخيره شده در حافظه اصلي وجود دارد.
يک روش از يک سگمنت داده مجزا استفاده ميکند، و روش ديگر دادههاي را در همان سگمنت کد روال ذخيره ميکند.
27
دستور ASSUME CS: proc_code,ds: poc_data به اسمبلر ميگويد فرض کند که ثبات CS در زمان اجراي دستورالعملهاي بعدي به سگمنت proc-code اشاره کرده و ثبات DS به سگمنت proc-data اشاره خوهد کرد. بکمک اين دستور، اسمبلر افستهاي متغيرها در داخل proc-data را از اول اين سگمنت و افستهاي دستورالعملها در داخل proc-code را از اول اين سگمنت محاسبه خواهد کرد.
28
در فراخواني يک روال، يک مقدار جديد بعنوان نتيجه دستورالعمل call بطور اتوماتيک در داخل ثبات DS قرار نميگيرد. اين وظيفه برنامهنويس است که محتواي ثبات DS مربوط به برنامه فراخوانند را ذخيره کرده، ثبات سگمنت داده جديد را بار کرده و قبل از بازگشته به برنامه فراخواننده، مقدار اوليه ثبات DS را بازسازي کند.
29
انتقال مقادير به يک روال و بالعکس:
دو روش ممکن براي انتقال يک مقدار باندازه کلمه عبارتند از: قرار دادن مقدار مورد نظر در يک ثبات قرار دادن مقدار مورد نظر روي پشته
30
در آدرس دهي مبنا، افست يک محل حافظه بصورت مجموع محتواي يک ثبات مبنا (ثبات BP يا BX) و عددي که در داخل دستورالعمل قرار دارد، محاسبه ميشود.
31
نشان گذاري براي آدرس دهي مبنا:
[bp+number] براي ثبات BPو از نشان گذاري [bx+number] براي ثبات BX استفاده ميکند. اگر ثبات BP استفاده شود، در اين صورت افست در سگمنت پشته قرار دارد؛ يعني آدرس حقيقي برابر [BP+number] :SS ميباشد از طرف ديگر، اگر ثبات BX استفاده شود، در اين صورت افست در سگمنت دادهها قرار دارد؛ يعني آدرس حقيقي برابر [BP+number] :DS ميباشد.
32
غالباً ميخواهيم پس از برگشت به برنامه فراخواننده مقدار ثبات BP تغيير پيدا نکند، در اين صورت مقدار BP بايستي در اول روال و قبل از کپي کردن مقدار ثبات SP بداخل ثبات BP، بر روي پشته اضافه گردد. بايد ترتيب هر کدام از آرگومانها باندازه دو بايت نسبت به SS:BP دورتر باشند. با فرض اينکه روال مزبور بصورت FAR تعريف شده باشد، در اين صورت آرگومان دوم در افست (BP+6) و آرگومان اولي در افست (BP+8) خواهد بود. اگر بخواهيد ثباتهاي ديگري را ذخيره کنيد ميتوانيد اين کار را بعد از کپي کردن ثبات SP بداخل BP انجام دهيد.
33
نقطه قوت اين سيستم اين است که پس از ثابت نگهداشتن ثبات BP، ميتواند پشته را بطور آزاد براي هر منظوري استفاده کرد و در نتيجه ثبات SP را تغيير داد، در حالي که ميتوان با استفاده از ثبات BP آرگومانها را دستيابي کرد.
34
اگر برنامهاي به اضافه کردن آرگومانها روي پشته و فراخواني روالها ادامه دهد، در اين صورت برنامه اصلي و يا روالهاي مربوطه بايستي اين مقادير را از پشته حذف کنند که در غير اين صورت ممکن است پشته سر زير نمايد. برنام اصلي ميتواند اين کار را انجام دهد که تعداد بايتهائي را که بايستي آزاد شوند به ثبات SP اضافه کند. اگر از پشته براي برگرداندن يک يا چند مقدار به برنامه اصلي استفاده شود، هيچکدام از اين تکنيکها بدون تغيير کار نخواهد کرد.
35
بازگشت پذيري (Recursion)
يک روال يا تابع بازگشتي روال يا تابعي است که بطور مستقيم يا غير مستقيم خودش را فراخواني نمايد. بهترين الگوريتمها براي پردازش بسياري از ساختارهاي اطلاعاتي بصورت بازگشتي ميباشند.
36
اگر پارامترها روي پشته انتقال يابند، در اين صورت براي هر فراخواني روال مزبور فضاي جديدي براي پارامترهاي آن تخصيص داده ميشود بطوري که آرگومانهاي انتقالي به يک فراخواني روال با آرگومانهاي انتقالي به فراخواني ديگر آن روال اشتباه نميشوند به همين ترتيب، اگر مقادير پشته ذخيره ميشوند، در اين صورت ميتوان از همان ثباتها و يا حتي مکانهاي حافظه در هر فراخواني بازگشتي يک روال استفاده نمود.
37
بدنه يك روال دستورالعملهاي call , return
در این حالت آدرس برنامه جاری در stack دخیره میگردد پس از پایان روال و با اجرای دستور ret مقدار قبلی PC از stack بازیابی شده و ادامه برنامه از سر گرفته میشود
38
دستورالعملهاي push , pop
بسیار محتمل است مقادیر رجیسترها در داخل یک روال تغییر کند لذا ذخیره ساری مقادیر اولیه ضروری است برای ذخیره سازی مقادیر رجیسترها از دستور push استفاده میشود که این دستور باید در ابتدای روال قرار گیرد برای بازگشت مقادی اولیه به رجیسترها از دستور pop استفاده میشود .این دستورات میباید آخرین دستورات یک روال باشند
39
انتقال مقادير به يك روال و بالعكس
برا یانتقال مقادیر به روال و بر عکس دو روش وجود دارد 1 – استفاده از پشته : که در این حالت مقادیر ارسالی را با استفاده از دستور push به پشته فرستاده و در داخل روال با دستور pop آنرا فراخوانی میکنیم 2 – استفاده از سگمنت داده ای : در این حالت آدرس خاصی از سگمنت را برای انتقال پارامترها در نظر میگیریم و در داخل روال نیز داده ها را از آدرس فوق بازیابی میکنیم
40
بازگشت پذيري (recursion)
یک برنامه recursive برنامه ای است که خود را فراخوانی میکند پیاده سازی یک برنامه خودفراخوان یا بازگشت پذیر در اسمبلی به راحتی نوشتن هر برنامه دیگر است تنها خطر برنامه های خود فراخوان سرریز پشته است زیرا در هر فراخوانی یکبار مقدار pc در پشته ذخیره میگردد
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.