将32位和16位代码与nasm混合
这是一个低级的系统问题。
我需要混合使用32位和16位代码,因为我正试图从保护模式返回实模式。作为一些背景信息,我的代码是在GRUB引导后立即执行的,因此我没有任何讨厌的操作系统来告诉我我可以做什么和不能做什么。
无论如何,我在程序集中使用[BITS 32]和[BITS 16]来告诉nasm应该使用哪种类型的操作,但是当我测试我的代码时使用bochs,看起来对于某些操作bochs并没有执行我写。看起来汇编器粘在了额外的0x66
和0x67
中,这会使boch感到困惑。
那么,如何在同一文件中混合使用32位和16位代码的情况下,如何使nasm成功地汇编代码?有什么把戏吗?
解决方案
回答
我们不是在开玩笑,这是低级的!
我们是否检查了生成的操作码/操作数以确保nasm正确遵守了BITS指令?还要检查以确保跳跃目标正确无误,也许nasm使用了错误的偏移量。
如果这不是nasm中的错误,那么bochs中可能有一个错误。我无法想象人们会经常从32位模式切换回16位模式。
回答
0x66和0x67是用于指示应将以下操作码解释为非默认位的操作码。更具体地说,(并且根据此链接),
"当NASM处于BITS 16模式时,使用32位数据的指令以0x66字节为前缀,而引用32位地址的指令以0x67前缀为前缀。在BITS 32模式中,情况正好相反:32位指令不需要前缀,而使用16位数据的指令则需要0x66,而使用16位地址的指令则需要0x67. "
这表明这是错误的。
回答
如果我们处于实模式,则默认大小隐式为16位,因此应使用BITS 16模式。这样,如果我们需要32位操作数大小,则添加0x66前缀,对于32位地址大小,则添加0x67前缀。
请参阅《英特尔IA-32软件开发人员指南》,第3卷,第16章(混合16位和32位代码;该章号可能会因本书版本而异):
Real-address mode, virtual-8086 mode, and SMM are native 16-bit modes.
如果在保护模式或者长模式之外使用BITS 32指令,则只会使汇编程序感到困惑。
回答
原来的问题是我没有正确设置描述符表。我有一点错了,所以我没有去16位模式,而是去了32位模式(段的大小刚好是1兆)。
感谢建议!
特里