1

I'm trying to get answers for a week. :)

But, maybe i ask wrong question. So here is it: I need to load and then unload residential program (set some vector and then get back to standard), i do that but after installing standard vector i try to free memory allocated for residential program by using 49h: first i get standard vector back, then i clear environment and then i clear mem for residential program. Then i can try to close CMD by clicking in [X] button of the window and but error appears: enter image description here

Here is my code:

 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

Help please.

Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
GALIAF95
  • 619
  • 1
  • 10
  • 25
  • Yes. but it doesn't solve my problem. But thanks. – GALIAF95 Apr 08 '15 at 23:12
  • On top of what is covered in answers `mov AL, 20h` and `out 20h, AL` is done just before the `iret` meaning you clobber the AL register before returning. But as the one answer suggests these 2 lines should be removed because `int 1ch` is called from the IRQ0 handler (int 8h). When the _IRET_ in your handler is done it will return back to the IRQ0 code and do the End of Interrupt (EOI) handling on the PIC before it does its own _IRET_ – Michael Petch Mar 18 '17 at 02:40

2 Answers2

3

I will present some observations about your program. See if it helps!

  1. The NEW_INT_PROC proc still uses AL after AX was popped in order to restore it. Move the pop ax below the aknowledging of the interrupt.
  2. The DIRECT_PRINT proc pushes and pops SP, which is silly! Also don't trust BIOS to not destroy AL while doing functions 02h and 03h.
  3. In the LOAD_RESIDENT proc DS already points to the segment of NEW_INT_PROC and the value of ES was already saved in the val_RES_PSP_ADDR variable.
  4. In the FREE_RESIDENT proc using cliand sti is useless because DOS takes care of such details. Don't you need the brackets to read the environment pointer? mov ES, ES:[002Ch] Please write mov ah, 49h 2 times to guard against an error on the first call.
  5. The IS_RES_RUNNING proc forgets to push/pop BX.
  6. In the MAIN proc you don't need to push DS/AX. You don't pop it anyway. You can drop the offset tags in mov DX, offset mark_NEW_INT_PROC_MEM and add DX, offset mark_END_OF_STACK. These symbolic constants carry the right value by themselves.

This is how I would change 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
Sep Roland
  • 33,889
  • 7
  • 43
  • 76
1

In addition to what @user3144770 said.

The NEW_INT_PROC proc does not need to aknowledge the interrupt. This is done by the handler for the hardware interrupt 08h.

If MASM automatically places your ASTACK stack segment below the code (and not included in the .EXE file) then you should not include this space in your calculation of DX prior to calling the 31h DOS function. Furthermore your interrupt handler does not make use of this stack anyway.

Fifoernik
  • 9,779
  • 1
  • 21
  • 27