异常发生后栈的布局:
ss
esp
eflags
cs
eip 以上由硬件自动完成压栈工作
ERROR_ CODE -----异常码,有些异常无异常码,用0代替(pushl 0)
function -----异常处理函数
pushl %ds
pushl %eax
xorl %eax,%eax
pushl %ebp
pushl %edi
pushl %esi
pushl %edx
decl %eax # eax = -1
pushl %ecx
pushl %ebx
cld
movl %es,%ecx
movl ORIG_EAX(%esp), %esi # get the error code
movl ES(%esp), %edi # get the function address
movl %eax, ORIG_EAX(%esp)
movl %ecx, ES(%esp)
movl %esp,%edx
pushl %esi # push the error code
pushl %edx # push the pt_regs pointer
movl $(__KERNEL_DS),%edx
movl %edx,%ds
movl %edx,%es
GET_CURRENT(%ebx)
call *%edi //调用异常处理函数,function(error_code, pt_regs)
addl $8,%esp
jmp ret_from_exception
中断发生后栈的布局:
ss
esp
eflags
cs
eip 以上由硬件自动完成压栈工作
irq --是一个负数, 为中断号-256,用irq & 0xFF取它的值,比如:1-256=-255=0xFFFFFF01, 跟0xFF与之后正好为1,但为什么用一个负数,还没搞清楚
ES
DS
EAX
EBP
EDI
ESI
EDX
ECX
EBX
call do_IRQ
do_IRQ定义如下:asmlinkage unsigned int do_IRQ(struct pt_regs regs)
系统调用发生后栈的布局:
ss
esp
eflags
cs
eip 以上由硬件自动完成压栈工作
syscall_no --系统调用的编号
ES
DS
EAX
EBP
EDI
ESI
EDX
ECX
EBX
call system_table[syscall_no](xxxxx)
我们再看看struct pt_regs刚好与栈中的数据相同,
struct pt_regs {
long ebx;
long ecx;
long edx;
long esi;
long edi;
long ebp;
long eax;
int xds;
int xes;
long orig_eax; //对就中断号或异常码或系统调用号
long eip;
int xcs;
long eflags;
long esp;
int xss;
};