PDA

View Full Version : سوال: در مورد پشته و لیبل اصلی برنامه



Kboy-9043
پنج شنبه 25 خرداد 1391, 07:33 صبح
سلام دوستان.

در مورد پشته و ليبل اصلي برنامه سوال دارم.

1. به تصوير زير نگاه کنيد:

http://img.majidonline.com/pic/276595/as1.jpg

در مورد اينکه گفته "معمولا در ابتداي هر زيربرنامه بهتر است مقادير ثبات هائي که تغيير مي کنند را در پشته ذخيره نمائيم و در انتهاي زيربرنامه و قبل از دستور ret مقادير آنها را از پشته بازيابي کنيم."

خب داخل ثبات هاي ax , cx چه مقاديري جاي مي گيرد؟

اگر مي شود يک مثال ملموس تر و واضح تر بزنيد.؟

مگه قبل از و بعد از قرار گرفتن در پشته اين ثبات ها چه مقاديري رو دارند؟

و اينکه چرا در زيربرنامه ها پشته تعريف مي کنيم؟(به غير از اون مورد مزیت براي ادرس هاي بازگشتي)
کی و چه موقع هایی بهتر هستش پشته تعریف کنیم؟

-------------------

2. تصوير زير رو نگاه کنيد.

http://img.majidonline.com/pic/276596/as2.jpg

سوال: از کجا بايد فهميد که lable اصلي برنامه رو کجا بايد قرار داد؟منظورم اينه که، چه مقاديري بايد درون
ليبل اصلي برنامه جاي بگيرند؟

ممنونم.

MostafaMohammadi
پنج شنبه 25 خرداد 1391, 13:03 عصر
من فقط جواب سوال اول ات رو میدم چون سوال دوم ات برای من گنگ‌ه.
فرض کن وسط یه برنامه محاسباتی هستی و یه عدد رو گرفتی و ریختی تو ثبات AX و یه عدد هم توی ثبات DX حالا می خواهی یه زیر برنامه بنویسی که اگه DX از AX بزرگتر بود یه پیغام خطا چاپ بشه. چون در یک جایی از اون زیر برنامه قراره یه پیغام چاپ بشه و برای چاپ رشته هم ما باید ثبات های AH و DX رو مورد استفاده قرار بدیم (شماره سرویس میره تو AH و آدرس آفست پیغامی که می خواهیم چاپ کنیم میره تو DX) وقتی بریم توی زیر برنامه و ازش در بیاییم دیگه اعدادی که توی AX و DX داشتیم تغییر کرده و محاسبات ما بهم میریزه. برای همین قبل از اینکه بریم تو زیر برنامه، محتویات AX و DX رو میریزیم توی پشته، پشته رو مطالعه کردی؟ بلدی اش؟ بعد هم که از زیر برنامه در اومدیم اون محتویات رو می خونیم و میریزیم سر جاشون. اینجا پشته میشه یه مکان موقت برای اطلاعات ما تا از بین نرن.

ssbostan
پنج شنبه 25 خرداد 1391, 13:17 عصر
با سلام؛
حتما نياز نيست زيربرنامه اي كه ايجاد ميكنيد ثبات هايي رو كه مورد استفاده قرار ميده اول در پشته ذخيره كنه و بعد از انجام عمليات دوباره از پشته خارج كنه.
اين عمليات رو شما هنگامي انجام ميديد كه اطلاعات درون ثبات هارو نياز داريد و الان هم نياز هست كه زيربرنامه، مثلا print رو صدا بزنيد. چون اين زيربرنامه باعث ميشه مقادير درون ثبات ها تغيير كنه، شما اول ثبات هارو در پشته ذخيره ميكنيد و بعد از تمام شدن عمليات اصلي زيربرنامه دوباره مقادير ثبات هارو به حالت اول برميگردونيد كه در ادامه برنامه بتونيد از اونها استفاده كنيد.
مشخص هست كه ثبات هارو وقتي به پشته مي بريد بايد برعكس ترتيبي كه وارد پشته كرديد خارج كنيد، چراكه ساختمان و ساختار پشته به صورت LIFO پياده سازي شده.

مثال:



mov ax, 1
mov cx, 2
mov dx, 5

call sum_print

add ax, cx
add ax, dx

call sum_show

mov ax, 4c00h
int 21h




sum_print proc

push ax
push dx
mov ax, 0900h
lea dx, myvar
int 21h
pop dx
pop ax
ret

sum_print endp


sum_show proc

push ax
push dx
mov dx, ax
add dx, 30h
mov ax, 0200h
int 21h
pop dx
pop ax
ret

sum_show endp


myvar db "print:", 24h

در مثال بالا اگر تابع sum_print مقادير رو در پشته ذخيره نكنه، اطلاعات مورد نياز من(اعداد) از بين خواهد رفت و جواب تابع sum_show چيز ديگري خواهد شد.

خروجي برنامه در حالتي كه مقادير مورد نياز در پشته ذخيره شده و بعد از پشته به ثبات ها برگردانده ميشود.

print:8

خروجي برنامه در حالتي كه مقادير مورد نياز در پشته ذخيره نشوند و توسط تابع تغيير كنند:

print:e'

پشته هم يه حافظه اي هست كه شما ميتونيد اطلاعاتتون رو درش ذخيره كنيد. مثلا شما هنگامي كه يك تابع رو صدا ميزنيد، افست فعلي برنامه + 1 ميشه و در پشته ذخيره ميشه و هنگامي كه از تابع با دستور ret خارج ميشيد تابع به افستي كه در پشته ذخيره شده پرش ميكنه و ادامه برنامه از سر گرفته ميشه.

دستور ret رو ميتونيد به اين شكل هم بنويسيد:


pop di
jmp di

آدرس بازگشت برنامه در پشته بوده، من از پشته آدرس رو خارج كردم و پرش زدم.

در مورد label هم، وقتي شما يك label ايجاد ميكنيد در اصل داريد به يك افست اشاره ميكنيد كه هنگام اسمبل شدن برنامه آدرس افست اين برچسب در symbol table مشخص ميشه و در برنامه شما هرجا به اون برچسب اشاره بشه در اصل داره به افست اي از حافظه اشاره ميشه.

مثال:


TEST_LABEL 00018 -1 LABEL (NOSEG)


استفاده از برچسب در طول برنامه به اختيار خودتون هست و قانوني نيست كه بگه برچسب كجا باشه و زير برچسب چه دستوراتي قرار بگيره.

موفق باشيد.

Kboy-9043
پنج شنبه 25 خرداد 1391, 19:38 عصر
از هر دو شما دوستان عزیز ممنونم.
خود ساختار پشته رو کامل می دونم.

اما چون توی روال به کار رفته بود کمی گیج شدم.

سوال:

sum_show proc

push ax
push dx
mov dx, ax
add dx, 30h

الان مقدار داخل dx اول که با رنگ قرمر نشون دادم چقدر بوده که push شده هستش؟
برای چی dx رو هم push کردیم؟

--------------

در مورد سوال دومم هم که در خصوص لیبل اصلی بود منظورم این هستش که:

اگر تصویری که در خصوص سوال دوم قرار دادم رو ببینید لیبل اصلی begin هستش حالا میان
همین لیبل اصلی چندتا مورد رو قرار داده که نشون دادم.حالا سوالم این بود که ما همیشه چه مقادیری
در لیبل اصلی قرار دهیم؟مثل همین تصویر که قرار دادم و مواردی رو در لیبل اصلی begin قرار داده.

ازتون خیلی خیلی ممنونم.

MostafaMohammadi
پنج شنبه 25 خرداد 1391, 23:02 عصر
در مورد سوال دومم هم که در خصوص لیبل اصلی بود منظورم این هستش که:

اگر تصویری که در خصوص سوال دوم قرار دادم رو ببینید لیبل اصلی begin هستش حالا میان
همین لیبل اصلی چندتا مورد رو قرار داده که نشون دادم.حالا سوالم این بود که ما همیشه چه مقادیری
در لیبل اصلی قرار دهیم؟مثل همین تصویر که قرار دادم و مواردی رو در لیبل اصلی begin قرار داده.

ازتون خیلی خیلی ممنونم.
منظورت اینه که چه اجزایی از سگمنت کد همیشه توی همه برنامه ها تکرار میشه؟
این دستورات
.CODE
BEGIN:
MOV AX, @DATA
MOV DS, AX
.
.
.
MOV AX, 4C00h
INT 21h
END BEGIN
دو خط اول آدرس سگمنت داده رو میریزه تو ثبات DS و دو خط آخر هم وقفه ایه که کنترل رو به سیستم عامل باز می گردونه.

MostafaMohammadi
پنج شنبه 25 خرداد 1391, 23:10 عصر
از هر دو شما دوستان عزیز ممنونم.
خود ساختار پشته رو کامل می دونم.

اما چون توی روال به کار رفته بود کمی گیج شدم.

سوال:

sum_show proc

push ax
push dx
mov dx, ax
add dx, 30h

الان مقدار داخل dx اول که با رنگ قرمر نشون دادم چقدر بوده که push شده هستش؟
مقدار اش 5 بوده.

برای چی dx رو هم push کردیم؟

فرض کن وسط یه برنامه محاسباتی هستی و یه عدد رو گرفتی و ریختی تو ثبات AX و یه عدد هم توی ثبات DX حالا می خواهی یه زیر برنامه بنویسی که اگه DX از AX بزرگتر بود یه پیغام خطا چاپ بشه. چون در یک جایی از اون زیر برنامه قراره یه پیغام چاپ بشه و برای چاپ رشته هم ما باید ثبات های AH و DX رو مورد استفاده قرار بدیم (شماره سرویس میره تو AH و آدرس آفست پیغامی که می خواهیم چاپ کنیم میره تو DX) وقتی بریم توی زیر برنامه و ازش در بیاییم دیگه اعدادی که توی AX و DX داشتیم تغییر کرده و محاسبات ما بهم میریزه. برای همین قبل از اینکه بریم تو زیر برنامه، محتویات AX و DX رو میریزیم توی پشته، پشته رو مطالعه کردی؟ بلدی اش؟ بعد هم که از زیر برنامه در اومدیم اون محتویات رو می خونیم و میریزیم سر جاشون. اینجا پشته میشه یه مکان موقت برای اطلاعات ما تا از بین نرن.