有符号除数的%运算符需要C中更多的程序存储器

时间:2018-04-24 01:39:46

标签: c mod xc8

案例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

1 个答案:

答案 0 :(得分:1)

%的操作数执行usual arithmetic conversions。我猜测i是签名类型; i % 3的结果可能与i % 3u的结果不同。

例如,-1 % 3u通常是0,因为转换为unsigned int后,-1通常会比偶数幂2变小一,例如655354294967295,总是3的倍数。

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

理所当然,编译器可能必须为这两种不同的情况发出不同的汇编指令。

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