¡Buenas!
Después de actualizar a la última versión de sdcc (3.5.0) me encuentro conque casi todo me ha dejado de funcionar.
Supongo que al tener el parámetro --oldralloc roto hay que hacer cambios en el inline assembler de funciones de C con parámetros y en las rutinas de ensamblador puro que reciben parámetros. ¿Sabe alguien con certeza cuáles son? Hay funciones que parece ser que no me dan problemas accediendo a los parámetros a través de IX pero otras que no.
Compilo con --fno-omit-frame-pointer
¡Ayuda!
SDCC y ASM
- ronaldo
- Forum Addict
- Mensajes: 358
- Registrado: Sab 14 Sep , 2013 9:31 pm
- Ubicación: Alicante
- Contactar:
Re: SDCC y ASM
Hola pacomix,
Hace unos meses publicamos algo por aquí al respecto (no recuerdo donde está). Tuve una conversación con los desarrolladores de SDCC y nos dijeron claramente que no usemos --fomit-frame-pointer porque tiene bugs y está deprecated desde hace tiempo (no van a corregirse los bugs). Lo mismo para --old-ralloc, que seguramente ya habrán dejado de soportarlo. Es más, todo surgió porque hice unas comparativas en las que ambos parámetros se observa que afectan muy negativamente al rendimiento y al espacio ocupado por el código generado.
Las recomendaciones son las siguientes:
Hace unos meses publicamos algo por aquí al respecto (no recuerdo donde está). Tuve una conversación con los desarrolladores de SDCC y nos dijeron claramente que no usemos --fomit-frame-pointer porque tiene bugs y está deprecated desde hace tiempo (no van a corregirse los bugs). Lo mismo para --old-ralloc, que seguramente ya habrán dejado de soportarlo. Es más, todo surgió porque hice unas comparativas en las que ambos parámetros se observa que afectan muy negativamente al rendimiento y al espacio ocupado por el código generado.
Las recomendaciones son las siguientes:
- Si una función utiliza IX o IY, salvarlos siempre y restaurarlos. De lo contrario, se pueden producir efectos laterales difíciles de identificar y depurar.
- Utilizar los nuevos modos que incorpora SDCC para obtener parámetros, adoptados de Z88DK: __z88dk_callee y __z88dk_fastcall.
- Con __z88dk_callee, se pueden obtener los parámetros de la pila usando POP y hacer push únicamente de la dirección de retorno.
- __z88dk_fastcall pasa parámetros de 8 bits en L, de 16 bits en HL y de 32 bits en DE:HL (esto último no lo he comprobado, pero es fácil de probar)
- No utilices SDCC 3.5.0. Bájate la 3.5.5. Hay un bug en la SDCC 3.5.0. con optimizaciones de recursión de cola que afecta a las convenciones de llamada __z88dk.
Re: SDCC y ASM
¡Muchas gracias! Tendré que repasar el inline assembler de todas mis funciones de C. Funcionan muchas cosas pero otras no. Sorprendentemente las funciones de assembler puro que uso de la cpcrslib y las rutinas de acceso a disco que escribí en asm puro me funcionan sin problemas... eso sin siquiera restaurar registros que modifico. Hablo desde la ignorancia... seguramente esto sea así para funciones escritas en ensamblador directamente (ficheros .s).
Os iré contando!
Os iré contando!
- ronaldo
- Forum Addict
- Mensajes: 358
- Registrado: Sab 14 Sep , 2013 9:31 pm
- Ubicación: Alicante
- Contactar:
Re: SDCC y ASM
Eso que dices es lógico. Tienes que tener en cuenta que SDCC genera automáticamente código para recoger los parámetros de las funciones definidas en C. Si quieres incluir una función completa, programada con ASM inline, deberías declararla como __naked. Un ejemplo:
Al declarar una función como __naked, SDCC no genera ningún código para la recogida de parámetros, dejándonos a nosotros todo el control, exactamente igual que si hubieramos definido la función en ensamblador completo (en un .s, por ejemplo).
Una cosa muy importante: mucho código de versiones anteriores de SDCC modifica los registros IX e IY sin salvarlos. Este tipo de modificación genera efectos laterales que pueden no ser perceptibles dependiendo de cómo programes en C. Aparentemente, las funciones van, pero en realidad tienen un problema grave que hace que el programa falle conforme continúas el desarrollo. He visto a muchos programadores frustrarse y culpar a SDCC de tener bugs, siendo en muchos casos un efecto lateral de haber modificado IX e IY. SDCC utiliza estos registros para apuntar a la pila y obtener/modificar las variables locales de las funciones. SDCC asume que no los vas a modificar. Si lo haces, los valores de las variables locales pueden cambiar aleatoriamente al volver de las funciones que hagan esto.
Por tanto, si tienes código que obtiene los parámetros de la pila usando IX o funciones que lo modifican, mejor revísalas y cámbia el código por algo como el ejemplo. Además, con __z88dk_callee y push/pops el código es más compacto y rápido que usando IX.
Código: Seleccionar todo
void mifuncion(int a, int b) __naked __z88dk_callee {
__asm
pop af ;; Dirección de retorno
pop hl ;; HL = parámetro A
pop de ;; DE = parámetro B
push af ;; Dejamos la dirección de retorno en la pila otra vez
;;; Aquí el código de la función
ret ;; Retorno
__endasm;
}
Una cosa muy importante: mucho código de versiones anteriores de SDCC modifica los registros IX e IY sin salvarlos. Este tipo de modificación genera efectos laterales que pueden no ser perceptibles dependiendo de cómo programes en C. Aparentemente, las funciones van, pero en realidad tienen un problema grave que hace que el programa falle conforme continúas el desarrollo. He visto a muchos programadores frustrarse y culpar a SDCC de tener bugs, siendo en muchos casos un efecto lateral de haber modificado IX e IY. SDCC utiliza estos registros para apuntar a la pila y obtener/modificar las variables locales de las funciones. SDCC asume que no los vas a modificar. Si lo haces, los valores de las variables locales pueden cambiar aleatoriamente al volver de las funciones que hagan esto.
Por tanto, si tienes código que obtiene los parámetros de la pila usando IX o funciones que lo modifican, mejor revísalas y cámbia el código por algo como el ejemplo. Además, con __z88dk_callee y push/pops el código es más compacto y rápido que usando IX.
Re: SDCC y ASM
Muchas gracias Ronaldo por tu aportación. ¡N¡ google oiga!
Seguramente tengo por ahí una función que modifica o hace uso de IX y no lo restauro al final. Por cierto vaya jugada lo de la dirección de retorno; ya podrían dejarla como último parámetro y así se ahorra el pop af push af...
A ver si saco algo de tiempo a final de semana para dejar la update del cpc bros a la 3.5.5 listo.
¡Saludos!
Seguramente tengo por ahí una función que modifica o hace uso de IX y no lo restauro al final. Por cierto vaya jugada lo de la dirección de retorno; ya podrían dejarla como último parámetro y así se ahorra el pop af push af...
A ver si saco algo de tiempo a final de semana para dejar la update del cpc bros a la 3.5.5 listo.
¡Saludos!
Re: SDCC y ASM
Durante la compilación de la función propuesta, SDCC indica el siguiente warning respecto a los parámetros a y b: "unreferenced function argument". Entiendo que no detecta el uso de los mismos dentro del código ASM. ¿Hay alguna forma de que no salgan estos avisos?
- ronaldo
- Forum Addict
- Mensajes: 358
- Registrado: Sab 14 Sep , 2013 9:31 pm
- Ubicación: Alicante
- Contactar:
Re: SDCC y ASM
No lo detecta porque no puede detectarlo. En el código ensamblador Z80 no hay forma de hacer referencia a las variables de C. Estás usando la pila, que no es exactamente lo mismo que usar las variables, así que no puede detectarlo.
Personalmente, cuando se va a introducir ensamblador en un programa para Amstrad con SDCC, recomiendo crear las funciones en ficheros aparte, que sean sólo ensamblador. Después en C se puede declarar la cabecera de la función y usarse, que el linker ya hará su trabajo. Es mucho mejor, ya que el código inline en SDCC es sucio y no es igual de funcional que el código directo en ensamblador. Mejor esta vía, que la de andar sorteando al compilador. Además, si usas CPCtelera, basta con que crees ficheros con extensión .s en tu carpeta src/ y automáticamente serán ensamblados al compilar el programa con make.
De todas formas, si quieres eliminar el warning, hay una forma fácil de hacerlo: usando la variable en una expresión vacía (sin asignación). Aquí tienes un ejemplo:
C permite crear expresiones sin asignación, lo que es como decirle que haga una operación sin guardar el resultado. La gracia es que eso no genera ningún código pero, a efectos del compilador, ya cuenta como que has hecho uso de la variable. Con esto, los warnings desaparecen.
Personalmente, cuando se va a introducir ensamblador en un programa para Amstrad con SDCC, recomiendo crear las funciones en ficheros aparte, que sean sólo ensamblador. Después en C se puede declarar la cabecera de la función y usarse, que el linker ya hará su trabajo. Es mucho mejor, ya que el código inline en SDCC es sucio y no es igual de funcional que el código directo en ensamblador. Mejor esta vía, que la de andar sorteando al compilador. Además, si usas CPCtelera, basta con que crees ficheros con extensión .s en tu carpeta src/ y automáticamente serán ensamblados al compilar el programa con make.
De todas formas, si quieres eliminar el warning, hay una forma fácil de hacerlo: usando la variable en una expresión vacía (sin asignación). Aquí tienes un ejemplo:
Código: Seleccionar todo
void mifuncion(int a, int b) __naked __z88dk_callee {
a; // Expresión vacía que usa a sin hacer nada
b; // Lo mismo para b
__asm
pop af
pop bc
pop de
push af
;;
;; Más cosas que hacer aquí
;;
ret
__endasm;
}
Re: SDCC y ASM
Olé!
Solucionado. Gracias por la respuesta. Ambas opciones me parecen buenas soluciones para este caso.
Solucionado. Gracias por la respuesta. Ambas opciones me parecen buenas soluciones para este caso.
¿Quién está conectado?
Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro
La Comunidad Española |