为什么我的 DOS 程序在我 memset 一个 64000 个 int 数组后崩溃了?

Sli*_*ore 1 c dos turbo-c x86-16

memset我在 Turbo C 中遇到了一个大的 for 循环问题。

当代码开始崩溃时,我正在 Virtual Box 上的 MS-DOS 6.22 上使用 Turbo C++ 3.00 编写一个基于模式 13h 的小型图形库。

我知道 Turbo C 确实已经过时了,但我想在类似 DOS 的系统上尝试旧式编码。

这是我的代码:

#include <stdlib.h>
#include <conio.h>
#include <stdio.h>
#include <string.h>
#include <dos.h>

int main(void) {
  int *buf;
  unsigned int i;

  _AH = 0x0;
  _AL = 0x13;
  geninterrupt(0x10);

  buf = malloc(sizeof(int)*64000);
  memset(buf,15,64000); //can't figure out why memset does not work properly...

  for (i=0;i< (unsigned int)64000;i++){
    buf[i] = 15; //trying to forcely set each byte to 0xf...
    pokeb(0xA000,i,buf[i]); //outputting to VGA
  }

  getch();
  free(buf);
  return(0);
}
Run Code Online (Sandbox Code Playgroud)

我想做的基本上就是用白色填充屏幕。

当我开始编码时,我注意到并memset没有将堆数组的所有字节设置为 0xf。

所以我决定通过编写 for 循环来手动设置它们。

我运行了它,它的效果就像黄油一样。当我将字节戳到屏幕上时,程序崩溃了,我不明白为什么......

有什么帮助吗?

PS:我对C还很陌生。

And*_*ton 7

在 MS-DOS 中,内存被组织成不超过 64K 的段。

您的 64,000 个整数的缓冲区比这个更大。

如果您使用unsigned char(单字节)而不是intor unsigned int(我似乎记得在 DOS/Turbo C++ 中是 16 位),那么它将适合单个段并且应该可以正常工作。

...当您存储要插入视频内存的字节时,您不需要整数提供的额外位宽。

#include <stdlib.h>
#include <conio.h>
#include <stdio.h>
#include <string.h>
#include <dos.h>

int main() {
  unsigned char *buf;
  unsigned int i;

  _AH = 0x0;
  _AL = 0x13;
  geninterrupt(0x10);

  buf = malloc(64000);
  memset(buf, 15, 64000);

  for (i=0; i < (unsigned int)64000; i++) {
    pokeb(0xA000, i, buf[i]); //outputting to VGA
  }
  getch();
  free(buf);
  return(0);
}
Run Code Online (Sandbox Code Playgroud)

正如 @Jabberwocky 所提到的,如果您不打算做任何其他事情,而是将这些值直接插入视频 RAM,您甚至可以完全忽略缓冲区:

int main() {
  unsigned int i;

  _AH = 0x0;
  _AL = 0x13;
  geninterrupt(0x10);

  for (i=0; i < (unsigned int)64000; i++) {
    pokeb(0xA000, i, 15); //outputting to VGA
  }
  getch();
  return(0);
}
Run Code Online (Sandbox Code Playgroud)

  • 实际上用“0xf”替换“buf[i]”并删除所有 malloc/memset/free 应该做同样的事情。 (3认同)
  • @SlickSpore:如果你想渲染到(回写可缓存)缓冲区,然后复制到视频 RAM,你将需要使用像“memcpy”这样的东西来有效地复制,而不是一次一个字节具有潜在的功能 -呼叫开销!除非`pokeb`内联并且可以将段寄存器(如ES)的设置提升到循环之外。如果不是,调用它 64k 次将比仅更新视频 RAM 中已更改的像素慢得多。特别是如果视频 RAM 不可缓存(无需写入组合),因此您的 1 字节传输全部单独进行,甚至一次不是 32 位双字,更不用说 64B 了。 (3认同)
  • `int` 和 `unsigned` 在 Turbo C 环境中绝对是 16 位。 (2认同)
  • 我的目标是制作一个帧缓冲区数组来存储整个帧,希望使实际渲染速度更快...... (2认同)