【问题标题】:Error: Invalid combination of opcode and operands - nasm错误:操作码和操作数的组合无效 - nasm
【发布时间】:2017-01-13 08:23:27
【问题描述】:

我正在创建一个小例程来使用lidt 指令加载idtr 寄存器。 我已经创建了这段代码 -

global load_idt

load_idt:
    mov eax, esp
    add eax, 4
    lidt eax    ;<-----------------LINE 9
    ret

但是当我使用 Nasm 编译它时,我得到一个错误 -

kernel/kernel_start.asm:9: error: invalid combination of opcode and operands

我的编译命令是-

nasm kernel/kernel_start.asm -f elf32 -o kernel/kernel_start.o

谁能指出这个程序的错误?

【问题讨论】:

  • 助记符是LIDT m16&amp;32 ...您的意思是lidt [eax] 吗?
  • 我想使用load_idt(&lt;address-of-the-stored-idtr&gt;)在C语言中调用函数。我必须使用[eax]吗?它不会指向 idtr 的值而不是它的地址吗? @Tommylee2k

标签: assembly x86 nasm osdev


【解决方案1】:

idtr 寄存器必须加载两条信息:指向描述符表的指针和前者的大小(以字节减一)。

因此,作为Tommylee2k pointed out,唯一有效的形式是LGDT m16&amp;32,其中m16&amp;32 是一个指向内存位置的指针,该内存位置包含一个16 位大小和一个32 位基指针。

引用英特尔

源操作数指定一个 6 字节的内存位置,其中包含中断描述符的基地址和限制 表。

注意大小在基地址之前。

如果我是你,我会通过适当使用 C 来尽量减少程序集。
例如,使用一个结构来表示 IDT 基数和限制,然后将其按值传递给用汇编编写的函数。
这也是inline assembly is fine 最罕见的情况之一,所以你可以考虑一下。

/* IDT descriptor */
struct desc_t;

/* IDT */
struct __attribute__ ((__packed__)) IDT
{
   uint16_t size;
   struct desc_t* table;
};

/* Declaration of assembly function */
void set_idt(struct IDT idt);


;Parameters in order of push
;
;   struct IDT idt
;
_set_idt:
 lidt [esp+4]
 ret

琐事

从技术上讲,lidt eax 是可编码的,使用值为 0d8h 的 ModR/M 字节就足够了(reg 字段为 011b 作为扩展操作码,mod 和 r/m 字段使用eax)但lidt 生成#UD 如果使用寄存器源(事实上lidt eax 被重用于vmrun AMD-v)。

【讨论】:

  • 我确实计划从 C 中调用汇编例程。虽然我使用的是描述符表的数组而不是指针。这会有什么不同或一些更好的功能吗?
  • 您不应该按值传递 IDT,而不是通过 set_idt 传递单个描述符吗?可能我在翻译中遗漏了一些东西或应该如何使用它。
  • 是的@MichaelPetch,我写错了结构,谢谢指出。
  • 如果您打算将 desc_t 描述为示例的不透明类型(给定 struct desc_t;),我想您可能需要将 desc_t* table; 更改为 struct desc_t* table;
  • @AneeshSharma 数组是描述符表的最佳选择。您仍然需要与上面的 struct IDT 等效,因为这正是 lidt 所期望的。
猜你喜欢
  • 2013-02-14
  • 1970-01-01
  • 2015-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多