[Edit: Ooops, that question already been answered a few years ago on Stack Overflow]
I'd expect there to be some reference (either a file handle or an old-fashioned FCB) in the PSP, but there's nothing I can find.
Almost. While there is no file handle or FCB to the program file, as it is already closed before execution starts, DOS (starting with 3.0) stores the program name as ASCIZ within the environment memory block, right after all environment variables.
To retrieve
- Test for min DOS version 3.0
- Get the environment segment from offset 002Ch of the PSP
- Advance after the last environment variable
- marked by two consecutive null bytes
- There's a word with the number of strings following
- If at least 1, the program name follows
- Fetch the program name (a full ASCIZ path name)
- Open that file
- Do whatever you want to do :))
This works for .COM and .EXE programs - but only with DOS 3.0 and above.
In Assembly this may look a bit like:
ORG 100h
MOV AH,3000h ; Get DOS version
INT 21h
JC LOWDOS ; Call failed -> DOS 1.x ?
CMP AL,3 ; At least DOS 3
JAE DOSOK ; Yes -> continue
LOWDOS: ; DOS version too low: terminate with exit code = 126
MOV AX,4C7Eh
INT 21h
DOSOK:
MOV AX,CS:[2Ch] ; Environment Segment
MOV ES,AX ; to DS
XOR DI,DI ; Point ES:DI at start of environment vars
MOV AX,DI ; Search for 0-bytes
CLD ; Upward
MOV CX,32767 ; Maximum size of an environment segment
SKIPVAR:
;Loop skipping all environment variables
REPNE SCASB ; Skip a string
JCXZ NFND ; Searched max.length without finding a zero
CMP AL,BYTE ES:[DI] ; next byte as well Zero ?
JNE SKIPVAR ; No -> Skip next var
INC DI ; Skip over zero byte
CMP WORD ES:[DI],AX; String count not zero ?
JE NFND ; No -> Not Found
INC DI ; Skip string count
INC DI
FOUND:
; Full Program Name at ES:DI
; Do whatever is to be done
; like opening it via 3Dh:
PUSH DS
MOV AX,ES
MOV DS,AX
MOV DX,DI ; Filename in DS:DX
MOV AL,<openmode> ; Read/Write/etc...
MOV CL,0
MOV AH,3Dh ; Open File
INT 21h
POP DS
JNC FILE_OPENED
; Open Error: terminate with exit code = openerror code
MOV AH,4Ch
INT 21h
NFND:
; Name Not Found: terminate with exit code = 127
MOV AX,4C7Fh
INT 21h
FILE_OPENED:
; Read or write from/to the program file
; File Handle in AX
...
END
Rather easy, isn't it?