Date: Friday, 15 March 1985
From: Harald Striepe
Re:   Use of IBM PC-DOS \"EXEC\" function call

> Does anyone have any experience with the use of PCDOS functions
> (INT 21H) I have been trying to figure out how to use the "Exec"
> function 4Bh and have been having no success.
> 
> Would someone who has used this function call please let me know what 
> the secret is.  A copy of a simple program using the call would 
> help also.
> 
> Brian

The key is to release the memory not used by your calling program.
MS-DOS appears to allocate all memory to the current application until
it is properly notified. Below is an example program.  Note that this
worked on a Rainbow, but should also function on any other PC with
MS-DOS V2 or higher.

--------------------------- cut here ---------------------------------


PAGE    56,132
TITLE   Exec Call Test- Call COMMAND.COM SHELL to do Directory (.EXE file)
NAME    EXEC1

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;                                                                        ;
;  DOS EXEC-CALL EXAMPLE                                                 ;
;  Loads COMMAND.COM,  and executes a directory on default drive.        ;
;                                                                        ;
;  Based on a shell example by Brian Markey.                             ;
;  Note: This example does not do any error checking!!!                  ;
;                                                                        ;
;  Author: H. Striepe                                            8/84    ;
;                                                                        ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


; EQUATES

MSDOS           EQU  021h       ;MS-DOS interrupt
Print           EQU  009h       ;  func: print string terminated with $
ModMem          EQU  04ah       ;        modify allocated memory
Exec            EQU  04bh       ;        load and execute program
TermProc        EQU  04ch       ;        terminate process

Stacklen        EQU  128        ;Size of program stack

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

code    SEGMENT PARA 'codeseg'

        ASSUME  CS:code,SS:stack,DS:data,ES:nothing

Start:                                          ; Program entry point

        MOV     AX,SEG data                     ; load data seg pointer
        MOV     DS,AX                           ;  .

        MOV     AH,Print                        ; Print "Before shell"
	MOV	DX,OFFSET mess1			;  .
	INT	MSDOS				;  ..

; MS-DOS allocates all available memory to a program upon loading,
; we first have to deallocate all unused memory using function 4Ah.
; ES := point to PSB (default after load)
; BX := current program size in paragraphs
; Note: If on calling function 4Ah ES: is not equal to the PSB MS-DOS
;       allocated on loading, an ARENA TRASHED error will result.

; ES: still points to PSB,  calculate memory required for calling 
; routine:

        MOV     BX,OFFSET end+256               ; code space+PSP
        ADD     BX,stacklen                     ; + stackspace
        ADD     BX,OFFSET lastloc+15            ; + data space
        MOV     CX,4                            ;  in
        SHR     BX,CL                           ;  paragraphs


        XOR     AL,AL                           ; Deallocate unused memory
        MOV     AH,Modmem                       ;  .
        INT     MSDOS                           ;  ..

; In case of error, carry would be set.
;   Error codes in AX:  7=> arena trashed
;                       8=> not enough memory
;                       9=> invalid block

        MOV     SI,2CH                          ; Get environment address
        MOV     AX,ES:[SI]                      ;  from PSP+2CH
        MOV     WORD PTR parmblk,AX             ;  .

        MOV     DX,OFFSET filenam               ; Set up exec call
        PUSH    DS                              ;  .
        POP     ES                              ;  ..
        MOV     BX,OFFSET parmblk               ;  ...
        XOR     AL,AL                           ;  ....
        MOV     AH,Exec                         ;  .....

	PUSH	DS				; Save machine state
	PUSH	ES				;  .
        MOV     CS:savess,SS                    ;  ..
        MOV     CS:savesp,SP                    ;  ...

	INT	MSDOS				; Shell to DOS

; In case of error, carry would be set.
;   Error codes in AX:  1=> invalid function
;                       2=> file not found
;                       8=> not enough memory
;                      10=> bad environment
;                      11=> bad format

        MOV     SP,CS:savesp                    ; Restore machine state
	MOV	SS,CS:savess			;  .
        POP     ES                              ;  ..
        POP     DS                              ;  ...

        MOV     AH,Print                        ; Print "After shell"
	MOV	DX,OFFSET mess2			;  .
	INT	MSDOS				;  ..

        MOV     AH,TermProc                     ; Terminate process
        XOR     AL,AL                           ;  .  no error...
        INT     MSDOS                           ;  ..

savess	DW	?				; Holders for SS:SP
savesp  DW      ?                               ;  .

end:

code    ENDS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

stack   SEGMENT PARA STACK 'stackseg'

        DB      Stacklen DUP (?)                ; Stack
TOS     LABEL   BYTE                            ;  .

stack   ENDS

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

data    SEGMENT PARA 'dataseg'

mess1	DB	'Before shell',0DH,0AH,'$'	; Program messages
mess2	DB	'After shell',0DH,0AH,'$'	;  ..
filenam DB      '\command.com',0                ; Load filename
parmblk	DW	00				; Parameter block
        DD      comline                         ;  .
        DD      fcb_one                         ;  ..
        DD      fcb_two                         ;  ...

comline DB      07H,'/C dir ',0DH               ; Command line
 
; The following are two full fcb's

                db 0ffh         ;flag byte, extended fcb
                db 5 dup (0)    ;reserved
                db (0)          ;attribute
fcb_one         db 0            ;drive number
                db "        "   ;filename
		db "   "	;extension
		dw 0		;current block
		dw 0		;record size
		dd 0		;file size
		dw 0		;date of last write
		dw 0		;time of last write
		db 8 dup (0)	;reserved
                db 0            ;current record
		dd 0		;relative record

                db 0ffh         ;flag byte, extended fcb
                db 5 dup (0)    ;reserved
                db (0)          ;attribute
fcb_two         db 0            ;drive number
                db "        "   ;filename
		db "   "	;extension
		dw 0		;current block
		dw 0		;record size
		dd 0		;file size
		dw 0		;date of last write
		dw 0		;time of last write
		db 8 dup (0)	;reserved
                db 0            ;current record
		dd 0		;relative record

lastloc LABEL   BYTE                            ; End of program

data    ENDS

        END     start
