int.s文件的核心功能是對(duì)中斷進(jìn)行設(shè)置,不過這里把一些中斷處理程序也放進(jìn)來,而且還把其他文件中用到的一些庫函數(shù)放到這兒,目的是為了方便,不需再在lib/目錄下重新建立asmlib.s類似的文件。由于該文件比較長(zhǎng),所有分兩部分解析。
1 %include "asm/int.sh"
2
3 extern boot_heartbeat
4 extern pre_schedule
5 extern validate_buffer
6 extern sys_call_table
7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
8 ; 到處中斷向量表和中斷描述符表寄存器
9 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
10 global idt
11 global idtr
12
13 global set_idt
14 global sys_call
15
16 global out_byte
17 global in_byte
18 global read_port
19 global write_port
20 global install_int_handler
21 global uninstall_int_handler
22 global install_sys_call_handler
23 global enable_hwint
24 global disable_hwint
25
26 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
27 ; 處理器能夠處理的默認(rèn)中斷和異常
28 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
29 global divide_error
30 global debug_exception
31 global nmi
32 global breakpoint_exception
33 global overflow
34 global bounds_check
35 global inval_opcode
36 global copr_not_available
37 global double_fault
38 global copr_seg_overrun
39 global inval_tss
40 global segment_not_present
41 global stack_exception
42 global general_protection
43 global page_fault
44 global copr_error
45 global exception
46
47 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
48 ; 可屏蔽的硬件中斷
49 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
50 global int_clock
51 global int_keyboard
52 global int_serial_port2
53 global int_serial_port1
54 global int_lpt2
55 global int_floppy
56 global int_lpt1
57 global int_rtc
58 global int_ps_2_mouse
59 global int_fpu_fault
60 global int_at_win
61 global int_default
62
63 [SECTION .text]
64 set_idt:
65 ; 對(duì)8259A主片寫入ICW1
66 push 0x11
67 push MASTER_CTL_8259
68 call out_byte
69 add esp, 4 * 2
70
71 ; 對(duì)8259A從片寫入ICW1
72 push 0x11
73 push SLAVE_CTL_8259
74 call out_byte
75 add esp, 4 * 2
76
77 ; 設(shè)置8259A主片的中斷入口地址,為IRQ0_IV
78 push IRQ0_IV
79 push MASTER_CTL_MASK_8259
80 call out_byte
81 add esp, 4 * 2
82
83 ; 設(shè)置8259A從片的中斷入口地址,為IRQ8_IV
84 push IRQ8_IV
85 push SLAVE_CTL_MASK_8259
86 call out_byte
87 add esp, 4 * 2
88
89 ; 向8259A主片寫入ICW3,表明IR2處級(jí)聯(lián)了從片
90 push 0x4
91 push MASTER_CTL_MASK_8259
92 call out_byte
93 add esp, 4 * 2
94
95 ; 向8259A從片寫入ICW3,表明從片是連接在主片的IR2處
96 push 0x2
97 push SLAVE_CTL_MASK_8259
98 call out_byte
99 add esp, 4 * 2
100
101 ; 向8259A主片寫入ICW4
102 push 0x1
103 push MASTER_CTL_MASK_8259
104 call out_byte
105 add esp, 4 * 2
106
107 ; 向8259A從片寫入ICW4
108 push 0x1
109 push SLAVE_CTL_MASK_8259
110 call out_byte
111 add esp, 4 * 2
112
113 ; 屏蔽8259A主片的所有硬件中斷
114 push 0xff
115 push MASTER_CTL_MASK_8259
116 call out_byte
117 add esp, 4 * 2
118
119 ; 屏蔽8259A從片的所有硬件中斷
120 push 0xff
121 push SLAVE_CTL_MASK_8259
122 call out_byte
123 add esp, 4 * 2
124
125 ; 除零錯(cuò)誤(內(nèi)核態(tài)允許的中斷)
126 ; 指令div or idiv
127 push PRIVILEGE_KERNEL
128 push divide_error
129 push INT_GATE_386
130 push DIVIDE_IV
131 call init_idt
132 add esp, 4 * 4
133
134 ; 調(diào)試異常(內(nèi)核態(tài)允許的中斷)
135 push PRIVILEGE_KERNEL
136 push debug_exception
137 push INT_GATE_386
138 push DEBUG_IV
139 call init_idt
140 add esp, 4 * 4
141
142 ; 非屏蔽中斷(內(nèi)核態(tài)允許的中斷)
143 push PRIVILEGE_KERNEL
144 push nmi
145 push INT_GATE_386
146 push NMI_IV
147 call init_idt
148 add esp, 4 * 4
149
150 ; 調(diào)試斷點(diǎn)異常(用戶態(tài)允許的中斷)
151 ; 指令int3
152 push PRIVILEGE_USER
153 push breakpoint_exception
154 push INT_GATE_386
155 push BREAKPOINT_IV
156 call init_idt
157 add esp, 4 * 4
158
159 ; 溢出異常(用戶態(tài)允許的中斷)
160 ; 指令into
161 push PRIVILEGE_USER
162 push overflow
163 push INT_GATE_386
164 push OVERFLOW_IV
165 call init_idt
166 add esp, 4 * 4
167
168 ; 越界錯(cuò)誤(內(nèi)核態(tài)允許的中斷)
169 ; linux將其設(shè)置為用戶態(tài)也允許的中斷
170 ; 指令bound
171 push PRIVILEGE_KERNEL
172 push bounds_check
173 push INT_GATE_386
174 push BOUNDS_IV
175 call init_idt
176 add esp, 4 * 4
177
178 ; 無效操作碼錯(cuò)誤(內(nèi)核態(tài)允許的中斷)
179 ; 主要由ud2或無效指令引起
180 push PRIVILEGE_KERNEL
181 push inval_opcode
182 push INT_GATE_386
183 push INVAL_OP_IV
184 call init_idt
185 add esp, 4 * 4
186
187 ; 設(shè)備不可用/無數(shù)學(xué)協(xié)處理器(內(nèi)核態(tài)允許的中斷)
188 ; 浮點(diǎn)數(shù)或wait/fwait指令
189 push PRIVILEGE_KERNEL
190 push copr_not_available
191 push INT_GATE_386
192 push COPROC_NOT_IV
193 call init_idt
194 add esp, 4 * 4
195
196 ; 雙重錯(cuò)誤(內(nèi)核態(tài)允許的中斷)
197 ; 所有能產(chǎn)生異?;騈MI或intr的指令
198 push PRIVILEGE_KERNEL
199 push double_fault
200 push INT_GATE_386
201 push DOUBLE_FAULT_IV
202 call init_idt
203 add esp, 4 * 4
204
205 ; 386機(jī)器不再產(chǎn)生此種異常
206 push PRIVILEGE_KERNEL
207 push copr_seg_overrun
208 push INT_GATE_386
209 push COPROC_SEG_IV
210 call init_idt
211 add esp, 4 * 4
212
213 ; 無效TSS錯(cuò)誤(內(nèi)核態(tài)允許的中斷)
214 ; 任務(wù)切換或訪問TSS段時(shí)
215 push PRIVILEGE_KERNEL
216 push inval_tss
217 push INT_GATE_386
218 push INVAL_TSS_IV
219 call init_idt
220 add esp, 4 * 4
221
222 ; 段不存在錯(cuò)誤(內(nèi)核態(tài)允許的中斷)
223 ; 加載段寄存器或訪問系統(tǒng)段時(shí)
224 push PRIVILEGE_KERNEL
225 push segment_not_present
226 push INT_GATE_386
227 push SEG_NOT_IV
228 call init_idt
229 add esp, 4 * 4
230
231 ; 堆棧段錯(cuò)誤(內(nèi)核態(tài)允許的中斷)
232 ; 堆棧段操作或加載ss時(shí)
233 push PRIVILEGE_KERNEL
234 push stack_exception
235 push INT_GATE_386
236 push STACK_FAULT_IV
237 call init_idt
238 add esp, 4 * 4
239
240 ; 常規(guī)保護(hù)錯(cuò)誤(內(nèi)核態(tài)允許的中斷)
241 ; 內(nèi)存或其他保護(hù)檢驗(yàn)時(shí)
242 push PRIVILEGE_KERNEL
243 push general_protection
244 push INT_GATE_386
245 push PROTECTION_IV
246 call init_idt
247 add esp, 4 * 4
248
249 ; 頁錯(cuò)誤(內(nèi)核態(tài)允許的中斷)
250 ; 內(nèi)存訪問時(shí)
251 push PRIVILEGE_KERNEL
252 push page_fault
253 push INT_GATE_386
254 push PAGE_FAULT_IV
255 call init_idt
256 add esp, 4 * 4
257
258
259 ;;;;;;;;;;;;;;;;注意這里0x0f號(hào)中斷保留,未使用
260
261
262 ; x87FPU浮點(diǎn)錯(cuò)誤(內(nèi)核態(tài)允許的中斷)
263 ; x87FPU浮點(diǎn)指令或WAIT/FWAIT指令
264 push PRIVILEGE_KERNEL
265 push copr_error
266 push INT_GATE_386
267 push COPROC_ERR_IV
268 call init_idt
269 add esp, 4 * 4
以上代碼雖然比較長(zhǎng),但是任務(wù)很簡(jiǎn)單主要完成的有:
1、設(shè)置8259A,80X86架構(gòu)里面內(nèi)置有兩片8259A,通過設(shè)置達(dá)到如下效果:分為主8259A和從8259A,從片連接在主片的IRQ2引腳上;設(shè)置主片的IRQ0引腳(時(shí)鐘中斷)的中斷號(hào)為IRQ0_IV(0x20),從8259A的IRQ0引腳的中斷號(hào)為IRQ8_IV;然后設(shè)置默認(rèn)屏蔽所有的主片和從片的中斷(這樣是為了在初始化對(duì)應(yīng)的硬件的時(shí)候再打開對(duì)應(yīng)中斷);
2、設(shè)置0~15號(hào)中斷向量,這些中斷向量都是Intel規(guī)定的中斷;設(shè)置中斷的核心函數(shù)是init_idt,該函數(shù)稍后會(huì)講解。
1 ; 從0x20開始到中斷向量表尾部,統(tǒng)一初始化成默認(rèn)的中斷處理程序
2 mov ecx, IRQ0_IV
3 push PRIVILEGE_KERNEL
4 push int_default
5 push INT_GATE_386
6 init_rest:
7 push ecx
8 call init_idt
9 pop ecx
10 inc ecx
11 cmp ecx, 255
12 jna init_rest
13 add esp, 4 * 3
14
15 ; 全部中斷向量入口程序加載完成之后便加載中斷描述符表
16 lidt [idtr] ; 加載中斷描述符表
17 ret
18
19 init_idt:
20 mov eax, [esp + 4 * 1] ; 中斷向量號(hào)
21 mov ebx, [esp + 4 * 2] ; 描述符類型(中斷門/調(diào)用門/陷阱門)
22 mov ecx, [esp + 4 * 3] ; 中斷處理程序入口
23 mov edx, [esp + 4 * 4] ; 特權(quán)級(jí)
24 mov esi, idt
25 shl eax, 3
26 add esi, eax ; 中斷向量號(hào)乘以8然后加上idt基地址就能找到對(duì)用中斷向量號(hào)的idt描述符
27 mov word [esi], cx
28 add esi, 2
29 mov word [esi], 0x8 ; CS段描述符
30 add esi, 2
31 mov byte [esi], 0x0
32 add esi, 1
33 shl edx, 5
34 and bl, 0x0f
35 or bl, 0x80
36 or bl, dl
37 mov byte [esi], bl
38 add esi, 1
39 shr ecx, 16
40 mov word [esi], cx
41 ret
42
43 ; 在發(fā)生中斷時(shí),eflags、cs、eip將自動(dòng)被壓入棧中
44 ; 如果有出錯(cuò)碼的話,那么出錯(cuò)碼緊接著繼續(xù)被壓入棧中(同樣被自動(dòng)壓入棧中)
45 ; 如果有堆棧切換,也就是說有特權(quán)級(jí)變化,那么原ss和esp將被壓入內(nèi)層堆棧,之后才是eflags、cs、eip
46 ; 從中斷或者異常中返回時(shí)必須用iretd,它與ret不同的時(shí)它會(huì)改變eflags的值
47 divide_error:
48 push 0xffffffff
49 push DIVIDE_IV
50 jmp exception
51
52 debug_exception:
53 push 0xffffffff
54 push DEBUG_IV
55 jmp exception
56
57 nmi:
58 push 0xffffffff
59 push NMI_IV
60 jmp exception
61
62 breakpoint_exception:
63 push 0xffffffff
64 push BREAKPOINT_IV
65 jmp exception
66
67 overflow:
68 push 0xffffffff
69 push OVERFLOW_IV
70 jmp exception
71
72 bounds_check:
73 push 0xffffffff
74 push BOUNDS_IV
75 jmp exception
76
77 inval_opcode:
78 push 0xffffffff
79 push INVAL_OP_IV
80 jmp exception
81
82 copr_not_available:
83 push 0xffffffff
84 push COPROC_NOT_IV
85 jmp exception
86
87 double_fault:
88 push DOUBLE_FAULT_IV
89 jmp exception
90
91 copr_seg_overrun:
92 push 0xffffffff
93 push COPROC_SEG_IV
94 jmp exception
95
96 inval_tss: ; 系統(tǒng)將出錯(cuò)碼自動(dòng)壓棧
97 push INVAL_TSS_IV
98 jmp exception
99
100 segment_not_present: ; 系統(tǒng)將出錯(cuò)碼自動(dòng)壓棧
101 push SEG_NOT_IV
102 jmp exception
103
104 stack_exception: ; 系統(tǒng)將出錯(cuò)碼自動(dòng)壓棧
105 push STACK_FAULT_IV
106 jmp exception
107
108 general_protection: ; 系統(tǒng)將出錯(cuò)碼自動(dòng)壓棧
109 push PROTECTION_IV
110 jmp $
111 jmp exception
112
113 page_fault: ; 系統(tǒng)將出錯(cuò)碼自動(dòng)壓棧
114 push PAGE_FAULT_IV
115 jmp exception
116
117 copr_error:
118 push 0xffffffff
119 push COPROC_ERR_IV
120 jmp exception
121
122 exception:
123 add esp, 4 * 2 ; 跳過出錯(cuò)碼和向量號(hào)
124 cli
125 hlt ; 我們目前不處理錯(cuò)誤,只要出錯(cuò)就讓機(jī)器hlt
126 ;iretd
127
上面這段代碼主要完成的工作有:
1、初始化從0x20-0xff的所有中斷向量,使得這些中斷向量均指向默認(rèn)的中斷處理函數(shù)int_default;
2、init_idt函數(shù)的實(shí)現(xiàn),該函數(shù)有如下形式:void init_idt(int iv, int privil, void *fun, int descr_type); 接受的四個(gè)參數(shù)依次是中斷向量號(hào),該中斷特權(quán)級(jí),中斷處理函數(shù),描述符類型(是中斷門or調(diào)用門or陷阱門);該函數(shù)通過設(shè)置對(duì)應(yīng)IDT中的描述符項(xiàng)的屬性完成設(shè)置。
3、0x00-0x0f的中斷處理函數(shù)的實(shí)現(xiàn),其實(shí)這些函數(shù)都跳轉(zhuǎn)到(不是調(diào)用,是直接跳轉(zhuǎn))exception函數(shù),該函數(shù)直接將系統(tǒng)hlt,意思是我們的系統(tǒng)目前不支持例如除零錯(cuò)誤等的異常中斷。
posted on 2012-02-14 00:21
myjfm 閱讀(542)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
操作系統(tǒng)