?? system_call.s
字號:
mov eax,10h ;// ds,es 置為指向內核數據段。 mov ds,ax mov es,ax mov eax,17h ;// fs 置為指向局部數據段(出錯程序的數據段)。 mov fs,ax push ret_from_sys_call ;// 把下面調用返回的地址入棧。 jmp _math_error ;// 執行C 函數math_error()(kernel/math/math_emulate.c,37);//// int7 -- 設備不存在或協處理器不存在(Coprocessor not available)。;// 如果控制寄存器CR0 的EM 標志置位,則當CPU 執行一個R_ESC 轉義指令時就會引發該中斷,這樣就;// 可以有機會讓這個中斷處理程序模擬R_ESC 轉義指令(169 行)。;// CR0 的TS 標志是在CPU 執行任務轉換時設置的。TS 可以用來確定什么時候協處理器中的內容(上下文);// 與CPU 正在執行的任務不匹配了。當CPU 在運行一個轉義指令時發現TS 置位了,就會引發該中斷。;// 此時就應該恢復新任務的協處理器執行狀態(165 行)。參見(kernel/sched.c,77)中的說明。;// 該中斷最后將轉移到標號ret_from_sys_call 處執行下去(檢測并處理信號)。align 4_device_not_available: push ds push es push fs push edx push ecx push ebx push eax mov eax,10h ;// ds,es 置為指向內核數據段。 mov ds,ax mov es,ax mov eax,17h ;// fs 置為指向局部數據段(出錯程序的數據段)。 mov fs,ax push ret_from_sys_call ;// 把下面跳轉或調用的返回地址入棧。 clts ;// clear TS so that we can use math mov eax,cr0 test eax,4h ;// EM (math emulation bit);// 如果不是EM 引起的中斷,則恢復新任務協處理器狀態,
je goto_math_state_restore;// 執行C 函數math_state_restore()(kernel/sched.c,77)。 push ebp push esi push edi call _math_emulate ;// 調用C 函數math_emulate(kernel/math/math_emulate.c,18)。 pop edi pop esi pop ebp ret ;// 這里的ret 將跳轉到ret_from_sys_call(101 行)。goto_math_state_restore:
jmp _math_state_restore
;//// int32 -- (int 0x20) 時鐘中斷處理程序。中斷頻率被設置為100Hz(include/linux/sched.h,5),;// 定時芯片8253/8254 是在(kernel/sched.c,406)處初始化的。因此這里jiffies 每10 毫秒加1。;// 這段代碼將jiffies 增1,發送結束中斷指令給8259 控制器,然后用當前特權級作為參數調用;// C 函數do_timer(long CPL)。當調用返回時轉去檢測并處理信號。align 4_timer_interrupt: push ds ;// save ds,es and put kernel data space push es ;// into them. %fs is used by _system_call push fs push edx ;// we save %eax,%ecx,%edx as gcc doesn't push ecx ;// save those across function calls. %ebx push ebx ;// is saved as we use that in ret_sys_call push eax mov eax,10h ;// ds,es 置為指向內核數據段。 mov ds,ax mov es,ax mov eax,17h ;// fs 置為指向局部數據段(出錯程序的數據段)。 mov fs,ax inc dword ptr _jiffies;// 由于初始化中斷控制芯片時沒有采用自動EOI,所以這里需要發指令結束該硬件中斷。 mov al,20h ;// EOI to interrupt controller ;//1 out 20h,al ;// 操作命令字OCW2 送0x20 端口。;// 下面3 句從選擇符中取出當前特權級別(0 或3)并壓入堆棧,作為do_timer 的參數。 mov eax,dword ptr [R_CS+esp] and eax,3 ;// %eax is CPL (0 or 3, 0=supervisor) push eax;// do_timer(CPL)執行任務切換、計時等工作,在kernel/shched.c,305 行實現。 call _do_timer ;// 'do_timer(long CPL)' does everything from add esp,4 ;// task switching to accounting ... jmp ret_from_sys_call;//// 這是sys_execve()系統調用。取中斷調用程序的代碼指針作為參數調用C 函數do_execve()。;// do_execve()在(fs/exec.c,182)。align 4_sys_execve: lea eax,[R_EIP+esp] push eax call _do_execve add esp,4 ;// 丟棄調用時壓入棧的R_EIP 值。 ret;//// sys_fork()調用,用于創建子進程,是system_call 功能2。原形在include/linux/sys.h 中。;// 首先調用C 函數find_empty_process(),取得一個進程號pid。若返回負數則說明目前任務數組;// 已滿。然后調用copy_process()復制進程。align 4_sys_fork: call _find_empty_process ;// 調用find_empty_process()(kernel/fork.c,135)。 test eax,eax js l2 push gs push esi push edi push ebp push eax call _copy_process ;// 調用C 函數copy_process()(kernel/fork.c,68)。 add esp,20 ;// 丟棄這里所有壓棧內容。l2: ret;//// int 46 -- (int 0x2E) 硬盤中斷處理程序,響應硬件中斷請求IRQ14。;// 當硬盤操作完成或出錯就會發出此中斷信號。(參見kernel/blk_drv/hd.c)。;// 首先向8259A 中斷控制從芯片發送結束硬件中斷指令(EOI),然后取變量do_hd 中的函數指針放入edx;// 寄存器中,并置do_hd 為NULL,接著判斷edx 函數指針是否為空。如果為空,則給edx 賦值指向;// unexpected_hd_interrupt(),用于顯示出錯信息。隨后向8259A 主芯片送EOI 指令,并調用edx 中;// 指針指向的函數: read_intr()、write_intr()或unexpected_hd_interrupt()。_hd_interrupt: push eax push ecx push edx push ds push es push fs mov eax,10h ;// ds,es 置為內核數據段。 mov ds,ax mov es,ax mov eax,17h ;// fs 置為調用程序的局部數據段。 mov fs,ax;// 由于初始化中斷控制芯片時沒有采用自動EOI,所以這里需要發指令結束該硬件中斷。 mov al,20h out 0A0h,al ;// EOI to interrupt controller ;//1 ;// 送從8259A。 jmp l3 ;// give port chance to breathel3: jmp l4 ;// 延時作用。l4: xor edx,edx xchg edx,dword ptr _do_hd ;// do_hd 定義為一個函數指針,將被賦值read_intr()或;// write_intr()函數地址。(kernel/blk_drv/hd.c);// 放到edx 寄存器后就將do_hd 指針變量置為NULL。 test edx,edx ;// 測試函數指針是否為Null。 jne l5 ;// 若空,則使指針指向C 函數unexpected_hd_interrupt()。 mov edx,dword ptr _unexpected_hd_interrupt ;// (kernel/blk_drv/hdc,237)。l5: out 20h,al ;// 送主8259A 中斷控制器EOI 指令(結束硬件中斷)。 call edx ;// "interesting" way of handling intr. pop fs ;// 上句調用do_hd 指向的C 函數。 pop es pop ds pop edx pop ecx pop eax iretd;//// int38 -- (int 0x26) 軟盤驅動器中斷處理程序,響應硬件中斷請求IRQ6。;// 其處理過程與上面對硬盤的處理基本一樣。(kernel/blk_drv/floppy.c)。;// 首先向8259A 中斷控制器主芯片發送EOI 指令,然后取變量do_floppy 中的函數指針放入eax;// 寄存器中,并置do_floppy 為NULL,接著判斷eax 函數指針是否為空。如為空,則給eax 賦值指向;// unexpected_floppy_interrupt (),用于顯示出錯信息。隨后調用eax 指向的函數: rw_interrupt,;// seek_interrupt,recal_interrupt,reset_interrupt 或unexpected_floppy_interrupt。_floppy_interrupt: push eax push ecx push edx push ds push es push fs mov eax,10h ;// ds,es 置為內核數據段。
mov ds,ax
mov es,ax
mov eax,17h ;// fs 置為調用程序的局部數據段。
mov fs,ax
mov al,20h ;// 送主8259A 中斷控制器EOI 指令(結束硬件中斷)。 out 20h,al ;// EOI to interrupt controller ;//1 xor eax,eax xchg eax,dword ptr _do_floppy ;// do_floppy 為一函數指針,將被賦值實際處理C 函數程序,;// 放到eax 寄存器后就將do_floppy 指針變量置空。 test eax,eax ;// 測試函數指針是否=NULL? jne l6 ;// 若空,則使指針指向C 函數unexpected_floppy_interrupt()。 mov eax,dword ptr _unexpected_floppy_interruptl6: call eax ;// "interesting" way of handling intr. pop fs ;// 上句調用do_floppy 指向的函數。 pop es pop ds pop edx pop ecx pop eax iretd;//// int 39 -- (int 0x27) 并行口中斷處理程序,對應硬件中斷請求信號IRQ7。;// 本版本內核還未實現。這里只是發送EOI 指令。_parallel_interrupt: push eax mov al,20h out 20h,al pop eax iretdend
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -