به نام خدا
براي ياد گرفتن اسمبلي بايد با مبناهاي عدد نويسي ، ساختمان داخلي كامپيوترو برنامه نويسي آشنا باشيم .
براي شروع ابتدا نگاهي به حافظه ميكنيم :

حافظه و آدرس دهي

هر كامپيوتر مبتني بر8086 داراي حداقل640 كيلوبايت حافظه است . اين 640 كيلوبايت به قطعات 64 كيلوبايتي تقسيم شده و ما اين قطعات را "قطعه " يا Segment ميناميم . هر سگمنت هم به خانه هاي تك بايتي ديگري تقسيم شده است.
براي بدست آوردن مقدار يك بايت مشخص از حافظه ما بايد عدد مربوط به سگمنت وهمچنين شماره آن بايت در سگمنت ( كه آفست ناميده ميشود) را بدانيم . Offset يعني يك آدرس در مبناي 16 كه 16 بيتي است و( يا در حالت win32 يك عدد 32 بيتي مي باشد. ) و مثلا اگر مقدار مورد نظر در قطعه 0030h باشد و افست آن 13C4h باشد ما بايد قطعه اي كه شماره آن 0030h است را بيابيم و بعد در همان قطعه افست 134C را بدست آوريم .
براي نمايش اين حالت بين عدد سگمنت و آفست علامت ( : ) قرار ميدهيم . يعني
0030:134C در حالت داس و 0030:0000134C در حالت ويندوز. Segment:Offset
** هميشه در آدرس دهي ها از اعداد مبناي 16 استفاده ميكنم .

Registers ثباتها

رجيسترها مكان هائي ازCPU هستند كه براي نگهداري داده ها (DATA) و كنترل اجراي برنامه بكار ميروند . ما ميتوانيم آنها را مقدار دهي كرده و يا بخوانيم و يا باتغيير محتواي آنهاCPU را مجبور به انجام يك پروسه (رويه ياProcedure ) كنيم .

دسته اي از رجيسترها كه ما آنها را "ثباتهاي همه كاره يا همه منظوره " ميخوانيم و شامل ax,bx,cd,dx هستند در حالت داس ( حالت 2 بايتي ) ودر حالت ويندوز eax,ebx,ecx,edx ( بصورت 4 بايتي) ، براي انتقال مقادير بين رجيستر ها وCPU بكار ميروند.
در حالت ويندوز ثباتهاي معروف ديگر( كه هر كدام قانون خاصي دارد ) عبارتند از :
EIP
اين ثبات مقدار شماره خط در حال اجرا نمايش مي دهد.
ESP
قبل از توضيح اين ثبات بايد در باره پشته صحبت كنيم . پشته يا Stack (نميدونم درست نوشتمش يا نه ) محلي است كه برنامه مقادير ذخيره شده ثباتهاي ديگر را در آن قرار مي دهد . قانوني پشته در اين است كه هر چيز كه اول وارد آن گردد آخر سر خارج مي شود.The 1st input is the last one come out
خوب معلوم است كه اين ثبات شماره پشته را در خود نگه مي دارد.
براي روشن تر شدن قضيه و چگونه استفاده از پشته يه مثال ميزنم . فرض كنيم يك MsgBox بايد نمايش داده شود .
در اين حالت مكان يا آدرس جايي كه رشته مورد نمايش در حاقظه قرار دارد در ثباتي مثل Eax قرار داده مي شود يعني
1- Mov eax,00450F1C eax آدرس رشته مورد نظر در خودش قرار ميده
حالا اين ادرس ذخيره ميشه :
2-Push eax در پشته قرار دادن اين آدرس
متغير رو صفر ميكنه :
Xor eax,eax صفر كردن متغير يا ثبات براي فرا خواني تابع
صدا زدن تابع :
[jmp dword ptr [004121F0
برنامه به محلي كه رويه Messageboxa توسط برنامه مورد مثال فرا خواني مي شود ارسال مي گردد.
( دستوارت بعدا توضيح داده مي شود).
همانطور كه ديده ميشه براي انتقال متغير به تابع سه راه حل وجود داره
استفاده از ثباتها ويا تركيبي از اونها
استفاده از پشته
استفاده هم از پشته هم از ثباتها
توي مثال بالا هم از از پشته هم از eax استفاده شد

ثبات( EDI (Data Index
اين ثبات براي نگه داري اطلاعات مورد نظر برنامه استفاده مي شود. تقريبا مثل ثبات همه كاره
ثبات(ESI(Segment Index
همانند EDI

ثباتهاي همه منظوره به دو نيم ثبات تك بايتي تقسيم ميشوند . بايت بالائي با نمادH و بايت پائيني با نمادL نشان داده ميشود . مثلا ثبات AX داراي دو نيم- ثبات AH,AL است .
در داس:
اگر AX را بصورت ABCD نمايش دهيم CD درAl و AB درAh قرار مي گيرد حال اگر مقدار 1234h (h نمايينده قرار گرفتن در مد Hex مي باشد) درAX قرار داده شود ( هنگامي كه از حافظه برنامه مقدار دهي شود .) مقدار 12 درAl و مقدار 34 درAh قرار مي گيرد.(Eax=3412)
در حالت ويندوز
اين حالت بر قرار است اماEax=XXXXABCD
AB معرف Ah وCD معرف Al مي باشد.
در درس بعدي اعداد پايه 16 تايي و 8 تايي و 10 تاي و چند دستور آموزش داده مي شود.

به نام خدا

با سلام

فكر كنم امروز نوبت رسيدن به حساب عدد ها باشه؟ نه

كلاس رسمي است.

ما معمولا اعداد را بر پايه ده نشان مي دهيم . يعني اعداد پايه ده. زيرا بعد از شمردن از 0 تا عدد 9 ، اعداد دو رقمي شده و يا به عبارت ديگر يكي به دهگان عدد اضافه مي شود .بطور مثال عدد 128 را در نظر بگيريد. اين عدد يعني

128=8*10^0+2*10^1+1*10^2

همانطور متوجه شديد رتبه دهگان و صدگان و هزارگان در واقعه معرف توان ده در رابطه بالا مي باشد.بعلت استفاده 10 به عنوان پايه توان اين مبنا را ده دهي مي گويند.
اعداد در پايه هاي ديگر هم داراي رابطه اي شبيه رابطه بالا مي باشند مثلا رابطه عدد 128 در پايه x بصورت زير نوشته مي گردد:

128(x)=8*x^0+ 2*x^1 +1*x^2

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

پايه دو دوبي: ( Binary)

همانطور كه از اسم اين پايه معلوم است مبنا اعداد در اين پايه دو بوده و اعداد تشكيل دهنده اين مبنا عبارتند از 0،1(اعداد كوچكتر از پايه با انضمام 0 )يك عدد در اين مبنا بصورت مينيمم 1 بيت را مورد استفاده قرار مي دهد.2^0=1 ماكزيمم عدد تشكيل دهنده

پايه هشت هشتي يا اكتال

شبيه پايه دو بوده ولي اعداد بكار رفته در آن عبارت است از: 0،1،2،3،4،5،6،7. هر عدد در اين مبنا حداقل 3 بيت مورد مصرف قرار
مي دهد
2^0+2^1+2^2=7
( هر كدام از جواب به توان رساندن يك بيت را اشغال مي نماييد )

پايه هگزا دسيمال (Hex)

اعداد بكار رفته در آن عبارت است از:F،E،D،C،B،A،9،8، 0،1،2،3،4،5،6،7. كه در آن A معرف 10و B معرف 11 و ... E معرف 15
مي باشد هر عدد در اين مبنا حداقل 4 بيت مورد مصرف قرار مي دهد
2^0+2^1+2^2+2^3=15

چگونگي تبديل پايه هاي ديگر به ده دهي:

براي تبديل هر عدد در مبناي x به مبناي ده دهي از روش زير استفاده مي كنيم: ( فرض كنيد عدد ما در مبنا x برابر QWER مي باشد )

QWER(x)=R*x^0+E*x^1+W*x^2+Q*x^3+….

حاصل جمع ما همان عدد در پايه ده دهي (مثلا TYUIO) يعني

TYUIO(10)=QWER(x)

حال مي رسيم به تبديل اعداد پايه 10 به پايه هاي ديگر

براي اين كار از روش تقسيمهاي متوالي استفاده مي نماييم عدد را بر پايه مورد نظر ( x ) تقسيم نموده .باقي مانده را در بجاي اولين عدد معادل قرار مي دهيم حال خارج قسمت را بر x تقسيم نموده و باقي مانده را در كنار باقي مانده قبلي در سمت چپ آن قرار مي دهيم آنقدر اين كار را انجام داده تا خارج قسمت از x كمتر گردد .حال آخرين خارج قسمت را نيز دز سمت چپ باقي مانده ها قرار مي دهيم ( آخرين باقيمانده را نيز قبل از اضافه كردن خارج قسمت به اعداد اضافه مي نماييم) عدد حاصله معادل عدد ده دهي در پايه x مي باشد.
الگوريتم آن عبارت است از:

1- عدد را بگير
2- اگر عدد كوچكتر از x است به مرحله6 بپر
3- عدد را بر x تقسيم كن باقيمانده را در سمت چپ عدد معادل كنار اعداد ديگر بنويس اگر عددي نبود آن را ياد داشت كن
4- خارج قسمت را جاي عدد بگذار
5- به مرحله 2 برو
6- عدد را به سمت چپ اعداد اضافه كن
7- نمايش رشته

قسمت دوم

دستورات اسمبلي


در اين قسمت به شناسايي دستورات اسمبلي مي رسيم .


Mov Dest,source
با اجراي اين دستور منبع درون مقصد كپي مي شود. منبع و يا مقصد مي تواند يكي از حالات زير باشه:
-ثبات يا رجي ستر
-آدرس حافظه
- رجي ستري كه به حافظه اي اشاره مكنه
-رجي ستري كه به حافظه اي كه نسبي اشاره مي كنه
( بعدا در نحوه آدرس دهي اين مفاهيم توضيح داده مي شود)
مثال


Mov eax,ebx
كه مقدار ebx تو eax مي ريزد.


Push value

وظيفه آن قرار دادن value در Stack memory مي باشد.
مثال


Push eax / Push [004044ca]
كه مقدار eax را تو پشته قرار مي دهد./ مقداراي را كه در حافظه [004044ca] مي باشد را در پشته قرار مي دهد.



Pop value
معكوس Push بوده و مقداري را كه با Push در حافظه قرار گرفته را بر مي گرداند.
مثال


eax= 10h push eax
eax=1000h mov eax,1000h
ebx=12h mov ebx,12h
ebx=ebx+eax=1012h add ebx,eax
eax=10h Pop eax



×هميشه متغيري كه در حافظه قرار ميگيرد لزوما با همان متغير برداشته نمي شود



Push eax
….
Pop ebx

PopA /PushA

دقيقا مثل پدرهاشون مي مانند. با اين تفاوت كه تمامي رجي ستر ها را در حافظه قرار داده يا همگي را مي خوانند.


Lea reg,Source

مقدار آدرس موثر(واقعي با سگ منت و افست ) منبع را در رجي ستر قرار مي دهد.


Jmp value

اگر value آدرس موثر باشد ( كه معمولا نيست ) به آن آدرس برنامه فرستاده مي شود .و اگر موثر نباشه به اندازه مقدار value به آدرس كنوني اضافه كرده و به اونجا مي رود
اگر ياد تون باشد EIP شماره خط در حال حاضر رو تو خودش دارد پس دو دستور زير با هم معادل اند:



Jmp 02 ,jump to address that is equal to current address+02
Add EIP +02 , EIP equal to EIP (Current Address)+2

Cmp Op1,Op2

مقدار اولي و دومي را مقايسه مي كند . (اولي منهاي دومي ) بر اساس نتيجه مقدار رجي ستر وضعيت ( قبلا معرفيشون نكردم فقط وضعيت مقايسه را تو خودش قرار مي دن )( شامل بيتهاي zf,sf,pf,of,cf,af است ) ست مي كند. مهمتر ينشون zf (حاصل تفريق 0 است zf=1 يعني با هم برابر اند)


Jz,Jnz,…
تمامي دستوراتي كه يا z شروع مي شن يعني اگر ... و پرش .مثلا JZ ( Jump if Zero)يعني اگر بيت zf از رجي ستر وضعيت 1 باشد به خط مورد نظر پرش نما



بيت معادل شرط
zf=1 = Jz=Je
zf=0 != Jnz
zf=0 and cf=0 بزرگتر Ja
cf=0 بزرگترو مساوي Jae
cf=1 كوچكتر Jb
cf=1 or zf=0 كوچكتر و مساوي Jbe
ecx=0 اگر cx برابر 0 شد Jcxz



(دستوراتي هم مثل JGو يا JL و هستن كه براي اعداد علامت دار مصرف ميشوند كه ثبات وضعيتشون يادم نيست به هر صورت خود تون ياد بگيريد.)


ADD و ADC( Adding & Adding With Carry)
هر دو مقدار اول را بعلاوه مقدار دوم كرده و نتيجه را در اوليه مي گذارند . قبل از اينكه فرقشون رو بگم بهتر كه Overflow رو بگم . در حالت اعداد طبيعي هر بايت نمايانگر يك عدد بين 0 تا 255 مي باشد ولي در حالت اعداد صحيح هر بايت نمايانگر يك عدد بين 128- تا 127 است.
بيت معمولي بيت معمولي بيت معمولي بيت معمولي بيت معمولي بيت معمولي بيت معمولي بيت علامت
اگر بيت علامت يك باشد يعني عدد منفي است و 0 بودن آن يعني عدد مثبت است .
حال فرض كنيم 96 را با 32 جمع كنيم نتيجه 128 مي شود ولي در حالت بالا عدد معادل 0 منفي است كه باعث سر ريز شده است .
در حالت جمع ADC اين حالت پيش نيامده و همچنين اگر دو بايت را يا هم جمع كرديم و بر16 ) مثل بر 10 ) در جمع آنها را نيز دخالت مي دهد. مثلا اگر يك كلمه را با كلمه ديگر جمع كنيم جواب درست نمايش داده مي شود.


SUB و SBB
عمل تفريق را انجام مي دهد .SBB داراي خصوصيات ADC است ولي عمل تفريق را انجام مي دهد.


Neg
علامت عدد را معكوس مي نمايد. از روش متمم دو


INC x
به عدد x يك عدد اضافه مي نمايد.( x مي تواند حافظه و يا آدرس و يا رجي ستر باشد)


DEC x

از x يك عدد كم مي كند.


MUL x

برابر eax=eax*x


IMUL x
مثل mul است ولي براي اعداد علامت دار


DIV x وIDIV x
تقسيم مثل MUL وMULI

جداول عملياتي


ANDوORوXORوNOTوTest
NOT A
A=NOT A XOR A,B
A=A XOR B AND A,B
A=A AND B OR A,B
A=A OR B B A
1 0 0 0 0 0
1 1 0 1 1 0
0 1 0 1 0 1
0 0 1 1 1 1

عمل TEST A,B مثل عمل AND بوده ولي باعث تغيير A نمي شود .ولي در صورت برابري AوB مقدار zf را يك مي كند.