2017-04-04 5 views
1

J'écris EXE programme avec SMALL modèle.
Je veux charger d'autres programmes avec l'aide de mon programme. Je lis que tout d'abord je dois libérer un peu de mémoire. J'utilise DOS 4Ah INT 21h interruption. Mais j'ai l'erreur 7 (la mémoire des unités de contrôle est détruite) dans AX quand l'utiliser. Ce que j'ai fait incorrect?ASM EXE programme 16 bits: Erreur lors de la modification de la taille de la mémoire

;-------------------MACRO----------------- 
println MACRO info 
    push ax 
    push dx 

    mov ah, 09h 
    mov dx, offset info 
    int 21h 

    ;print new line 
    mov dl, 10 
    mov ah, 02h 
    int 21h 

    mov dl, 13 
    mov ah, 02h 
    int 21h 

    pop dx 
    pop ax 
ENDM 
;-----------------end macro---------------- 

.model small 

.stack 100h 

.data 

initToRunErrorText db "Bad init to run other programs", '$' 

myDataEnd db '0' 

.code 

main: 
    mov ax, @data 
    mov es, ax 
    mov ds, ax 

    call initToRun 

    mov ah, 4Ch 
    int 21h 

; Result 
;  ax = 0 => all is good 
;  ax != 0 => we have an error 
initToRun PROC 
    push ax bx 

    mov ah, 4Ah 
    mov bx, offset myDataEnd + 100h 
    shr bx, 4 
    add bx, 2 
    int 21h 

    jnc initToRunAllGood 

    add ax, '0' 
    mov dl, al 
    mov ah, 06h 
    int 21h 

    mov ax, 1 
    println initToRunErrorText 

    jmp initToRunEnd 

initToRunAllGood: 
    mov ax, 0 

initToRunEnd: 
    pop bx ax 
    ret 
ENDP 

program_length equ $-main 

end main 

Pour utiliser la compilation Je TASM 16 bits avec DOSBox 0,74

+1

Vous avez oublié de mettre le 'es'. – Jester

+0

@Jester mov, ax - in main – AJIOB

+0

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

Répondre

2

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 :-)

+0

En fait, vous avez besoin de libérer de la mémoire dans un programme .EXE créé par TLINK car il définit le nombre maximum de paragraphes à allouer dans l'en-tête EXE à FFFFh, ce qui signifie que MS-DOS lui allouera le plus gros morceau de mémoire , juste comme un fichier .COM. Cela suppose bien entendu que vous ayez besoin d'allouer de la mémoire pour quelque chose d'autre, comme lancer un autre programme, sinon vous n'aurez pas besoin de libérer de la mémoire, que vous utilisiez un fichier .EXE ou .COM. –

+0

@RossRidge: Vous avez raison. Je ne trouve pas de lien pour télécharger un utilitaire comme 'exemod.exe'. En connaissez-vous un? Je pense quand j'ajoute un paragraphe et un lien je n'ai pas besoin de supprimer cette réponse (trop mauvais sur les jolis 15 points). – rkhb

+0

@RossRidge Ok, comment puis-je libérer de la mémoire pour lancer un nouveau programme? – AJIOB