sábado, 17 de septiembre de 2011

Programando con SDCC. Funciones y retornos.

A la hora de programar con SDCC me he encontrado con algunos problemas, que francamente no se si están descritos en alguna parte, pero quiero compartirlos por si alguien se anima a programar con este compilador cruzado y se encuentra que no le funcionan sus programas.

En este post, voy ha hablar de dos casos relacionados con la creación de funciones.

El primero se da en funciones que no devuelven datos (void). Lo normal es que no se incluya la sentencia "RETURN" y por lo general funcionara correctamente, pero me he encontrado con casos en los que me ha dado un error al compilar (cuando compila el código ensamblador que genera a partir del fuente C). La causa la desconozco pero si no recuerdo mal en todos los casos finalizaba la función con una condición de tipo "IF" o "SWITCH CASE". Se soluciona incorporando siempre un retorno.

El segundo caso, es cuando realizamos una función en ensamblador dentro de nuestro fuente en C, y queremos que en un determinado momento salga con un "ret". Las funciones en ensamblador cuando se compilan, añade un retorno automáticamente al final de esta, pero en el caso de que la función le pasemos datos, el compilador añade un "push IX" al inicio y por consiguiente al final añade un "pop IX". En estos casos si ponemos un retorno se colgará nuestro programa al ejecutarlo. Para solucionarlo, antes tendremos que añadir un "pop IX".

Ejemplo:
void IniciaDatos(char valor)
{
valor;
__asm
ld HL,#DATA

ld A,4(IX)
cp #0
jr Z,COPY

ld B,#0
ld C,A

sla C ; multiplico por 8
sla C
sla C

ADD HL,BC

COPY:
ld DE,#BUFFER
ld BC,#8

ldir

pop IX ; IMPORTANTE! solo en funciones con entrada de datos
ret

DATA:
.db 0x00,0x02,0x06,0x0E,0x1E,0x3E,0x7E,0x00
.db 0x38,0x44,0x82,0x82,0x82,0x44,0x38,0x00
.db 0xFF,0xE7,0xC3,0x81,0x00,0x18,0x3C,0x7E
.db 0xF0,0xF0,0xF0,0xF0,0x0F,0x0F,0x0F,0x0F

__endasm;
}

2 comentarios:

  1. Prueba a añadir __naked a la definición de la función. El compilador no añadirá nada de nada a tu código, y de lo único que debes preocuparte es de preservar IX. Ejemplo chorra:

    void copy(byte* to, byte* from, int len) __naked
    {
    __asm

    push ix
    ld ix,#4
    add ix,sp
    ld e,(ix)
    ld d,1(ix)
    ld l,2(ix)
    ld h,3(ix)
    ld c,4(ix)
    ld b,5(ix)
    ldir
    pop ix
    ret

    __endasm;
    }

    ResponderEliminar
  2. no lo conocía... :-O
    gracias Konamiman!

    ResponderEliminar