2

我正在尝试lidt使用 -masm=intel 和 32 位(-m32)在 gcc 中的内联汇编中编写指令。所以我定义了以下结构:

typedef struct {
    uint16_t length;
    uint32_t base;
} idt_desc;

static idt_desc desc = {
    sizeof(idt)-1,
    (uint32_t)(uintptr_t)idt,
};

如果我使用 nasm,我将使用lidt [desc]. 但我正在使用内联汇编并将其包含在一个函数中:

asm volatile("lidt %0"::"m"(desc):);

这给了我“错误:不支持的指令‘lidt’”。生成的程序集如下所示:

    lidt QWORD PTR desc

据我所知,大括号在气体英特尔语法中是可选的。所以这里的问题是指令中qword ptr不可接受的,因为它需要一个操作数。我怎样才能告诉 gcc 使用它?即,放下并使用. lidtm16&32qword ptrdesc

4

1 回答 1

2

您需要打包idt_desc结构,因为编译器将在 16 位length和 32 位base结构成员之间添加填充。即使编译器设法为此生成代码,该结构也将无效,并且 LIDT 几乎肯定会加载不正确的 IDT 记录,从而导致在运行时最终崩溃/三重错误。它应该是:

typedef struct {
    uint16_t length;
    uint32_t base;
} __attribute__((packed)) idt_desc;

-masm=intel选项似乎导致编译器将结构的解压缩版本视为填充的 8 字节结构,然后将其视为 64-bit QWORD。在 32 位代码中,anLIDT不采用指向 a 的指针,QWORD它采用指向 48 位值(FWORD在某些英特尔方言中也称为)的指针,这是错误的根源。通过打包结构,编译器不再生成QWORD,因为打包版本的大​​小为 6 个字节。

于 2019-09-14T14:59:54.287 回答