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 <Q:01.14> [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
<Q:01.01> - Is MS-DOS Dead?
<Q:01.02> - What is this article for?
<Q:01.03> - Who has contributed to this article?
<Q:01.04> - How can I search this article for a particular topic?
<Q:01.05> - Are the answers guaranteed to be correct and complete?
<Q:01.06> - What is comp.os.msdos.programmer about?
<Q:01.07> - Is comp.os.msdos.programmer just for C programmers?
<Q:01.08> - What is comp.sys.ibm.pc.programmer?
<Q:01.09> - Is comp.os.msdos.programmer available as a mailing list?
<Q:01.10> - What's this netiquette?
<Q:01.11> - How can I learn more about Usenet?
<Q:01.12> - What other technical newsgroups should I know about?
<Q:01.13> - Where are FAQ lists archived?
<Q:01.14> - Where can I get the latest copy of this FAQ list?
Section 2. General Reference
<Q:02.01> - Are there any good on-line references for PC hardware
components?
<Q:02.02> - Are there any good on-line references for PC interrupts?
<Q:02.03> - What and where is Ralf Brown's interrupt list?
<Q:02.04> - Where can I find lex, yacc, and language grammars?
<Q:02.05> - What's the best book to learn programming?
<Q:02.06> - Why won't my code work?
<Q:02.07> - Are there any good sources of example code?
<Q:02.08> - What and where is SNIPPETS?
<Q:02.09> - Is the source code MS-DOS available?
<Q:02.10> - What are my alternatives for MS-DOS compatible OSes?
<Q:02.11> - What and where is FreeDOS?
<Q:02.12> - Where can I find out about batch files?
PART 2:
Section 3. Compile and link
<Q:03.01> - What the heck is DGROUP > 64K?
<Q:03.02> - How do I fix 'automatic data segment exceeds 64K' or 'stack
plus data exceed 64K'?
<Q:03.03> - Will Borland C code and Microsoft C code link together?
<Q:03.04> - Why did my program bomb at run time with 'floating point
formats not linked' or 'floating point not loaded'?
<Q:03.05> - How can I change the stack size in Borland's C compilers?
<Q:03.06> - What's the format of an .OBJ file?
<Q:03.07> - What's the format of an .EXE header?
<Q:03.08> - What's the difference between .COM and .EXE formats?
<Q:03.09> - How do I create a .COM file?
<Q:03.10> - Where is EXE2BIN located?
<Q:03.11> - What does this message mean: 'A20 already enabled so test
is meaning less?'
Section 4. Keyboard
<Q:04.01> - How can I read a character without echoing it to the
screen, and without waiting for the user to press the Enter
key?
<Q:04.02> - How can I find out whether a character has been typed,
without waiting for one?
<Q:04.03> - How can I disable Ctrl-C/Ctrl-Break and/or Ctrl-Alt-Del?
<Q:04.04> - How can I disable the print screen function?
<Q:04.05> - How can my program turn NumLock (CapsLock, ScrollLock) on
or off?
<Q:04.06> - How can I speed up the keyboard's auto-repeat?
<Q:04.07> - What is the SysRq key for?
<Q:04.08> - How can my program tell what kind of keyboard is on the
system?
<Q:04.09> - How can I tell if input, output, or stderr has been
redirected?
<Q:04.10> - How can I increase the size of the keyboard buffer?
<Q:04.11> - How can I stuff characters into the keyboard buffer?
PART 3: (this part)
Section 5. Disks and files
<Q:05.01> - What drive was the PC booted from?
<Q:05.02> - How can I boot from drive B:?
<Q:05.03> - Which real and virtual disk drives are valid?
<Q:05.04> - How can I make my single floppy drive both a: and b:?
<Q:05.05> - How can I disable access to a drive?
<Q:05.06> - How can a batch file test existence of a directory?
<Q:05.07> - Why won't my C program open a file with a path?
<Q:05.08> - How can I redirect printer output to a file?
<Q:05.09> - How can I redirect the output of a batch file?
<Q:05.10> - How can I redirect stderr?
<Q:05.11> - How can my program open more files than DOS's limit of 20?
<Q:05.12> - How can I read, create, change, or delete the volume label?
<Q:05.13> - How can I get the disk serial number?
<Q:05.14> - What's the format of .OBJ, .EXE., .COM files?
<Q:05.15> - How can I flush the software disk cache?
<Q:05.16> - How can I see if a drive is a RAM drive?
<Q:05.17> - How can I determine a hard drive's manufacturer?
<Q:05.18> - Where can I find information about the ATA/ATAPI
specification?
<Q:05.19> - How can I copy files to or from filenames containing date
information?
Section 6. Serial ports (COM ports)
<Q:06.01> - How do I set my machine up to use COM3 and COM4?
<Q:06.02> - How do I find the I/O address of a COM port?
<Q:06.03> - But aren't the COM ports always at I/O addresses 3F8, 2F8,
3E8, and 2E8?
<Q:06.04> - How do I configure a COM port and use it to transmit data?
PART 4:
Section 7. Other hardware questions and problems
<Q:07.01> - Which 80x86 CPU is running my program?
<Q:07.02> - How can a C program send control codes to my printer?
<Q:07.03> - How can I redirect printer output?
<Q:07.04> - Which video adapter is installed?
<Q:07.05> - How do I switch to 43- or 50-line mode?
<Q:07.06> - How can I find the Microsoft mouse position and button
status?
<Q:07.07> - How can I access a specific address in the PC's memory?
<Q:07.08> - How can I read or write my PC's CMOS memory?
<Q:07.09> - How can I access memory beyond 640K?
<Q:07.10> - How can I use the protected mode?
<Q:07.11> - How can I tell if my program is running on a PS/2-style
machine.
<Q:07.12> - Is there a 80x87 math unit installed?
<Q:07.13> - How can I power off the computer from a batch file?
Section 8. Other software questions and problems
<Q:08.01> - How can a program reboot my PC?
<Q:08.02> - How can I time events with finer resolution than the system
clock's 55 ms (about 18 ticks a second)?
<Q:08.03> - How can I find the error level of the previous program?
<Q:08.04> - How can a program set DOS environment variables?
<Q:08.05> - How can I change the switch character to - from /?
<Q:08.06> - How can I write a TSR (terminate-stay-resident utility)?
<Q:08.07> - Why does my interrupt function behave strangely?
<Q:08.08> - How can I write a device driver?
<Q:08.09> - What can I use to manage versions of software?
<Q:08.10> - What's this 'null pointer assignment' after my C program
executes?
<Q:08.11> - How can a batch file tell whether it's being run in a DOS
box under Windows?
<Q:08.12> - How can my program tell if it's running under Windows?
<Q:08.13> - How can a program tell whether ANSI.SYS is installed?
<Q:08.14> - How do I copyright software that I write?
<Q:08.15> - How can I place date and time information into environment
variables?
PART 5:
Section 9. Downloading
<Q:09.01> - What are SimTel and Garbo?
<Q:09.02> - Can I get archives on CD-ROM?
<Q:09.03> - Where do I find program <mumble>?
Section 10. Vendors and products
<Q:10.01> - How can I contact Borland?
<Q:10.02> - How can I contact Microsoft?
<Q:10.03> - What is the current version of DJGPP?
<Q:10.04> - What and where is DJGPP?
<Q:10.05> - Are there any good shareware/freeware compilers?
<Q:10.06> - Where is QBASIC?
<Q:10.07> - 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: <Q:05.01> - 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: <Q:05.02> - How can I boot from drive B:?
Date: 8 Feb 2002 19:52:06 -0400
Downloadable shareware: <http://www.simtel.net/pub/pd/44102.html>
<ftp://garbo.uwasa.fi/pc/bootutil/>
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: <Q:05.03> - 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:
<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");
}
}
Subject: <Q:05.04> - 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: <Q:05.05> - 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
<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
Subject: <Q:05.06> - 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 <ftp://garbo.uwasa.fi/pc/link/>
Subject: <Q:05.07> - 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: <Q:05.08> - How can I redirect printer output to a file?
Date: 8 Feb 2002 19:55:31 -0400
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.
Subject: <Q:05.09> - 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:
<ftp://garbo.uwasa.fi/pc/link/>
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>
Subject: <Q:05.10> - 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:
<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>
Subject: <Q:05.11> - 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: <Q:05.12> - 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 <Q:05.13> [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 (<Enter> for none): ");
if (chars_got > 0)
{
DOS(extfcb,16h)
printf(status ? "label failed\n" : "label created\n");
}
}
} // end function vollabel
Subject: <Q:05.13> - 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 (<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?]
Subject: <Q:05.14> - What's the format of .OBJ, .EXE., .COM files?
Date: 5 Feb 2002 22:03:03 -0400
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?]
Subject: <Q:05.15> - How can I flush the software disk cache?
Date: 5 Feb 2002 22:03:03 -0400
Please see <Q:08.01> [How can a program reboot my PC?] (Trust me.)
Subject: <Q:05.16> - 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 (<Q:02.03> [What
and where is Ralf Brown's interrupt list?]) for more information.
Subject: <Q:05.17> - 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 "<Q:05.18> [Where can I
find information about the ATA/ATAPI specification?]
Subject: <Q:05.18> - 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
<http://www.t13.org>. At that web site the ATA and ATAPI specifications
are availible in PDF form.
Subject: <Q:05.19> - 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 <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=
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: <Q:06.01> - 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: <Q:06.02> - 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 <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.
Subject: <Q:06.03> - 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: <Q:06.04> - 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,
<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/> 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.
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.
|
Comment about this article, ask questions, or add new information about this topic: