View Full Version : سوال: تابع بازگشتی
mc_laren
سه شنبه 29 اردیبهشت 1388, 23:48 عصر
به نام خدا
با سلام
لطفا از دوستان اگه کسی شیوه نوشتن یک تابع به روش بازگشتی رو بلده ما رو بی
نصیب نزاره.
باتشکر
tdkhakpur
چهارشنبه 30 اردیبهشت 1388, 00:41 صبح
سلام:
برای چی با اسمبلی میخاییش ولی بازم کد زیر رو پایه قرار بده.
SW DW 10
PROC1 PROC
SUB DW, 1
CMP DW, 10
JE LABEL1
;-----------------------------------------
; برنامها رو اینجا قرار بده و شرط دلخواهت رو بالا بررسی کن
;-----------------------------------------
CALL PROC1
LABEL1:
RET
PROC1 ENDP
در بالا برنامه شما 10 بار تابع رو به روش بازگشتی صدا میزنه.
موفق باشید.
mortezamsp
چهارشنبه 30 اردیبهشت 1388, 16:26 عصر
باسلام.
من اینجا سعی کردم برنامه فیبوناتچی رو بصورت بازگشتی بنویسم.ببینید درسته یا نه! من الان در شرایطی هستم که امولاتور ندارم.
برنامه ساختن فیبوناتچی بصورت بازگشتی:
n db 10 ;تاجمله ی دهم را بسازد
x db 0 ;حاصل جواب
y db 0 ;متغیر کمکی
call fibo
fibo proc
mov al,n
cmp n,1
je lable_1
cmp al,2
je lable_1
jne lable_3
lable_1:
add x,1
push x
ret
lable_3:
mov y,x
dec n
call fibo ;بازگشت
pop x
add x,y
fibo endp
آیا بنظر شما این درست بیده؟
تنها راه برای بازگشتی همون تعریف proc هستش. باید در هر proc دو شرط برای خانه آخر و غیر از آن قرار داد. درصورتیکه ما نوز به مرحله آخر نرسیده باشیم باید ابتدا مقدار حاصل را نگه داریم ، سپس proc را مجددا call کنیم ، و پس از پایان کار proc آن را pop کنیم .
mc_laren
پنج شنبه 31 اردیبهشت 1388, 20:37 عصر
با سلام
ضمن تشکر از پاسخ .
لطفا در مورد دستور ret توضیح دهید.
در ضمن آیا نباید در اسمبلی در تابع های بازگشتی برعکس زبان های سطح بالا خودمان در انتهای برنامه
پشته را مدیریت کنیم؟
tdkhakpur
پنج شنبه 31 اردیبهشت 1388, 22:07 عصر
سلام:
نخیر تا وقتی که شما دستور push رو در برنامتون استفاده نکردید لازم به مدیریت پشته نیست.
واما ret باعث میشه که از صف پشته مکان قبل از ورود به تابع جاری برداشته شده و در داخل cs و ipقرار بگیره.
ولی یه توضیحی به شما بدم و اون اینه که در توابع بازگشتی حتما ار دستور local استفاده کن تا متغییر هایتون عمومی نباشن.
proc1 proc
local begin, num1, x, y
jmp begin
x dw ?
y dw ?
num1 db 10 dup(?)
begin:
;....................
;....................
;....................
;....................
proc1 endp
mc_laren
سه شنبه 05 خرداد 1388, 12:55 عصر
با سلام
من این برنامه رو نوشتم که بصورت بازگشتی دو عدد 2 بایتی رو درهم ضرب می کنه . اما استاد گیر داده
میگه نباید از تابع call استفاده کنی و بجای اون باید از push,pop استفاده کنی .کسی می تونه کمک کنه؟
st_seg segment
db 64 dup(?)
st_seg ends
dt_seg segment para 'data'
N1 dw 04h
N2 dw 0ffffh
sum dd 0h
dt_seg ends
codesg segment para 'code'
main proc far
assume ds:dt_seg,cs:codesg,ss:st_seg
mov ax,dt_seg
mov ds,ax
call zarb
mov ax,4c00h
int 21h
main endp
zarb proc
cmp N1,0
je exit
dec N1
mov AX,word ptr sum
add AX,N2
mov word ptr sum,AX
mov bx,word ptr sum+2
adc bx,0
mov word ptr sum+2,BX
call zarb
exit:
ret
zarb endp
codesg ends
end main
tdkhakpur
سه شنبه 05 خرداد 1388, 17:30 عصر
سلام:
ببینید اگه call رو بررسی کنید دارای یه آپ کد هست که خودش در حقیقت عمل push و popرو انجام میدهد. قتی شما call میکنید آدرس فعلی توسط push داخل پشته قرار میگیره و به هنگام ret کردن این آدرس از پشته برگردونده میشود, cs:ipبه محل مورد نظر برمیگرده..
حالا برنامه ات رو بشکل زیر Call کنید.
;-----------------------
lea bx, Label1
push bx
jump zepra
Label1:
موفق باشید.
mc_laren
سه شنبه 05 خرداد 1388, 17:56 عصر
اگه در مورد کد کمی توضیح داده بشه بهتره!
tdkhakpur
سه شنبه 05 خرداد 1388, 18:23 عصر
سلام:
بالای اون کد ها توضیح کلی رو داده بودم.
ولی مرور میکنیم.
lea bx, Label1
این کد ادرس جایی رو که میخواییم بعد از برگشت از تابع به آن نقطه برگردیم رو در رجیستر bx قرار میدیم.
push bx
مقدار آدرس رو درون پشته قرار داده تا توسط ret از پشته برگردونده بشه یعنی به محل دستور بعدی بتونیم برگردیم.
jmp zebra
با کد فوق به تابع میرویم این عمل در اصل کار call رو انجام میده البته بدون push کردن آدرس جاری
Label1:
این آدرس برگشت هست که ret اون رو از پشته برمیداره.
موفق باشید.
shahin0
جمعه 08 خرداد 1388, 04:05 صبح
st_seg segment
db 64 dup(?)
st_seg ends
dt_seg segment para 'data'
N1 dw 04h
N2 dw 0ffffh
sum dd 0h
dt_seg ends
codesg segment para 'code'
main proc far
assume ds:dt_seg,cs:codesg,ss:st_seg
mov ax,dt_seg
mov ds,ax
call zarb
mov ax,4c00h
int 21h
main endp
zarb proc
cmp N1,0
je exit
dec N1
mov AX,word ptr sum
add AX,N2
mov word ptr sum,AX
mov bx,word ptr sum+2
adc bx,0
mov word ptr sum+2,BX
call zarb
exit:
ret
zarb endp
codesg ends
end main
سلام دوست عزیز من با کامپایل این برنامه که شما گذاشتید مشکل دارم این ارور رو میده
End of file encountered on input file
2b.asm(42) : error 85: End of file, no END directive
End of file encountered on input file
48800 Bytes symbol space free
1 Warning Errors
1 Severe Errors
میشه راهنمایی کنید مشکل کجاست ؟
tdkhakpur
جمعه 08 خرداد 1388, 14:30 عصر
سلام
بصورت زیر کامپایل کنید.
masm b2.asm, b2.obj, b2.map, b2.crf
link b2.obj, b2.exe, nul, nul, nul
mc_laren
جمعه 08 خرداد 1388, 23:52 عصر
برنامه مشکلی نداشته و با masm کامپایل میشه فقط با Emu8086 یک ایراد به نوع داده dd که 4 بایتی میگیره.
tdkhakpur
شنبه 09 خرداد 1388, 11:21 صبح
سلام
اسمبلی هست و 1001 راه
خوب شما dd رو ربصورت ریز استفاده کتید.
result dw 2 dup(?)
shahin0
دوشنبه 11 خرداد 1388, 22:57 عصر
برای برنامه قبلی تشکر مشکل حل شد . فقط در استفاده ازش یه مشکل هست من تایپ میکنم 2b.exe 2 2 و انتظار دارم این دو رقم ضرب کنه و خروجی بده ولی جواب نمیده .؟ آیا من درست پیش میرم
و اگه امکان داره در رابطه با این برنامه هم راهنمایی کنید . من تازه کارم و با تعریف داده کد و کامل کردن این برنامه مشکل دارم . اگه راهنمایی کنید ممنون میشم.
برنامه ساختن فیبوناتچی بصورت بازگشتی:
n db 10 ;تاجمله ی دهم را بسازد
x db 0 ;حاصل جواب
y db 0 ;متغیر کمکی
call fibo
fibo proc
mov al,n
cmp n,1
je lable_1
cmp al,2
je lable_1
jne lable_3
lable_1:
add x,1
push x
ret
lable_3:
mov y,x
dec n
call fibo ;بازگشت
pop x
add x,y
fibo endp
shahin0
جمعه 15 خرداد 1388, 02:06 صبح
از دوستان کسی مایل به راهنمای نیست . . . !
shahin0
شنبه 16 خرداد 1388, 02:09 صبح
آیا سوال من مشکلی داره که کسی جواب نمیده ؟
kiuhnmgtrdcv
یک شنبه 21 تیر 1388, 10:50 صبح
برنامه های بازگشتی در اسبملی به صورت کلی اینطوری کار میکنند
در تابع بازگشتی
اول شرط مقایسه
فراخوانی تابع
محاسبات
__
myproc proc
push bp
mov bp,sp
cmp [bp+4],something
jz somewhere
push something
call myproc
pop something
somewhere:
pop bp
ret
در اخر کد به تعدادی که پوش کردیم با ret پاپ خواهیم داشت و ret 2 نمیگذاریم و .. برای پارامترها (نکتش اینجاست)
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.