Confusión con un código de ensamblaje simple para AVR

1

Estoy usando ATmega328P con Atmel Studio. Tengo un problema para entender la manipulación del registro en este código:

#include <avr/io.h>

int main(void)
{
    DDRB =  0b00000111;
    PORTB = 0b00000111;

    while (1)
    {           
        PORTB = 0b00000000;         
        PORTB = 0b00000111;     
    }
}

Y aquí está su montaje:

     5: {
     6:     DDRB =  0b00000111;
00000040 87.e0                LDI R24,0x07      Load immediate 
00000041 84.b9                OUT 0x04,R24      Out to I/O location 
     7:     PORTB = 0b00000111;
00000042 85.b9                OUT 0x05,R24      Out to I/O location 
    12:         PORTB = 0b00000000;
00000043 15.b8                OUT 0x05,R1       Out to I/O location 
00000044 fd.cf                RJMP PC-0x0002        Relative jump 

Y aquí está la vista de los registros de E / S para PORTB para la última ejecución:

Mi pregunta es:

Si vamos paso a paso, aquí 00000111 se mueve al registro de CPU R24 y se mueve el registro DDRB que está en la dirección 0x04:

        DDRB =  0b00000111;
00000040 87.e0                LDI R24,0x07      Load immediate 
00000041 84.b9                OUT 0x04,R24      Out to I/O location 

Aquí se aplica el mismo patrón de bits en R24 al registro PORTB

     PORTB = 0b00000111;
00000042 85.b9                OUT 0x05,R24      Out to I/O location 

Pero lo que está pasando aquí en las dos últimas líneas aquí:

00000043 15.b8                OUT 0x05,R1       Out to I/O location 
00000044 fd.cf                RJMP PC-0x0002        Relative jump 

En primer lugar, ¿qué es R1 que no está declarado? Y mi código no tiene nada que ver con el registro PINB , pero ¿por qué PINB0, PINB1 y PINB2 de PINB se convierten en 1 aquí? Las dos últimas líneas son:

    
pregunta user16307

1 respuesta

5
  

En primer lugar, ¿qué es R1 que no está declarado?

r0 ... r31 son los registros de propósito general del AVR. r1 se establece en 0x00 mediante el código de inicio que gcc genera implícitamente y luego el compilador asume que contiene 0x00 para siempre. Por lo tanto, donde se necesita 0x00 pero no se puede usar un literal, gcc simplemente usa r1 . (Similarmente, r0 está reservado como registro de almacenamiento temporal y puede usarse para cualquier propósito en cualquier parte del código porque gcc nunca lo usará para almacenar nada a través de una llamada de función o una sección de ensamblaje en línea).

Consulte también enlace .

  

Y mi código no tiene nada que ver con el registro PINB, pero ¿por qué PINB0, PINB1 y PINB2 de PINB se convierten en 1 aquí?

PINx representa el valor (alto / bajo) como se ve en el pin. Cuando genera un valor a través de PORTx, ese valor también se refleja en el PINx (retrasado por 1 ciclo de reloj, IIRC). Eso también se menciona explícitamente en las hojas de datos.

    
respondido por el JimmyB

Lea otras preguntas en las etiquetas