PDA

View Full Version : توقف چند ثانیه ای اجرا برنامه



هم دانشگاهی
جمعه 29 اردیبهشت 1391, 23:17 عصر
سلام
چه طوری در اسمبلی مانند ++C برنامه را چند ثانیه ای sleep کنیم؟
ممنون

ssbostan
شنبه 30 اردیبهشت 1391, 10:39 صبح
سلام؛
رجوع شود به تابع 86h از وقفه 15h.

موفق باشيد.

هم دانشگاهی
شنبه 30 اردیبهشت 1391, 19:12 عصر
خب این intrrupt چه جوری کار میکنه ؟

ssbostan
شنبه 30 اردیبهشت 1391, 22:04 عصر
اين صفحه رو بخونيد، متوجه ميشيد.
http://www.ctyme.com/intr/rb-1525.htm

اگر مشكلي بود توضيح ميدم.

هم دانشگاهی
دوشنبه 01 خرداد 1391, 12:31 عصر
من درست متوجه نشدم
میشه یک ماکرو براش بنویسین !
ممنون

MostafaMohammadi
دوشنبه 01 خرداد 1391, 14:20 عصر
من درست متوجه نشدم
عجیبه که متوجه نشدین!
مدت زمان مورد نظرت رو به واحد میکروثانیه بریز تو ثبات های CX:DX، بعد Int 15/AH=86h رو اجرا کن. وقتی مدت زمان مد نظرت سپری بشه، Carry Flag صفر میشه.

هم دانشگاهی
دوشنبه 01 خرداد 1391, 19:25 عصر
من اینجوری نوشتم

mov cx,1000
mov dx,0000
mov ah,86h
int 15h

ولی اصلا اجرا برنامه متوقف نمیشه !
درست نوشتم ؟!

MostafaMohammadi
دوشنبه 01 خرداد 1391, 22:52 عصر
من اینجوری نوشتم

mov cx,1000
mov dx,0000
mov ah,86h
int 15h


درست نوشتم ؟!
بله درست نوشتید، با این تکه کدی که نوشتید 65 ثانیه صبر می کنه بعد میره دستوری که بعد از این تکه کد نوشتید.

ولی اصلا اجرا برنامه متوقف نمیشه !
با چه محیطی دارید برنامه تون رو می نویسید؟ توی بعضی محیط ها زمان درست محاسبه نمیشه و بعضا میبینی به جای یک ثانیه دو ثانیه صبر می کنه، مثلا یه برنامه می نویسی که هر 60 ثانیه، یک واحد به دقیقه اضافه کنه ولی در عمل هر 120 ثانیه این کار رو می کنه!:لبخند:

هم دانشگاهی
سه شنبه 02 خرداد 1391, 01:07 صبح
من با emu8086 کار میکنم !

در حقیقت اصلا برنامه من متوقف نمیشه چه برسه به 65 ثانیه !

یا خیلی سریع هست که محسوس نیست یا هم که کار نمیکنه !!!

MostafaMohammadi
سه شنبه 02 خرداد 1391, 02:58 صبح
من همین تکه کدی که شما نوشتید رو کپی پیست کردم توی یکی از برنامه هام و جواب داد. شما هم همین کار رو بکنید، این تکه کد رو توی یک برنامه ساده استفاده کنید تا یه موقع ایراد از برنامه تون نباشه. بعلاوه چک کنید دقیقا بعد از اجرا شدن این وقفه CF و AH چه مقادیری دارند.

xman_1365_x
سه شنبه 02 خرداد 1391, 03:01 صبح
1-این وقفه روی سسیستم های AT کار میکنه BIOS - WAIT (AT,PS)
2-مثالی که در زیر گذاشتم 5 ثانیه تاخیر ایجاد میکنه، کامنت هایی که گذاشتم فکر کنم دیگه نیاز به توضیحی نداره و مثال هم اجرا شده در emu8086 و مشکلی نداره



data segment

pkey db "press any key...$"
ends

stack segment
dw 128 dup(0)
ends

code segment
start:
; set segment registers:
mov ax, data
mov ds, ax
mov es, ax

;32bit:cx:dx
;A microsecond is an SI unit of time equal to one millionth (10^-6) of a second.
;1 second = 1 000 000 microseconds
; cx dx
;32bit=0000 0000 0000 0000 | 0000 0000 0000 0000b
;1sec =0000 0000 0000 1111 | 0100 0010 0100 0000b
;5sec =0000 0000 0100 1100 | 0100 1011 0100 0000b
;60sec=0000 0011 1001 0011 | 1000 0111 0000 0000b


;wait 5sec = 0000 0000 0100 1100 | 0100 1011 0100 0000b
mov cx,004ch
mov dx,4b40h
mov ah,86h
int 15h

lea dx, pkey
mov ah, 9
int 21h ; output string at ds:dx

; wait for any key....
mov ah, 1
int 21h

mov ax, 4c00h ; exit to operating system.
int 21h
ends

end start ; set entry point and stop the assembler.



موفق باشی

xman_1365_x
سه شنبه 02 خرداد 1391, 03:37 صبح
*ضمنا با توجه به پاسخ های ارسالی بد نیست یک سوال برای دوستان مطرح کنم اگر پاسخی ندیدم جواب رو بعد از مدتی اعلام میکنم(جواب ساده هست!)

1-با توجه به مقدار میکرو ثانیه مقدار 65 ثانیه عدد 65sec=65*1000000= 03DF:D240h میباشد پس چرا در مثال قبل یعنی عدد 1000:0000 هم نتیجه ای یکسان در بر داشته ؟



;65sec=65*1000000= 03DF:D240h
mov cx,03DFh
mov dx,0D240h
mov ah,86h
int 15h

;65sec
mov cx,1000h
mov dx,0
mov ah,86h
int 15h


ویرایش:
بد نیست دو سوال دیگه هم اضافه کنم
2- بازه این تابع را هم مشخص کنید؟
3-چرا با زیاد کردن مقدار cx:dx تابع سرریز میکنید و چه مقدار مقدار صحیح میباشد و دلیل این امر چیست؟

برم بخوابم تا سوالات بیشتری ننوشتم:لبخند:
موفق باشید

MostafaMohammadi
سه شنبه 02 خرداد 1391, 05:33 صبح
1-با توجه به مقدار میکرو ثانیه مقدار 65 ثانیه عدد 65sec=65*1000000= 03DF:D240h میباشد پس چرا در مثال قبل یعنی عدد 1000:0000 هم نتیجه ای یکسان در بر داشته ؟



;65sec=65*1000000= 03DF:D240h
mov cx,03DFh
mov dx,0D240h
mov ah,86h
int 15h

;65sec
mov cx,1000h
mov dx,0
mov ah,86h
int 15h

عددی که هم دانشگاهی (http://barnamenevis.org/member.php?160802-%D9%87%D9%85-%D8%AF%D8%A7%D9%86%D8%B4%DA%AF%D8%A7%D9%87%DB%8C) نوشته، اینه:


03 E8 00 00
0000 0011 1110 1000 | 0000 0000 0000 0000
65536000
عددی که شما نوشتی، اینه:


03 DF D2 40
0000 0011 1101 1111 | 1101 0010 0100 0000
65000000

این دوتا با هم یکسان اند؟ خیر، چیزی حدود نیم ثانیه با هم اختلاف دارند:


00 08 2D C0
0000 0000 0000 1000 | 0010 1101 1100 0000
536 000






2- بازه این تابع را هم مشخص کنید؟
بازه اش روی کاغذ از 0 میکروثانیه تا 4294967295 میکروثانیه (1 ساعت و 12 دقیقه) است ولی برای فاصله های زمانی خیلی کوچک یه مشکلی وجود داره:


Note: The resolution of the wait period is 977 microseconds on many systems because many BIOSes use the 1/1024 second fast interrupt from the AT real-time clock chip which is available on INT 70; because newer BIOSes may have much more precise timers available, it is not possible to use this function accurately for very short delays unless the precise behavior of the BIOS is known (or found through testing)



3-چرا با زیاد کردن مقدار cx:dx تابع سرریز میکنید و چه مقدار مقدار صحیح میباشد و دلیل این امر چیست؟
این سوال رو متوجه نشدم.

هم دانشگاهی
سه شنبه 02 خرداد 1391, 08:17 صبح
خیلی عجیبه !:متعجب:
وقتی برنامه ای رو که نوشتید emulate میکنم دقیقا 5 ثانیه متوقف میشه !
ولی وقتی فایل رو compile میکنم سریع از روش رد میشه !
به نظر شما مشکل از کجاست ؟
برای ساختن فایل exe من روی compile میزنم و بعد هم فایل exe رو اجرا میکنم درسته ؟

xman_1365_x
سه شنبه 02 خرداد 1391, 12:52 عصر
دوست عزیز MostafaMohammadi :

هم دانشگاهی این کد رو وارد کردن

mov cx,1000
mov dx,0000
mov ah,86h
int 15h
شما از این عدد چطور به مقدار زیر رسیدین ؟


03 E8 00 00
0000 0011 1110 1000 | 0000 0000 0000 0000
65536000

کمی بیشتر روش فکر کنید،همینطور روی بازه با خوندن حرف زیر برای سوال سوم متوجه میشین
سوال سوم:در مورد سرریز برای مثال اگر شما cx:dx را با ffff:ffffh مقدار دهی کنید تابع سر ریز میکنه اگر حرف شما درست بود این عدد 32 بیتی ما هست و همون بازه میکرو ثانیه 32 بیتی ،
حال
1-مقدار مقدار 65 ثانیه تاخیر برابر هست 65sec=65*1000000= 03DF:D240h این در حالی هست که این مقدار هم 1000:0000 جوابی مشابه دارد دلیل این امر چیست؟
2- بازه صحیح چه عددی هست؟
3- چرا وقتی بزرگتر ازیه عدد خاص میشه سر ریز میکنه؟
موفق باشی

xman_1365_x
سه شنبه 02 خرداد 1391, 14:11 عصر
خیلی عجیبه !
وقتی برنامه ای رو که نوشتید emulate میکنم دقیقا 5 ثانیه متوقف میشه !
ولی وقتی فایل رو compile میکنم سریع از روش رد میشه !
به نظر شما مشکل از کجاست ؟
برای ساختن فایل exe من روی compile میزنم و بعد هم فایل exe رو اجرا میکنم درسته ؟

عجیب نیست، ویندوز nt سری 2k و xp به بعد در ntvdm خیلی از وقفه ها پشتیبانی نمیشه تا جایی که در ویندوز7-64بیتی به طور کامل پشتیبانی از برنامه های 16 بیتی رو حذف کردن

حال دو راه حل
1-خودتون این وقفه رو شبیه سازی کنید،یک مثال در emu8086 Custom_Interrupt.asm
2-با استفاده از وقفه INT 1Ah / AH = 00h - get system time. یا INT 21h / AH=2Ch - get system time;
زمان فعلی رو بخونید بعد اگر برابر با زمان شما شد ادامه کد ها اجرا بشه (فقط یادتون باشه صدم ثانیه رو در محاسبات استفاده نکنید به خطا میخورید)

یک راه غیر استاندارد هم داریم حلقه هایی که با طول مشخص میچرخه هیچ کاری نمیکنه جز درگیر کردن پردازنده و دادن تاخیر

موفق باشید

MostafaMohammadi
سه شنبه 02 خرداد 1391, 17:45 عصر
دوست عزیز MostafaMohammadi :

هم دانشگاهی این کد رو وارد کردن

شما از این عدد چطور به مقدار زیر رسیدین ؟


03 E8 00 00
0000 0011 1110 1000 | 0000 0000 0000 0000
65536000

کمی بیشتر روش فکر کنید،همینطور روی بازه با خوندن حرف زیر برای سوال سوم متوجه میشین
سوال سوم:در مورد سرریز برای مثال اگر شما cx:dx را با ffff:ffffh مقدار دهی کنید تابع سر ریز میکنه اگر حرف شما درست بود این عدد 32 بیتی ما هست و همون بازه میکرو ثانیه 32 بیتی ،
حال
1-مقدار مقدار 65 ثانیه تاخیر برابر هست 65sec=65*1000000= 03DF:D240h این در حالی هست که این مقدار هم 1000:0000 جوابی مشابه دارد دلیل این امر چیست؟
2- بازه صحیح چه عددی هست؟
3- چرا وقتی بزرگتر ازیه عدد خاص میشه سر ریز میکنه؟
موفق باشی
xman_1365_x (http://barnamenevis.org/member.php?33193-xman_1365_x) عزیز شما که خودت استادی! این اشتباه ازتون بعیده.
وقتی عدد 1000 در دستگاه Decimal رو به ثبات CX اختصاص بدیم، سپس عدد 0000 در دستگاه Decimal رو به ثبات DX، مقدار عددی CX:DX میشه 1000:0000؟
یا میشه (16^2)*1000؟
دستگاه Decimal نیست که چهار تا صفر گذاشته باشیم جلو 1000 و شده باشه 10000000!
قوانین، قوانین‌ه دستگاه‌ه Binary است. عامل اصلی اشباه اینه که شما تو ذهن تون عدد رو اینطوری فرض می کنید 1000:0000، تصور کردن به این شکل برای اعداد توی دستگاه Decimal غلطه، این شکل نمایش فقط به درد دستگاه Binary و Hexadecimal می خوره.
چه چهار تا صفر به ثبات DX اختصاص بدیم چه یه صفر، در هر صورت کل خونه های DX رو برابر با صفر قرار دادیم. این کار باعث میشه مقدار عددی که در ثبات CX گذاشتیم، 16 بار به سمت چپ شیفت پیدا کند یا به عبارتی ضرب در 16^2 شود.
به نظر میرسه سوالات تون رو تحت تاثیر این اشتباه می پرسید و اگه متوجه اشتباه تون بشید، خود به خود این سوالات از ذهن تون محو میشن. مگرنه همونطور که اشاره کردم این دو مقدار عددی 536000 تا با هم اختلاف دارن! حالا چون این 536000 تا در عمل نیم ثانیه تفاوت ایجاد می کنه و برای ما محسوس نیست، دلیل بر این نمیشه که این دو عدد یکسان اند و نتیجه مشابهی می دهند.

MostafaMohammadi
سه شنبه 02 خرداد 1391, 18:03 عصر
خیلی عجیبه !:متعجب:
وقتی برنامه ای رو که نوشتید emulate میکنم دقیقا 5 ثانیه متوقف میشه !
ولی وقتی فایل رو compile میکنم سریع از روش رد میشه !
به نظر شما مشکل از کجاست ؟
توضیح اش اینه که وقتی از گزینه emulate استفاده می کنی emu8086 همه مراحل اجرای کد رو شبیه سازی می کنه، ولی وقتی compile می زنی، emu8086 فایل اجرایی رو میسازه و سپس برنامه رو از روی فایل اجرایی ساخته شده اجرا می کنه.

برای ساختن فایل exe من روی compile میزنم و بعد هم فایل exe رو اجرا میکنم درسته ؟
شما بهتره از همون روش شبیه سازی برای برنامه نویسی استفاده کنی و دردسر برای خودت درست نکنی، استادهای دانشگاه براشون اهمیتی نداره. ولی اگه خیلی اصرار داری یه سیستم عامل قدیمی نصب کن تا بتونی فایل های اجرایی برنامه هات رو اجرا کنی، یه راه دیگه هم اینه که برای اجرای فایل اجرایی برنامه هات از برنامه DOSBox استفاده کنی. این برنامه سیستم عامل داس رو با تمام وقفه های داس و 8086 شبیه سازی می کنه. ولی به نظر من هیچکدوم از اینا لازم نیست، چون برنامه شما درسته.

ssbostan
چهارشنبه 03 خرداد 1391, 00:30 صبح
*ضمنا با توجه به پاسخ های ارسالی بد نیست یک سوال برای دوستان مطرح کنم اگر پاسخی ندیدم جواب رو بعد از مدتی اعلام میکنم(جواب ساده هست!)

1-با توجه به مقدار میکرو ثانیه مقدار 65 ثانیه عدد 65sec=65*1000000= 03DF:D240h میباشد پس چرا در مثال قبل یعنی عدد 1000:0000 هم نتیجه ای یکسان در بر داشته ؟



;65sec=65*1000000= 03DF:D240h
mov cx,03DFh
mov dx,0D240h
mov ah,86h
int 15h

;65sec
mov cx,1000h
mov dx,0
mov ah,86h
int 15h


ویرایش:
بد نیست دو سوال دیگه هم اضافه کنم
2- بازه این تابع را هم مشخص کنید؟
3-چرا با زیاد کردن مقدار cx:dx تابع سرریز میکنید و چه مقدار مقدار صحیح میباشد و دلیل این امر چیست؟

برم بخوابم تا سوالات بیشتری ننوشتم:لبخند:
موفق باشید


سلام؛

طبق بررسي هايي كه كردم متوجه شدم اين مدت زمان محدود شده و داراي زمان انقضاء هست و اين زمان انقضاء معادل 65536000 مايكرو ثانيه هست.
پس ميشه برداشت كرد كه هرچيزي بالاتر از اين ميزان داده بشه با توجه به اين محدوديت expiration time حداكثر تا اين ميزان محاسبه ميشه.

بازه اين تابع از 1000 مايكرو ثانيه تا 2147483647 مايكرو ثانيه هست، اما با توجه به محدوديتي كه گفتم هرچيزي بالاتر از 65536000 مايكرو ثانيه درخواست بشه در نهايت به اين ميزان كه رسيد، منقضي خواهد شد.

توجه كنيد كه حداقل و حداكثر ميران محسوس در اجراي اين تابع با در نظر گرفتن محدوديت فوق از 0000:03e8 تا 03e8:0000 ميتونه باشه.

حداكثر مقداري كه تابع سرريز نميكنه 7fff:ffff هست.

در ضمن 100% راهي هست كه بشه محدوديت 65536000 مايكرو ثانيه رو برداشت.

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

موفق باشيد.

MostafaMohammadi
چهارشنبه 03 خرداد 1391, 02:13 صبح
دوستان این حرف‌هایی که می زنید درست نیست ها!
Overflow ای که شما ازش حرف می زنید صرفا یک ایرادیه که هنگام شبیه سازی این وقفه در برنامه Emu8086 رخ می ده و هیچ ربطی به خود وقفه نداره. شما به راحتی می تونید حداکثر مقدار عددی، یعنی FFFF:FFFFh رو استفاده کنید.
این کد رو ببینید:



TITLE 'TEST.ASM' It test an interrupt
SSEG SEGMENT STACK
DB 32 DUP(0)
SSEG ENDS
;---------------------------------------
DSEG SEGMENT
MSG DB "Hello world!$"
DSEG ENDS
;---------------------------------------
CSEG SEGMENT
ASSUME CS:CSEG, DS:DSEG, SS:SSEG
START PROC FAR
MOV AX,DSEG
MOV DS,AX
;---------------------------------------
MOV CX, 0FFFFh
MOV DX, 0FFFFh
MOV AH, 86h
INT 15h
;----------------------------------------
LEA DX, MSG
MOV AH, 9h
INT 21h
;----------------------------------------
MOV AH,01H
INT 21H
;----------------------------------------
MOV AX,4c00h
INT 21H
START ENDP
CSEG ENDS
END START
END


من عین این کد رو بدون هیچ ایرادی کامپایل و لینک کردم و سپس با استفاده از محیط DOXBox اون رو اجرا کردم.
تا الان هم که 20 دقیقه صبر کردم و ایرادی پیش نیومده، که این یعنی حرف شما مبنی بر محدودیت 65 ثانیه ایی این وقفه درست نیست.
مطمئن ام سر 1 ساعت و 12 دقیقه Hello world! چاپ میشه. شما هم اگه حرف من رو قبول ندارید خودتون امتحان کنید.:چشمک:

MostafaMohammadi
چهارشنبه 03 خرداد 1391, 03:16 صبح
همون طور که انتظار می رفت، عمل کرد. برنامه دقیقا بعد از 1 ساعت و 12 دقیقه Hello world! رو برام چاپ کرد.