16 votos

De C a de la Asamblea

Supongamos que tenemos el siguiente fragmento de código C para el avr de 8 bits:

int v1=1;
int v2=2;
v2=v2+v1;

Yo esperaba que el siguiente desmontar

ldi r18, 1;
ldi r19, 2;
add r19, r18;

pero después de que me encontré:

avr-gcc -mmcu=atmega2560 Test.c -o Test.elf

y

avr-objdump -S Test.elf > Test.lss

Tengo las siguientes desmontar

    ldi r24, 0x01   ; 1
    ldi r25, 0x00   ; 0
    std Y+2, r25    ; 0x02
    std Y+1, r24    ; 0x01
    ldi r24, 0x02   ; 2
    ldi r25, 0x00   ; 0
    std Y+4, r25    ; 0x04
    std Y+3, r24    ; 0x03
    ldd r18, Y+3    ; 0x03
    ldd r19, Y+4    ; 0x04
    ldd r24, Y+1    ; 0x01
    ldd r25, Y+2    ; 0x02
    add r24, r18
    adc r25, r19
    std Y+4, r25    ; 0x04
    std Y+3, r24    ; 0x03

hay alguien que me puede ayudar a entender el resultado de la desensamblador?

Editar: Usar char la asamblea se convierte en:

ldi r24, 0x01
std Y+1, r24
ldi r24, 0x02
std Y+2, r24
ldd r25, Y+2
ldd r24, Y+1
add r24, r25
std Y+2, r24

Cuando hay instrucción std?

4voto

Mario Puntos 191

Como puedo encontrar el código de ejemplo voy a hacer mi comentario una respuesta - que otros ya han explicado el problema.

Un montón de código incrustado de trabajo con las define tipos adicionales que son específicos de su tamaño, tales como "uint8, uint16, uint32" para el unsigned int, por ejemplo. De esa manera usted siempre sabe exactamente que tipo de variable que se está tratando. Especialmente en las pequeñas incrustadas, firmado, float, "int" de tamaño indefinido/signedness va a costar a todos ustedes ciclos de CPU en el mejor y causar graves errores en el peor.

Aquí está nuestra actual #define:

/*
 * Example - the basic data types from our embedded code
 */
typedef unsigned char       uint8;  /*  8 bits */
typedef unsigned short int  uint16; /* 16 bits */
typedef unsigned long int   uint32; /* 32 bits */

typedef char                int8;   /*  8 bits */
typedef short int           int16;  /* 16 bits */
typedef int                 int32;  /* 32 bits */

typedef volatile int8       vint8;  /*  8 bits */
typedef volatile int16      vint16; /* 16 bits */
typedef volatile int32      vint32; /* 32 bits */

typedef volatile uint8      vuint8;  /*  8 bits */
typedef volatile uint16     vuint16; /* 16 bits */
typedef volatile uint32     vuint32; /* 32 bits */

2voto

johnfound Puntos 3851

Tu código C utiliza 16 bits variables de número entero (int). El compilador no puede leer su mente, de modo que compila exactamente lo que está en el archivo de origen. Así que, si quieres 8bit variables, usted tiene que utilizar respectivo tipo.

Como resultado, usted todavía recibirá almacenar los valores en la memoria (aunque más simple). Yo no soy tan buena en C, pero en mi humilde opinión, hay algunas opciones para asignar a la variable a algún registro, si desea algunas variables en los registros, en lugar de la RAM. Algo así como:

register unsigned char VARNAME asm("r3");

Tenga en cuenta que no todos los registros están disponibles para esos trucos.

Así, la conclusión? Escribir programas en ensamblador. Ellos siempre van a ser más pequeño, más rápido y fácil para la lectura o de apoyo.

0voto

jns Puntos 449

Respuesta corta: sus registros son de 8 bits y sus valores son de 16 bits. Por lo tanto, el manejo de ellos en dos piezas.

Respuesta larga:

    ldi r24, 0x01   ; 1
    ldi r25, 0x00   ; 0

Almacenar el valor de 16 bits 1 en 8-bits de los registros r24,r25.

    std Y+2, r25    ; 0x02
    std Y+1, r24    ; 0x01

Almacenar en la pila de lugares Y+1, Y+2.

    ldi r24, 0x02   ; 2
    ldi r25, 0x00   ; 0

Almacenar el valor de 16 bits 2 en 8-bits de los registros r24,r25.

    std Y+4, r25    ; 0x04
    std Y+3, r24    ; 0x03

Almacenar en la pila de lugares Y+3, Y+4.

    ldd r18, Y+3    ; 0x03
    ldd r19, Y+4    ; 0x04
    ldd r24, Y+1    ; 0x01
    ldd r25, Y+2    ; 0x02

Copia de vuelta de la pila (r18,r19) y (r24,r25)

    add r24, r18
    adc r25, r19

Agregar (r18,r19) (r24,r25), incluyendo el llevar en la segunda, además de

    std Y+4, r25    ; 0x04
    std Y+3, r24    ; 0x03

La tienda de nuevo en la pila.

Para obtener el original de la asamblea, trate de hacer dos cosas:

  • el uso de "char" variables
  • el uso de "-O2" opción del compilador

Edit: la razón por la que el compilador almacena las variables de la pila en lugar de mantenerlos en los registros es porque están almacenados con el valor "auto" tipo de almacenamiento. Se puede optimizar en los registros, pero no tiene que, incluso si se declaran con "registrar" clase de almacenamiento.

Si bien esto no es un requisito estricto de la lengua es normal compilador de comportamiento. Si en algún momento de tomar la dirección de v1, entonces debe ser asignado a una ubicación de almacenamiento, y se guarda la parte de atrás hay siempre que el valor de "v1" los cambios. Así que para salvar a la contabilidad de si o no v1 debe ser almacenado en un registro o en la pila, se la guarda en la pila y trata a cada línea de código por separado.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X