<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應用 > 建立一個AVR的RTOS(3)—GCC中對寄存器的分配與使用

          建立一個AVR的RTOS(3)—GCC中對寄存器的分配與使用

          作者: 時間:2016-12-03 來源:網(wǎng)絡(luò) 收藏
          第三篇:GCC中對寄存器的分配與使用

          在很多用于AVRRTOS中,都會有任務(wù)調(diào)度時,插入以下的語句:

          本文引用地址:http://www.ex-cimer.com/article/201612/325274.htm

          入棧:

          __asm__ __volatile__("PUSH R0 nt");

          __asm__ __volatile__("PUSH R1 nt");

          ......

          __asm__ __volatile__("PUSH R31 nt");

          出棧

          __asm__ __volatile__("POP R31 nt");

          ......

          __asm__ __volatile__("POP R1 nt");

          __asm__ __volatile__("POP R0 nt");

          通常大家都會認為,在任務(wù)調(diào)度開始時,當然要將所有的通用寄存器都保存,并且還應該保存程序狀態(tài)寄存器SREG。然后再根據(jù)相反的次序,將新任務(wù)的寄存器的內(nèi)容恢復。

          但是,事實真的是這樣嗎?如果大家看過陳明計先生寫的small rots51,就會發(fā)現(xiàn),它所保存的通用寄存器不過是4組通用寄存器中的1組。

          在Win AVR中的幫助文件avr-libc Manual中的Related Pages中的Frequently Asked Questions,其實有一個問題是"What registers are used by the C compiler?"回答了編譯器所需要占用的寄存器。一般情況下,編譯器會先用到以下寄存器

          1 Call-used registers (r18-r27, r30-r31):調(diào)用函數(shù)時作為參數(shù)傳遞,也就是用得最多的寄存器。

          2 Call-saved registers (r2-r17, r28-r29):調(diào)用函數(shù)時作為結(jié)果傳遞,當中的r28和r29可能會被作為指向堆棧上的變量的指針。

          3 Fixed registers (r0, r1):固定作用。r0用于存放臨時數(shù)據(jù),r1用于存放0。

          還有另一個問題是"How to permanently bind a variable to a register?",是將變量綁定到通用寄存器的方法。而且我發(fā)現(xiàn),如果將某個寄存器定義為變量,編譯器就會不將該寄存器分配作其它用途。這對RTOS是很重要的。

          在"Inline Asm"中的"C Names Used in Assembler Code"明確表示,如果將太多的通用寄存器定義為變量,剛在編譯的過程中,被定義的變量依然可能被編譯器占用。

          大家可以比較以下兩個例子,看看編譯器產(chǎn)生的代碼:(在*.lst文件中)

          第一個例子:沒有定義通用寄存器為變量

          #include

          unsigned char add(unsigned char b,unsigned char c,unsigned char d)

          {

          return b+c*d;

          }

          int main(void)

          {

          unsigned char a=0;

          while(1)

          {

          a++;

          PORTB=add(a,a,a);

          }

          }

          在本例中,"add(a,a,a);"被編譯如下:

          mov r20,r28

          mov r22,r28

          mov r24,r28

          rcall add

          第二個例子:定義通用寄存器為變量

          #include

          unsigned char add(unsigned char b,unsigned char c,unsigned char d)

          {

          return b+c*d;

          }

          register unsigned char a asm("r20"); //將r20定義為變量a

          int main(void)

          {

          while(1)

          {

          a++;

          PORTB=add(a,a,a);

          }

          }

          在本例中,"add(a,a,a);"被編譯如下:

          mov r22,r20

          mov r24,r20

          rcall add

          當然,在上面兩個例子中,有部份代碼被編譯器優(yōu)化了。

          通過反復測試,發(fā)現(xiàn)編譯器一般使用如下寄存器:

          第1類寄存器,第2類寄存器的r28,r29,第3類寄存器

          如在中斷函數(shù)中有調(diào)用基它函數(shù),剛會在進入中斷后,固定地將第1類寄存器和第3類寄存器入棧,在退出中斷又將它們出棧。



          關(guān)鍵詞: AVRRTOSGCC寄存

          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();