Foreword
The ACME Menu application was first written in 1986, then went dormant a couple of years later with the release and subsequent use of Microsoft Windows 3.1. In the DOS days, everything was done at the command line, with LOTS of repetitive typing. If you were not a typist (I'm not, really) it was tedious indeed.
Move forward to 2019. I retired from software engineering, though the timing was not of my own choosing. I wanted to improve the applications that I had written all those years ago, so I found a DOS look-alike that would run on Windows, and got to work.
My first challenge was to find references that were still available in book form. With the help of a couple of world-wide web sites, I was able to recover two of my favorites: The Peter Norton Programmer's Guide to the IBM PC & PS/2 by Peter Norton and Advanced MS-DOS by Ray Duncan.
Next on the list was finding a copy of the long since abandoned PL/M-86 compiler. Thanks to the Vetus Software site, another problem solved. Now came the real work. I remembered that there was no operating system API available, so I had to write my own. The earlier version was mostly implemented in x86 assembler, with some of the higher level functions in PL/M-86. The problem was that it meant LOTS of work any time the memory model was changed.
Not wanting to go down that path again, I took advantage of my experience to make the task of writing applications easier. The first step down the new path was to allow the application's entry point (from the programmer’s perspective) to be a function called "main" which accepted three parameters and returned an integer, just like those applications written in C, C++ and many other languages.
Since DOS applications have some specific requirements at the start, and since much of the necessary information was available only in the context of the starting instruction, the first lines were written in assembler, but passed to PL/M as soon as reasonable. In that first assembly language module, I made the first improvement to the developer's API, I initialized the static heap to zero. This allowed the programmer to make assumptions about the initial value of variables defined on the heap. Detection of initialization was now possible.
Also absent from those early versions of the (Intel) UDI-like environment was the ability to dynamically allocate memory. Since I wanted the ability to allocate memory dynamically in my applications, I chose that task next. That took all of 8 lines of assembly (with 17 lines of comments so that I would not forget WHY I did it).
Next came the real work of the startup code. For that, I moved to PL/M. It is here that I parsed the command line, and initialized an array of pointers to character strings for the command line parameters, commonly referred to as argv in the C language programming references. That is perhaps the single largest improvement in the API from the developer's perspective. No more calls to DQ$GET$ARGUMENT for each of the application's arguments. These arguments could be referenced in any order desired, and could be read many times, not just once.
Now that the initial code was in place, application development could begin. However, those first few simple applications took a LONG time to develop. While PL/M was a great language for embedded microprocessor applications, there was no library of useful utilities to manage I/O, strings, memory or anything else of that nature. This led to the next necessary feature of the environment: executing calls to DOS and the BIOS from PL/M-86, and not resorting to assembler every time.
The early C libraries for DOS had a function called int86() which allowed the programmer to set values in registers, and execute the appropriate interrupt. This is perhaps the greatest challenge yet: CPU registers must be initialized before the interrupt, and then captured and returned to the caller without context loss.
With that next critical piece in place, the creation of the I/O portion of the library was substantially easier. I could rely on the system call functionality provided by int86() to make the job easier. What followed (quite quickly actually) was the low level I/O in files and the user interface.
Of course, there is no reason to have file I/O if you are not going to use it, so I re-created one of my first serious applications for DOS: fprint. Indeed, there was a rudimentary version of that even before I discovered DOS and the IBM-PC. But this version was going to be faster, cleaner, and more likely to be used.
The next big challenge was to make the parsing of the command line easier and more consistent. I did not want to require that the parameters to be specified in a particular order. I also did not want to have command line parsing code repeated in every application.
My experience taught me that a common parser was more valuable than some might expect. As a model, I grabbed the simple API model from the Python library, and implemented it. That let me specify parameters in any order I wished. That was a huge improvement. I could now specify what arguments and modifiers were acceptable, and provided both a short version and a longer version to be specified. If the user wanted to know the acceptable command syntax, that could be provided using the same information provided to the command parser. Two wins with one API.
Lastly, there are two more things that I always wanted to do in my own API, printf() and its other related functions fprintf() and sprintf() which allow for the easy formatting of information, and strftime() which allows me to format the date/time string as I wish. The date/time report formatter was relatively easy since there is a fixed number of command arguments.
printf()/sprintf()/fprintf() would be a bigger challenge because the PL/M language syntax does not allow direct function calls with a variable number of parameters. I could make an indirect call (through a pointer) with no problem, but how could I find the first argument in the function list CONSISTENTLY? If called through a pointer, the function addressed by the pointer can NOT have any arguments, or the calling sequence is different. I found a method that works, but only when not called from a reentrant function.
(update: printf()/sprintf()/fprintf() may reliably now be reliably called from reentrant functions)
--
You received this message because you are subscribed to the Google Groups "intel-devsys" group.
To unsubscribe from this group and stop receiving emails from it, send an email to intel-devsys...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/intel-devsys/0e128c3e-1c55-48f4-8522-49fb432206ffn%40googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "intel-devsys" group.
To unsubscribe from this group and stop receiving emails from it, send an email to intel-devsys...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/intel-devsys/9a57b88d-1202-40bd-b5f4-f4fe91cfb31b%40retrotechnology.com.
Mike
Downloaded many thanks
Mark
To view this discussion visit https://groups.google.com/d/msgid/intel-devsys/CA%2BJgass6N3ML%3DangbJb3d-xDTj4D1aNwi0LTcqwPqz1L7E_p8g%40mail.gmail.com.
Mike
The code is now in my Intel repository on the web at https://mark-ogden.uk/files/intel/msdos/DOS%20IO%20Lib/
I have added a readme.txt to acknowledge that you wrote the code and also a pdf version of the DOSLibrary documentation with bookmarks to help navigation.
Mark
To view this discussion visit https://groups.google.com/d/msgid/intel-devsys/000901dbbde0%242223d820%24666b8860%24%40btinternet.com.
To view this discussion visit https://groups.google.com/d/msgid/intel-devsys/CA%2BJgass6N3ML%3DangbJb3d-xDTj4D1aNwi0LTcqwPqz1L7E_p8g%40mail.gmail.com.
To view this discussion visit https://groups.google.com/d/msgid/intel-devsys/001a01dbbde2%240f1e3ca0%242d5ab5e0%24%40btinternet.com.
Bill
From a purely personal perspective I would suggest we keep to Intel hardware, OS and unique tools e.g. PL/M86 along with source code written using these tools. If we extended to MSDOS/PCDOS or CP/M I fear the group would start to lose focus.
There are many other fora and repositories that cover MSDOS/PCDOS and CP/M. They also have many more active members who would appreciate your work.
I would also note that if you are considering early MSDOS/PCDOS then versions before MSDOS 3.x existed for several non standard implementations, as companies created personal computers without copying IBM.
To view this discussion visit https://groups.google.com/d/msgid/intel-devsys/2b60175f-38f3-473a-a193-f359b3e71791%40nj7p.info.
--
You received this message because you are subscribed to the Google Groups "intel-devsys" group.
To unsubscribe from this group and stop receiving emails from it, send an email to intel-devsys...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/intel-devsys/2e0c7984-e34a-4852-813c-0e4bfc80373a%40retrotechnology.com.
To view this discussion visit https://groups.google.com/d/msgid/intel-devsys/00d401dbbe6f%24ed4dae60%24c7e90b20%24%40btinternet.com.