![]() |
1
8
在DOS下,是的,你可以开始使用另一段内存。然而,有一个重要的警告! 看看你正在使用的DOS版本的内存映射。您需要确保没有选择实际用于其他用途的内存区域。这是一个来自 Dr. Dobb's 日记账:
“官方”内存分配机制是通过内存控制块(MCB)和DOS中断0x21使用0x48分配和0x49释放内存。关于这一点,可以在下面找到很好的讨论 Microsoft support document . 有关中断方法的文档, you might look here. |
![]() |
2
7
我最近偶然发现了这个问题。尽管它只有几年的历史,但我觉得除了目前的答案之外,还有一些其他信息可能对未来的读者有用。 这个问题实际上可以归结为:我可以任意写入超出DOS分配的程序范围的内存吗?这个问题是针对DOS COM程序的,但大部分信息也适用于DOS EXE程序。 GNU汇编程序的局限性在于它不能生成16位DOS EXE程序,所以您必须生成DOS COM程序。原点为0x100的DOS COM程序。代码、数据和堆栈不能超过64KiB内存(在加载时)。DOS COM程序一旦被DOS加载程序加载到内存中,就具有以下特征:
人们应该问的第一个问题是:我的DOS COM程序实际上有多少内存?简单的答案是:它会有所不同。它可能因可用的常规内存量而异(IBM PC通常带有64KiB、128KiB、256KiB、512KiB或640KiB)。另一个答案中引用的Dobbs博士杂志文章发表于1988年,记忆图谱缺少一些关键的东西。
1987年,IBM发布了IBM PS/2系列计算机。为了保存鼠标相关信息,IBM意识到
BIOS Data Area
在中断向量表上方,因此他们创建了一个
Extended BIOS Data Area
(EBDA)。此内存由BIOS保留,IBM PS/2 BIOS开始报告1KiB更少的内存(639KiB而不是640KiB)。EBDA可以有不同的大小,具体取决于BIOS制造商。BIOS
更糟糕的是,当基于386SL的系统发布时,它包括 System Management Mode 它在第二环上运行,可以完全访问您的PC。这些系统也开始使用EBDA中的空间。某些系统需要超过1KiB。理论上,你可以拥有128KiB的EBDA空间,尽管我不确定是否有任何系统有过这样的空间!此区域最终用于电源管理(APM)、ACPI、SMBIOS,并且可以随时通过系统管理模式写入此区域。出于这个原因,该区域通常被视为OS保留的区域。实际发生的情况取决于BIOS和机器制造商。 除了EBDA,一些DOS程序(和恶意软件)拦截BIOS Int 12h并报告较少内存,以隐藏(或驻留)DOS不应该接触的代码/数据。Dobbs博士的记忆地图可能需要添加以下内容:
故事的寓意
:您不应该假设可用内存量介于
要回答如何判断程序专用的内存区域的问题,可以通过查看PSP,特别是偏移量处的WORD值来回答
通过读取这个值,你可以得到第一个字节的段,刚好超出你的程序被分配的部分(我们称之为
COM程序分配128KiB由于 20-bit segment:offset addressing 每个段指向内存中不同的16字节区域的开始,该区域称为 段落 。将一个段增加1将在内存中增加16个字节,将其减少16个字节。这对于执行所需的算法以确定程序需要多少并确保有足够的可用内存来满足请求非常重要。
128KiB是128*1024/16=8192段。我们的COM程序加载到的区域(以及堆栈所在的区域)的实际大小由CS:0x0000和堆栈正上方的段限定(
服务提供商
)正在指向。由于DOS总是推送一个2字节的值(返回地址
最简单的方法是将128KiB的数据放在堆栈的上边缘(
注:
DOS<2.0不支持
Memory Control Blocks
这意味着
一个使用GNU汇编程序的程序版本,它确保在堆栈之后,我们的程序有128KiB的可用空间,如下所示:
一个稍微复杂的变体是将默认给定的堆栈大小调整为适合我们工作的大小,然后将128KiB的额外数据放在堆栈之后。我们需要计算代码和数据的范围,以便将堆栈放在它的正上方,然后是128KiB数据的内存。此代码正是使用4096字节堆栈来实现这一点的:
这些示例可以组装并链接到名为
在DOS EXE程序中分配128KiBDOS加载程序还加载EXE程序(它们有一个 MZ header ). MZ头包含程序信息、重定位表、堆栈、入口点以及可执行文件中物理存在的数据之外的最小和最大内存分配要求。具有完全未初始化数据的段(包括但不限于BSS和堆栈段)不会占用可执行文件中的空间,但DOS加载程序被告知通过 MINALLOC公司 和 MAXALLOC公司 标题字段:
MINALLOC是EXE本身代码和数据上方的段落数 必修的 .MAXALLOC始终至少等于MINALLOC,但如果是(MAXALLOC>MINALLOC),则DOS将尝试满足附加段落的请求(MAXALOC-MINALLOC)。如果无法满足该请求,DOS将分配它所拥有的所有可用空间。通常,MAXALLOC和MINALLOC之间的额外内存称为 HEAP(堆) 通过许多工具和编程语言。
值得注意的是,生成设置MINALLOC和MAXALLOC的可执行文件的是最终链接过程。通常,链接器默认情况下会将MAXALLOC设置为0xffff,从而有效地请求HEAP占用DOS可以分配的尽可能多的连续空间。这个
EXEMOD显示或更改DOS文件头中的字段。要使用 这个实用程序,您必须了解文件头的DOS约定
/最大n
在DOS<中;2.0没有内存控制块的概念,使用
对于此讨论,128KiB的额外内存是 必修的 这样示例将把该数据放在未初始化的数据中。链接/可执行文件生成过程将通过添加所需的额外段落来调整MZ标题中的MINALLOC字段。 希望分配128KiB(两个64KiB段依次放置)的DOS程序的第一个示例被写入 FASM 装配:
适用于大多数MASM/JWASM/TASM版本的版本如下:
脚注:
|
|
3
5
如果我们启动一个程序,DOS会给这个程序所有的空闲内存,所以我们必须在请求新内存之前把它还给DOS。第一步是计算程序所需的内存并将其余内存返回给DOS。在SS、SP和ES被操纵之前,我们必须将这一部分放在程序的开头。
下一步是请求新内存。
|
![]() |
4
0
通过将其中一个段寄存器设置为所需的值,可以获得所需的任何段。但请记住
|
![]() |
the_endian · 8086汇编程序始终打印相同的字符串 7 年前 |
|
Ina Gabrielle · 汇编语言中十进制到二进制的转换 7 年前 |
![]() |
mihaicata1205 · TASM程序未打印任何内容 7 年前 |
![]() |
H. Daniel · 组件8086中的序列构造 7 年前 |
![]() |
m0d3r · 如何在TASM x64中连接外部文件 7 年前 |
![]() |
bad · 如何在MASM 5.10中的表达式中使用外部EQU 7 年前 |