gpt4 book ai didi

实模式 DOS .COM(独立式)的自定义内存分配器——如何调试?

转载 作者:太空宇宙 更新时间:2023-11-04 04:34:55 24 4
gpt4 key购买 nike

先了解一下背景:偶然发现 this blog post ,我了解到可以使用 GNU 链接器创建 DOS .COM 文件,这甚至不是火箭科学。使用 clang-m16 开关(通过相应地为 32 位指令添加前缀来创建 实模式 兼容的 32 位代码),效果很好。所以我有想法尝试实现足够的运行时间来获得 little curses game我最近写信编译成 .COM 并在 real-mode DOS 中运行。该游戏足够小,因此将所有内容(文本、数据、bss、堆、堆栈)压缩到 64KB 似乎是可行的。当然,它使用了malloc()。所以我不得不想出我自己的实现。这是它的样子:

typedef unsigned short size_t; /* from stddef.h */

typedef struct hhdr hhdr;
struct hhdr
{
void *next;
int free;
};

extern char _heap;
static char *hbreak = &_heap;
static hhdr hhead = { &_heap, 0 };

static void *newchunk(size_t size)
{
char *stack;
__asm__("mov %%esp, %0": "=rm" (stack));
if (hbreak + size > stack - 0x40) return 0;
if (size < 1024) size = 1024;
hhdr *chunk = (hhdr *)hbreak;
hbreak += size;
if (hbreak > stack - 0x40) hbreak = stack - 0x40;
chunk->next = hbreak;
chunk->free = 1;
return chunk;
}

void *malloc(size_t size)
{
if (!size) return 0;
if (size % sizeof(hhdr)) size += sizeof(hhdr) - (size % sizeof(hhdr));

hhdr *hdr = &hhead;
while ((char *)hdr->next < hbreak)
{
hdr = hdr->next;
if (hdr->free &&
(char *)hdr->next - (char *)hdr - sizeof(hhdr) >= size)
{
if ((char *)hdr->next - (char *)hdr - 2*sizeof(hhdr) > size)
{
hhdr *hdr2 = (hhdr *)((char *)hdr + sizeof(hhdr) + size);
hdr2->free = 1;
hdr2->next = hdr->next;
hdr->next = hdr2;
}
hdr->free = 0;
return (char *)hdr + sizeof(hhdr);
}
}

if (!(hdr->next = newchunk(size + sizeof(hhdr)))) return 0;
return malloc(size);
}

void free(void *ptr)
{
if (!ptr) return;
hhdr *hdr = (hhdr *)((char *)ptr - sizeof(hhdr));
hdr->free = 1;
if ((void *)hdr != hhead.next)
{
hhdr *hdr2 = hhead.next;
while (hdr2->next != hdr) hdr2 = hdr2->next;
if (hdr2->free) hdr = hdr2;
}
hhdr *next = hdr->next;
while ((char *)next < hbreak)
{
if (!next->free) break;
hdr->next = next;
next = next->next;
}
if ((char *)next == hbreak) hbreak = (char *)hdr;
}

_heap 符号由链接器定义。此处未显示 realloc(),因为它现在还未使用(因此完全未经测试)。

现在的问题是:我创建了我的 runtime在这里(malloc 在 src/libdos/stdlib.c 中),写了很多测试的东西,最后,一切似乎都运行良好。另一方面,我的游戏使用 valgrind 进行了全面测试和检查是否存在无效内存访问。尽管如此,将两个部分放在一起,它还是崩溃。 (尝试使用 make -f libdos.mk 从 git 构建游戏,您需要安装 llvm/clang)。

由于我首先经历了一个奇怪的 heisenbug(我现在解决了它),我猜这可能是优化器在为 实模式 编译时出错,这确实不常见。但我不能确定,下一个敏感的候选人可能是我的内存管理,见上文。

现在棘手的问题是:我将如何调试这样的东西?仅使用我自己的测试代码,它工作得很好。我无法在没有优化的情况下编译我的游戏,因为这样做会超过 64KB。有什么建议么?或者任何人都可以发现上面的代码有明显的错误吗?

最佳答案

如果这是实模式 DOS,我不确定 esp 的高位。至于malloc(),使用ss:sp和0xa000:0000之间的内存,栈顶和640k之间的内存界线。我不记得 MS-DOS 是否为 .COM 程序分配了所有 640k 区域。有两个 DOS 调用,INT 21H,ah = 04Ah 释放内存,ah = 048H 分配内存,但我不记得这些是针对 .COM 还是 .EXE 程序。

关于实模式 DOS .COM(独立式)的自定义内存分配器——如何调试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31842228/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com