4

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

AndrewHoover898
  • 159
  • 1
  • 9
  • 1
    Can't you get it by parsing [the PSP](https://en.wikipedia.org/wiki/Program_Segment_Prefix)? (which should be located at `DS:0000h` as long as you haven't modified `DS`). – Michael Jan 25 '21 at 18:24
  • DS is modified but then restored (so it should be ok). But I don't really get how parsing the PSP would help me find the filename. – AndrewHoover898 Jan 25 '21 at 18:29
  • 1
    The PSP has the command line which starts with the program name IIRC. – Jester Jan 25 '21 at 18:31
  • 1
    What offset though? I swear I looked through the entire .com structure and I cannot find the filename anywhere. Sorry if this should be obvious but I'm a beginner. I know that .com file has DS=CS=SS (.com always has only 64 kb). Here's what is at that offset for me https://i.imgur.com/i89DTkE.png – AndrewHoover898 Jan 25 '21 at 18:37
  • 4
    https://www.bttr-software.de/forum/board_entry.php?id=17394 It's in the environment block behind the last variable, the block which is located by reading the segment word in PSP:2Ch. – ecm Jan 25 '21 at 18:43
  • ...Uhm...what am I missing? https://i.imgur.com/0Hx9C8l.png – AndrewHoover898 Jan 25 '21 at 19:08
  • 1
    Look at 4493h:0, the word [PSP:2Ch] is a segment pointer. – ecm Jan 25 '21 at 19:24
  • Well...https://i.imgur.com/FowkwEw.png – AndrewHoover898 Jan 25 '21 at 20:24
  • 2
    That's `ds:4493` not `4493:0000` – Jester Jan 25 '21 at 20:39
  • Oh, ok ok, sorry. Still cannot find the name of my program -> https://i.imgur.com/MbGxgRa.png . – AndrewHoover898 Jan 25 '21 at 20:43
  • 2
    Now you just need to scroll past the environment variables. – Jester Jan 25 '21 at 20:45
  • Finally found it! Thanks for bearing with me. Now I only have to find a way to take it and store it somewhere. Since it gives you the full path, I cannot use a hardcoded offset since the directory the program might always have a variable length name. – AndrewHoover898 Jan 25 '21 at 20:50

1 Answers1

4

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

Sep Roland
  • 33,889
  • 7
  • 43
  • 76
  • I will try it, thank you for this code snippet! – AndrewHoover898 Jan 25 '21 at 20:52
  • I get these errors -> "[Constant] assumed to mean immediate constant" and "Illegal use of segment register". Also " cannot generate .COM file, data below initial CS:IP defined" – AndrewHoover898 Jan 25 '21 at 21:51
  • 1
    Depends on the assembler that you use. Maybe you have to use `mov ds, [0x002C]`. And maybe you need `.model tiny` directive and `.code` and `END`. Use whatever you were using before to generate a .COM file. – Sep Roland Jan 25 '21 at 21:55
  • 1
    If the assembler is really picky about `mov ds, [002Ch]`, add `word ptr` or you could split it up into `mov ax, word ptr [002Ch]` `mov ds, ax`. Just an idea. – Sep Roland Jan 25 '21 at 22:02
  • Ok, I managed to pass those errors by using word ptr and then MOV DS, AX. But I still don't really understand your code. Where am I supposed to get the name of the currently running program exactly? I'd need it stored somewhere in a buffer area. And isn't manipulating DS not recommended? I plan to integrate this into a bigger program and I feel like it would mess things up a little bit. Maybe I could push it to the stack and restore it later, but yeah...i still don't get how your code works, I'm sorry :( – AndrewHoover898 Jan 25 '21 at 22:52
  • I mean, after executing your code in a standalone .asm program, SI = 0003 and DS:SI doesn't really point to the name of the program. ---> EDIT: Okay, I will wait, thank you for the patience :) – AndrewHoover898 Jan 25 '21 at 23:00
  • 1
    `SI=3` would imply that the environment is empty. Fine, but if after you don't find any readable text with the filespec, your DOS implementation is faulty. Or really old, like versions 1 or 2. There's no danger in manipulating `DS` as long as we restore it afterwards. – Sep Roland Jan 25 '21 at 23:06
  • DOS version is 5.0, using DOSBOX. Also, I might reply a bit later than usual because it's getting really late where I'm from, but thank you for trying to help me. – AndrewHoover898 Jan 25 '21 at 23:12
  • 2
    Well, I literally just verified the environment in DOSBox 0.74 and all is fine. Every bit of info is present. – Sep Roland Jan 25 '21 at 23:14
  • That's exactly the code I'm using. https://pastebin.com/raw/0bt6FRKA - Had to use that "START_PR" label because I'd get an "Invalid initial entry point address" otherwise. – AndrewHoover898 Jan 25 '21 at 23:22
  • First of all, thank you for the code. I think something very strange is happening here, this is what's in the buffer for me at the end of the program -> only a $ sign -> https://i.imgur.com/8b7cjw3.png . Also, when called, nothing is displayed in the command line interface. – AndrewHoover898 Jan 26 '21 at 19:17
  • Alright, so I just recorded myself trying to debug the program using turbodebugger. Maybe that will help? https://streamable.com/u7oqlm – AndrewHoover898 Jan 26 '21 at 19:28
  • 1
    I realise you've never told what assembler you're using. But in my edit to the answer, I have suggested you use FASM. It's probably easier than what you're using today. And don't worry, FASM is just as powerful as most other assemblers. – Sep Roland Jan 27 '21 at 23:15
  • I'm using TASM. Would try FASM as you're suggesting, but without getting into details, I'm somehow forced to use this specific assembler. – AndrewHoover898 Jan 28 '21 at 13:07
  • 2
    @AndrewHoover898 I finally cracked the problem with the program in TASM. Read about the addressing troubles in TASM/MASM in my edited answer. – Sep Roland Jan 30 '21 at 12:17