c - 基于零的Linux asm ("int $0x0" ) vs 划分

  显示原文与译文双语对照的内容
0 0

有人能解释之间的差异汇编指令 int $0x00然后执行实际的被零除。 我设置了断点在divide_error( ) 处理函数在内核中与第0 个关联项IDT ( 除法错误) 。

当我这样做在我C 程序:

int i = 5/0;

然后我打了断点( 按预期) 。 但是,

asm volatile ("int $0x00")

都不触发处理程序。 为什么?

时间:原作者:2个回答

0 0

int 0h不是一回事如 " CPU 生成陷阱由于除数为零0 。

文章的Phrack 解释IDT和Linux如何设置起来的做得很好。 这些关键部分是:

DPL=Descriptor Privilege Level
    The DPL is equal to 0 or 3. Zero is the most privileged level (kernel
mode).  The current execution level is saved in the CPL register (Current
Privilege Level). The UC (Unit Of Control) compares the value of the CPL
register against the DPL field of the interrupt in the IDT. The interrupt
handler is executed if the DPL field is greater (less privileged) or equal
to the value in the CPL register. Userland applications are executed in
ring3 (CPL==3). Certain interrupt handlers can thus not be invoked by
userland applications.
...
linux/arch/i386/kernel/traps.c::set_system_gate(n, addr)
        insert a trap gate.
    The DPL field is set to 3.
These interrupts can be invoked from the userland (ring3).
                set_system_gate(3,&int3)
                set_system_gate(4,&overflow)
                set_system_gate(5,&bounds)
                set_system_gate(0x80,&system_call);
linux/arch/i386/kernel/traps.c::set_trap_gate(n, addr)
        insert a trap gate with the DPL field set to 0.
        The Others exception are initialized with set_trap_gate : 
                set_trap_gate(0,&divide_error)
                set_trap_gate(1,&debug)
                set_trap_gate(2,&nmi)
                set_trap_gate(6,&invalid_op)
                set_trap_gate(7,&device_not_available)
                set_trap_gate(8,&double_fault)
                set_trap_gate(9,&coprocessor_segment_overrun)
                set_trap_gate(10,&invalid_TSS)
                set_trap_gate(11,&segment_not_present)
                set_trap_gate(12,&stack_segment)
                set_trap_gate(13,&general_protection)
                set_trap_gate(14,&page_fault)
                set_trap_gate(15,&spurious_interrupt_bug)
                set_trap_gate(16,&coprocessor_error)
                set_trap_gate(17,&alignement_check)
                set_trap_gate(18,&machine_check)

那里的说明解释得很好。 oNLY int3,4,5 - 最后可以调用0x80从用户空间,因为内核设置其陷阱门( Descriptor Prvilege Level ) dpl=3 。

提到的其他处理器异常向量DPL=0 ( ring 0 ) 中只能调用。

当你的CPU除数为零,首先切换到Ring 0 和内核处理该异常, divide_error. 如果显式调用它, int 0x00然而,你仍在( Current Privilege Level ) cpl=3 。

对于非常低级别nitty坚韧不拔的详细信息,你应该查阅Intel Software开发者是Manual 。 卷2 介绍了 int指令执行的步骤,并给出了所有决策的CPU才会决定如何处理trap/interrupt 。 卷2 介绍的私密细节IDT,陷阱Gates等。

具体来说,Table 3 61 Decision Table 说明每年都是发生在每一个可能的中断方式。 在你的例子中,调用 int 0x00使你进入第2 列,这实质上说,

if PE=1                 # protected mode enabled
and DPL < CPL           # DPL=0 - kernel set up trap gate like this
                        # CPL=3 - b/c you're in user-mode
and int type == S/W     # you executed int instruction (s/w interrupt)
then issue #GP          # General Protection fault
                        # -- kernel delivers this to usermode as SIGSEGV

更多参考:

原作者:
0 0

如果希望简单的说,是那个除数为零中断只能由内核调用。 如果希望再听签出答案从ZarathustrA 这里

原作者:
...