1

情况1:

static uint8_t i;
i % 3;     // 3 is a signed number

案例2:

static uint8_t i;
i % 3u;    // 3 is a unsigned number

使用 Microchip XC8 编译器,我发现案例 1 需要更多指令(使用的程序内存几乎没有增加)。为什么?

注:8 位 CPU。XC8 编译器符合 C89 标准。

部件:

225:                   if(KEYbits.I2C == ON && h%5u == 0){
02F2  1ED2     BTFSS KEYbits, 0x5
02F3  2AF5     GOTO 0x2F5
02F4  2AF6     GOTO 0x2F6
02F5  2C75     GOTO 0x475
02F6  3005     MOVLW 0x5
02F7  00F0     MOVWF __pcstackCOMMON
02F8  3000     MOVLW 0x0
02F9  00F1     MOVWF hold
02FA  0850     MOVF h, W
02FB  00DE     MOVWF 0x5E
02FC  01DF     CLRF 0x5F
02FD  085E     MOVF 0x5E, W
02FE  00F2     MOVWF product
02FF  085F     MOVF 0x5F, W
0300  00F3     MOVWF multiplier
0301  318A     MOVLP 0xA            //here
0302  22B4     CALL 0x2B4           //here
0303  3180     MOVLP 0x0
0304  0870     MOVF __pcstackCOMMON, W
0305  0471     IORWF hold, W
0306  1D03     BTFSS STATUS, 0x2
0307  2B09     GOTO 0x309
0308  2B0A     GOTO 0x30A
0309  2C75     GOTO 0x475
226:                       h = 0;

02B4  0834     MOVF TMR4_counter, W
02B5  07DE     ADDWF 0x5E, F
02B6  0835     MOVF 0x35, W
02B7  3DDF     ADDWFC 0x5F, F
02B8  0836     MOVF 0x36, W
02B9  3DE0     ADDWFC 0x60, F
02BA  0837     MOVF 0x37, W
02BB  3DE1     ADDWFC 0x61, F
02BC  0861     MOVF 0x61, W
02BD  00B7     MOVWF 0x37
02BE  0860     MOVF 0x60, W
02BF  00B6     MOVWF 0x36
02C0  085F     MOVF 0x5F, W
02C1  00B5     MOVWF 0x35
02C2  085E     MOVF 0x5E, W
02C3  00B4     MOVWF TMR4_counter

225:                   if(KEYbits.I2C == ON && h%5 == 0){
02F2  1ED2     BTFSS KEYbits, 0x5
02F3  2AF5     GOTO 0x2F5
02F4  2AF6     GOTO 0x2F6
02F5  2C75     GOTO 0x475
02F6  3005     MOVLW 0x5
02F7  00F0     MOVWF __pcstackCOMMON
02F8  3000     MOVLW 0x0
02F9  00F1     MOVWF hold
02FA  0850     MOVF h, W
02FB  00DE     MOVWF 0x5E
02FC  01DF     CLRF 0x5F
02FD  085E     MOVF 0x5E, W
02FE  00F2     MOVWF product
02FF  085F     MOVF 0x5F, W
0300  00F3     MOVWF multiplier
0301  3186     MOVLP 0x6           //here
0302  2663     CALL 0x663          //here
0303  3180     MOVLP 0x0
0304  0870     MOVF __pcstackCOMMON, W
0305  0471     IORWF hold, W
0306  1D03     BTFSS STATUS, 0x2
0307  2B09     GOTO 0x309
0308  2B0A     GOTO 0x30A
0309  2C75     GOTO 0x475
226:                       h = 0;


0663  01F6     CLRF sign
14:             if(dividend < 0) {
0664  1FF3     BTFSS multiplier, 0x7
0665  2E67     GOTO 0x667
0666  2E68     GOTO 0x668
0667  2E70     GOTO 0x670
15:                 dividend = -dividend;
0668  09F2     COMF product, F
0669  09F3     COMF multiplier, F
066A  0AF2     INCF product, F
066B  1903     BTFSC STATUS, 0x2
066C  0AF3     INCF multiplier, F
16:                 sign = 1;
066D  01F6     CLRF sign
066E  0AF6     INCF sign, F
066F  2E70     GOTO 0x670
4

1 回答 1

1

通常的算术转换 是在 的操作数上执行的%。我猜这i是有符号的类型;的结果i % 3可能与 的结果不同i % 3u

例如,-1 % 3u通常是0因为在转换为 之后unsigned int-1通常会变为小于 2 的偶数次方,例如655354294967295,它始终是 3 的倍数。

但是-1 % 3-1或者2在 C89 中(它是实现定义的)。

按理说编译器可能必须针对这两种不同的情况发出不同的汇编指令。

对问题的编辑不会改变这一点;uint8_t被提升为 signed ,int优化器可能没有意识到它可以在这两种情况下使用“更好”的程序集。

于 2018-04-24T02:00:46.180 回答