Hello World en C para el C64 #Programación retro del Commodore 64

La página de documentación de cc65 (https://cc65.github.io/doc/) tiene cuatro apartados:

  • Un primer apartado con documentación sobre los programas, es decir, sobre el macro ensamblador (ca65.exe), el compilador (cc65.exe), el enlazador (ld65.exe), el compilador – enlazador (cl65.exe), etc.
  • Un segundo apartado con documentación sobre el uso de cc65. Este segundo apartado incluye el clásico ejemplo "Hello World", trucos para conseguir programas más eficientes, depuración, etc.
  • Un tercer apartado sobre el entorno de ejecución de cc65 (cc65 runtime), la implementación en cc65 de las librerías típicas de C (ANSI / ISO C), y otras librerías propias de cc65 como "dio" para acceso a disco, "tgi" para gráficos, "geos" para el sistema operativo GEOS, "conio" para entrada / salida, "joystick" para manejo de joystick, "mouse" para manejo de ratón, etc.
  • Un cuarto apartado con información específica de las plataformas de destino de cc65, es decir, Apple II, Atari, VIC20, C16, C64, C128, etc.

En esta entrada vamos a revisar el clásico ejemplo "Hello World" para el C64, lo que nos servirá como introducción a todos los apartados anteriores. Este ejemplo se describe en la página https://cc65.github.io/doc/intro.html.

Ficheros fuente:

Los ficheros fuente están en la carpeta cc65\samples\tutorial:

Los ficheros fuente son:

  • "hello.c": Este fichero está en C.
  • "text.s": Este fichero está en ensamblador del 6502.

El fichero "Makefile" no es parte del código fuente, es decir, no es parte del programa propiamente dicho. Permite automatizar la compilación y construcción del programa con la herramienta "make" típica de los sistemas Unix / Linux.

El fichero "hello.c" es así:

Es decir, este programa en C referencia una variable llamada "text", de tipo array de char, y declarada en el fichero en ensamblador "text.s". También implementa la función main(), que es el programa principal. Este programa principal básicamente llama a la función printf() pasando la variable "text", que la imprime por consola / pantalla, y luego termina devolviendo el código EXIT_SUCCESS, que indica que el programa ha terminado correctamente.

Por otro lado, el fichero "text.s" es así:

Es decir, es un programa en ensamblador que declara la variable "text" y le da el valor ASCII "Hello world!".

No es necesario que la variable "text" se declare en un fichero aparte, ni mucho menos en un programa en ensamblador. El ejemplo lo hace así para ejemplificar la combinación de programas en C y programas en ensamblador, lo cual está permitido en cc65.

Proceso de compilación y construcción:

El proceso para construir el programa es así:

  • Con cc65.exe, hay que compilar el fichero "hello.c". Esto da lugar al fichero en ensamblador "hello.s".
  • Con ca65.exe, hay que ensamblar los ficheros "hello.s" y "text.s". Esto da lugar a los ficheros objeto "hello.o" y "text.o".
  • Con ld65.exe, hay que enlazar los ficheros "hello.o", "text.o" y "c64.lib". Esto da lugar al programa ejecutable "hello".

Para poder ejecutar el compilador (cc65.exe), el ensamblador (ca65.exe) y el enlazador (ld65.exe), o bien usamos el directorio bin como directorio de trabajo, o bien lo incluimos en la variable de entorno PATH, que es la lista de rutas donde Windows busca los ejecutables.

En nuestro caso usaremos bin como directorio de trabajo. Por ello, conviene tener abiertas dos ventanas, una con el directorio cc65\bin y otra con el directorio cc65\samples\tutorial para ir viendo los resultados.

De este modo, si compilamos el fichero fuente C "hello.c":

efectivamente se genera el fichero ensamblador "hello.s":

Y si ensamblamos los ficheros "hello.s" y "text.s":

efectivamente se generan los ficheros objeto "hello.o" y "text.o".

Por último, si enlazamos los ficheros "hello.o", "text.o" y "c64.lib":

efectivamente se genera el ejecutable "hello":

Programa ejecutable:

El fichero "hello" tiene formato PRG, es decir, formato de programa ejecutable para el C64. Por tanto, si arrastramos el fichero "hello" hasta el emulador VICE vemos esto:

Es decir, se carga un programa en BASIC, se ejecuta RUN, la pantalla se pone en minúsculas, y aparece el mensaje "Hello world!", que es lo que cabía esperar a la vista de cómo es el programa en C que estamos analizando.

El programa en BASIC se puede analizar con LIST:

Es decir, se trata del programa BASIC:

531 sys2061

es decir, es un programa muy simple que básicamente llama al código máquina almacenado a partir de la dirección 2061 = $080d.

Es importante recalcar que, aunque aparentemente se cargue y ejecute un programa en BASIC, en realidad, el grueso del programa generado por cc65 está en código máquina a partir de la dirección $080d. Es decir, el programa en BASIC es un mero instrumento de cc65 para ejecutar el código máquina del 6502 que resulta de compilar el programa en C.

Una alternativa más directa:

Hay una forma más directa de generar el mismo resultado. Consiste en ejecutar el programa cl65.exe, que compila y enlaza todo en uno:

De este modo se genera el ejecutable "hello" y, además, no se generan los subproductos "hello.s", "hello.o" y "text.o" (probablemente se generan igualmente, pero luego se borran):

El motivo por el que el ejecutable "hello" generado ahora ocupa 2.669 bytes, mientras que el generado antes ocupaba algo más (2.673 bytes), radica en que ahora con cl65.exe hemos usando la opción –O = Optimize code. Esta opción también puede usarse con el compilador cc65.exe.

Bueno, pues ya sabemos usar cc65 para programar en C y compilar a código máquina del C64.


Editar

Josepzin

No hay comentarios:

Publicar un comentario