⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 system_call.s

📁 带中文注释的 linux 0.11 源代码0.11,很好的
💻 S
📖 第 1 页 / 共 2 页
字号:
pushl $ret_from_sys_call # 把下面调用返回的地址入栈。jmp _math_error # 执行C 函数math_error()(kernel/math/math_emulate.c,37)#### int7 -- 设备不存在或协处理器不存在(Coprocessor not available)。# 如果控制寄存器CR0 的EM 标志置位,则当CPU 执行一个ESC 转义指令时就会引发该中断,这样就# 可以有机会让这个中断处理程序模拟ESC 转义指令(169 行)。# CR0 的TS 标志是在CPU 执行任务转换时设置的。TS 可以用来确定什么时候协处理器中的内容(上下文)# 与CPU 正在执行的任务不匹配了。当CPU 在运行一个转义指令时发现TS 置位了,就会引发该中断。# 此时就应该恢复新任务的协处理器执行状态(165 行)。参见(kernel/sched.c,77)中的说明。# 该中断最后将转移到标号ret_from_sys_call 处执行下去(检测并处理信号)。.align 2_device_not_available:push %dspush %espush %fspushl %edxpushl %ecxpushl %ebxpushl %eaxmovl $0x10,%eax # ds,es 置为指向内核数据段。mov %ax,%dsmov %ax,%esmovl $0x17,%eax # fs 置为指向局部数据段(出错程序的数据段)。mov %ax,%fspushl $ret_from_sys_call # 把下面跳转或调用的返回地址入栈。clts # clear TS so that we can use math5.5 system_call.s 程序movl %cr0,%eaxtestl $0x4,%eax # EM (math emulation bit)# 如果不是EM 引起的中断,则恢复新任务协处理器状态,je _math_state_restore # 执行C 函数math_state_restore()(kernel/sched.c,77)。pushl %ebppushl %esipushl %edicall _math_emulate # 调用C 函数math_emulate(kernel/math/math_emulate.c,18)。popl %edipopl %esipopl %ebpret # 这里的ret 将跳转到ret_from_sys_call(101 行)。#### 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 2_timer_interrupt:push %ds # save ds,es and put kernel data spacepush %es # into them. %fs is used by _system_callpush %fspushl %edx # we save %eax,%ecx,%edx as gcc doesn'tpushl %ecx # save those across function calls. %ebxpushl %ebx # is saved as we use that in ret_sys_callpushl %eaxmovl $0x10,%eax # ds,es 置为指向内核数据段。mov %ax,%dsmov %ax,%esmovl $0x17,%eax # fs 置为指向局部数据段(出错程序的数据段)。mov %ax,%fsincl _jiffies# 由于初始化中断控制芯片时没有采用自动EOI,所以这里需要发指令结束该硬件中断。movb $0x20,%al # EOI to interrupt controller #1outb %al,$0x20 # 操作命令字OCW2 送0x20 端口。# 下面3 句从选择符中取出当前特权级别(0 或3)并压入堆栈,作为do_timer 的参数。movl CS(%esp),%eaxandl $3,%eax # %eax is CPL (0 or 3, 0=supervisor)pushl %eax# do_timer(CPL)执行任务切换、计时等工作,在kernel/shched.c,305 行实现。call _do_timer # 'do_timer(long CPL)' does everything fromaddl $4,%esp # task switching to accounting ...jmp ret_from_sys_call#### 这是sys_execve()系统调用。取中断调用程序的代码指针作为参数调用C 函数do_execve()。# do_execve()在(fs/exec.c,182)。.align 2_sys_execve:lea EIP(%esp),%eaxpushl %eaxcall _do_execveaddl $4,%esp # 丢弃调用时压入栈的EIP 值。ret5.5 system_call.s 程序#### sys_fork()调用,用于创建子进程,是system_call 功能2。原形在include/linux/sys.h 中。# 首先调用C 函数find_empty_process(),取得一个进程号pid。若返回负数则说明目前任务数组# 已满。然后调用copy_process()复制进程。.align 2_sys_fork:call _find_empty_process # 调用find_empty_process()(kernel/fork.c,135)。testl %eax,%eaxjs 1fpush %gspushl %esipushl %edipushl %ebppushl %eaxcall _copy_process # 调用C 函数copy_process()(kernel/fork.c,68)。addl $20,%esp # 丢弃这里所有压栈内容。1: 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:pushl %eaxpushl %ecxpushl %edxpush %dspush %espush %fsmovl $0x10,%eax # ds,es 置为内核数据段。mov %ax,%dsmov %ax,%esmovl $0x17,%eax # fs 置为调用程序的局部数据段。mov %ax,%fs# 由于初始化中断控制芯片时没有采用自动EOI,所以这里需要发指令结束该硬件中断。movb $0x20,%aloutb %al,$0xA0 # EOI to interrupt controller #1 # 送从8259A。jmp 1f # give port chance to breathe1: jmp 1f # 延时作用。1: xorl %edx,%edxxchgl _do_hd,%edx # do_hd 定义为一个函数指针,将被赋值read_intr()或# write_intr()函数地址。(kernel/blk_drv/hd.c)# 放到edx 寄存器后就将do_hd 指针变量置为NULL。testl %edx,%edx # 测试函数指针是否为Null。jne 1f # 若空,则使指针指向C 函数unexpected_hd_interrupt()。movl $_unexpected_hd_interrupt,%edx # (kernel/blk_drv/hdc,237)。1: outb %al,$0x20 # 送主8259A 中断控制器EOI 指令(结束硬件中断)。call *%edx # "interesting" way of handling intr.pop %fs # 上句调用do_hd 指向的C 函数。pop %espop %ds5.5 system_call.s 程序popl %edxpopl %ecxpopl %eaxiret#### 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:pushl %eaxpushl %ecxpushl %edxpush %dspush %espush %fsmovl $0x10,%eax # ds,es 置为内核数据段。mov %ax,%dsmov %ax,%esmovl $0x17,%eax # fs 置为调用程序的局部数据段。mov %ax,%fsmovb $0x20,%al # 送主8259A 中断控制器EOI 指令(结束硬件中断)。outb %al,$0x20 # EOI to interrupt controller #1xorl %eax,%eaxxchgl _do_floppy,%eax # do_floppy 为一函数指针,将被赋值实际处理C 函数程序,# 放到eax 寄存器后就将do_floppy 指针变量置空。testl %eax,%eax # 测试函数指针是否=NULL?jne 1f # 若空,则使指针指向C 函数unexpected_floppy_interrupt()。movl $_unexpected_floppy_interrupt,%eax1: call *%eax # "interesting" way of handling intr.pop %fs # 上句调用do_floppy 指向的函数。pop %espop %dspopl %edxpopl %ecxpopl %eaxiret#### int 39 -- (int 0x27) 并行口中断处理程序,对应硬件中断请求信号IRQ7。# 本版本内核还未实现。这里只是发送EOI 指令。_parallel_interrupt:pushl %eaxmovb $0x20,%aloutb %al,$0x20popl %eaxiret

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -