I'm trying to get the name of the currently running .COM file.
I know that int 21h
functions 4Eh (SearchForFirstMatch) and 4Fh (SearchForNextMatch) will put the name at offset 1Eh in the DiskTransferArea DTA, but is the name of the currently running .COM file also in the DTA? If not, how can I get it?
EDIT: Probably should have mentioned that I'm using TASM
The DOS environment is a series of ASCIIZ strings and ending with one more zero plus an obscure word of some kind. Hereafter you have the name of the currently running program as an ASCIIZ string.
To get the name of the currently running .COM file use next code:
.model tiny
.code
ORG 256
Begin:
mov ax, word ptr [002Ch] ; Segment of the DOS environment DOES NOT WORK IN TASM
mov ds, ax ; SEE [EDIT 2]
xor si, si
cld
jmp StartSearch
SkipEntry:
lodsb
cmp al, 0
jne SkipEntry
StartSearch:
lodsb
cmp al, 0
jne SkipEntry ; Go skip an environment string
; End of environment
lodsw ; ???
;Here `DS:SI` points at the name of the running program (path included).
; Copy
mov di, offset Buffer
Again:
movsb
cmp byte ptr [si], 0
jne Again
; Restoring DS
push es
pop ds
mov byte ptr [di], "$"
; Printing path
mov dx, offset Buffer
mov ah, 09h
int 21h
; Wait key and end
mov ah, 00h
int 16h
mov ax, 4C00h
int 21h
Buffer db 256 dup (0)
END Begin
I tested the program in DOSBox 0.74 and results are OK.
[edit 1]
From comments I see that the issue is not yet resolved even though, you too, run the code in DOSBox. I suggest you use the FASM assembler that you can download at https://flatassembler.net. It's the easiest assembler around and it's a one-step compiler, meaning there's no separate linking required.
This is the adapted source for our current program:
ORG 256 ; FASM automatically 'knows' that you want a .COM program
; No '.model' or so needed
Begin:
mov ds, [002Ch] ; Segment of the DOS environment
xor si, si
cld
jmp StartSearch
SkipEntry:
lodsb
cmp al, 0
jne SkipEntry
StartSearch:
lodsb
cmp al, 0
jne SkipEntry ; Go skip an environment string
; End of environment
lodsw ; ???
;Here `DS:SI` points at the name of the running program (path included).
; Copy
mov di, Buffer
Again:
movsb
cmp byte [si], 0
jne Again
; Restoring DS
push es
pop ds
mov byte [di], "$"
; Printing path
mov dx, Buffer
mov ah, 09h
int 21h
; Wait key and end
mov ah, 00h
int 16h
mov ax, 4C00h
int 21h
Buffer db 256 dup (0)
In FASM (just like in NASM), mov dx, Buffer
gives the (offset) address of the Buffer variable, whereas mov dx, [Buffer]
gives the value stored IN the Buffer variable. This is one of most important differences if you're coming from MASM or TASM.
The executable that FASM produces will have 306 bytes.
[edit 2]
mov ax, word ptr [002Ch] mov ds, ax
The instruction mov ax, word ptr [002Ch]
does not do what we needed.
In TASM, neither the presence of the square brackets, nor even the mention of word ptr
turn this into a read from memory. It gets encoded as an immediate load to AX
(B8,2C,00).
For our program it means that we will be looking at the many zeroes stored at offset 02C0h in the Interrupt Vector Table.
Working alternatives include (both require 5 bytes):
Using a register addresses memory
mov bx, 002Ch ; BB,2C,00
mov ds, [bx] ; 8E,1F
Using a (redundant) segment override addresses memory
mov ds, cs:[002Ch] ; 2E,8E,1E,2C,00
Read more about this peculiar TASM syntax in: Confusing brackets in MASM32