asm.s中断过程分析

1. 中断调用没有出错号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
_divide_error:
pushl $_do_divide_error 调用函数地址入栈
no_error_code:
//eax和esp指向的内容互换,即eax原来的值入栈,调用函数的地址放到eax
xchgl %eax,(%esp)
pushl %ebx
pushl %ecx
pushl %edx
pushl %edi
pushl %esi
pushl %ebp
push %ds
push %es
push %fs
pushl $0 # "error code" //调用函数的第一个参数
//将堆栈中原指向eip的指针装入edx, 之后压入栈中
lea 44(%esp),%edx
pushl %edx //调用函数的第二个参数
//do_divide_err函数:
//void do_divide_error(long esp, long error_code)
//{
// die("divide error",esp,error_code);
//}
movl $0x10,%edx
//设置ds, es, fs的内容: 内核数据段选择符
mov %dx,%ds
mov %dx,%es
mov %dx,%fs
call *%eax //调用操作数指定地址处的函数,比如do_divide_error();
addl $8,%esp //丢弃前面入栈的2个参数,当前esp重新指向fs
pop %fs
pop %es
pop %ds
popl %ebp
popl %esi
popl %edi
popl %edx
popl %ecx
popl %ebx
popl %eax //弹出交换前eax的内容
iret

2. 中断调用有出错号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
_double_fault:
pushl $_do_double_fault
error_code:
xchgl %eax,4(%esp) # error code <-> %eax
xchgl %ebx,(%esp) # &function <-> %ebx
pushl %ecx
pushl %edx
pushl %edi
pushl %esi
pushl %ebp
push %ds
push %es
push %fs
pushl %eax # error code
lea 44(%esp),%eax # offset
//do_double_deault的具体实现:
//void do_double_fault(long esp, long error_code)
//{
// die("double fault",esp,error_code);
//}
pushl %eax
movl $0x10,%eax
mov %ax,%ds
mov %ax,%es
mov %ax,%fs
call *%ebx 这两步与没有出错号的做法相同
addl $8,%esp
pop %fs
pop %es
pop %ds
popl %ebp
popl %esi
popl %edi
popl %edx
popl %ecx
popl %ebx
popl %eax
iret