我正在使用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
1条答案
按热度按时间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
。这是一个灾难性的因素。不要从中断处理程序中调用任何操作系统函数。简而言之,你的中断处理程序应该设置一些变量来通知你的主循环它应该停止循环。