如何使用超过64kb的数据在16位保护模式下编程?

时间:2015-05-06 15:44:47

标签: assembly abi protected-mode 80286

我想为16位保护模式编写一些代码,特别是带有一些程序的简单操作系统。我知道这听起来很愚蠢,可能是,但我对理解如何在这些约束条件下编写程序感兴趣。

我想知道在16位保护模式下工作的各种操作系统中采用了哪些约定(例如OS / 2和Win 3.1)。他们用ABI做了什么?远点如何传递?是否存在针对不同代码模型的多个ABI?

为了澄清,我知道远端指针是什么以及如何在API级别上使用它们。我想知道的是它如何在汇编级别上工作。远端指针的段是否在堆栈上传递?有没有特别约定?

2 个答案:

答案 0 :(得分:2)

大多数16位保护模式API都将远指针作为参数。 far指针是一个32位值,包含16位偏移(低位字)和16位选择器(高位字,选择器指代段)。它通过像任何其他参数一样将它放在堆栈上来传递值。通常这些指针只能引用内存区域大小达65536字节,但不同的远指针可以引用不同的内存区域,允许使用超过64K的内存。

例如,在16位Windows API(Win16)中,函数GetClientRect具有以下记录的接口:

void GetClientRect(hwnd, lprc)

HWND hwnd;    /* handle of window */
RECT FAR* lprc;   /* address of structure for rectangle   */

符号FAR是一个在使用16位Windows API时扩展为far关键字的宏。今天,这个API函数被记录为采用LPRECT参数,该参数被认为是指向RECT"的长(远)指针。符号LPRECT在32位和64位Windows API中定义为RECT *的typedef。如果仍然支持使用16位API,那么它将是RECT far *的typedef。

对于不同的内存模型(小型,中型,紧凑型,大型),没有单独的API,因为在指针上使用了far关键字(以及函数本身),API可以从所有内存模型。编译器会看到它需要一个远指针并根据需要提升任何近(16位)指针。

答案 1 :(得分:1)

据我记得,过去介绍了采用80286架构的AT系统,内存由64 KB段组成,这是可以使用16位地址寄存器(实模式)寻址的最大地址。当在汇编中进行编码时,分别在段内或段外发生近和远跳。当发生远程跳转时,在汇编中,首先应该给出跳转发生的段,然后是段内的本地地址。

在保护模式下,可以使用描述符表来扩展段的寻址范围,这可以增加可以在机器上使用的内存量。

如果代码实现为可重入,则可以使用适当的BIOS和OS中断实现多任务以及终止和驻留(TSR)程序。