بعضي از دستورالعمل هاي پايه اي استفاده شده در مجموع دستورالعمل هاي ARM که براي برنامه نويسي هسته هاي ARM استفاده ميشوند را ياد بگيريد.


اين مقاله براي کمک به شما در يادگيري دستورالعمل هاي پايه اي اسمبلي براي برنامه نويسي هسته ي ARM تهيه شده است.


ما پست قبلي از فايل هاي ثبتي  ARM را انتخاب ميکنيم. لطفا قبل از ادامه ي مقاله آن را دوباره  مرور کنيد، چون در دستورالعمل هاي زير به علائم اختصاري ثبت شده مراجعه ميکنيم.


اين اطلاعات براي برنامه ريزي يک Raspberry Pi که در هسته هاي 32 بيتي استفاده ميشود، در مقاله ي بعدي هم استفاده خواهند شد. در اين مقاله تمرکز ما روي دستورالعمل هاي ARMv7 و رجيستر هاي 32 بيت خواهد بود.


توجه: ورژن هاي جديد Raspberry Pi که رسپبيان را اجرا ميکنند، از يک پردازنده ي ARMv8 64 بيتي استفاده ميکنند ولي دقيقا مثل ورژن هاي قديمي آن را به شکل 32 بيت نصب ميکنند. احتمالا در مقاله ي بعدي درمورد ARMv8 صحبت خواهيم کرد.


 


کد ماشين


پردازنده از دستورالعمل ها استفاده ميکند. بياييد نگاهي به کد ماشين که دستورالعمل ها نشانش ميدهند بياندازيم. بيشتر دستورالعمل هايي که با آن سروکار داريم به عمليات هاي ديتا مرتبط هستند، به همين دليل من دستورالعمل پردازش ديتا را از کتاب راهنماي ARMV7 استخراج کرده ام.


 


دستورالعمل هاي ARM


دستورالعمل پردازش ديتا


تصوير بالا نشان دهنده ي 32 بيت موجود در دستورالعمل پردازش ديتا است، هر بيت هدف ويژه و مخصوصي يا به صورت جداگانه و يا به عنوان بخشي از گروه دارد.


وسعت زمينه ي وضعيت 4 بيت است، در نتيجه 15 کد شرطي وجود دارد. کد عملياتي که 4 بيتي است کنار پرچم صريح قرار گرفته و نشان ميدهد که عملگر 2 مقدار صريح و پرچم شرايط-مجموع دارد و ما از آن براي به روز کردن موقعيت رجيستر در حين عمليات استفاده ميکنيم. توجه داشته باشيد که اين کد عملياتي است که عملي را- مثل جمع، تفريق و يا فقط OR – که پردازنده انجام ميدهد، تعيين ميکند.


همانطور که در دستورالعمل هاي زير ميبينيد، به تصوير اول مراجعه ميکنيم و ميبينيم دستورالعمل اسمبلي انکد ميشود و به يک جفت تبديل ميشود. براي بدست آوردن اطلاعات بيشتر، در کتاب راهنماي ARM کاوش و جست و جو کنيد.


نحوه ي خواندن دستورالعمل هاي اسمبلي:


يادمان ها و عملگر ها


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


يادمان    DESR، SRC2، SRC2


دستورالعمل ADD ( که در بخش زير توضيح داده شده است)، R2 را به R1 اضافه ميکند و نتيجه ي بدست آمده را در R0 ميگذارد (براي توضيح اين علائم اختصاري مقاله ي قبلي را بخوانيد). اين يک روش نرمال براي خواندن يک دستورالعمل اسمبلي است. R2 را به  R1 اضافه کنيد و نتيجه اش را در R0 قرار دهيد. کد ماشين برابر که بر روي پردازنده اجرا ميشود درکنار دستورالعمل ADD نشان داده شده است.


 


دستورالعمل هاي ARM


 


زبان اسمبلي


بخش Cond براي اجراي هميشگي داراي “1110”  است. اين بيت ها هنگام استفاده از پسوند هاي شرطي که به عمليات ADD پيوست شده اند، اجرا ميشوند. بخش بعدي استفاده نشده است و صفر شده است. بخش”I”  صفر است چون Op2 يک رجيستر است نه مقدار فوري. بخش “S” صفر است چون ما S را به عمليات ADD اضافه نکرده ايم. يعني براي به روز رساني پرچم هاي وضعيت رجيستر اين دستورالعمل را نميخواهيم. (در مورد بخش هاي N,Z,C و V بعدا توضيح ميدهيم.)


اگر دوباره نگاهي به تصوير اول بيندازيد، متوجه کد عملياتي جمع بستن ميشويد. اين يک 0100b است و به پردازنده ميگويد براي عمليات ADD يک مسير ديتا تنظيم کند. سه بخش آخر، R3(0001b)، R0 (0000b) و R2 (…0010b) هستند.


 


Cond    I OpCd S  Rn Rd Op2


ADD     R0,  R1, R2     @ 1110|00|0|0100|0|0001|0000|000000000010


 


عملگر هاي يک دستورالعمل معمولا رجيستر هستند اما ميتوانند آدرس حافظه و يا مقدار فوري هم باشند. يک مقدار فوري، عدد دقيقي است که بايد استفاده شود. اينها يک پيشوند با نشان # هستند. براي مثال در بالا به جاي استفاده از R2 ميتوانيم از مقدار فوري 42 استفاده کنيم. اين دستور در زير نشان داده شده است:


 


Cond    I OpCd S  Rn Rd Op2


ADDS     R4,    R6, #42    @ 1110|00|1|0100|1|0110|0100|000000101010


 


اين دستور العمل 42 را به R6 اضافه ميکند و نتيجه را در R4 قرار ميدهد. اين بار “I” بر روي 1 تنظيم شده است چون ما براي عملگر 2 از يک مقدار فوري استفاده ميکنيم. کد عملياتي به همان شکل باقي ميماند چون هنوز در حال جمع بستن هستيم. دقت کنيد که بخش “S” 1 است. به همين دليل براي آپديت پرچم هاي رجيستر وضعيت ما در حال اجرا، به عمليات ADD احتياج داريم.


 


 


دستورالعمل هاي ARM


يادمان ها و عملگر ها


دستورالعمل بعدي ميتواند از بخش Cond براي بررسي پرچم هاي وضعيت و اجراي شرطي بر اساس نتيجه استفاده کند. Rn، 0110b ، بيان کننده ي R6 و Rd، 0100b براي R4 است. مقدار فوري Op2، 12 بيت جفتي بيانگر عدد 42 است. ادامه ي اين بخش زيرمجموعه اي از اساسي ترين دستورالعمل هاي ARM را با يک توضيح کوتاه و مثال ليست کرده است.


 


دستورالعمل پردازش ديتا


دستورالعمل هاي زير ديتا را اداره ميکنند. ميتوانند عمل هاي حسابي باشند که تابع هاي رياضي، عمل هاي مقايسه اي و يا حرکت هاي ديتا اجرا ميکنند.


جمع (ADD)


جمع يعني همان ADD، R2 را به R1 اضافه ميکند و نتيجه را در R0 ميگذارد. جمع با حمل، همراه با پرچم رقم نقلي R2 را با R1 جمع ميکند. اين دستور هنگام معامله با اعداد بزرگتر از يک کلمه ي واحد 32 بيتي استفاده ميشود.


 


ADD R0, R1, R2


ADC R0, R1, R2


 


تفريق (SUB)


تفريق (SUB)، R2 را از R1 کم ميکند و نتيجه را در R0 ميگذارد.  تفريق با رقم حمل ( SBC) R2  را از R1 کم ميکند و اگر پرچم رقم حمل پاک شود، يک را از نتيجه کسر ميکند. اين دستور برابر با قرض گرفتن در علم حساب است و درست کار کردن تفريق هاي چند کلمه اي را تضمين ميکند.


 


SUB R0, R1, R2


SBC R0, R1, R2


 


مقايسه (CMP) و مقايسه ي منفي(CMN)


مقايسه (CMP) و مقايسه ي منفي (CMN) دو عملگر را مقايسه ميکنند. مقايسه R1 را از R0 کسر ميکند و مقايسه ي منفي  R2 را به 1R اضافه ميکند و سپس پرچم هاي وضعيت بر طبق نتيجه ي جمع و يا کسر آپديت ميشوند.


 


CMP R0, R1


CMN R1, R2


 


دستورالعمل هاي ARM


زبان اسمبلي


 


حرکت (MOV)


عمل حرکت (MOV) دقيقا همان کاري که به نظر مي آيد را انجام ميدهد. يعني ديتا را از جايي به جاي ديگر منتقل ميکند. در دستور زير، R1 به R0 کپي ميشود. در خط دوم مقدار فوري 8 در R0 قرار ميگيرد.


 


MOV R0, R1


MOV R0, #8


 


حرکت منفي  (MNV)


حرکت منفي (MNV) همان کار حرکت (MOV) را انجام ميدهد با اين تفاوت که اول ديتا را کامل ميکند (و يا برعکس). اين کار هنگام عمليات با اعداد منفي، مخصوصا با نشان مکمل دو  قابل استفاده است. دستورالعمل زير  NOT 8 که بيشتر به عنوان 9- شناخته شده است، در R0 ميگذارد. اگر يک را به نتيجه اضافه کنيد و اين دو مکمل را انجام دهيد، 8- بدست مي آوريد.


 


MVN R0, #8


 


و عملکرد بيتي و R2 و R1 را انجام ميدهد و نتيجه را درR0 ميگذارد. به جاي R2 ميتوان از مقدار فوري استفاده کرد.


 


AND R0, R1, R2


 


ORR و EOR


ORR و EOR عمليات بيتي OR و XOR را به ترتيب R2 و R1 انجام ميدهند.


 


ORR R0, R1, R2


 


EOR R0, R1, R2


 


پاک کردن بيت(BIC)


پاک کردن بيت يک عمليات بيتي AND R2 و R1 را انجام ميدهد اما اول بيت هاي  R2 را کامل ميکند. معمولا اين کار با استفاده از مقدار هاي فوري انجام ميشود. همانطور که در خط دوم که مقدار فوري، 0xFF، مع شده است و متعاقبا با R1، AND شده است. AND کردن 8 صفر به بيت اول همه ي آن بيت هارا پاک ميکند يعني آنها را برابر با صفر ميکند و نتيجه را در R0 قرار ميدهد.


 


BIC R0, R1, R2


BIC R0, R1, #0xFF


 


دستورالعمل هاي ARM


 


شاخه هاي عناصر زبان اسمبلي


 


 


بيت هاي آزمايشي (TST) و تعادل آزمايشي (TEQ)


کار بيت هاي آزمايشي و تعادل آزمايشي، آزمايش بيت هايي است که در رجيستر قرار دارند. اين دستورالعمل ها از مقصد رجيستر استفاده نميکنند بلکه، فقط رجيستر را بر اساس نتيجه آپديت ميکنند. بيت هاي آزمايشي ذاتا يک عمليات بيتي AND دو عملگر را انجام ميدهند. ما ميتوانيم با استفاده از يک ماسک براي دو عملگر، تنظيم يک بيت تکي را در R0 آزمايش کنيم.


در اين صورت بيت 3 را (bitmask = 1000b = 8) بررسي ميکنيم و پرچم  Z را بر اساس خروجي تنظيم ميکنيم. تعادل آزمايشي هم همين کار را انجام ميدهد و يا برابر بودن دو رجيستر را بررسي ميکند. اين کار پرچم N و  Z را آپديت ميکند و به همين دليل روي اعداد علامت دار هم کار ميکند؛ اگر علامت هايشان با هم متفاوت باشند  N بر روي يکي تنظيم ميشود.


 


TST R0, #8


TEQ R1, R2


 


عمل ضرب(MUL)


در دستورالعمل عمل ضرب، R1 در R2 ضرب ميشود و نتيجه در R0 قرار ميگيرد. ضرب قابل استفاده با مقدار فوري نيست.


 


MUL R0, R1, R2


 


دستورالعمل انتقال يا چرخش


انتقال چپ منطقي (LSL)


دستورالعمل انتقال چپ منطقي (LSL) بيت ها را توسط يک مقدار انتقالي در R1، انتقال ميدهد. در اين صورت مقدار فوري 3 و مهم ترين بيت ها آزاد ميشوند. آخرين بيتي که به بيرون منتقل شده است، در پرچم رقم حمل قرار ميگيرد و کوچکترين بيت هاي مهم با صفر پر ميشوند. در دستورالعمل هاي زير،  R1 توسط مقدار فوري 3 به چپ منتقل ميشود، يا يک مقدار بين 0 و 31 در R2، به R0 تغيير ميکنند. يک انتقال چپ منطقي، يک مقدار را در دو ضرب ميکند. اين کار يک روش کم هزينه براي ضرب ساده است.


 


LSL R0, R1, #3


 LSL R0, R1, R2


 


دستورالعمل هاي ARM


انتقال و چرخش در زبان اسمبلي


 


انتقال راست منطقي(LSR)


دستورالعمل انتقال راست منطقي به روش مع انتقال چپ منطقي کار ميکند و به شکل موثري يک مقدار را تقسيم بر دو ميکند. مهم ترين بيت ها با صفر پر ميشوند و بيت کم اهميت در پرچم رقم حمل گذاشته ميشود.


 


LSR R0, R1, #2


 


انتقال راست حسابي(ASR)


دستورالعمل انتقال راست حسابي همان کار انتقال راست منطقي را انجام ميدهد اما براي اعداد علامت دار طراحي شده است. اين عمل بين هاي علامت دار را در آخرين وضعيت چپ کپي ميکند.


 


ASR R0, R1, #4


 


چرخش راست(ROR)


چرخش راست تمام بيت هاي يک کلمه را با چند مقدار، ميچرخاند. در اين دستور به جاي پر کردن بيت هاي چپ با صفر، بيت هاي منتقل شده به سادگي به انتهاي سمت ديگر برگردانده ميشوند.


 


ROR R0, R1, #5


 


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


يکي از  وظايف مهم يک پردازنده، توانايي انتخاب بين دو مسير کد مبتني بر مجموعه اي از ورودي هاست. اين دقيقا کاري است که عمليات منشعب انجام ميدهند. معمولا يک پردازنده يک دستورالعمل را با افزايش R15، شمارنده ي برنامه(PC)، يکي پس از ديگري توسط 4 بيت اجرا ميکند(يعني طول يک دستورالعمل تک). شعبه بندي کردن PC را به محل ديگري که توسط يک برچسب که آن بخش از کد اسمبلي را نشان ميدهد، انتقال ميدهد.


شعبه(B)


دستورالعمل شعبه(B) شمارنده ي برنامه را توسط يک برچسب به آدرس تعيين شده اي منتقل ميکند. برچسب (loop در مثال پايين) نشان دهنده ي بخشي از کد است که شما ميخواهيد پردازنده در مرحله ي بعد اجرا کند. برچسب ها فقط يک متن و معمولا يک کلمه ي معني دار هستند.


 


B     loop


 


دستورالعمل هاي ARM


 


زبان اسمبلي در مجموع دستورالعمل هاي ARM


 


پيوند شعبه(BL)


دستورالعمل پيوند شعبه (BL) همان کار را انجام ميدهد اما آدرس دستورالعمل بعدي را در  R14، يعني اتصال رجيستر (LR) کپي ميکند. اين کار عمل هنگام انجام خوانش زيروال/روند بسيار عالي کار ميکند چون به محض اينکه بخش کد در برچسب تمام ميشود ميتوانيم از LR براي برگرداندن به جايي که منشعب کرده ايم استفاده کنيم. ما در پايين به برچسب زيروال منشعب ميشويم و سپس براي برگشتن به دستورالعمل بعدي از اتصال رجيستر استفاده ميکنيم.


BL      زيروال


    …


زيروال:


    …


    MOV    PC, LR


ما براي برگرداندن اتصال رجيستر به شمارنده ي برنامه از يک دستورالعمل حرکت (MOV) استفاده ميکنيم. اين کار درست بعد از خوانش زيروال ما، برنامه را به محل برميگرداند. به استفاده ي LR و PC در بالا توجه کنيد. اسمبل هاي ARM آنها را به ترتيب به عنوان R14 و R15 ميشناسند. اين کار يک تذکر آسان و راحت در مورد عملي که انجام ميشود به برنامه نويس ميدهد.


دستورالعمل هاي بارگيري و ذخيره سازي


اطلاعات ذخيره سازي حافظه ي کامپيوتر چيزي است که پردازنده به آن نياز دارد. اين ديتا با استفاده از يک آدرس بدست مي آيد. در ابتدا ميتوانيم با دادن يه آدرس به يک رجيستر، از طريق همان آدرس به ديتا دسترسي پيدا کنيم. به همين خاطر است که از عمليات هاي بارگيري و ذخيره سازي استفاده ميکنيم.


 


دستورالعمل هاي ARM


دستورالعمل هاي پردازش ديتا


رجيستر بارگيري(LDR)


دستورالعمل رجيستر بارگيري، ديتاي مستقر در يک آدرس را درون رجيستر مقصد بارگذاري ميکند. پرانتز هاي اطراف R1 حاکي از اين است که رجيستر يک آدرس دارد. ما با استفاده از پرانتز ها ديتا را به جاي خود آن آدرس در آدرس R0 قرار ميدهيم. همچنين ميتوانيم از اين علامت گذاري براي قرار دادن ديتاي افست از يک آدرس معين استفاده کنيم، همانطور که در دستورالعمل خط دوم نشان داده شده است. R0 شامل ديتاي دو کلمه اي دور از هر چيزي است که داراي آدرس R0 است.


 


LDR R0, [R1]


LDR R0, [R1, #8]


 


همچنين ميتوانيم براي نشان دادن يک آدرس از برچسب ها استفاده کنيم و ديتاي مرتبط هم ميتوانند در يک رجيستر بارگذاري شوند.


اولين خط زير آدرس برچسب “info” را در R0 بارگذاري ميکنند. مقدار ذخيره شده در آدرس هم قابل دستيابي است و در خط دوم در R1 گذاشته شده است.


 


LDR R0, =info


LDR R1, [R0]


 


ذخيره سازي (STR)


ذخيره سازي يک عمليات مکمل را براي بارگيري انجام ميدهد. ذخيره سازي، محتويات رجيستر را در محل حافظه قرار ميدهد. کد زير ديتاي درون R1 را در آدرس R0 ذخيره ميکند. پرانتز ها باز هم نشان دهنده ي اين هستند که R0 يک آدرس دارد و ما ميخواهيم ديتاي آن آدرس را تغيير دهيم.


 


STR R1, [R0]


 


دستورالعمل هاي ARM


دستورالعمل ها و توضيحاتشان


انواع بارگذاري و ذخيره سازي: بيت (B)، هف ورد (H)، کلمه (حذف شده)، علامت گذاري شده (SB)، علامت گذاري نشده (B)


هم بارگذاري و هم ذخيره سازي با يک نوع پيوست به آنها قابل نوشتن است. اين نوع حاکي از اين است که آيا دستورالعمل يک بيت، يک هف وورد و يا يک کلمه را دستکاري ميکند و اينکه آيا ديتا علامت گذاري شده است يا خير.


اين ممکن است که براي دستکاري استرينگ (رشته) به کار بيايد، چون رقم هاي ASCII طول يک بايت را دارند. همانطور که در دستورالعمل خط آخر مشاهده ميشود، اين عمليات اجازه ي استفاده از آفست ها را هنگام بارگذاري و يا ذخيره سازي را هم ميدهند.


LDR R0, = متن                                 @بارگذاري يک آدرس 32 بيتي در R0


  STRB R1, [R0]                          @ ذخيره سازي بيت در آدرسي در حافظه


STRB R1, [R0, + R2]                   @ ذخيره سازي بيت در آدري+ آفست R2


 


دستورالعمل هاي شرطي


همانطور که قبل تر گفته شده است، ممکن است يادمان هاي استفاده شده در يک دستورالعمل، کد هاي شرطي انتخابي پيوست شده به آنها را داشته باشند. اين کار اجازه ي اجراي شرطي را ميدهد.


يادتان باشد پرچم ها (همانطور که در مقاله ي قبلي ديديد) Z (صفر) ، C(رقم حمل)، N( منفي) و V(سرريز) هستند. براي مجبور کردن دستورالعمل ها براي آپديت کردن رجيستر وضعيت، S انتخابي ميتواند به بيشتر يادمان هايي که تاکنون به آنها اشاره شده اضافه شوند. وقتي رجيستر وضعيت آپديت شد، تعدادي از پسوند هاي شرطي که در تصوير زير نشان داده شده اند، ميتوانند براي اجراي دستورالعمل ها استفاده شوند. کدهاي دوتايي اين پسوند ها مطابق با 4 بيت اول دستورالعمل پردازش ديتا در اولين عکس مقاله نشان داده شده اند.


 


 


دستورالعمل هاي ARM


پسوند هاي شرطي


اين پسوند ها در زمان نوشتن اسمبلي به يادمان اضافه ميشوند.


در ليست زير تعدادي از پسوند هاي شرطي استفاده شده با دستورالعمل هاي که در طول مقاله به آنها اشاره شد، گردآوري شده است.


به دليل اينکه در مقاله ي بعدي با اسمبل کننده GNU سروکار خواهيم داشت، بايد براي نشان دادن يک نظر از علامت @ استفاده کنيم.


.شروع_جهاني (  .global _start )


شروع:


MOV R0, #3                @مقدار 3 را در R0ميگذارد


MOV R1, #0                @مقدار 0 را در R1 ميگذارد


Loop:


CMP R0, R1                @R1 را با R0 مقايسه ميکند (در اصل R0 را منهاي R1 ميکند)


BEQ         انجام شد        @ اگر برابر هستند شعبه با برچسب باشند، تمام شده است. (Z=1)


ADDGT R1, #1            @ اگر R0 بزرگتر از R1 است، 1 را به R1 اضافه کنيد.


SUBLT R1, #1             @ اگر R0 کوچکتر از R1 است، 1 را از R1 کسر کنيد.


B loop                        @شعبه را به عقب ببريد و loop را دوباره نصب کنيد.


انجام شد:


کار هاي ديگر را انجام دهيد.


آموزش تعميرات برد الکترونيکي يکي از دوره هاي پر متقاضي درمجتمع آموزشي فني سازان مي باشد.در تعميرات برد الکترونيکي با توجه به پيچيدگي و تنوع زياد اين نوع بردها نياز مبرم به تخصص مي باشد. لذا از اين رو مجتمع آموزشي فني سازان با استفاده از اساتيد مجرب و تجهيزات فوق مدرن تلاش نموده تا تمامي علاقه مند به اين رشته به صورت تخصصي تمامي مراحل آموزشي را طي نمايند تا کارآموزان در بازار کار از لحاظ تئوري و عملي کارآمد باشند.




مشخصات

تبلیغات

محل تبلیغات شما

آخرین ارسال ها

عکس آقای خامنه ای

آخرین جستجو ها

کابل شبکه ربات ساز استاد کريت Mary John Angie Ana Kathy مرجع مقالات رسمي سئو Anna Wes