assembly 如何在8086汇编语言中捕获定时器中断

5f0d552i  于 2023-04-12  发布在  其他
关注(0)|答案(1)|浏览(126)

我正在使用tasm和dosbox来解决一个问题。我必须捕获定时器中断并输出所有自然数的平方,直到它们具有16位长度。在示例中,我的教授提供了08h中断被替换为新的中断,这不是一件好事,因为更改08h可能会导致故障。据我所知,切换1ch中断要好得多。这是由08h每18,2毫秒触发,并没有做任何必要的计算机.此外阅读我的教授的代码给我留下了大量的什么和为什么.我写了下面的代码,但它似乎并不像预期的那样工作,它确实输出广场,然而,它在一个随机的时刻停止执行,我不明白我错过了什么。任何帮助将不胜感激,感谢阅读

.MODEL SMALL
.STACK 1024H 
.DATA     
  NUM    DB 1
  SQUARE DW ?         
.CODE  
  ASSUME CS:@CODE, DS:@DATA, ES:NOTHING 
  START:    
  OLD_INT_SEG DW ?
  OLD_INT_OFF DW ? 
  MOV AX, @DATA
  MOV DS, AX
  ;saving away the old interrupt;         
  MOV AX, 0
  MOV ES, AX
  MOV AX, ES:[1CH * 4]     
  MOV WORD PTR OLD_INT_OFF, AX
  MOV AX, ES:[1CH * 4 + 2]
  MOV WORD PTR OLD_INT_SEG, AX          
  ;patching into the new one;
  CLI 
  MOV WORD PTR ES:[1CH * 4], OFFSET TIMER_ISR 
  MOV WORD PTR ES:[1CH * 4 + 2], CS      
  STI   
  ;calculating squares;    
  TO_THE_SECOND_POWER:  
    XOR AX, AX
    MOV AL, NUM   
    MUL NUM
    ;outputing them;  
    CALL PRINT_NUM    
    INC NUM
  LOOP TO_THE_SECOND_POWER
  ;the new isr's body;              
  TIMER_ISR PROC NEAR     
    PUSH DS
    PUSH AX
    MOV AX, @DATA
    MOV DS, AX 
    JС OVERFLOW_REACHED   
    POP AX           
    POP DS 
   ;calling the original 1ch isr; 
    JMP CS:OLD_INT_OFF   
  TIMER_ISR ENDP        
  PRINT_NUM PROC 
    PUSH BX
    PUSH DX
    PUSH SI 
    PUSH CX 
    MOV CX, 0
    MOV BX, 10  
    LOOP_HERE: 
      MOV DX, 0 
      DIV BX 
      PUSH AX 
      ADD DL, "0"  
      POP AX  
      PUSH DX  
      INC CX  
      CMP AX, 0 
    JNZ LOOP_HERE
    MOV AH, 2  
    LOOP_HERE_2: 
      POP DX      
      MOV AH, 02H  
      INT 21H
    LOOP LOOP_HERE_2   
    MOV DL, 10
    MOV AH, 02H
    INT 21H
    MOV DL, 13
    MOV AH, 02H
    INT 21H
    POP CX 
    POP SI 
    POP DX 
    POP BX 
    RET
  PRINT_NUM ENDP  
  ;if overflow has occurred;
  OVERFLOW_REACHED:  
  ;restoring the old isr;                  
  MOV AX, 0
  MOV ES, AX
  CLI 
  MOV AX, WORD PTR OLD_INT_OFF  
  MOV ES:[1CH * 4], AX
  MOV AX, WORD PTR OLD_INT_SEG
  MOV ES:[1CH * 4 + 2], AX
  STI
  ;and terminating the program;    
  MOV AH, 4CH                     
  MOV AL, 0H                   
  INT 21H                     
END START   
CODE ENDS
d7v8vwbk

d7v8vwbk1#

1.您的代码段从START:标签开始,带有两个DW ?指令。它们将像代码一样执行。您的代码没有在那里崩溃,这是一个奇迹。
1.为了完全(偏执地)正确,保存旧的中断应该在CLI/STI块内完成,因为理论上有人可能会在您保存它之后和修补它之前更改它。
1.如果设置了C标志,则JС OVERFLOW_REACHED会跳转,但不会遵循任何修改C标志的指令。(MOV指令***不会***更改C标志。)因此,如果C标志被中断抢占的任何代码设置,则它可能会跳转。这是灾难的根源。
1.循环LOOP TO_THE_SECOND_POWER使用CX寄存器作为循环计数器。您无需在任何地方初始化CX
1.在LOOP TO_THE_SECOND_POWER之后,你没有做任何有意义的事情来确保你的程序将优雅地处理它计算所有要计算的数字的情况。
1.您的中断处理程序可能会调用OVERFLOW_REACHED:,而OVERFLOW_REACHED:又会调用INT 21H。这是一个灾难性的因素。不要从中断处理程序中调用任何操作系统函数。
简而言之,你的中断处理程序应该设置一些变量来通知你的主循环它应该停止循环。

相关问题