Sender: jeffrey@carlyle.com (Jeffrey Carlyle)
Organization: JeffC.org
Approved: news-answers-request@MIT.edu
Newsgroups: comp.os.msdos.programmer,alt.msdos.programmer,comp.answers,alt.answers,news.answers
Followup-To: poster
Summary: Frequently asked questions from DOS programmers with tested answers.
Last-modified: 8 Feb 2002
comp.os.msdos.programmer FAQ Version 2002.02.08
This is the Frequently Asked Questions list for the newsgroup comp.os.msdos.programmer.
COPYRIGHT
Copyright 2002 by Jeffrey Carlyle. All rights reserved. This article is not in the public domain, but it may be redistributed so long as this notice, the acknowledgments, and the information on obtaining the latest copy of this list are retained and no fee is charged. The code fragments may be used freely; credit to the FAQ would be polite. This FAQ is not to be included in any static: archive (e.g. CD-ROM or book); however, a pointer to the FAQ may be included. See <Q:01.14> [Where can I get the latest copy of this FAQ list?] for a link to the latest version of the FAQ.)
Date: 5 Feb 2002 22:03:03 -0500
The General FAQ and Newsgroup Information section contains information about how to use the FAQ and the newsgroup.
Date: 7 Feb 2002 14:31:56 -0500
No. Though Microsoft may not be actively developing MS-DOS there are still many computers that are not capable of running Microsoft Windows. The current versions of Microsoft Windows will also run most MS-DOS programs; therefore, MS-DOS is not dead, and will most- likely never die just as Commodore-64s and Amigas have not completely died.
Indeed, DOS has found a new life in embedded systems. Other parties continue to develop MS-DOS compatible operating systems for more information see <Q:02.10> [What are my alternatives for MS-DOS compatible OSes?]
Windows NT, 2000, and XP all have a "Command Prompt" which is similar to the orignal MS-DOS command prompt. The new Windows command prompt has some differences from the original MS-DOS command prompty; see <Q:01.12> [What other technical newsgroups should I know about?] for pointers on where to learn about these diffences.
Date: 5 Feb 2002 22:03:03 -0500
This is the FAQ (Frequently Asked Questions) list for the newsgroup comp.os.msdos.programmer.
FAQ lists are intended to reduce the noise level in their newsgroups that results from the repetition of the same questions, correct answers, wrong answers, corrections to the wrong answers, corrections to the corrections, debate, etc.
This list should serve as a repository of the canonical "best" answers to the questions in it. The names of folks who have helped to improve this FAQ list are listed in <Q:01.03> [Who has contributed to this article?]
Date: 7 Feb 2002 14:57:05 -0500
This list is maintained and edited by Jeffrey Carlyle. To contact him send email to <mailto:jeffrey@carlyle.com> or visit his website at <http://www.jeffc.org/> for more information.
Stan Brown, as the former list maintainer, has been the major contributor: Stan wrote most of this list.
Many articles posted in comp.os.msdos.programmer sparked ideas or provided information for the first version of this list. Though they are not responsible for any errors, thanks are due to the following persons for posted articles or private email that led to improvements in this FAQ list:
Jamshid Afshar, Mark Aitchison, Sanjay Aiyagari, George Almasi, Aaron Auseth, Robert Baker, Preston Bannister, Scott Barman, Denis Beauregard, Per Bergland, Mike Black, Chris Blum, Ron Bodkin, Mark Brader, Jon Brinkmann, Andrew James Bromage, Glynn Brooks, Paul Brooks, Ralf Brown, Stan Brown, Shaun Burnett, D'Arcy J.M. Cain, Jeffrey Carlyle, Raymond Chen, Kelly Cooper, Dale Curtis, Denny de Jonge, Eric DeVolder, Alan Drew, Paul Ducklin, Gary Dueck, Dave Dunfield, Roland Eriksson, Mark Evans, Markus Fischer, George Forsman, Roger Fulton, Vincent Giovannone, Robert Grunloh, B.Haible, Janos Haide, Klaus Hartnegg, Kris Heidenstrom, Tom Haapanen, Joel Hoffman, Ari Hovila, Chin Huang, Daniel P Hudson, Joe Huffman, Michael Holin, Mike Iarrobino, Byrial Jensen, Rune Jorgensen, Ajay Kamdar, Everett Kaser, Tim Kannel, JJ Keijser, Jeff Kellam, Igor Kerp, Jen Kilmer, Reinhard Kirchner, Dave Kirsch, Chad Knudsen, Samuel Ko, Jan Kotas, Janne Kukonlehto, Robert Luursema, Benjamin Lee, Stephen Lee, Jim Lynch, Greg Malknecht, Sidney Markowitz, Jim Marks, Dimitri Matzarakis, Fred McCall, Ken McKee, Doug Merrett, Tom Milner, Bill Moore, Duncan Murdoch, Steve Murphy, Daniel Neri, Mert Nickerson, David Nugent, John Oldenburg, David Pape, Keith Petersen, Kevin D. Quitt, Karl Riedling, Arthur Rubin, Gerald Ruderman, Timo Salmi, Tapio Sand, Charles Sandmann, John Schmid, Russell Schulz, Paul Schylter, Huseyin Sevay, Adam Seychell, Ajay Shah, Bob Smith, John Stockton, Bob Stout, Sean Sullivan, Steve Summit, Tom Swingle, Anders Thulin, Curt Tilmes, Rick Watkins, Ya-Gui Wei, Morten Welinder, Joe Wells, Scott Winder, Gregory Youngblood, Eli Zaretski, ceison@lis.net.au, khill@vax1.umkc.edu
Date: 5 Feb 2002 22:03:03 -0500
To locate a certain word or phrase use your newsreader's, browser's, or editor's search function.
Date: 5 Feb 2002 22:03:03 -0500
There has been an attempt to check all facts, but THERE IS NO WARRANTY ON THE CODE OR ON THE TECHNIQUES DESCRIBED HEREIN. Please send corrections to <mailto:jeffrey@carlyle.org>. All the code has been tested; but the testing may not have been perfect, and machines and configurations vary. (Except where otherwise noted, C code was tested with MSC 5, BC++ 2.0, BC++ 4.x, MSVC 5, or MSVC 6.)
The mention of particular books or programs must not be construed to reflect unfavorably on any that are not mentioned.
If you encounter any errors in the FAQ please contact me via email.
Date: 5 Feb 2002 22:03:03 -0500
Comp.os.msdos.programmer (comp.sys.ibm.pc.programmer until September 1990) concerns programming for MS-DOS systems. The article "USENET Readership report for Jul 94" in news.lists shows 120,000 readers of this newsgroup worldwide. Traffic (exclusive of crossposts) was 1981 articles aggregating 3.1 Megabytes. It ranked as the 79th most popular newsgroup.
More programming topics in the newsgroup focus on C than on any one other language, but we are not just for C programmers (see <Q:01.07> [Is comp.os.msdos.programmer just for C programmers?]).
Since most MS-DOS systems run on hardware that is roughly compatible with the IBM PC, on Intel 8088, 80188, or 80x86 chips, we tend to get a lot of questions and answers about programming other parts of the hardware.
Date: 7 Feb 2002 14:40:59 -0500
No, it is for all programmers who want to share information about programming in MS-DOS and DOS replacements like 4DOS. Programs and questions are also posted in Pascal, assembly, and other languages (including MS-DOS batch programming).
Why does the newsgroup seem to be so C-oriented sometimes? There are two reasons. First, comp.lang.c and comp.lang.pascal have evolved in different directions. Comp.lang.pascal has split into discussions about individual Pascal compilers. comp.lang.pascal.borland welcomes discussion specific to Turbo Pascal, and the other new groups likewise. Turbo Pascal programmers tend to find DOS questions welcomed in comp.lang.pascal.borland, so that comp.os.msdos.programmer gets less of the "DOS in Turbo Pascal" traffic. On the other hand, comp.lang.c has stayed closer to talking only about the C language, and vendor-specific or operating-system-specific questions are not welcome. This tends to push questions about disks, DOS file structure, video, the keyboard, TSRs, etc. to comp.os.msdos.programmer even when those programs are written in C.
This FAQ is definitely C-oriented, not because that's necessarily best but because I tried to stick to what I could verify personally. As a C programmer (with some assembler), I could most carefully verify solutions in C or assembler. I felt that short, clear programs could be published in just one language and programmers could translate them into their languages of choice. But the FAQ list also contains several long programs written only in C; this is a defect with no obvious remedy. Most answers that point to source code at archive sites include both C- and Pascal- language source when available.
Date: 5 Feb 2002 22:03:03 -0500
The newsgroup comp.sys.ibm.pc.programmer is the old name of the modern newsgroup comp.os.msdos.programmer, and the old name has been obsolete since September 1990; however, some systems may not have removed the old group, or may have removed it but aliased it to the new name.This means that some people still think they're posting to comp.sys.ibm.pc.programmer even though they're actually posting to comp.os.msdos.programmer.
You can easily verify the non-existence of comp.sys.ibm.pc.programmer by reference to the "List of Active Newsgroups" posted to news.groups. It's available at:
<ftp://rtfm.mit.edu/pub/usenet-by-group/news.answers/active-newsgroups>
(For RTFM usage instructions see <Q:01.13> [Where are FAQ lists archived?])
Date: 5 Feb 2002 22:03:03 -0500
Sorry, the newsgroup is not available as a mailing list.
Date: 5 Feb 2002 22:03:03 -0500
Netiquette is good Usenet etiquette. It includes basic rules like the ones below. (See also <Q:01.11> [How can I learn more about Usenet?])
Date: 5 Feb 2002 22:03:03 -0500
There are two important newsgroups for learning about how Usenet and newsreader software works:
The following postings in news.announce.newusers might be considered the "mandatory course" for new users:
The articles mentioned above are downloadable via ftp from rtfm.mit.edu in the following files:
Welcome to news.newusers.questions (Weekly posting): <ftp://rtfm.mit.edu/pub/usenet-by-group/news.answers/news-newusers-intro>
Introduction to news.announce.newusers: <ftp://rtfm.mit.edu/pub/usenet-by-group/news.answers/news-announce/introduction/part1>
What is Usenet: <ftp://rtfm.mit.edu/pub/usenet-by-group/news.answers/usenet/what-is/part1> <ftp://rtfm.mit.edu/pub/usenet-by-group/news.answers/usenet/what-is/part2>
Answers to Frequently Asked Questions: <ftp://rtfm.mit.edu/pub/usenet-by-group/news.answers/usenet/faq/part1>
Rules for posting to Usenet: <ftp://rtfm.mit.edu/pub/usenet-by-group/news.answers/usenet/posting-rules/part1>
A Primer on How to Work with the Usenet Community: <ftp://rtfm.mit.edu/pub/usenet-by-group/news.answers/usenet/primer/part1>
Hints on writing style for Usenet: <ftp://rtfm.mit.edu/pub/usenet-by-group/news.answers/usenet/writing-style/part1>
Emily Postnews Answers Your Questions on Netiquette: <ftp://rtfm.mit.edu/pub/usenet-by-group/news.answers/usenet/emily-postnews/part1>
For rtfm.mit.edu instructions, see <Q:01.13> [Where are FAQ lists archived?]
Date: 7 Feb 2002 14:35:45 -0500
It is impractical to attempt to list all relevant newsgroups here. The few that are listed are some of the older newsgroups. To find additional groups use your newsreader's newsgroup search facility.
Caution: Some of these newsgroups have specialized charters; you'll probably get flamed (and deserve it) if you post to an inappropriate group. Most groups have FAQ lists that will tell you what's appropriate. Don't post a request for the FAQ list; instead, retrieve it yourself: see <Q:01.13> [Where are FAQ lists archived?]
Date: 5 Feb 2002 22:03:03 -0500
Very possibly the FAQ list you want is already at your site. Check the newsgroup news.answers; if your site doesn't carry news.answers, check comp.answers, rec.answers, etc., according to the top-level name in the FAQ list's "home" newsgroup. Articles are posted to the *.answers groups in a way that should make them last until the next versions are posted. If they expire sooner at your site, you might want to lobby your sysadmin to treat the moderated *.answers groups as a special case and grant them longer expiration times than other groups.
To ftp most FAQ lists, connect to <ftp://rtfm.mit.edu/pub/usenet-by-group/news.answers>. The name of the file that you want is the Archive-name from the top of the article. For instance, if the Archive-name were software-eng/part1 you would retrieve <ftp://rtfm.mit.edu/pub/usenet-by-group/news.answers/software-eng/part1>.
By email (only if you have no ftp access, please), the server is <mailto:mail-server@rtfm.mit.edu>. It accepts "send" commands that omit the leading "/pub/" from file names; for example:
send usenet-by-group/news.answers/software-eng/part1
For full instructions about the mail server, send it a message consisting of these two lines:
help
index
Not just FAQ lists, but every article listed in the "List of Periodic Informational Postings" (LoPIP) can be obtained by ftp or email from rtfm.mit.edu. If you have an old copy of an informational article, look for an "Archive-name" at the beginning. The article is stored under that name at <ftp://rtfm.mit.edu/pub/usenet-by-group/news.answers>. If the article has no Archive-name, check the first name on the Newsgroups line and change to that directory under <ftp://rtfm.mit.edu/pub/usenet-by-group>.
Stan Brown also maintains a FAQ on finding FAQs. It can be found at <http://www.mindspring.com/~brahms/faqget.htm>.
Date: 7 Feb 2002 01:05:15 -0500
The latest version of the FAQ posted to the newsgroup can always be found on the RTFM server: <ftp://rtfm.mit.edu/pub/usenet-by-group/news.answers/msdos-programmer-faq>
If you have no ftp access, see <Q:01.13> [Where are FAQ lists archived?] for instructions on retrieving it by email.
The most recent version of the FAQ can be obtained from: <http://www.stratoware.com/msdos/>
The Stratoware.Com site is the FAQ editor's official site and contains an HTML version of the FAQ. Various other HTML versions can be found, but they are not guaranteed to be up-to-date. You can find these HTML versions by searching for "comp.os.msdos.programmer FAQ" at any popular search engine.
Date: 5 Feb 2002 22:03:03 -0500
The General Reference section contains information about finding popular online MS-DOS reference materials.
Date: 8 Feb 2002 19:36:40 -0500
Good reports of HELPPC21 have been posted. It is downloadable as: <ftp://garbo.uwasa.fi/pc/programming/helppc21.zip>
This hypertext system contains much information on ports and other hardware, as well as some overlap with Ralf Brown's interrupt list <Q:02.03> [What and where is Ralf Brown's interrupt list?]. It is shareware ($25).
Additional information (and more recent) information can be found in Ralf Brown's interrupt list; see <Q:02.03> [What and where is Ralf Brown's interrupt list?] for information on locating the list.
Date: 5 Feb 2002 22:03:03 -0500
The definitive work is Ralf Brown's interrupt list. For more information see <Q:02.03> [What and where is Ralf Brown's interrupt list?].
Date: 8 Feb 2002 19:37:16 -0500
Ralf Brown's Interrupt List contains megabytes of information on documented and (officially) undocumented BIOS and DOS interrupts, DOS tables, and interrupts hooked by many software packages.
The distribution files contain not only the actual list, but also a collection of utilities and conversion programs for the list.
Ralf Brown's Interrupt List can be downloaded from his page at: <http://www.cs.cmu.edu/~ralf/files.html>
HTML versions of Ralf Brown's Interrupt List can be found at:
Updates are announced in comp.archives.msdos.announce and on Ralf Brown's web page at: <http://www.cs.cmu.edu/~ralf/>
Ralf's web page contains the somewhat unassuming line: "[h]e is well-known in cyberspace for maintaining the Interrupt List..." Ralf has done astounding work as the maintainer of the list; his work has been greatly appreciated by thousands of programmers.
Date: 5 Feb 2002 22:03:03 -0500
The FAQ list of the comp.compilers newsgroup answers this for BASIC, C, Pascal, and other languages. See <Q:01.13> [Where are FAQ lists archived?]
Date: 5 Feb 2002 22:03:03 -0500
Sorry, this FAQ list cannot settle religious arguments.
Much of the heat over this topic arises because each person believes that the book that he or she learned from is the best book, but different people have very different experiences of the same book. The only person who can tell you which is the best book for learning a given topic is you.
Your best bet is to go to a fairly well stocked bookstore when you have a couple of hours to spare. Start at one end of the shelf and work your way methodically through every book that looks like it might cover what you want to learn. Look at the tables of contents; read a page or two from each book. Then make your decision. If money is a problem or if you're not sure of your choice, check out your top two or three from your library.
Date: 7 Feb 2002 14:44:40 -0500
First you need to try to determine whether the problem is in your use of the programming language or in your use of MS-DOS and your PC hardware. (Your manual should tell you which features are standard and which are vendor- or MS DOS- or PC-specific. You have read your manual carefully, haven't you?)
If the feature that seems to be working wrong is something related to your PC hardware or to the internals of MS-DOS, this group is the right place to ask. (Please check this FAQ list first, to make sure your question isn't already answered here.)
On the other hand, if your problem is with the programming language, the comp.lang hierarchy (including comp.lang.pascal.* and comp.lang.c) is probably a better resource. Please read the other group's FAQ list thoroughly before posting. (These exist in comp.lang.c, comp.lang.c++, comp.lang.modula3, comp.lang.lisp, comp.lang.perl; they may exist in other groups as well. comp.lang.pascal.borland has a Mini-FAQ.) It's almost never a good idea to crosspost between comp.os.msdos.programmer and a language group.
Before posting in either place, try to make your program as small as possible while still exhibiting the bad behavior. Sometimes this alone is enough to show you where the trouble is. Also edit your description of the problem to be as short as possible. This makes it look more like you tried to solve the problem on your own, and makes people more inclined to try to help you. See also <Q:01.10> [What's this netiquette?]
Date: 5 Feb 2002 22:03:03 -0500
Bob Stout maintains a very large archive called SNIPPETS. For more information see <Q:02.08> [What and where is SNIPPETS?].
Date: 6 Feb 2002 00:00:45 -0500
Excerpt from the SNIPPETS FAQ follows:
The SNIPPETS archive, maintained by Bob Stout, contains public
domain/freeware portable C/C++ source code & instructional text.
There are more than 500 files, including:
Approx. 56,000 lines of code + approx. 10,000 lines of
tutorials.
Approx. 30% PC-specific, 70% portable
Approx. 6% C++-specific, 94% C/C++
The PC-specific functions are system-level utility code - no
multimedia or GUI code. Tested on all popular PC compilers plus
Unix compilers where possible. An eclectic collection with
everything from macros to complete cut-and-paste C/C++ code
solutions & utilities, along with FAQ and instructional files.
Official SNIPPETS sites: <ftp://ftp.snippets.org/> <http://www.snippets.org/>
Date: 5 Feb 2002 22:03:03 -0500
No, the source code to MS-DOS is not currently available; however, the source code to an MS-DOS alternative known as FreeDOS is freely available; see <Q:02.11> [What and where is FreeDOS?] for more information.
Date: 5 Feb 2002 22:03:03 -0500
The FreeDOS Project (see <Q:02.11> [What and where is FreeDOS?]) has created an open source MS-DOS compatible operating system known as FreeDOS. Additionly, IBM has released an updated version of their PC-DOS known as PC-DOS 2000.
Lineo currently owns the rights to DR-DOS, but they appear to no longer be developing or supporting it; however, one can still find DR-DOS and even CP/M on their FTP site: <ftp://ftp.lineo.com/pub/drdos/>
Date: 7 Feb 2002 00:49:45 -0500
The FreeDOS Project creates and maintains FreeDOS an open source operating system covered by the GNU General Public License. FreeDOS is a functional operating system; however, they have not yet reached their stated of goal of being able to run Windows and DOOM. The FreeDOS Project has not accessed any Microsoft source code and is creating FreeDOS from scratch.
More information and the FreeDOS distribution itself can be found at: <http://www.freedos.org>
Date: 7 Feb 2002 12:59:56 -0500
If the question is not answered elsewhere in this FAQ, it may be answered in Timo Salmi's "Frequently Asked Questions about MS-DOS batches." This list can be found at <ftp://garbo.uwasa.fi/pc/link/tsbat.zip>.
Date: 5 Feb 2002 22:03:03 -0500
The Compile and Link section contains information issues involving compiling and linking of MS-DOS code.
Date: 8 Feb 2002 19:38:12 -0500
This question explains the problem; the next question gives some remedies.
DGROUP is a link-time group of data segments, and the compiler typically generates code that expects DS to be pointing to DGROUP. (Exception: Borland's huge model has no DGROUP.)
Here's what goes into DGROUP:
In all of the above, which is to say all six models in Microsoft C and all but huge in Borland C, DGROUP is limited to 64K including string literal data (which are treated as static data). This limitation is due to the Intel CPU's segmented architecture.
For more information, see topics like "memory models" and "memory management" in the index of your compiler manual. Also for an extended general discussion of memory usage in Borland C programs, of which much applies to any C compiler in DOS see TI738.asc, downloadable as part of:
<ftp://garbo.uwasa.fi/pc/c-lang/bchelp10.zip>
Date: 5 Feb 2002 22:03:03 -0500
These messages are a variation of "DGROUP > 64K". For causes, please see the preceding question.
If you get this error in tiny model, your program is simply too big and you must use a different memory model. If you get this link error in models small, compact, medium, large, or Microsoft's huge, there are some things you can do. (This error can't occur in Borland's huge model.)
If you have one or two big global arrays, simply declare them far. The compiler takes this to mean that any references to them will use 32-bit pointers, so they'll be in separate segments and no longer part of DGROUP.
Or you can use the /Gt[number] option with Microsoft or - Ff[=size] with Borland C++ 2.0 and up. This will automatically put variables above a certain size into their own segments outside of DGROUP.
Yet another option is to change global arrays to far pointers. Then at the beginning of your program, allocate them from the far heap (_fmalloc() in Microsoft, farmalloc() in Borland).
Finally, you can change to huge model (with Borland compilers, not Microsoft). Borland's H model still uses far pointers by default, but "sets aside the [64K] limit" and has no DGROUP group, according to the BC++ 2.0 Programmer's Guide. Microsoft's H model does use huge data pointers by default but retains DGROUP and its 64K limit, so switching to the huge model doesn't buy you anything if you have DGROUP problems.
Date: 5 Feb 2002 22:03:03 -0500
Typically someone who owns compiler A and is trying to write code to link with a third-party library that was compiled under compiler B asks this question.
The answer to the question is, Not in general. Here are some of the reasons:
Those problems will generate link-time errors. Others may not show up until run time:
That said, there are some circumstances where you can link hybrids. Your best chance of success comes if you compile in large model with the compiler switch that says to reload DS on entry to each function, avoid longs and floating point, use only 16-bit pointers, suppress stack checking, and specify all libraries used in the link.
Date: 5 Feb 2002 22:03:03 -0500
These messages look similar but have very different causes.
"Floating point not loaded" is Microsoft C's run-time message when the code requires a numeric coprocessor but your computer doesn't have one installed. If the program is yours, relink it using the xLIBCE or xLIBCA library (where x is the memory model).
"Floating point formats not linked" is a Borland run-time error (Borland C or C++, Turbo C or C++). Borland's compilers try to be smart and not link in the floating- point (f-p) library unless you need it. Alas, they all get the decision wrong. One common case is where you don't call any f-p functions, but you have %f or other f-p formats in scanf() or printf() calls. The cure is to call an f-p function, or at least force one to be present in the link.
To do that, define this function somewhere in a source file but don't call it:
static void forcefloat(float *p)
{
float f = *p;
forcefloat(&f);
}
It doesn't have to be in the module with the main program, as long as it's in a module that will be included in the link.
If you have Borland C++ 3.0, the README file documents a slightly less ugly work-around. Insert these statements in your program:
extern unsigned _floatconvert; #pragma extref _floatconvert
Date: 5 Feb 2002 22:03:03 -0500
In Turbo C, Turbo C++, and Borland C++, you may not find "stack size" in the index but the global variable _stklen should be there. The manual will instruct you to put a statement like
extern unsigned _stklen = 54321U;
in your code, outside of any function. You must assign the value right in the extern statement; it won't work to assign a value at run time. The linker may give you a duplicate symbol warning, which you can ignore.
If you are using the Borland PowerPack for DOS _stklen does not change the stack size. To change the stack size you must use STACKSIZE in your .DEF file. HEAPSIZE can be used to change the size of your program's heap.
Date: 5 Feb 2002 22:03:03 -0500
Information about the base .OBJ format can be found in Intel's document number #121748-001, {8086 Relocatable Object Module Formats} (not verified).
Both Microsoft and Borland have extended the .OBJ format, as has IBM for OS/2; and according to the MS-DOS encyclopedia, Microsoft doesn't actually use all the listed formats.
Microsoft-specific .OBJ formats:
Borland-specific .OBJ formats:
A "tutorial on the .OBJ format" comes with the VAL experimental linker, downloadable as <ftp://garbo.uwasa.fi/pc/assembler/linker.zoo>.
Date: 5 Feb 2002 22:03:03 -0500
See PC Magazine 30 June 1992 (XI: 12) pages 349-350 for the old and new formats. For a more detailed layout, look under INT 21 AH=4B in Ralf Brown's interrupt list <Q:02.03> [What and where is Ralf Brown's interrupt list?] That list includes extensions for Borland's TLINK and Borland debugger info.
Among the books that detail formats of executable files are {DOS Programmer's Reference: 2d Edition} by Terry Dettman and Jim Kyle, ISBN 0-88022-458-4; and {Microsoft MS-DOS Programmer's Reference}, ISBN 1-55615-329-5.
Date: 7 Feb 2002 14:47:51 -0500
To oversimplify: a .COM file is a direct image of how the program will look in main memory, and a .EXE file will undergo some further relocation when it is run (and so it begins with a relocation header). A .COM file is limited to 64K for all segments combined, but a .EXE file can have as many segments as your linker will handle and be as large as RAM can take.
The actual file extension doesn't matter. DOS knows that a file being loaded is in .EXE format if its first two bytes are MZ or ZM; otherwise it is assumed to be in .COM format. For instance, DR-DOS 6.0's COMMAND.COM is in .EXE format as is COMMAND.COM in recent versions of MS-DOS.
Reader Paul Schylter posted this description of .COM files vs. .EXE files to the newsgroup in message <a3rpp8$a9h$1@merope.saaf.se>:
"Actually they must be less than 0xFF00 bytes long, since the PSP, which isn't included in the COM file but is within those 64K, is 256 bytes long.
"Then CAN use many segments, but they don't have to. In particular, any .COM file can be converted to an .EXE file by adding an appropriate header to it.
"There are some other differences between a .COM file and a single segment .EXE file (both of which must be smaller than 64K):
"The entry point of the .COM file is _always_ 0x100, while the entry point of the .EXE file can be at any address.
"The stack size of the .COM file is the remainder of those 64K which isn't used by the code image, while the stack size if the single segment .EXE file can be set at any size as long as it fits within those 64K. Thus the stack can be smallere in the .EXE file.
"When a COM file is loaded, the entire TPA (= "free memory") of MS-DOS is allocated for that COM file -- including those parts of the TPA which are outside the 64k of the COM file. If you don't want this (e.g. because your COM file is a TSR and you want to load other programs later), you must explicitly free those parts of the TPA you want freed. In the header of an .EXE file you can specify how large part of the TPA that .EXE file should receive."
Date: 5 Feb 2002 22:03:03 -0500
There are two steps to creating a .COM file. First, your program must not have a stack. In C, you must compile your program with the TINY memory model. Second, use EXE2BIN or a similar program to convert an EXE file to a COM file. To find EXE2BIN see subject: <Q:03.10> [Where is EXE2BIN located?]
Date: 5 Feb 2002 22:03:03 -0500
EXE2BIN was formerly shipped with MS-DOS. If you are still using DOS 5.0 or earlier you can find EXE2BIN in your DOS directory. Users of DOS 6.x need to get the MS-DOS Supplemental Disks. These disks are available via FTP at ftp.microsoft.com.
<ftp://ftp.microsoft.com/peropsys/msdos/public/supplmnt>
Date: 5 Feb 2002 22:03:03 -0500
The DPMIINST program included with older versions of Borland C++ and Turbo C++ compilers generates this message. Before running DPMIINST you must clean boot your computer.
Date: 5 Feb 2002 22:03:03 -0500
The keyboards sections coontains information about how to access the keyboard.
Date: 5 Feb 2002 22:03:03 -0500
The C compilers from Microsoft and Borland offer getch() (or getche() to echo the character); Turbo Pascal has ReadKey.
In other programming languages, execute INT 21 AH=8; AL is returned with the character from standard input (possibly redirected). If you don't want to allow redirection, or you want to capture Ctrl-C and other special keys, use INT 16 AH=10; this will return the scan code in AH and ASCII code (if possible) in AL, but AL=E0 with AH nonzero indicates that one of the gray "extended" keys was pressed. (If your BIOS doesn't support the extended keyboard, use INT 16 AH=0 not 10.)
Date: 5 Feb 2002 22:03:03 -0500
In Turbo Pascal, use KeyPressed. Both Microsoft C and Turbo C offer the kbhit() function. All of these tell you whether a key has been pressed. If no key has been pressed, they return that information to your program. If a keystroke is waiting, they tell your program that but leave the key in the input buffer.
You can use the BIOS call, INT 16 AH=01 or 11, to check whether an actual keystroke is waiting; or the DOS call, INT 21 AH=0B, to check for a keystroke from stdin (subject to redirection). See Ralf Brown's interrupt list <Q:02.03> [What and where is Ralf Brown's interrupt list?].
Date: 5 Feb 2002 22:03:03 -0500
Several utilities are downloadable from: <ftp://ftp.simtel.net/pub/simtelnet/msdos/keyboard/>
In that directory, cadel.zip contains a TSR (with source code) to disable those keys. Also, keykill.arc contains two utilities: keykill.com lets you disable up to three keys of your choice, and deboot.com changes the boot key to leftShift-Alt-Del. C programmers who simply want to make sure that the user can't Ctrl-Break out of their program can use the ANSI-standard signal() function; the Borland compilers also offer ctrlbrk() for handling Ctrl-Break. However, if your program uses normal DOS input such as getch(), ^C will appear on the screen when the user presses Ctrl-C or Ctrl-Break. You can avoid the ^C echo for Ctrl-C by using _bios_keybrd() in MSC or bioskey() in BC++; however, Ctrl-Break will still terminate the program.
An alternative approach involves programming input at a lower level. You can use INT 21 AH=7, which allows redirection but doesn't echo the ^C (or any other character, for that matter); or use INT 16 AH=0 or 10; or hook INT 9 to discard Ctrl-C and Ctrl-Break before the regular BIOS keyboard handler sees them; etc., etc.
You should be aware that Ctrl-C and Ctrl-Break are processed quite differently internally. Ctrl-Break, like all keystrokes, is processed by the BIOS code at INT 9 as soon as the user presses the keys, even if earlier keys are still in the keyboard buffer: by default the handler at INT 1B is called. Ctrl-C is not special to the BIOS, nor is it special to DOS functions 6 and 7; it is special to DOS functions 1 and 8 when at the head of the keyboard buffer. You will need to make sure BREAK is OFF to prevent DOS polling the keyboard for Ctrl-C during non-keyboard operations.
Some good general references are {Advanced MS-DOS} by Ray Duncan, ISBN 1-55615-157-8; {8088 Assembler Language Programming: The IBM PC}, ISBN 0-672-22024-5, by Willen & Krantz; and {COMPUTE!'s Mapping the IBM PC}, ISBN 0-942386- 92-2.
Date: 5 Feb 2002 22:03:03 -0500
There are really two print screen functions: 1) print current screen snapshot, triggered by PrintScreen or Shift- PrtSc or Shift-gray*, and 2) turn on continuous screen echo, started and stopped by Ctrl-P or Ctrl-PrtSc.
1) Screen snapshot to printer:
The BIOS uses INT 5 for this. Fortunately, you don't need to mess with that interrupt handler. The standard handler, in BIOS versions dated December 1982 or later, uses a byte at 0040:0100 (= 0000:0500) to determine whether a print screen is currently in progress. If it is, pressing PrintScreen again is ignored. So to disable the screen snapshot, all you have to do is write a 1 to that byte. When the user presses PrintScreen, the BIOS will think that a print screen is already in progress and will ignore the user's keypress. You can re-enable PrintScreen by zeroing the same byte.
Here's some simple code:
void prtsc_allow(int allow) /* 0=disable, nonzero=enable */
{
unsigned char far* flag = (unsigned char far*)0x00400100UL;
*flag = (unsigned char)!allow;
}
2) Continuous echo of screen to printer:
If ANSI.SYS is loaded, you can easily disable the continuous echo of screen to printer (Ctrl-P or Ctrl- PrtSc). Just redefine the keys by "printing" strings like these to the screen (BASIC print, C printf(), Pascal Write statements, or ECHO command in batch files), where <27> stands for the Escape character, ASCII 27:
<27>[0;114;"Ctrl-PrtSc disabled"p <27>[16;"^P"p
If you haven't installed ANSI.SYS, I can't offer an easy way to disable the echo-screen-to-printer function.
Actually, you might not need to disable Ctrl-P and Ctrl- PrtSc. If your only concern is not locking up your machine, when you see the "Abort, Retry, Ignore, Fail" prompt just press Ctrl-P again and then press I. As an alternative, install one of the many print spoolers that intercept printer-status queries and always return "Printer ready".
Date: 5 Feb 2002 22:03:03 -0500
First, if you just don't want NumLock turned on when you reboot, check your system's setups. (Press a special key like Del at boot time, or run the setup program supplied with your system.) Many systems may have an option in setup to turn NumLock off at boot time.
You need to twiddle bit 5, 6, or 4 of location 0040:0017. The code example below demonstrates changing NumLock status: lck() turns on a lock state, and unlck() turns it off.
/* The status lights on some keyboards may not reflect the
* change. If yours is one, call INT 16 AH=2, "get shift
* status", and that may update them. It will certainly do no
* harm.)
*/
#define NUM_LOCK (1 >> 5)
#define CAPS_LOCK (1 >> 6)
#define SCRL_LOCK (1 >> 4)
void lck(int shiftype)
{
char far* kbdstatus = (char far*)0x00400017UL;
*kbdstatus |= (char)shiftype;
}
void unlck(int shiftype)
{
char far* kbdstatus = (char far*)0x00400017UL;
*kbdstatus &= ~(char)shiftype;
}
Date: 8 Feb 2002 19:42:39 -0500
The keyboard speed has two components: delay (before a key that you hold down starts repeating) and typematic rate (the speed once the key starts repeating). Most BIOS versions since 1986 let software change the delay and typematic rate by calling INT 16 AH=3, "set typematic rate and delay"; see Ralf Brown's interrupt list <Q:02.03> [What and where is Ralf Brown's interrupt list?]. If you have DOS 4.0 or later, you can use the MODE CON command that you'll find in your DOS manual.
On 83-key keyboards (mostly XTs), the delay and typematic rate can't easily be changed. According to PC Magazine 15 Jan 1991 (x: 1) page 409, to adjust the typematic rate you need "a memory-resident program which simply '[watches]' the keyboard to see if you're holding down a key . and after a certain time [starts] stuffing extra copies of the held-down key into the buffer." No source code is given in that issue; but the QUICKEYS utility that PC Magazine published in 1986 does this sort of watching (not verified); source and object code are downloadable from <http://www.simtel.net/pub/pd/48667.html>
Date: 5 Feb 2002 22:03:03 -0500
There is no standard use for the key. The BIOS keyboard routines in INT 16 simply ignore it; therefore so do the DOS input routines in INT 21 as well as the keyboard routines in libraries supplied with high-level languages.
When you press or release a key, the keyboard triggers hardware line IRQ1, and the CPU calls INT 9. INT 9 reads the scan code from the keyboard and the shift states from the BIOS data area.
What happens next depends on whether your PC's BIOS supports an enhanced keyboard (101 or 102 keys). If so, INT 9 calls INT 15 AH=4F to translate the scan code. If the translated scan code is 54 hex (for the SysRq key) then INT 9 calls INT 15 AH=85 and doesn't put the keystroke into the keyboard buffer. The default handler of that function does nothing and simply returns. (If your PC has an older BIOS that doesn't support the extended keyboards, INT 15 AH=4F is not called. Early ATs have 84-key keyboards, so their BIOS calls INT 15 AH=85 but not 4F.)
Thus your program is free to use SysRq for its own purposes, but at the cost of some programming. You could hook INT 9, but it's probably easier to hook INT 15 AH=85, which is called when SysRq is pressed or released.
Date: 5 Feb 2002 22:03:03 -0500
Ralf Brown's Interrupt List <Q:02.03> [What and where is Ralf Brown's interrupt list?] includes MEMORY.LST, a detailed breakdown by Robin Walker of the contents of the BIOS system block that starts at 0040:0000. Bit 4 of byte 0040:0096 is "1=enhanced keyboard installed". Here is a C code example to test the keyboard type:
char far *kbd_stat_byte3 = (char far *)0x00400096UL;
if (0x10 & *kbd_stat_byte3)
{
/* 101- or 102- keyboard is installed */
}
else
{
/* Not installed */
}
PC Magazine 15 Jan 1991 (x: 1) suggests on page 412 that "for some clones [the above test] is not foolproof". If you use this method in your program you should provide the user some way to override this test, or at least some way to tell your program to assume a non-enhanced keyboard. The article suggests a different approach to determining the type of keyboard.
Date: 8 Feb 2002 19:49:17 -0500
Normally, input and output are associated with the console (i.e., with the keyboard and the screen, respectively). If either is not, you know that it has been redirected. Some source code to check this is available at the usual archive sites.
Timo Salmi has created a collection of Turbo Pascal units, one of which can be used to detect such redirection. These can be downloaded from <http://garbo.uwasa.fi/pc/ts.html>. The files you are looking for have names of the format tspaVV??.zip where the VV is the current version and ?? is 70, 60, 55, 50, or 40 for Turbo Pascal 7.0, 6.0, 5.5, 5.0, or 4.0 respectively.) Source code is not included. Also see the downloadable Frequently Asked Questions files by Timo Salmi: <ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip>
If you program in C, use isatty() if your implementation has it.
Good references for the principles are PC Magazine 16 Apr 1991 (x: 7) page 374; Ray Duncan's {Advanced MS-DOS}, ISBN 1-55615-157-8, or Ralf Brown's interrupt list (<Q:02.03> [What and where is Ralf Brown's interrupt list?]) for INT 21 AX=4400; and Terry Dettman and Jim Kyle's {DOS Programmer's Reference: 2d edition}, ISBN 0-88022-458-4, pages 602-603.
Date: 8 Feb 2002 19:50:41 -0500
Microsoft has its own keyboard extender available on the MS-DOS supplemental disks for MS-DOS 6.22 which can be found at: <ftp://ftp.microsoft.com/peropsys/msdos/public/supplmnt/sup622.exe>
Stan Brown, the former list maintainer, tested only one of the many available device drivers that do this, namely BUF160, which extends the keyboard buffer to 160 characters. It performed flawlessly for two years with MS-DOS 5 and Windows 3.1. It's downloadable as: <http://www.simtel.net/pub/pd/47186.html> <ftp://garbo.uwasa.fi/pc/keyboard/buf160_6.zip>
Date: 5 Feb 2002 22:03:03 -0500
If your computer has an enhanced keyboard (see <Q:04.08> [How can my program tell what kind of keyboard is on the system?]), put the scan code in CH and the ASCII character in CL, then execute INT 16 AH=5. The return in AL is 0 for success or 1 for buffer full.
Date: 5 Feb 2002 22:03:03 -0500
Information about accessing disks and files from MS-DOS.
Date: 5 Feb 2002 22:03:03 -0500
Under DOS 4.0 or later, use INT 21 AX=3305. DL is returned with an integer indicating the boot drive (1=A:, etc.).
Date: 8 Feb 2002 19:52:06 -0500
Downloadable shareware: <http://www.simtel.net/pub/pd/44102.html> <ftp://garbo.uwasa.fi/pc/bootutil/boot_b.zip>
The included documentation says it works by writing a new boot sector on a disk in your a: drive that redirects the boot to your B: drive. (A similar utility is bboot.zip in the same directory at Garbo only.)
If that doesn't work, you can always interchange your A: and B: drives by switching ribbon cables and changing the setup in your BIOS. From an article posted 27 Jan 1993 on another newsgroup:
[begin quotation] Take the "ribbon" connector, as you call it, and switch them. To double-check, start at the end of the cable that connects to the motherboard or floppy controller. Follow the cable until you get to the first connector. Connect this to the drive you want to be B:. After this, there should be a few lines on the cable that get flipped left to right. (On most cables, they just cut the lines and physically reverse them. It should be quite obvious from looking at the cable.) Anyway, the connector after the pins get flipped right to left is the connector for your a: drive. [end quotation]
Date: 5 Feb 2002 22:03:03 -0500
Use INT 21 AH=29 (parse filename). Point DS:SI at a null- terminated ASCII string that contains the drive letter and a colon, point ES:DI at a 37-byte dummy FCB buffer, and call INT 21 AX=2900. On return, AL is FF if the drive is invalid, something else if the drive is valid. RAM disks and SUBSTed drives are considered valid.
You can detect whether the drive is ASSIGNed by using INT 2F AX=0601. To check whether the drive is SUBSTed, use INT 21 AX=4409; or use INT 21 AH=52 to test for both JOIN and SUBST. See Ralf Brown's interrupt list: <Q:02.03> [What and where is Ralf Brown's interrupt list?].
Unfortunately, the b: drive is considered valid even on a single-diskette system. You can check that special case by interrogating the BIOS equipment byte at 0040:0010. Bits 7- 6 contain the one less than the number of diskette drives, so if those bits are zero you know that b: is an invalid drive even though function 29 says it's valid.
Following is some code originally posted by Doug Dougherty to test valid drives (treating SUBSTed and JOINed drives as valid), with my fix for the b: special case, tested in Borland C++ 4.5 (in the large model):
#include <dos.h>
#include <stdio.h>
void drvlist(void)
{
char s[3] = "A:", fcb_buff[37];
int valid;
for( ; *s<='Z'; (*s)++)
{
_SI = (unsigned) s;
_DI = (unsigned) fcb_buff;
_ES = _DS;
_AX = 0x2900;
geninterrupt(0x21);
valid = _AL != 0xFF;
if (*s == 'B' && valid)
{
char far *equipbyte = (char far *)0x00400010UL;
valid = (*equipbyte & (3 << 6)) != 0;
}
printf("Drive '%s' is %sa valid drive.\n", s, valid ? "" : "not ");
}
}
This code was translated to MSC 7.0 and tested it in small model:
#include <dos.h>
#include <stdio.h>
void drvlist(void)
{
char s[3] = "A:", fcb_buff[37], *buff=fcb_buff;
int valid;
for ( ; *s<='Z'; (*s)++)
{
__asm mov si,s __asm mov di,buff
__asm mov ax,ds __asm mov es,ax
__asm mov ax,0x2900 __asm int 21h
__asm xor ah,ah __asm mov valid,ax
valid = (valid != 0xFF);
if (*s == 'B' && valid)
{
char far *equipbyte = (char far *)0x00400010UL;
valid = (*equipbyte & (3 << 6)) != 0;
}
printf("Drive '%s' is %sa valid drive.\n", s, valid ? "" : "not");
}
}
Date: 5 Feb 2002 22:03:03 -0500
Under any DOS since DOS 2.0, you can put the following command into your AUTOEXEC.BAT file:
assign b=a
Then, when you type "dir b:" you'll no longer get the annoying prompt to insert diskette B (and the even more annoying prompt to insert A the next time you type "dir a:").
You may be wondering why anybody would want to do this. Suppose you use two different machines, maybe one at home and one at work. One of them has only a 3.5" diskette drive; the other machine has two drives, and b: is the 3.5" one. You're bound to type "dir b:" on the first one, and get the nuisance message:
Insert diskette for drive B: and press any key when ready.
But if you assign drive b: to point to a:, you avoid this problem.
Caution: there are a few commands, such as DISKCOPY, that will not work right on ASSIGNed or SUBSTed drives. See the DOS manual for the full list. Before typing one of those commands, be sure to turn off the mapping by typing "assign" without arguments.
The DOS 5.0 manual says that ASSIGN is obsolete, and recommends the equivalent form of SUBST: "subst b: a:\". Unfortunately, if this command is executed when a: doesn't hold a diskette, the command fails. ASSIGN doesn't have this problem, so under DOS 5.0 you should disregard that particular bit of advice in the manual.
Date: 8 Feb 2002 19:53:23 -0500
Reader Eric DeVolder writes that he has made available a program to do this. I haven't tried it, but it's downloadable from <http://www.simtel.net/pub/pd/44403.html>
Reader Igor Karp reports that MS-DOS version 5.0 and greater provides two interrupts to do this.
--------D-215F07-----------------------------
INT 21 - DOS 5+ - ENABLE DRIVE
AX = 5F07h
DL = drive number (0=A:)
Return: CF clear if successful
CF set on error
AX = error code (0Fh) (see #0885 at AH=59h)
Notes: simply sets the "valid" bit in the drive's CDS
this function is not supported by Novell DOS 7
See Also: AH=52h,AX=5F08h"DOS"
--------D-215F08-----------------------------
INT 21 - DOS 5+ - DISABLE DRIVE
AX = 5F08h
DL = drive number (0=A:)
Return: CF clear if successful
CF set on error
AX = error code (0Fh) (see #0885 at AH=59h)
Notes: simply clears the "valid" bit in the drive's CDS
this function is not supported by Novell DOS 7
Date: 8 Feb 2002 19:54:04 -0500
The standard way, which in fact is documented in the DOS manual, is:
if exist d:\path\nul goto found
Unfortunately, this is not entirely reliable. I found it failed in Pathworks (a/k/a PCSA, DEC's network that connects PCs and VAXes), or on a MARS box that uses an OEM version of MS-DOS 5.0. Readers have reported that it gave the wrong answer on Novell networks, on DR-DOS, and in a DOS window under OS/2. By "failed" I mean that it "found" a directory that didn't exist, or failed to find one that did exist, or both. (It has been reported that IBM fixed the OS/2 bug in version 2.11 of OS/2.) As a legacy from earlier versions of DOS it always succeeds if the path is DEV.
There appears to be no foolproof way to use pure batch commands to test for existence of a directory. The real solution is to write a program, which returns a value that your batch program can then test with an "if errorlevel". Reader Duncan Murdoch kindly posted the following Turbo Pascal version:
program existdir;
{ Confirms the existence of a directory given on the
command line. Returns errorlevel 2 on error, 1 if not
found, 0 if found. }
uses dos;
var
s : searchrec;
begin
if paramcount <> 1 then
begin
writeln('Syntax: EXISTDIR directory');
halt(2);
end
else
begin
findfirst(paramstr(1),Directory,S);
while (Doserror = 0) and ((Directory and S.Attr) = 0) do
findnext(S);
if Doserror <> 0 then
begin
Writeln('Directory not found.');
halt(1);
end
else
begin
Writeln('Directory found.');
halt(0);
end;
end;
end.
Timo Salmi also has a Turbo Pascal version in his Turbo Pascal FAQ, which is downloadable as <ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip>
Date: 5 Feb 2002 22:03:03 -0500
You've probably got something like the following code:
char *filename = "c:\foo\bar\mumble.dat"; FILE *fptr; /*.*/ fptr = fopen(filename, "r");
The problem is that \f is a form feed, \b is a backspace, and \m is m. Whenever you want a backslash in a string constant in C, you must use two backslashes:
char *filename = "c:\\foo\\bar\\mumble.dat";
This is a feature of every C compiler, because Dennis Ritchie designed C this way. It's a problem only on MS-DOS systems, because only DOS (and Atari ST/TT running TOS) uses the backslash in directory paths. But even in DOS this backslash convention applies _only_ to string constants in your source code. For file and keyboard input at run time, \ is just a normal character, so users running your program would type in file specs the same way as in DOS commands, with single \ characters.
Another possibility is to code all paths in source programs with / rather than \ characters:
char *filename = "c:/foo/bar/mumble.dat";
Ralf Brown writes, "All versions of the DOS kernel accept either forward or backslashes as directory separators. I tend to use this form more frequently than backslashes since it is easier to type and read." This applies to DOS function calls (and therefore to calls to the file library of every programming language), but not to DOS commands.
Date: 8 Feb 2002 19:55:31 -0500
Recommended: PRN2FILE from PC Magazine, downloadable as: <http://www.simtel.net/pub/pd/49066.html>
PRN2FILE contains ASM source code. PC Magazine has given copies away as part of its utilities disks, so you may already have a copy.
The directories mentioned above have lots of other utilities to redirect printer output.
Date: 7 Feb 2002 14:48:46 -0500
Assuming the batch file is called batch.bat, to send its output (stdout) to another file, just invoke COMMAND.COM as a secondary command processor:
command /c batch parameters_if_any >outfile
Timo Salmi's notes on this and other batch tricks are downloadable from: <ftp://garbo.uwasa.fi/pc/link/tsbat.zip>
A reader of comp.os.msdos.programmer has created a utility that can capture batch file output. It can be found at: <http://www.simtel.net/pub/dl/11141.shtml>
Date: 8 Feb 2002 19:58:21 -0500
Use freopen(..., stderr) and then execute the desired command via system(). There are downloadable versions of programs to do this.
This file includes TP4 source and an executable: <http://www.simtel.net/pub/pd/50430.html>
A C example is downloadable as: <http://www.simtel.net/pub/pd/41772.html>
I compiled it with MSC 7.0, and it works fine with one exception: Contrary to the included comments, redirected output starts writing at the beginning of the output file rather than appending. That is easily solved by adding "fseek(stderr, 0L, SEEK_END);" after the freopen() call for stderr.
A reader comp.os.msdos.programer has created a utilitiy that can capture console output. It can be found at: <http://www.simtel.net/pub/dl/11141.shtml>
Date: 5 Feb 2002 22:03:03 -0500
This is a summary of an article Ralf Brown posted on 8 August 1992, with some additions from a Microsoft tech note and information from Chin Huang.)
DOS imposes some limits. Once you overcome those, which is pretty easy, you may have to take additional measures to overcome the limitations built into your compiler's run- time library.
1) Limitations imposed by DOS:
There are separate limits on files and file handles. For example, DOS opens three files but five file handles: CON (stdin, stdout, and stderr), AUX (stdaux), and PRN (stdprn).
The limit in FILES= in CONFIG.SYS is a system-wide limit on files opened by all programs (including the three that DOS opens and any opened by TSRs); each process has a limit of 20 handles (including the five that DOS opens). Example: CONFIG.SYS has FILES=40. Then program #1 will be able to open 15 file handles. Assuming that the program actually does open 15 handles pointing to 15 different files, other programs could still open a total of 22 files (40-3-15 = 22), though no one program could open more than 15 file handles. If you're running DOS 3.3 or later, you can increase the per-process limit of 20 file handles by a call to INT 21 AH=67, Set Handle Count. Your program is still limited by the system-wide limit on open files, so you may also need to increase the FILES= value in your CONFIG.SYS file (and reboot). The run-time library that you're using may have a fixed-size table of file handles, so you may also need to get source code for the module that contains the table, increase the table size, and recompile it.
2) Limitations in Microsoft C run-time library:
In Microsoft C the run-time library limits you to 20 file handles. To change this, you must be aware of two limits:
File handles used with _open(), _read(), etc.: Edit _NFILE_ in CRT0DAT.ASM.
Stream files used with fopen(), fread(), etc.: Edit _NFILE_ in _FILE.C for DOS or FILE.ASM for Windows/QuickWin. This must not exceed the value of _NFILE_ in CRT0DAT.ASM. (QuickWin uses the constant _WFILE_ in CRT0DAT.ASM and WFILE.ASM for the maximum number of child text windows.)
After changing the limits, recompile using CSTARTUP.BAT. Microsoft recommends that you first read README.TXT in the same directory.
3) Limitations in Borland C++ run-time library:
(Reader Chin Huang provided this information on 12 Sep 1993.) To increase the open file limit for a program you compile with Borland C++ 3.1, edit the file _NFILE.H in the include directory and change the _NFILE_ value. Compile and link the modules FILES.C and FILES2.C from the lib directory into your program.
Date: 5 Feb 2002 22:03:03 -0500
In DOS 5.0 (and possibly in 4.0 as well), there are actually two volume labels: the LABEL command reports only the first but changes both of them.
The rest of this answer assumes that by "volume label" you mean the traditional one, the one that DIR and VOL display. Though it's a directory entry in the root directory, you can't change it using the newer DOS file-access functions (INT 21 AH=3C, 41, 43); instead, use the old FCB-oriented directory functions. Specifically, you need to allocate a 64-byte buffer and a 41- byte extended FCB (file control block). Call INT 21 AH=1A to find out whether there is a volume label. If there is, AL returns 0 and you can change the label using DOS function 17 or delete it using DOS function 13. If there's no volume label, function 1A will return FF and you can create a label via function 16. Important points to notice are that ? wildcards are allowed but * are not; the volume label must be space filled not null terminated.
The following MSC 7.0 code worked for me in DOS 5.0; the functions it uses have been around since DOS 2.0. The function parameter is 0 for the current disk, 1 for a:, 2 for b:, etc. It doesn't matter what your current directory is; these functions always search the root directory for volume labels. (I didn't try to change the volume label of any networked drives.)
// Requires DOS.H, STDIO.H, STRING.H
void vollabel(unsigned char drivenum)
{
static unsigned char extfcb[41], dta[64], status, *newlabel;
int chars_got = 0;
#define DOS(buff,func) __asm { __asm mov dx,offset buff \
__asm mov ax,seg buff __asm push ds __asm mov ds,ax \
__asm mov ah,func __asm int 21h __asm pop ds \
__asm mov status,al }
#define getlabel(buff,prompt) newlabel = buff; \
memset(newlabel,' ',11); printf(prompt); \
scanf("%11[^\n]%n", newlabel, &chars_got); \
if (chars_got < 11) newlabel[chars_got] = ' ';
// Set up the 64-byte transfer area used by function 1A.
DOS(dta, 1Ah)
// Set up an extended FCB and search for the volume label.
memset(extfcb, 0, sizeof extfcb);
extfcb[0] = 0xFF; // denotes extended FCB
extfcb[6] = 8; // volume-label attribute bit
extfcb[7] = drivenum; // 1=A,2=B,...; 0=current drive
memset(&extfcb[8], '?', 11);// wildcard *.*
DOS(extfcb,11h)
if(status == 0)
{ // DTA has volume label's FCB
printf("volume label is %11.11s\n", &dta[8]);
getlabel(&dta[0x18], "new label (\"delete\" to delete): ");
if(chars_got==0)
printf("label not changed\n");
else if (strncmp(newlabel,"delete ",11) == 0)
{
DOS(dta,13h)
printf(status ? "label failed\n":"label deleted\n");
}
else
{ // user wants to change label
DOS(dta,17h)
printf(status ? "label failed\n" : "label changed\n");
}
}
else
{ // no volume label was found
printf("disk has no volume label.\n");
getlabel(&extfcb[8], "new label (<Enter> for none): ");
if (chars_got > 0)
{
DOS(extfcb,16h)
printf(status ? "label failed\n" : "label created\n");
}
}
} // end function vollabel
Date: 5 Feb 2002 22:03:03 -0500
If the disk was formatted by DOS 4.0 or later, use INT 21: AX=6900 gets the serial number; AX=6901 sets it. (The disk serial number doesn't exist if the disk was formatted with an earlier version of DOS, or with some third-party formatters.) See Ralf Brown's interrupt list (<Q:02.03> [What and where is Ralf Brown's interrupt list?]), or PC Magazine July 1992 (xi:13) page 496, for details.
INT 21 AH=69 also gets and sets the volume label in the boot record, which is not necessarily the same as "the" volume label displayed by the DIR, VOL, and LABEL commands. For that volume label, see <Q:05.12> [How can I read, create, change, or delete the volume label?]
Date: 5 Feb 2002 22:03:03 -0500
Please see <Q:03.06> [What's the format of an .OBJ file?]; <Q:03.07> [What's the format of an .EXE header?]; and <Q:03.08> [What's the difference between .COM and .EXE formats?]
Date: 5 Feb 2002 22:03:03 -0500
Please see <Q:08.01> [How can a program reboot my PC?] (Trust me.)
Date: 5 Feb 2002 22:03:03 -0500
Use INT 21 AX=4409h. See Ralph Brown's interrupt list (<Q:02.03> [What and where is Ralf Brown's interrupt list?]) for more information.
Date: 5 Feb 2002 22:03:03 -0500
Information about the hard drive's manufacturer is retrieved by using the ATA and ATAPI specifications. Please see "<Q:05.18> [Where can I find information about the ATA/ATAPI specification?]
Date: 5 Feb 2002 22:03:03 -0500
The AT Attachment (ATA) standard is maintained by T13, a Technical Committee for the National Committee on Information Technology Standards which as accredited by ANSI. Their web site can be found at <http://www.t13.org>. At that web site the ATA and ATAPI specifications are availible in PDF form.
Date: 7 Feb 2002 14:26:15 -0500
You can use the NOWMINUS program. This program creates environment variables containing date and time information. See <Q:08.15> [How can I place date and time information into environment variables?] for more information.
Here is an example of using NOWMINUS to rename the files thisweek.* to {lastweeksdate}.*:
NOWMINUS d7 z7 f1 j0 vLASTWEEK
ren thisweek.* %LASTWEEK%.*
set LASTWEEK=
Date: 5 Feb 2002 22:03:03 -0500
This section provides information about how to access the serial ports. In the future I will be working on adding information about using MS-DOS for networking and internet access.
Date: 5 Feb 2002 22:03:03 -0500
Unless your machine is fairly old, it's probably already set up. After installing the board that contains the extra COM port(s), check the I/O addresses in word 0040:0004 or 0040:0006. (In DEBUG, type "D 40:4 L4" and remember that every word is displayed low byte first, so if you see "03 56" the word is 5603.) If those addresses are nonzero, your PC is ready to use the ports and you don't need the rest of this answer.
If the I/O address words in the 0040 segment are zero after you've installed the I/O board, you need some code to store these values into the BIOS data segment:
0040:0004 word I/O address of COM3 0040:0006 word I/O address of COM4 0040:0011 byte (bits 3-1): number of serial ports installed
The documentation with your I/O board should tell you the port addresses. When you know the proper port addresses, you can add code to your program to store them and the number of serial ports into the BIOS data area before you open communications. Or you can use DEBUG to create a little program to include in your AUTOEXEC.BAT file, using this script:
n SET_ADDR.COM <--- or a different name ending in .COM
a 100
mov AX,0040
mov DS,AX
mov wo [0004],aaaa <--- replace aaaa with COM3 address or 0
mov wo [0006],ffff <--- replace ffff with COM4 address or 0
and by [0011],f1
or by [0011],8 <--- use number of serial ports times 2
mov AH,0
int 21
<--- this line must be blank
rCX
1f
rBX
0
w
q
Date: 8 Feb 2002 20:00:09 -0500
Look in the four words beginning at 0040:0000 for COM1 through COM4. (The DEBUG command "D 40:0 L8" will do this. Remember that words are stored and displayed low byte first, so a word value of 03F8 will be displayed as F8 03.) If the value is zero, that COM port is not installed (or you've got an old BIOS; see <Q:06.01> [How do I set my machine up to use COM3 and COM4?]). If the value is nonzero, it is the I/O address of the transmit/receive register for the COM port.
Each COM port occupies eight consecutive I/O addresses (though many chips use only the first seven).
Here's some C code to find the I/O address:
unsigned ptSel(unsigned comport)
{
unsigned io_addr;
if (comport >= 1 && comport <= 4)
{
unsigned far *com_addr = (unsigned far *)0x00400000UL;
io_addr = com_addr[comport-1];
}
else
io_addr = 0;
return io_addr;
}
You might also want to explore Port Finder, downloadable as: <http://www.simtel.net/pub/pd/47138.html>
I haven't tried it myself, but a posted article reviewed it very favorably and said it also lets you swap ports around.
Date: 5 Feb 2002 22:03:03 -0500
The first two are usually right (though not always); the last two are different on many machines.
Date: 8 Feb 2002 20:03:52 -0500
Do you want actual code, or do you want books that explain what's going on?
1) Source code
First, check your compiler's run-time library. Many compilers offer functions similar to Microsoft C's _bios_serialcom() or Borland's bioscom(), which may meet your needs.
Second, check for downloadable resources at SimTel and Garbo. At SimTel, <http://www.simtel.net/pub/pd/41750.html> (March 1993) is described as "Asynchronous communications library for C"; Garbo has a whole <ftp://garbo.uwasa.fi/pc/comm> directory. Also, an extended example is in Borland's TechFax TI445, downloadable as part of: <http://www.simtel.net/pub/pd/50843.html> <ftp://garbo.uwasa.fi/pc/c-lang/bchelp10.zip>
Though written by Borland, much of it is applicable to other forms of C, and it should give you ideas for other programming languages.
Third, SNIPPETS (see <Q:02.08> [What and where is SNIPPETS?]) contains a sample interrupt-driven serial communications library.
2) Reference books
Highly recommended: Joe Campbell's {C Programmer's Guide to Serial Communications}, ISBN 0-672-22584-0. He gives complete details on how serial ports work, along with complete programs for doing polled or interrupt-driver I/O. The book is quite thick, and none of it looks like filler.
If Campbell's book is overkill for you, you'll find a good short description of serial I/O in {DOS 5: A Developer's Guide}, ISBN 1-55851-177-6, by Al Williams.
Finally, a reader has recommended {Serial Communications Programming in C/C++} by Mark Goodwin (ISBN 1-55828-198-3), with source code in the book and on disk. Topics include the basics, various methods of serial communications on the PC (with consideration of high-speed modems), ANSI screen interface, file transfer protocols (Xmodem and Ymodem), etc. There is code in C, and that code is extended into a C++ class for those who use C++. There are also subroutines in Assembly.
3) Downloadable information files
A "Serial Port FAQ" is occasionally posted to this newsgroup, and is downloadable as multiple files:
<ftp://ftp.phil.uni-sb.de/pub/people/chris/>
This directory contains a series of files beginning with Serial_Port.
Date: 5 Feb 2002 22:03:03 -0500
The subject says it all. Bv)
Date: 5 Feb 2002 22:03:03 -0500
SNIPPETS (see <Q:02.08> [What and where is SNIPPETS?]) contains C-callable x86 assembly language code for determining the type of CPU in CPUCHECK.ASM.
Date: 5 Feb 2002 22:03:03 -0500
If you just fprintf(stdprn, ...), C will translate some of your control codes. The way around this is to reopen the printer in binary mode: prn = fopen("PRN", "wb");
You must use a different file handle because stdprn isn't an lvalue. By the way, in DOS 5.0 a colon must not follow PRN or LPT1.
There's one special case, Ctrl-Z (ASCII 26), the DOS end-of- file character. If you try to send an ASCII 26 to your printer, DOS simply ignores it. To get around this, you need to reset the printer from "cooked" to "raw" mode. Microsoft C users must use INT 21 AH=44, "get/set device information". Turbo C and Borland C++ users can use ioctl to accomplish the same thing: ioctl(fileno(prn), 1, ioctl(fileno(prn),0) & 0xFF | 0x20, 0);
An alternative approach is simply to write the printer output into a disk file, then copy the file to the printer with the /B switch.
A third approach is to bypass DOS functions entirely and use the BIOS printer functions at INT 17. If you also fprintf(stdprn,...) in the same program, you'll need to use fflush() to synchronize fprintf()'s buffered output with the BIOS's unbuffered.
By the way, if you've opened the printer in binary mode from a C program, remember that outgoing \n won't be translated to carriage return/line feed. Depending on your printer, you may need to send explicit \n\r sequences.
Date: 5 Feb 2002 22:03:03 -0500
Please see <Q:05.08> [How can I redirect printer output to a file?]
Date: 5 Feb 2002 22:03:03 -0500
The technique below should work if your BIOS is not too old. It uses three functions from INT 10, the BIOS video interrupt. (If you're using a Borland language, you may not have to do this the hard way. Look for a function called DetectGraph or something similar.)
Set AX=1200, BL=32 and call INT 10. If AL returns 12, you have a VGA. If not, set AH=12, BL=10 and call INT 10 again. If BL returns 0,1,2,3, you have an EGA with 64,128,192,256K memory. If not, set AH=0F and call INT 10 a third time. If AL is 7, you have an MDA (original monochrome adapter) or Hercules; if not, you have a CGA.
This worked when tested with a VGA, but I had no other adapter types to test it with.
Date: 8 Feb 2002 20:05:49 -0500
The following file contains .COM utilities and .ASM source code: <http://www.simtel.net/pub/pd/49657.html>
Date: 8 Feb 2002 20:07:14 -0500
Use INT 33 AX=3, described in Ralf Brown's interrupt list (<Q:02.03> [What and where is Ralf Brown's interrupt list?]).
The Windows manual says that the Logitech mouse is compatible with the Microsoft one, so the interrupt will probably work the same.
Also, many files are downloadable from: <http://www.simtel.net/pub/msdos/mouse/>
Date: 7 Feb 2002 14:50:10 -0500
First check the library that came with your compiler. Many vendors have some variant of peek and poke functions. For example:
By the way, it's not useful to talk about "portable" ways to do this. Any operation that is tied to a specific memory address is not likely to work on another kind of machine.
Date: 8 Feb 2002 20:11:37 -0500
There are a great many public-domain utilities that do this. The following files can be downloaded from <http://www.simtel.net/pub/msdos/sysutl/>:
cmos14.zip 5965 920817 Saves/restores CMOS to/from file cmoser11.zip 28323 910721 386/286 enhanced CMOS setup program cmosram.zip 76096 920214 Save AT/386/486 CMOS data to file and restore rom2.zip 15692 900131 Save AT and 386 CMOS data to file and restore setup21.zip 18172 880613 Setup program which modifies CMOS RAM viewcmos.zip 11068 900225 Display contents of AT CMOS RAM, w/C source
A program to check and display CMOS memory (but not write to it) is downloadable as part of: <http://www.simtel.net/pub/pd/50522.html> <ftp://garbo.uwasa.fi/pc/ts/tsutle23.zip>
Good reports of CMOS299.ZIP have been posted, but it no longer appears to be online.
Stan Brown, the former list maintainer, reports that he personally tested CMOSRAM and that it worked fine. It contains an excellent (and witty) .DOC file that explains the hardware involved and gives specific recommendations for preventing disaster or recovering from it. It's $5 shareware.
Robert Jourdain's {Programmer's Problem Solver for the IBM PC, XT, and AT} has code for accessing the CMOS RAM, according to an article posted in this newsgroup.
Date: 8 Feb 2002 20:50:34 -0500
Part of this involves switching into protected mode.
An article entitled "How DOS Programs Can Use Over 1MB of RAM" appeared in PC Magazine 29 June 1993 (xii: 12) pages 302-304.
I also suggest John English's XMS classes for C++: <ftp://ftp.brighton.ac.uk/pub/je/xms200je.zip>.
See also <Q:07.10> [How can I use the protected mode?]
Date: 8 Feb 2002 20:15:02 -0500
DJ Delorie has produced DJGPP, a protected mode programming environment which supports a port of the GNU C/C++/Ada. For more informat see <Q:10.04> [What and where is DJGPP?]
Users of Borland C++ Version 4.xx could once purchase the Borland PowerPack for DOS Version 1.00; however, it appears that its sell has been discontinued. This package includes Borland C++ 4.02 Service Update, 16-bit DPMI libraries and extenders, 32-bit DPMI libraries and extenders, TurboVision 2.0 (16-bit DOS, 16-bit DPMI, 32-bit DPMI), SuperVGA BGI Drivers (16-bit DOS, 16-bit DPMI, 32- bit DPMI).
A reader of comp.os.msdos.programmer has the following updateu about the PowerPack and additional information about DPMI programming:
[begin quote] About protected-mode programming (Question 7.10), Borland no longer supports the PowerPack (from what I've read in this newsgroup), so I doubt that it can still be purchased. However, the FAQ could mention that the extender is integrated into Borland C++ version 5.x (and probably the Builder product as well). Borland doesn't fully support that either, since the documentation isn't very clear about compiling DPMI programs and a stub for the executable has to be extracted from one of Borland's executables. The necessary steps were posted a long time ago (by someone else), and I can provide the information if necessary. Even if the FAQ didn't describe those steps, it could at least indicate that version 5.x can compile DPMI programs (as well as clarifying the PowerPack info). [end quote]
There are more extenders out there. One notable DOS extender is Adam Seychell's DOS32 Version 3.5 beta. It can be found at <http://www.programmersheaven.com/zone5/cat19/1363.htm> Also check out Adam's page at <http://www.geocities.com/SiliconValley/2151/pmode.html>
Date: 5 Feb 2002 22:03:03 -0500
Use INT 15 AX=C0, described in Ralf Brown's interrupt list (<Q:02.03> [What and where is Ralf Brown's interrupt list?]).
Date: 5 Feb 2002 22:03:03 -0500
SNIPPETS (see <Q:02.08> [What and where is SNIPPETS?]) contains C-callable assembly code to determine presence of coprocessor in NDPCHECK.ASM.
Date: 6 Feb 2002 20:36:38 -0500
A utility known as ATXOFF.COM is available at <http://www.informatik.fh-muenchen.de/~ifw98223/dostools.htm>. It uses APM 1.2 to power off the system but doesn't attempt to flush the disk cache.
Date: 5 Feb 2002 22:03:03 -0500
This section is noteworthy for having the longest code snippets.
Date: 8 Feb 2002 20:16:09 -0500
You can generate a "cold" boot or a "warm" boot. A cold boot is the same as turning the power off and on; a warm boot is the same as Ctrl-Alt-Del and skips the power-on self 'test.
For a warm boot, store the hex value 1234 in the word at 0040:0072. For a cold boot, store 0 in that word. Then, if you want to live dangerously, jump to address FFFF:0000. Here's C code to do it:
/* WARNING: data loss possible */
void bootme(int want_warm) /* arg 0 = cold boot, 1 = warm */
{
void (far* boot)(void) = (void (far*)(void))0xFFFF0000UL;
unsigned far* type = (unsigned far*)0x00400072UL;
*type = (want_warm ? 0x1234 : 0);
(*boot)( );
}
What's wrong with that method? It will boot right away, without closing files, flushing disk caches, etc. If you boot without flushing a write-behind disk cache (if one is running), you could lose data or trash the file allocation table in your hard drive.
There are two methods of signaling the cache to flush its buffers:
(1) Simulate a keyboard Ctrl-Alt-Del in the keystroke translation function of the BIOS (INT 15 AH=4F; but see notes below)
(2) Issue a disk reset (DOS function 0D). Most disk-cache programs hook one or both of those interrupts, so if you use both methods you'll probably be safe.
When user code simulates a Ctrl-Alt-Del, one or more of the programs that have hooked INT 15 AH=4F can ask that the key be ignored by clearing the carry flag. For example, HyperDisk does this when it has started but not finished a cache flush. So if the carry flag comes back cleared, the boot code has to wait a couple of clock ticks and then try again. (None of this matters on older machines whose BIOS can't support 101- or 102-key keyboards; see the discussion of INT 21 AH=4F in <Q:04.07> [What is the SysRq key for?])
C code that tries to signal the disk cache (if any) to flush is given below. Turbo Pascal code by Timo Salmi that does more or less the same job may be found at question 49 (as of this writing) in the Turbo Pascal FAQ in comp.lang.pascal, and is downloadable as file FAQPAS2.TXT, which is part of: <ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip>
Here's C code that reboots after trying to signal the disk cache:
#include <dos.h>
void bootme(int want_warm) /* arg 0 = cold boot, 1 = warm */
{
union REGS reg;
void (far* boot)(void) = (void (far*)(void))0xFFFF0000UL;
unsigned far* boottype = (unsigned far*)0x00400072UL;
char far* shiftstate = (char far*)0x00400017UL;
unsigned ticks;
int time_to_waste;
/* Simulate reception of Ctrl-Alt-Del: */
for (;;)
{
*shiftstate |= 0x0C; /* turn on Ctrl & Alt */
reg.h.ah = 0x4F; /* see notes below */
reg.h.al = 0x53; /* 0x53 = Del's scan code */
reg.x.cflag = 1; /* sentinel for ignoring key */
int86(0x15, ®, ®);
/* If carry flag is still set, we've finished. */
if(reg.x.cflag)
break;
/* Else waste some time before trying again: */
reg.h.ah = 0;
int86(0x1A, ®, ®); /* system time into CX:DX */
ticks = reg.x.dx;
for (time_to_waste = 3; time_to_waste > 0; )
{
reg.h.ah = 0;
int86(0x1A, ®, ®);
if (ticks != reg.x.dx)
ticks = reg.x.dx , --time_to_waste;
}
}
/* Issue a DOS disk reset request: */
reg.h.ah = 0x0D;
int86(0x21, ®, ®);
/* Set boot type and boot: */
*boottype = (want_warm ? 0x1234 : 0);
(*boot)( );
}
Reader Timo Salmi reported (26 July 1993) that the INT 15 AH=4F call may not work on older PCs (below AT, XT2, XT286), according to Ralf Brown's interrupt list (<Q:02.03> [What and where is Ralf Brown's interrupt list?]).
Reader Roger Fulton reported (1 July 1993) that INT 15 AH=4F hangs even a modern PC "ONLY when ANSI.SYS [is] loaded high using EMM386.EXE. (Other things loaded high with EMM386.EXE were OK; ANSI.SYS loaded high with QEMM386.SYS was OK; ANSI.SYS loaded low with EMM386.EXE installed was OK.)" His solution was to use only the disk reset, INT 21 AH=0D, which does flush SMARTDRV, then wait five seconds in hopes that any other disk-caching software would have time to flush its queue.
Reader Per Bergland reported (10 Sep 1993) that the jump to FFFF:0000 will not work in Windows or other protected-mode programs. (For example, when the above reboot code ran in a DOS session under Windows, a box with "waiting for system shutdown" appeared. The PC hung and had to be reset by cycling power.) His solution, which does a cold boot not a warm boot, is to pulse pin 0 of the 8042 keyboard controller, which is connected to the CPU's "reset" line.
He has tested the following code on various Compaqs, and expects it will work for any AT-class machine; he cautions that you must first flush the disk cache as indicated above.
cli @@WaitOutReady: ; Busy-wait until 8042 ready for new command in al,64h ; read 8042 status byte test al,00000010b ; this bit indicates input buffer full jnz @@WaitOutReady mov al,0FEh ; Pulse "reset" = 8042 pin 0 out 64h,al ; The PC will reboot now
Date: 8 Feb 2002 20:19:05 -0500
The PC Timing FAQ / Application Note, maintained by Kris Heidenstrom (kheidenstrom@actrix.gen.nz), contains information relating to timing with PC hardware and software. It can be found on SimTel: <http://www.simtel.net/pub/pd/46935.html>
The following files, among others, are downloadable from SimTel in the <http://www.simtel.net/pub/msdos/sysutl/> directory:
atim.zip 4783 881126 Precision program timing for AT
In the <http://www.simtel.net/pub/msdos/c/> directory:
millisec.zip 37734 911205 MSC/asm src for millisecond timing mschrt3.zip 53708 910605 High-res timer toolbox for MSC 5.1 msec_12.zip 8484 920320 High-def timer v1.2 (C,ASM) ztimer11.zip 77625 920428 Microsecond timer for C, C++, ASM
For Turbo Pascal users, source and object code are downloadable as: <ftp://garbo.uwasa.fi/pc/turbopas/bonus507.zip>
Also see "Q: How is millisecond timing done?" in FAQPAS.TXT, downloadable as part of: <ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip>
Date: 8 Feb 2002 20:21:49 -0500
First, which previous program are you talking about? If your current program ran another one, when the child program ends its error level is available to the program that spawned it. Most high-level languages provide a way to do this; for instance, in Turbo Pascal it's Lo(DosExitCode) and the high byte gives the way in which the child terminated. In Microsoft C, the exit code of a synchronous child process is the return value of the spawn- type function that creates the process.
If your language doesn't have a function to return the error code of a child process, you can use INT 21 AH=4D (get return code). By the way, this will tell you the child's exit code and the manner of its ending (normal, Ctrl-C, critical error, or TSR).
It's much trickier if the current program wants to get the error level of the program that ran and finished before this one started. G.A. Theall has published source and compiled code to do this; the code is downloadable as: <http://www.simtel.net/pub/pd/40610.html>
(The code uses undocumented features in DOS 3.3 through 5.0. In the .DOC file Theall says that the values returned under 4DOS or other replacements won't be right.)
Date: 8 Feb 2002 20:22:43 -0500
Program functions that read or write "the environment" typically access only the program's copy of it. What this Q really wants to do is to modify the active environment, the one that is affected by SET commands in batch files or at the DOS prompt. You need to do some programming to find the active environment, and that depends on the version of DOS.
A fairly well-written article in PC Magazine 28 Nov 1989 (viii:20), pages 309-314, explains how to find the active environment, and includes Pascal source code. The article hints at how to change the environment, and suggests creating paths longer than 128 characters as one application.
Now as for downloadable source code, there are many possibilities.
Stan Brown, the former list maintainer recommends the following: <ftp://garbo.uwasa.fi/pc/envutil/rbsetnv1.zip>
It includes some utilities to manipulate the environment, with source code in C. A newer program from PC Magazine 22 Dec 1992 (XI: 22) is: <ftp://garbo.uwasa.fi/pc/pcmagvol/vol11n22.zip>
You can also use a call to INT 2E, Pass Command to Interpreter for Execution; see Ralf Brown's interrupt list (<Q:02.03> [What and where is Ralf Brown's interrupt list?]) for details and cautions.
Reader Dr. John Stockton has written a unit for Turbo Pascal known as jrs_envu.pas to facilitate writing to the environment. It is for DOS (not DPMI) mode programs running under DOS to Win98, but not WinNT. It can be downloaded from here: <http://www.merlyn.demon.co.uk/programs/jrs_envu.pas>. For more information, see <http://www.merlyn.demon.co.uk/batprogs.htm>.
Date: 5 Feb 2002 22:03:03 -0500
Under DOS 5.0 and above you can not. INT 21 AX=3700, get switch character, always returns a '/' (hex 2F). But the DOS commands don't even call that function: they simply hard code '/' as the switch character.
Some history: DOS used to let you change the switch character by using SWITCHAR= in CONFIG.SYS or by calling DOS function 3701. DOS commands and other programs called DOS function 3700 to find out the switch character. If you changed the switch character to '-' (the usual choice), you could then type "dir c:/c700 -p" rather than "dir c:\c700 /p". Under DOS 4.0, the DOS commands ignored the switch character but functions 3700 and 3701 still worked and could be used by other programs. Under DOS 5.0, even those functions no longer work, though all DOS functions still accept '/' or '\' in file specs.
You can reactivate the functions to get and set switchar by using programs like SLASH.ZIP or the sample TSR called SWITCHAR in amisl091.zip (see <Q:08.06> [How can I write a TSR (terminate-stay-resident utility)?]). DOS commands will still use the slash, but non-DOS programs that call DOS function 3700 will use your desired switch character. (DOS replacements like 4DOS may honor the switch character for internal commands.)
Some readers may wonder why this is even an issue. Making '-' the switch character frees up the front slash to separate names in the path part of a file spec. This is easier for the ten-fingered to type, and it's one less difference to remember for commuters between DOS and Unix. The switch character is the only issue, since all the INT 21 functions accept '/' or '\' to separate directory names.
Date: 8 Feb 2002 20:31:08 -0500
There are books, and there's code to download.
First, the books:
Next, the code. Some of it is companion code to published articles, which are also listed below:
Finally, there are (were?) commercial products, of which TesSeRact (for C-language TSRs) is one of the best known.