Assembly 将ISR链接到向量中断80x86 32位AT&;T组件
我从事Intel Atom 32位(汇编AT&T)的工作 我想将ISR链接到向量中断0x33:Assembly 将ISR链接到向量中断80x86 32位AT&;T组件,assembly,x86,Assembly,X86,我从事Intel Atom 32位(汇编AT&T)的工作 我想将ISR链接到向量中断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) pop %ebp //Return to the calling fun
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)
pop %ebp //Return to the calling function
ret
当我尝试使用我的int$0x33时,什么都没有发生
怎么了?在x86 32位中,ISR信息存储在IDT中。IDT不仅仅是地址列表,也不一定存储在地址0处。有关IDT格式的说明,请参阅。IDT的位置由操作系统决定,用户模式软件可能无法访问它。假设您有权修改它,您可以使用
sidt
指令获取IDT的位置
sidt -6(%esp)
在32位模式下,sidt
将在指定位置存储6字节的数据。我在示例中使用了-6(%esp)
,它将数据存储在当前堆栈的正下方。低两个字节是IDT的长度,以字节为单位,接下来的4个字节(在32位模式下)是IDT的地址。由于每个IDT条目的长度为8个字节,因此所需条目的位置应为IDT开始后的0x33*8
字节。在修改条目之前,您应该确保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
在x86 32位中,ISR信息存储在IDT中。IDT不仅仅是地址列表,也不一定存储在地址0处。有关IDT格式的说明,请参阅。IDT的位置由操作系统决定,用户模式软件可能无法访问它。假设您有权修改它,您可以使用
sidt
指令获取IDT的位置
sidt -6(%esp)
在32位模式下,sidt
将在指定位置存储6字节的数据。我在示例中使用了-6(%esp)
,它将数据存储在当前堆栈的正下方。低两个字节是IDT的长度,以字节为单位,接下来的4个字节(在32位模式下)是IDT的地址。由于每个IDT条目的长度为8个字节,因此所需条目的位置应为IDT开始后的0x33*8
字节。在修改条目之前,您应该确保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
x86上的地址由一个段和一个偏移量组成。在实模式下,它是段*16+偏移。在保护模式下有一点间接性:段寄存器它实际上是一个指向段描述符的选择器,该描述符包含段基址和限制以及其他段属性。访问内存的指令可以采用显式段说明符(例如:
DS:BX
),或者采用取决于所用寄存器的隐式段(例如:如果使用SP,则隐式段为SS)
实模式下的IVT位于地址0000:0000,保护模式下的IDT位于地址IDT:0000,其中IDT可通过LIDT/SIDT指令访问
您还应该考虑到,如果在虚拟内存操作系统上运行,您无法直接访问物理内存,程序中的地址是虚拟地址,在分段和分页后会转换为物理地址。x86上的地址由段和偏移组成。在实模式下,它是段*16+偏移。在保护模式下有一点间接性:段寄存器它实际上是一个指向段描述符的选择器,该描述符包含段基址和限制以及其他段属性。访问内存的指令可以采用显式段说明符(例如:
DS:BX
),或者采用取决于所用寄存器的隐式段(例如:如果使用SP,则隐式段为SS)
实模式下的IVT位于地址0000:0000,保护模式下的IDT位于地址IDT:0000,其中IDT可通过LIDT/SIDT指令访问
您还应该考虑到,如果您在虚拟内存操作系统上运行,您无法直接访问物理内存,程序中的地址是虚拟地址,在分段和分页后转换为物理地址。解析:),因为有BIOS,它已经构建了GDT/IDT,因此,我使用sidt和sgdt指令找到了IDT的地址,并将我的ISR添加到sidt中(已解决:),因为有一个BIOS,它已经构建了GDT/IDT,所以我使用sidt和sgdt指令找到了IDT的地址,并将我的ISR添加到sidt中+1很好的答案,除了必须的链接外,我没有其他要添加的内容。(哦,为了完整起见,可能会在顶部加一个
sub$8,%esp
)@user786653谢谢你的链接。至于低于8美元的价格,%esp
,我的回答取决于你的推理。如果1)您正在为函数对齐堆栈,这是不必要的,因为没有函数调用;或者2)您希望使用正偏移量%esp
,我更喜欢在红色区域中尽可能地处理如此少量的数据。我想在堆栈上分配空间,我不记得在32位x86上使用过带有红色区域的调用约定吗?无论哪种方式,任何能够理解和使用上述代码的人都应该能够轻松地对其调用约定进行适当的调整:)谢谢,当我测试这段代码时,它总是在IDT_too_short宏中!!!,使用此代码进行调查后:sidt-6(%esp)movb-1(%esp),%ah movb-2(%esp),%al movb-3(%esp),%bh movb-4(%esp),%bl movb-5(%esp),%ch movb-6(%esp),%cl%ah=00%al=00%bh=03%bl=06%ch=00%cl=00,因为我在32位,所以解释应该是:DEST[0:15]← IDTR(极限)=0x00目的地[16:47]← IDTR(Base);FI;(*全32位