我试图获得一周的答案。 :)
但是,也许我会问错误的问题。所以这就是它:我需要加载然后卸载住宅程序(设置一些矢量然后回到标准),我这样做但是在安装标准矢量后我尝试使用49h释放为住宅程序分配的内存:首先我得到标准矢量回来,然后我清除环境,然后我清除mem住宅计划。然后我可以通过单击窗口的[X]按钮尝试关闭CMD,但出现错误:
这是我的代码:
ASTACK segment stack
dw 100h dup(?)
mark_END_OF_STACK = $
ASTACK ends
ACODE segment
assume CS: ACODE, DS: ACODE, SS: ASTACK
str_MOD db 'StdMod$' ;\ Residential data (ResMod - if residential program, StdMod - if not residential program)
val_COUNTER db 0 ; |
val_RES_PSP_ADDR dw 0 ; | PSP address of residential programm
val_OLD_INT_PROC_ADDR dd 0 ;/ Old int 1Ch address
NEW_INT_PROC proc far
push DS ;Saving registers
push AX
push CS
pop DS
cmp val_COUNTER, 10
je CLEAR_COUNTER
mov AL, val_COUNTER
add AL, '0'
inc val_COUNTER
call DIRECT_PRINT
jmp EXIT_RES
CLEAR_COUNTER:
mov val_COUNTER, 0
EXIT_RES:
pop AX ;Recovering registers
pop DS
mov AL, 20h
out 20h, AL
iret
NEW_INT_PROC endp
DIRECT_PRINT proc near
push AX
push BX
push CX
push DX
push SP
push BP
push SI
push DI
;Getting current cursor position
mov AH, 03h
mov BH, 00h
int 10h
push DX;Saving current row and column of cursor position
;Settin new cursor position
mov AH, 02h
mov BH, 00h
mov DX, 0000h
int 10h
;Print number from AL
mov AH, 09h
mov BH, 0
;mov BL, 153
mov CX, 1
int 10h
;Recovering cursor position
mov AH, 02h
mov BH, 00h
pop DX;Recoveing initial cursor position
int 10h
pop DI
pop SI
pop BP
pop SP
pop DX
pop CX
pop BX
pop AX
ret
DIRECT_PRINT endp
mark_NEW_INT_PROC_MEM = $
PRNT_MARKED_STRING proc near
;Print string with end of string mark
;String offset must be in DX
push AX
mov AH, 09h
int 21h
pop AX
ret
PRNT_MARKED_STRING endp
LOAD_RESIDENT proc near
push AX
push BX
push DX
mov [str_MOD], 'R'
mov [str_MOD + 1], 'e'
mov [str_MOD + 2], 's'
mov [val_RES_PSP_ADDR], ES ;Save PSP address to realise memory later
push ES
mov AX, 351Ch ;Getting CS:IP of standart interruption procedure
int 21h
mov word ptr [val_OLD_INT_PROC_ADDR], BX ;IP of standart interruption procedure saved
mov word ptr [val_OLD_INT_PROC_ADDR + 2], ES ;CS of standart interruption procedure saved
pop ES
push DS
mov DX, offset NEW_INT_PROC ;Installing new interruption on 1Ch
mov AX, seg NEW_INT_PROC
mov DS, AX
mov AX, 251Ch
int 21h
pop DS
pop DX
pop BX
pop AX
ret
LOAD_RESIDENT endp
FREE_RESIDENT proc near
push AX
push BX
push DX
push ES
mov AX, 351Ch
int 21h
mov AX, word ptr ES:[val_OLD_INT_PROC_ADDR]
mov word ptr [val_OLD_INT_PROC_ADDR], AX
mov BX, word ptr ES:[val_OLD_INT_PROC_ADDR + 2]
mov word ptr [val_OLD_INT_PROC_ADDR + 2], BX
mov BX, ES:[val_RES_PSP_ADDR]
mov [val_RES_PSP_ADDR], BX ;Get residential PSP address
pop ES
cli ;Recovering standart interruption
push DS
mov DX, word ptr [val_OLD_INT_PROC_ADDR]
mov AX, word ptr [val_OLD_INT_PROC_ADDR + 2]
mov DS, AX
mov AX, 251Ch
int 21h
pop DS
sti
mov AH, 49h
push ES
mov ES, [val_RES_PSP_ADDR]
push ES
mov ES, ES:2Ch
int 21h
pop ES
int 21h
pop ES
pop DX
pop BX
pop AX
ret
FREE_RESIDENT endp
IS_RES_RUNNING proc near
push ES
push AX
mov AX, 351Ch
int 21h
cmp ES:[str_MOD], 'R'
jne EXIT_RES_NOT_RUNNING
cmp ES:[str_MOD+1], 'e'
jne EXIT_RES_NOT_RUNNING
cmp ES:[str_MOD+2], 's'
jne EXIT_RES_NOT_RUNNING
cmp ES:[str_MOD+3], 'M'
jne EXIT_RES_NOT_RUNNING
cmp ES:[str_MOD+4], 'o'
jne EXIT_RES_NOT_RUNNING
cmp ES:[str_MOD+5], 'd'
jne EXIT_RES_NOT_RUNNING
mov DS:[val_RES_RUNNING], 1
EXIT_RES_NOT_RUNNING:
pop AX
pop ES
ret
IS_RES_RUNNING endp
USER_UNLOAD proc near
push ES
push AX
mov ES, [val_RES_PSP_ADDR]
cmp byte ptr ES:[80h], 04h
jne EXIT_USR_INLOAD
cmp byte ptr ES:[82h], '/'
jne EXIT_USR_INLOAD
cmp byte ptr ES:[83h], 'u'
jne EXIT_USR_INLOAD
cmp byte ptr ES:[84h], 'n'
jne EXIT_USR_INLOAD
mov [val_RES_USR_UNLOAD], 1
EXIT_USR_INLOAD:
pop AX
pop ES
ret
USER_UNLOAD endp
str_RES_LOADED db 'Residential program has been loaded', 10, 13, '$'
str_RES_RUNNING db 'Residential program is running', 10, 13, '$'
str_RES_NOT_RUNNING db 'Residential program is not running', 10, 13, '$'
str_RES_UNLOADED db 'Residential program has been unloaded', 10, 13, '$'
val_RES_RUNNING db 0
val_RES_USR_UNLOAD db 0
MAIN proc far
push DS
push AX
mov AX, ACODE
mov DS, AX
mov [val_RES_PSP_ADDR], ES ;Saving PSP address
call IS_RES_RUNNING
cmp val_RES_RUNNING, 1
je FREE_RESIDENT_PROG
mov DX, offset str_RES_NOT_RUNNING
call PRNT_MARKED_STRING
mov DX, offset str_RES_LOADED
call PRNT_MARKED_STRING
call LOAD_RESIDENT
mov DX, offset mark_NEW_INT_PROC_MEM
add DX, offset mark_END_OF_STACK
add DX, 10Fh
mov CL, 4
shr DX, CL
mov AX, 3100h
int 21h
FREE_RESIDENT_PROG:
mov DX, offset str_RES_RUNNING
call PRNT_MARKED_STRING
call USER_UNLOAD
cmp [val_RES_USR_UNLOAD], 1
jne EXIT
mov DX, offset str_RES_UNLOADED
call PRNT_MARKED_STRING
call FREE_RESIDENT
EXIT:
mov AX, 4C00h
int 21h
MAIN endp
ACODE ends
end MAIN
请帮助。
答案 0 :(得分:3)
我将介绍一些有关您的计划的意见。看看它是否有帮助!
pop ax
移到中断的知识之下。cli
和sti
是没用的,因为DOS会处理这些细节。你不需要括号来读取环境指针吗? mov ES, ES:[002Ch]
请写mov ah, 49h
2次以防止第一次通话时出错。 mov DX, offset mark_NEW_INT_PROC_MEM
和add DX, offset mark_END_OF_STACK
中删除偏移标记。这些符号常量本身具有正确的价值。我将如何更改 FREE_RESIDENT proc
push AX
push BX
push DX
push ES
push DS
mov AX, 351Ch
int 21h ; => ES:BX
mov BX, ES:[val_RES_PSP_ADDR]
mov DX, ES:[val_OLD_INT_PROC_ADDR]
mov DS, ES:[val_OLD_INT_PROC_ADDR + 2]
mov AX, 251Ch
int 21h
mov ES, BX
mov ES, ES:[002Ch]
mov AH, 49h
int 21h
mov ES, BX
mov AH, 49h
int 21h
pop DS
pop ES
pop DX
pop BX
pop AX
ret
答案 1 :(得分:1)
除了@ user3144770所说的内容。
NEW_INT_PROC proc不需要知道中断。这是由硬件中断08h的处理程序完成的。
如果MASM自动将 ASTACK 堆栈段放在代码下面(并且不包含在.EXE文件中),那么在调用31h DOS函数之前,不应该在DX的计算中包含这个空格。此外,您的中断处理程序无论如何都不会使用此堆栈。