El problema que tienes no tiene nada que ver con la fuente. Es un problema diferente. Fíjate bien en la salida de la consola, que es algo que debes hacer siempre, para darte cuenta de dónde se produce el error. El error viene en la parte que dice "Creating Cassette File". Eso es posterior a haber compilado, enlazado y generado el binario (lo puedes ver más arriba). Por tanto, lo primero que debes deducir de ahí, es que el error no es ni de compilación, ni de enlazado. No es un error de código, ni de programación, porque todo tu programa compila, enlaza y genera el binario. Así pues, no puede ser un error del fichero de fuentes, que es simplemente un fichero ensamblador que se ensambla y linka.
El error, por tanto, es de la herramienta que está tomando el fichero binario y generando el fichero CDT de cinta. La herramienta es CPC2CDT. Como siempre os digo, lo primero que hay que hacer con las cosas es leer __detenidamente__, es decir, dando significado a cada cosa que lees y entendiendo exactamente qué significa. Así es como hubieras deducido tú mismo esto que te acabo de explicar, y no intentarías buscar errores en lugares en que no los vas a encontrar porque no están.
Ahora, ¿Por qué falla CPC2CDT? El error tiene que ver con una "lectura corta" (short read) en "AMSDOS headermake[1]". ¿Qué significa esto? Cuando se añade un fichero a una cinta, se está añadiendo de forma que luego pueda ser leído. En este caso, quien tiene que leer los ficheros que se añaden a la cinta es el programita que hay en el firmware del AMSTRAD, el programa cargador que se ejecuta cuando escribes RUN". Ese programa es el que lee de cinta y tiene que entender lo que lee en la cinta y saber qué hacer con ello. Para eso, a los ficheros en cinta se les añaden 128 bytes iniciales de metadatos para que el firmware sepa qué debe hacer con el fichero: estos 128 bytes contienen el nombre del fichero, el tipo de fichero que és, cuánto ocupa, en qué posición de memoria debe ser cargado y cuál es la posición de memoria donde debe empezar la ejecución, si es un ejecutable, entre otras cosas. Sin eso, el firmware no sabría nada de todo esto. Esos 128 bytes que se añaden están estructurados de una forma concreta llamada "cabecera AMSDOS" (AMSDOS header). El programa CPC2CDT añade esta cabecera automáticamente __SOLO si el fichero no tiene ya una__. ¿Cómo sabe si el fichero tiene una cabecera AMSDOS? Las cabeceras AMSDOS tiene un byte al final que es el byte de verificación de suma (checksum). Conforme se lee una cabecera AMSDOS, hay que llevar una cuenta que va simplemente sumando todos los bytes. De la suma final, se desprecia el acarreo (acarreo es lo que manualmente llamamos, "me llevo una") y el resultado se representa sólo con 1 byte. La suma de los 128 bytes de cualquier cabecera AMSDOS debe dar 00. El último byte, por tanto, el de checksum, se calcula cuando se pone la cabecera AMSDOS para que sea exactamente lo que falta para sumar 00. Esto sirve para verificar, cuando lees de cassette, que lo que se ha leído es correcto y no hay errores. Si hay errores de lectura (algo frecuente), la suma sale mal y se puede detectar el error.
Ocurre que CPC2CDT simplemente suma los 128 primeros bytes de tu fichero binario y, si la suma da 00, asume que eso es una cabecera AMSDOS. Por tanto, la deja como está y no añade una. Sin embargo, puede ocurrir por casualidad que tus 128 primeros bytes sumen 00, pero no sean (como no son ahora mismo) una cabecera AMSDOS. Entonces, el resto del programa, que la interpreta, da error, que es lo que ha pasado ahí. Ese es el problema.
¿Cómo puedes solucionarlo? Fácil. Los 128 primeros bytes de tu binario no pueden sumar 00. Basta con que añadas 1 byte al principio con un valor que altere la suma. Crea un nuevo fichero loquequieras.s en tu proyecto y haces que simplemente emita 1 byte al binario (con .DB). Emites un byte con un 01, por ejemplo y te aseguras que ese byte vaya el primero en el binario. Como tus fuentes están en 0x40 en memoria (posición Absoluta (ABS), que es lo que ves en el fichero generado por cpct_png2chars), y ahí es donde empieza tu programa en memoria (Records Start = 40), basta con que pongas ese byte en la posición anterior (la 3F, ojo, no la 39, que está en hexadecimal). ¿Como haces que ese byte vaya ahí? De la misma manera que lo hace png2chars, creando un area posicionada de forma absoluta (.area LLAMALACOMOQUIERAS (ABS)) y diciéndole dónde quieres que esté (.org 0x3F) org = origin. Ahí pones tu .DB para emitir un byte, y listo. Así te aseguras que los 128 primeros bytes no sumen 00.
Más adelante, cuando cambies las cosas de tu binario final, puedes probar a quitarlo y ver si los 128 primeros bytes ya han dejado de sumar 00 de forma natural.
Esta es la respuesta del profesor Francisco y con la que he conseguido solucionar el problema, por si alguien se encuntra con el mismo problema.