Iro*_*Pug 9 c dos real-mode watcom x86-16
我正在尝试用 C 语言对实模式 MS-DOS 进行编程。使用一些关于游戏编程的旧书作为起点。书中的源代码是为 Microsoft C 编写的,但我试图让它在 OpenWatcom v2 下编译。当我尝试访问指向 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;
}
Run Code Online (Sandbox Code Playgroud)
这是远指针赋值引发以下错误:
VGA.C(33):错误!E1077:缺少 '}'
VGA.C(33):警告!W107:缺少函数“main”的返回值
VGA.C(36):错误!E1099: 语句必须位于函数内部。可能的原因:缺少{
这有点令人困惑,似乎宏定义出了问题,或者是什么......
当我使用相同的编译器尝试维基百科关于远指针的文章中的代码时:
#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;
}
Run Code Online (Sandbox Code Playgroud)
它编译。编译命令适用wcl -bcl=dos source.c于两种情况。
所以我现在有点困惑,似乎无法查明问题所在。我即将在随机的地方扔一些星号和括号,看看它是否粘在某个地方......
Mic*_*tch 12
您的 OpenWatcom C 编译器似乎默认使用 C89。在 C89 中,变量声明必须位于块作用域的开头。在您的情况下,所有代码和数据都在函数范围内,因此必须在main代码之前的开头声明该变量。
以这种方式移动变量声明应该与 C89 兼容:
int main(void)
{
char far *video_buffer = (char far *)0xA0000000L;
Set_Video_Mode(0x13);
while (!kbhit()) { };
Set_Video_Mode(0x03);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果按照您的建议使用 OpenWatcom 2.0,您应该能够通过-za99在wcl选项中添加该选项来使用 C99 模式进行编译。在 C99 中,您可以将变量声明放置在块作用域顶部以外的位置。
当编译为 C89 时,Watcom 扩展了 C89 以允许 C++ 样式注释,就像 C99 支持它一样。这种行为似乎被记录为:
Open Watcom C/16 和 C/32 编译器支持注释扩展。符号 // 可以用在物理源代码行中的任何位置(字符常量或字符串文字内部除外)。从 // 到行尾的任何字符都被视为注释字符。注释在行尾结束。
我同意这样的评估:如果不允许 C++ 风格的注释,编译器会更好地了解真正的问题是什么。一开始我也被愚弄了,我并没有立即意识到它被编译为 C89 代码。自从被接受以来我就假设//它一定是C99。