Reputation: 3796
I'm trying to write a lidt
instruction in inline assembly in gcc with -masm=intel and 32 bits (-m32). So I have defined the following structures:
typedef struct {
uint16_t length;
uint32_t base;
} idt_desc;
static idt_desc desc = {
sizeof(idt)-1,
(uint32_t)(uintptr_t)idt,
};
If I were using nasm, I would be done with lidt [desc]
. But I'm using inline assembly and have this inside a function:
asm volatile("lidt %0"::"m"(desc):);
This gives me "Error: unsupported instruction `lidt'". The assembly generated looks like this:
lidt QWORD PTR desc
As far as I know, braces are optional in gas intel syntax. So the problem here is the qword ptr
which is not acceptable in lidt
instruction as it expects a m16&32
operand. How can I tell gcc to use that? i.e., drop qword ptr
and just use desc
.
Upvotes: 2
Views: 253
Reputation: 47573
You need pack the idt_desc
structure as the compiler will add padding between the 16-bit length
and the 32-bit base
structure members. Even if the compiler had managed to generate the code for this the structure would have been invalid and LIDT would have almost certainly loaded an incorrect IDT record leading to an eventual crash/triple fault at runtime. It should be:
typedef struct {
uint16_t length;
uint32_t base;
} __attribute__((packed)) idt_desc;
The -masm=intel
option seems to have caused the compiler to see the unpacked version of the structure as a padded 8 byte structure and then treated it as a 64-bit QWORD
. In 32-bit code an LIDT
doesn't take a pointer to a QWORD
it takes a pointer to a 48-bit value (aka FWORD
in some Intel dialects) which is the source of the error. By packing the structure the compiler is no longer generating QWORD
since the packed version is 6 bytes in size.
Upvotes: 2