6

这是一个低级系统问题。

我需要混合 32 位和 16 位代码,因为我试图从保护模式返回到实模式。作为一些背景信息,我的代码在 GRUB 启动之后执行此操作,因此我没有任何讨厌的操作系统来告诉我我能做什么和不能做什么。

无论如何,我在我的程序集中使用 [BITS 32] 和 [BITS 16] 来告诉 nasm 它应该使用哪些类型的操作,但是当我测试我的代码使用 bochs 时,看起来对于某些操作 bochs 没有执行的代码我写。看起来汇编程序正在添加额外内容0x660x67's,这让 bochs 感到困惑。

那么,在同一文件中混合 32 位和 16 位代码的情况下,如何让 nasm 成功组装代码?有什么技巧吗?

4

4 回答 4

6

The problem turned out to be that I wasn't setting up my descriptor tables correctly. I had one bit flipped wrong so instead of going to 16-bit mode I was going to 32-bit mode (with segments that happened to have a limit of one meg).

Thanks for the suggestions!

Terry

于 2008-08-21T14:43:15.480 回答
4

0x66 和 0x67 是用于指示以下操作码应被解释为非默认位数的操作码。更具体地说,(并根据此链接),

“当 NASM 处于 BITS 16 模式时,使用 32 位数据的指令以 0x66 字节为前缀,而引用 32 位地址的指令则以 0x67 为前缀。在 BITS 32 模式下,反之亦然:32 位指令不需要前缀,而使用 16 位数据的指令需要 0x66,而使用 16 位地址的指令需要 0x67。”

这表明这是错误的。

于 2008-08-20T16:54:09.823 回答
0

如果您处于实模式,则默认大小隐式为 16 位,因此您应该使用 BITS 16 模式。这样,如果您需要 32 位操作数大小,则添加 0x66 前缀,对于 32 位地址大小,您添加 0x67 前缀。

查看英特尔 IA-32 软件开发人员指南,第 3 卷,第 16 章(混合 16 位和 32 位代码;章节编号可能会根据本书的版本而变化):

实地址模式、虚拟 8086 模式和 SMM 是本机 16 位模式。

如果您在保护模式或长模式之外使用 BITS 32 指令,它只会混淆汇编器。

于 2008-08-20T17:30:46.710 回答
0

你不是在开玩笑,这是低级的!

您是否检查了生成的操作码/操作数以确保 nasm 正确遵守您的 BITS 指令?还要检查以确保跳转目标正确 - 可能 nasm 使用了错误的偏移量。

如果不是 nasm 中的错误,则可能是 bochs 中的错误。我无法想象人们会经常从 32 位模式切换回 16 位模式。

于 2008-08-20T16:50:47.757 回答