The Art of
ASSEMBLY LANGUAGE PROGRAMMING

Chapter Nineteen (Part 2)

Table of Content

Chapter Nineteen (Part 4)

CHAPTER NINETEEN:
PROCESSES COROUTINES AND CONCURRENCY (Part 3)
19.1.4 - Exception Handling in DOS: Traps
19.1.5 - Redirection of I/O for Child Processes

19.1.4 Exception Handling in DOS: Traps

In addition to the break and critical error exceptions there are the 80x86 exceptions that can happen during the execution of your programs. Examples include the divide error exception bounds exception and illegal opcode exception. A well-written application will always handle all possible exceptions.

DOS does not provide direct support for these exceptions other than a possible default handler. In particular DOS does not restore such vectors when the program terminates; this is something the application break handler and critical error handler must take care of.

19.1.5 Redirection of I/O for Child Processes

When a child process begins execution it inherits all open files from the parent process (with the exception of certain files opened with networking file functions). In particular this includes the default files opened for the DOS standard input standard output standard error auxiliary and printer devices. DOS assigns the file handle values zero through four respectively to these devices. If a parent process closes one of these file handles and then reassigns the handle with a Force Duplicate File Handle call.

Note that the DOS EXEC call does not process the I/O redirection operators ("<" and ">" and "|"). If you want to redirect the standard I/O of a child process you must do this before loading and executing the child process. To redirect one of the five standard I/O devices you should do the following steps:

1) Duplicate the file handle you want to redirect (e.g. to redirect the standard output duplicate file handle one).

2) Close the affected file (e.g. file handle one for standard output).

3) Open a file using the standard DOS Create or CreateNew calls.

4) Use the Force Duplicate File Handle call to copy the new file handle to file handle one.

5) Run the child process.

6) On return from the child close the file.

7) Copy the file handle you duplicated in step one back to the standard output file handle using the Force Duplicate Handle function.

This technique looks like it would be perfect for redirecting printer or serial port I/O. Unfortunately many programs bypass DOS when sending data to the printer and use the BIOS call or worse yet go directly to the hardware. Almost no software bothers with DOS' serial port support - it truly is that bad. However most programs do call DOS to input or output characters on the standard input output and error devices. The following code demonstrates how to redirect the output of a child process to a file.

; REDIRECT.ASM -Demonstrates how to redirect I/O for a child process.
; This particular program invokes COMMAND.COM to execute
; a DIR command
when is sent to the specified output file.

include stdlib.a
includelib      stdlib.lib

dseg            segment para public 'data'

OrigOutHandle   word    ?                       ;Holds copy of STDOUT handle.
FileHandle      word    ?                       ;File I/O handle.
FileName        byte    "dirctry.txt"
0         ;Filename for output data.

; MS-DOS EXEC structure.

ExecStruct      word    0                       ;Use parent's Environment blk.
dword   CmdLine                 ;For the cmd ln parms.
dword   DfltFCB
dword   DfltFCB

DfltFCB         byte    3
" "
0
0
0
0
0
CmdLine         byte    7
" /c DIR"
0dh       ;Do a directory command.
PgmName         dword   PgmNameStr              ;Points at pgm name.
PgmNameStr      byte    "c:\command.com"
0
dseg            ends

cseg            segment para public 'code'
assume  cs:cseg
ds:dseg


Main            proc
mov     ax
dseg                ;Get ptr to vars segment
mov     ds
ax
MemInit                         ;Start the memory mgr.

; Free up some memory for COMMAND.COM:

mov     ah
62h                 ;Get our PSP value
int     21h
mov     es
bx
mov     ax
zzzzzzseg           ;Compute size of
sub     ax
bx                  ; resident run code.
mov     bx
ax
mov     ah
4ah                 ;Release unused memory.
int     21h

; Save original output file handle.

mov     bx
1                   ;Std out is file handle 1.
mov     ah
45h                 ;Duplicate the file handle.
int     21h
mov OrigOutHandle
ax           ;Save duplicate handle.

; Open the output file:

mov     ah
3ch                 ;Create file.
mov     cx
0                   ;Normal attributes.
lea     dx
FileName
int     21h
mov     FileHandle
ax          ;Save opened file handle.

; Force the standard output to send its output to this file.
; Do this by forcing the file's handle onto file handle #1 (stdout).

mov     ah
46h                 ;Force dup file handle
mov     cx
1                   ;Existing handle to change.
mov     bx
FileHandle          ;New file handle to use.
int     21h

; Print the first line to the file:

print
byte    "Redirected directory listing:"
cr
lf
0

; Okay
execute the DOS DIR command (that is
execute COMMAND.COM with
; the command line parameter "/c DIR").

mov     bx
seg ExecStruct
mov     es
bx
mov     bx
offset ExecStruct ;Ptr to program record.
lds     dx
PgmName
mov     ax
4b00h               ;Exec pgm
int     21h

mov     bx
sseg                ;Reset the stack on return.
mov     ss
ax
mov     sp
offset EndStk
mov     bx
seg dseg
mov     ds
bx

; Okay
close the output file and switch standard output back to the
; console.

mov     ah
3eh                 ;Close output file.
mov     bx
FileHandle
int     21h

mov     ah
46h                 ;Force duplicate handle
mov     cx
1                   ;StdOut
mov     bx
OrigOutHandle       ;Restore previous handle.
int     21h

; Return control to MS-DOS

Quit:           ExitPgm
Main            endp
cseg            ends

sseg            segment para stack 'stack'
dw      128 dup (0)
endstk          dw      ?
sseg            ends

zzzzzzseg       segment para public 'zzzzzzseg'
Heap            db      200h dup (?)
zzzzzzseg       ends
end     Main

Chapter Nineteen (Part 2)

Table of Content

Chapter Nineteen (Part 4)

Chapter Nineteen: Processes Coroutines and Concurrency (Part 3)
29 SEP 1996