Path: senator-bedfellow.mit.edu!dreaderd!not-for-mail Message-ID: Supersedes: Expires: 18 Mar 2004 09:26:10 GMT References: X-Last-Updated: 2003/08/14 From: jeffrey@carlyle.org (Jeffrey Carlyle) Sender: jeffrey@carlyle.org (Jeffrey Carlyle) Reply-To: jeffrey@carlyle.org (Jeffrey Carlyle) Approved: news-answers-request@MIT.edu Organization: JeffC.org Subject: comp.os.msdos.programmer FAQ part 3/5 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. Originator: faqserv@penguin-lust.MIT.EDU Date: 13 Feb 2004 09:26:47 GMT Lines: 942 NNTP-Posting-Host: penguin-lust.mit.edu X-Trace: 1076664407 senator-bedfellow.mit.edu 573 18.181.0.29 Xref: senator-bedfellow.mit.edu comp.os.msdos.programmer:127080 alt.msdos.programmer:54652 comp.answers:56252 alt.answers:71473 news.answers:266072 Archive-name: msdos-programmer-faq/part3 Comp-os-msdos-programmer-archive-name: dos-faq-pt3.txt Posting-frequency: 28 days Last-modified: 14 Aug 2003 comp.os.msdos.programmer FAQ Version 2003.08.14 This is the Frequently Asked Questions list for the newsgroup comp.os.msdos.programmer. COPYRIGHT Copyright 2003 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 [Where can I get the latest copy of this FAQ list?] for a link to the latest version of the FAQ.) This is part 3 of 5 parts. TABLE OF CONTENTS PART 1: Section 1. General FAQ and Newsgroup Information - Is MS-DOS Dead? - What is this article for? - Who has contributed to this article? - How can I search this article for a particular topic? - Are the answers guaranteed to be correct and complete? - What is comp.os.msdos.programmer about? - Is comp.os.msdos.programmer just for C programmers? - What is comp.sys.ibm.pc.programmer? - Is comp.os.msdos.programmer available as a mailing list? - What's this netiquette? - How can I learn more about Usenet? - What other technical newsgroups should I know about? - Where are FAQ lists archived? - Where can I get the latest copy of this FAQ list? Section 2. General Reference - Are there any good on-line references for PC hardware components? - Are there any good on-line references for PC interrupts? - What and where is Ralf Brown's interrupt list? - Where can I find lex, yacc, and language grammars? - What's the best book to learn programming? - Why won't my code work? - Are there any good sources of example code? - What and where is SNIPPETS? - Is the source code MS-DOS available? - What are my alternatives for MS-DOS compatible OSes? - What and where is FreeDOS? - Where can I find out about batch files? PART 2: Section 3. Compile and link - What the heck is DGROUP > 64K? - How do I fix 'automatic data segment exceeds 64K' or 'stack plus data exceed 64K'? - Will Borland C code and Microsoft C code link together? - Why did my program bomb at run time with 'floating point formats not linked' or 'floating point not loaded'? - How can I change the stack size in Borland's C compilers? - What's the format of an .OBJ file? - What's the format of an .EXE header? - What's the difference between .COM and .EXE formats? - How do I create a .COM file? - Where is EXE2BIN located? - What does this message mean: 'A20 already enabled so test is meaning less?' Section 4. Keyboard - How can I read a character without echoing it to the screen, and without waiting for the user to press the Enter key? - How can I find out whether a character has been typed, without waiting for one? - How can I disable Ctrl-C/Ctrl-Break and/or Ctrl-Alt-Del? - How can I disable the print screen function? - How can my program turn NumLock (CapsLock, ScrollLock) on or off? - How can I speed up the keyboard's auto-repeat? - What is the SysRq key for? - How can my program tell what kind of keyboard is on the system? - How can I tell if input, output, or stderr has been redirected? - How can I increase the size of the keyboard buffer? - How can I stuff characters into the keyboard buffer? PART 3: (this part) Section 5. Disks and files - What drive was the PC booted from? - How can I boot from drive B:? - Which real and virtual disk drives are valid? - How can I make my single floppy drive both a: and b:? - How can I disable access to a drive? - How can a batch file test existence of a directory? - Why won't my C program open a file with a path? - How can I redirect printer output to a file? - How can I redirect the output of a batch file? - How can I redirect stderr? - How can my program open more files than DOS's limit of 20? - How can I read, create, change, or delete the volume label? - How can I get the disk serial number? - What's the format of .OBJ, .EXE., .COM files? - How can I flush the software disk cache? - How can I see if a drive is a RAM drive? - How can I determine a hard drive's manufacturer? - Where can I find information about the ATA/ATAPI specification? - How can I copy files to or from filenames containing date information? Section 6. Serial ports (COM ports) - How do I set my machine up to use COM3 and COM4? - How do I find the I/O address of a COM port? - But aren't the COM ports always at I/O addresses 3F8, 2F8, 3E8, and 2E8? - How do I configure a COM port and use it to transmit data? PART 4: Section 7. Other hardware questions and problems - Which 80x86 CPU is running my program? - How can a C program send control codes to my printer? - How can I redirect printer output? - Which video adapter is installed? - How do I switch to 43- or 50-line mode? - How can I find the Microsoft mouse position and button status? - How can I access a specific address in the PC's memory? - How can I read or write my PC's CMOS memory? - How can I access memory beyond 640K? - How can I use the protected mode? - How can I tell if my program is running on a PS/2-style machine. - Is there a 80x87 math unit installed? - How can I power off the computer from a batch file? Section 8. Other software questions and problems - How can a program reboot my PC? - How can I time events with finer resolution than the system clock's 55 ms (about 18 ticks a second)? - How can I find the error level of the previous program? - How can a program set DOS environment variables? - How can I change the switch character to - from /? - How can I write a TSR (terminate-stay-resident utility)? - Why does my interrupt function behave strangely? - How can I write a device driver? - What can I use to manage versions of software? - What's this 'null pointer assignment' after my C program executes? - How can a batch file tell whether it's being run in a DOS box under Windows? - How can my program tell if it's running under Windows? - How can a program tell whether ANSI.SYS is installed? - How do I copyright software that I write? - How can I place date and time information into environment variables? PART 5: Section 9. Downloading - What are SimTel and Garbo? - Can I get archives on CD-ROM? - Where do I find program ? Section 10. Vendors and products - How can I contact Borland? - How can I contact Microsoft? - What is the current version of DJGPP? - What and where is DJGPP? - Are there any good shareware/freeware compilers? - Where is QBASIC? - What is a vendor's web site address? ------------------------------ Subject: Section 5. Disks and files Date: 5 Feb 2002 22:03:03 -0400 Information about accessing disks and files from MS-DOS. ------------------------------ Subject: - What drive was the PC booted from? Date: 5 Feb 2002 22:03:03 -0400 Under DOS 4.0 or later, use INT 21 AX=3305. DL is returned with an integer indicating the boot drive (1=A:, etc.). ------------------------------ Subject: - How can I boot from drive B:? Date: 8 Feb 2002 19:52:06 -0400 Downloadable shareware: 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] ------------------------------ Subject: - Which real and virtual disk drives are valid? Date: 5 Feb 2002 22:03:03 -0400 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: [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 #include 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 #include 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"); } } ------------------------------ Subject: - How can I make my single floppy drive both a: and b:? Date: 5 Feb 2002 22:03:03 -0400 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. ------------------------------ Subject: - How can I disable access to a drive? Date: 8 Feb 2002 19:53:23 -0400 Reader Eric DeVolder writes that he has made available a program to do this. I haven't tried it, but it's downloadable from 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 ------------------------------ Subject: - How can a batch file test existence of a directory? Date: 8 Feb 2002 19:54:04 -0400 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 ------------------------------ Subject: - Why won't my C program open a file with a path? Date: 5 Feb 2002 22:03:03 -0400 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. ------------------------------ Subject: - How can I redirect printer output to a file? Date: 8 Feb 2002 19:55:31 -0400 Recommended: PRN2FILE from PC Magazine, downloadable as: 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. ------------------------------ Subject: - How can I redirect the output of a batch file? Date: 7 Feb 2002 14:48:46 -0400 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: A reader of comp.os.msdos.programmer has created a utility that can capture batch file output. It can be found at: ------------------------------ Subject: - How can I redirect stderr? Date: 8 Feb 2002 19:58:21 -0400 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: A C example is downloadable as: 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: ------------------------------ Subject: - How can my program open more files than DOS's limit of 20? Date: 5 Feb 2002 22:03:03 -0400 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. ------------------------------ Subject: - How can I read, create, change, or delete the volume label? Date: 5 Feb 2002 22:03:03 -0400 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 traditional volume label is an entry with "volume label" attribute in the root directory of the disk. The DIR, VOL, and LABEL commands report this volume label, and LABEL sets it. * There is a second volume label, which may be different, in the boot record along with the serial number. In DOS 4.0 and later, INT 21 AH=69 gets or sets the boot record's serial number and volume label together; see [How can I get the disk serial number?] DIR and VOL ignore this volume label; the LABEL command doesn't report it but does set it. 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 ( for none): "); if (chars_got > 0) { DOS(extfcb,16h) printf(status ? "label failed\n" : "label created\n"); } } } // end function vollabel ------------------------------ Subject: - How can I get the disk serial number? Date: 5 Feb 2002 22:03:03 -0400 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 ( [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 [How can I read, create, change, or delete the volume label?] ------------------------------ Subject: - What's the format of .OBJ, .EXE., .COM files? Date: 5 Feb 2002 22:03:03 -0400 Please see [What's the format of an .OBJ file?]; [What's the format of an .EXE header?]; and [What's the difference between .COM and .EXE formats?] ------------------------------ Subject: - How can I flush the software disk cache? Date: 5 Feb 2002 22:03:03 -0400 Please see [How can a program reboot my PC?] (Trust me.) ------------------------------ Subject: - How can I see if a drive is a RAM drive? Date: 5 Feb 2002 22:03:03 -0400 Use INT 21 AX=4409h. See Ralph Brown's interrupt list ( [What and where is Ralf Brown's interrupt list?]) for more information. ------------------------------ Subject: - How can I determine a hard drive's manufacturer? Date: 5 Feb 2002 22:03:03 -0400 Information about the hard drive's manufacturer is retrieved by using the ATA and ATAPI specifications. Please see " [Where can I find information about the ATA/ATAPI specification?] ------------------------------ Subject: - Where can I find information about the ATA/ATAPI specification? Date: 5 Feb 2002 22:03:03 -0400 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 . At that web site the ATA and ATAPI specifications are availible in PDF form. ------------------------------ Subject: - How can I copy files to or from filenames containing date information? Date: 7 Feb 2002 14:26:15 -0400 You can use the NOWMINUS program. This program creates environment variables containing date and time information. See [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= ------------------------------ Subject: Section 6. Serial ports (COM ports) Date: 5 Feb 2002 22:03:03 -0400 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. ------------------------------ Subject: - How do I set my machine up to use COM3 and COM4? Date: 5 Feb 2002 22:03:03 -0400 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 ------------------------------ Subject: - How do I find the I/O address of a COM port? Date: 8 Feb 2002 20:00:09 -0400 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 [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: I haven't tried it myself, but a posted article reviewed it very favorably and said it also lets you swap ports around. ------------------------------ Subject: - But aren't the COM ports always at I/O addresses 3F8, 2F8, 3E8, and 2E8? Date: 5 Feb 2002 22:03:03 -0400 The first two are usually right (though not always); the last two are different on many machines. ------------------------------ Subject: - How do I configure a COM port and use it to transmit data? Date: 8 Feb 2002 20:03:52 -0400 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, (March 1993) is described as "Asynchronous communications library for C"; Garbo has a whole directory. Also, an extended example is in Borland's TechFax TI445, downloadable as part of: 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 [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: This directory contains a series of files beginning with Serial_Port. ------------------------------ Subject: Conclusion This is the end of part 3 of 5 parts. This text is copyright 2003 by Jeffrey Carlyle. All rights reserved. Please see the top of this article for additional copyright information.