在Microchip C18中,为什么插入NOP会导致更大的代码?

And*_*eKR 11 c microcontroller pic pic18

我在ISR中有一些代码.代码是为了完整性而给出的,问题只是关于注释掉的__asm_块.

如果没有__asm_块,则会将其编译为82条指令.使用__asm_块,结果是107条指令.为什么差别很大?

这是C代码:

if (PIR1bits.SSPIF)
{
    spi_rec_buffer.read_cursor = 0;
    spi_rec_buffer.write_cursor = 0;

    LATAbits.LATA4 ^= 1;
//      _asm nop nop _endasm
    LATAbits.LATA4 ^= 1;

    while (!PORTAbits.NOT_SS && spi_rec_buffer.write_cursor < spi_rec_buffer.size)
    {
        spi_rec_buffer.data[spi_rec_buffer.write_cursor] = SSPBUF;
        SSPBUF = spi_out_msg_buffer.data[spi_out_msg_buffer.read_cursor];
        PIR1bits.SSPIF = 0;
        spi_rec_buffer.write_cursor++;
        spi_out_msg_buffer.read_cursor++;
        if (spi_out_msg_buffer.read_cursor == spi_out_msg_buffer.write_cursor)
            LATAbits.LATA4 = 0;
        LATBbits.LATB1 = 1;
        while (!PORTAbits.NOT_SS && !PIR1bits.SSPIF);
        LATBbits.LATB1 = 0;
    }

    spi_message_locked = true;
    spi_message_received = true;

}
Run Code Online (Sandbox Code Playgroud)

没有NOP:

BTFSS     0x9e,0x3,0x0      if (PIR1bits.SSPIF)
BRA       0x2ba
                            {
MOVLB     0xf                   spi_rec_buffer.read_cursor = 0;
CLRF      0x4,0x1
CLRF      0x5,0x1
CLRF      0x6,0x1               spi_rec_buffer.write_cursor = 0;
CLRF      0x7,0x1
BTG       0x89,0x4,0x0          LATAbits.LATA4 ^= 1;
BTG       0x89,0x4,0x0          LATAbits.LATA4 ^= 1;
MOVF      0x80,0x0,0x0          while (!PORTAbits.NOT_SS && spi_rec_buffer.write_cursor < spi_rec_buffer.size)
ANDLW     0x20
BNZ       0x2b0
MOVLB     0xf
MOVF      0x7,0x0,0x1
XORWF     0x3,0x0,0x1
BTFSS     0xe8,0x7,0x0
BRA       0x254
RLCF      0x3,0x0,0x1
BRA       0x25c
MOVF      0x2,0x0,0x1
SUBWF     0x6,0x0,0x1
MOVF      0x3,0x0,0x1
SUBWFB    0x7,0x0,0x1
BC        0x2b0
BRA       0x240
                                {
MOVF      0x0,0x0,0x1               spi_rec_buffer.data[spi_rec_buffer.write_cursor] = SSPBUF;
ADDWF     0x6,0x0,0x1
MOVWF     0xe9,0x0
MOVF      0x1,0x0,0x1
ADDWFC    0x7,0x0,0x1
MOVWF     0xea,0x0
MOVFF     0xfc9,0xfef
MOVLB     0xf                       SSPBUF = spi_out_msg_buffer.data[spi_out_msg_buffer.read_cursor];
MOVF      0x10,0x0,0x1
ADDWF     0x14,0x0,0x1
MOVWF     0xe9,0x0
MOVF      0x11,0x0,0x1
ADDWFC    0x15,0x0,0x1
MOVWF     0xea,0x0
MOVF      0xef,0x0,0x0
MOVWF     0xc9,0x0
BCF       0x9e,0x3,0x0              PIR1bits.SSPIF = 0;
MOVLB     0xf                       spi_rec_buffer.write_cursor++;
INCF      0x6,0x1,0x1
MOVLW     0x0
ADDWFC    0x7,0x1,0x1
MOVLB     0xf                       spi_out_msg_buffer.read_cursor++;
INCF      0x14,0x1,0x1
ADDWFC    0x15,0x1,0x1
MOVF      0x16,0x0,0x1              if (spi_out_msg_buffer.read_cursor == spi_out_msg_buffer.write_cursor)
XORWF     0x14,0x0,0x1
BNZ       0x29e
MOVF      0x17,0x0,0x1
XORWF     0x15,0x0,0x1
BNZ       0x29e
BCF       0x89,0x4,0x0                  LATAbits.LATA4 = 0;
BSF       0x8a,0x1,0x0              LATBbits.LATB1 = 1;
MOVF      0x80,0x0,0x0              while (!PORTAbits.NOT_SS && !PIR1bits.SSPIF);
ANDLW     0x20
BNZ       0x2ac
MOVF      0x9e,0x0,0x0
ANDLW     0x8
BZ        0x2a0
BCF       0x8a,0x1,0x0              LATBbits.LATB1 = 0;
                                }
MOVLB     0xf                   spi_message_locked = true;
MOVLW     0x1
MOVWF     0x18,0x1
MOVLB     0xf                   spi_message_received = true;
MOVWF     0x19,0x1
                            }
MOVLW     0x4            }
SUBWF     0xe1,0x0,0x0
BC        0x2c4
CLRF      0xe1,0x0
MOVF      0xe5,0x1,0x0
MOVWF     0xe1,0x0
MOVF      0xe5,0x1,0x0
MOVFF     0xfe7,0xfd9
MOVF      0xe5,0x1,0x0
MOVFF     0xfe5,0xfea
MOVFF     0xfe5,0xfe9
MOVFF     0xfe5,0xfda
RETFIE    0x1
Run Code Online (Sandbox Code Playgroud)

有了NOP:

BTFSS     0x9e,0x3,0x0      if (PIR1bits.SSPIF)
BRA       0x30e
                            {
MOVLB     0xf                   spi_rec_buffer.read_cursor = 0;
CLRF      0x4,0x1
CLRF      0x5,0x1
MOVLB     0xf                   spi_rec_buffer.write_cursor = 0;
CLRF      0x6,0x1
CLRF      0x7,0x1
BTG       0x89,0x4,0x0          LATAbits.LATA4 ^= 1;
NOP                             _asm nop nop _endasm
NOP
BTG       0x89,0x4,0x0          LATAbits.LATA4 ^= 1;
MOVF      0x80,0x0,0x0          while (!PORTAbits.NOT_SS && spi_rec_buffer.write_cursor < spi_rec_buffer.size)
ANDLW     0x20
BNZ       0x302
MOVLB     0xf
MOVF      0x7,0x0,0x1
MOVLB     0xf
XORWF     0x3,0x0,0x1
BTFSS     0xe8,0x7,0x0
BRA       0x27e
RLCF      0x3,0x0,0x1
BRA       0x28c
MOVF      0x2,0x0,0x1
MOVLB     0xf
SUBWF     0x6,0x0,0x1
MOVLB     0xf
MOVF      0x3,0x0,0x1
MOVLB     0xf
SUBWFB    0x7,0x0,0x1
BC        0x302
BRA       0x268
                                {
MOVLB     0xf                       spi_rec_buffer.data[spi_rec_buffer.write_cursor] = SSPBUF;
MOVLB     0xf
MOVF      0x0,0x0,0x1
MOVLB     0xf
ADDWF     0x6,0x0,0x1
MOVWF     0xe9,0x0
MOVLB     0xf
MOVLB     0xf
MOVF      0x1,0x0,0x1
MOVLB     0xf
ADDWFC    0x7,0x0,0x1
MOVWF     0xea,0x0
MOVFF     0xfc9,0xfef
MOVLB     0xf                       SSPBUF = spi_out_msg_buffer.data[spi_out_msg_buffer.read_cursor];
MOVLB     0xf
MOVF      0x10,0x0,0x1
MOVLB     0xf
ADDWF     0x14,0x0,0x1
MOVWF     0xe9,0x0
MOVLB     0xf
MOVLB     0xf
MOVF      0x11,0x0,0x1
MOVLB     0xf
ADDWFC    0x15,0x0,0x1
MOVWF     0xea,0x0
MOVF      0xef,0x0,0x0
MOVWF     0xc9,0x0
BCF       0x9e,0x3,0x0              PIR1bits.SSPIF = 0;                           // Interruptflag löschen...
MOVLB     0xf                       spi_rec_buffer.write_cursor++;
INCF      0x6,0x1,0x1
MOVLW     0x0
ADDWFC    0x7,0x1,0x1
MOVLB     0xf                       spi_out_msg_buffer.read_cursor++;
INCF      0x14,0x1,0x1
MOVLW     0x0
ADDWFC    0x15,0x1,0x1
MOVLB     0xf                       if (spi_out_msg_buffer.read_cursor == spi_out_msg_buffer.write_cursor)
MOVF      0x16,0x0,0x1
MOVLB     0xf
XORWF     0x14,0x0,0x1
BNZ       0x2ea
MOVLB     0xf
MOVF      0x17,0x0,0x1
MOVLB     0xf
XORWF     0x15,0x0,0x1
BNZ       0x2ee
BCF       0x89,0x4,0x0                  LATAbits.LATA4 = 0;
BSF       0x8a,0x1,0x0              LATBbits.LATB1 = 1;
MOVF      0x80,0x0,0x0              while (!PORTAbits.NOT_SS && !PIR1bits.SSPIF);
ANDLW     0x20
BNZ       0x2fe
MOVF      0x9e,0x0,0x0
ANDLW     0x8
BNZ       0x2fe
BRA       0x2f0
BCF       0x8a,0x1,0x0              LATBbits.LATB1 = 0;
                                }
MOVLB     0xf                   spi_message_locked = true;
MOVLW     0x1
MOVWF     0x18,0x1
MOVLB     0xf                   spi_message_received = true;
MOVLW     0x1
MOVWF     0x19,0x1
                            }
MOVLW     0x4            }
SUBWF     0xe1,0x0,0x0
BC        0x318
CLRF      0xe1,0x0
MOVF      0xe5,0x1,0x0
MOVWF     0xe1,0x0
MOVF      0xe5,0x1,0x0
MOVFF     0xfe7,0xfd9
MOVF      0xe5,0x1,0x0
MOVFF     0xfe5,0xfea
MOVFF     0xfe5,0xfe9
MOVFF     0xfe5,0xfda
RETFIE    0x1
Run Code Online (Sandbox Code Playgroud)

这是部分差异的截图(点击放大): DIFF

Mic*_*urr 10

所以人们不必猜测,这是Microchip C18手册中的声明(重点补充):

通常建议将内联装配的使用限制在最低限度.编译器不会优化包含内联汇编的任何函数.要编写汇编代码的大片段,请使用MPASM汇编器并使用MPLINK链接器将模块链接到C模块.

我认为这是内联asm的常见情况.GCC是一个例外 - 它将优化内联汇编以及周围的C代码; 为了正确地做到这一点,GCC的内联汇编非常复杂(你必须让它知道哪些寄存器和内存被破坏了).