فصل ششم

روال ها

 

روال‌ها

کلمه روال در زبان پاسکال و ساير زبانهاي برنامه‌نويسي سطح بالا براي بيان زير برنامه‌اي که تقريباً يک واحد کاملي مي‌باشد، بکار مي‌رود.

آرگومانها بايستي متناظر با پارامترهاي مجازي روال مزبور باشند. در زبان پاسکال نوع ديگري از زير برنامه‌ به نام تابع وجود دارد. يک تابع در زبان پاسکال شبيه يک روال مي‌باشد بجز اينکه آن را در داخل يک عبارتي با ذکر نام و آرگومانهاي مربوطه در داخل پرانتز، فراخواني مي‌کنيم. يک تابع مقداري را بر مي‌گرداند که اين مقدار در عبارت مربوطه مورد استفاده قرار مي‌گيرد.

آدرس برگشت به برنامه فراخواننده زير برنامه روي پشته ذخيره مي‌شود مي‌توان مقادير ثبات‌ها در زمان فراخواني يک زيربرنامه را روي پشته ذخيره نموده و در زمان برگشت به برنامه فراخواننده مقادير ثبات‌ها را با استفاده از پشته بازسازي نمود، با استفاده از پشته مي‌توان آرگومانها را به يک زيربرنامه انتقال داده و يا مقاديري را از يک زيربرنامه فراخواننده انتقال داد، و حتي مي‌توان فضاي لازم براي متغيرهاي محلي را روي پشته تخصيص داد.

 

بدنه يک روال؛ دستورالعمل‌هاي CALL و RETURN

 

بدنه يک رواي در داخل دستورات PROC و ENDR قرار مي‌گيرد و هر کدام از دستور العملها داراي بر چسبي است که برابر نام روال مزبور مي‌باشد. بعلاوه، دستور PROC شامل يکي از عملوندهاي NEAR يا FAR مي‌باشد. يک روال NEAR در همان سگمنت کدي که فراخواني مي‌ شود تعريف مي‌گردد، و يک روال FAR معمولاً در يک سگمنت کد مجزايي تعريف مي‌شود.

اجراي يک برنامه لزوماً از اولين دستورالعمل سگمنت کد شروع نمي‌شود، بلکه از دستورالعمل‌ مشخص شده توسط عملوند دستور END که پايان برنامه را نشان مي‌دهد، شروع مي‌شود.

بطور کلي، يک روال را مي‌توان هر چند بار فراخواني کرد.

دستور العمل‌ برگشت کنترل اجرا را از روال به برنامه اصلي برمي‌گرداند؛ معمولاً حداقل يک دستورالعمل ret در يک روال وجود دارد که البته مي‌تواند بيش از يک دستورالعمل ret وجود داشته باشد.

زماني که پشته براي ذخيره کردن مقاديري بکار مي‌رود، يک يا چند کلمه ذخيره مي‌‌شود، هرگز يک بايت تکي ذخيره نمي‌شود. براي ذخيره کردن يک کلمه، ثبات SP باندازه 2 واحد (بايت) کاهش مي‌يابد.

 

Image and video hosting by TinyPic

 

توجه داشته باشيد که با ذخيره شدن کلمات روي پشته، مقدار ثابت SS تغيير نکرده بلکه تنها ثابت SP تغيير پيدا مي‌کند.

زماني که دستورالعمل Call اجرا مي‌شود، افست دستورالعمل‌ بعد از call را روي پشته ذخيره مي‌کند. سپس ثبات IP برابر افست روال قرار داد شده و اجراي برنامه از دستورالعمل واقع در آدرس CS:IP يعني اولين دستورالعمل روال مزبور ادامه مي‌يابد. با توجه به اينکه برنامه اصلي و روال مزبور در داخل يک سگمنت قرار دارند، نيازي به تغيير شماره سگمنت واقع در ثبات CS وجود ندارد.

زماني که دستور العمل ret اجرا مي‌شود، کلمه واقع در بالاي پشته بازيابي شده و در ثبات IP ذخيره مي‌گردد. سپس اجراي برنامه از دستورالعمل واقع در آدرس IP:CS يعني از دستورالعمل بعد از call‌ در برنامه اصلي ادامه پيدا مي‌کند. اين نوع فراخواني يا برگشت را فراخواني يا برگشت درون يک سگمنت گويند.

فرم دور(far) يک دستوالعمل فراخواني ابتدا محتواي ثبات CS را روي پشته ذخيره کرده و شماره سگمنت حاوي روال مورد نظر را داخل ثباتCS قرار مي‌دهد. سپس افست دستورالعمل بعدي را روي پشته ذخيره کرده و افست روال مزبور (در داخل سگمنت کد جديد) را در ثبات IP قرار مي‌دهد. جمعاً چهار بايت ناحيه پشته مورد استفاده قرار مي‌گيرد. فرم دور يک دستورالعمل ret عکس اين مراحل را انجام مي‌دهد، ابتدا ثبات IP را برابر افست دستورالعمل بعد از فراخواني اوليه قرار داده و سپس ثبات CS را برابر شماره سگمنت برنام فراخواننده قرار مي‌دهد؛ اين دو کلمه از داخل پشته کپي مي‌شوند.

Call procedure

 

عملوند procedure معمولاً برابر نام روال مورد نظر مي‌باشد، ولي مي‌تواند با استفاده از آدرسي در داخل يک ثبات يا در حافظه بطور غير مستقيم بکار رود.

دستور العمل ret داراي دو فرم مختلف است. فرم معمول‌تر آن بدون عملوند بوده و بصورت زير است:

 Ret(1

فرم ديگر دستورالعمل ret که کمتر معمول مي‌باشد بصورت زير است

Ret pop –value (2

عملوند pop –value پس از اتمام ساير مراحل فرآيند برگشت (بازسازي ثبات IP و در مورد يک روال دور، بازسازي مقدار ثبات CS) به محتواي ثبات SP افزوده مي‌شود.

 

از اين فرم مي‌توان در مواردي که کلماتي (بعضي مواقع مقادير پارامترها) روي پشته ذخيره شده و مي‌خواهيم آنها را در زمان خروج از روال بطور منطقي حذف کنيم، استفاده کرد.)

براي ساختن بلوکهاي تشکيل دهنده برنامه‌‌هاي بزرگ معمولاً يک روال يا گروهي از روال‌ها را بطور مجزا اسمبل مي‌کنيم.

دستور

 PUBLIC Procedurel,Procedure2

 

به اسمبلر و لينکر مي‌گويد که برچسب‌هاي procedure1 و procedure2 ممکن است به وسيله برنامه‌هايي که به طور مجزا اسمبل شده‌اند، مورد استفاده قرار بگيرند.

برنامه‌اي که اين روال‌ها را فراخواني مي‌کند بايستي شامل يک يا چند دستور EXTRN باشد که به اسمبلر بگويد که برچسب‌هاي Procedurel و Procedurel2 خارجي (exretnal) بوده و بطور محلي تعريف نشده‌اند.

معمولاً دستورات EXTRN در ابتداي برنامه مربوطه ذکر مي‌شوند. با استفاده از يک دستور، فرم دستور EXTRN بصورت زير است:

EXTRN Procedure 1:FAR, procedure 2:FAR

فرض کنيد که فايل‌هاي استفاده شده براي برنامه اصلي و روال‌ها به ترتيب ASM.MAIN و PROCS.ASM باشند.

 

براي ساختن يک برنامه قابل اجرا مراحل زير لازم مي‌‌باشد‌:

با استفاده از MASM فايلهاي MAIN و PROCS را اسمبل کنيد (هر کدام را بخواهيد اول اسمبل کنيد) باين ترتيب دو فايل OBJ . بنامهاي OBJ. MAIN‌و PROCS.OBJ ساخته مي‌شوند.

با استفاده از LINK برنامه اصلي و روال‌ها را با ذکر "main+procs+io" بعنوان ماژولهاي هدف به يکديگر پيونده دهيد (بطور کلي واحدهاي OBJ. مورد نظر را با کاراکتر «+» ‌از يکديگر جدا کنيم. واحد io تنها زماني مورد نياز مي‌باشد که از ماکروهاي فايل IO.H استفاده کرده باشيد.) LINK معمولاً نام برنامه EXE را برابر نام اولين واحد OBJ قرار مي‌دهد؛ مي‌توانيد نام واحدهاي OBJ. را به هر ترتيبي ذکر کنيد.

بدنبال اين مراحل، مي‌توانيد با دادن نام فايل EXE. به سيستم عامل DOS آن را اجرا کنيد.

ثباتهاي همگاني AX، BX، ‍CXو DX بوسيله دستورالعملهاي call و ret تغيير پيدا نکرده و نه داراي وظائف مشخص ديگري مي‌‌باشند، از اين رو مي‌توانيم از اين ثباتها براي انتقال مقادير باندازه کلمه به روال‌ها و بالعکس، استفاده کنيم.

دستورالعمل‌هاي PUSH و POP؛ داده‌هاي محلي

 

دستورالعمل‌هاي push براي ذخيره کردن داده‌هاي روي پشته و دستورالعمل‌هاي pop براي بازيابي آنها از پشته صورت مي‌‌‌گيرد.

بمنظور ذخيره کردن محتواي يک ثبات يا کلمه حافظه اصلي، مقدار مورد نظر معمولاً بعد از شروع اجراي يک روال روي پشته ذخيره شده و قبل از اجراي دستور العمل برگشت از روال آن را روي پشته بازيابي مي‌کنيم.

Push Source

 

 عملوند Source مي‌تواند هر ثباتي بجز ثبات نشانه‌ها و ثبات اشاره‌گر دستورالعملها يعني IP بوده و يا مي‌تواند کلمه‌اي در حافظه اصلي را ارجاع دهد. يک عملوند بلاواسطه مجاز نمي‌باشد. دستورالعملهاي push و pop‌ هيچکدام ثبات نشانه‌ها را تغيير نمي‌دهند.

دستورالعمل‌ push از پشته دقيقاً مانند دستور العمل Call استفاده مي‌کند. اشاره‌گر پشته SP باندازه دو بايت کاهش يافته و سپس کلمه آدرس داده شده بوسيله عملوند منبع در دو بايت با آدرس SS:SP ذخيره مي‌شود. البته، اجراي برنامه بجاي اولين دستورالعمل روال مربوط در دستورالعمل Call، با دستور العمل بعدي ادامه پيدا مي‌کند.

POP destination

 

که destination مي‌تواندکلمه‌اي در حافظه اصلي را ارجاع داده و يا مي‌تواند هر ثباتي بجز ثبات نشانه‌ها و ثبات اشاره‌گر دستور العملها IP و ثبات سگمنت کد CS باشد.

از دستورالعملهاي Push و POP معمولاً بصورت زوج استفاده مي‌شود.

دستورالعمل‌ Pushf (ذخيره کردن نشانه‌ها) 16 بيت نشانه‌ها را (حتي آنهائي را که معني خاصي بعنوان نشانه‌ ندارند) روي پشته ذخيره کرده و دستورالعمل popf (بازيابي نشانه‌ها) نشانه‌ها را از روي پشته بازيابي مي‌کند.

 

در روالهاي پيچيده غالباً نياز به دستيابي داده‌هاي ذخيره شده در حافظه اصلي وجود دارد.

يک روش از يک سگمنت داده مجزا استفاده مي‌کند، و روش ديگر داده‌هاي را در همان سگمنت کد روال ذخيره مي‌کند.

دستور

ASSUME CS: proc_code,ds: poc_data

به اسمبلر مي‌گويد فرض کند که ثبات CS در زمان اجراي دستورالعملهاي بعدي به سگمنت proc-code اشاره کرده و ثبات DS به سگمنت  proc-data اشاره خوهد کرد.

بکمک اين دستور، اسمبلر افست‌هاي متغيرها در داخل proc-data را از اول اين سگمنت و افست‌هاي دستورالعملها در داخل proc-code را از اول اين سگمنت محاسبه خواهد کرد.

در فراخواني يک روال، يک مقدار جديد بعنوان نتيجه دستورالعمل call بطور اتوماتيک در داخل ثبات DS قرار نمي‌گيرد. اين وظيفه برنامه‌نويس است که محتواي ثبات DS  مربوط به برنامه فراخوانند را ذخيره کرده، ثبات سگمنت داده جديد را بار کرده و قبل از بازگشته به برنامه فراخواننده، مقدار اوليه ثبات DS را بازسازي کند.

 

انتقال مقادير به يک روال و بالعکس:

 

دو روش ممکن براي انتقال يک مقدار باندازه کلمه عبارتند از:

- قرار دادن مقدار مورد نظر در يک ثبات

- قرار دادن مقدار مورد نظر روي پشته

 

در آدرس دهي مبنا، افست يک محل حافظه بصورت مجموع محتواي يک ثبات مبنا (ثبات BP يا BX) و عددي که در داخل دستورالعمل قرار دارد، محاسبه مي‌شود.

 

نشان گذاري براي آدرس دهي مبنا:

[bp+number]

براي ثبات BPو از نشان گذاري

[bx+number]

 

 براي ثبات BX استفاده مي‌کند. اگر ثبات BP استفاده شود، در اين صورت افست در سگمنت پشته قرار دارد؛ يعني آدرس حقيقي برابر [BP+number] :SS مي‌باشد از طرف ديگر، اگر ثبات BX استفاده شود، در اين صورت افست در سگمنت داده‌ها قرار دارد؛ يعني آدرس حقيقي برابر [BP+number] :DS مي‌باشد.

 

غالباً مي‌خواهيم پس از برگشت به برنامه فراخواننده مقدار ثبات BP تغيير پيدا نکند، در اين صورت مقدار BP بايستي در اول روال و قبل از کپي کردن مقدار ثبات SP بداخل ثبات BP، بر روي پشته اضافه گردد. بايد ترتيب هر کدام از آرگومانها باندازه دو بايت نسبت به SS:BP دورتر باشند. با فرض اينکه روال مزبور بصورت FAR تعريف شده باشد، در اين صورت آرگومان دوم در افست (BP+6) و آرگومان اولي در افست (BP+8) خواهد بود. اگر بخواهيد ثباتهاي ديگري را ذخيره کنيد مي‌‌توانيد اين کار را بعد از کپي کردن ثبات SP بداخل BP انجام دهيد.

نقطه قوت اين سيستم اين است که پس از ثابت نگهداشتن ثبات BP، مي‌تواند پشته را بطور آزاد براي هر منظوري استفاده کرد و در نتيجه ثبات SP را تغيير داد، در حالي که مي‌توان با استفاده از ثبات BP آرگومانها را دستيابي کرد.

اگر برنامه‌اي به اضافه کردن آرگومان‌ها روي پشته و فراخواني روالها ادامه دهد، در اين صورت برنامه اصلي و يا روالهاي مربوطه بايستي اين مقادير را از پشته حذف کنند که در غير اين صورت ممکن است پشته سر زير نمايد. برنام اصلي مي‌تواند اين کار را انجام دهد که تعداد بايتهائي را که بايستي آزاد شوند به ثبات SP اضافه کند.

اگر از پشته براي برگرداندن يک يا چند مقدار به برنامه اصلي استفاده شود، هيچکدام از اين تکنيکها بدون تغيير کار نخواهد کرد.

 

بازگشت پذيري (Recursion)

 

يک روال يا تابع بازگشتي روال يا تابعي است که بطور مستقيم يا غير مستقيم خودش را فراخواني نمايد. بهترين الگوريتم‌ها براي پردازش بسياري از ساختارهاي اطلاعاتي بصورت بازگشتي مي‌باشند.

 

اگر پارامترها روي پشته انتقال يابند، در اين صورت براي هر فراخواني روال مزبور فضاي جديدي براي پارامترهاي آن تخصيص داده مي‌شود بطوري که آرگومانهاي انتقالي به يک فراخواني روال با آرگومانهاي انتقالي به فراخواني ديگر آن روال اشتباه نمي‌شوند به همين ترتيب، اگر مقادير پشته ذخيره مي‌شوند، در اين صورت مي‌توان از همان ثبات‌ها و يا حتي مکانهاي حافظه در هر فراخواني بازگشتي يک روال استفاده نمود.

 

بدنه يك روال دستورالعملهاي  call , return

 

- دستور call باعث فراخوانی یک روال میگردد

- در این حالت آدرس برنامه جاری در stack دخیره میگردد

- پس از پایان روال و با اجرای دستور ret مقدار قبلی PC از stack  بازیابی شده و ادامه برنامه از سر گرفته میشود

 

دستورالعملهاي push , pop

 

- بسیار محتمل است مقادیر رجیسترها در داخل یک روال تغییر کند لذا ذخیره ساری مقادیر اولیه ضروری است

- برای ذخیره سازی مقادیر رجیسترها از دستور push استفاده میشود که این دستور باید در ابتدای روال قرار گیرد

- برای بازگشت مقادی اولیه به رجیسترها از دستور pop استفاده میشود .این دستورات میباید آخرین دستورات یک روال باشند

 

انتقال مقادير به يك روال و بالعكس

- برا یانتقال مقادیر به روال و بر عکس دو روش وجود دارد

1-  استفاده از پشته : که در این حالت مقادیر ارسالی را با استفاده از دستور push به پشته فرستاده و در داخل روال با دستور pop آنرا فراخوانی میکنیم

2-  استفاده از سگمنت داده ای : در این حالت آدرس خاصی از سگمنت را برای انتقال پارامترها در نظر میگیریم و در داخل روال نیز داده ها را از آدرس فوق بازیابی میکنیم

 

بازگشت پذيري (recursion)

- یک برنامه recursive برنامه ای است که خود را فراخوانی میکند

- پیاده سازی یک برنامه خودفراخوان یا بازگشت پذیر در اسمبلی به راحتی نوشتن هر برنامه دیگر است

- تنها خطر برنامه های خود فراخوان سرریز پشته است زیرا در هر فراخوانی یکبار مقدار pc در پشته ذخیره میگردد

 

استفاده از دستورالعمل‌هاي رشته‌اي

 

پنج دستورالعمل وجود دارد که براي عمليات بر روي رشته‌ها طراحي شده‌اند:

  1. Movs : براي کپي‌کردن يک رشته از يک موقعيت حافظه به موقعيت ديگر
  2. Cmps: براي مقايسه محتويات دو رشته
  3. Scas: مي‌توان در يک رشته به دنبال يک مقدار معين گشت.
  4. Stos : مي‌تواند براي ذخيره کردن يک مقدار جديد در يک رشته به کار برود.
  5. Lods: يک مقدار را از يک رشته به دست مي‌آورد.

 

رشته به مجموعه‌اي متوالي از بايت‌ها يا کلمات در حافظه اشاره مي‌کند.

معمولاً در يک برنامه رشته‌ها به وسيله دستورات اسمبلر زير در سگمنت داده تعريف مي‌شوند:

Respons DB80  Dup(?)

Label_1 DB 'the results are',0

Word_string DW50 Dup (?)

 

هر دستورالعمل رشته‌اي روي يک رشته منبع، يک رشته مقصد يا هر دو عمل مي‌کند.

براي مشخص کردن هر بايت يا هر کلمه از روش آدرس‌دهي غيرمستقيم ثبات استفاده مي‌گردد. اين دستورالعمل‌ها براي دستيابي عناصر رشته مبدأ از آفستي که در ثبات SI قرار دارد و براي دستيابي عناصر رشته مقصد از آفستي که در ثبات DI قرار دارد، استفاده مي‌کنند. عنصر مبدأ در سگمنت داده قرار دارد بنابراين آدرس واقعي آن عبارت از DS:SI مي‌باشد. عنصر مقصد در سگمنت فوق‌العاده قرار دارد، بنابراين آدرس واقعي آن عبارت از ES:DI مي‌باشد.

از آنجايي که آدرس‌هاي عناصر رشته‌اي مبدأ و مقصد هميشه در ثبات‌هاي SI و DI قرار دارند، براي مشخص کردن اين آدرس‌ها به هيچ عملوندي نياز نمي‌باشد. در اين صورت اسمبلر اندازه عناصري را که بايد مورد استفاده قرار بگيرند نمي‌داند.

ماکرو اسمبلر شرکت مايکروسافت براي حل اين مشکل دو راه پيشنهاد مي‌کند:

 

  1. از عملوندهاي مقصد و منبع استفاده شود.
  2. از فرم‌هاي خاصي از دستور که اندازه عنصر را تعيين مي‌کنند، استفاده نمود.

وقتي عناصر در اندازه بايت مورد استفاده قرار مي‌گيرند، ثبات‌هاي DI و SI (شاخص) فقط يک واحد تغيير داده مي‌شوند ولي وقتي که عناصر در اندازه کلمه مورد استفاده قرار مي‌گيرند، ثبات‌هاي SI و DI به اندازه دو واحد تغيير مي‌کنند.

جهت حرکت به وسيله فلگ جهت (DF) که بيت دهم ثبات نشانه‌ها است، تعيين مي‌شود.

اگر فلگ DF حاوي مقدار يک باشد، آنگاه مقادير SI و DI به وسيله دستورالعمل‌هاي رشته‌اي کاهش داده مي‌شوند. بنابراين جهت رشته از سمت راست به چپ است.

اگر فلگ DF حاوي مقدار صفر باشد، آنگاه مقادير SI و DI به وسيله دستورالعمل‌هاي رشته‌اي افزايش داده مي‌شوند. بنابراين دو رشته از چپ به راست مورد پردازش قرار مي‌گيرند.

دستور cld فلگ DF را صفر مي‌کند؛

دستور ctd فلگ DF را يک مي‌کند.

دستورالعمل انتقال رشته يعني MOVS يک عنصر رشته (بايت يا کلمه) را از رشته مبدأ به رشته مقصد انتقال مي دهد.

دستورالعمل movs بر روي هيچ فلگي اثر نمي‌گذارد.

قبل از استفاده از movs، بسياري مراحل مقدماتي بايد انجام شوند:

ثبات سگمنت فوق‌العاده ES بايد حاوي شماره سگمنت رشته مقصد باشد.

ثبات‌هاي DI و SI بايد به آفست اولين بايت رشته‌اي که بايد مورد پردازش قرار گيرند، مقداردهي گردند.

ثبات نشانه‌ها بايد به مقدار مناسب، مقداردهي شود.

 

براي آنکه بدانيم آيا بايت بعدي مبدأ همان کاراکتر تهي است، دستور زير مورد استفاده قرار مي‌گيرد:

While: cmp BYTE PTR [Si],0 ;null source byte?

فرم [Si] نشاندهنده آن است که آدرس‌دهي غيرمستقيم ثبات مورد استفاده قرار گرفته است، بنابراين عنصري که در آفست SI قرار دارد، مورد استفاده قرار مي‌گيرد و اين همان بايت جاري رشته مبدأ است.

 

پيشوندهاي تکرار:

پيشوند rep معمولاً با دستورالعمل movs و دستورالعمل Stos به کار مي‌رود. اين پيشوند باعث مي‌شود که طرح زير اجرا شود:

While (shomareye mojood dar CX != 0 ) loop

 دستورالعمل اوليه را اجرا کن ;

کم کن CX يک واحد از;

End while;

دو پيشوند تکرار ديگر عبارتند از repe و repne.

فرم repe به معني «تا زماني که حالت تساوي وجود دارد، تکرار کن» و فرم repz يعني «تا زماني که صفر است تکرار کن» مي‌باشد.

به همين ترتيب repne و repnz‌به معني «تا زماني که حالت مساوي وجود ندارد تکرار کن» و «تا زماني که صفر نيست تکرار کن» مي‌باشد. هر کدام از اين پيشوندهاي تکرار مناسب استفاده با دو دستورالعمل رشته‌اي cmps و scas که بر روي فلگ صفر اثر مي‌کنند، مي‌باشند.

 

اين پيشوندها تا زماني که CX صفر نيست، دستورالعمل اوليه را تکرار مي‌کنند.

پيشوندهاي repe و repz تکرار را تا زماني که ZF=1‌است تکرار مي‌کنند.

پيشوندهاي repne و repnz تکرار را تا زماني که ZF=0 است تکرار مي‌کنند.

 

Cmps دو عنصر رشته‌اي را تفريق کرده و فلگ‌ها را بر اساس آنها تنظيم مي‌کند؛ هيچکدام از عملوندها تغيير داده نمي‌شوند.

چنانچه به وسيله دستور cmps بخواهيم بدانيم که دو رشته مشابه هستند، پيشوند repe براي همراهي با اين دستورالعمل کاملاً مناسب است.

اغلب لازم است رشته‌اي که در درون رشته ديگري قرار دارد، جستجو کرد.

 

تست مقابل براي تطبيق مي‌تواند صورت بگيرد

;آدرس رشته موردنظر SI:=

+POSITION-1;آدرس رشته مقصد DI:=

;طول رشته موردنظر CX:=

 Forever loop

; end if از حلقه خارج شو If CX=0 then;

 [DI] و [SI]را مقايسه کن و متناسب با آن ZFرا تنظيم کن

 SI;را افزايش بده

 ;  DI را افزايش بده

 CX; را کاهش بده

  ; enf if ;از حلقه خارج شود   If ZF=0 the

End loop;

If ZF-1

Then

 ;رشته موردنظر پيدا شد  

End if;

 

 

 

 

 

دليل وجود if‌اضافي در انتهاي طرح آن است که:

از آنجايي که حلقه وقتي تمام مي‌شود که CX=0 بوده و يا زماني که ZF=0 باشد، لازم است اطمينان حاصل نمود که آخرين جفت کاراکترهاي مقايسه شده يکسان بوده‌اند.

دستورالعمل پويش رشته‌اي scas براي پويش يک رشته جهت وجود داشتن و يا وجود نداشتن يک عنصر رشته‌اي معين به کار مي‌رود.

فرم‌هاي scasb و scasw از هيچ عملوندي استفاده نمي‌کنند زيرا فرم دستور اندازه عنصر موردنظر را تعيين مي‌نمايد.

 

دستورالعمل ذخيره‌سازي رشته‌اي stos يک بايت يا يک کلمه را از ثبات AL يا رشته AX به يک عنصر رشته مقصد کپي مي‌نمايد.

اين دستور بر روي هيچ فلگي اثر نمي‌گذارد. بنابراين وقتي که اين دستورالعمل با پيشوند rep تکرار شود، يک مقدار را در موقعيت‌هاي متوالي يک رشته کپي مي‌نمايد.

دستورالعمل بار کردن رشته‌اي lods يک عنصر رشته مبدأ را به ثبات AL يا ثبات AX بار مي‌نمايد. دستورالعمل lods بر روي فلگ‌ها هيچ اثري نمي‌گذارد.

 

ترجمه کاراکترها

دستورالعمل Xlat يک کاراکتر را به کاراکتر ديگري ترجمه مي‌نمايد.

اين دستورالعمل در ترکيب با دستورالعمل‌هاي پردازش رشته به راحتي مي‌تواند تمام کاراکترهاي يک رشته را ترجمه کند.

قبل از اجراي دستورالعمل Xlat، کاراکتري که بايد ترجمه شود در ثبات AL قرار داده مي‌شود. اين دستورالعمل براي ترجمه بايتي که در آن AL قرار دارد از يک جدول ترجمه که در سگمنت داده قرار دارد استفاده مي‌کند.

به طور کلي Xlat از کاراکتري که ترجمه مي‌گردد بعنوان آفست در جدول ترجمه استفاده مي‌نمايد و بايتي را که در آفست مزبور قرار دارد جايگزين آن مي‌کند.

دستورالعمل Xlat داراي دو فرم زير است:

Xlat

و

Xlat table_name

در فرم دوم، عملوند table_name‌بايد جدول ترجمه را آدرس‌دهي نمايد. البته استفاده از اين عملوند به طور خودکار ثبات BX را مقداردهي نمي‌نمايد. اين عملوند مي‌تواند حذف گردد مگر در موارد نادري که نياز به پيشوند اعلام صريح ثبات سگمنت وجود داشته باشد.

ترجمه يک کاراکتر به خودش مجاز است. همين اتفاق براي ارقام عددي مي‌افتد. کدهاي اسکي 3016 تا 3916 که معرف اعداد صفر تا 9 هستند در آفست‌هاي 3016 تا 3916 قرار گرفته‌اند. کدهاي هفت کاراکتر : تا @ کاراکترهاي بعدي جدول اسکي هستند، هرکدام از آنها به يک فاصله خالي ترجمه خواهند شد.

 

تبديل يک عدد مکمل دو به يک رشته اسکي

ماکروي itoa براي تبديل يک عدد صحيح مکمل دو به يک رشته شش کاراکتري جهت خروجي، مورد استفاده قرار گرفته است.

اين دستورالعمل‌ها براي ارسال پارامترها به روال itoa_proc از ثبات‌هاي AX و DI استفاده مي‌نمايند. بنابراين کاربر نبايد نگران دست خوردن هيچکدام از ثبات‌ها باشد. ثبات‌هاي AX و DI ابتدا در پشته ذخيره شده و در انتهاي برنامه بازيابي مي‌شوند. عدد مکمل دو که در source قرار دارد در ثبات AX و آدرس مقصد جهت رشته در ثبات DI قرار داده مي‌شود.

 

استفاده از دستورالعملهاي رشته اي

در زبان اسمبلی 5 دستورالعمل رشته ای وجود دارد

انتقال رشته ها MOVS  

 مقایسه رشته ها CMPS

 پویش رشته ها SCAS

 ذخیره رشته ها STOS

 بارگذاری رشته ها LODS

 

پيشوندهاي تكرار و بقيه دستورالعملهاي رشته اي

 

شرط تکرار

پیشوند

CX <> 0

REP

CX <> 0 and ZF=1

REPE

CX <> 0 and ZF=1

REPZ

CX <> 0 and ZF=0

REPNZ

CX <> 0 and ZF=0

REPNE

 

 در زبان اسمبلی 3 پیشوند تکرار دستورالعملهای رشته وجود دارد

 تکرار انتقال یا ذخیره سازی آرایه  REP ( MOVS STOS )

تکرار تا وجود حالت تساوی   repz repe

 تکرار تا شرط عدم وجود حالت تساوی   repnz repne

 

ترجمه كاراكترها

- کارکترها در فرمهای نمایش متفوتی نشانداده میشوند

- فرم ebcdic یک عد یک عدد 7 بیتی است که توان نمایش 128 کاراکتر را دارد

- فرم ascii یک عدد یک بایتی برای نمایش 256 کارکتر را دارد

- دستور xlat  در زبان اسمبلی برای ترجمه کارکترها مورد استفاده قرار میگیرد

 

تبديل يك عدد مكمل 2 به يك رشته اسكي

 

- در زبان اسمبلی ماکروی itoa  برا ی این تبدیل در نظر گرفته شده است

استفاده از این ماکرو به این دلیل ضرورت دارد که همواره اعدادی که از صفحه کلید دریافت میشوند بصورت کارکتر بوده و برای ذخیره در رجیسترها باید بصورت عدد مکمل 2 در آیند