Estoy tratando de entender la programación de MS-DOS en modo real en C. Usando algunos libros antiguos sobre programación de juegos como punto de partida. El código fuente del libro está escrito para Microsoft C, pero estoy tratando de compilarlo en OpenWatcom v2. Me encontré con un problema al principio, al intentar acceder a un puntero al inicio de la memoria de video VGA.
#include <stdio.h> #include <dos.h> void Set_Video_Mode(int mode) { union REGS inregs, outregs; inregs.h.ah = 0; inregs.h.al = (unsigned char) mode; int86(0x10, &inregs, &outregs); } int main(void) { Set_Video_Mode(0x13); //the following line throws an error, without it the code compiles and runs char far *video_buffer = (char far *)0xA0000000L; while (!kbhit()) { }; Set_Video_Mode(0x03); return 0; }Es la asignación del puntero lejano la que arroja los siguientes errores:
VGA.C(33): ¡Error! E1077: Falta '}'
VGA.C(33): ¡Advertencia! W107: Falta el valor de retorno para la función 'principal'
VGA.C(36): ¡Error! E1099: La instrucción debe estar dentro de la función. Causa probable: falta {
Lo cual es un poco desconcertante, y parece que una definición de macro salió mal, o algo así...
Cuando pruebo el código del artículo de Wikipedia sobre punteros lejanos, con el mismo compilador:
#include <stdio.h> int main() { char far *p = (char far *)0x55550005; char far *q = (char far *)0x53332225; *p = 80; (*p)++; printf("%d", *q); return 0; } Se compila. El comando de compilación es wcl -bcl=dos source.c en ambos casos.
Así que estoy un poco perplejo ahora, y parece que no puedo identificar el problema. Estoy a punto de tirar algunos asteriscos y corchetes en lugares aleatorios para ver si se pega en alguna parte...
Parece que su compilador OpenWatcom C está predeterminado para usar C89. En C89, las declaraciones de variables deben estar al comienzo de un alcance de bloque. En su caso, todo su código y datos están en el alcance de la función, por lo que la variable debe declararse al comienzo de main antes del código.
Mover la declaración de la variable de esta manera debería ser compatible con C89:
int main(void) { char far *video_buffer = (char far *)0xA0000000L; Set_Video_Mode(0x13); while (!kbhit()) { }; Set_Video_Mode(0x03); return 0; } Si usa OpenWatcom 2.0 como sugiere, debería poder compilar con el modo C99 agregando la opción -za99 a las opciones de wcl . En C99 puede colocar declaraciones de variables en lugares que no sean la parte superior del alcance del bloque.
Al compilar como C89, Watcom amplió C89 para permitir comentarios de estilo C++ de la misma manera que C99 lo admite. Este comportamiento parece estar documentado como:
Los compiladores Open Watcom C/16 y C/32 admiten una extensión para comentarios. El símbolo // se puede utilizar en cualquier punto de una línea de origen física (excepto dentro de una constante de carácter o un literal de cadena). Todos los caracteres desde // hasta el final de la línea se tratan como caracteres de comentario. El comentario termina al final de la línea.
Estoy de acuerdo con la evaluación de que si no se hubieran permitido los comentarios de estilo C ++, el compilador habría dado una idea mucho mejor de cuál era el problema real. A mí también me engañaron al principio y no se me ocurrió de inmediato que se estaba compilando como código C89. Supuse que desde que se aceptó // que debe haber sido C99.