1. مهمان گرامی، جهت ارسال پست، دانلود و سایر امکانات ویژه کاربران عضو، ثبت نام کنید.
    بستن اطلاعیه

آموزش اسمبلی(12)

شروع موضوع توسط hector2141 ‏15/10/12 در انجمن Assembly

  1. کاربر ارشد

    تاریخ عضویت:
    ‏6/9/12
    ارسال ها:
    14,323
    تشکر شده:
    2,698
    امتیاز دستاورد:
    0
    حرفه:
    daneshjo
    [​IMG] در این قسمت نحوه دسترسی به مقادیر متغیر ها را یاد میگیریم .


    وقتی که میخواهیم مقدار یک متغیر را به یک متغیر یا ثبات دیگر منتقل کنیم باید به اندازه آن توجه داشته باشیم . مثلا اگر متغیری بصورت 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/’$’

    اعداد ۱۳وَ۱۰ انتهای رشته برای انتقال مکان نما به سطر بعد هستند و کاراکتر ‘$’ از این جهت وجود دارد که تابع چاپ رشته انتهای رشته کاراکتری را با بودن $ تشخیص میدهد.
    برای چاپ رشته کاراکتری راه هائی وجود دارد که یکی از آنها استفاده از تابع ۹h مربوط به INT 21h میباشد .
    برای فراخوانی آن باید به این صورت رجیستر ها را پر کنیم :
    AH=09H
    آدرس رشته کاراکتری DS:DX = INT 21H عبارت DS:DX نشان میدهد که مقدار قطعه
    (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 SMALL
    . 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

    تمرین :
    برای اینکه تمرین بهتری داشته باشیم ، میخواهیم خودمان و فقط با استفاده از وقفه مربوط به چاپ کاراکتر همین جمله را چاپ کنیم . قبلا گفتیم که تابع ۰Eh از وقفه ۱۰h یک کاراکتر را در محل مکان نما چاپ کرده و مکان نما را یک خانه به راست انتقال میدهد. میخواهیم رشته کاراکتری بالا را تا رسیدن به علامت $ چاپ کنیم .
    بهترین کار اینست که عدد آفست را در BX قرار بدهیم . در اینموقع آفست اولین کاراکتر در BX است . مقدار داخل این آفست را بصورت
    MOV al/[bx] به ثبات AL منتقل کرده و بعد چاپ میکنیم . برای کاراکتر بعدی یکواحد به BX اضافه میکنیم و دوباره همان کارهای قبلی … . این عملیات را باید تا رسیدن به کاراکتر ‘$’ ادامه بدهیم .
    ** این برنامه را خودتان و بدون توجه به راه حل ارائه شده بنویسید و فایل COM. آن را بسازید.

    MODEL SMALL.
    . CODE
    ORG 100H
    START :
    JMP MAIN ; jump toMAIN
    MSG DB ‘A QUICK START TO ASSEMBLY PROGRAMMING’/13/10/’$’
    MAIN :
    LEA BX/MSG ; get MSG offset
    MOV AH/0EH ; write char function
    LOOP :_
    MOV AL/[BX] ; move [BX] to AL: charactre code
    CMP AL/’$’ ; if al isequal with ‘$’
    JE END _; then jump to END _
    INT 10H ; otherwise callinterrupt 10h
    INC BX ; BX=BX+1
    JMP LOOP _; jump to next caharcter
    END :_
    INT 20H ; terminae program
    END START