14-01-2020, 02:06 AM
برنامهای که به زبان اسمبلی نوشته شده باشد عملا متشکل از یک سری خطوط پشت سر هم است. هریک از این خطوط شامل یکی از دستورات اسمبلی است. به طور کلی هر دستور اسمبلی از چهار بخش تشکیل شده است که عبارتند از: برچسب، کلمه ی اختصاری، عملوند و توضیح (یا کامنت).
برچسب (label)
گاهی در برنامه نویسی نیاز است که به خطی از برنامه برگردیم و آن را اجرا کنیم. برای این که بتوانیم این کار را انجام دهیم از برچسب استفاده می کنیم. به این صورت که به هر خطی که می خواهیم یک برچسب اختصاص می دهیم و در صورت نیاز برای مراجعه به آن خط از برچسب تعریف شده برای آن خط استفاده می کنیم. فیلد مربوط به برچسب نمی تواند از تعداد مشخصی کاراکتر بیشتر باشد. به عنوان مثال در شکل بالا به خط سوم برنامه برچسبی تحت عنوان SetupP1 اختصاص داده شده است.
کلمات اختصاری یا دستورات ماشین (Mnemonic) و عملوندها (Operands)
یک دستور در زبان اسمبلی یک کلمه ی اختصاری است که برای کاری در نظر گرفته شده است و دارای یک یا چند عملوند است. عملوند به واحد داده ای است که طبق دستور داده شده پردازش می شود. این کلمات اختصاری یا همان فرمان ها هستند که به CPU می گویند با عملوندها چه کنند. بنابراین عملاً دستورها و عملوندها هستند کار واقعی برنامه ی اسمبلی را انجام می دهند. در شکل بالا یک کلمه ی اختصاری (که در اینجا دستور jmp می باشد) و همچنین عملوندها نشان داده شده اند.
کد عمل یا opcode چیست؟ هر دستور (یا کلمه ی اختصاری) در زبان اسمبلی دارای یک کد است. اسمبلر هنگام تبدیل کد اسمبلی به زبان ماشین به جای یک دستور کد آن دستور را قرار می دهد. به این کد که در اختیار CPU قرار می گیرد کد دستور یا opcode می گویند.
شبه دستور یا دستورالعمل (Assembler Directive) چیست؟ دستورالعمل ها یا همان شبه دستورات، اسمبلر را هدایت می کنند. دستورالعمل ها فقط توسط اسمبلر به کار گرفته می شوند. نمونه ای از شبه دستورات، دستورالعمل .ORG است که به اسمبلر می گوید که کد عمل را در خانه ی صفر حافظه قرار دهد.
آیا شبه دستورات نیز مانند دستورات دارای کد عمل هستند؟ خیر، چون شبه دستورات فقط وظیفه ی هدایت اسمبلر را بر عهده دارند و قرار نیست که برای ماشین ترجمه شوند.
توضیح یا comment:
این فیلد با نقطه ویرگول ( شروع میشود و اختیاری است. نوشتن کانت به برنامه نویسان توصیه می شود تا دیگر افراد بتوانند برنامه را به راحتی خوانده و آن را خوب بفهمند. لازم به ذکر است که اسمبلر فیلد توضیح را نادیده می گیرد.
همانطور که گفته شد برای نوشتن برنامه به زبان اسمبلی نیاز است تا با ساختار حافظه ، ثبات ها و معماری cpu موجود و نقش هر کدام در پردازش داده آشنا شویم.
Avr ثبات های زیادی برای انجام محاسبات و عملیات منطقی دارد.در cpu، ثبات ها برای ذخیره سازی موقت اطلاعات بکار می روند.این اطلاعات میتواند یک بایت داده و یا آدرسی که به داده مورد نیاز اشاره می کند باشد.اکثر ثبات ها در avr هشت بیتی هستند.
در avr 32 ثبات همه منظوره وجود دارد، ثبات های همه منظوره همانند انباره در دیگر میکرو پروسسورها عمل میکند یعنی برای انجام محاسبات و عملیات منطقی به کار می روند.در avr ثبات های همه منظوره که پایین ترین مکان حافظه را به خود اختصاص داده اند R0 تا R31 نام دارند و بدون توجه به نوع تراشه AVR همیشه آدرس خانه های ۰۰ تا ۱F هگز را به خود اختصاص داده اند.
در این جا با شروع توضیح در مورد دستورات اسمبلی با نحوه کار با ثبات ها آشنا می شوید.
دستورهای مهم اسمبلی در AVR
۱-دستور (ldi(load with immediate:
از این دستور برای بارگذاری یک داده هشت بیتی در یک ثبات همه منظوره استفاده می شود.کلمه immediate بر بی واسطه بودن دلالت می کند.این دستور مقدار عملوند سمت راست را در عملوند سمت چپ کپی می کند.
فرمت کلی آین دستور به این شکل است
;Ldi Rd,k
در این دستور k یک مقدار ۸ بیتی بین ۰ تا ۲۵۵ دهدهی یا ۰۰ تا FF شانزدهی می باشد. Rd هر یک از ۱۶ ثبات R16 تا R31 می تواند باشد. از این دستور نمیتوان برای مقداردهی ثبات های R0 تا R15 استفاده کرد. مثال:
LDI R16,0x0F;R16=0x0F
LDI R17,0x38;R16=0x38
LDI R19,67;R16=67
LDI R21,0b11001100;R16=0b11001100
در اسمبلی برای نوشتن توضیحات از علامت “;” استفاده می کنیم.این علامت مانند علامت”//” در زبان C عمل می کند که باعث می شود توضیحات از کد موجود در آن خط تفکیک شود.
نکته ها:
الف:اگر عددی بر مبنای شانزده باشد باید علامت دلار($) و یا مقدار ۰x را درابتدای آن قرار دهیم.اگر چیزی در ابتدای عدد نگذاریم آن عدد مبنای ده در نظر گرفته می شود.
ب:اگر مقدار ۰ تا F در یک ثبات هشت بیتی ریخته شود بقیه بیت ها صفر در نظر گرفته می شود.به عنوان نمونه در مثال اول R16=00001111 می شود.
ج:انتقال مقادیر بیش از ۲۵۵(۰xFF )به ثبات های همه منظوره خطا ایجاد می کند.
د:برای نوشتن عدد به فرمت دودویی باید ابتدای آن ۰b بگذاریم.
۲- دستور ADD
این دستور محتوای دو ثباث را باهم جمع کرده و نتیجه را در عملوند سمت چپ(ثبات مقصد) قرار می دهد. فرمت کلی این دستور به این شکل است:
ADD Rd,Rr ;Rd=Rd+Rr
مثال:
LDI R16,0x65 ;R16=0x65
LDI R17,0x43 ;R17=0x43
ADD R16,R17 ;R16=0x65+0x43=0xA8
لازم به ذکر است که این دستور پرچمهای وضعیت را تحت تآثیر قرار می دهد. در این مثال C=0،N=1،Z=0 میشود.
۳- دستور( LDS(Load direct from data space:
با استفاده از این دستور می توانیم یک بایت را از آدرسی در حافظه داده در یک ثبات همه منظوره کپی کنیم.
فرمت کلی دستور به این شکل است: LDS RD,K
در اینجا K یک آدرس از ۰x000 تا ۰xFFFF و RD یکی از ثبات های همه منظوره است.خانه حافظه داده می تواند در هر قسمتی از فضای داده قرار گرفته باشد.
مثال: در این مثال محتویات خانه داده با آدرس ۰x210 در ثبات R5 قرار می گیرد. LDS R5,0x210
LDS R16,0x01 ;R16=R1
LDS R18,0x3F ;R18=SREG
در مثال سوم ۰X3F آدرس ثبات وضعیت(sreg) در حافظه داده است که در محدوده SFR قرار گرفته.
۴-دستور (STS(stor direct to data space:
فرمت کلی این دستور به این شکل است: STS K,Rr
این دستور درست برعکس دستور LDS عمل می کند و محتویات یک ثبات همه منظوره (Rr) را در یک خانه حافظه داده با آدرس مشخص شده(k) قرار می دهد.این آدرس هر جایی از حافظه داده می تواند باشد.
مثال:
;STS ۰x38,R18
;STS ۰x32,R17
در این مثال ۰x38 آدرس پورت B و ۰x32 آدرس پورت D در خانه حافظه داده می باشد.بنابراین پس از اجرای این دستورات مقدار پورت B برابر R18 و مقدار پورت D برابر R17 می شود.
۵- دستور(IN(IN from i/o location:
بوسیله این دستور cpu یک بایت از یک ثبات i/o را در یک ثبات همه منظوره کپی می کند. فرمت این دستور به این شکل است: IN Rd,A لازم به ذکر است که در AVR هر خانه حافظه i/o علاوه بر آدرس حافظه داده دارای یک آدرس اختصاصی مخصوص به ثبات های i/o می باشد که یک آدرس نسبی در مقایسه با شروع حافظه i/o است.در اینجا A همان آدرس اختصاصی است که به آن آدرس i/o می گویند
برای سهولت کار با ثبات های i/o می توان از نام آنها به جای آدرس استفاده کرد.البته نسبت دهی نام به آدرس قبلا باید تعریف شده باشد که دراین مورد در آینده صحبت خواهد شد. مثال:
IN R16,0x10 == IN R16,PIND
برتری های دستور IN نسبت به LDS: الف:CPU دستور IN را سریعتر از LDS اجرا میکند.چون دستورIN یک چرخه ماشین طول می کشد درحالی که LDS دوچرخه ماشین طول می کشد. ب: پهنای دستور IN دو بایت است درحالی که پهنای دستور LDS 4 بایت است.پس دستور LDS فضای بیشتری از ROM را میگیرد. ج:در استفاده از دستور IN می توانیم از نام ثبات های I/O هم استفاده کنیم. د: دستور IN در تمامی AVR ها موجود است در حالی که دستور LDS در برخی AVR ها پیاده نشده است.
۶-دستور( OUT(out to i/o location:
با این دستور می توان محتویات یک ثبات همه منظوره را در یک ثبات i/o کپی کرد. فرمت این دستور به این شکل است:OUT A,Rd هر آنچه که در مورد دستور IN گفته شد در مورد این دستور هم صدق می کند فقط این دستور برعکس دستور IN عمل می کند. مثال:برنامه زیر ثبات PIND را بر روی ثبات PORTA کپی می کند.
;IN R0,PIND
;OUT PORTA,R0
دستور MOV: این دستور داده را از یک ثبات همه منظوره به یک ثبات همه منظوره دیگر کپی میکند.
فرمت کلی این دستور به این شکل است
MOV Rd,Rr ;Rd=Rr
مثال :MOV R10,R20 ;R10=R20