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

问题描述 投票:0回答:1

我对

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(int argc, char *argv[]) {
  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);
}


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

开始编码后,我注意到

memset
并未将堆数组的所有字节设置为 0xf。

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

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

有什么帮助吗?

PS:我对 C 还很陌生。

c x86-16 dos turbo-c
1个回答
7
投票

在 MS-DOS 中,内存按不超过 64K 的

segments
组织。

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

如果您使用

unsigned char
(单字节)而不是
int
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);
}

正如 @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);
}
© www.soinside.com 2019 - 2024. All rights reserved.