这个驻留程序是通过这两个命令完成的: TASM.exe 程序.asm & TLINK.exe /t 程序.obj
为什么当我运行另一个必须中断的.exe时它不起作用?
以下代码必须在屏幕上显示分钟和秒,并在大约 1 秒后更新一次值(因为驻留程序每秒运行 18 次)。
.MODEL SMALL
.CODE
ORG 100H
PROGRAMA:
JMP RESIDE
MINUTOS DB 0d
SEGUNDOS DB 0d
FONDO DB 00001111b
CONTADOR DB 18d
RUTINA PROC
CLI
PUSH AX
PUSH BX
PUSH CX
PUSH SI
PUSH ES
MOV AX, SEG @DATA
MOV DS, AX
CMP CONTADOR, 0b
JNE FIN
CMP SEGUNDOS, 60d
JNE CONTINUE
SISEG60:
MOV SEGUNDOS, 0d
INC MINUTOS
CONTINUE:
MOV AX, 0B800h
MOV ES, AX
XOR AX, AX
;APLICAMOS ATRIBUTO A LAS 4 CASILLAS
MOV AH, FONDO
MOV SI, 3001d
MOV ES:[SI], AH
ADD SI, 2d
MOV ES:[SI], AH
ADD SI, 4d
MOV ES:[SI], AH
ADD SI, 2d
MOV ES:[SI], AH
XOR AX,AX
MOV SI, 3000d
;ESCRIBIMOS LOS MINUTOS
XOR AX,AX
MOV AL, MINUTOS
MOV BL, 10d
DIV BL
ADD AL, 30h
MOV ES:[SI], AL
ADD SI, 2d
ADD AH, 30h
MOV ES:[SI], AH
;ESCRIBIMOS LOS SEGUNDOS
XOR AX, AX
ADD SI, 4d
MOV AL, SEGUNDOS
MOV BL, 10d
DIV BL
ADD AL, 30h
MOV ES:[SI], AL
ADD SI, 2d
ADD AH, 30h
MOV ES:[SI], AH
INC SEGUNDOS
MOV CONTADOR, 18d
FIN:
DEC CONTADOR
POP ES
POP SI
POP CX
POP BX
POP AX
STI
IRET
ENDP
RESIDE:
MOV DX, offset RUTINA
MOV AX, 0
MOV ES, AX
MOV SI, 1Ch
CLI
MOV ES:[SI], DX
MOV ES:[SI+2], CS
STI
MOV DX, offset RESIDE
INT 27h
END PROGRAMA
为什么当我运行另一个必须中断的 .exe 时它使用不工作?
mov si, 1Ch
,您没有设置
int 1Ch
的向量,而是设置
int 07h
的向量(保留中断)。每个中断向量占用4个字节,所以正确的指令是
mov si, 1Ch * 4
。你可以稍微简化一下苦差事,因为
有一个DOS函数可以为你设置中断向量。 reside部分则变为:
reside:
mov dx, OFFSET rutina
mov ax, 251Ch
int 21h ; DOS.SetInterruptVector
mov dx, OFFSET reside
int 27h ; DOS.TerminateAndStayResidient
它“停止工作”的另一个原因是您允许处理程序修改 DS 段寄存器。被中断的程序不会预料到这一点!
如果依赖于 DS 的内存访问次数很少,那么可以选择使用 cs:
段覆盖前缀,而不是设置需要 4 个字节的 DS (push ds
push cs
pop ds
...
pop ds
)。
有关您的处理程序的更多信息。
当您的处理程序开始执行时,中断标志 (IF) 已被 CPU 重置。你的
cli
当处理程序结束时,
iret
sti
没有用。
您的处理程序(当前)不使用 CX 寄存器,因此不需要/没有用在堆栈上保留该寄存器。另一方面,DS ...
我还会吸收子程序中的“APLICAMOS ATRIBUTO A LAS 4 CASILLAS”:
RUTINA PROC
push ax
push bx
push si
push ds
push es
push cs
pop ds
...
CONTINUE:
mov ax, 0B800h
mov es, ax
mov al, MINUTOS
mov si, 3000
call ESCRIBIMOS
mov al, SEGUNDOS
mov si, 3006
call ESCRIBIMOS
inc SEGUNDOS
mov CONTADOR, 18
FIN:
dec CONTADOR
pop es
pop ds
pop si
pop bx
pop ax
iret
; ------------------
; IN (al,es:si)
ESCRIBIMOS:
cbw ; Clears AH because AL is positive [0,59]
mov bl, 10
div bl
add ax, 3030h ; Make ASCII both digits at once
mov bh, FONDO ; Attribute
mov bl, al ; AL is tens digit
mov es:[si], bx
mov bl, ah ; AH is ones digit
mov es:[si+2], bx
ret
; ------------------
ENDP