DOS 3.30 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

3520 lines
62 KiB

_ _ | | _ _
_ ______________
Random Read (Function 21H)
Call:
AH = 21H
DS:DX
Pointer to opened FCB
Return:
AL
0 = Read completed successfully
1 = End of file, record empty
2 = DTA too small
3 = End of file, partial record
Comments:
Function 21H reads (into the Disk Transfer Address) the record pointed to
by the Relative Record field (offset 20H) of the FCB. DX must contain the
offset (from the segment address in DS) of an opened FCB. The Current
Block field (offset 0CH) and Current Record field (offset 1FH) are set to
agree with the Relative Record field (offset 20H). The record is then loaded
at the Disk Transfer Address. The record length is taken from the Record
Size field (offset 0EH) of the FCB.
AL returns a code that describes the processing:
Code
Meaning
_ ________________________________________________________________
0 Read completed successfully
1 End-of-file; no data in the record
2 Not enough room at the Disk Transfer Address to read one record;
read canceled
3 End-of-file; a partial record was read and padded to the record
length with zeros
1
_ _ | | _ _
_ _ | | _ _
_ ______________
Macro Definition:
read_ran macro fcb
mov dx,offset fcb
mov ah,21H
int 21H
endm
Example:
The following program prompts for a letter, converts it to its alphabetic
sequence (A = 1, B = 2, etc.), then reads and displays the corresponding
record from a file named alphabet.dat that is on the disk in drive B. The
file contains 26 records, each 28 bytes long.
record_size equ 0EH ;offset of Record Size
;field of FCB
relative_record equ 21H ;offset of Relative Record
; field of FCB
fcb db 2,"ALPHABETDAT"
db 26 dup (?)
buffer db 28 dup(?),"$"
prompt db "Enter letter: $"
crlf db 0DH,0AH,"$"
;
begin: set_dta buffer ;see Function 1AH
open fcb ;see Function 0FH
mov fcb[record_size],28 ;set record size
get_char: display prompt ;see Function 09H
read_kbd_and_echo ;see Function 01H
cmp al,0DH ;just a CR?
je all_done ;yes, go home
sub al,41H ;convert ASCII code
;to record #
mov fcb[relative_record],al ;set relative
;record
display crlf ;see Function 09H
read_ran fcb ;THIS FUNCTION
display buffer ;see Function 09H
display crlf ;see Function 09H
jmp get_char ;get another char.
all_done: close fcb ;see Function 10H
2
_ _ | | _ _
_ _ | | _ _
_ ______________
Random Write (Function 22H)
Call:
AH = 22H
DS:DX
Pointer to opened FCB
Return:
AL
00H = Write completed successfully
01H = Disk full
02H = DTA too small
Comments:
Function 22H writes (from the Disk Transfer Address) the record pointed
to by the Relative Record field (offset 20H) of the FCB. DX must contain
the offset from the segment address in DS of an opened FCB. The Current
Block (offset 0CH) and Current Record (offset 1FH) fields are set to agree
with the Relative Record field (offset 20H). This record is then written
from the Disk Transfer Address.
The record length is taken from the Record Size field (offset 0EH) of the
FCB. If the record size is less than a sector, the data at the Disk Transfer
Address is written to a buffer, the buffer is written to disk when it contains
a full sector of data; or when a program closes the file, or when it issues
Function 0DH (Reset Disk).
AL returns a code that describes the processing:
Code
Meaning
_ ________________________________________________________________
0 Write completed successfully
1 Disk is full
2 Not enough room at the Disk Transfer Address to write one record;
write canceled
3
_ _ | | _ _
_ _ | | _ _
_ ______________
Macro Definition:
write_ran macro fcb
mov dx,offset fcb
mov ah,22H
int 21H
endm
Example:
The following program prompts for a letter, converts it to its alphabetic
sequence (A = 1, B = 2, etc.), then reads and displays the corresponding
record from a file named alphabet.dat that is on the disk in drive B. After
displaying the record, it prompts you to enter a changed record. If you
type a new record, it is written to the file, but if you just press the RETURN
key, the record is not replaced. The file contains 26 records, each 28 bytes
long.
record_size equ 0EH ;offset of Record Size
;field of FCB
relative_record equ 21H ;offset of Relative Record
; field of FCB
fcb db 2,"ALPHABETDAT"
db 26 dup (?)
buffer db 28 dup(?),0DH,0AH,"$"
prompt1 db "Enter letter: $"
prompt2 db "New record (RETURN for no change): $"
crlf db 0DH,0AH,"$"
reply db 28 dup (32)
blanks db 26 dup (32)
;
begin: set_dta buffer ;see Function 1AH
open fcb ;see Function 0FH
mov fcb[record_size],28 ;set record size
get_char: display prompt1 ;see Function 09H
read_kbd_and_echo ;see Function 01H
cmp al,0DH ;just a carriage return?
je all_done ;yes, go home
sub al,41H ;convert ASCII
;code to record #
mov fcb[relative_record],al
;set relative record
display crlf ;see Function 09H
read_ran fcb ;THIS FUNCTION
display buffer ;see Function 09H
display crlf ;see Function 09H
display prompt2 ;see Function 09H
get_string 27,reply ;see Function 0AH
display crlf ;see Function 09H
cmp reply[1],0 ;was anything typed
;besides CR?
je get_char ;no
;get another char.
4
_ _ | | _ _
_ _ | | _ _
_ ______________
xor bx,bx ;to load a byte
mov bl,reply[1] ;use reply length as
;counter
move_string blanks,buffer,26 ;see chapter end
move_string reply[2],buffer,bx ;see chapter end
write_ran fcb ;THIS FUNCTION
jmp get_char ;get another character
all_done: close fcb ;see Function 10H
5
_ _ | | _ _
_ _ | | _ _
_ ______________
Get File Size (Function 23H)
Call:
AH = 23H
DS:DX
Pointer to unopened FCB
Return:
AL
00H = Directory entry found
FFH = No directory entry found
Comments:
Function 23H returns the size of a specified file. DX must contain the
offset (from the segment address in DS) of an unopened FCB.
If there is a directory entry that matches the specified file, MS-DOS divides
the File Size field (offset 1CH) of the directory entry by the Record Size
field (offset 0EH) of the FCB, puts the result in the Relative Record field
(offset 20H) of the FCB, and returns 00 in AL.
You must set the Record Size field of the FCB to the correct value before
calling this function. If the Record Size field is not an even divisor of the
File Size field, the value set in the Relative Record field is rounded up,
yielding a value larger than the actual number of records.
If this call does not find a matching directory, AL returns FFH.
Macro Definition:
file_size macro fcb
mov dx,offset fcb
mov ah,23H
int 21H
endm
6
_ _ | | _ _
_ _ | | _ _
_ ______________
Example:
The following program prompts for the name of a file, opens the file to fill
in the Record Size field of the FCB, issues a File Size system call, and
displays the record length and number of records.
fcb db 37 dup (?)
prompt db "File name: $"
msg1 db "Record length: ",0DH,0AH,"$"
msg2 db "Records: ",0DH,0AH,"$"
crlf db 0DH,0AH,"$"
reply db 17 dup(?)
;
begin: display prompt ;see Function 09H
get_string 17,reply ;see Function 0AH
cmp reply[1],0 ;just a CR?
jne get_length ;no, keep going
jmp all_done ;yes, go home
get_length: display crlf ;see Function 09H
parse reply[2],fcb ;see Function 29H
open fcb ;see Function 0FH
file_size fcb ;THIS FUNCTION
mov ax,word ptr fcb[33] ;get record length
convert ax,10,msg2[9] ;see end of chapter
mov ax,word ptr fcb[14] ; get record number
convert ax,10,msg1[15] ;see end of chapter
display msg1 ;see Function 09H
display msg2 ;see Function 09H
all_done: close fcb ;see Function 10H
7
_ _ | | _ _
_ _ | | _ _
_ ______________
Set Relative Record (Function 24H)
Call:
AH = 24H
DS:DX
Pointer to opened FCB
Return:
None
Comments:
Function 24H sets the Relative Record field (offset 20H) to the file address
specified by the Current Block field (offset 0CH) and Current Record field
(offset 1FH). DX must contain the offset (from the segment address in DS)
of an opened FCB. You use this call to set the file pointer before a Ran-
dom Read or Write (Functions 21H, 22H, 27H, or 28H).
Macro Definition:
set_relative_record macro fcb
mov dx,offset fcb
mov ah,24H
int 21H
endm
Example:
The following program copies a file using the Random Block Read and
Random Block Write system calls. It speeds the copy by setting the record
length equal to the file size and the record count to 1, and by using a
buffer of 32K bytes. It positions the file pointer by setting the Current
Record field (offset 1FH) to 1 and using Function 24H (Set Relative
Record) to make the Relative Record field (offset 20H) point to the same
record that the combination of the Current Block field (offset 0CH) and
8
_ _ | | _ _
_ _ | | _ _
_ ______________
Current Record field (offset 1FH) points to.
current_record equ 20H ;offset of Current Record
;field of FCB
fil_size equ 10H ;offset of File Size
; field of FCB
fcb db 37 dup (?)
filename db 17 dup(?)
prompt1 db "File to copy: $" ;see Function 09H for
prompt2 db "Name of copy: $" ;explanation of $
crlf db 0DH,0AH,"$"
file_length dw ?
buffer db 32767 dup(?)
;
begin: set_dta buffer ;see Function 1AH
display prompt1 ;see Function 09H
get_string 15,filename ;see Function 0AH
display crlf ;see Function 09H
parse filename[2],fcb ;see Function 29H
open fcb ;see Function 0FH
mov fcb[current_record],0 ;set Current Record
;field
set_relative_record fcb ;THIS FUNCTION
mov ax,word ptr fcb[fil_size] ;get file size
mov file_length,ax ;save it for
;ran_block_write
ran_block_read fcb,1,ax ;see Function 27H
display prompt2 ;see Function 09H
get_string 15,filename ;see Function 0AH
display crlf ;see Function 09H
parse filename[2],fcb ;see Function 29H
create fcb ;see Function 16H
mov fcb[current_record],0 ;set Current Record
;field
set_relative_record fcb ;THIS FUNCTION
mov ax,file_length ;get original file
ran_block_write fcb,1,ax ;see Function 28H
close fcb ;see Function 10H
9
_ _ | | _ _
_ _ | | _ _
_ ______________
Set Interrupt Vector (Function 25H)
Call:
AH = 25H
AL
Interrupt number
DS:DX
Pointer to interrupt-handling
routine
Return:
None
Comments:
Function 25H sets the address in the interrupt vector table for the
specified interrupt.
AL must contain the number of the interrupt. DX must contain the offset
(to the segment address in DS) of the interrupt-handling routine.
To avoid compatibility problems, programs should never set an interrupt
vector directly and should never use Interrupt 25H to read directly from
memory. To get a vector, use Function 35H (Get Interrupt Vector), and to
set a vector, use Function 25H, unless your program must be compatible
with MS-DOS versions earlier than 2.0.
Macro Definition:
set_vector macro interrupt,handler_start
mov al,interrupt
mov dx,offset handler_start
mov ah,25H
endm
10
_ _ | | _ _
_ _ | | _ _
_ ______________
Example:
Because interrupts tend to be machine-specific, no example is shown.
11
_ _ | | _ _
_ _ | | _ _
_ ______________
Create New PSP (Function 26H)
Call:
AH = 26H
DX
Segment address of new PSP
Return:
None
Comments:
This function request has been superseded. Use Function 4BH (Load and
Execute Program) to run a child process, unless your program must be
compatible with MS-DOS versions earlier than 2.0.
Function 26H creates a new Program Segment Prefix. DX must contain the
segment address where the new PSP is to be created.
Macro Definition:
create_psp macro seg_addr
mov dx,seg_addr
mov ah,26H
endm
Example:
Because Function 4BH (Load and Execute Program) and 4B03H (Load
Overlay) have superseded this function request, no example is shown.
12
_ _ | | _ _
_ _ | | _ _
_ ______________
Random Block Read (Function 27H)
Call:
AH = 27H
DS:DX
Pointer to opened FCB
CX
Number of blocks to read
Return:
AL
0 = Read completed successfully
1 = End of file, empty record
2 = DTA too small
3 = End of file, partial record
CX
Number of blocks read
Comments:
Function 27H reads one or more records from a specified file to the Disk
Transfer Address. DX must contain the offset (to the segment address in
DS) of an opened FCB. CX must contain the number of records to read.
Reading starts at the record specified by the Relative Record field (offset
20H); you must set this field with Function 24H (Set Relative Record)
before calling this function.
DOS calculates the number of bytes to read by multiplying the value in
CX by the Record Size field (offset 0EH) of the FCB.
CX returns the number of records read. The Current Block field (offset
0CH), Current Record field (offset 1FH), and Relative Record field (offset
20H) are set to address the next record.
If you call this function with CX=0, no records are read.
AL returns a code that describes the processing:
Code
Meaning
_ ________________________________________________________________
0 Read completed successfully
13
_ _ | | _ _
_ _ | | _ _
_ ______________
1 End-of-file; no data in the record
2 Not enough room at the Disk Transfer Address to read one record;
read canceled
3 End-of-file; a partial record was read and padded to the record
length with zeros
Macro Definition:
ran_block_read macro fcb,count,rec_size
mov dx,offset fcb
mov cx,count
mov word ptr fcb[14],rec_size
mov ah,27H
int 21H
endm
Example:
The following program copies a file by using Function 27H (Random Block
Read). This program speeds the copy process by specifying a record count
of 1 and a record length equal to the file size, and by using a buffer of 32K
bytes; the file is read as a single record (compare to the sample program
for Function 28H that specifies a record length of 1 and a record count
equal to the file size).
current_record equ 20H ;offset of Current Record field
fil_size equ 10H ;offset of File Size field
;
fcb db 37 dup (?)
filename db 17 dup(?)
prompt1 db "File to copy: $" ;see Function 09H for
prompt2 db "Name of copy: $" ;explanation of $
crlf db 0DH,0AH,"$"
file_length dw ?
buffer db 32767 dup(?)
;
begin: set_dta buffer ;see Function 1AH
display prompt1 ;see Function 09H
get_string 15,filename ;see Function 0AH
display crlf ;see Function 09H
parse filename[2],fcb ;see Function 29H
open fcb ;see Function 0FH
mov fcb[current_record],0 ;set Current
;Record field
set_relative_record fcb ;see Function 24H
mov ax, word ptr fcb[fil_size]
;get file size
mov file_length,ax ;save it
ran_block_read fcb,1,ax ;THIS FUNCTION
display prompt2 ;see Function 09H
14
_ _ | | _ _
_ _ | | _ _
_ ______________
get_string 15,filename ;see Function 0AH
display crlf ;see Function 09H
parse filename[2],fcb ;see Function 29H
create fcb ;see Function 16H
mov fcb[current_record],0;set current
;Record field
set_relative_record fcb ;see Function 24H
ran_block_write fcb,1,ax ;see Function 28H
close fcb ;see Function 10H
15
_ _ | | _ _
_ _ | | _ _
_ ______________
Random Block Write (Function 28H)
Call:
AH = 28H
DS:DX
Pointer to opened FCB
CX
Number of blocks to write
(0 = set File Size field)
Return:
AL
00H = Write completed successfully
01H = Disk full
02H = End of segment
CX
Number of blocks written
Comments:
Function 28H writes one or more records to a specified file from the Disk
Transfer Address. DX must contain the offset (to the segment address in
DS) of an opened FCB; CX must contain either the number of records to
write or 0.
If CX is not 0, the specified number of records is written to the file, start-
ing at the record specified in the Relative Record field (offset 20H) of the
FCB. If CX is 0, no records are written, but MS-DOS sets the File Size
field (offset 1CH) of the directory entry to the value in the Relative Record
field (offset 20H) of the FCB. To satisfy this new file size, disk allocation
units are allocated or released, as required.
MS-DOS calculates the number of bytes to write by multiplying the value
in CX by the Record Size field (offset 0EH) of the FCB. CX returns the
number of records written; the Current Block field (offset 0CH), Current
Record field (offset 1FH), and Relative Record (offset 20H) field are set to
address the next record.
AL returns a code that describes the processing:
Code
Meaning
_ ________________________________________________________________
16
_ _ | | _ _
_ _ | | _ _
_ ______________
0 Write completed successfully
1 Disk full. No records written
2 Not enough room at the Disk Transfer Address to write one record;
write canceled
Macro Definition:
ran_block_write macro fcb,count,rec_size
mov dx,offset fcb
mov cx,count
mov word ptr fcb[14],rec_size
mov ah,28H
int 21H
endm
Example:
The following program copies a file using Function 27H (Random Block
Read) and Function 28H (Random Block Write). This program speeds the
copy process by specifying a record count equal to the file size and a record
length of 1, and by using a buffer of 32K bytes; the file is copied quickly
with one disk access each to read and write (compare to the sample pro-
gram of Function 27H, which specifies a record count of 1 and a record
length equal to file size).
current_record equ 20H ;offset of Current Record field
fil_size equ 10H ;offset of File Size field
;
fcb db 37 dup (?)
filename db 17 dup(?)
prompt1 db "File to copy: $" ;see Function 09H for
prompt2 db "Name of copy: $" ;explanation of $
crlf db 0DH,0AH,"$"
num_recs dw ?
buffer db 32767 dup(?)
;
begin: set_dta buffer ;see Function 1AH
display prompt1 ;see Function 09H
get_string 15,filename ;see Function 0AH
display crlf ;see Function 09H
parse filename[2],fcb ;see Function 29H
open fcb ;see Function 0FH
mov fcb[current_record],0;set Current
Record field
set_relative_record fcb ;see Function 24H
mov ax, word ptr fcb[fil_size]
;get file size
mov num_recs,ax ;save it
ran_block_read fcb,num_recs,1 ;THIS FUNCTION
display prompt2 ;see Function 09H
17
_ _ | | _ _
_ _ | | _ _
_ ______________
get_string 15,filename ;see Function 0AH
display crlf ;see Function 09H
parse filename[2],fcb ;see Function 29H
create fcb ;see Function 16H
mov fcb[current_record],0 ;set Current
;Record field
set_relative_record fcb ;see Function 24H
ran_block_write fcb,num_recs,1 ;see Function 28H
close fcb ;see Function 10H
18
_ _ | | _ _
_ _ | | _ _
_ ______________
Parse File Name (Function 29H)
Call:
AH = 29H
AL
Controls parsing (see text)
DS:SI
Pointer to string to parse
ES:DI
Pointer to buffer for unopened FCB
Return:
AL
00H = No wildcard characters
01H = Wildcard characters used
FFH = Drive letter invalid
DS:SI
Pointer to first byte past
string that was parsed
ES:DI
Pointer to unopened FCB
Comments:
Function 29H parses a string for a filename of the form
drive:filename.extension. SI must contain the offset (to the segment
address in DS) of the string to parse; DI must contain the offset (to the
segment address in ES) of an area of memory large enough to hold an uno-
pened FCB. If the string contains a valid filename, this call creates a
corresponding unopened FCB at ES:DI.
AL controls the parsing. Bits 4-7 must be 0; bits 0-3 have the following
meaning:
Table 0.1
Bit values for Function 29H
_ _________________________________________________________________________
Bit Value Meaning
_ _________________________________________________________________________
0 0 Stop parsing if a file separator is encountered.
1 Ignore leading separators.
1 0
Set the drive number in the FCB to 0 (current drive) if the string
does not contain a drive number.
19
_ _ | | _ _
_ _ | | _ _
_ ______________
1
Leave the drive number in the FCB unchanged if the string does
not contain a drive number.
2 0
Set the filename in the FCB to eight blanks if the string does not
contain a filename.
1
Leave the filename in the FCB unchanged if the string does not
contain a filename.
3 1
Leave the extension in the FCB unchanged if the string does not
contain an extension.
0
Set the extension in the FCB to three blanks if the string does not
contain an extension.
_ _________________________________________________________________________
If the string contains a filename or extension that includes an asterisk (*),
all remaining characters in the name or extension are set to question
marks (?).
Filename separators:
: ; . , = + / " [ ] \ < > | space tab
Filename terminators include all the filename separators, plus any control
character. A filename cannot contain a filename terminator, since if the
call encounters one, parsing stops.
If the string contains a valid filename:
o AL returns 1 if the filename or extension contains a wildcard char-
acter (* or ?); AL returns 0 if neither the filename nor extension
contains a wildcard character.
o DS:SI points to the first character following the parsed string.
o ES:DI points to the first byte of the unopened FCB.
If the drive letter is invalid, AL returns FFH. If the string does not contain
a valid filename, ES:DI+1 points to a blank.
Macro Definition:
parse macro string,fcb
mov si,offset string
mov di,offset fcb
push es
push ds
pop es
mov al,0FH ;bits 0-3 on
mov ah,29H
int 21H
20
_ _ | | _ _
_ _ | | _ _
_ ______________
pop es
endm
Example:
The following program verifies the existence of the file named in reply to
the prompt.
fcb db 37 dup (?)
prompt db "Filename: $"
reply db 17 dup(?)
yes db "File exists",0DH,0AH,"$"
no db "File does not exist",0DH,0AH,"$"
crlf db 0DH,0AH,"$"
;
begin: display prompt ;see Function 09H
get_string 15,reply ;see Function 0AH
parse reply[2],fcb ;THIS FUNCTION
display crlf ;see Function 09H
search_first fcb ;see Function 11H
cmp al,0FFH ;dir. entry found?
je not_there ;no
display yes ;see Function 09H
jmp return
not_there: display no
21
_ _ | | _ _
_ _ | | _ _
_ ______________
Get Date (Function 2AH)
Call:
AH = 2AH
Return:
CX
Year (1980-2099)
DH
Month (1-12)
DL
Day (1-31)
AL
Day of week (0=Sun., 6=Sat.)
Comments:
Function 2AH returns the current date set in the operating system as
binary numbers in CX and DX:
Register
Contents
_ ________________________________________________________________
CX Year (1980-2099)
DH Month (1=January, 2=February, etc.)
DL Day of month (1-31)
AL Day of week (0=Sunday, 1=Monday, etc.)
Macro Definition:
get_date macro
mov ah,2AH
int 21H
endm
22
_ _ | | _ _
_ _ | | _ _
_ ______________
Example:
The following program gets the date, increments the day, increments the
month or year, if necessary, and sets the new date.
month db 31,28,31,30,31,30,31,31,30,31,30,31
;
begin: get_date ;THIS FUNCTION
inc dl ;increment day
xor bx,bx ;so BL can be used as index
mov bl,dh ;move month to index register
dec bx ;month table starts with 0
cmp dl,month[bx] ;past end of month?
jle month_ok ;no, set new date
mov dl,1 ;yes, set day to 1
inc dh ;and increment month
cmp dh,12 ;past end of year?
jle month_ok ;no, set new date
mov dh,1 ;yes, set month to 1
inc cx ;increment year
month_ok: set_date cx,dh,dl ;see Function 2AH
23
_ _ | | _ _
_ _ | | _ _
_ ______________
Set Date (Function 2BH)
Call:
AH = 2BH
CX
Year (1980-2099)
DH
Month (1-12)
DL
Day (1-31)
Return:
AL
00H = Date was valid
FFH = Date was invalid
Comments:
Function 2BH sets the date in the operating system (and in the CMOS
clock, if one exists). Registers CX and DX must contain a valid date in
binary:
Register
Contents
_ ________________________________________________________________
CX Year (1980-2099)
DH Month (1=January, 2=February, etc.)
DL Day of month (1-31)
If the date is valid, the call sets it and AL returns 0. If the date is not
valid, the function aborts and AL returns FFH.
Macro Definition:
set_date macro year,month,day
mov cx,year
mov dh,month
mov dl,day
mov ah,2BH
int 21H
endm
24
_ _ | | _ _
_ _ | | _ _
_ ______________
Example:
The following program gets the date, increments the day, increments the
month or year, if necessary, and sets the new date.
month db 31,28,31,30,31,30,31,31,30,31,30,31
;
begin: get_date ;see Function 2AH
inc dl ;increment day
xor bx,bx ;so BL can be used as index
mov bl,dh ;move month to index register
dec bx ;month table starts with 0
cmp dl,month[bx] ;past end of month?
jle month_ok ;no, set the new date
mov dl,1 ;yes, set day to 1
inc dh ;and increment month
cmp dh,12 ;past end of year?
jle month_ok ;no, set the new date
mov dh,1 ;yes, set the month to 1
inc cx ;increment year
month_ok: set_date cx,dh,dl ;THIS FUNCTION
25
_ _ | | _ _
_ _ | | _ _
_ ______________
Get Time (Function 2CH)
Call:
AH = 2CH
Return:
CH
Hour (0-23)
CL
Minutes (0-59)
DH
Seconds (0-59)
DL
Hundredths (0-99)
Comments:
Function 2CH returns the current time set in the operating system (and
sets the CMOS clock, if one exists) as binary numbers in CX and DX:
Register
Contents
_ ________________________________________________________________
CH Hour (0-23)
CL Minutes (0-59)
DH Seconds (0-59)
DL Hundredths of a second (0-99)
Depending on how your hardware keeps time, some of these fields may be
irrelevant. As an example, many CMOS clock chips do not resolve more
than seconds. In such a case, the value in DL will probably always be 0.
Macro Definition:
get_time macro
mov ah,2CH
int 21H
endm
26
_ _ | | _ _
_ _ | | _ _
_ ______________
Example:
The following program displays the time continuously until you press any
key.
time db "00:00:00.00",0DH,"$"
;
begin: get_time ;THIS FUNCTION
byte_to_dec ch,time ;see end of chapter
byte_to_dec cl,time[3] ;see end of chapter
byte_to_dec dh,time[6] ;see end of chapter
byte_to_dec dl,time[9] ;see end of chapter
display time ;see Function 09H
check_kbd_status ;see Function 0BH
cmp al,0FFH ;has a key been pressed?
je return ;yes, terminate
jmp begin ;no, display time
27
_ _ | | _ _
_ _ | | _ _
_ ______________
Set Time (Function 2DH)
Call:
AH = 2DH
CH
Hour (0-23)
CL
Minutes (0-59)
DH
Seconds (0-59)
DL
Hundredths (0-99)
Return:
AL
00H = Time was valid
FFH = Time was invalid
Comments:
Function 2DH sets the time in the operating system. Registers CX and DX
must contain a valid time in binary:
Register
Contents
_ ________________________________________________________________
CH Hour (0-23)
CL Minutes (0-59)
DH Seconds (0-59)
DL Hundredths of a second (0-99)
Depending on how your hardware keeps time, some of these fields may be
irrelevant. As an example, many CMOS clock chips do not resolve more
than seconds. In such a case, the value in DL will not be relevant.
If the time is valid, the call sets it and AL returns 0. If the time is not
valid, the function aborts and AL returns FFH.
28
_ _ | | _ _
_ _ | | _ _
_ ______________
Macro Definition:
set_time macro hour,minutes,seconds,hundredths
mov ch,hour
mov cl,minutes
mov dh,seconds
mov dl,hundredths
mov ah,2DH
int 21H
endm
Example:
The following program sets the system clock to 0 and displays the time
continuously. When you type a character, the display freezes; when you
type another character, the clock is reset to 0 and the display starts again.
time db "00:00:00.00",0DH,0AH,"$"
;
begin: set_time 0,0,0,0 ;THIS FUNCTION
read_clock: get_time ;see Function 2CH
byte_to_dec ch,time ;see end of chapter
byte_to_dec cl,time[3] ;see end of chapter
byte_to_dec dh,time[6] ;see end of chapter
byte_to_dec dl,time[9] ;see end of chapter
display time ;see Function 09H
dir_console_io 0FFH ;see Function 06H
cmp al,00H ;was a char. typed?
jne stop ;yes, stop the timer
jmp read_clock ;no keep timer on
stop: read_kbd ;see Function 08H
jmp begin ;keep displaying time
29
_ _ | | _ _
_ _ | | _ _
_ ______________
Set/Reset Verify Flag (Function 2EH)
Call:
AH = 2EH
AL
0 = Do not verify
1 = Verify
Return:
None
Comments:
Function 2EH tells MS-DOS whether to verify each disk write. If AL is 1,
verify is on; if AL is 0, verify is off. MS-DOS checks this flag each time it
writes to a disk.
The flag is normally off; you may wish to turn it on when writing critical
data to disk. Because disk errors are rare and verification slows writing,
you will probably want to leave it off at other times. You can check the
setting with Function 54H (Get Verify State).
Macro Definition:
verify macro switch
mov al,switch
mov ah,2EH
int 21H
endm
30
_ _ | | _ _
_ _ | | _ _
_ ______________
Example:
The following program copies the contents of a single-sided disk in drive A
to the disk in drive B, verifying each write. It uses a buffer of 32K bytes.
on equ 1
off equ 0
;
prompt db "Source in A, target in B",0DH,0AH
db "Any key to start. $"
first dw 0
buffer db 60 dup (512 dup(?)) ;60 sectors
;
begin: display prompt ;see Function 09H
read_kbd ;see Function 08H
verify on ;THIS FUNCTION
mov cx,6 ;copy 60 sectors
;6 times
copy: push cx ;save counter
abs_disk_read 0,buffer,60,first ;see Int 25H
abs_disk_write 1,buffer,64,first ;see Int 26H
add first,60 ;do next 60 sectors
pop cx ;restore counter
loop copy ;do it again
verify off ;THIS FUNCTION
31
_ _ | | _ _
_ _ | | _ _
_ ______________
Get Disk Transfer Address (Function 2FH)
Call:
AH = 2FH
Return:
ES:BX
Pointer to Disk Transfer Address
Comments:
Function 2FH returns the segment address of the current Disk Transfer
Address in ES and the offset in BX.
Macro Definition:
get_dta macro
mov ah,2fH
int 21H
endm
Example:
The following program displays the current Disk Transfer Address in the
form: segment:offset.
message db "DTA -- : ",0DH,0AH,"$"
sixteen db 10H
temp db 2 dup (?)
;
begin: get_dta ;THIS FUNCTION
mov word ptr temp,ex ;To access each byte
convert temp[1],sixteen,message[07H] ;See end of
convert temp,sixteen,message[09H] ;chapter for
32
_ _ | | _ _
_ _ | | _ _
_ ______________
convert bh,sixteen,message[0CH] ;description
convert bl,sixteen,message[0EH] ;of CONVERT
display message ;See Function 09H
33
_ _ | | _ _
_ _ | | _ _
_ ______________
Get MS-DOS Version Number (Function 30H)
Call:
AH = 30H
Return:
AL
Major version number
AH
Minor version number
BH
OEM serial number
BL:CX
24-bit user (serial) number
Comments:
Function 30H returns the MS-DOS version number. AL returns the major
version number; AH returns the minor version number. (For example,
MS-DOS 3.0 returns 3 in AL and 0 in AH.)
If AL returns 0, the MS-DOS version is earlier than 2.0.
Macro Definition:
get_version macro
mov ah,30H
int 21H
endm
Example:
The following program displays the MS-DOS version if it is 1.28 or
greater.
message db "MS-DOS Version . ",0DH,0AH,"$"
ten db 0AH ;For CONVERT
;
begin: get_version ;THIS FUNCTION
cmp al,0 ;1.28 or later?
34
_ _ | | _ _
_ _ | | _ _
_ ______________
jng return ;No, go home
convert al,ten,message[0FH] ;See end of chapter
convert ah,ten,message[12H] ;for description
display message ;See Function 9
35
_ _ | | _ _
_ _ | | _ _
_ ______________
Keep Process (Function 31H)
Call:
AH = 31H
AL
Return code
DX
Memory size, in paragraphs
Return:
None
Comments:
Function 31H makes a program remain resident after it terminates. You
can use it to install device-specific interrupt handlers. But unlike Interrupt
27H (Terminate But Stay Resident), this function request allows more
than 64K bytes to remain resident and does not require CS to contain the
segment address of the Program Segment Prefix. You should use Function
31H to install a resident program unless your program must be compatible
with MS-DOS versions earlier than 2.0.
DX must contain the number of paragraphs of memory required by the
program (one paragraph = 16 bytes). AL contains an exit code.
Be careful when using this function with .exe programs. The value in DX
must be the total size to remain resident, not just the size of the code seg-
ment which is to remain resident. A typical error is to forget about the
100H-byte program-header-prefix and give a value in DX that is 10H too
small.
MS-DOS terminates the current process and tries to set the memory allo-
cation to the number of paragraphs in DX. No other allocation blocks
belonging to the process are released.
36
_ _ | | _ _
_ _ | | _ _
_ ______________
By using Function 4DH (Get Return Code of Child Process), the parent
process can retrieve the process's exit code from AL. (You can test this
exit code by using the if command with errorlevel.)
Macro Definition:
keep_process macro return_code,last_byte
mov al,return_code
mov dx,offset last_byte
mov cl,4
shr dx,cl
inc dx
mov ah,31H
int 21H
endm
Example:
Because the most common use of this call is to install a machine-specific
routine, an example is not shown. The macro definition, however, shows
the calling syntax.
37
_ _ | | _ _
_ _ | | _ _
_ ______________
CONTROL-C Check (Function 33H)
Call:
AH = 33H
AL
0 = Get state
1 = Set state
DL (if AL=1)
0 = Off
1 = On
Return:
DL (if AL=0)
0 = Off
1 = On
AL
FFH = error (AL was neither 0 nor 1
when call was made)
Comments:
Function 33H gets or sets the state of CONTROL-C (or CONTROL-BREAK for
IBM compatibles) checking in MS-DOS. AL must contain a code that
specifies the requested action:
Code
Meaning
_ ________________________________________________________________
0 Current state of CONTROL-C checking in DL
1 Set state of CONTROL-C checking to the value in DL
If AL is 0, DL returns the current state (0=off, 1=on). If AL is 1, the value
in DL specifies the state to be set (0=off, 1=on). If AL is neither 0 nor 1,
AL returns FFH and the state of CONTROL-C checking is unaffected.
MS-DOS normally checks for CONTROL-C only when carrying out certain
function requests in the 01H through 0CH group (see the description of
specific calls for details). When CONTROL-C checking is on, MS-DOS checks
for CONTROL-C when carrying out any function request. For example, if
CONTROL-C checking is off, all disk I/O proceeds without interruption, but
if it is on, the CONTROL-C interrupt is issued at the function request that
initiates the disk operation.
_ ________________________________________________________________
Note
38
_ _ | | _ _
_ _ | | _ _
_ ______________
Programs that use Function 06H (Direct Console I/O) or 07H (Direct
Console Input) to read CONTROL-C as data must ensure that the
CONTROL-C checking is off.
_ ________________________________________________________________
Macro Definition:
ctrl_c_ck macro action,state
mov al,action
mov dl,state
mov ah,33H
int 21H
endm
Example:
The following program displays a message that tells whether CONTROL-C
checking is on or off:
message db "CONTROL-C checking ","$"
on db "on","$",0DH,0AH,"$"
off db "off","$",0DH,0AH,"$"
;
begin: display message ;See Function 09H
ctrl_c_ck 0 ;THIS FUNCTION
cmp dl,0 ;Is checking off?
jg ck_on ;No
display off ;See Function 09H
jmp return ;Go home
ck_on: display on ;See Function 09H
39
_ _ | | _ _
_ _ | | _ _
_ ______________
Get Interrupt Vector (Function 35H)
Call:
AH = 35H
AL
Interrupt number
Return:
ES:BX
Pointer to interrupt routine
Comments:
Function 35H gets the address from the interrupt-vector table for the
specified interrupt. AL must contain the number of an interrupt.
ES returns the segment address of the interrupt handler; BX returns the
offset.
To avoid compatibility problems, programs should never read an interrupt
vector directly from memory, nor set an interrupt vector by writing it into
memory. Use this function request to get a vector and Function 25H (Set
Interrupt Vector) to set a vector, unless your program must be compatible
with MS-DOS versions earlier than 2.0.
Macro Definition:
get_vector macro interrupt
mov al,interrupt
mov ah,35H
int 21H
endm
40
_ _ | | _ _
_ _ | | _ _
_ ______________
Example:
The following program displays the segment and offset (CS:IP) for the
handler for Interrupt 25H (Absolute Disk Read).
message db "Interrupt 25H -- CS:0000 IP:0000"
db 0DH,0AH,"$"
vec_seg db 2 dup (?)
vec_off db 2 dup (?)
;
begin: push es ;save ES
get_vector 25H ;THIS FUNCTION
mov ax,es ;INT25H segment in AX
pop es ;save ES
convert ax,16,message[20] ;see end of chapter
convert bx,16,message[28] ;see end of chapter
display message ;See Function 9
41
_ _ | | _ _
_ _ | | _ _
_ ______________
Get Disk Free Space (Function 36H)
Call:
AH = 36H
DL
Drive (0=default, 1=A, etc.)
Return:
AX
0FFFFH if drive number is invalid;
otherwise, sectors per cluster
BX
Available clusters
CX
Bytes per sector
DX
Clusters per drive
Comments:
Function 36H returns the number of clusters available on the disk in the
specified drive, and the information necessary to calculate the number of
bytes available on the disk. DL must contain a drive number (0=default,
1=A, etc.). If the drive number is valid, MS-DOS returns the information
in the following registers:
Register
Contents
_ ________________________________________________________________
AX Sectors per cluster
BX Available clusters
CX Bytes per sector
DX Total clusters
If the drive number is invalid, AX returns 0FFFFH.
This call supersedes Functions 1BH and 1CH in earlier MS-DOS versions.
42
_ _ | | _ _
_ _ | | _ _
_ ______________
Macro Definition:
get_disk_space macro drive
mov dl,drive
mov ah,36H
int 21H
endm
Example:
The following program displays the space information for the disk in drive
B.
message db " clusters on drive B.",0DH,0AH ;DX
db " clusters available.",0DH,0AH ;BX
db " sectors per cluster.",0DH,0AH ;AX
db " bytes per sector,",0DH,0AH,"$" ;CX
;
begin: get_disk_space 2 ;THIS FUNCTION
convert ax,10,message[55] ;see end of chapter
convert bx,10,message[28] ;see end of chapter
convert cx,10,message[83] ;see end of chapter
convert dx,10,message ;see end of chapter
display message ;See Function 09H
43
_ _ | | _ _
_ _ | | _ _
_ ______________
Get Country Data (Function 38H)
Call:
AH = 38H
AL
00H = Current country
1-0FEH = Country code
0FFH = BX contains country code
BX (if AL = 0FFH)
Country code 255 or higher
DS:DX
Pointer to 32-byte memory area
Return:
Carry set:
AX
2 = Invalid country code
Carry not set:
BX
Country code
Comments:
Function 38H gets the country-dependent information that MS-DOS uses
to control the keyboard and display, or it sets the currently defined coun-
try (to set the country code, see the next function request description, Set
Country Data). To get the information, DX must contain the offset (from
the segment address in DS) of a 32-byte memory area to which the country
data returns. AL specifies the country code:
Value in AL
Meaning
_ ________________________________________________________________
00H Retrieve information about the country currently set.
1 to 0FEH Retrieve information about the country identified by this
code.
0FFH Retrieve information about the country identified by the
code in BX.
BX must contain the country code if the code is 255 or greater. The coun-
try code is usually the international telephone-prefix code.
44
_ _ | | _ _
_ _ | | _ _
_ ______________
The country-dependent information returns in the following form:
Offset
Hex Decimal Field Name Length in bytes
_ ________________________________________________________________
00H 0 Date format 2 (word)
02H 2 Currency symbol 5 (ASCIZ string)
07H 7 Thousands separator 2 (ASCIZ string)
09H 9 Decimal separator 2 (ASCIZ string)
0BH 11 Date separator 2 (ASCIZ string)
0DH 13 Time separator 2 (ASCIZ string)
0FH 15 Bit field 1
10H 16 Currency places 1
11H 17 Time format 1
12H 18 Case-map call address 4 (DWORD)
16H 22 Data-list separator 2 (ASCIZ string)
18H 24 Reserved 10
_ ________________________________________________________________
Date Format:
0 = USA (month/day/year)
1 = Europe (day/month/year)
2 = Japan (year/month/day)
Bit Field:
Bit Value Meaning
_ ________________________________________________________________
0 0 Currency symbol precedes amount
1 Currency symbol follows amount
1 0 No space between symbol and amount
1 One space between symbol and amount
_ ________________________________________________________________
All other bits are undefined.
Time format:
0 = 12-hour clock
1 = 24-hour clock
Currency Places:
45
_ _ | | _ _
_ _ | | _ _
_ ______________
Specifies the number of places that appear after the decimal point on
currency amounts.
Case-Mapping Call Address:
Specifies the segment and offset of a FAR procedure that performs
country-specific lowercase-to-uppercase mapping on character values from
80H to 0FFH. You call it with the character to be mapped in AL. If there
is an uppercase code for the character, it is returned in AL; if there is not,
or if you call it with a value less than 80H in AL, AL returns unchanged.
AL and the FLAGS are the only altered registers.
If there is an error, the carry flag (CF) is set and the error code returns in
AX:
Code
Meaning
_ ________________________________________________________________
2 Invalid country code (no table for it).
Macro Definition:
get_country macro country,buffer
local gc_01
mov dx,offset buffer
mov ax,country
cmp ax,OFFH
jl gc_01
mov al,OFFh
mov bx,country
gc_01: mov ah,38h
int 21H
endm
Example:
The following program displays the time and date in the format appropri-
ate to the current country code, and the number 999,999 and 99/100 as a
currency amount with the proper currency symbol and separators.
time db " : : ",5 dup (20H),"$"
date db " / / ",5 dup (20H),"$"
number db "999?999?99",0DH,0AH,"$"
data_area db 32 dup (?)
;
begin: get_country 0,data_area ;THIS FUNCTION
get_time ;See Function 2CH
byte_to_dec ch,time ;See end of chapter
byte_to_dec cl,time[03H] ;for description of
byte_to_dec dh,time[06H] ;CONVERT macro
get_date ;See Function 2AH
46
_ _ | | _ _
_ _ | | _ _
_ ______________
sub cx,1900 ;Want last 2 digits
byte_to_dec cl,date[06H] ;See end of chapter
cmp word ptr data_area,0 ;Check country code
jne not_usa ;It's not USA
byte_to_dec dh,date ;See end of chapter
byte_to_dec dl,date[03H] ;See end of chapter
jmp all_done ;Display data
not_usa: byte_to_dec dl,date ;See end of chapter
byte_to_dec dh,date[03H] ;See end of chapter
all_done: mov al,data_area[07H] ;Thousand separator
mov number[03H],al ;Put in NUMBER
mov al,data_area[09H] ;Decimal separator
mov number[07H],al ;Put in AMOUNT
display time ;See Function 09H
display date ;See Function 09H
display_char data_area[02H] ;See Function 02H
display number ;See Function 09H
47
_ _ | | _ _
_ _ | | _ _
_ ______________
Set Country Data (Function 38H)
Call:
AH = 38H
DX = -1 (0FFFFH)
AL
Country code less than 255, or
0FFH if the country code is in BX
BX (if AL=0FFH)
Country code 255 or higher
Return:
Carry set:
AX
2 = Invalid country code
Carry not set:
No error
Comments:
Function 38H sets the country code that MS-DOS uses to control the key-
board and the display, or it retrieves the country-dependent information
(to get the country data, see the previous function request description, Get
Country Data). To set the information, DX must contain 0FFFFH. AL
must contain either the country code, if it is less than 255, or 255 to indi-
cate that the country code is in BX. If AL contains 0FFH, BX must con-
tain the country code.
The country code is usually the international telephone prefix-code. See
"Get Country Data" for a description of the country data and how it is
used.
If there is an error, the carry flag (CF) is set and the error code returns in
AX:
Code
Meaning
_ ________________________________________________________________
2 Invalid country code (no table for it).
48
_ _ | | _ _
_ _ | | _ _
_ ______________
Macro Definition:
set_country macro country
local sc_01
mov dx,0FFFFH
mov ax,country
cmp ax,0FFH
jl sc_01
mov bx,country
mov al,0ffh
sc_01: mov ah,38H
int 21H
endm
Example:
The following program sets the country code to the United Kingdom (44).
uk equ 44
;
begin: set_country uk ;THIS FUNCTION
jc error ;routine not shown
49
_ _ | | _ _
_ _ | | _ _
_ ______________
Create Directory (Function 39H)
Call:
AH = 39H
DS:DX
Pointer to pathname
Return:
Carry set:
AX
2 = File not found
3 = Path not found
5 = Access denied
Carry not set:
No error
Comments:
Function 39H creates a new subdirectory. DX must contain the offset
(from the segment address in DS) of an ASCIZ string that specifies the path-
name of the new subdirectory.
If there is an error, the carry flag (CF) is set and the error code returns in
AX:
Code
Meaning
_ ________________________________________________________________
2 File not found
3 Path not found
5 No room in the parent directory, a file with the same name exists
in the current directory, or the path specifies a device
Macro Definition:
make_dir macro path
mov dx,offset path
mov ah,39H
int 21H
endm
50
_ _ | | _ _
_ _ | | _ _
_ ______________
Example:
The following program adds a subdirectory named new_dir to the root
directory on the disk in drive B and changes the current directory to
new_dir. The program then changes the current directory back to the ori-
ginal directory and then deletes new_dir. It displays the current directory
after each step to confirm the changes.
old_path db "b:
new_path db "b:\new_dir",0
buffer db "b:
;
begin: get_dir 2,old_path[03H] ;See Function 47H
jc error_get ;Routine not shown
display_asciz old_path ;See end of chapter
make_dir new_path ;THIS FUNCTION
jc error_make ;Routine not shown
change_dir new_path ;See Function 3BH
jc error_change ;Routine not shown
get_dir 2,buffer[03H] ;See Function 47H
jc error_get ;Routine not shown
display_asciz buffer ;See end of chapter
change_dir old_path ;See Function 3BH
jc error_change ;Routine not shown
rem_dir new_path ;See Function 3AH
jc error_rem ;Routine not shown
get_dir 2,buffer[03H] ;See Function 47H
jc error_get ;Routine not shown
display_asciz buffer ;See end of chapter
51
_ _ | | _ _
_ _ | | _ _
_ ______________
Remove Directory (Function 3AH)
Call:
AH = 3AH
DS:DX
Pointer to pathname
Return:
Carry set:
AX
2 = File not found
3 = Path not found
5 = Access denied
16 = Current directory
Carry not set:
No error
Comments:
Function 3AH deletes a subdirectory. DX must contain the offset (from the
segment address in DS) of an ASCIZ string that specifies the pathname of
the subdirectory you want to delete.
The subdirectory must not contain any files. You cannot erase the current
directory. If there is an error, the carry flag (CF) is set and the error code
returns in AX:
Code
Meaning
_ ________________________________________________________________
2 File not found
3 Path not found
5 Directory not empty, or path doesn't specify a directory, or it
specifies the root directory, or it is invalid
16 Path specifies current directory
52
_ _ | | _ _
_ _ | | _ _
_ ______________
Macro Definition:
rem_dir macro path
mov dx,offset path
mov ah,3AH
int 21H
endm
Example:
The following program adds a subdirectory named new_dir to the root
directory on the disk in drive B and changes the current directory to
new_dir. The program then changes the current directory back to the ori-
ginal directory and deletes new_dir. It displays the current directory after
each step to confirm the changes.
old_path db "b:
new_path db "b:\new_dir",0
buffer db "b:
;
begin: get_dir 2,old_path[03H] ;See Function 47H
jc error_get ;Routine not shown
display_asciz old_path ;See end of chapter
make_dir new_path ;See Function 39H
jc error_make ;Routine not shown
change_dir new_path ;See Function 3BH
jc error_change ;Routine not shown
get_dir 2,buffer[03H] ;See Function 47H
jc error_get ;Routine not shown
display_asciz buffer ;See end of chapter
change_dir old_path ;See Function 3BH
jc error_change ;Routine not shown
rem_dir new_path ;THIS FUNCTION
jc error_rem ;Routine not shown
get_dir 2,buffer[03H] ;See Function 47H
jc error_get ;Routine not shown
display_asciz buffer ;See end of chapter
53
_ _ | | _ _
_ _ | | _ _
_ ______________
Change Current Directory (Function 3BH)
Call:
AH = 3BH
DS:DX
Pointer to pathname
Return:
Carry set:
AX
2 = File not found
3 = Path not found
Carry not set:
No error
Comments:
Function 3BH changes the current directory. DX must contain the offset
(from the segment address in DS) of an ASCIZ string that specifies the path-
name of the new current directory.
The directory string is limited to 64 characters.
If any member of the path doesn't exist, the path is unchanged. If there is
an error, the carry flag (CF) is set and the error code returns in AX:
Code
Meaning
_ ________________________________________________________________
2 File not found
3 Path either doesn't exist or it specifies a file instead of a directory
Macro Definition:
change_dir macro path
mov dx,offset path
mov ah,3BH
int 21H
endm
54
_ _ | | _ _
_ _ | | _ _
_ ______________
Example:
The following program adds a subdirectory named new_dir to the root
directory that is on the disk in drive B and changes the current directory
to new_dir. The program then changes the current directory back to the
original directory and deletes new_dir. It displays the current directory
after each step to confirm the changes.
old_path db "b:
new_path db "b:\new_dir",0
buffer db "b:
;
begin: get_dir 2,old_path[03H] ;See Function 47H
jc error_get ;Routine not shown
display_asciz old_path ;See end of chapter
make_dir new_path ;See Function 39H
jc error_make ;Routine not shown
change_dir new_path ;THIS FUNCTION
jc error_change ;Routine not shown
get_dir 2,buffer[03H] ;See Function 47H
jc error_get ;Routine not shown
display_asciz buffer ;See end of chapter
change_dir old_path ;See Function 3BH
jc error_change ;Routine not shown
rem_dir new_path ;See Function 3AH
jc error_rem ;Routine not shown
get_dir 2,buffer[03H] ;See Function 47H
jc error_get ;Routine not shown
display_asciz buffer ;See end of chapter
55
_ _ | | _ _
_ _ | | _ _
_ ______________
Create Handle (Function 3CH)
Call:
AH = 3CH
DS:DX
Pointer to pathname
CX
File attribute
Return:
Carry set:
AX
2 = File not found
3 = Path not found
4 = Too many open files
5 = Access denied
Carry not set:
AX
Handle
Comments:
Function 3CH creates a file and assigns it the first available handle. DX
must contain the offset (from the segment address in DS) of an ASCIZ string
that specifies the pathname of the file to be created. CX must contain the
attribute to be assigned to the file, as described under "File Attributes"
earlier in this chapter.
If the specified file does not exist, this function creates it. But if the file
already exists, it is truncated to a length of 0. Function 3CH then assigns
the attribute in CX to the file and opens it for read/write. AX returns the
file handle.
If there is an error, the carry flag (CF) is set and the error code returns in
AX:
Code
Meaning
_ ________________________________________________________________
2 File not found
3 Path is invalid
4 Too many open files (no handle available)
5 Directory is full, a directory with the same name exists, or a file
with the same name exists with more restrictive attributes
56
_ _ | | _ _
_ _ | | _ _
_ ______________
Macro Definition:
create_handle macro path,attrib
mov dx,offset path
mov cx,attrib
mov ah,3CH
int 21H
endm
Example:
The following program creates a file named dir.tmp, containing the name
and extension of each file in the current directory, on the disk in drive B.
srch_file db "b:*.*",0
tmp_file db "b:dir.tmp",0
buffer db 43 dup (?)
handle dw ?
;
begin: set_dta buffer ;See Function 1AH
find_first_file srch_file,16H ;See Function 4EH
cmp ax,12H ;Directory empty?
je all_done ;Yes, go home
create_handle tmp_file,0 ;THIS FUNCTION
jc error ;Routine not shown
mov handle,ax ;Save handle
write_it: write_handle handle,buffer[1EH],12 ;Function 40H
find_next_file ;See Function 4FH
cmp ax,12H ;Another entry?
je all_done ;No, go home
jmp write_it ;Yes, write record
all_done: close_handle handle ;See Function 3EH
57
_ _ | | _ _
_ _ | | _ _
_ ______________
Open Handle (Function 3DH)
Call:
AH = 3DH
AL
Access code (see text)
DS:DX
Pointer to pathname
Return:
Carry set:
AX
2 = File not found
3 = Path not found
4 = Too many open files
5 = Access denied
12 = Invalid access
Carry not set:
No error
Comments:
Function 3DH opens any file, including hidden and system files, for input
or output. DX contains the offset (from the segment address in DS) of an
ASCIZ string that specifies the pathname of the file to be opened. AL con-
tains a code that specifies how the file is to be opened. This code is
described later under "Controlling Access to the File."
If there is no error, AX returns the file handle. MS-DOS sets the read/write
pointer to the first byte of the file.
58
_ _ | | _ _
_ _ | | _ _
_ ______________
Controlling Access to the File
The value in AL is made up of three parts that specify whether the file is
to be opened for read, write, or both (access code); what access other
processes have to the file (sharing mode); and whether a child process
inherits the file (inherit bit).
|---|-----------|---------------|
Bit | 7 | 6 5 4 | 3 2 1 0 |
|---|---|---|---|---|---|---|---|
\/ \________/ \____________/
| | |
| | |--------> Access code
| |
| |-----------------------> Sharing mode
|
|-------------------------------> Inherit bit
Inherit Bit The high-order bit (bit 7) specifies whether the file is inherited
by a child process created with Function 4BH (Load and Execute Pro-
gram). If the bit is 0, the child process inherits the file; if the bit is 1, it
doesn't.
59
_ _ | | _ _
_ _ | | _ _
_ ______________
Sharing Mode
The sharing mode bits (bits 4-6) specify what access, if any, other
processes have to the open file. It can have the following values:
Table 0.2
Sharing Mode Bit Values
_ _________________________________________________________________________
Bits 4-6 Sharing Mode Description
_ _________________________________________________________________________
000 Compatibility
On a given machine, any process can open the file
any number of times with this mode. Fails if the file
has been opened with any of the other sharing
modes.
001 Deny both
Fails if the file has been opened in compatibility
mode or for read or write access, even if by the
current process.
010 Deny write
Fails if the file has been opened in compatibility
mode or for write access by any other process.
011 Deny read
Fails if the file has been opened in compatibility
mode or for read access by any other process.
100 Deny none
Fails if the file has been opened in compatibility
mode by any other process.
_ _________________________________________________________________________
60
_ _ | | _ _
_ _ | | _ _
_ ______________
Access Code
The access code (bits 0-3) specifies how the file is to be used. It can have
the following values:
Table 0.3
Access Code Bit Values
_ _________________________________________________________________________
Access
Bits 0-3 Allowed Description
_ _________________________________________________________________________
0000 Read
Fails if the file has been opened in deny read or deny both
sharing mode.
0001 Write
Fails if the file has been opened in deny write or deny both
sharing mode.
0010 Both
Fails if the file has been opened in deny read, deny write, or
deny both sharing mode.
_ _________________________________________________________________________
If there is an error, the carry flag (CF) is set and the error code is returned
in AX:
Code
Meaning
_ ________________________________________________________________
2 Specified file is invalid or doesn't exist
3 Specified path is invalid or doesn't exist
4 No handles are available in the current process or the internal sys-
tem tables are full
5 Program attempted to open a directory or VolumeID, or tried to
open a read-only file for writing
12 Access code (bits 0-3 of AL) not 0, 1, or 2
If this system call fails because of a file-sharing error, MS-DOS issues
Interrupt 24H with error code 2 (Drive Not Ready). A subsequent Function
59H (Get Extended Error) returns the extended error code that specifies a
sharing violation.
When opening a file, it is important to inform MS-DOS of any operations
that other processes may perform on this file (sharing mode). The default
(compatibility mode) denies all other processes access to the file, unless
they also attempt to open the file in compatibility mode.
The following table shows the effect of opening a file with compatibility
mode set:
61
_ _ | | _ _
_ _ | | _ _
_ ______________
Type of File Opening Read-Only File Not Read-Only
_ ________________________________________________________________
First open for read, write, Succeeds Succeeds
or both by machine/process
"N"
Subsequent opens by machine Succeeds Succeeds
or process
"N"
An open by another machine Succeeds Fails
or process
_ ________________________________________________________________
Files may be read-only with the MS-DOS attrib command or by a read-only
share over the network.
It may be all right for other processes to continue to read the file while
your process is operating on it. In this case, you should specify "Deny
Write," which inhibits other processes from writing to your files but allows
them to read from these files.
Similarly, it is important for you to specify what operations your process
will perform ("Access" mode). If another process has the file open with
any sharing mode other than "Deny" mode, then the default mode
("Read/write") causes the open request to fail. If you only want to read
the file, your open request succeeds unless all other processes have
specified "Deny" mode or "Deny write."
Macro Definition:
open_handle macro path,access
mov dx, offset path
mov al, access
mov ah, 3DH
int 21H
endm
Example:
The following program prints a file named textfile.asc that is on the disk in
drive B.
file db "b:textfile.asc",0
buffer db ?
handle dw ?
;
begin: open_handle file,0 ;THIS FUNCTION
mov handle,ax ;Save handle
read_char: read_handle handle,buffer,1 ;Read 1 character
62
_ _ | | _ _
_ _ | | _ _
_ ______________
jc error_read ;Routine not shown
cmp ax,0 ;End of file?
je return ;Yes, go home
print_char buffer ;See Function 05H
jmp read_char ;Read another
63
_ _ | | _ _
_ _ | | _ _
_ ______________
Close Handle (Function 3EH)
Call:
AH = 3EH
BX
Handle
Return:
Carry set:
AX
6 = Invalid handle
Carry not set:
No error
Comments:
Function 3EH closes a file opened with Function 3DH (Open Handle) or
3CH (Create Handle). BX must contain the handle of the open file that you
want to close.
If there is no error, MS-DOS closes the file and flushes all internal buffers.
If there is an error, the carry flag (CF) is set and the error code returns in
AX:
Code
Meaning
_ ________________________________________________________________
6 Handle not open or invalid
Macro Definition:
close_handle macro handle
mov bx,handle
mov ah,3EH
int 21H
endm
64
_ _ | | _ _
_ _ | | _ _
_ ______________
Example:
The following program creates a file named dir.tmp, containing the
filename and extension of each file in the current directory, in the current
directory on the disk in drive B.
srch_file db "b:*.*",0
tmp_file db "b:dir.tmp",0
buffer db 43 dup (?)
handle dw ?
;
begin: set_dta buffer ;See Function 1AH
find_first_file srch_file,16H ;See Function 4EH
cmp ax,12H ;Directory empty?
je all_done ;Yes, go home
create_handle tmp_file,0 ;See Function 3CH
jc error_create ;Routine not shown
mov handle,ax ;Save handle
write_it: write_handle handle,buffer[1EH],12 ;See Function
jc error_write ;40H
find_next_file ;See Function 4FH
cmp ax,12H ;Another entry?
je all_done ;No, go home
jmp write_it ;Yes, write record
all_done: close_handle handle ;See Function 3EH
jc error_close ;Routine not shown
65
_ _ | | _ _
_ _ | | _ _
_ ______________
Read Handle (Function 3FH)
Call:
AH = 3FH
BX
Handle
CX
Bytes to read
DS:DX
Pointer to buffer
Return:
Carry set:
AX
5 = Access denied
6 = Invalid handle
Carry not set:
AX
Bytes read
Comments:
Function 3FH reads from the file or device associated with the specified
handle. BX must contain the handle. CX must contain the number of
bytes to be read. DX must contain the offset (to the segment address in
DS) of the buffer.
If there is no error, AX returns the number of bytes read; if you attempt to
read starting at end of file, AX returns 0. The number of bytes specified in
CX is not necessarily transferred to the buffer; if you use this call to read
from the keyboard, for example, it reads only up to the first carriage-
return.
If you use this function request to read from standard input, you can
redirect the input.
If there is an error, the carry flag (CF) is set and the error code returns in
AX:
Code
Meaning
_ ________________________________________________________________
5 Handle not open for reading
6 Handle not open or invalid
66
_ _ | | _ _
_ _ | | _ _
_ ______________
Macro Definition:
read_handle macro handle,buffer,bytes
mov bx,handle
mov dx,offset buffer
mov cx,bytes
mov ah,3FH
int 21H
endm
Example:
The following program displays a file named textfile.asc that is on the disk
in drive B.
filename db "b:\textfile.asc",0
buffer db 129 dup (?)
handle dw ?
;
begin: open_handle filename,0 ;See Function 3DH
jc error_open ;Routine not shown
mov handle,ax ;Save handle
read_file: read_handle buffer,file_handle,128
jc error_open ;Routine not shown
cmp ax,0 ;End of file?
je return ;Yes, go home
mov bx,ax ;# of bytes read
mov buffer[bx],"$" ;Make a string
display buffer ;See Function 09H
jmp read_file ;Read more
67
_ _ | | _ _