پیوند و اجرای اسمبلی

saalek110

Well-Known Member
باز نشد.
ميشه فايل را دوباره بفرستيد. اگه ميشه زيپ نكنيد.
شش بار تلاش كردم. شايد هم اشكال از كامپيوتر منه. كه اكثرا همين طوره.
 
آخرین ویرایش:

Old User

Member
چرا باز نشد... پیغامی چیزی میده؟؟؟

تواین فایل حدود 85 تا برنامه به زبان اسمبلیه... برنامه های جالبه... گفتم شاید بدتون نیاد رو این برنامه ها برای این دوستمون که اسمبلی کار میکنه توضیح بدید...

باید زیپ بشه ... من که بازش کردم مشکلی نداره!!
 

saalek110

Well-Known Member
من با وين زيپ كار مي كنم. مي گه فايل مشكل داره. ولي گفتم كه كامپيوتر من خيلي مشكل داره. بگذار دوستان ديگر نظر بدهند.
-------------
پسوند فايل را هم به ((زيپ)) تبديل كردم. باز گفت فايل مشكل دارد.
 
آخرین ویرایش:

saalek110

Well-Known Member
ممنون. دانلود كردم. ولي باز همان مشكل را داشت.اگه ميشه با ئي ميل بفرستيد.
======

با ئي ميل دريافت كردم. ممنون دوست عزيز از زحمت.
مثالهاي خوبي دارد. بعضي خيلي بزرگ و حرفه اي. و بعضي كوچك و ساده.85 سورس.


========================

من قبلا يك آموزش اسمبلي در يك سايتي داشتم كه قسمتي از آن در وبلاگ زير نقل شده. البته وبلاگ من نيست.
http://7soft.blogsky.com/?PostID=53
 

Old User

Member
:wink: خواهش میکنم ... خوبه با بچه ها اینجا درموردشون بحث کنید همه استفاده کنن.

موفق باشید.
 

saalek110

Well-Known Member
سلام.
من الان 5 تاشون را كامپايل كردم. همه كامپايل شدند. ولي چون شرحي همراش نبود و من هم مبتدي هستم نمي توانم باهاشون كار كنم.
الان داشتم سرچ مي كردم براي سورس همراه شرح.
آرمان بياد ببينيم چي ميشه.
 

saalek110

Well-Known Member
حالا تا من سورس پيدا كنم يك مقدار مقدمه مي نويسم تا وقتي كه سورس پيدا كرديم نخواهيم اين چيزهاي اوليه را توضيح بدهيم.

ما دراسمبلي مستقيما به cpu دستور مي دهيم.
يعني دستورات ما دستوراتي صريح است به cpu كه بايد چه كار كند.
مثلا انتقال محتويات يك حافظه به ديگري يا تاثير دادن محتواي دو حافظه با هم (مثلا جمع).

حالا اين حافظه ها كجا هستند؟
يكي همان ram است كه همه مي شناسند.
ديگري رجيسترهاي cpu است.

رجيسترهاي cpu چيست؟
اين ها حافظه هايي داخل خود cpu هستند كه به نوعي دروازه هاي cpu محسوب مي شوند.
يا ميشه بندرگاههاي cpu ناميد كه اينپورت و اكسپورت خود را از آنها تحويل مي گيرد و تحويل مي دهد.

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

در داخل ram بهتر است از پشته نام ببريم.
بهتره بگوييم كه cpu رويكردش به ram اين طور نيست كه همه آن را يكپارچه ببيند. بلكه آن را قطعه قطعه مي بيند.

در فايلهاي com همه قسمتهاي برنامه در يك قطعه 64 كيلويي قرار دارد. و برنامه هاي com تمام كارهاي خود را در اين قطعه واحد انجام مي دهند. مي دانيد كه برنامه عبارت است از مقداري دستورات اسمبلي(البته در مورد اين فايل com ) . و cpu دستورات را داخل همين قطعه فايل com اجرا مي كند. مثلا وقتي برنامه مي گويد كه چيزي را در پشته قرار بده ، چون پشته فايل com در انتهاي قطعه قرار دارد آنرا آنجا قرار مي دهد. البته فايلها مي توانند به جاهاي ديگر ram هم دست اندازي كنند ولي منظور اين است كه اگر دستور برنامه به طور صريح اعلام نكند به طور ديفالت در همان قطعه كارها انجام مي شود.

در مورد فايلهاي exe ، بسته به نوع آن كه tiny و small و large و huge است قطعه هاي برنامه از قطعات بيشتري استفاده مي كنند.
قطعات مورد نياز يكي همان پشته بود .
يكي قطعه داده.
يكي همان قطعه كد كه دستورات آنجا قرار مي گيرند.

پشته نوعي مخزن است تا چيزهايي را موقتا آنجا نگهداري كنيم. استفاده هاي متنوعي ميشه كرد از پشته و يكي از استفاده هاي اون اينه كه چون تعداد رجيسترهاي cpu كم هستند ميشه چيزي را آنجا گذاشت تا بعدا برداريم. نوعي صندوق امانات است اينجا پشته.
قطعه داده هم مثلا براي نگهداري يك رشته استفاده ميشه. مثلا متغيري به نام name را ميشه از نام خانوادگي پر كرد و در آنجا قرار داد.

با اين مقدمه ميشه دستورات اسمبلي را به دسته هايي تقسيم كرد.
عده اي يك رجيستر را به رجيستر ديگر منتقل مي كنند يا دو رجيستر را بر هم تاثير مي دهند.
عده اي محتواي رجيسرها را به ram و برعكس منتقل مي كنند. مثلا دستور push ax باعث ميشه رجيستر ax برود به پشته . و پشته هم كه داخل ram بود.
دستورات ديگري داريم كه وقفه هاي dos را اجرا مي كنند. اينها را ميشه توابع آماده كاربرد ناميد. وقفه هاي داس و بيوس در قسمتهاي اوليه ram قرار دارند. ميشه براحتي آنها را با نوشتن دستوراتي دست كاري كرد ولي اين كار بايد با داشتن دانش آن انجام شود چون ممكن است باعث اختلال كلي سيستم كامپيوتر شود.

خلاصه بحث:
دستورات اسمبلي مستقيما بر تغيير حافظه ها دستور مي دهند.

يك نكته: وقتي ما براي masm و tasm برنامه مي نويسيم و با آنها برنامه را كامپايل مي كنيم ، فقط راهنماها را كامپايلر براي خودش برداشته و استفاده مي كند و كدهاي اسمبلي ما بي هيچ تغييري به فايل تبديل مي شود. يعني نبايد فكر كنيد كه كدهاي ما دچار تغيير مي شوند. بلكه همان دستورات ما دقيقا دستور به دستور بر cpu توسط برنامه exe ما اعمال مي شوند. حالا راهنماها به كامپايلر چه مي گويند؟ يكي اينكه برنامه ما از چه مدلي است . مثلا small است. كامپايلر با ديدن اين دستور قطعه ها را تنظيم مي كند. و كارهاي ديگر.
شما مي توانيد با ديباگ ويندوز يا برنامه هايي مثل توربو ديباگر برنامه ساخته شده exe خود را ببينيد و با اين كار خواهيد ديد كه دقيقا كدهاي شما بي تغيير داخل برنامه موجود است.
ولي در زباني مثل C هر دستور به دستوراتي از نوع اسمبلي تبديل مي شود.
 

saalek110

Well-Known Member
از همين سايت:

خانواده 80x86 با 8086 در سال 1981 شروع شد و جديد ترين عضو آن پنتيوم است كه 13 سال بعد در 1994 عرضه شد.
همه آنها بكوارد كامپتيبل هستند.(يعني قبلي را پشتيباني مي كنند.) و با اضافه شدن فيچورهايي به آنها. و سريع تر از قبلي ها.
امروزه كامپيوترهاي كمي با 8088 و 8086 كار مي كنند. و آنها خيلي از دور خارج و كند هستند.
تعداد 286 ها و 386 ها هم روز به روز كم مي شوند. حتي 486 هم با پنتيوم جايگزين شده.
پنتيوم پرو و mmx based باعث سرعت و توانايي بالا مي باشد.
== = = = = = = =
اعداد در كامپوتر به شكل باينري ذخيره مي شوند. يعني مبناي 2 .
يك بيت ساده ترين حالت اطلاعات است كه دو حالت صفر و يك دارد.
يك نيبل NIBBLE عبارت است از 4 بيت.
يعني 0000 .

پس نيبل نيم بايت است. (بايت 8 بيت است.)
پس نيبل تا عدد 15 (در مبناي 2 ميشه 1111 ) را ظرفيت دارد.
و اين رقم بيس مبناي هگزا دسيمال است. (مبناي 16) .
مبناي 16 خوبي اش در فهم راحت تر آن نسبت به مبناي 2 است. يعني به نوعي آشتي مبناي 2 و مبناي 10 .
اعداد هگزا دسيمال از 1 تا f ادامه مي يابند. (عدد 10 ميشه a و 11 ميشه b و الي آخر)
در انتهاي اعداد هگزا دسيمال يك h مي گذارند. و اگر با حرف شروع بشه قبلش يك 0 (صفر) مي گذارند.
يك بايت 8 بيت است. يا 2 نيبل.
بايت حداكثر 255 مي تواند بشود. خودتان 2 را به توان 8 برسانيد.مي فهميد. از صفر تا 255 ميشه 256 حالت.
بزرگترين عدد يك بايت همان ff است.
يك word يا كلمه دو بايت است. مي تواند تا ffff برود. 65536 ميشه.
= = = == ==
رجيسترها:
Registers are a place in the CPU where a number can be stored and manipulated.
تعريفش را قبلا گفتيم. اين هم متن انگليسي آن.
در 386 ها ما دو نوع رجيستر داريم. 8 بيت و 16 بيت.
و در مدلهاي بالاتر 32 بيتي هم داريم.

رجيسترها 4 نوعند:
رجيسترهاي با مقاصد عمومي.
رجيسترهاي سگمنت.
رجيسترهاي ايندكس.
رجيسترهاي پشته.

رجيسترهاي استك (stack = پشته) و رجيسترهاي سگمنت بعدا گفته ميشه. بقيه را شرح مي دهد.


General Purpose Registers:
شامل: ax bx cx dx
كه 16 بيتي يعني يك word (كلمه) است. و آنها قابل بخش به دو نيمه هستند.(همه رجيسترها قابل نصف كردن نيستند) پس مثلا ax را ميشه به ah و al تقسيم كرد و bx cx dx هم به همين ترتيب قابل نصف كردن هستند. H يعني high و l يعني low .
در كامپيوترهاي بالاي 386 ما داراي رجيسترهاي 32 بيتي با همين نامه هستيم كه يك حرف E اولشان دارند. مثل EAX EBX ECX EDX .
شما مي توانيد AH و AL و AX و EAX را جداگانه براي منظورهايي بكار بريد.چون اين جا حساسه جمله انگليسي اش را بكار مي برم. منظورش را اگر كسي توانست شرح دهد بفرمايد.
You can use AL, AH, AX and EAX separately and treat them as separate registers for some tasks.

رجيسترهاي SI, DI, SP and BP هم مي تواند به عنوان رجيستر همه منظوره بكار رود.
ولي أنها وظايف خاص خود را دارند و به دو نيمه هم اسپليت(شكسته) نمي شوند. (مترجم: اون قبلي ها يعني AX BX CX DX هم وظايف خاص دارند. )

Index Registers:
رجيسترهاي SI DI IP (3 رجيستر) اولي سورس ايندكسه اسمش دومي دستينيشن ايندكسه اسمش و سومي اينستراكشن پوينتر.
در بالاي 386 داريم: EDI and ESI

رجيستر BX هم به عنوان ايندكس استفاده ميشه.
منظور از ايندكس چيه؟اينجا نگفته ولي مثلا اگر بخواهيم چيزي را به جايي منتقل كنيم اين DI و SI نشانه روي مي كنند. از RAM به AX مثلا. بعدا بايد بحث بشه.
رجيستر IP هم خاص است چون شماره خطي از برنامه را كه بايد اجرابشه را در خود نگه مي دارد. يا دستكاري نكنيد يا بدانيد چه كار مي كنيد چون CPU دستور بعدي را از روي IP پيدا مي كند و اگر اشتباه باشه CPU يعني گم ميشه توي RAM و يعني كامپيوتر شما ديگه كامپيوتر بشو نيست و قاطي مي كنه.


Stack registers:
رجيسترهاي BP and SP هستند.
رجيسترهاي پشته است و اينجا گفته بعدا مي گيم.

Segments and offsets:
در 8088 ديده بودند كه فقط به يك مگا بايت حافظه بايد پوشش بدهند. و براي اين پوشش 20 بيت أدرس لازم بوده.خودتان حساب كنيد. ببينيد 2 به توان 20 چند ميشه. حدود يك مگا ميشه.
ولي اون موقع رجيسترها 16 بيتي بودند. (كمبود امكانات)
پس اومدند دو رجيستر را براي آدرس دهي استفاده كردند. يكي را نامش را سگمنت و ديگري را نامش را آفست گذاشتند.
مثل كوچه و پلاك براي ram . ولي چطوري 32 بيت (يعني 2 رجيستر) شد 20 بيت؟
جواب اين كه
OFFSET = SEGMENT * 16
SEGMENT = OFFSET / 16 (the lower 4 bits are lost)
يعني 4 بيت از يك رجيستر را با ضرب انداختند.
اگه كسي توضيح بيشتر خواست بگه.
مثال:
DS stores the Segment and SI stores the offset.
اين دو با هم كار مي كنند.
رجيسترهااي سگمنت اينها هستند:
CS, DS, ES, SS
در بالاي 386 اينها هم هستند:
FS and GS

آفست ها اين ها هستند:
BX, DI, SI, BP, SP, IP
In 386+ protected mode, ANY general register (not a segment register) can be used as an Offset register. (Except IP, which you can't manipulate directly).


The Stack:
وقتي 6 رجيستر براي كارها استفاده مي شوند چطور كارها ممكن است؟ جواب: پشته محلي براي ذخيره و بازيابي اطلاعات است.

پشته مثل تپه است هر چيزي را اول بگذاريد آخر بايد برداريد.
چيزي كه دوم بگذاريد آدرسش كوچك تر است از آنكه اول گذاشته ايد يعني پشته رو به پايين رشد مي كند.

اين بود يك قسمت از 7 قسمت آموزش اين سايت. اميدوارم بتوانم بقيه اش را هم ادامه دهم. بعضي قسمتها نياز به شرح بيشتر دارد كه اگر كسي خواست توضيح بدهم. ولي فكر كنم خود سايت در ادامه آموزش گفته.
 

saalek110

Well-Known Member
با سلام. سايتي كه دو پست قبل معرفي كردم در 7 page آموزش اسمبلي داده كه page 1 آنرا در پست قبلي گفتيم. تا آقا آرمان بياد page 2 را هم بگيم ببينيم چي ميشه.

== = = = = == =
An Introduction to Assembly Instructions
مقدمه اي بر آموزش اسمبلي

در اين قسمت دستوراتي كه زياد استفاده مي شود گفته مي شود.

در قسمتهاي قبلي گفتيم كه يك سري رجيستر داريم كه حافظه هايي داخل cpu هستند. خوب خوبه كه بتوانيم مقدار دهي كنيم آنها را. به دستورات زير دقت كنيد.

کد:
mov ax,10; put 10 into ax
mov bx,20 ; put 20 into bx
mov cx,30 ; put 30 into cx
mov dx,40 ; put 40 into dx

مي بينيد كه با دستورات بالا ما رجيسترهاي ax تا dx را مقدار دهي كرده ايم.
بعد سمي كلون در اسمبلي همه چيز كامنت است يعني متني كه براي شرح براي خود برنامه نويس و ديگر برنامه نويسان است و اجرا نمي شود.
فعلا براي اجرا نرويد. ولي اگر مي خواهيد كه اثر اينها را ببينيد با ديباگ كار كنيد.
استارت را بزنيد تا منوي بالا رونده برود بالا . بعد روي run كليك كنيد تا باز بشه. بعد داخلش بنويسيد debug و ok را بزنيد. اين طوري برنامه ديباگ ويندوز راه ميافته. راه ديگش اينه كه باز از استارت برويد به programs تا برسيد به dos prompt يا در ايكس پي فكر كنم command promp و اونجا بنويسيد debug و اينتر كنيد تا وارد محيط ديباگ بشويد و با حرف q هم از محيط ديباگ باز به dos prompt برمي گرديد. وقتي در محيط ديباگ هستيد يك منها داريم كه يك منهاي چشمك زن داره. ولي در محيط داس پرومپت معلومه كه نام درايو را داريم مثل C: . وقتي از run (روش اول) ديباگ را باز كنيد با زدن q ديگه وارد پرومپت داس نمي شويد بلكه فقط بالاي پنجره مي نويسد finished . يعني اين پنجره ديگه كارش تمام شده.

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

حالا كه وارد محيط ديباگ هستيد بنويسيد :
کد:
a 100
و اينتر كنيد. اين طوري به شما اجازه داده ميشه در حافظه 100 شروع به نوشتن دستورات بكنيد. وقتي من همين a 100 را نوشتم به خط زير رسيدم. البته عدد اولي در كامپيوتر شما به احتمال زياد فرق داره كه بسته به ساختار سخت افزار شماست.
کد:
129d:0100

مي توانم با زدن اينتر بدون نوشتن هيچ چيز از حالت دستور تايپ كردن خارج بشوم . ولي من مي خواهم دستور بنويسم. يكي از دستورات بالا را مي نويسم و اينتر مي كنم.
کد:
129d:0100 mov ax,10
ميخوانم: mov بعدش ax بعدش ويرگول بعدش 10 .
بعد اينتر دارم:
کد:
129d:0103
و باز منتظر دستور بعدي است كه مي توانم باز با اينتر در حالت خالي از حالت دستور نويسي خارج شوم.

حالا يك سري نكته:

چرا 100 شد 103 ؟ علتش اينه كه دستور من 3 بايت از ram را اشغال كرده. بعدا ياد مي گيريد كه بعضي دستورات يك بايتي اند بعضي دو بايتي و بعضي 3 بايتي و همين طور مي رويم بالا.

نكته بعدي: چرا عدد اول يعني 129d عوض نميشه؟ جواب اين كه اين شماره قطعه است. ما الان داريم يك فايل com مي سازيم. در فايلهاي com همه قسمتهاي برنامه داخل يك قطعه قرار مي گيرند. و شماره قطعه ما الان 129d است. يعني قطعه اي در ram . بعدا خواندن هارد را هم خواهيد آموخت ولي فعلا فقط به ram فكر كنيد. مي دانيد كه هارد براي ذخيره است و همه اتفاقات در ram مي افتد.

نكته سوم: چرا ما از 100 شروع مي كنيم به نوشتن و از اول قطعه شروع نمي كنيم ؟ چون كه قبل 100 در فايلهاي com 256 بايت(100 در مبناي 16 است. براي تبديل يك رقم مبناي 16 به مبناي 10 اولي را با ضرب دومي در 16 و ضرب سومي در 256 جمع كنيد) براي كارهاي ديگري رزرو شده و وقتي هم كه برنامه را run مي كنيم cpu مي رود از شماره 100 شروع به اجرا مي كند.

خوب. حالا بياييد برنامه اي كه نوشتيم را run كنيم. اول با زدن يك اينتر از حالت دستور دهي خارج مي شويم و بعد با زدن t و اينتر برنامه ما كه فعلا فقط يك خط است را اجرا مي كنيم.
بعد نوشتن حرف t و اينتر كردن يك سري چيزهايي اتواتيك چاپ ميشه. اين نوشته ها براي بعد آموزشي است احتمالا . و حرف t هم براي اجرا در حالت آموزشي خيلي خوب است. خوب چه مي بينيد؟

42mmpfd.gif


مي بيند كه رجيستر ax شده 10 . و bx تا dx همان طور صفرند. نام بقيه رجيسترها كه د رپستهاي قبلي نام برديم هم هست. همچنين نام فلاگها را كه زيرش خط آبي كشيدم را مي بينيد. بعدا راجع به آنها بحث ميشه. همچنين مي بيند كه دستوري كه در خط 103 است شده push si . ما دستوري ننوشتيم براي خط سوم بلكه cpu چون در منطقه دستورات است هر چي مي بينه دستور برداشت مي كنه و بطور تصادفي از اطلاعات اون قسمت اين دستور ايجاد شده. پس ديگه t نزنيد. چون معلوم نيست اين دستورات چه بلايي ايجاد مي كنند. ممكن است مجبور به ريست كامپيوتر شويد. اگر خواستيد دستور خط 100 را دوباره اجرا كنيد بايد ip را به 100 تنظيم كنيد. در پست بعد اين كارها را تمرين مي كنيم. البته شايد لازم نباشد كار با ديباگ را ياد بگيريد و با ساختن سورس كار كنيد.
 
آخرین ویرایش:

saalek110

Well-Known Member
ادامه:
از page 2 اين سايت در پست قبلي فقط 7 خط گفتيم و بقيه اش شد شرح كار در محيط ديباگ. شايد لازم نباشه راجع به ديباگ صحبت كنيم و شما هم اگر دوست نداشتيد نخوانيد. جزو اين سايت هم نبود اين شرح ديباگ.

اما در ديباگ يك دستور r داريم كه وقتي بنويسيم و اينتر كنيم همين ليست رجيسترها مياد. بعد اجراي برنامه تك خطي بالا هر چه اين r را بزنيد مي بيند كه ax همان 10 است كه ما مقدار دهي كرده بوديم. تا كامپيوتر را ريست نكنيد همين وضع هست. يا بايد برنامه ديگري بنويسيد تا ax را تغيير دهيد. ولي چرا وقتي ما هر بار به رجيستر ها سر مي زنيم هميشه صفرند؟ مگه نگفتيم رجيسترها دروازه هاي cpu با دنياي خارجند. مگه كامپيوتر كار ديگه نداره كه هميشه رجيسترها ثابتند؟ من دقيقا جواب را نمي دانم. ولي بجاي t ما يك دستور داريم كه فكر كنم g بود. بعدا نگاه مي كنم و باهاش كار مي كنيم. وقتي بجاي t با g كار مي كنيم همه دستورات ما را اجرا مي كند و بعد همه رجيسترها را به حالت اول برمي گرداند. به خاطر همين گفتم t حالت آموزشي بيشتري دارد. چون g نمي گذارد تغيير رجيسترها را ببينيم. و يك فرق ديگه هم داره g با t و اونم اينه كه يك دستور را اجرا نمي كنه بلكه تا به دستور end نرسه همين جوري هر چند بايت را براي خود دستور فرض مي كنه و اجرا مي كنه. پس اگر خواستيد از آن استفاده كنيد حتما بايد برنامه شما دستور اختتام داشته باشه. كه البته end نيست. وقفه هاي dos است كه مثل تابعي فراخوانده مي شود و برنامه را خاتمه مي دهد. خاتمه برنامه يعني اينكه كنترل را به ديباگ يا ويندوز برمي گرداند.
بخاطر ديدن همين دستور g بود كه من فكر مي كنم اكثر برنامه ها همين طوري اند كه رجيسترها تغييري از خود ظاهرا نشان نمي دهند. مثلا روش كارشون اينه كه قبل هر كاري همه رجيسترها را در پشته ذخيره مي كنند و بعد كارهاي خود را مي كنند و بعد از پشته دوباره همه رجيسترها را مقدار دهي مي كنند.

برگرديم به دستورات: حرف r علاوه بر اينكه مي تواند ليست رجيسترها و فلاگها را نشان دهد براي تنظيم يك رجيستر هم خوبه. براي اين كار اول بنويسيد r بعد نام رجيستر مورد نظر و بعد اينتر كنيد. مثلا r ax و اينتر . بعد اينتر كردن مي نويسه ax و بعد مقدار فعلي اون را مي نويسه و بعد منتظر مقدار جديد ميشه. من مي دهم 1234 . بعد دوباره r خالي مي زنم تا ليست رجيسترها را ببينم. مهم نيست چي بگذاريد داخل رجيسترها . اين كاري كه الان من با r ax كردم هيچ فرقي با mov ax,10 نداشت. ولي اولي دستي بود و دومي كدهاي درون برنامه.
حالا چرا r را الان گفتم. چون كه بايد ip را تنظيم كنيم. چون مي بينيد كه شده 103 و دستور ما در 100 است پس بنويسيد r ip و اينتر و مقدار 100 را بدهيد و اينتر كنيد.
حالا با r نگاه كنيد . من مي بينم كه ax شده 1234 و ip 100 است. هميشه در ليستي كه با r مي گيريم اولين دستور هم قابل مشاهده است. يعني دستوري كه اگر t بزنيم اجرا ميشه. كه الان mov ax,10 است. كه اگه الان من t بزنم باز ax ميشه 10 . كه بهتره بخوانيم 0010 . يعني ah صفره و al است كه 10 است.
= = == = = = == =
برگرديم به آموزش سايت.
دستور بعدي push و pop است.
اولي يك رجيستر را به پشته مي فرستد و دومي از پشته به رجيستر مي فرستند.
و معلومه كه بعد هر دو بايد نام رجيستر بياد. مثلا
کد:
push cx ; put cx on the stack
push ax ; put ax on the stack
pop cx ; put value from stack into cx
pop ax; put value from stack into ax

فرض كنيد برنامه بالا را اجرا كنيم كه شامل 4 خط است. اين برنامه باعث جابجايي cx و ax ميشه. چرا؟
چون كه اول cx را مي گذاريم كف پشته. بعد ax را مي گذاريم روي آن. بعد روئي يه را مي گذاريم در cx و بعد اون كه كف پشته بود را مي گذاريم در ax .

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

کد:
xchg ax,cx

من الان براي چكش با r در ديباگ به cx دادم 3333 و به ax دادم 1111 . بعد در خط 100 همين دستور بالا را نوشتم. درست بود. باعث شد دو رجيسترجايشان عوض شود. پس ديباگ هم يك خوبي هايي دارد. ديديد چه ساده يك دستور را چك كردم. اگر الان مي خواستم فايل asm بسازم و tasm كنم و link كنم خيلي وقت مي گرفت.
= = = = = =
حدود يك چهارم page 2 را گفتيم كه شامل 3 دستور mov و push و Pop بود. اين xchg زياد من نديدم استفاده بشه. براي همين گفتم 3 دستور. در پستهاي بعدي ادامه خواهيم داد بحث را.
 

saalek110

Well-Known Member
اما در مورد پشته متاسفانه ديباگ محتواي پشته رانمايش نمي دهد. البته زياد هم مهم نيست كه ببينيم پشته را. فقط نظم را رعايت كنيم در ارسال و تحويل گيري از پشته كافيه.
من سعي كردم با ارسال رجيستري به پشته و بعد پيگيري با دستور e كه محتواي بايتها را نشان مي دهد در آخر قطعه دنبال پشته باشم ولي نتوانستم.
اموليتورها با شبيه سازي پشته محيط آموزشي خوبي فراهم مي كنند.

= = = == = = = = ==
اما سه نوع مقدار مي توانيم به رجيستر بدهيم. يكي همان عدد است كه با mov داديم به رجيستر در پست قبلي. ديگري قرار دادن مقدار رجيستر ديگر در يك رجيستر و ديگري از ram در رجيستر. به مثالهاي زير دقت كنيد:

کد:
mov ax,10 ; moves an immediate value into ax 
mov bx,cx ; moves value from cx into bx
mov dx,Number ; moves the value of Number into dx

در كد بالا ، اولي را كه قبلا كار كرديم.
دومي مياد cx را در bx مي گذارد كه ساده است و زياد فرقي با اولي ندارد.
در سومي محتواي number را در dx ميگذارد. بعدا به طرز استفاده سومي خواهيم پرداخت.

بحث بعدي طرز صدا كردن وقفه هاست كه مثل تابع كارهايي را براي ما انجام مي دهند. هر وقفه مي تواند بيش از يك دستور اسمبلي باشد كه ما كاري باهاش نداريم و فقط كاري كه اين تابع بلده را ازش مي خواهيم. از كلمه int كه مخفف اينتراپت به معني وقفه است در اين مورد استفاده مي شود.

کد:
int 21h; Calls DOS service
int 10h ; Calls the Video BIOS interrupt

در كد بالا ما در اولي وقفه داس را صدا زده ايم و در دومي وقفه بيوس را ولي طرز صدا زدنشان فرقي ندارد. با كار آنها هم فعلا كار نداريم.

اما يك وقفه خاص مي تواند كارهاي متنوعي انجام دهد. مثلا همين int 21 دهها كار متنوع انجام مي دهد. براي اين كه يك كار خاص ازش بخواهيم بايد قبلش تنظيمش كنيم. مثل حالت كد زير:

کد:
mov ah,9 ; subroutine number 9
int 21h ; call the interrupt

در كد بالا با تنظيم ah داريم به وقفه 21 مي گوييم كه چه كاري ازش انتظار داريم. يعني اين دو دستور با هم باعث مي شوند كه وقفه 21 بياد و كار مثلا شماره 25 از مثلا 100 كار مختلف خود را انجام دهد و برود.

در انتهاي page 2 اين سايت يك برنامه گذاشته به عنوان اولين برنامه كه ما اجرا مي كنيم.
براي اجرا من در اديتورم كدش را مي نويسم و با پسوند asm ذخيره مي كنم و بعد با tasm و link به فايل اجرايي تبديل مي كنم. در اول تاپيك لينك دانلود اين دو هست.
حالا بايد مقداري شرح بدهيم قضايا را تا اين برنامه را درك شود.
اين برنامه از جهاتي براي ما خيلي مهم است.
يكي اين كه دستور end را دارد. كه عبارت است از :

کد:
mov ax,4c00h ; return to dos DOS 
int 21h

اين نوع end براي فايل exe مناسب است. در اين دو خط اين جوري مي گوييم كه داريم از سرويس 4c از وقفه 21 استفاده مي كنيم براي اختتام برنامه.
در خط اول مي شد بنويسيم mov ah,4c و فرقي با اين نداره چون كه ax از ah و al تشكيل شده. و مي بينيد كه در كد بالا هم دو تا صفر در محل al هست.
زياد چيز پيچيده اي نيست اين دو خط كه بشه بيشتر توضيحش داد. فقط لازمه كه برنامه ما اين end را حتما داشته باشه. و بعد اين دو خط ديگه اجرا ادامه پيدا نمي كنه ، پس در جاي مناسب end را قرار بدهيد.

نكته بعدي برنامه ما اينه كه داره در قطعه اي داده ذخيره مي كنه. و داده ما hello world يعني يك رشته است. كل برنامه را حالا مي گذارم تا از خط اول روي آن بحث كنيم.
کد:
.model small
.stack 
.data 

Message db "Hello World!$" ; message to be display

.code 
start proc
mov dx,OFFSET Message ; offset of Message is in DX 
mov ax,SEG Message ; segment of Message is in AX
mov ds,ax ; DS:DX points to string 

mov ah,9 ; function 9 - display string 
int 21h ; call dos service 
mov ax,4c00h ; return to dos DOS 
int 21h 

start endp
     end start

خط اول آمده مدل برنامه را تعيين كرده. كه مدل ها ربط داره با تعداد قطعات و روش قرار گيري و چيزهاي ديگر كه بعدا بحث مي كنيم.

خط دوم پشته را تعريف كرده. چون عددي جلوي آن نيامده مقدار ديفالت براش قرار داده ميشه كه فكر كنم 1024 بايت است. بعدا نگاه مي كنم ميگم. فعلا مهم نيست. و كافي است اين مقدار. چون شما قراره كه هر چي در پشته مي گذاريد بعدا برداريد و پشته هر چه برنامه كار مي كنه نبايد با بي نظمي پر بشه.

بعد آمده نوشته data كه متغيري به نام Message تعريف كرده و بعدش db گذاشته و بعد مقدار آن را داده. و يك علامت $ هم در انتهايش گذاشته.
اين علامت دلار در اسمبلي نشانه اختتام رشته است .
ما در كدهايمان از وقفه اي استفاده مي كنيم كه به اين علامت دلار حساس است. بعدش هم هر چي بعد سمي كلون ; گذاشته كامنت است كه فقط شرح است و مي دانيد كه اجرا نميشه.

آن جا كه code نوشته تازه محلي است كه ما مي توانيم دستورات اسمبلي را بنويسيم.
آن دستور start proc را من اضافه كردم. در سايت نبود. همچنين start endp را. كلمه start را سايت براي اين انتخاب كرده چون اولين برنامه اي است كه داره عرضه ميشه و چيز خاصي نيست.
حالا چرا من اين دو خط را اضافه كردم؟ چون كه هر كامپايلري به راهنماهاي خاصي نياز داره و چون من با tasm كار مي كردم و ديدم اينها را مي خواهد اضافه كردم. شما شايد جور ديگه كار مي كنيد. اينها مهم نيست. چون همه راهنماها توسط كامپايلر برداشته ميشه و فقط كدهاي اسمبلي داخل فايل اجرايي اطراق مي كند.
شايد بپرسيد آن hello world!$ پس چي؟ يعني اگر فقط كدها اطراق مي كنند داخل فايل اجرايي ما اين رشته كجا مي رود.
جواب اين سئوال بحث جالبي دارد و آن بحث قطعه ها در فايل exe است. گفتيم كه در فايل com همه اجزا در يك قطعه جا مي گيرند ولي در فايل exe در قطعات مختلف مي توانند باشند. پس اين hello در قطعه خاصي قرار مي گيرد.
و قسمتي از كد ما هم حول همين محور ميچرخد.
بگذاريد واضح تر بگويم. اين دو خط كد برنامه را نگاه كنيد:

کد:
mov ah,9 ; function 9 - display string 
int 21h ; call dos service

در اينجا باز وقفه اي احضار شده و در خط اولش هم شماره سرويس ذكر شده.
مواظب باشيد اين دو خط را با دو خط بعدي كه براي end برنامه كار مي كرد را اشتباه نكنيد.
حالا مي خواهيم راجع به سرويس 9 از وقفه 21 صحبت كنيم.
اين سرويس به ram در نقطه DS : DX نگاه مي كنه. Ds و dx شماره قطعه و آفست(آدرس بايت داخل قطعه) است. مثل همان كوچه و پلاك.
و چون اين سرويس به ds و dx نگاه مي كند بايد قبل آتش كردن اين سرويس بياييم dx و ds را تنظيم كنيم.

حالا روش تنظيم كردن dx و ds :
اولا بگم كه نميشده مستقيما به ds مقدار داد. چون يك جورهايي قابل انجام نيست اين كار و برمي گرده به طراحي اوليه. پس يك خط به كد ما اضافه شده سر همين.
يعني اول ريخته اند در ax و بعد از ax ريخته اند داخل ds . اين از اين.

فقط مي مونه اين كه آمده اند در اين ds:dx چي بريزند؟ جواب مختصر اين است مختصات Message را.
بعدا همه اينها را باز تمرين مي كنيم و شرح مي دهيم.
- - --
خط آخر برنامه يعني end start فقط كارش اينه كه بگه برنامه اصلي كدوم بود. ما فقط يك برنامه داريم و تابع نساختيم. تابع و برنامه اصلي دقيقا شبيه هم ساخته مي شوند. با همين proc و endp . پس end start داره ميگه كه start برنامه اصليه بوده.

براي اولين مثال ، مثال خوبي را انتخاب نكرده بود. سنگين بود. ولي اجزاي همين برنامه را در مثالهاي كوچك تر بعدا تمرين كنيم بهتر است.

= = = = = = = =
خوب. صفحه دوم هم تقريبا تمام شد. چند خط كوچك مونده كه در پست بعدي مي گويم.
 
آخرین ویرایش:

saalek110

Well-Known Member
نكاتي از page 2 مونده كه در اين پست مي گوييم:

يكي سينتكس كاملتر push :

کد:
pop register (or variable)

يعني به جز رجيستر ميشه چيز ديگه هم به پشته فرستاد. بعدا تمرين مي كنيم.

= = = =
يك نكته هم اينه كه حرف h را يادتان نره بعد اعداد مبناي 16 بگذاريد. در محيط ديباگ مهم نيست ولي وقتي سورس مي سازيد مهم است. مثلا int 21h كه عدد 21 در مبناي 16 است. چند ميشه در مبناي 10 ؟ يك بعلاوه 2 ضربدر 16 .

= == = = ==
راجع به تعيين سرويس گفته usually put in AH . يعني معمولا سرويس با تنظيم ah تعيين ميشه. پس رجيسترهاي ديگري هم مي توانند تعيين كننده سرويس وقفه ها باشند.
= = == == = =
داريم:
DS : DX to be a far pointer
اشاره دو نوع است near و far . بعدا بحث ميشه. فقط بدانيد كه near درون يك قطعه است و far ميان قطعه ها.
= == = = = = ==
در عبارت:

کد:
Message DB "Hello World!$"

حروف db مخفف declare byte است . يعني Message آرايه اي از ((بايت ها)) است.

همچنين به عبارات زير دقت كنيد:

کد:
Number1 db ?
Number2 dw ?

علامت ؟ يعني كه متغير تعريف شده ولي مقدار اوليه داده نشده(اينيتيالايز نشده)
مي شد به راحتي به جاي علامت سئوال اعدادي مثل 0 و 1 را گذاشت.
همچنين به db و dw دقت كنيد. كلا 3 حالت داريم. Db و dw و dd كه به ترتيب بايت ، كلمه(دو بايت) و ((دو كلمه))(dd ) است.
اين dd فعلا براي ما استفاده نداره . براي رجيسترهاي 32 بيتي مثل eax كاربرد داره.

به كد زير دقت كنيد:

کد:
Number1 db 0
Number2 dw 1
…………
………
…………
mov al,Number1 ; ok
mov ax,Number1 ; error

mov bx,Number2 ; ok
mov bl,Number2 ; error
مي بينيد كه نميشه در يك رجيستر يك بايتي بياييم متغير دو بايتي بگذاريم
يا برعكس در يك رجيستر دو بايتي نميشه بياييم متغير يك بايتي بگذاريم.

== == = = = = =
نكاتي راجع به كامپايلرها:
کد:
Turbo Assembler

tasm file.asm
tlink file [/t]

در مورد توربو اسمبلر گفته كه با گذاشتن حرف t ميشه فايل com ساخت به شرطي كه مدل فايل در كدها tiny باشه.
من اين را تست نكردم. فقط براي اين كه چيزي جا نيفتد گفتم.

در مورد a86 :
کد:
a86 file.asm

گفته كه ميشه فايل com ساخت با a86 و برايش مدل فرقي نداره. متن اصلي:
This will compile your program to a .COM file. It doesn't matter what the memory model is.

= = = = == = = = = =
خوب. Page 2 هم تمام شد.
من حداقل 10 برابر از خودم توضيح اضافه كردم . اميدوارم در page هاي بعدي نياز به توضيح ديگه نباشه و سريع تمام بشه.
 
آخرین ویرایش:

saalek110

Well-Known Member
خوشبختانه در page 3 كدنويسي را شروع كرده و بحث شيريني است. پس سعي مي كنم همين امشب اين صفحه را نقل كنم.
اما قبلش مي خواهم از يك تاپيك آموزش اسمبلي در سايت ديگري مطالبي را نقل كنم.
لينك تاپيك:
http://www.myimei.com/forum/showthread.php?tid=112

در شروع وظيفه خود مي دانم كه از استادان imei و كرگدن تشكر كنم كه در چندين زبان استاد و راهنماي من بوده اند.
 

saalek110

Well-Known Member
مطلب اول دهمين پست اين تاپيك است نوشته كرگدن راجع به قطعه ها.
من در اين تاپيك كمي تنبلي كردم و يا سوادم كم بوده با نقل اين مطلب جبران ميشه.
== = = = = == = =
سگمنت:

نا حیه ای از حافظه است که آدرس شروع آن بر 16 قابل قسمت است و اندازه آن می تواند تا 64k باشد.

هر برنامه اسمبلی می تواند تا چهار نوع سگمنت داشته باشد.

سگمنت کد (code segment):
دستورهای زبان ماشین که باید اجرا شوند در این سگمنت قرار خواهند گرفت
در صورتی که کد برنامه از 64K بیشتر شد می توان از چند سگمنت کد استفاده کرد

سگمنت داده (data segment):
متغیر ها و داده ها ی برنامه در این قسمت قرار می گیرند
در صورت نیاز میی توان از چند سگمنت داده در برنامه استفاده کرد

سگمنت پشته (stack segment):
حاوی آدرس بازگشت از زیربرنامه و به طور کلی حاوی تمام اطلاعاتی که برای فراخوانی زیربرنامه ها لازم است

سگمنت اضافی:
این سگمنت برای انجام عملیات بر روی رشته ها مورد استفاده قرار می گیرد


مرجع:کتاب برنامه نویسی به زبان اسمبلی از 8086 تا پنتیوم جعفر نژاد قمی- رمضان عباسپور
 

saalek110

Well-Known Member
باز نقل از اين تاپيك پست 12:
هر زبانی کاربرد خودشو داره
هیچ زبانی برای از بین رفتن زبان قبلی به وجود نیومده

خیلی کارها با اسمبلی راحت تر از زبانهای دیگر هست
سرعت اسمبلی را هیچ زبانی ندارد
برای ماشین ها با کارایی محدود بهترین گزینه اسمبلی است
وقتی برای ماشینی بخواهیم کامپایلری ایجاد کنیم باز هم بهترین انتخاب اسمبلی است.
= = = = = = = = =
پست 14:
با دونستن اینکه هر کدی که در هر زبان مینویسید به صورت اسمبلی به چه شکلی است میتونید برنامه خودتون رو بهینه کنید

مثلاً

a=a+1;
a+=1;
a++;

فرق بین اینا چیه؟
کدوم سریعتر هستند؟
اینو فک کنم ایمی قبلاً تو تاپیک سی گفته بود
(از پایین به بالا کندتر میشن)
یا مثلاً فرق ضرب در 2 یا شیفت به چپ چیه؟
کدوم سریعتره؟
(شیفت به چپ)
و......
 

saalek110

Well-Known Member
از همين تاپيك ، پست 16 :
راجع به رجيسترها و فلاگها:

== = == = = == = = ==
ثبات ها

ثبات ها حافظه های 8 16 32 و 64 بیتی در داخل پردازنده هستند (به تاپیک cpu &chip مراجعه کنید) که سرعت بسار بالایی دارند و می توان از آنها در ساختارهایی که به شمارنده و محاسبات زیادی نیاز دارند استفاده کرد
در این بخش با ثباتهای 16 بیتی کار داریم

ثباتهای عمومی:
AX-BX-CX-DX
که هر کدام از دو قسمت 8 بیتی کم ارزش و پر ارزش تشکیل شدند
مثلاً AL بخش کم ارزش و AH بخش پر ارزش AX می باشد
و برای DX نیز DL, DH
خانه ها را از 0 شماره گذاری می کنیم (بنابر این هر ثبات 16 بیتی از 0 تا 15 شماره گذاری میشه)
از ثبات CX در شمارنده ها استفاده میشه ( متغییر کنترلی اتمام حلقه ها هستند)
نتیجه ضرب و تقسیم اعداد بزرگ در DX قرار می گیره
به ثبات BX هم ثبات پایه می گن وبه عنوان اندیس ازش استفاده می کنن
ثبات AX هم در محاسبات زیاد مورد استفاده قرار می گیره

ثباتهای سگمنت:
ES-SS-DS-CS
در این ثباتها آدرس شروع سگمنت هایی که قبلاً گفتم ذخیره می شه

(SS (stack segment برای سگمنت پشته
DS (data segment برای سگمنت داده
(CS (code segment برای سگمنت کد
(ES (extra segment برای سگمنت اضافی

ثباتهای اندیس:
BP-SP-SI-DI

اول یک توضیح در مورد آفست بدم
در قسمت قبلی در مورد آدرس سگمنت ها حرف زدیم
هر سگمنت یک آدرس شروعی داره که در ثبات سگمنت ذخیره میشه
به فاصله ای که از این آدرس داریم آفست میگیم

ثبات (BP (base pointer شامل آفستی از ثبات SS هست
ثبات (SP (stack pointer حاوی آفست بالای پشته است
بالای پشته= آخرین ورودی
پشته در این زبان از بالا بسته است و از پایین پر میشود (از نظر آدرسی)

ثبات (SI(source index برای عملیات بر روی رشته ها هست و آدرس رشته منبع رو نگهداری میکنه
ثبات (DI(destination index برای عملیات بر روی رشته ها هست و آدرس رشته مقصد رو نگهداری میکنه

ثباتهای وضعیت و کنترلی:
IP-FLAG

ثبات IP آفست دستور بعدی اجرایی برنامه را دارد

ثبات فلگها
CF-PF-AF-ZF-SF-TF-IF-DF-OF
یک ثبات 16 بیتی که 9 بیت آن به طور مشخص نامگذاری شده و وضعیت پردازنده رو نشون میده



بیت (c (carry برای نشان دادن وجود رقم نقلی در محاسبات که آنرا CF می نامند
بیت (D (direction به معنی جهت می باشد و جهت پردازش روی رشته ها رو مشخص میکنه (از چپ به راست یا برعکس) و با DF نشون داده میشه
بیت (P (parity) اگر صفر باشه نشاندهنده اینه که تعداد شیفت ها زوج بوده وگرنه فرد بوده و با PF نشون داده میشه
بیت (A (auxiliary carry رقم نقلی کمکی هست و در محاسبات 8 بیتی اگه رقم نقلی استفاده میشه و با AF نمایش داده میشه
بیت (Z(zero اگر در نتیجه محاسبات صفر ایجاد بشه این بیت برابر یک میشه و با ZF نشون داده میشه
بیت (S (sign اگر نتیجه محاسبات منفی باشه این بیت 1 میشه و با SF نشون داده میشه
بیت (T(trap اگر این بیت برابر یک باشه اجرای برنامه به صورت دستور به دستور در میاد و با TF نشون داده میشه
بیت (I(interrupt اگر این بیت 1 باشه سیستم به وقفه ها پاسخ میده وگرنه اونارو نادیده می گیره که با IF نشون داده میشه
بیت (O(overflow اگه در محاسبات بیت پر ارزش سرریز بشه بیت O صفر میشه , با OF نشون داده میشه
= = = = = = = = == = = = = =
پست 21:

Saalek :
يك سئوال هم داشتم . فرق sp با bp چيه. اگر قبلا گفته بوديد و من دقت نكردم شرمنده.
. کرگدن :
bp میتونه ثابت باشه
ولی sp با اضافه و کم شدن عضو ها تغییر میکنه و آخرین عضو رو نشون میده
(در صورت خالی بودن پشته قبل از ss رو نشون میده)
مثلاً bp میتونه فقط روی خونه 4 ام پشته باشه و تغییری نکنه ولی sp حتماً خونه آخر رو نشون میده
 

saalek110

Well-Known Member
پست 26 از همين تاپيك:
= = = = == = = == =
داده ها در اسمبلی:

همونطور که گفتم هر برنامه از سگمنت های مختلفی تشکیل شده که یکی از اونا سگمنت داده هست
تعریف داده هایی که در برنامه استفاده میشه ، در این قسمت صورت میگیره.

نکته :اعداد نوشته شده در اسمبلی به طور پیش فرض در مبنای 10 هستند مگر اینکه اونارو با پسوند های h (برای مبنای 16) ، b (برای مبنای 2)، q و o (برای مبنای 8) بنویسیم

نکته: اگر عدد ما در مبنای 16 با حرف شروع بشه قبل از اون یه 0 (صفر)باید بذاریم
به این شکل FFF5h --> 0FFF5h

برای داده های 1 بایتی از DB ، 2 بایتی DW ،4 بایتی از DD استفاده می کنیم.
برای داده های بزرگتر هم دستورهای دیگه ای داریم که فعلاً با اونا کاری نداریم
نحوه تعریف داده:

کد:
<مقدار> <DD یا Dwیا DB>  <نام>

مقادیر ما در حافظه در مبنای 16 یا هگز ذخیره میشوند
مثال:
کد:
byte1 db 255

در حافظه به صورت FF ذخیره می شود

توجه:
متغییر هایی که بیشتر از یک بایت هستند در حافظه به صورت معکوس ذخیره می شوند

کد:
word1 dw  1234h

در حافظه به صورت12 34 ذخیره می شود (آفست 34 کمتر از 12 هست)

با این دستور ها میشه چند متغییر رو هم زمان تعریف کرد (که بعداً در مورد دسترسی بهشون صحبت می کنیم)

کد:
p1 db 12,13,15

اگر متغییری داشته باشیم که می خوایم در طول برنامه مقدار دهی بشه از علامت ؟ در قسمت مقدار استفاده می کنیم

کد:
byte1 db ?

به متغییر ها رشته هم میشه داد که بین دوتا " یا ' قرار می گیرند
انتخاب " یا ' به رشته مون بر میگرده
اگه " در رشتمون باشه از ' استفاده میکنیم و بر عکس
کد:
str1 db "a"

str2 dw "bb"
 

saalek110

Well-Known Member
پست 49 از همين تاپيك:
= == == = = = = = =
عملگر dup:

با استفاده از این عملگر در DB,DW,DB شما می تونید چندین خونه از اونا رو مورد استفاده قرار بدین
مثال:
کد:
test dw 100 dup(0)

که 100 خونه dw با مقدار 0 در نظر میگیره
مثال:

کد:
test db 10 dup(' ~'), ' ~'
این دستور 22 بایت از حافظه رو می گیره که شامل ~ , فاصله هستند


دستور mov :

باین دستور دو عملوندی هست که مقدار عملوند دوم رو به عملوند اول منتقل می کنه
چندتا شرط داره
1-طول و اندازه دو عملوند باید یکی باشه (هردو بایت باشن یا کلمه یا ...)
2- دو عملوند نمی تونن حافظه باشن (که توسط db , dw و... تعریفشون کردیم)
3- هردو عملوند نمی تونن ثبات سگمنت باشند
4-مقدار دهی ثابت به ثبات ثابت هم مجاز نیست
مثلاً

کد:
count dw 20h

mov al,count
]چون اندازه ها رعایت نشده

کد:
mov c1,c2

]c1 , c2 هردو حافظه هستند

کد:
mov ds,4

انتقال عدد ثابت به ثبات سگمنت

کد:
mov ds, datasg

datasg آدرس سگمنت هست (خودمون انتخاب کردیم و بعداً بیشتر در موردش حرف می زنیم)

همگی غیر مجاز هستند.
 
آخرین ویرایش:

جدیدترین ارسال ها

بالا