Autor Tema: Bootloader encriptado para Attiny88  (Leído 18540 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #15 en: 21 de Septiembre de 2015, 18:24:09 »
Yo creo que el "unsigned int i" y el "unsigned int num_rounds" se pueden sustituir por dos char.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #16 en: 21 de Septiembre de 2015, 18:26:44 »
Si además la key se hace global, quedaría así:

Código: [Seleccionar]
uint32_t const key[4] = {
    0x12345678,
    0x12345678,
    0x12345678,
    0x12345678,
}

void decipher(char num_rounds, uint32_t v[2]) {
    uint32_t v0 = v[0];
    uint32_t v1 = v[1];
    uint32_t delta = 0x9E3779B9;
    uint32_t sum = delta * num_rounds;
    while(num_rounds--) {
        v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
        sum -= delta;
        v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
    }
    v[0] = v0;
    v[1] = v1;
}

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Bootloader encriptado para Attiny88
« Respuesta #17 en: 21 de Septiembre de 2015, 18:45:58 »
Listo Picuino. Esta noche o mañana cuando tengo un tiempito lo hago.

El bootloader se ejecuta antes que el crt0 o despues ?, es para saber si manejarme con el stack o si puedo elegir aleatoriamente cualquier posicion de la RAM.

Citar
Habría que salvar los registros antes del ensamblador.

Eso depende.. Si todavia no iniciaste C con el crt0/1 entonces puedo utilizar los registros a mi gusto, si lo iniciaste entonces debo guardar los registros en el stack y crear las variables en el stack para manejarme.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #18 en: 21 de Septiembre de 2015, 18:46:29 »
Con algunos cambios más:

Código: [Seleccionar]
#define XTEA_DELTA  0x9E3779B9
#define NUM_ROUND   32L

uint32_t const key[] = {
   // Cambiar los siguientes valores por la key
   0x12345678, 0x12345678, 0x12345678, 0x12345678,  
}

void decipher(uint32_t v[2]) {
   uint32_t v0 = v[0];
   uint32_t v1 = v[1];
   uint32_t sum =  XTEA_DELTA * NUM_ROUND;
   char num_rounds = 32;
   while(num_rounds--) {
      v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
      sum -= XTEA_DELTA;
      v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
   }
   v[0] = v0;
   v[1] = v1;
}

He usado el valor recomendado para el número de rondas (32)
Creo que el algoritmo no ha cambiado.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #19 en: 21 de Septiembre de 2015, 18:50:58 »
Gracias Killer. Creo que al final haré todo en ensamblador para que sea más pequeño.
No hay que preocuparse por la ram. Está toda disponible para el bootloader.

Los datos llegan por la UART en grupos de 64 bytes (una página flash) + checksum

Una vez comprobados, se decodifican en grupos de 4 bytes (el algoritmo XTEA),  se guardan en la memoria temporal flash y se escriben en flash.

Recuerda que es para un Attiny. Yo estoy acostumbrado al PIC y eso me está dando algún dolor de cabeza. Son bien distintos.

Un saludo.

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp
Re: Bootloader encriptado para Attiny88
« Respuesta #20 en: 21 de Septiembre de 2015, 21:38:22 »

He usado el valor recomendado para el número de rondas (32)



Más seguro si lo haces a 64 rondas, así lo tengo yo en mi bootloader.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Bootloader encriptado para Attiny88
« Respuesta #21 en: 22 de Septiembre de 2015, 03:34:29 »
Esto ya lo tengo realizado en ASM:

Código: C
  1. while(num_rounds--) {
  2.         v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
  3.         sum -= delta;
  4.         v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
  5.     }

El tema es que no me gusta como esta hecho.. por que esta todo lineal por asi decirlo, no quiero reducir mas la funcion. Aunque todo se ve agrandado por 4 debido a que hay que manejarse a 32bits
Como se puede observar hay codigo "repetido" ya que para las lineas de v1 -= xxx y las de v0 -= xxx son casi iguales. entonces quiero hacer un codigo en el que los puedan usar a ambos

Código: ASM
  1. Loop_while
  2.         ;Rotar todos
  3.  
  4.         MOVW    Vtemp0[0],V0[0] // Vtemp0 para (v0<<4) y Vtemp1 para (V0 >> 5)
  5.         MOVW    Vtemp0[2],V0[2]
  6.         MOVW    Vtemp1[0],V0[0]
  7.         MOVW    Vtemp1[2],V0[2]
  8.  
  9.         LDI     R0,4
  10. RotateLeftv0                    // (v0 << 4)
  11.         LSL     Vtemp0[0]
  12.         ROL     Vtemp0[1]
  13.         ROL     Vtemp0[2]
  14.         ROL     Vtemp0[3]       // Por ser de 32 bits se deberian perder los bits que salgan de aca
  15.         DEC     R0
  16.         BRNE    RotateLeftv0
  17.  
  18.         LDI     R0,5
  19. RotateRightv0                   // (V0 >> 5 )
  20.         LSR     Vtemp1[3]
  21.         ROR     Vtemp1[2]
  22.         ROR     Vtemp1[1]
  23.         ROR     Vtemp1[0]
  24.         DEC     R0
  25.         BRNE    RotateRightv0
  26.  
  27.         EOR     Vtemp0[0],Vtemp1[0]     //  (v0 << 4) ^ (v0 >> 5)
  28.         EOR     Vtemp0[1],Vtemp1[1]
  29.         EOR     Vtemp0[2],Vtemp1[2]
  30.         EOR     Vtemp0[3],Vtemp1[3]
  31.  
  32.         ADD     Vtemp0[0],V0[0]         //  ((v0 << 4) ^ (v0 >> 5)) + v0
  33.         ADC     Vtemp0[1],V0[1]         // Vtemp0 = ((v0 << 4) ^ (v0 >> 5)) + v0
  34.         ADC     Vtemp0[2],V0[2]
  35.         ADC     Vtemp0[3],V0[3]
  36.  
  37.         MOVW    Vtemp1[0],sum[0]
  38.         MOVW    Vtemp1[2],sum[2]
  39.  
  40.         MOV     R0,SUM[1]               // sum>>11 & 3
  41.         LSR     R0
  42.         ANDI    R0,0x0C                 // 0000 aa00
  43.         ADD     ZL,R0                   // Le sumo el valor de R0 o lo que es igual a 4 * index
  44.         LD      Aux[0],Z+               // key[sum>>11&3]
  45.         LD      Aux[1],Z+
  46.         LD      Aux[2],Z+
  47.         LD      Aux[3],Z+
  48.  
  49.         ADD     Vtemp1[0],Aux[0]        // sum + key[(sum>>11) & 3]
  50.         ADC     Vtemp1[1],Aux[1]        // Vtemp1 = sum + key[(sum>>11) & 3]
  51.         ADC     Vtemp1[2],Aux[2]
  52.         ADC     Vtemp1[3],Aux[3]
  53.  
  54.         EOR     Vtemp0[0],Vtemp1[0]     //  (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3])
  55.         EOR     Vtemp0[1],Vtemp1[1]     //   Vtemp[0]
  56.         EOR     Vtemp0[2],Vtemp1[2]
  57.         EOR     Vtemp0[3],Vtemp1[3]
  58.  
  59.         SUB     V1[0],Vtemp0[0]         // v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3])
  60.         SBC     V1[1],Vtemp0[1]
  61.         SBC     V1[2],Vtemp0[2]
  62.         SBC     V1[3],Vtemp0[3]         // si ocurrio overflow ocurrio, lo lamento
  63.  
  64.         // Resta de Suma
  65.  
  66.         SUB     sum[0],XTEA_DELTA[0]    // sum -= XTEA_DELTA;
  67.         SBC     sum[1],XTEA_DELTA[1]
  68.         SBC     sum[2],XTEA_DELTA[2]
  69.         SBC     sum[3],XTEA_DELTA[3]
  70.  
  71.         // Comienzo de la segunda operacion
  72.  
  73.         LDI     ZL,0x00                 // Renuevo el valor de las keys
  74.  
  75.         MOVW    Vtemp0[0],V1[0]
  76.         MOVW    Vtemp0[2],V1[2]
  77.         MOVW    Vtemp1[0],V1[0]
  78.         MOVW    Vtemp1[2],V1[2]
  79.  
  80.         LDI     R0,5
  81. RotateLeftv1                    // (v1 << 4)
  82.         LSL     Vtemp0[0]
  83.         ROL     Vtemp0[1]
  84.         ROL     Vtemp0[2]
  85.         ROL     Vtemp0[3]       // Por ser de 32 bits se deberian perder los bits que salgan de aca
  86.         DEC     R0
  87.         BRNE    RotateLeftv1
  88.  
  89.         LDI     R0,5
  90. RotateRightv1                   // (V1 >> 5 )
  91.         LSR     Vtemp1[3]
  92.         ROR     Vtemp1[2]
  93.         ROR     Vtemp1[1]
  94.         ROR     Vtemp1[0]
  95.         DEC     R0
  96.         BRNE    RotateRightv1
  97.  
  98.         EOR     Vtemp0[0],Vtemp1[0]     //  (v1 << 4) ^ (v1 >> 5)
  99.         EOR     Vtemp0[1],Vtemp1[1]
  100.         EOR     Vtemp0[2],Vtemp1[2]
  101.         EOR     Vtemp0[3],Vtemp1[3]
  102.  
  103.         ADD     Vtemp0[0],V1[0]         //  ((v1 << 4) ^ (v1 >> 5)) + v1
  104.         ADC     Vtemp0[1],V1[1]         // Vtemp0 = ((v1 << 4) ^ (v1 >> 5)) + v1
  105.         ADC     Vtemp0[2],V1[2]
  106.         ADC     Vtemp0[3],V1[3]
  107.  
  108.         MOVW    Vtemp1[0],sum[0]
  109.         MOVW    Vtemp1[2],sum[2]
  110.  
  111.         MOV     R0,SUM[0]               // sum & 3
  112.         ANDI    R0,0x03                 // 0000 00aa
  113.         ADD     ZL,R0                   // Le sumo el valor de R0 o lo que es igual a 4 * index
  114.         LD      Aux[0],Z+               // key[sum&3]
  115.         LD      Aux[1],Z+
  116.         LD      Aux[2],Z+
  117.         LD      Aux[3],Z+
  118.  
  119.         MOVW    Vtemp1[0],sum[0]
  120.         MOVW    Vtemp1[2],sum[2]
  121.  
  122.         ADD     Vtemp1[0],Aux[0]        // sum + key[sum & 3]
  123.         ADC     Vtemp1[1],Aux[1]        // Vtemp1 = sum + key[sum & 3]
  124.         ADC     Vtemp1[2],Aux[2]
  125.         ADC     Vtemp1[3],Aux[3]
  126.  
  127.         EOR     Vtemp0[0],Vtemp1[0]     //  (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3])
  128.         EOR     Vtemp0[1],Vtemp1[1]     //  Vtemp0
  129.         EOR     Vtemp0[2],Vtemp1[2]
  130.         EOR     Vtemp0[3],Vtemp1[3]
  131.  
  132.         SUB     V0[0],Vtemp0[0]         // v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3])
  133.         SBC     V0[1],Vtemp0[1]
  134.         SBC     V0[2],Vtemp0[2]
  135.         SBC     V0[3],Vtemp0[3]         // si ocurrio overflow ocurrio, lo lamento
  136.  
  137.         DEC     Round
  138.         BRNE    Loop_while

Lo otro feo es que utilize con eso casi todos los registros del core   :), me quedo solo el de R0 que lo uso de temporal como para las operaciones...
Lo hice asi solo para evitar el ciclo extra que hay a la SRAM

Código: [Seleccionar]
R1  = Round
R2  = Aux[0]
R3  = Aux[1]
R4  = Aux[2]
R5  = Aux[3]
R6  = V1[0]
R7  = V1[1]
R8  = V1[2]
R9  = V1[3]
R10 = sum[0]
R11 = sum[1]
R12 = sum[2]
R13 = sum[3]
R14 = V0[0]
R15 = V0[1]
R16 = V0[2]
R17 = V0[3]
R18 = Vtemp0[0]
R19 = Vtemp0[1]
R20 = Vtemp0[2]
R21 = Vtemp0[3]
R22 = Vtemp1[0]
R23 = Vtemp1[1]
R24 = Vtemp1[2]
R25 = Vtemp1[3]
R26 = XL
R27 = XH
R28 = YL
R29 = YH
R30 = ZL
R31 = ZH

Ahora me voy a dormir por que son casi 3am, mañana lo achico para que ocupe menos espacio y termino la otra parte.

Citar
Los datos llegan por la UART en grupos de 64 bytes (una página flash) + checksum

Supongo que en la UART se va nicluyendo el cheksum apenas van llegando.
Una ves llegado los 64bytes y comprobado, se procede a decodificarlo y luego a grabarlos.
Voy a pensar como que hay un buffer de 64 bytes empezando en 0x100(Comienzo de SRAM) hasta 0x139, se decodifica todo esas 64 bytes y sale de esta rutina para que se pueda programar. Tambien se podria aprovechar toda la RAM para crear 2 buffers de 64 bytes. asi mientras se llena uno mediante interrupciones, el otro va decodificandose/grabandose.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #22 en: 22 de Septiembre de 2015, 07:46:38 »
El algoritmo UART utiliza pooling. No se pueden utilizar interrupciones.

No hace falta optimizar tiempos:
   A 115200 baud, se reciben 64 bytes + checksum en aproximadamente 6 milisegundos.
   Luego se decodifican. He calculado aproximadamente 1 ms por cada 8 bytes a partir de tu rutina. En total 8 ms por página de 64 bytes.
   A continuación se envían a grabar (unos 2 milisegundos) que se puede hacer mientras se recibe otra página.
   En total calculo unos 15ms por página.
   Tiempo total = 1.8 segundos en grabar 8kb de flash.

No hay que preocuparse por optimizar ese tiempo para nada.

Lo que más me preocupa es la memoria. Cuanto más pequeño sea, mejor.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #23 en: 22 de Septiembre de 2015, 07:49:41 »
Más seguro si lo haces a 64 rondas, así lo tengo yo en mi bootloader.

Ese punto no me queda muy claro. En Wikipedia dicen que para hacer 64 rondas, es necesario hacer 32 ciclos, porque el algoritmo hace 2 rondas por ciclo:
https://en.wikipedia.org/wiki/XTEA
Citar
The recommended value for the "num_rounds" parameter is 32, not 64, as each iteration of the loop does two Feistel-cipher rounds

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #24 en: 22 de Septiembre de 2015, 08:05:51 »
Paper de los autores proponiendo el XTEA:
http://www.cix.co.uk/~klockstone/xtea.pdf

Comentario y rutina:
Citar
 v gives the plain text of 2 words,
  k gives the key of 4 words,
  N gives the number of cycles, 32 are recommended,
  if negative causes decoding, N must be the same as for coding,
  if zero causes no coding or decoding.
  assumes 32 bit \long" and same endian coding or decoding

tean( long * v, long * k, long N) {
   unsigned long y=v[0], z=v[1], DELTA=0x9e3779b9 ;
   if (N>0) {
      /* coding */
      unsigned long limit=DELTA*N, sum=0 ;
      while (sum!=limit)
         y += (z<<4 ^ z>>5) + z ^ sum + k[sum&3],
         sum +=DELTA,
         z += (y<<4 ^ y>>5) + y ^ sum + k[sum>>11 &3] ;
   }

   else {
      /* decoding */
      unsigned long sum=DELTA*(-N) ;
      while (sum)
         z -= (y<<4 ^ y>>5) + y ^ sum + k[sum>>11 &3],
         sum -=DELTA,
         y -= (z<<4 ^ z>>5) + z ^ sum + k[sum&3] ;
   }
   v[0]=y;
   v[1]=z ;
   return;
}

El comentario de los autores:

  N gives the number of cycles, 32 are recommended,
« Última modificación: 22 de Septiembre de 2015, 08:14:04 por Picuino »

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #25 en: 22 de Septiembre de 2015, 08:12:27 »
En base a esto, cambiando N por 32:

Código: [Seleccionar]
#define XTEA_DELTA  0x9E3779B9
uint32_t const xtea_key[] = {
   0x12345678, 0x12345678, 0x12345678, 0x12345678,
}

void xtea_decipher(uint32_t *data) {
   uint32_t data0 = data[0];
   uint32_t data1 = data[1];

   /* decoding */
   uint32_t sum = XTEA_DELTA * 32;
   while (sum) {
      data1 -= (((data0<<4) ^ (data0>>5)) + data0) ^ (sum + xtea_key[(sum>>11) & 3];
      sum -= XTEA_DELTA;
      data0 -= (((data1<<4) ^ (data1>>5)) + data1) ^ (sum + xtea_key[sum & 3] ;
   }
   v[0] = data0;
   v[1] = data1;
}
« Última modificación: 22 de Septiembre de 2015, 08:19:34 por Picuino »

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #26 en: 22 de Septiembre de 2015, 08:18:21 »
No me queda claro si será mejor comprobar que (sum == 0) o contar directamente el número de rondas.

He comprobado las dos rutinas y son iguales (excepto en la condición de salida del bucle)

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #27 en: 22 de Septiembre de 2015, 09:29:42 »
Rutina en Python para probar el algoritmo XTEA:

Código: [Seleccionar]
import random, ctypes

NUM_ROUNDS = 32
XTEA_DELTA = 0x9E3779B9
xtea_key = [random.randrange(0, 0xFFFFFFFF) for n in range(4)]


def xtea_encode(data):
   data0 = data[0]
   data1 = data[1]
   suma = 0
   rounds = 32
   while(rounds):
      data0 += (((data1<<4) ^ (data1>>5)) + data1) ^ (suma + xtea_key[suma & 3])
      data0 = uint32(data0)
      suma = uint32(suma + XTEA_DELTA)
      data1 += (((data0<<4) ^ (data0>>5)) + data0) ^ (suma + xtea_key[(suma>>11) & 3])
      data1 = uint32(data1)
      rounds -= 1
   data[0] = data0
   data[1] = data1


def xtea_decode(data):
   data0 = data[0]
   data1 = data[1]
   suma = uint32(XTEA_DELTA * 32);
   rounds = 32
   while(rounds):
      data1 -= uint32((((data0<<4) ^ (data0>>5)) + data0) ^ (suma + xtea_key[(suma>>11) & 3]))
      data1 = uint32(data1)
      suma = uint32(suma - XTEA_DELTA)
      data0 -= uint32((((data1<<4) ^ (data1>>5)) + data1) ^ (suma + xtea_key[suma & 3]))
      data0 = uint32(data0)
      rounds -= 1
   data[0] = data0
   data[1] = data1


def test_xtea(data):
   org0, org1 = data
   xtea_encode(data)
   enc0, enc1 = data
   xtea_decode(data)
   dec0, dec1 = data
   if (dec0 == org0 and dec1 == org1 and
       enc0 != org0 and enc1 != org1):
      return True
   else:
      print '\nError en XTEA'
      print '  Codificado   :', encode_data
      print '  Decodificado :', decode_data
      return False
  

def uint32(data):
    return ctypes.c_uint32(data).value

    
def main():
   msgs = 1000
   print('Testing %d messages' % msgs)
   random.SystemRandom()
   data = [0, 1]
   for i in range(msgs):
      data[0] = random.randrange(0, 0xFFFFFFFF)
      data[1] = random.randrange(0, 0xFFFFFFFF)
      if test_xtea(data) == False:
         break;        
   print("Test End")

  
main()

Voy a probar con ella a hacer simplificaciones a la rutina de decodificacion.

Saludos.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5883
    • Picuino
Re: Bootloader encriptado para Attiny88
« Respuesta #28 en: 22 de Septiembre de 2015, 09:55:40 »
El código se puede simplificar así:

Código: [Seleccionar]
# data0 = registro temporal 32 bits = 4 bytes
# data1 = registro temporal 32 bits = 4 bytes
# Ta    = registro temporal 32 bits = 4 bytes
# Tb    = registro temporal 32 bits = 4 bytes
# suma  = registro temporal 32 bits = 4 bytes
# rounds = registro temporal 8 bits = 1 byte
# r1    = registro temporal  8 bits = 1 byte

def xtea_sub1():
   global Ta, Tb, r1, suma
   Tb = Ta    
   Ta <<= 4
   Tb >>= 5
   xtea_sub3()  # goto xtea_sub3  


def xtea_sub2():
   global Ta, Tb, r1, suma
   Tb = xtea_key[r1]
   Tb += suma
   xtea_sub3()  # asm continue in xtea_sub3


def xtea_sub3():
   global Ta, Tb, r1, suma
   Ta ^= Tb

  
def xtea_decode(data):
   global Ta, Tb, r1, suma
   data0 = data[0]
   data1 = data[1]

   suma = uint32(XTEA_DELTA * 32);
   rounds = 64
   while(rounds):
      Ta = data0
      xtea_sub1()
      Ta += data0
      if not (rounds & 1):
         r1 = (suma>>11) & 3    
      else:
         r1 = suma & 3
      xtea_sub2()
      data1 -= Ta
      data1 = uint32(data1)
      if not (rounds & 1):
         suma -= XTEA_DELTA
         suma = uint32(suma)
      data0, data1 = data1, data0
      rounds -= 1
      
   data[0] = data0
   data[1] = data1
« Última modificación: 22 de Septiembre de 2015, 09:59:43 por Picuino »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Bootloader encriptado para Attiny88
« Respuesta #29 en: 22 de Septiembre de 2015, 11:42:32 »
Citar
No me queda claro si será mejor comprobar que (sum == 0) o contar directamente el número de rondas.

Ahi yo me cause una confusion tambien. Si se observa en C, sum es de 32 bits unsigned

Cuando se hace sum = XTEA_DELTA * num_round, se desplaza el dato a la derecha, 5 lugares para el caso de 32bits

Vos me diste este valor XTEA_DELTA 0x9E3779B9

Que si lo multiplico por 32 quedaria: 0x13C6EF3720, 1 byte mas. Pero luego cuando se guarda en sum, por ser de 32bits termino con
sum = 0xC6EF3720

Si resto continuamente ese valor siempre va a ser de 32bits, Por eso pienso que la condicion no debe ser sum = 0, lo pense en su momento para que contar las rondas si puedo esperar a 0, e incluso hice el ASM con sum de hasta 5 bytes. Pero luego me di cuenta que no es asi.

Tu ultimo codigo es justo, justo, identico, me copiaste, lo que estaba haciendo Picuino. xD

Código: ASM
  1. Loop_while
  2.  
  3.         RCALL   Termino
  4. ;Resta
  5.         SUB     sum[0],XTEA_DELTA[0]    ; sum -= XTEA_DELTA;
  6.         SBC     sum[1],XTEA_DELTA[1]
  7.         SBC     sum[2],XTEA_DELTA[2]
  8.         SBC     sum[3],XTEA_DELTA[3]
  9.  
  10. ;Cambio de lugar v0 y v1
  11.  
  12.         MOVW    Vtemp0[0],V1[0]
  13.         MOVW    Vtemp0[2],V1[2]
  14.         MOVW    V1[0],V0[0]
  15.         MOVW    V1[2],V0[2]
  16.         MOVW    V0[0],Vtemp0[0]
  17.         MOVW    V0[2],Vtemp0[2]
  18.  
  19.         RCALL   Termino
  20.  
  21. ;Cambio de lugar v0 y v1 , para la proxima ronda
  22.  
  23.         MOVW    Vtemp0[0],V1[0]
  24.         MOVW    Vtemp0[2],V1[2]
  25.         MOVW    V1[0],V0[0]
  26.         MOVW    V1[2],V0[2]
  27.         MOVW    V0[0],Vtemp0[0]
  28.         MOVW    V0[2],Vtemp0[2]
  29.  
  30.         DEC     Count
  31.         BRNE    Loop_while
  32.         RET
  33.  
  34.  
  35. Termino
  36.         LDI     ZL,0                    ; Recargo valor de Z con el valor original, para la proxima obtencion de valores de llaves.
  37.  
  38.         MOVW    Vtemp0[0],V0[0] ; Vtemp0 para (v0<<4) y Vtemp1 para (V0 >> 5)
  39.         MOVW    Vtemp0[2],V0[2]
  40.         MOVW    Vtemp1[0],V0[0]
  41.         MOVW    Vtemp1[2],V0[2]
  42.  
  43.         LDI     R0,4
  44. RotateLeftv0                    ; (v0 << 4)
  45.         LSL     Vtemp0[0]
  46.         ROL     Vtemp0[1]
  47.         ROL     Vtemp0[2]
  48.         ROL     Vtemp0[3]       ; Por ser de 32 bits se deberian perder los bits que salgan de aca
  49.         DEC     R0
  50.         BRNE    RotateLeftv0
  51.  
  52.         LDI     R0,5
  53. RotateRightv0                   ; (V0 >> 5 )
  54.         LSR     Vtemp1[3]
  55.         ROR     Vtemp1[2]
  56.         ROR     Vtemp1[1]
  57.         ROR     Vtemp1[0]
  58.         DEC     R0
  59.         BRNE    RotateRightv0
  60.  
  61.         EOR     Vtemp0[0],Vtemp1[0]     ;  (v0 << 4) ^ (v0 >> 5)
  62.         EOR     Vtemp0[1],Vtemp1[1]
  63.         EOR     Vtemp0[2],Vtemp1[2]
  64.         EOR     Vtemp0[3],Vtemp1[3]
  65.  
  66.         ADD     Vtemp0[0],V0[0]         ;  ((v0 << 4) ^ (v0 >> 5)) + v0
  67.         ADC     Vtemp0[1],V0[1]         ; Vtemp0 = ((v0 << 4) ^ (v0 >> 5)) + v0
  68.         ADC     Vtemp0[2],V0[2]
  69.         ADC     Vtemp0[3],V0[3]
  70.  
  71.         SBRS    Count,0
  72.         RJMP    Primer_t                ; Si es Par indica que es el primero. Si es impar es el segundo
  73. ;Seg_t
  74.         MOV     R0,sum[0]               ; sum & 3 , necesito multiplicarlo por 4, ya que son 4 bytes cada valor de llave
  75.         LSL     R0
  76.         LSL     R0
  77.         RJMP    Save_Sum
  78. Primer_t
  79.         MOV     R0,sum[1]               ; sum>>11 & 3 , 000a a000, 1 shift derecha, es igual a lo que se pide * 4
  80.         LSR     R0
  81. Save_Sum
  82.         ANDI    R0,0x0C                 ; 0000 aa00
  83.         ADD     ZL,R0                   ; Le sumo el valor de R0 o lo que es igual a 4 * index
  84.         LD      Vtemp1[0],Z+            ; key[sum&3] o key[(key>>11) & 3]
  85.         LD      Vtemp1[1],Z+
  86.         LD      Vtemp1[2],Z+
  87.         LD      Vtemp1[3],Z+
  88.  
  89.         ADD     Vtemp1[0],sum[0]        ; sum + key[(sum>>11) & 3]
  90.         ADC     Vtemp1[1],sum[1]        ; Aux = sum + key[(sum>>11) & 3]
  91.         ADC     Vtemp1[2],sum[2]
  92.         ADC     Vtemp1[3],sum[3]
  93.  
  94.         EOR     Vtemp0[0],Vtemp1[0]     ;  (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3])
  95.         EOR     Vtemp0[1],Vtemp1[1]     ;   Vtemp[0]
  96.         EOR     Vtemp0[2],Vtemp1[2]
  97.         EOR     Vtemp0[3],Vtemp1[3]
  98.  
  99.         SUB     V1[0],Vtemp0[0]         ; v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3])
  100.         SBC     V1[1],Vtemp0[1]
  101.         SBC     V1[2],Vtemp0[2]
  102.         SBC     V1[3],Vtemp0[3]         ; si ocurrio overflow ocurrio, lo lamento
  103.         RET

Me falta la parte de la inicializacion, en el que Z es a la base de Key
Paso de 105 lineas a 75, creo que podria reducirse en 3 lineas mas si hago el pasaje de V0 a V1 en un call.

Código: [Seleccionar]
R1  =
R2  =
R3  =
R4  =
R5  = Round
R6  = V1[0]
R7  = V1[1]
R8  = V1[2]
R9  = V1[3]
R10 = sum[0]
R11 = sum[1]
R12 = sum[2]
R13 = sum[3]
R14 = V0[0]
R15 = V0[1]
R16 = V0[2]
R17 = V0[3]
R18 = Vtemp0[0]
R19 = Vtemp0[1]
R20 = Vtemp0[2]
R21 = Vtemp0[3]
R22 = Vtemp1[0]
R23 = Vtemp1[1]
R24 = Vtemp1[2]
R25 = Vtemp1[3]
R26 = XL
R27 = XH
R28 = YL = SP
R29 = YH = SP
R30 = ZL
R31 = ZH

Como casi no utilizo la RAM podrias casi llenarla, esperar a decodificar todo y enviarle un mensaje al PC cuando este listo para recibir mas datos.
De la RAM necesito lugar para solo para los CALLs, cada CALL son 2bytes que es la direccion de retorno. Asi que para este codigo estara entre 3 a 4 CALLs como mucho. Inclusive el de llamada a desencriptarlo, unos 10bytes o por ahi cerca.
Hay 512 bytes. Asi que si haces bloques de 64bytes, podrias meter 7 bloques todo de una ocupandote 448 bytes y teniendo mucho espacio de RAM para el stack.

Si no era el problema el espacio, se podia pre-calcular sum, para cada vuelta. pero como el espacio apremia, entonces es preferible usar unas 10/20 instrucciones mas.
La otra es precalcularlo y guardarlo en una posicion especifica de la memoria, lo cual reduciria en 6 intrucciones el calculo de los terminos (lo cual haria mas rapido), pero agregaria mas instrucciones al inicio, por que hay que calcular todos los valores antes. Asi que estamos igual de mal sea la situacion que sea.

Mas compacto no se.. Intente usar las instrucciones que mejor se acomodaban para esto. Luego paso la inicializacion, Pero estoy mas que seguro que vas a terminar con unos 100 y algo de lineas.
« Última modificación: 22 de Septiembre de 2015, 12:37:33 por KILLERJC »