如何从内存中卸载.EXE驻留程序

问题描述 投票:0回答:1

我有一个程序可以更改 1Ch int 过程并将其自身加载为住宅。它具有 .EXE 结构(我知道 .COM 更好),但我需要 .EXE。我有显示 MCB 块信息的程序。安装新的 1Ch int 程序后,我可以看到出现了一个新的 MCB 块,它与我的住宅程序相关。但在我尝试释放内存(在我看来卸载驻留内存)后,与驻留程序相关的 MCB 块仍然存在。我的.EXE结构如下所示:堆栈段->代码段(这里也有一些数据)。我在加载之前保存 PSP 地址,当我尝试卸载程序时,我将 stadart 1Ch int 过程返回,并将保存的 PSP 地址放入 ES 中,然后我调用 int 21h 的 49h。 那么如何才能完全卸载.EXE住宅程序呢?

UPD:我做了一些编码并且代码可以工作,但是当我尝试在 AFDPRO 中调试它时,第一次启动驻留加载精细的面包时,当我尝试在调试器中加载其他程序时,就像显示 MCB 块一样,调试器崩溃。这是代码:

    ASTACK segment stack
dw 100h dup('*')
END_OF_STACK_MARK = $
ASTACK ends

ACODE segment
assume CS: ACODE, DS: ACODE, SS: ASTACK

NEW_INT_PROC proc far
        push DS                     ;Saving registers
        push ES
        push AX
        push BX
        push CX
        push DX
        push SI
        push DI

        mov AX, ACODE               ;Setting CODE seg to ds to
        mov DS, AX                  ;correctly accessing residential data
        xor AX, AX

        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 DI                      ;Recovering registers
        pop SI
        pop DX
        pop CX
        pop BX
        pop AX
        pop ES
        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

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_MEM_MARK = $

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 ES, ES:[val_RES_PSP_ADDR]
    push ES
    mov ES, ES:2Ch
    mov AH, 49h
    int 21h
    pop ES
    mov AH, 49h
    int 21h
    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

    pop DX
    pop BX
    pop AX
    ret
FREE_RESIDENT endp

IS_RES_RUNNING proc near
        push ES
        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 [val_RES_RUNNING], 1
    EXIT_RES_NOT_RUNNING:
        pop ES
        ret
IS_RES_RUNNING endp

USER_UNLOAD proc near
        push ES
        push AX
        push BX
        mov AH, 62h
        int 21h
        mov ES, BX
        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 BX
        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 
        sub AX, AX
        mov AX, ACODE
        mov DS, AX

        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 NEW_INT_PROC_MEM_MARK
        add DX, offset END_OF_STACK_MARK
        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
assembly x86-16 dos masm
1个回答
0
投票

在中断表中设置 int 1Ch 之前(段:0 偏移量:1Ch*4),您的程序应在程序将例程地址写入该处之前保存存储在该偏移量处的双字。要卸载,您必须恢复该双字。这将恢复旧的中断向量

© www.soinside.com 2019 - 2024. All rights reserved.