entero binario sin signo de 32 bits a BCD de 8 bits en AVR ASM para ATtiny. ¿Cómo hacerlo más eficiente?

5

Escribí un programa en AVR ASM para convertir los números binarios sin signo 32-bit a 8 digit decimales basados en el shift-add-3 . (Sé que 32-bit es más de 8 dígitos, pero solo necesito 8.)

La entrada 32-bit está en R16-R19 (bajo-alto).

La salida 8 digit está en R20-R24 (bajo-alto), 2 números / byte, uno en el nibble inferior, uno en el nibble superior.

Mi problema: Se requieren ~ 1500 ciclos para calcular un número 16-bit y ~ 2000 ciclos para calcular un 32-bit .

¿Puede alguien sugerirme un método más rápido y más profesional para esto? Ejecutar un procedimiento de 2000 ciclos en un ATtiny en 32,768 Khz no es algo con lo que me sienta cómodo.

Mapa de uso de memoria:

Definiciones:

.def    a0  =   r16
.def    a1  =   r17
.def    a2  =   r18
.def    a3  =   r19

.def    b0  =   r20
.def    b1  =   r21
.def    b2  =   r22
.def    b3  =   r23

.def    i   =   r24
.def    j   =   r25

El código:

BinaryToBCD:
    clr     b0
    clr     b1
    clr     b2
    clr     b3
    ldi     i,  32
    sts     0x0068, i       ;(SRAM s8)

BinaryToBCD_1:
    clc
    rol     a0
    rol     a1
    rol     a2
    rol     a3
    rol     b0
    rol     b1
    rol     b2
    rol     b3

    lds     i, 0x0068       ;(SRAM s8)
    dec     i
    sts     0x0068, i       ;(SRAM s8)
    brne    BinaryToBCD_2
    ret

BinaryToBCD_2:
    cpi     b0,     0
    breq    BinaryToBCD_3
    mov     i,      b0
    rcall   Add3ToNibbles
    mov     b0,     i

BinaryToBCD_3:
    cpi     b1,     0
    breq    BinaryToBCD_4
    mov     i,      b1
    rcall   Add3ToNibbles
    mov     b1,     i

BinaryToBCD_4:
    cpi     b2,     0
    breq    BinaryToBCD_5
    mov     i,      b2
    rcall   Add3ToNibbles
    mov     b2,     i

BinaryToBCD_5:
    cpi     b3,     0
    breq    BinaryToBCD_1
    mov     i,      b3
    rcall   Add3ToNibbles
    mov     b3,     i
    rjmp    BinaryToBCD_1


Add3ToNibbles:
    mov     j,      i
    andi    j,      0b00001111
    cpi     j,      5
    in      j,      SREG
    sbrs    j,      0
    subi    i,      -3

    mov     j,      i
    swap    j
    andi    j,      0b00001111
    cpi     j,      5
    in      j,      SREG
    sbrs    j,      0
    subi    i,      -48
    ret
    
pregunta Gábor Dani

2 respuestas

1

Esto se basa en el enfoque de venny (venny lo llamó triangulación), expresado en un "pseudo-C":

uint32 x; // input variable to convert

w = { 2, 1, 4, 7, 4, 8, 3, 6, 4, 8 }; // 2^31
r = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // initial result = 0

for (i = 31; i >= 0; i --)
{
   if ( 2^i  AND x )  // is x's bit i up?
      add(r, w);      // if yes, 1 ASCII ADD and 9 ASCII ADD w/CARRY MAX
   divide(w, 2)       // 10 SHIFT RIGHT MAX
}

Las rutinas de adición y división no son una explicación necesaria, imo.

    
respondido por el asndre
0

Hay una serie de documentos y notas de aplicación sobre el tema. Por ejemplo, enlace

    
respondido por el pjc50

Lea otras preguntas en las etiquetas