According to a few tutorials I am seeing, DOS used dollar-terminated strings to write to the terminal. This seems to also be documented here on INT 21H.

Entry: DS:DX -> '$'-terminated string
Return: AL = 24h
Notes: ^C/^Break are checked

You can see this from the code in this tutorial here. What was the reason for going with dollar-terminated strings rather than NUL-terminated strings like C?

  • 15
    That comes from CP/M.
    – mannaggia
    Commented Sep 19, 2018 at 17:44
  • 3
  • 2
    Please note that all other strings in DOS (like file names) are NUL-terminated. Commented Sep 20, 2018 at 5:54
  • 3
    That is not actually true, M. Rosenau. Command tails in the PSP are terminated by Carriage Return, for starters.
    – JdeBP
    Commented Sep 20, 2018 at 8:32
  • 2
    Why would he not tag MS-DOS?
    – idrougge
    Commented Sep 21, 2018 at 11:28

3 Answers 3


The short answer is that DOS was designed to be similar to CP/M, and drawing a quote from here:

While 8-bit programs could not run on 16-bit computers, Intel documented how the original software developer could mechanically translate an 8-bit program into a 16-bit program. Only the developer of the program with possession of the source code could make this translation. I designed DOS so the translated program would work the same as it had with CP/M – translation compatibility. The key to making this work was implementing the CP/M API.

Or course this brings up the question as to why CP/M used the dollar sign.

This discussion says CP/M got the idea from DEC, which used the RAD50 character encoding. With only 40 characters (50 octal), you only have uppercase, digits, space, period, dollar, and percent.

Both CP/M and RT-11 are evolved from earlier DEC OS's, most notably OS/8 (on the PDP-8) and DOS-11 (on the PDP-11). The most obvious feature of all of these OS's is the presence of "PIP"

So DEC probably chose dollar because it didn't have many options, CP/M got it from DEC, and DOS got it from CP/M.

  • 6
    I'm really impressed by the RAD50 information. I'll mark this answer as chosen if no one else has anything to do add. It looks like you went down a good rabbit hole from DOS to CP/M to find that. Commented Sep 19, 2018 at 17:57
  • 6
    That's a great discussion you linked, by the way. Tim Shoppa, who is reliable, suggested it might go back to mainframe data conventions from the 1970s. And here's an example -- en.wikipedia.org/wiki/… -- a mainframe language in which every statement line is terminated by a dollar sign. There's no way I know of to connect the dots to CP/M though. And it also seems like this ancient convention may also explain why a dollar sign at the end of a regular expression is an assertion of end-of-line.
    – MetaEd
    Commented Sep 19, 2018 at 23:26
  • 11
    It could also explain why in BASIC a dollar sign at the end of a variable name denotes a string type -- if it was already thought of as a string terminator.
    – MetaEd
    Commented Sep 19, 2018 at 23:38
  • 6
    You might also go back to TECO. Teco was a text editor originally from MIT, that made its way to DEC in the 1960s. Commands like insert and search were followed by a text string. This text string was terminated by an escape character. This escape character was echoed as a dollar sign. Commented Sep 20, 2018 at 0:42
  • 4
    Nevertheless, there was a DOS-11. It was a very early PDP-11 system. Here's the Wikipedia entry: en.wikipedia.org/wiki/DEC_BATCH-11/DOS-11
    – dave
    Commented Sep 21, 2018 at 22:39

So, what about the last part of the question, why not use nul as c? As shown in an earlier answer, MS-DOS was influenced by CP/M, CP/M was influenced by DOS/11 on PDP-11 and that was an extension of OS/8 from PDP-8.

OS/8 used a character set called DEC Radix-50. After checking the link about the RAD50 character set, the answer why OS/8 didn't use nul to terminate strings is quite simple. nul is Space in that character set. Considering that apart from letters and digits you only had 3 punctuation marks ".", "%" and "$" you had to choose one. The question remaining is why they choose $ and not %.

Besides that, as commented below, C did not exist when the PDP-8 was constructed, so it could not have influenced the choice of string terminator.

  • 3
    But you are also speaking as if C always existed but it didn’t really get popular outside of Bell Labs until the mid to late 70’s.
    – mannaggia
    Commented Sep 20, 2018 at 1:50
  • 1
    This answer fails to demonstrate a connection between paper tape and MS/PC-DOS version 1.
    – JdeBP
    Commented Sep 20, 2018 at 8:28
  • 2
    The PDP-8 predates the C language by a long way - C was first targeted at the PDP-11.
    – pjc50
    Commented Sep 20, 2018 at 9:36
  • 7
    Also note that null terminated strings are not C's invention ... C actually inherited that convention from the DEC assemblers that its early compilers targeted (the PDP 11 assembler, for instance, had a directive ASCIZ to produce null terminated strings), so it seems unlikely Kildall wouldn't have been exposed to the idea even though he stsrted working on the first versions of CP/M before C was well known.
    – Jules
    Commented Sep 20, 2018 at 16:18
  • 3
    Verson 1 of unix was for the PDP-7, which predated the PDP-8. The port to the PDP-11 was the motivation for C. Commented Sep 20, 2018 at 17:25

It's worth noting that CP/M was written originally in the PL/M-80 programming language (also developed by Gary Kildall) (source here )

The PL/M-80 Manual on page 11 states that

The character set used in PL/M is a subset of both ASCII and EBCDIC character sets. The valid PL/M characters consist of the alphanumerics


a b c d e f g h I j k l m n o p q r s t u v w x y z

0 1 2 3 4 5 6 7 8 9

along with the special characters

= . / ( ) + - ' * , < > : ;

and the blank characters

space tab carriage-return line-feed

If a PL/M program contains any character not in this set, the compiler may treat the character as an error

That's 80 characters.

Interestingly there is no mention there of $ at all - yet on page 15 it is listed as a character that "may be freely inserted between the characters of a constant to improve readability".

I can't say whether or why this might have affected the decision to use $ as the string terminator for function 15 in CP/M, especially since page 16 is explicit that "character strings are denoted by printable ascii characters enclosed by apostrophes" which doesn't limit it to the same character set as the code body.

I can say from personal experience that function 15 was almost never used, and CP/M / CP/M-86 / MP/M / Concurrent DOS / CDOS /… assembler programmers pretty well invariably used subroutines containing loops that called function 2, usually using either a byte count or a null terminator.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .