-
-

مدیر تالار مهندسی کامپیوتر
عملگر 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
-
کاربر زیر به خاطر این پست مفید از WIN32 تشکر کرده است:
-
-

مدیر تالار مهندسی کامپیوتر
ضرب و تقسيم با 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
تمرين :
همين عمل را براي تقسيم نيز با ديباگ انجام بدهيد
-
کاربر زیر به خاطر این پست مفید از WIN32 تشکر کرده است:
-
-

مدیر تالار مهندسی کامپیوتر
رويه ها (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 را در برنامه اصلي بكار ببريم ، برنامه پايان مي يابد .
-
2 کاربر از WIN32 به خاطر این پست مفید تشکر کرده اند:
DataBus (11-27-2010), setare (12-13-2010)
مجوز های ارسال و ویرایش
- شما نمیتوانید موضوع جدیدی ارسال کنید
- شما امکان ارسال پاسخ را ندارید
- شما نمیتوانید فایل پیوست کنید.
- شما نمیتوانید پست های خود را ویرایش کنید
مشاهده قوانین
انجمن