我正在创建一个小例程来加载带有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
有人能指出这个程序中的错误吗?
答案 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
。