首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在x86汇编和DOS(16位)中使用实数段模式时,大于64k的程序

在x86汇编和DOS(16位)中使用实数段模式时,大于64k的程序
EN

Stack Overflow用户
提问于 2010-09-09 02:22:58
回答 4查看 1K关注 0票数 2

我想知道当你在DOS的实分段模式下进行16位(汇编)编程时,你需要如何处理大于64k的汇编程序。在我正在阅读的这本书( Jeff Duntemann的“汇编语言一步一步”)中,作者提到了一些关于使用多个代码段的事情(但不幸的是没有深入细节)。我只想知道怎么做。我知道这个内存模型现在已经过时了,但出于好奇,我只是想知道您将如何实现这一点。

EN

回答 4

Stack Overflow用户

发布于 2010-09-09 02:25:26

好的,你只需要把你工作地址的高位字写到DS,你就可以通过DS:DI使用它了。这样你可以使用更多高达300-500kb的内存。

票数 1
EN

Stack Overflow用户

发布于 2010-09-09 03:35:33

使用超过64kb的内存本身并不是非常复杂(除非您需要处理跨越段边界的数据结构-这可能是“有趣的”)。如果您所需要的只是动态内存,那么只需使用16:16 (seg:ofs)远指针。

您可以让DS指向您的主数据段,并使用ES (或者,如果在80386或更高版本上执行,甚至在实模式下) FS或GS数据段来保存远指针的段部分。您可以对偏移部分使用任何您想要的通用寄存器,DS:SI和ES:DI只有在处理字符串指令(lods/mov/stos)时才是特殊的。此外,请记住,如果您不使用显式段覆盖,则BP和SP默认为SS段!

如果您需要超过64kb的静态程序数据(哇!),那么您需要一个支持段/段的汇编程序,并且在链接到.exe之前,您很可能还需要汇编成对象格式。如何处理静态数据远指针将取决于你选择的汇编程序,但可能会有一些关键字来引用变量的段部分。

票数 1
EN

Stack Overflow用户

发布于 2013-01-22 12:04:40

段寄存器偏移存储器访问的基数。16位模式下的地址计算如下:

代码语言:javascript
复制
address = ((twenty_bit_t)segment << 4) + offset

其中(虚构的) twenty_bit_t是至少20位的类型。

16位实数模式下的地址空间为1MB,即20位。段允许您影响前四位,并以16字节的粒度进行操作(在当时通常称为“段落”)。将段值加1会使指针在内存中领先16个字节。

您的偏移量被限制为16位的值,因此要访问超过16位的值,您必须使用“远指针”。远指针的长度为32位。但不是真正的32位,高16位实际上只是与偏移量重叠的段。

远指针比普通指针要昂贵得多,因为(对于当时的典型编译器)每次它解引用一个不同的指针时,它都必须加载段寄存器。通常,编译器每次都会继续加载段寄存器。

有几个“模型”(我们当时这样叫它们)。它基本上是近/远代码指针、近/远数据指针的所有组合的矩阵(并且IIRC是一种具有大于64KB的全局变量的方法)。

编译器提供了对每个指针是远还是近的细粒度控制。对于频繁访问的代码/数据,使用近程代码和近程数据,并在需要的地方添加额外的扩展指令来声明特定的指针或函数,这是一种优化。

然而,远调用和返回的影响没有远数据那么严重,因为指针被解除引用的次数比函数被调用的次数多得多。

x86 CPU有特殊的指令(和前缀)来处理远调用、远返回和远指针。即使是32位操作系统也至少需要初始化段寄存器。某些x86系统指令需要使用段寄存器。但是,在32位模式下,段寄存器的值具有与我上面描述的所有内容完全不同的含义。

链接和加载

目标文件有代码和数据块,每个块都要进入一个特定的段(按名称)。每个段也被标记为代码或数据等。链接器计算出需要什么,计算出每个段有多大,计算出所有东西的地址,并记住可执行文件中任何指针的位置。将计算远调用操作数和初始化的远指针,就好像可执行文件的加载地址是零一样,并且为每个操作数发出一个重定位条目。

DOS动态地处理内存,因此您的程序将被加载到一个不可预测的地址。为了解决这个问题,DOS可执行文件有“重定位”,这是一个指向代码和初始化数据的指针列表。加载时,DOS遍历该列表,并将加载地址的基段添加到重新定位条目所指向的值。例如,代码重定位将直接指向call指令中表示该段的字节。这修复了任何初始化的全局远指针和任何远调用指令操作数。

(从286开始,地址计算实际上几乎变成了21位-段寄存器的FFFF +偏移量FFFF,地址将是10FFEF - (1 MB + 64 KB - 16 B)。HIMEM.SYS实际上有一个应用程序接口调用来分配高内存,要么全部分配,要么不分配。通常,人们通过在他们的config.sys中放入DOS=HIGH来获得它。)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3670757

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档