Vous ne avez pas besoin de libérer de la mémoire dans un programme .exe
. Seul un programme .com
se réserve toute la mémoire. Il est plutôt compliqué de déterminer le vrai dernier octet d'un programme .exe
et de trouver le segment du bloc alloué. BTW: Dans un programme .com
, vous devez ajuster le pointeur de la pile!
Comme @RossRidge mentions, des lieurs (par exemple TLink) écrire dans l'en-tête d'information pour allouer la mémoire maximale. C'est énervant.
Vous pouvez modifier cet élément d'en-tête à l'aide d'un outil tel que le exemod
de Microsoft contenu dans les suites MASM (versions < 6). Une suite est téléchargeable here. L'utilitaire exemod peut être trouvé dans DISK4. Utilisez-le comme:
exemod <exefile> /max 1
Une autre option consiste à redimensionner la mémoire allouée dans le programme. Faire d'abord un programme simple HELLO.EXE
à exécuter par un programme parent:
.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
Maintenant, le 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
La fin du programme est déterminé par le pointeur de la pile. Vous devez donc être sûr que le segment STACK est le dernier segment du programme. Générez un fichier .MAP
avec l'option de ligne de commande tlink /s
. Il devrait ressembler à:
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
Comme vous pouvez le voir STACK
est le dernier segment énumérés ici.
Maintenant, vous pouvez exécuter le parent et lire ce que l'enfant (Hello.exe) doit dire :-)
Vous avez oublié de mettre le 'es'. – Jester
@Jester mov, ax - in main – AJIOB
Vous n'avez pas besoin de libérer de la mémoire dans un programme '.exe'. Seul un programme '.com' réserve toute la mémoire. – rkhb