使用nasm混合32位和16位代码

7

这是一个低级系统问题。

我需要混合32位和16位代码,因为我正在尝试从保护模式返回到实模式。作为背景信息,我的代码在GRUB引导后执行,所以没有任何麻烦的操作系统告诉我可以做什么和不能做什么。

无论如何,我使用[BITS 32]和[BITS 16]来告诉nasm应该使用哪种类型的操作,但是当我使用bochs测试我的代码时,看起来对于某些操作,bochs没有执行我编写的代码。看起来汇编器会插入额外的0x660x67,这使得bochs感到困惑。

那么,我该如何让nasm成功地汇编混合32位和16位代码的文件?有什么诀窍吗?

4个回答

6
问题最终发现是我没有正确设置描述符表。我有一位错位,所以我不是进入了16位模式,而是进入了32位模式(使用片段其限制恰好为1兆字节)。
感谢您的建议!
Terry

4
0x66和0x67是操作码,用于指示以下的操作码应解释为非默认位数。更具体地说,(根据此链接),当NASM处于BITS 16模式时,使用32位数据的指令前缀为0x66字节,而引用32位地址的指令前缀为0x67。在BITS 32模式下,情况相反:32位指令无需前缀,而使用16位数据的指令需要0x66前缀,对16位地址起作用的指令需要0x67前缀。这表明bochs有问题。

1

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

请参阅英特尔IA-32软件开发人员指南第3卷第16章(混合16位和32位代码;根据书籍版本,章节号可能会更改):

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

BITS 32指令只会在保护模式或长模式之外使用时使汇编器混淆。


如果有人今天(2023年)在查找软件开发者指南,现在是第3卷,第22章。https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html - Jody Bruchon
如果有人今天(2023年)在查找《软件开发者指南》,现在它是第3卷,第22章。https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html - undefined

0

你说得没错,这确实是低级的!

你检查过生成的操作码/操作数,确保nasm正确遵守了你的BITS指令吗?还要检查跳转目标是否正确-也许nasm使用了错误的偏移量。

如果不是nasm的bug,那么bochs可能存在bug。我无法想象人们现在还经常从32位模式切换回16位模式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接