【问题标题】:Mixing 32 bit and 16 bit code with nasm使用 nasm 混合 32 位和 16 位代码
【发布时间】:2010-09-06 07:24:20
【问题描述】:
这是一个低级系统问题。
我需要混合 32 位和 16 位代码,因为我试图从保护模式返回到实模式。作为一些背景信息,我的代码在 GRUB 启动后执行此操作,因此我没有任何讨厌的操作系统来告诉我我能做什么和不能做什么。
无论如何,我在我的程序集中使用 [BITS 32] 和 [BITS 16] 来告诉 nasm 它应该使用哪些类型的操作,但是当我测试我的代码使用 bochs 时,看起来对于某些操作 bochs 没有执行我写的代码。看起来汇编器正在添加额外的 0x66 和 0x67,这让 bochs 感到困惑。
那么,当我在同一个文件中混合 32 位和 16 位代码时,如何让 nasm 成功组装代码?有什么技巧吗?
【问题讨论】:
标签:
operating-system
nasm
osdev
assembly
【解决方案1】:
问题原来是我没有正确设置我的描述符表。我有一点错误,所以我没有进入 16 位模式,而是进入 32 位模式(恰好有 1 兆的限制)。
感谢您的建议!
特里
【解决方案2】:
0x66 和 0x67 是操作码,用于指示以下操作码应被解释为非默认位数。更具体地说,(根据this link),
"当 NASM 处于 BITS 16 模式时,使用 32 位数据的指令以 0x66 字节为前缀,而引用 32 位地址的指令以 0x67 为前缀。在 BITS 32 模式下,反之亦然:32位指令不需要前缀,而使用 16 位数据的指令需要 0x66,而使用 16 位地址的指令需要 0x67。”
这表明它是错误的。
【解决方案3】:
这不是在开玩笑!
您是否检查过生成的操作码/操作数以确保 nasm 正确地遵守您的 BITS 指令?还要检查以确保跳转目标正确 - 可能 nasm 使用了错误的偏移量。
如果不是 nasm 中的错误,则可能是 bochs 中的错误。我无法想象人们会经常从 32 位模式切换回 16 位模式。
【解决方案4】:
如果您处于实模式,则默认大小隐式为 16 位,因此您应该使用 BITS 16 模式。这样,如果您需要 32 位操作数大小,则添加 0x66 前缀,对于 32 位地址大小,您添加 0x67 前缀。
查看英特尔 IA-32 软件开发人员指南,第 3 卷,第 16 章(混合 16 位和 32 位代码;章节编号可能会根据本书的版本而变化):
实地址模式、虚拟 8086 模式和 SMM 是本机 16 位模式。
只有在保护模式或长模式之外使用 BITS 32 指令才会混淆汇编器。