I work on Intel-Atom 32bits (Assembly AT&T).
I want to link my ISR to a vector interrupt 0x33:
push %ebp //save the context to swith back
movl %esp,%ebp
movl $OSTickISR, %eax //address of int 0x33 = address of OSTickISR
movl $0x33*4, %ebx
movl %eax, (%ebx)
p开发者_StackOverflow社区op %ebp //Return to the calling function
ret
When I try to use my int $0x33, nothing happends !!!
What was wrong ?
In x86 32 bit, ISR information is stored in an IDT. The IDT is not simply a list of addresses, and is not necessarily stored at the address 0. For a description of the IDT format, see the OSDev Wiki page. The location of the IDT is determined by the OS, and it might not be accessible to user mode software. Assuming you do have the right to modify it, you can get the location of the IDT using the sidt
instruction.
sidt -6(%esp)
In 32 bit mode, sidt
will store 6 bytes worth of data at the specified location. I used -6(%esp)
for my example, which will store the data just below the current stack. The low two bytes are the length of the IDT, in bytes, and the next 4 (in 32 bit mode) are the address of the IDT. Since each IDT entry is 8 bytes long, the location of the entry you want would be 0x33*8
bytes after the start of the IDT. Before modifying the entry, you should ensure the IDT actually contains that entry (it is at least 0x34*8
bytes long).
Here is an example which finds the IDT, ensures it is long enough, and sets the entry for interrupt 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
An address on x86 consists of a segment and an offset. In real mode, it's segment*16 + offset. In protected mode there's a bit of indirection: the segment register it's really a selector that points to a segment descriptor, which contains the segment base and limit, along with other segment attributes. Instructions that access memory can take an explicit segment specifier (e.g: DS:BX
), or else they take an implicit segment which depends on the register used (e.g: if you use SP the implicit segment is SS).
The IVT in real mode is at address 0000:0000, the IDT in protected mode is at address IDT:0000, where IDT can be accessed via LIDT/SIDT instructions.
You should also take into consideration that if you are running over a Virtual Memory Operating System, you don't have direct access to physical memory, the addresses in your program are virtual addresses that get translated to physical addresses after segmentation and paging.
Resolved :), as there is a BIOS, it already built the GDT/IDT, so I found the address of IDT using sidt and sgdt instructions, and i added my ISR to sidt
精彩评论