释放为.EXE住宅程序分配的内存后出错

时间:2015-04-08 21:29:57

标签: assembly x86 dos masm tsr

我试图获得一周的答案。 :)

但是,也许我会问错误的问题。所以这就是它:我需要加载然后卸载住宅程序(设置一些矢量然后回到标准),我这样做但是在安装标准矢量后我尝试使用49h释放为住宅程序分配的内存:首先我得到标准矢量回来,然后我清除环境,然后我清除mem住宅计划。然后我可以通过单击窗口的[X]按钮尝试关闭CMD,但出现错误:enter image description here

这是我的代码:

 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

请帮助。

2 个答案:

答案 0 :(得分:3)

我将介绍一些有关您的计划的意见。看看它是否有帮助!

  1. NEW_INT_PROC proc在弹出AX后仍然使用AL以恢复它。将pop ax移到中断的知识之下。
  2. DIRECT_PRINT proc推送并弹出SP,这很傻!在执行功能02h和03h时,也不要相信BIOS不会破坏AL。
  3. LOAD_RESIDENT 中,proc DS已指向 NEW_INT_PROC 的段,ES的值已保存在 val_RES_PSP_ADDR 变量中。
  4. FREE_RESIDENT 过程中,使用clisti是没用的,因为DOS会处理这些细节。你不需要括号来读取环境指针吗? mov ES, ES:[002Ch]请写mov ah, 49h 2次以防止第一次通话时出错。
  5. IS_RES_RUNNING proc忘记推送/弹出BX。
  6. MAIN 过程中,您不需要推送DS / AX。无论如何你都不会弹出它。您可以在mov DX, offset mark_NEW_INT_PROC_MEMadd DX, offset mark_END_OF_STACK中删除偏移标记。这些符号常量本身具有正确的价值。
  7. 我将如何更改 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的计算中包含这个空格。此外,您的中断处理程序无论如何都不会使用此堆栈。