7

我有一些用C语言编写的16位旧代码,使用Borland C++在多个堆栈之间切换,使用longjmps。它通过执行 malloc 创建一个新堆栈,然后使用 inline Assembler 将 SS 和 SP 寄存器设置为 malloc 区域地址的段和偏移量。我想将它转换为 Win32,看起来这两条指令应该被一个设置 ESP 的指令替换。这两条指令被 CLI/STI 对包围,但在 Win32 中,它们提供“特权指令”,所以我现在将它们删掉了。当谈到 Windows 时,我是一个真正的无辜者,所以,我的第一个测试用例成功了,我感到相当惊讶!所以,我相当模糊的问题是在这里问专家我正在做的事情是否a)太危险而无法继续,或者b)如果我添加一些代码会起作用,采取某些预防措施等?如果是后者,应该添加什么,我在哪里可以找到它?我是否需要担心任何其他寄存器,例如 SS、EBX 等?我在用没有优化...感谢人们可以给我的任何提示。

4

5 回答 5

9

由于操作环境的差异,删除 CLI/STI 仍然有效。

在 16 位 DOS 上,可能会发生中断,并且该中断最初会在同一个堆栈上运行。如果你在操作过程中被打断,中断可能会崩溃,因为你只更新了 ss 而不是 sp。

在 Windows 和任何其他现代环境中,每个用户模式线程都有自己的堆栈。如果您的线程由于某种原因被中断,它的堆栈和上下文将被安全地保留 - 您不必担心在您的线程和堆栈上运行的其他东西。在这种情况下,cli/sti 将保护您免受操作系统已经保护的东西。

正如 Greg 所提到的,在 Windows 上像这样交换堆栈的安全、受支持的方法是 CreateFiber/SwitchToFiber。这确实有改变整个上下文的副作用,所以它不像只是切换堆栈。

这确实提出了您想要做什么的问题。很多时候,切换堆栈是为了获得有限的堆栈空间,在 16 位 DOS 上是 64k。在 Windows 上,您有 1 MB 堆栈,您可以分配更大的堆栈。你为什么要切换堆栈?

于 2009-05-15T01:46:20.057 回答
5

到目前为止,最安全的方法是将代码移植到官方 Win32 多道程序结构,例如线程或光纤。Fibers提供了一个非常轻量级的多堆栈范例,听起来它可能适合您的应用程序。

为什么 Win32 甚至还有纤程?文章也很有趣。

于 2009-05-15T01:42:20.393 回答
0

我在用户模式下完成了这个,它似乎没有问题。您不需要 cli/sti,这些说明只是防止代码中的中断,从您告诉我们的有限信息来看,这应该是不必要的。

于 2009-05-15T01:54:03.250 回答
0

看看Bert Hubert 的Mtasker。它执行简单的协作多任务处理,您可能很容易使用它来移植您的代码。

于 2009-05-15T06:01:53.093 回答
0

不要忘记跳跃堆栈会占用任何参数或堆栈驻留变量。

于 2009-05-15T06:19:45.670 回答