在x86 32位中,ISR信息存储在IDT中。 IDT不仅仅是地址列表,并且不一定存储在地址0处。关于IDT格式的描述,请参阅OSDev Wiki page。 IDT的位置由操作系统决定,用户模式软件可能无法访问。假设您有权修改它,您可以使用sidt
指令获取IDT的位置。
sidt -6(%esp)
在32位模式中,sidt
将存储值得在指定的位置数据的6个字节。我使用-6(%esp)
作为例子,它会将数据存储在当前堆栈的正下方。低两个字节是IDT的长度,以字节为单位,而下一个4(在32位模式下)是IDT的地址。由于每个IDT条目的长度为8个字节,所以在IDT开始之后,您想要的条目的位置是个字节。在修改条目之前,应确保IDT实际上包含该条目(至少为0x34*8
字节)。
下面是一个例子,它查找IDT,确保它足够长,并设置中断0x33的条目。
sidt -6(%esp) // Get the location and size of the IDT
cmpw $0x34*8, -6(%esp) // Make sure the IDT is long enough
jb IDT_too_short // and handle the error if it isn't
mov -4(%esp), %ebx // Get the IDT's address
add $0x33*8, %ebx // and move to the entry for 0x33
mov $OSTickISR, %eax // Get the ISR's address
mov %ax, (%ebx) // Store the low 16 bits of the ISR's address
movw $ISR_CS, 2(%ebx) // Store the code segment which should be used with this ISR
movb $0, 4(%ebx) // This has to be 0
movb $0xEE, 5(%ebx) // See the OSDev link for information on this byte.
// 0xEE is most common for interrupts available from user mode
shr $16, %eax
mov %ax, 6(%ebx) // Store the high 16 bits of the ISR's address
+1伟大的答案,除了[IA软件开发人员手册](http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html)的强制性链接之外,我没有其他补充内容。 (哦,为了完整性可能会投入一个'sub $ 8,%esp'顶部:) – user786653
@ user786653感谢您的链接。至于'sub $ 8,%esp',我的回应取决于你的推理。如果1)你正在为函数调整堆栈,这是没有必要的,因为没有函数调用,或者2)你想使用'%esp'的正偏移量,我更喜欢在红色区域工作尽可能少量的数据。 – ughoavgfhw
我想在堆栈上分配空间,因为我不记得在32位x86上使用了带有红色区域的调用约定?无论哪种方式,能够理解和使用上面的代码中任何人都应该能够轻松地做出适当的调整他们的调用约定:) – user786653