orange's学习--第六章:参考Minix美化时钟中断处理程序ghij

参考Minix,时钟中断处理程序是经过很长时间优化出来的,经过本过程理解代码。

ALIGN    16
hwint00:        ; Interrupt routine for irq 0 (the clock).
    call    save                                                         //保存进程表一个进程信息,并且call指令会在进程表占用一个表项

    in    al, INT_M_CTLMASK    ; `.
    or    al, 1            ;  | 不允许再发生时钟中断
    out    INT_M_CTLMASK, al    ; /

    mov    al, EOI            ; `. reenable
    out    INT_M_CTL, al        ; /  master 8259

    sti
    push    0                    
    call    clock_handler
    add    esp, 4
    cli

    in    al, INT_M_CTLMASK    ; `.
    and    al, 0xFE        ;  | 又允许时钟中断发生
    out    INT_M_CTLMASK, al    ; /

    ret                                              //对应   jmp     [eax + RETADR - P_STACKBASE]  前面一句的push 的地址

 

现在来考虑一下,为什么这个save与我们以前的函数看起来是如此的不同?一般的函数最后都是以ret指令结尾,跳回调用处 
继续执行,那是因为函数所使用的堆栈最后都被释放了,调用时call指令的下一条指令地址被压栈,最后ret指令将这条指令从堆 
栈中弹出,函数调用前后esp的值是一样的。可是我们这里的save函数则不同,调用前后esp的值是完全不同的,甚至是否发生中断重入也影响着esp的值。所以我们必须事先将返回地址保存起来,最后用jmp指令跳转回去。 

; =====================================================
;                                   save
; =====================================================
save:
        pushad          ; `.
        push    ds      ;  |
        push    es      ;  | 保存原寄存器值
        push    fs      ;  |
        push    gs      ; /
        mov     dx, ss
        mov     ds, dx
        mov     es, dx

        mov     eax, esp                                           ;eax = 进程表起始地址

        inc     dword [k_reenter]                               ;k_reenter++;
        cmp     dword [k_reenter], 0                         ;if(k_reenter ==0)
        jne     .1                                                        ;{
        mov     esp, StackTop                                  ;  mov esp, StackTop <--切换到内核栈
        push    restart                                               ;  push restart
        jmp     [eax + RETADR - P_STACKBASE]   ;  return;
.1:                                                                         ;} else { 已经在内核栈,不需要再切换
        push    restart_reenter                                  ;  push restart_reenter
        jmp     [eax + RETADR - P_STACKBASE]   ;  return;
                                                                             ;}

; =====================================================
;                                   restart
; =====================================================
restart:
    mov    esp, [p_proc_ready]
    lldt    [esp + P_LDT_SEL] 
    lea    eax, [esp + P_STACKTOP]
    mov    dword [tss + TSS3_S_SP0], eax
restart_reenter:
    dec    dword [k_reenter]
    pop    gs
    pop    fs
    pop    es
    pop    ds
    popad
    add    esp, 4
    iretd                                                 //最后中断处理完毕,返回中断的进程
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值