saalek110
Well-Known Member
از همين تاپيك : پست بعدي.
= = == = == = = ==
نستا:
در اين قسمت نحوه دسترسي به مقادير متغير ها را ياد ميگيريم .
وقتي كه ميخواهيم مقدار يك متغير را به يك متغير يا ثبات ديگر منتقل كنيم بايد
به اندازه آن توجه داشته باشيم . مثلا اگر متغيري بصورت:
LOCATE DB 10
تعريف كرده باشيم ، به دليل تك بايتي بودن ، نميتوانيم آن را به يك ثبات كامل مثل AX يا متغير دوبايتي كه با DW تعريف شده است ارسال كنيم .
اما انتقال آن به يك نيم ثبات مثل ALيا AH و ... مجاز است مانند:
MOV BH,LOCATE
از متغيرها بيشتر براي نگهداري موقت داده ها استفاده ميشود .
مثلا وقتي كه برنامه اي براي كار با قطاعهاي ديسك مينويسيم ، بايد يك محل موقتي براي ذخيره محتواي قطاع هاي خوانده شده ايجاد كنيم .
در اين موقع يك متغير به شكل (ترجيحا)آرايه تعريف ميكنيم .
وقتي به اين شكل با متغيرها برخورد ميشود، به دانستن آدرس آن نياز پيدا ميكنيم.
فرض كنيد ميخواهيم جمله:
A QUICK START TO ASSEMBLY PROGRAMMING
را چاپ كنيم .
در قدم اول بايد متغيري تعريف كرده و اين جمله را داخل آن قرار دهيم .
پس:
MSG DB 'A QUICK START TO ASSEMBLY PROGRAMMING',13,10,'$'
اعداد 13وَ10 انتهاي رشته براي انتقال مكان نما به سطر بعد هستند و كاراكتر '$'
از اين جهت وجود دارد كه تابع چاپ رشته انتهاي رشته كاراكتري را با بودن $
تشخيص ميدهد.
براي چاپ رشته كاراكتري راه هائي وجود دارد كه يكي از آنها استفاده از تابع 9h مربوط به INT 21h ميباشد .
براي فراخواني آن بايد به اين صورت رجيستر ها را پر كنيم:
AH=09H
آدرس رشته كاراكتري DSX = INT 21H
عبارت DSX نشان ميدهد كه مقدار قطعه (Segment) رشته كاراكتري ، يعني آن قطعه اي كه متغير تعريف شده در آن قرار گرفته است ، را بايد در DS قرار بدهيم .
به همين صورت نيز مقدار آفست (Offset) آن را به DX انتقال ميدهيم .
براي بدست آوردن شماره قطعه يك متغير از عملگر SEG استفاده ميكنيم .
مثلا براي بدست آوردن شماره قطعه MSGاز:
MOV AX,Seg MSG
استفاده ميكنيم . اين دستور شماره سگمنت MSG را پيدا كرده و در AX قرار ميدهد .
براي بدست آوردن شماره آفست هم از OFFSET استفاده ميكنيم مثلا:
MOV DX,OFFSET MSG
پس براي چاپ رشته MSG بايد به اين صورت عمل كنيم :
MOV AH,09H
MOV DX,OFFSET MSG
INT 21H
اين قطعه كاري كه ما ميخواهيم را انجام ميدهد و اگر دقت كنيد متوجه ميشويد كه اصلا شماره قطعه (Segment) را محاسبه نكرده ايم . علت اينست كه متغير ما به دليل
COM
بودن برنامه در
Code Segment
كه با
CODE.
مشخص ميشود تعريف شده پس خود بخود DS حاوي مقدار سگمنت آن هست .
( باز هم ياد آوري ميكنيم كه CS حاوي شماره ثبات كد و DS حاوي ثبات داده ها است و در برنامه هاي COM. مقدار برابر دارند)
يك دستور خلاصه براي بدست آوردن عدد آفست وجود دارد بنام
LEA .
كل كاري كه اين دستورالعمل انجام ميدهد اينست كه ديگر احتياج به نوشتن
OFFSET
نخواهد بود . به عنوان مثال
MOV DX,OFFSET MSG
با
LEA DX,MSG
برابر است .
با اين تفاسير كل برنامه به اين شكل خواهد بود .
تمرين :
براي اينكه تمرين بهتري داشته باشيم ، ميخواهيم خودمان و فقط با استفاده از وقفه
مربوط به چاپ كاراكتر همين جمله را چاپ كنيم . قبلا گفتيم كه تابع 0Eh از وقفه
10h يك كاراكتر را در محل مكان نما چاپ كرده و مكان نما را يك خانه به راست انتقال ميدهد. ميخواهيم رشته كاراكتري بالا را تا رسيدن به علامت $ چاپ كنيم . بهترين كار اينست كه عدد آفست را در BX قرار بدهيم . در اينموقع آفست اولين كاراكتر در BX است . مقدار داخل اين آفست را بصورت
MOV al,[bx]
به ثبات AL منتقل كرده و بعد چاپ ميكنيم . براي كاراكتر بعدي يك واحد به BX اضافه ميكنيم و دوباره همان كارهاي قبلي ... . اين عمليات را بايد تا رسيدن به كاراكتر '$' ادامه بدهيم .
اين برنامه را خودتان و بدون توجه به راه حل ارائه شده بنويسيد و فايل COM.
آن را بسازيد.
سالك: دو برنامه اين پست را هر دو را اجرا كردم . بي نقص بود.
با توضيحات داده شده فكر نمي كنم ديگه توضيح لازم باشد.
= = == = == = = ==
نستا:
در اين قسمت نحوه دسترسي به مقادير متغير ها را ياد ميگيريم .
وقتي كه ميخواهيم مقدار يك متغير را به يك متغير يا ثبات ديگر منتقل كنيم بايد
به اندازه آن توجه داشته باشيم . مثلا اگر متغيري بصورت:
LOCATE DB 10
تعريف كرده باشيم ، به دليل تك بايتي بودن ، نميتوانيم آن را به يك ثبات كامل مثل AX يا متغير دوبايتي كه با DW تعريف شده است ارسال كنيم .
اما انتقال آن به يك نيم ثبات مثل ALيا AH و ... مجاز است مانند:
MOV BH,LOCATE
از متغيرها بيشتر براي نگهداري موقت داده ها استفاده ميشود .
مثلا وقتي كه برنامه اي براي كار با قطاعهاي ديسك مينويسيم ، بايد يك محل موقتي براي ذخيره محتواي قطاع هاي خوانده شده ايجاد كنيم .
در اين موقع يك متغير به شكل (ترجيحا)آرايه تعريف ميكنيم .
وقتي به اين شكل با متغيرها برخورد ميشود، به دانستن آدرس آن نياز پيدا ميكنيم.
فرض كنيد ميخواهيم جمله:
A QUICK START TO ASSEMBLY PROGRAMMING
را چاپ كنيم .
در قدم اول بايد متغيري تعريف كرده و اين جمله را داخل آن قرار دهيم .
پس:
MSG DB 'A QUICK START TO ASSEMBLY PROGRAMMING',13,10,'$'
اعداد 13وَ10 انتهاي رشته براي انتقال مكان نما به سطر بعد هستند و كاراكتر '$'
از اين جهت وجود دارد كه تابع چاپ رشته انتهاي رشته كاراكتري را با بودن $
تشخيص ميدهد.
براي چاپ رشته كاراكتري راه هائي وجود دارد كه يكي از آنها استفاده از تابع 9h مربوط به INT 21h ميباشد .
براي فراخواني آن بايد به اين صورت رجيستر ها را پر كنيم:
AH=09H
آدرس رشته كاراكتري DSX = INT 21H
عبارت DSX نشان ميدهد كه مقدار قطعه (Segment) رشته كاراكتري ، يعني آن قطعه اي كه متغير تعريف شده در آن قرار گرفته است ، را بايد در DS قرار بدهيم .
به همين صورت نيز مقدار آفست (Offset) آن را به DX انتقال ميدهيم .
براي بدست آوردن شماره قطعه يك متغير از عملگر SEG استفاده ميكنيم .
مثلا براي بدست آوردن شماره قطعه MSGاز:
MOV AX,Seg MSG
استفاده ميكنيم . اين دستور شماره سگمنت MSG را پيدا كرده و در AX قرار ميدهد .
براي بدست آوردن شماره آفست هم از OFFSET استفاده ميكنيم مثلا:
MOV DX,OFFSET MSG
پس براي چاپ رشته MSG بايد به اين صورت عمل كنيم :
MOV AH,09H
MOV DX,OFFSET MSG
INT 21H
اين قطعه كاري كه ما ميخواهيم را انجام ميدهد و اگر دقت كنيد متوجه ميشويد كه اصلا شماره قطعه (Segment) را محاسبه نكرده ايم . علت اينست كه متغير ما به دليل
COM
بودن برنامه در
Code Segment
كه با
CODE.
مشخص ميشود تعريف شده پس خود بخود DS حاوي مقدار سگمنت آن هست .
( باز هم ياد آوري ميكنيم كه CS حاوي شماره ثبات كد و DS حاوي ثبات داده ها است و در برنامه هاي COM. مقدار برابر دارند)
يك دستور خلاصه براي بدست آوردن عدد آفست وجود دارد بنام
LEA .
كل كاري كه اين دستورالعمل انجام ميدهد اينست كه ديگر احتياج به نوشتن
OFFSET
نخواهد بود . به عنوان مثال
MOV DX,OFFSET MSG
با
LEA DX,MSG
برابر است .
با اين تفاسير كل برنامه به اين شكل خواهد بود .
کد:
.model tiny
.code
org 100h
START :
JMP MAIN ; skip to main codes
MSG DB 'A QUICK START TO ASSEMBLY PROGRAMMING',13,10,'$'
MAIN :
LEA DX,MSG ; get MSG offset
MOV AH,09 ; write string function
INT 21H ; call interrupt 21h
INT 20H ; terminate program
END START
تمرين :
براي اينكه تمرين بهتري داشته باشيم ، ميخواهيم خودمان و فقط با استفاده از وقفه
مربوط به چاپ كاراكتر همين جمله را چاپ كنيم . قبلا گفتيم كه تابع 0Eh از وقفه
10h يك كاراكتر را در محل مكان نما چاپ كرده و مكان نما را يك خانه به راست انتقال ميدهد. ميخواهيم رشته كاراكتري بالا را تا رسيدن به علامت $ چاپ كنيم . بهترين كار اينست كه عدد آفست را در BX قرار بدهيم . در اينموقع آفست اولين كاراكتر در BX است . مقدار داخل اين آفست را بصورت
MOV al,[bx]
به ثبات AL منتقل كرده و بعد چاپ ميكنيم . براي كاراكتر بعدي يك واحد به BX اضافه ميكنيم و دوباره همان كارهاي قبلي ... . اين عمليات را بايد تا رسيدن به كاراكتر '$' ادامه بدهيم .
اين برنامه را خودتان و بدون توجه به راه حل ارائه شده بنويسيد و فايل COM.
آن را بسازيد.
کد:
.model tiny
.code
org 100h
START :
JMP MAIN ; jump to MAIN
MSG DB 'A QUICK START TO ASSEMBLY PROGRAMMING',13,10,'$'
MAIN :
LEA BX,MSG ; get MSG offset
MOV AH,0EH ; write char function
halgheh :
MOV AL,[BX] ; move [BX] to AL: charactre code
CMP AL,'$' ; if al is equal with '$'
JE payan ; then jump to END
INT 10H ; otherwise call interrupt 10h
INC BX ; BX=BX+1
JMP halgheh ; jump to next caharcter
payan :
INT 20H ; terminae program
END START
با توضيحات داده شده فكر نمي كنم ديگه توضيح لازم باشد.