کاربران تگ شده

+ پاسخ به موضوع
صفحه 2 از 2 نخستنخست 1 2
نمایش نتایج: از شماره 11 تا 13 , از مجموع 13

موضوع:
آموزش زبان اسمبلی

  1. #11


    محل سکونت
    اینجا
    رشته تحصیلی
    نرم افزار
    نوشته ها
    1,210
    پسندیده
    2,426
    تشکر شده
    1,693 بار در 816 پست
    Mention شده
    در 0 پست
    تگ شده
    در 0 تاپیک
    عملگر Not : عملوند Not ارزش همه بيتهاي يك بايت يا كلمه را برعكس ميكند .
    يعني تمام بيتهاي 1را 0ا و تمام بيتهاي 0را 1ا ميكند . بعنوان مثال اگر AH حاوي
    مقدار 10101101 باشد، بعد از اجراي Not Al ، محتواي AL بصورت 01010010 خواهد
    بود.

    جدول ارزشي Not Not X X N
    F | T
    T | F



    عملگر Neg . اين اپراتور معمولا با Not اشتباه ميشود در صورتي كه كمتر شباهتي بين
    آنها وجود دارد . Neg ارزش عددي يك عدد علامتدار را برعكس ميكند . يعني يك عدد
    منفي را مثبت ميكند و برعكس . در اعداد علامتدار ( همانطور كه بعدا هم خواهيم
    ديد )، اولين بيت سمت چپ ( بيت هشتم ) بيت علامت است . 1 بودن آن نشاندهنده
    منفي بودن و 0 بودن آن نشان دهنده مثبت بودن است .
    عملگر Neg با عكس كردن بيت علامت ، ارزش عدد را عكس ميكند .
    اين عملوند را در مبحث اعداد علامتدار مفصلا ميخوانيم .
    مثال : ميخواهيم برنامه اي بنويسيم كه تمام حروف كوچك يك عبارت را به حروف
    بزرگ تبديل كند . از نظر مقدار عددي ، تفاوت حروف كوچك و بزرگ در اينست كه
    بيت پنجم در حروف بزرگ برابر 0 و در حروف كوچك 1 است . مثلا كداسكي حرف a
    به باينري برابر 01100001 و كد A برابر 01000001 است . پس برنامه اي مينويسيم
    كه تمام كاراكترهاي رشته كاراكتري مورد نظر را خوانده و بيت پنچم آنها را 0 كند
    . در قسمت قبلي ديديم كه براي 0 كردن يك بيت ، يك عدد باينري كه تمام بيتهاي
    آن 1 ، و بيت مورد نظر (براي 0 كردن ) 0 باشد را با عدد مورد نظر AND ميكنيم .


    . MODEL SMALL
    . CODE
    ORG 100H
    START :
    JMP MAIN
    MSG DB ' this is an example/ ..$'
    MAIN :


    بدست آوردن آدرس رشته ; LEA BX/MSG LOOP :_

    قرار دادن كاركتر در AL ; MOV AL/[BX]
    آيا كاراكتر $ است ? ; CMP AL/'$'
    بله ، به MAIN برو ; _JZ END
    بيت پنجم را صفر كن ; AND [BX]/11011111B
    يكواحد به BX اضافه كن - كاراكتر بعدي ; INC BX JMP LOOP _;
    END :_

    قرار دادن آفست رشته در DX ; MOV DX/BX
    تابع 9 براي نمايش رشته ; MOV AH/9
    قفه 21h ; INT 21H
    پايان برنامه ; INT 20H END START


    معمولا برنامه هائي كه پيغامهاي خود را كد ميكنند ( مثل ويروسها ) از اين روش يا
    روشي مشابه براي Decode كردن پيغامها استفاده ميكنند .

    مثال :
    بايت وضعيت صفحه كليد كه مربوط به وضعيت كليد هاي كنترلي CapsLock/NumLock
    در بايوس هاي AT/PS2 در آدرس 0017h:0040h قرار دارد.
    بيتهاي اين بايت نشان ميدهد كه كدام كليد فعال است . 1 بودن به معني روشن بودن
    و 0 به معني خاموش بودن آن است . در مثال زير بيت ششم براي كليد CapsLockرا 1ا
    ميكنيم تا Capslock روشن شود .


    .MODEL SMALL
    .CODE
    ORG 100h
    START:
    PUSH ES
    MOV AX/0040h
    MOV ES/AX
    MOV AL/ES:[17h]
    OR AL/32
    MOV BYTE PTR ES:[17h]/AL
    POP ES
    MOV AH/1
    INT

  2. کاربر زیر به خاطر این پست مفید از WIN32 تشکر کرده است:

    DataBus (11-27-2010)

  3. #12


    محل سکونت
    اینجا
    رشته تحصیلی
    نرم افزار
    نوشته ها
    1,210
    پسندیده
    2,426
    تشکر شده
    1,693 بار در 816 پست
    Mention شده
    در 0 پست
    تگ شده
    در 0 تاپیک
    ضرب و تقسيم با 8088
    8088
    براي ضرب دو عدد از دستورالعمل MUL با كد ماشين F7h استفاده ميكند .
    اين دستورالعمل روي كلمه ها ( دوبايتي ها) كار ميكند . بنا براين حاصلضرب دو عدد16
    بيتي ميتواند 32 بيتي يا 2 كلمه اي باشد . به همين دليل براي ذخيره نتيجه ضرب
    يك ثبات تنها كافي نيست . MUL
    هميشه محتواي يك ثبات را در محتواي ثبات AX ضرب كرده و حاصلضرب را در
    جفت ثبات DX:AX ذخيره ميكند . به اينصورت كه دوبايت بالا را در DX و كلمه
    پائين را در AX قرار ميدهد. وقتي از حساب 8088 صحبت ميكنيم ، نوشتن DX:AX به
    معني نگهداري عدد 32 بيتي در آن جفت ثبات است نه محلي از حافظه كه با DX:AX
    مشخص ميشود.
    براي ضرب محتواي يك رجيستر در AX ( هميشه در AX ضرب ميشود) از MUL بصورت زير
    استفاده ميكنيم : MUL Register


    كه منظور از رجيستر يك ثبات مانند DXيا BXا است .
    چون هميشه محتواي رجيستر مورد نظر در AX ضرب ميشود، نيازي به نوشتن AX نداريم .

    بعنوان مثال اگر AX برابر 100hو BXو برابر 7C4Bh باشد ، حاصل MUL BX برابر 7C4B00h
    ميشود و چون اين مقدار يك عدد 32 بيتي است ، در جفت ثبات DX:AX
    نگهداري ميشود به شكلي كه DX=7C4Bhو AXو برابر 0000h باشد.

    عمل تقسيم هم به شيوه مشابهي انجام ميشود.
    وقتي كه دوعدد را به هم تقسيم ميكنيم حاصل تقسيم ( قسمت صحيح يا خارج قسمت ) در AX
    و باقيمانده در DX قرار ميگيرد.

    براي تقسيم كردن دو ثبات به هم ، از دستور DIV استفاده ميكنيم . وقتي از DIV براي
    تقسيم استفاده ميكنيم ، CPU محتواي جفت ثبات DX:AX را بر محتواي ثبات ذكر
    شده تقسيم ميكند بنا براين در هنگام استفاده از DIV فقط نام همان ثبات را ذكر
    ميكنيم . مثلا اگر بخواهيم ( برعكس ضربي كه در بالا انجام داديم ) عدد 7CB400h را
    بر 100h تقسيم كنيم ، BX را برابر 100h و جفت ثبات Dx:Ax را برابر 7CB4100h
    قرار ميدهيم . براي اينكار عدد 7CB4100h را به دو نيمه 007Ch و 4100h تقسيم كرده
    و در DXو AXو قرار ميدهيم . (/ DX:007Ch AX=4100h) . در نهايت با DIV BX عمل
    تقسيم را انجام ميدهيم .
    بعد از انجام تقسيم 7C4Bhدر AXر و 0000hدر DXر قرار ميگيرد.

    مثال براي ضرب

    براي ديدن مطالب گفته شده ، همان دو عدد 100hو 4CBhو را با ديباگ در هم ضرب
    ميكنيم .
    بنا براين Debug را اجرا كرده و سطرهاي زير را وارد ميكنيم .


    17AA:0100 mov ax/100
    17AA:0103 mov bx/4cb
    17AA:0106 mul bx
    17AA:0108 int 20
    17AA:010A
    - t


    پس از وارد كردن برنامه بالا ، از دستور T ( مخفف Trace) كه براي رديابي اجراي
    برنامه بكار ميرود استفاده ميكنيم . با هربار اجراي اين دستور يك خط از برنامه
    اجرا شده و محتواي ثباتها بعلاوه وضعيت فلاگها نمايش داده ميشوند.

    در اين سطر محتواي AX برابر 0100 است


    AX=0100 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
    DS=17AA ES=17AA SS=17AA CS=17AA IP=0103 NV UP EI PL NZ NA PO NC
    17AA:0103 BBCB04 MOV BX/04CB
    - t


    محتواي BX برابر 0$CB شده ...

    AX=0100 BX=04CB CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
    DS=17AA ES=17AA SS=17AA CS=17AA IP=0106 NV UP EI PL NZ NA PO NC
    17AA:0106 F7E3 MUL BX
    - t


    بعد از انجام ضرب ، محتواي DX برابر 4 و محتواي AX برابر CB00 شد ه . بنابراين
    جفت ثبات DX:AX مقدار 4CB00 را نشان ميدهد . يعني همان عددي كه قبلا هم بدست
    آورده بوديم .


    AX=CB00 BX=04CB CX=0000 DX=0004 SP=FFEE BP=0000 SI=0000 DI=0000
    DS=17AA ES=17AA SS=17AA CS=17AA IP=0108 OV UP EI PL NZ NA PO CY
    17AA:0108 CD20 INT 20
    - t
    - q



    تمرين :

    همين عمل را براي تقسيم نيز با ديباگ انجام بدهيد

  4. کاربر زیر به خاطر این پست مفید از WIN32 تشکر کرده است:

    DataBus (11-27-2010)

  5. #13


    محل سکونت
    اینجا
    رشته تحصیلی
    نرم افزار
    نوشته ها
    1,210
    پسندیده
    2,426
    تشکر شده
    1,693 بار در 816 پست
    Mention شده
    در 0 پست
    تگ شده
    در 0 تاپیک
    رويه ها (Procedures) .

    در برنامه نويسي با زبانهاي سطح بالا ، با زيربرنامه ها يا پروسيجر ها آشنا شديم .
    مثلا در زبان بيسيك به آنها Subroutine ميگوئيم يا در زبان پاسكال Procedure و..

    رويه ها نوشت برنامه هاي واحدي را ممكن و آسان ميسازند و از تكرار كدهاي
    برنامه جلوگيري ميكنند .

    در زبان اسمبلي براي ساختن يك زيربرنامه از اعلان Proc در مقابل نام آن استفاده
    ميكنيم . مثلا براي تعريف رويه Print آن را با Print Proc تعريف ميكنيم .
    در واقع Proc يك برچسب ( از نوع Near) است كه اسمبلر توجه بيشتري نسبت به
    يك برچسب عادي به آن ميكند.

    وقتي يك اعلان زيرروال را تعريف كرديم ، كد اجرائي آن را مينويسيم . مثلا اگر
    بخواهيم زير روال ما كاراكتر مشخص شده با AL را چاپ كند ميتوانيم با استفاده از
    تابع 0Eh از وقفه 10h چنين چيزي بنويسيم :


    Print Proc
    Mov Ah/0Eh
    Int 10h
    :
    :




    وقتي به انتهاي كد مورد نظر رسيديم ، با يك دستور Ret به محلي از برنامه اصلي كه
    زيرروال فراخواني شده بود برميگرديم .

    Print Proc
    Mov Ah/0Eh
    Int 10h
    Ret
    :



    و در پايان هم دوباره نام پروسيجر را به همراه يك كلمه End به معني پايان كار
    زيرروال مي آوريم . در مورد مثال ما

    : Print End Print Proc
    Mov Ah/0Eh
    Int 10h
    Ret
    Print End



    نكته مهمي كه بايد به آن توجه كنيم اينست كه اعلان Proc مانند يك برچسب است و
    در صورتي كه از روي آن با دستور JMP جهش نكنيم ، داخل پروسيجر هم اجرا خواهد شد
    بنا براين هميشه بعد از Org 100h يا پروسيجر ها را نوشته و با يك فرمان JMP از
    روي آنها به كداصلي پرش ميكنيم .


    . MODEL SMALL
    . CODE
    ORG 100H
    START :


    JMP MAIN
    پرش به | اعلان پروسيجر Print Proc
    قسمت اصلي | Mov Ah/0Eh
    برنامه | Int 10h Ret |

    | پايان رويه Print End
    :MAIN :
    :
    END START


    پس از آن ميتوانيم با يك فرمان Call رويه مورد نظر را فراخواني كنيم .
    مثلا Call print . قبل از فراخواني رويه مورد نظر بايد پارامترها و شراي اجراي آن
    را فراهم كرده باشيم . مثلا در مورد رويه Print بايد هميشه ثبات AL كه حاوي كد
    اسكي كاراكتر براي چاپ است ، مقدار دهي صحيح شده باشد .
    مثال :

    MAIN :
    Mov Al/65 ;'A'
    Call Print
    :
    END START



    مثال : اين همان برنامه چاپ كاراكترهاي اسكي با كد 128 تا 255 است كه قبلا بدون
    استفاده از رويه ها نوشتيم :

    . MODEL SMALL
    . CODE
    ORG 100H ; IP points to 100h / starting offset
    START
    JMP MAIN ; Jump over the procedure
    Print Proc ; procedure declaration
    Mov Ah/0Eh
    Int 10h
    Ret ; procedure ends
    Print End
    MAIN :; main program
    MOV BH/128
    LOOP :_
    MOV AL/BH ; AL = Ascii character code
    CALL PRINT ; Call procedure
    INC BH
    CMP BH/255
    JNP LOOP _; Jmp LOOP _if BH is below 255
    INT 20H ; otherwise terminate normally
    END START ; program ends according the START label

    **

    معمولا كد اصلي برنامه را هم بصورت يك Procedure مينويسند . مثلا در مثال بالا
    بعد از برچسب Main ميتوان يك Prog proc و در انتهاي برنامه هم يك Prog End
    قرار داد . اين امر تفاوتي در اجراي برنامه نخواهد داشت ولي معمولا و براي داشتن
    انعطاف بيشتر در نوشتن برنامه اين كار را انجام ميدهند.
    **
    اگر دستور Ret را در برنامه اصلي بكار ببريم ، برنامه پايان مي يابد .

  6. 2 کاربر از WIN32 به خاطر این پست مفید تشکر کرده اند:

    DataBus (11-27-2010), setare (12-13-2010)

+ پاسخ به موضوع
صفحه 2 از 2 نخستنخست 1 2

مجوز های ارسال و ویرایش

  • شما نمیتوانید موضوع جدیدی ارسال کنید
  • شما امکان ارسال پاسخ را ندارید
  • شما نمیتوانید فایل پیوست کنید.
  • شما نمیتوانید پست های خود را ویرایش کنید