اطلاعیه

Collapse
No announcement yet.

برنامه نویسی به زبان اسمبلی

Collapse
این موضوع برجسته شده است.
X
X
 
  • فیلتر
  • زمان
  • Show
Clear All
new posts

    پاسخ : برنامه نویسی به زبان اسمبلی

    دستور CPSE دو رجیستر را با هم مقایسه می کند و در صورت برابر بودن از روی دستور بعدی پرش می کند. اگر دو رجیستر برابر نباشند، اجرای دستور یک سیکل طول می کشد. در صورت برابری دو رجیستر و انجام عمل پرش هم اگر دستوری که از روی آن پرش می شود یک word باشد، اجرای دستور 2 سیکل و در صورتی که طول دستور بعدی دو word باشد، اجرای دستور 3 سیکل طول می کشد.
    اوژن: به معنای افکننده و شکست دهنده است
    دانایی، توانایی است-Knowledge is POWER
    برای حرفه ای شدن در الکترونیک باید با آن زندگی کرد
    وضعمان بهتر می شود، اگر همه نسبت به جامعه و اطراف خود مسوول باشیم و نگوئیم به ما چه
    قوی شدن و خوب ماندن - خوبی کردن به دیگران یک لذت ماندگار است
    اگر قرار باشد نفت و منابع خام را بدهیم و چرخ بگیریم، بهتر است چرخ را از نو اختراع کنیم
    ساعت کار بدن اکثر انسان ها کمتر از 800000 ساعت است و بعد از آن از کار می افتد

    دیدگاه


      پاسخ : برنامه نویسی به زبان اسمبلی

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

      دیدگاه


        پاسخ : برنامه نویسی به زبان اسمبلی

        نوشته اصلی توسط شهریار رجب زاده
        همیشه یه سوال تو ذهنم بوده اینکه ما که با C برنامه مینویسیم این همه غلط داریم میشینیم با سختی مشکل رو بر طرف میکنیم اونوقت شما با اسمبلی چی کار میکنید؟از دیباگر استفاده میکنید؟
        من تازه شروع کردم ولی وقتی دارم اسمبلی مینویسم مثله اینکه که توی ذهنم دارم کد هارو شیبه سازی میکنم.
        یادش بخیر یه وقتایی هر روز میومدم اینجا !

        دیدگاه


          پاسخ : برنامه نویسی به زبان اسمبلی

          با سلام
          بعد از کلی درگیری تونستم اسمبلی بنویسم . داشتم با مثال های کوچک دستورها را تمرین میکردم که گفتم بهتره این کد ها را توی انجمن بزارم،هم دوستان استفاده کنند و هم اساتید نظرشون را در مورد کد ها بیان کنند.

          همه ی کد ها را روی میکروی MEGA32 نوشتم.


          1-تولید پالس از پایه ی PORTA,0
          (T=~3mS)


          کد:
          .ORG 0
          .INCLUDE "M32DEF.INC"
          LDI R16,HIGH(RAMEND)
          OUT SPH,R16
          LDI R16,LOW(RAMEND)
          OUT SPL,R16
          LDI R16,$FF
          OUT DDRA,R16
          OUT DDRB,R16
          LOOP:
          SBI PORTA,0
          CALL DELAY
          CBI PORTA,0
          CALL DELAY
          RJMP LOOP
          
          DELAY:
          LDI R17,0
          T:
          NOP 
          INC R17
          CPI R17,250
          BREQ M
          RJMP T 
          M:
          RET


          کد اصلاح شده:
          کد:
          .ORG 0
          .INCLUDE "M32DEF.INC"
          LDI R16,HIGH(RAMEND)
          OUT SPH,R16
          LDI R16,LOW(RAMEND)
          OUT SPL,R16
          LDI R16,$FF
          OUT DDRA,R16
          OUT DDRB,R16
          LOOP:
          SBI PORTA,0
          CALL DELAY
          CBI PORTA,0
          CALL DELAY
          RJMP LOOP
          
          DELAY:
          LDI R17,0
          T:
          NOP
          INC R17
          CPI R17,250
          BRNE T
          RET
          یادش بخیر یه وقتایی هر روز میومدم اینجا !

          دیدگاه


            پاسخ : برنامه نویسی به زبان اسمبلی

            بجای LDI R16,$ff می توانید از دستور SER R16 و بجای LDI R17,$00 می توانید از دستور CLR R17 استفاده کنید. همچنین بخش آخر برنامه هم می تواند به شکل زیر نوشته شود ( صرف نظر از زمان بندی برنامه):

            کد:
            T:
            NOP
            INC R17
            CPI R17,250
            BRNE T
            RET
            اوژن: به معنای افکننده و شکست دهنده است
            دانایی، توانایی است-Knowledge is POWER
            برای حرفه ای شدن در الکترونیک باید با آن زندگی کرد
            وضعمان بهتر می شود، اگر همه نسبت به جامعه و اطراف خود مسوول باشیم و نگوئیم به ما چه
            قوی شدن و خوب ماندن - خوبی کردن به دیگران یک لذت ماندگار است
            اگر قرار باشد نفت و منابع خام را بدهیم و چرخ بگیریم، بهتر است چرخ را از نو اختراع کنیم
            ساعت کار بدن اکثر انسان ها کمتر از 800000 ساعت است و بعد از آن از کار می افتد

            دیدگاه


              پاسخ : برنامه نویسی به زبان اسمبلی

              2-تقسیم R17/R18 (البته این تقسیم فقط واسه اعداد بخش پذیر هستش )

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

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


              R17=15
              R18=3
              R17/R18=


              کد:
              .ORG 0
              .INCLUDE "M32DEF.INC"
              SER R16
              OUT DDRA,R16
              LOOP:
              LDI R17,15
              LDI R18,3
              CLR R16
              LOOP2:
              INC R16
              SUB R17,R18
              CPI R17,0
              BREQ M
              RJMP LOOP2
              M:
              OUT PORTA,R16
              RJMP LOOP
              یادش بخیر توی بسکام همه چیزو روی LCD نشون میدادیم. الان رو LED !



              یادش بخیر یه وقتایی هر روز میومدم اینجا !

              دیدگاه


                پاسخ : برنامه نویسی به زبان اسمبلی

                با سلام
                ببخشید اگه میشه در مورد برنامه ترکیبی از c و اسمبلی توضیح بدید آیا میشه که مثلا تابع lcd رو از داخل یک برنامه اسمبلی فراخونی کرد این به خاطر این میپرسم که یک سورس به زبان اسمبلی دارم میخوام مقادیر ش رو با استفاده از توابع کتابخانه ای آمده روی lcd نشون بدم ، یکسری مطالب توی avr034 خوندم اما روند کلی کار دستم نیومد
                راستی اگه میشه یک خورده هم در مورد فرمت برنامه نویسی اسمبلی در کامپایلر iar توضیح بدید
                ممنون

                دیدگاه


                  پاسخ : برنامه نویسی به زبان اسمبلی

                  آقای طراح من در انجام تقسیم دچار مشکل شدم و نمیدونم چجوری اعداد اعشاری را تقسیم کنم.اگه در این مورد توضیح بدین ممنون میشم البته یه کمی هم در مورد ذخیره اعداد اعشاری در اسمبلی بگین.
                  برای روتین های اسمبلی تقسیم می توانید به بخش AVR assembler libraries در لینک زیر مراجعه کنید:

                  http://elm-chan.org/cc_e.html

                  درباره اعداد اعشاری هم اگر بخواهید وارد مباحث ذخیره اعداد بصورت ممیز ثابت و ممیز شناور شوید که جزئیات پیچیده ای دارند. اما در شرایطی که تعداد اعداد بعد از ممیز ثابت باشند، یک روش نسبتا ساده این است که از بحث ممیز صرف نظر کنید و اعداد را بصورت صحیح در نظر بگیرید و تنها در هنگام نمایش عدد، ممیز را نمایش دهید. مثلا بجای ضرب عدد 2.1 در 1.1 مقادیر 21 را 11 ضرب کنید و در موقع نمایش دو رقم آخر را بعد از ممیز نمایش بدهید و بجای نمایش 231 عدد 2.31 را نمایش دهید.

                  اگه میشه در مورد برنامه ترکیبی از c و اسمبلی توضیح بدید آیا میشه که مثلا تابع lcd رو از داخل یک برنامه اسمبلی فراخونی کرد این به خاطر این میپرسم که یک سورس به زبان اسمبلی دارم میخوام مقادیر ش رو با استفاده از توابع کتابخانه ای آمده روی lcd نشون بدم ، یکسری مطالب توی avr034 خوندم اما روند کلی کار دستم نیومد
                  راستی اگه میشه یک خورده هم در مورد فرمت برنامه نویسی اسمبلی در کامپایلر iar توضیح بدید
                  صدا زدن روتین های اسمبلی از داخل برنامه C امری کاملا ممکن است که نمونه آن در AVR1300 وجود دارد.اما برای روال برعکس آن یعنی صدا زدن تابع c از درون اسمبلی نمونه ای ندیده ام. در این رابطه یک فایل 122 صفحه ای نسبتا مفصل در بخش Help در IAR وجود دارد که می توانید به آن مراجعه کنید.
                  اوژن: به معنای افکننده و شکست دهنده است
                  دانایی، توانایی است-Knowledge is POWER
                  برای حرفه ای شدن در الکترونیک باید با آن زندگی کرد
                  وضعمان بهتر می شود، اگر همه نسبت به جامعه و اطراف خود مسوول باشیم و نگوئیم به ما چه
                  قوی شدن و خوب ماندن - خوبی کردن به دیگران یک لذت ماندگار است
                  اگر قرار باشد نفت و منابع خام را بدهیم و چرخ بگیریم، بهتر است چرخ را از نو اختراع کنیم
                  ساعت کار بدن اکثر انسان ها کمتر از 800000 ساعت است و بعد از آن از کار می افتد

                  دیدگاه


                    پاسخ : برنامه نویسی به زبان اسمبلی

                    با سلام.

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

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

                    دوم اینکه در صورتی که به این روال پارامتری پاس میشه بایستی طبق قواعد بازی کامپایلر مربوطه کار کنین. مثلا در WinAVR پارامتر اول اگر 2 بایتی باشه در r25:r24 پاس میشه.

                    سوم اینکه به مانند زمانی که از روال اسمبلی به C برمیگردیم؛ در هنگام صدا کردن روال C باید شرایطی لحاظ بشه که پیش فرض های کامپایلر با اون تناقضی نداشته باشه. مثلا رجیستر r1 حتما مقدار صفر داشته باشه.

                    چهارم اینکه حواسمون باشه که بعضی از روال ها ممکنه حاوی کد هایی باشند که مقادیر یک سری رجیستر ها رو تغییر بده. مسئولیت حفظ مقدار این رجیستر ها قبل و بعد از فراخوانی تابع به عهده خودتونه. مثلا اگر تابعی داریم که بصورت زیر تعریف شده:


                    کد:
                    void test(void);


                    با اینکه هیچ مقداری برنمیگردونه و هیچ پارامتری هم برایش ارسال نمیشه اما دلیلی وجود نداره که مقادیر رجیستر های r25 , r24 در اون تغییر نکنه.

                    و ایضا یک مورد بسیار مهم:
                    در بعضی کامپایلر ها اگر سورس شما در یک فایل cpp باشه و کامپایلر شما هم ++C باشه ممکنه تمامی شرایط فوق برقرار باشه ولی باز هم در زمان link خطای نشناختن اون تابع رو بده. چون برای پیاده سازی مکانیسم های overloading در ++C کامپایلر ها از مکانیسمی به نام name mangling استفاده میکنن که مثلا تابع فوق به نامی مشابه test$qv تبدیل میشه و در روال اسمبلی بایستی به این نام ارجاع داده بشه و نه test.

                    برای پرهیز از این دردسر بهتره (حتی اگر از حالت ++C استفاده نمیکنین) تمامی توابع غیر static تون رو بصورت زیر در هدر مربوطه تعریف کنین:


                    کد:
                    #ifdef __cplusplus
                    extern "C" {
                    #endif
                    
                    void test(void);
                    
                    #ifdef __cplusplus
                    };
                    #endif


                    این به کامپایلر متذکر میشه که با این تابع؛ مشابه حالتی که با یک تابع C برخورد میکرد؛ برخورد کنه.

                    دیدگاه


                      پاسخ : برنامه نویسی به زبان اسمبلی

                      ممنون از پاسختون اما برای من کلاس اولی فهمش خیلی مشکله

                      اول اینکه روالی که میخوایین صداش کنین نبایستی static معرفی شده باشه. چون روالهایی که static معرفی میشن (بطور عام) در فایل .obj نهایی آدرسشون قید نمیشه و نتیجتا از obj های دیگه قابل دسترسی نیستن.
                      روال نباید static باشه یعنی چی ؟ اگه میشه یک تابع نمونه مثال بزنید

                      دوم اینکه در صورتی که به این روال پارامتری پاس میشه بایستی طبق قواعد بازی کامپایلر مربوطه کار کنین. مثلا در WinAVR پارامتر اول اگر 2 بایتی باشه در r25:r24 پاس میشه.
                      خوب من توی یکی از appnote ها در این مورد این جدول رو دیدم منظورتون همینه ؟

                      زمانی که یک تابع فراخوانی می شود مقادیر ورودی تابع در رجیسترهای R16-R23 متناسب با اندازه مقادیر قرار میگیرند . و زمانی هم که یک تابع یک مقدار را برمیگرداند آن مقدار در داخل رجیستر های R16-R19 متناسب با اندازه مقداربرگشتی از تابع قرار می گیرد از این رو میتوان نتیجه گرفت حداکثر خروجی یک تابع 4 بایت می باشد .

                      در جدول زیر نحوه قرار گیری ورودی های یک تابع در رجیسترهای R16-R23 متناسب با اندازه ورودی ها در هنگام فراخوانی توابع نشان داده شده است :


                      سوم اینکه به مانند زمانی که از روال اسمبلی به C برمیگردیم؛ در هنگام صدا کردن روال C باید شرایطی لحاظ بشه که پیش فرض های کامپایلر با اون تناقضی نداشته باشه. مثلا رجیستر r1 حتما مقدار صفر داشته باشه.

                      چهارم اینکه حواسمون باشه که بعضی از روال ها ممکنه حاوی کد هایی باشند که مقادیر یک سری رجیستر ها رو تغییر بده. مسئولیت حفظ مقدار این رجیستر ها قبل و بعد از فراخوانی تابع به عهده خودتونه
                      نمیشه مقدار رجیستر ها یی که در برنامه اسمبلی مون استفاده کردیم قبل از فراخوانی پوش کنیم و زمان برگشت از تابع اون ها رو (بییییب)

                      در بعضی کامپایلر ها اگر سورس شما در یک فایل cpp باشه و کامپایلر شما هم ++C باشه ممکنه تمامی شرایط فوق برقرار باشه ولی باز هم در زمان link خطای نشناختن اون تابع رو بده. چون برای پیاده سازی مکانیسم های overloading در ++C کامپایلر ها از مکانیسمی به نام name mangling استفاده میکنن که مثلا تابع فوق به نامی مشابه test$qv تبدیل میشه و در روال اسمبلی بایستی به این نام ارجاع داده بشه و نه test.

                      برای پرهیز از این دردسر بهتره (حتی اگر از حالت ++C استفاده نمیکنین) تمامی توابع غیر static تون رو بصورت زیر در هدر مربوطه تعریف کنین
                      توی avr034 یک مثالی در این رابطه زده و فکر میکنم این کدی که شما فرمودین رو توش لحاظ کرده البته نمیدونم من درست متوجه شدم که اون چی گفته یا نه به خاطر همون چیزی رو که از اون قسمت فهمیدم این جا میزارم به همراه کد نمونه ای که قرار داده بود ، نمیشه از همین ایده گرفت ؟

                      3. فراخوانی توابع C در برنامه نوشته شده به زبان اسمبلی :

                      فرض کنیم که در یک برنامه نوشته شده به زبان اسمبلی تابع ()rand از داخل کتابخانه استاندارد C فراخوانی میشود و یک عدد به صورت رندم بوسیله این تابع روی PORTB به نمایش در میآید . تابع rand() یک مقدار 2 بایتی را برمیگرداند که در مثال زیر 8 بیت پایین این 16 بیتی بر روی PORTB به نمایش در می آید .


                      NAME get_port
                      #include "ioavr.h" ; The #include file must be within the module
                      EXTERN rand, max_val ; External symbols used in the function
                      PUBLIC get_port ; Symbols to be exported to C function
                      RSEG CODE ; This code is relocatable, RSEG
                      get_port: ; Label, start execution here
                      clr R16 ; Clear R16
                      sbis PIND,0 ; Test if PIND0 is 0
                      rcall rand ; Call RAND() if PIND0 = 0
                      out PORTB,R16 ; Output random value to PORTB
                      lds R17,max_val ; Load the global variable max_val
                      cp R17,R16 ; Check if number higher than max_val
                      brlt nostore ; Skip if not
                      sts max_val,R16 ; Store the new number if it is higher
                      nostore:
                      ret ; Return
                      END


                      باز هم از توجهتون ممنونم

                      دیدگاه


                        پاسخ : برنامه نویسی به زبان اسمبلی

                        روال نباید static باشه یعنی چی ؟
                        مثلا فرض کنین پروژه ما از چند سورس مجزا (که include نشن و جدا گانه کامپایل بشن) تشکیل شده. در این حالت object های هر سورس بعد از کامپایل شدن در فاز لینک بهم وصل میشن تا فایل نهایی رو تولید کنن. در این حالت اگر متغیر عمومی یا تابعی بصورت static معرفی بشه (البته طبق قواعد عمومی زبان C) دیگه به اسم خودش در object نهایی معرفی نمیشه. یعنی نمیشه از object های دیگه شناسایی بشه و نتیجتا قابل صدا کردن هم نیست:


                        کد:
                        file main.c:
                        
                        void main(void)
                        {
                          func1_in_test_c();
                          wait_for_response();
                        }
                        
                        
                        file test.c
                        
                        void func1_in_test_c(void)
                        {
                        }
                        
                        
                        file uart.c
                        
                        static void wait_for_response(void)
                        {
                        }
                        
                        --------
                        
                        a part of project map file
                        
                         .text     0x000000a4    0xa main.o
                                0x000000a4        main
                         .text     0x000000ae    0x2 test.o
                                0x000000ae        func1_in_test_c
                         .text     0x000000b0    0x0 uart.o
                         .text     0x000000b0    0x0 c:/winavr/bin/../lib/gcc/avr/4.3.3/avr5\libgcc.a(_exit.o)
                                0x000000b0        . = ALIGN (0x2)
                        
                        
                        --------
                        
                        compile error
                        
                        Z:\Projects\test\test\default/../main.c:8: undefined reference to `wait_for_response'



                        اگر توجه کنین میبینین که با اینکه تمامی توابع در پروژه موجوده و کامپایلر WinAVR خطا میده که نماد wait_for_response رو نمیشناسه. این بخاطر استفاده از لغت static در هنگام نوشتن تابع هست که به کامپایلر حالی میکنه که object نهایی نباید حاوی اسم این تابع باشه.

                        ----

                        خوب من توی یکی از appnote ها در این مورد این جدول رو دیدم منظورتون همینه ؟
                        ممکنه. اما این جدول متعلق به WinAVR نیست. چون این کامپایلر آرگومانها رو با r24 و r25 به پایین به تابع فراخوانی شده اطلاع میده.

                        ----

                        نمیشه مقدار رجیستر ها یی که در برنامه اسمبلی مون استفاده کردیم قبل از فراخوانی پوش کنیم و زمان برگشت از تابع اون ها رو پوپ
                        چرا! دقیقا هم باید همین کارو بکنین. اما نه همیشه. مثلا در WinAVR فرض بر اینه که r25:r24 ممکنه در یک تابع خراب بشه بنابراین حواسش هست که در فراخوانی یک تابع اگر به مقادیر این رجیستر ها احتیاج باشه (البته بعد از برگشت از تابع فراخوانی شده) یا مقدارشون رو push/pop میکنه و یا در یک رجیستری که دست نمیخوره جاشون میده. بنا براین اگر قراره این دو رجیستر (در WinAVR البته) استفاده بشه احتیاجی به push/pop نیست چون کامپایلر اینو حالیش نیست. ولی مثلا r10 رو باید حتما push/pop کنین. اما push/pop های بیخودی هم وقت میکرو رو تلف میکنه و هم حافظه مصرفی برنامه رو بالا میبره. پس دقت کنین.

                        ----

                        فرض کنیم که در یک برنامه نوشته شده به زبان اسمبلی تابع ()rand از
                        اینجا چیز زیادی نمیتونم بگم جز اینکه انشالله حواستون جمع هست که rcall فقط موقعی بدرد میخوره که فاصله بین جایی که تابع داره صدا زده میشه و خود تابع حداکثر 2 کیلو ورد باشه. اگر این دستور رو بطور عام استفاده کنین؛ و این فاصله بیش از این باشه؛ در زمان link ممکنه ایراد بگیره و link نکنه یا (برای یک کامپایلر شوت!!) کد عوضی تولید کنه.

                        ---
                        ضمنا!
                        لغت pop؛ پاپ تلفظ میشه و تلفظ به این فرمی که شما انجام میدین لغت زشتیه. با عرض معذرت.

                        دیدگاه


                          پاسخ : برنامه نویسی به زبان اسمبلی

                          با سلام.
                          در سری Mega AVR دستورات اسمبلی SBI ، CBI و SBIC , ... روی 32 آدرس اول رجیسترهای I/O عمل میکردند. فکر میکنم برد آدرس این دستورات در سری Xmega بیشتر باشه . اینطور نیست؟ اگر دوستان در این مورد توضیح بدن ممنون میشم.

                          دیدگاه


                            پاسخ : برنامه نویسی به زبان اسمبلی

                            در خانواده های AVR و XMEGA در عملکرد دستورات فوق از نظر محدوده آدرس، تفاوتی وجود ندارد.
                            اوژن: به معنای افکننده و شکست دهنده است
                            دانایی، توانایی است-Knowledge is POWER
                            برای حرفه ای شدن در الکترونیک باید با آن زندگی کرد
                            وضعمان بهتر می شود، اگر همه نسبت به جامعه و اطراف خود مسوول باشیم و نگوئیم به ما چه
                            قوی شدن و خوب ماندن - خوبی کردن به دیگران یک لذت ماندگار است
                            اگر قرار باشد نفت و منابع خام را بدهیم و چرخ بگیریم، بهتر است چرخ را از نو اختراع کنیم
                            ساعت کار بدن اکثر انسان ها کمتر از 800000 ساعت است و بعد از آن از کار می افتد

                            دیدگاه


                              پاسخ : برنامه نویسی به زبان اسمبلی

                              درود

                              دوستان میشه لطف کنن یه توضیحی در مورد این دستورات بدن؟:(مربوط به USART)
                              کد:
                              ; Enable receiver and transmitter
                              ldi r16, (1<<RXENn)|(1<<TXENn)
                              out UCSRnB,r16
                              ; Set frame format: 8data, 2stop bit
                              ldi r16, (1<<USBSn)|(3<<UCSZn0)
                              out UCSRnC,r16

                              اینکه این شیفت یه چپ چجوری بیت رو ست میکنه؟

                              سپاس

                              دیدگاه


                                پاسخ : برنامه نویسی به زبان اسمبلی

                                هر کدوم از بیت های رجیستر ها داخل فایل هدر هر میکرو تعریف شده و معادل یه عدد هست از 0 تا 7 به این شکل :
                                SFR_B_N(0x0A,UCSRB,RXCIE,TXCIE,UDRIE,RXEN,TXEN,UCS Z2,RXB8,TXB8)
                                (البته این برای مگا 16 هست)
                                حالا تو اینجا میشه با استفاده از این تعاریف برای واضح تر شدن برنامه برای مراجعات بعدی بجای عدد از اینها استفاده کرد به این ترتیب مثلا تو برنامه شما بیت های 3 و 4 رجیستر UCSRB یک میشه به این ترتیب که اول میاد مقدار 1 رو از بیت صفرم به سمت چپ به اندازه 3 تا بیت و بعد دوباره از صفر به اندازه 4 بیت شیفت داده میشه که نتیجه اون میشه یک شدن توام بیت 3 و 4
                                و یا در ادامه برنامه بیت های USBS,UCSZ1,UCSZ0 یک میشن به این ترتیب که اول یه یک به اندازه شماره بیت USBS از بیت صفرم به سمت چت تا بیت معادل USBS شیفت داده میشه و بعد عدد 3 (به باینری 11) از بیت صفرم به سمت چپ از به اندازه بیت معادل UCSZ0 شیفت داده میشه که نتیجه اون یک شدن بیت معادل UCSZ0 و بیت بعدیش یعنی UCSZ1 هست.

                                دیدگاه

                                لطفا صبر کنید...
                                X