错误:操作码和操作数的组合无效 - nasm

时间:2017-01-13 08:23:27

标签: assembly x86 nasm osdev

我正在创建一个小例程来加载带有idtr指令的lidt寄存器。 我创建了这段代码 -

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

有人能指出这个程序中的错误吗?

1 个答案:

答案 0 :(得分:2)

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

因此,作为Tommylee2k pointed out,唯一有效的形式是LGDT m16&32,其中m16&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作为扩展操作码,11b和000b为 mod r / m 字段使用eax)但lidt生成 #UD 如果使用了寄存器源(并且实际上) lidt eax被重用于AMD {v}的vmrun

相关问题