Operand size for lgdt/lidt

Hello
I use lgdt/lidt instructions to load descriptor tables registers:

load_idtr proc
lidt tbyte ptr[rcx]
ret
load_idtr endp

load_gdtr proc
lgdt tbyte ptr[rcx]
ret
load_gdtr endp

However I get error “error A2024: invalid operand size for instruction”.

nt uses these instructions for example in function KiRestoreProcessorControlState :
000000014019880F: 0F 01 51 56 lgdt tbyte ptr [rcx+56h]
0000000140198813: 0F 01 59 66 lidt tbyte ptr [rcx+66h]

So it looks like my code must be assembling correctly.

What is my mistake ?

idt tbyte ptr[rcx]

lgdt tbyte ptr[rcx]

What is my mistake ?

Are you still wondering what your mistake is all about???

Anton Bassov

Strange but it works like this:

load_gdtr proc
lgdt fword ptr[rcx]
ret
load_gdtr endp

However if I disassembling my driver i get tbyte modifier:
load_gdtr:
00000001400011F6: 0F 01 11 lgdt tbyte ptr [rcx]
00000001400011F9: C3 ret

Sergey_Pisarev wrote:

I use lgdt/lidt instructions to load descriptor tables registers:

load_idtr proc
lidt tbyte ptr[rcx]
ret
load_idtr endp

load_gdtr proc
lgdt tbyte ptr[rcx]
ret
load_gdtr endp

“tbyte ptr” is a 10-byte operand,  used only with the FBLD and FBST
instructions.   Although the GDT is 10 bytes long in 64-bit mode, it’s
not useful, so I’m guessing MASM never added support for it. lidt and
lgdt in 32-bit land need a 6-byte operand, which is an “fword ptr”.  It
doesn’t matter whether it’s lying; if that’s what it takes to get MASM
to generate 0F 01 51 56, the hardware will know what to do.

What do you think you’re going to be doing with this?  The use of rcx
implies 64-bit mode, where the GDT is essentially vestigial. And why
would you define a subroutine to do this instead of doing it inline?  It
takes more characters to type the subroutine call than to do the
instruction.

Sergey_Pisarev wrote:

Strange but it works like this:

load_gdtr proc
lgdt fword ptr[rcx]
ret
load_gdtr endp

However if I disassembling my driver i get tbyte modifier:

load_gdtr:
00000001400011F6: 0F 01 11 lgdt tbyte ptr [rcx]
00000001400011F9: C3 ret

It’s not really that hard to figure out, is it? The disassembler has to assume 32-bit or 64-bit mode. There is no way to tell that from the byte stream. In 32-bit mode, 0F 01 11 is “lgdt fword ptr [bx][di]”. In 64-bit mode, 0F 01 11 is “lgdt tbyte ptr [rcx]”. The type designations are only for human consumption; the types are not embedded in the instruction stream. Those come from the context.

MASM has long been an orphan. My guess is that no one ever updated its internal tables to tell it that lgdt and lidt need a “tbyte ptr” in 64-bit mode, so it unconditionally expects an “fword ptr”.

This is x64 only driver, so inline assembly is not available.

I have function:
get_gdtr proc
sgdt tbyte ptr [rcx]
ret
get_gdtr endp

It compiles and work no problem.

I need to restore GDTR on unload to values that patchguard likes.