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

时间:2008-08-20 16:30:52

标签: operating-system nasm osdev assembly

这是一个低级系统问题。

我需要混合32位和16位代码,因为我试图从保护模式返回实模式。作为一些背景信息,我的代码就是在GRUB引导之后这样做的,所以我没有任何讨厌的操作系统来告诉我我能做什么和不能做什么。

无论如何,我在我的程序集中使用[BITS 32]和[BITS 16]告诉nasm它应该使用哪种类型的操作,但是当我测试我的代码时使用bochs它看起来像某些操作bochs没有执行我写的代码。看起来汇编程序正在使用额外的0x660x67来混淆bochs。

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

4 个答案:

答案 0 :(得分:5)

问题原来是我没有正确设置我的描述符表。我有一点错误,所以我没有进入16位模式,而是进入32位模式(片段恰好有一个兆字节)。

感谢您的建议!

特里

答案 1 :(得分:3)

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

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

这表明这是错误的bochs。

答案 2 :(得分:0)

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

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

如果它不是nasm中的错误,也许bochs中有一个错误。我无法想象人们会经常从32位模式切换回16位模式。

答案 3 :(得分:0)

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

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

  

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

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