我想为16位保护模式编写一些代码,特别是带有一些程序的简单操作系统。我知道这听起来很愚蠢,可能是,但我对理解如何在这些约束条件下编写程序感兴趣。
我想知道在16位保护模式下工作的各种操作系统中采用了哪些约定(例如OS / 2和Win 3.1)。他们用ABI做了什么?远点如何传递?是否存在针对不同代码模型的多个ABI?
为了澄清,我知道远端指针是什么以及如何在API级别上使用它们。我想知道的是它如何在汇编级别上工作。远端指针的段是否在堆栈上传递?有没有特别约定?
答案 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)程序。