ASM EXE program 16bit: Error changing size of memory

后端 未结 1 589
栀梦
栀梦 2021-01-16 10:03

I write EXE program with SMALL model.
I want to load other programs with the help of my program. I read that first of all I must free s

相关标签:
1条回答
  • 2021-01-16 10:38

    You don't need to free memory in an .exeprogram. Only a .com program reserves all memory. It's rather complicated to determine the real last byte of an .exe program and to find the segment of the allocated block. BTW: In a .com program you must adjust the stack pointer!

    As @RossRidge mentions, some linkers (e.g. TLINK) write into the header an information to allocate the maximum memory. This is annoying.

    You can modify this header item by using a tool like Microsoft's exemod which is contained in the MASM suites (versions < 6). A suite is downloadable here. The exemod utility can be found in DISK4. Use it like:

    exemod <exefile> /max 1
    

    Another option is to resize the allocated memory inside the program. Make first a simple program HELLO.EXE to be executed by a parent program:

    .MODEL small
    .STACK          ; default: 1000h
    .DATA
        hello db "Hello world", 13, 10, "$"
    .CODE
    main PROC
        mov ax, @data
        mov ds, ax
        mov dx, OFFSET hello
        mov ah, 09h
        int 21h
        mov ax, 4C00h
        int 21h
    main ENDP
    END main
    

    Now the parent:

    .MODEL small
    
    .STACK
    
    .DATA
        hello db "HELLO.EXE", 0
    
        params label word
            dw 0
            dw OFFSET command_line, SEG command_line
            dw 0ffffh,0ffffh ; fcb1
            dw 0ffffh,0ffffh ; fcb2
    
        command_line db 0,13
    
    .CODE
    
    free_memory PROC
        mov ax, sp              ; SS:SP -> nearly the end of program
        shr ax, 4
        mov bx, ss
        add bx, ax
        add bx, 2               ; BX = a paragraph beyond program
        mov ax, es              ; ES -> first paragraph of the program (containing PSP)
        sub bx, ax              ; BX = program size in paragraphs
        mov ah, 4ah             ; Resize memory block - http://www.ctyme.com/intr/rb-2936.htm
        int 21h                 ; Call MS-DOS
    
        ret
    free_memory ENDP
    
    execute_hello PROC
        push ds                 ; Save DS
        push es                 ; Save ES
    
        mov cs:[stk_seg],ss     ; Save stack pointer
        mov cs:[stk_ptr],sp
    
        mov ax, 4B00h
        mov dx, OFFSET hello
        mov bx, SEG params
        mov es, bx
        mov bx, OFFSET params
    
        mov ax,4b00h            ; Exec - load and/or execute program - http://www.ctyme.com/intr/rb-2939.htm
        int 21h                 ; Call MS-DOS
    
        cli                     ; Let no interrupt disturb
        mov ss,cs:[stk_seg]     ; Restore stack pointer
        mov sp,cs:[stk_ptr]
        sti                     ; Allow interrupts
    
        pop es                  ; Restore ES and DS
        pop ds
        ret
    
        ; Data for this function in the code segment
        stk_ptr dw 0
        stk_seg dw 0
    execute_hello ENDP
    
    main PROC
        mov ax, @data           ; Initialize DS
        mov ds, ax
    
        call free_memory        ; ES should point to PSP (default)
        call execute_hello
    
        mov ax, 4C00h           ; Terminate with return code - http://www.ctyme.com/intr/rb-2974.htm
        int 21h                 ; Call MS-DOS
    main ENDP
    
    END main
    

    The end of the program is determined by the stack pointer. You should therefore be sure that the STACK segment is the last segment in the program. Generate a .MAP file with the tlink command line option /s. It should look like:

     Start  Stop   Length Name               Class
    
     00000H 0005BH 0005CH _TEXT              CODE
     00060H 00079H 0001AH _DATA              DATA
     00080H 0047FH 00400H STACK              STACK
    
    
    Detailed map of segments
    
     0000:0000 005C C=CODE   S=_TEXT          G=(none)   M=INBBC8~1.ASM ACBP=48
     0006:0000 001A C=DATA   S=_DATA          G=DGROUP  M=INBBC8~1.ASM ACBP=48
     0006:0020 0400 C=STACK  S=STACK          G=DGROUP  M=INBBC8~1.ASM ACBP=74
    
    Program entry point at 0000:004C
    

    As you can see STACK is the last segment listed here.

    Now you can run the parent and read what the child (HELLO.EXE) has to tell :-)

    0 讨论(0)
提交回复
热议问题