久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

專注電子技術學習與研究
當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

一個從定時計數器賦初值引起的故事【原創】

作者:佚名   來源:本站原創   點擊數:  更新時間:2010年10月19日   【字體:

  最近單片機課講到了定時計數器,在C語言中定時計數器的初值可以采用這種方式(假設計數10000次)TH0=(65536-10000)/256;TL0=(65536-10000)%256;這是通用的方法,65536-10000=55536=0xD8F0;賦值后TH0=0xD8,TL0=0xF0。我聯想到補碼的規則,65536-10000的數值在計算機中和-10000數據存儲是一樣的,于是我就簡單賦值為TH0=(-10000)/256.;TL0=(-10000)%256;可以少寫一個數據,減少敲字的工作。我就這樣給學生講了。這兩種方法都可以。

   在一天李老師看到我的學生作業都是寫TH0=(-10000)/256.;TL0=(-10000)%256;她說-10000可能使用不對。當天晚上的時候在QQ上發消息過來說,經驗證,在Keil中,TH0=(65536-10000)/256;TL0=(65536-10000)%256;的賦值方式TH0=0xD8,TL0=0xF0。但是TH0=(-10000)/256.;TL0=(-10000)%256;的賦值方式TH0=0xD9,TL0=0xF0。TH0的數值總是要大1,而且取不同的數值驗證均是這個結果,兩種方式TH0總是相差1,而TL0數值是一樣的。我打開Keil,輸入程序,然后調試查看匯編指令,得到如下結果:

     8: TH0=(65536-10000)/256;
C:0x009B    758CD8   MOV      TH0(0x8C),#0xD8
     9:   TH1=(-10000)/256;
C:0x009E    758DD9   MOV      TH1(0x8D),#0xD9

發現匯編指令直接對于TH0和TH1進行賦值,沒有經過任何的運算,但是就是相差1,這是為什么呢?我無法理解,后來在百度知道上提問,得到的回答是:這個和默認數據類型有關,TH0=(65536-10000)/256,默認unsigned char,即TH0=0xD8;TH0=(-10000)/256,默認signed char,二進制最高位為符號位,負數為1,所以TH0=0xD9 。

原來是Keil編譯器計算數據的時候默認的數據類型不一樣,65536-10000=55536是unsigned類型,55536/256=216=0xD8,而-10000是signed類型,(-10000)/256=-39=0xD9。原來如此,Keil的編譯器預先處理的時候根據不同類型的數據進行了不同的運算,然后直接賦值。我又驗證了一下,TH0=(unsigned int)(-10000)/256;發現先把-10000強制轉換為unsigned類型后,得到的結果就是正確的了TH0=0xD8。得到答案后臉紅了,不過多虧是在放假期間,沒有學生看到。開學后立即在課堂上更正了。╮(╯▽╰)╭,這次糗大了。

    我重新寫了一個程序,#include<reg51.h>
void main()
{
unsigned int  i;
 unsigned char j;
 i= - 10000;
 j=i/256;

while(1)
 ;
}

中間加一個變量,看Keil會怎么處理,結果發現

     2: void main()
     3: { 
     4: unsigned int  i;
     5:  unsigned char j;
     6:  i=-10000;
C:0x000F    7ED8     MOV      R6,#0xD8
     7:  j=i/256;
     8: 
C:0x0011    8E08     MOV      0x08,R6
     9: while(1)
C:0x0013    80FE     SJMP     C:0013

還是直接賦值,編譯器太聰明了,知道80C51對于數據運算非常非常的不擅長,于是直接處理完數據,然后用賦值的方式來寫匯編的指令。而且還知道,i的低字節沒有用到,在指令里根本沒有出現,這也太聰明了吧。Keil軟件是最流行,最好用的編譯器,不是浪得虛名的。

我再修改:

include<reg51.h>
void main()
{
unsigned int  i;
 unsigned char j;
 i=-10000;
 i++;
 j=i/256;

while(1)
 ;
}

結果發現代碼只增加了一點。

         2: void main()
     3: { 
     4: unsigned int  i;
     5:  unsigned char j;
     6:  i=-10000;
C:0x0003    7FF0     MOV      R7,#B(0xF0)
C:0x0005    7ED8     MOV      R6,#0xD8
     7:  i++;
C:0x0007    0F       INC      R7
C:0x0008    BF0001   CJNE     R7,#0x00,C:000C
C:0x000B    0E       INC      R6
     8:  j=i/256;
     9: 
C:0x000C    8E08     MOV      0x08,R6
    10: while(1)
C:0x000E    80FE     SJMP     C:000E

但對于j的運算還是用賦值的方式。我再改,把i類型變成signed類型,結果大吃一驚:

include<reg51.h>
void main()
{
    int  i;
 unsigned char j;
 i=-10000;
 
 j=i/256;

while(1)
 ;
}

程序變得非常龐大,代碼從28B猛增到169B:

C:0x0000    02009D   LJMP     C:009D
                 C?SIDIV:
C:0x0003    C2D5     CLR      F0(0xD0.5)
C:0x0005    EC       MOV      A,R4
C:0x0006    30E709   JNB      0xE0.7,C:0012
C:0x0009    B2D5     CPL      F0(0xD0.5)
C:0x000B    E4       CLR      A
C:0x000C    C3       CLR      C
C:0x000D    9D       SUBB     A,R5
C:0x000E    FD       MOV      R5,A
C:0x000F    E4       CLR      A
C:0x0010    9C       SUBB     A,R4
C:0x0011    FC       MOV      R4,A
C:0x0012    EE       MOV      A,R6
C:0x0013    30E715   JNB      0xE0.7,C:002B
C:0x0016    B2D5     CPL      F0(0xD0.5)
C:0x0018    E4       CLR      A
C:0x0019    C3       CLR      C
C:0x001A    9F       SUBB     A,R7
C:0x001B    FF       MOV      R7,A
C:0x001C    E4       CLR      A
C:0x001D    9E       SUBB     A,R6
C:0x001E    FE       MOV      R6,A
C:0x001F    120039   LCALL    C?UIDIV(C:0039)
C:0x0022    C3       CLR      C
C:0x0023    E4       CLR      A
C:0x0024    9D       SUBB     A,R5
C:0x0025    FD       MOV      R5,A
C:0x0026    E4       CLR      A
C:0x0027    9C       SUBB     A,R4
C:0x0028    FC       MOV      R4,A
C:0x0029    8003     SJMP     C:002E
C:0x002B    120039   LCALL    C?UIDIV(C:0039)
C:0x002E    30D507   JNB      F0(0xD0.5),C:0038
C:0x0031    C3       CLR      C
C:0x0032    E4       CLR      A
C:0x0033    9F       SUBB     A,R7
C:0x0034    FF       MOV      R7,A
C:0x0035    E4       CLR      A
C:0x0036    9E       SUBB     A,R6
C:0x0037    FE       MOV      R6,A
C:0x0038    22       RET      
                 C?UIDIV:
C:0x0039    BC000B   CJNE     R4,#0x00,C:0047
C:0x003C    BE0029   CJNE     R6,#0x00,C:0068
C:0x003F    EF       MOV      A,R7
C:0x0040    8DF0     MOV      B(0xF0),R5
C:0x0042    84       DIV      AB
C:0x0043    FF       MOV      R7,A
C:0x0044    ADF0     MOV      R5,B(0xF0)
C:0x0046    22       RET      
C:0x0047    E4       CLR      A
C:0x0048    CC       XCH      A,R4
C:0x0049    F8       MOV      R0,A
C:0x004A    75F008   MOV      B(0xF0),#0x08
C:0x004D    EF       MOV      A,R7
C:0x004E    2F       ADD      A,R7
C:0x004F    FF       MOV      R7,A
C:0x0050    EE       MOV      A,R6
C:0x0051    33       RLC      A
C:0x0052    FE       MOV      R6,A
C:0x0053    EC       MOV      A,R4
C:0x0054    33       RLC      A
C:0x0055    FC       MOV      R4,A
C:0x0056    EE       MOV      A,R6
C:0x0057    9D       SUBB     A,R5
C:0x0058    EC       MOV      A,R4
C:0x0059    98       SUBB     A,R0
C:0x005A    4005     JC       C:0061
C:0x005C    FC       MOV      R4,A
C:0x005D    EE       MOV      A,R6
C:0x005E    9D       SUBB     A,R5
C:0x005F    FE       MOV      R6,A
C:0x0060    0F       INC      R7
C:0x0061    D5F0E9   DJNZ     B(0xF0),C:004D
C:0x0064    E4       CLR      A
C:0x0065    CE       XCH      A,R6
C:0x0066    FD       MOV      R5,A
C:0x0067    22       RET      
C:0x0068    ED       MOV      A,R5
C:0x0069    F8       MOV      R0,A
C:0x006A    F5F0     MOV      B(0xF0),A
C:0x006C    EE       MOV      A,R6
C:0x006D    84       DIV      AB
C:0x006E    20D21C   JB       OV(0xD0.2),C:008D
C:0x0071    FE       MOV      R6,A
C:0x0072    ADF0     MOV      R5,B(0xF0)
C:0x0074    75F008   MOV      B(0xF0),#0x08
C:0x0077    EF       MOV      A,R7
C:0x0078    2F       ADD      A,R7
C:0x0079    FF       MOV      R7,A
C:0x007A    ED       MOV      A,R5
C:0x007B    33       RLC      A
C:0x007C    FD       MOV      R5,A
C:0x007D    4007     JC       C:0086
C:0x007F    98       SUBB     A,R0
C:0x0080    5006     JNC      C:0088
C:0x0082    D5F0F2   DJNZ     B(0xF0),C:0077
C:0x0085    22       RET      
C:0x0086    C3       CLR      C
C:0x0087    98       SUBB     A,R0
C:0x0088    FD       MOV      R5,A
C:0x0089    0F       INC      R7
C:0x008A    D5F0EA   DJNZ     B(0xF0),C:0077
C:0x008D    22       RET      

     2: void main()
     3: { 
     4:     int  i;
     5:  unsigned char j;
     6:  i=-10000;
     7:  
C:0x008E    7FF0     MOV      R7,#B(0xF0)
C:0x0090    7ED8     MOV      R6,#0xD8
     8:  j=i/256;
     9: 
C:0x0092    7C01     MOV      R4,#0x01
C:0x0094    7D00     MOV      R5,#0x00
C:0x0096    120003   LCALL    C?SIDIV(C:0003)
C:0x0099    8F08     MOV      0x08,R7
    10: while(1)
C:0x009B    80FE     SJMP     C:009B

就是一個signed和unsigned的區別,用的著差別這么大嗎?

通過以上的實驗,可以得出結論:Keil編譯器非常智能,會生成最短的代碼,能夠智能判斷每個變量的使用,生成最短的代碼。同時,學習單片機的各位同仁,除非萬不得已,千萬不要用signed類型。

關閉窗口

相關文章

主站蜘蛛池模板: 国产精品亚洲一区 | 日韩精品视频网 | 欧美精品久久久 | 国产欧美精品一区二区 | 久久精品福利 | 国产精品久久午夜夜伦鲁鲁 | 最新免费av网站 | 久久成人国产 | 视频在线观看一区 | 在线视频亚洲 | 亚洲免费在线 | 日本成人久久 | 午夜一区 | 国产日韩欧美一区二区在线播放 | 在线a视频| 国产精品亚洲成在人线 | 日韩在线一区二区 | 狠狠狠干 | 九九热精品视频在线观看 | 国产区一区 | 一级一级一级毛片 | 日韩精品成人 | 中文字幕第三页 | 麻豆精品一区二区三区在线观看 | 欧美激情在线一区二区三区 | 一区中文字幕 | 亚洲天堂网站 | 欧美精品一区在线 | 成人精品一区二区 | 成人伊人| 日韩中文不卡 | 欧美专区在线 | 免费看的黄网站 | 中文字幕一区二区三区在线乱码 | 久久综合99 | 嫩草影院黄 | 伊人影院在线观看 | 国产乱码一二三区精品 | 黑人精品xxx一区一二区 | 国产美女在线观看 | 欧美女优在线观看 |