1

我试图得到一个星期的答案。:)

但是,也许我问错了问题。所以就是这样:我需要加载然后卸载住宅程序(设置一些向量然后回到标准),我这样做但是在安装标准向量之后我尝试使用 49h 释放分配给住宅程序的内存:首先我得到标准向量返回,然后我清除环境,然后我清除内存用于住宅程序。然后我可以尝试通过单击窗口的 [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

请帮忙。

4

2 回答 2

3

我将介绍一些关于您的程序的意见。看看有没有帮助!

  1. NEW_INT_PROC proc 在 AX 弹出仍使用 AL 以恢复它。移动pop ax下面的中断确认。
  2. DIRECT_PRINT proc推送和弹出 SP,这很愚蠢!也不要相信 BIOS 在执行功能 02h 和 03h 时不会破坏 AL。
  3. LOAD_RESIDENT 过程中DS 已经指向NEW_INT_PROC的段并且 ES 的值已经保存在val_RES_PSP_ADDR变量中。
  4. FREE_RESIDENT 过程中使用cliandsti是无用的,因为 DOS 会处理这些细节。您不需要括号来读取环境指针吗?mov ES, ES:[002Ch]请写mov ah, 49h2次以防第一次调用出错。
  5. IS_RES_RUNNING过程忘记推送/弹出 BX。
  6. 进程中,您不需要推动 DS/AX。无论如何,你不会弹出它。您可以将偏移标签放在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
于 2015-04-12T21:05:23.103 回答
1

除了@user3144770 所说的。

NEW_INT_PROC 过程不需要知道中断。这是由硬件中断 08h 的处理程序完成的。

如果 MASM 自动将您的ASTACK堆栈段放在代码下方(并且不包含在 .EXE 文件中),那么在调用 31h DOS 函数之前,您不应该在计算 DX 时包含此空间。此外,您的中断处理程序无论如何都不会使用此堆栈。

于 2015-04-16T10:31:47.017 回答