2017-04-23 90 views
1

我想写一个简单的操作系统,使用GCC,这将允许我在我输入的显示器上显示文本。我在C中有一个中断表,我需要加载并希望能够使用内联汇编代替外部汇编语言模块。如何使用内联汇编中的LIDT加载中断向量表?

我在寻找的是将指针传递给内联汇编的一种方法。

我试图内联的指令,需要一个存储器操作数是LIDT

载荷将源操作数的值代入全局描述符表寄存器(GDTR)或中断描述符表寄存器(ID​​TR) 。源操作数指定包含全局描述符表(GDT)或中断描述符表(IDT)的基址(线性地址)和限制(字节大小)的6字节内存位置。如果操作数大小属性为32位,则将16位限制(6字节数据操作数的低2字节)和32位基址(数据操作数的高4字节)装入寄存器。如果操作数大小属性为16位,则加载16位限制(低2字节)和24位基址(第3,第4和第5字节)。这里,不使用操作数的高位字节,GDTR或IDTR中基地址的高位字节用零填充。

+1

我认为这是处于保护模式,你正在寻找使用'lidt'指令从包含一个6字节的IDT记录(它有基地址和限制)的内存位置加载IDTR? –

回答

1

你不提供任何代码,你不说这Ç编译器,但我会假设GCC和32位内核。这是你可以做一个例子:

#include <stdint.h> 

struct idt_record 
{ 
    uint16_t limit;  /* Size of IDT array - 1 */ 
    uintptr_t base;  /* Pointer to IDT array */ 
} __attribute__((packed)); 

void load_idt (struct idt_record *idt_r) 
{ 
    __asm__ ("lidt %0" :: "m"(*idt_r)); 
} 

该代码使用内联汇编,并传递IDT记录到它是用来通过LIDT指令扩展内联模板地址。我们使用mconstraint。如果参数约束为(idt_r)它会传递一个指针的内存引用。我们需要一个内存参考的实际数据,所以我们用*去引用它,这就是我使用"m"(*idt_r)的原因。

你必须设置base指向您的实际IDT阵列和limit将是IDT阵列减1的大小,如果你在我们显示你的数据结构我也不会提供这样的一般的回应。我不知道你如何定义你的记录结构,所以我使用了一个快速简单的例子。

我可能会提供load_idt函数在一个包含文件中,并将该函数标记为static inline


注意:如果您使用的IDT记录的结构确保您相似,我有__attribute__((packed))所做的结构。如果您不打包,则会在limitbase之间添加额外的2个字节,这将生成损坏的IDT记录。

+1

谢谢!这解决了我的问题。我在网上发现了很多,但我真的希望能够通过gcc做到这一点。 –