В 32-битном x86 информация ISR сохраняется в IDT.IDT - это не просто список адресов, и он не обязательно хранится по адресу 0. Описание формата IDT см. На странице OSDev Wiki .Местоположение IDT определяется ОС, и оно может быть недоступно для программного обеспечения пользовательского режима.Предполагая, что у вас есть право изменить его, вы можете получить местоположение IDT с помощью инструкции sidt
.
sidt -6(%esp)
В 32-битном режиме sidt
будет хранить данные размером 6 байт вуказанное место.Я использовал -6(%esp)
для моего примера, который будет хранить данные чуть ниже текущего стека.Два младших байта - это длина IDT в байтах, а следующие 4 (в 32-битном режиме) - это адрес IDT.Поскольку каждая запись IDT имеет длину 8 байтов, местоположение требуемой записи будет 0x33*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