نحوه ی نوشتن زبان اسمبلی

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

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

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

پیشنهاد ما: دوره آموزش plc صنعتی با 30 درصد تخفیف برای مدت زمان محدود به همراه اعطای مدرک معتبر فنی و حرفه ای

آموزش-plc-صنعتی

کد ماشین

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

 

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

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

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

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

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

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

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

یادمان    DESR، SRC2، SRC2

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

 

بخش 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 احتیاج داریم.

دستورالعمل بعدی می تواند از بخش 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

 

حرکت (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

 

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

بیت های آزمایشی (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

 

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

انتقال راست منطقی(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

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

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

BL      زیروال

    …

زیروال:

    …

    MOV    PC, LR

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

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

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

 

رجیستر بارگیری(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]

 

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

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

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

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

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

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

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

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

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

 

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

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

به دلیل اینکه در مقاله ی بعدی با اسمبل کننده 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 را دوباره نصب کنید.

انجام شد:

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

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

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

۱
۲
۳
۴
۵
میانگین امتیازات ۵ از ۵
از مجموع ۱ رای
guest
0 دیدگاه
بازخورد درون متنی
مشاهده همه نظرات