home *** CD-ROM | disk | FTP | other *** search
Text File | 2013-11-08 | 611.4 KB | 16,704 lines |
- \SAMPCODE
- \SAMPCODE\ADVMSDOS
- \SAMPCODE\ADVMSDOS\CHAP03
- \SAMPCODE\ADVMSDOS\CHAP03\HELLO_C.ASM
-
- title HELLO.COM --- print hello on terminal
- page 55,132
-
- ;
- ; HELLO-C.ASM Demonstrates components of a
- ; functional COM-type assembly
- ; language program, and an MS-DOS
- ; function call.
- ;
- ; Copyright (C) 1988 Ray Duncan
- ;
- ; Build: MASM HELLO-C;
- ; LINK HELLO-C;
- ; EXE2BIN HELLO.EXE HELLO.COM
- ; DEL HELLO.EXE
- ;
- ; Usage: HELLO
- ;
-
- stdin equ 0 ; standard input handle
- stdout equ 1 ; standard output handle
- stderr equ 2 ; standard error handle
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII line feed
-
-
- _TEXT segment word public 'CODE'
-
- org 100h ; COM files always have
- ; an origin of 100H
-
- assume cs:_TEXT,ds:_TEXT,es:_TEXT,ss:_TEXT
-
- print proc near ; entry point from MS-DOS
-
- mov ah,40h ; function 40H = write
- mov bx,stdout ; handle for standard output
- mov cx,msg_len ; length of message
- mov dx,offset msg ; address of message
- int 21h ; transfer to MS-DOS
-
- mov ax,4c00h ; exit, return code = 0
- int 21h ; transfer to MS-DOS
-
- print endp
-
-
- msg db cr,lf ; message to display
- db 'Hello World!',cr,lf
-
- msg_len equ $-msg ; length of message
-
-
- _TEXT ends
-
- end print ; defines entry point
-
-
- \SAMPCODE\ADVMSDOS\CHAP03\HELLO_E.ASM
-
- title HELLO.EXE --- print Hello on terminal
- page 55,132
- ;
- ; HELLO-E.ASM Demonstrates components of a
- ; functional EXE-type assembly
- ; language program, use of segments,
- ; and a MS-DOS function call.
- ;
- ; Copyright (C) 1988 Ray Duncan
- ;
- ; Build: MASM HELLO-E;
- ; LINK HELLO-E;
- ;
- ; Usage: HELLO-E
- ;
-
- stdin equ 0 ; standard input handle
- stdout equ 1 ; standard output handle
- stderr equ 2 ; standard error handle
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII line feed
-
-
- _TEXT segment word public 'CODE'
-
- assume cs:_TEXT,ds:_DATA,ss:STACK
-
- print proc far ; entry point from MS-DOS
-
- mov ax,_DATA ; make our data segment
- mov ds,ax ; addressable...
-
- mov ah,40h ; function 40h = write
- mov bx,stdout ; standard output handle
- mov cx,msg_len ; length of message
- mov dx,offset msg ; address of message
- int 21h ; transfer to MS-DOS
-
- mov ax,4c00h ; exit, return code = 0
- int 21h ; transfer to MS-DOS
-
- print endp
-
- _TEXT ends
-
-
- _DATA segment word public 'DATA'
-
- msg db cr,lf ; message to display
- db 'Hello World!',cr,lf
-
- msg_len equ $-msg ; length of message
-
- _DATA ends
-
-
- STACK segment para stack 'STACK'
-
- db 128 dup (?)
-
- STACK ends
-
- end print ; defines entry point
-
-
- \SAMPCODE\ADVMSDOS\CHAP05
- \SAMPCODE\ADVMSDOS\CHAP05\MOUDEMO.C
-
- /*
- Simple Demo of Int 33H Mouse Driver
- (C) 1988 Ray Duncan
-
- Compile with: CL MOUDEMO.C
-
- Usage: MOUDEMO (press both mouse buttons to exit)
- */
-
- #include <stdio.h>
- #include <dos.h>
-
- union REGS regs;
-
- void cls(void); /* function prototypes */
- void gotoxy(int, int);
-
- main(int argc, char *argv[])
- {
- int x,y,buttons; /* some scratch variables */
- /* for the mouse state */
-
- regs.x.ax = 0; /* reset mouse driver */
- int86(0x33, ®s, ®s); /* and check status */
-
- if(regs.x.ax == 0) /* exit if no mouse */
- { printf("\nMouse not available\n");
- exit(1);
- }
-
- cls(); /* clear the screen */
- gotoxy(45,0); /* and show help info */
- puts("Press Both Mouse Buttons To Exit");
-
- regs.x.ax = 1; /* display mouse cursor */
- int86(0x33, ®s, ®s);
-
- do {
- regs.x.ax = 3; /* get mouse position */
- int86(0x33, ®s, ®s); /* and button status */
- buttons = regs.x.bx & 3;
- x = regs.x.cx;
- y = regs.x.dx;
-
- gotoxy(0,0); /* display mouse position */
- printf("X = %3d Y = %3d", x, y);
-
- } while(buttons != 3); /* exit if both buttons down */
-
- regs.x.ax = 2; /* hide mouse cursor */
- int86(0x33, ®s, ®s);
-
- cls(); /* display message and exit */
- gotoxy(0,0);
- puts("Have a Mice Day!");
- }
-
- /*
- Clear the screen
- */
- void cls(void)
- {
- regs.x.ax = 0x0600; /* ROM BIOS video driver */
- regs.h.bh = 7; /* Int 10H Function 6 */
- regs.x.cx = 0; /* initializes a window */
- regs.h.dh = 24;
- regs.h.dl = 79;
- int86(0x10, ®s, ®s);
- }
-
- /*
- Position cursor to (x,y)
- */
- void gotoxy(int x, int y)
- {
- regs.h.dl = x; /* ROM BIOS video driver */
- regs.h.dh = y; /* Int 10H Function 2 */
- regs.h.bh = 0; /* positions the cursor */
- regs.h.ah = 2;
- int86(0x10, ®s, ®s);
- }
-
-
- \SAMPCODE\ADVMSDOS\CHAP05\TRYBREAK.C
-
- /*
- TRYBREAK.C
-
- Demo of BREAK.ASM Ctrl-Break and Ctrl-C
- interrupt handler, by Ray Duncan
-
- Build: MASM /Mx BREAK;
- CL TRYBREAK.C BREAK.OBJ
-
- Usage: TRYBREAK
-
- */
-
- #include <stdio.h>
-
- main(int argc, char *argv[])
- {
- int hit = 0; /* flag for keypress */
- int c = 0; /* character from keyboard */
- static int flag = 0; /* true if Ctrl-Break
- or Ctrl-C detected */
-
- puts("\n*** TRYBREAK.C running ***\n");
- puts("Press Ctrl-C or Ctrl-Break to test handler,");
- puts("Press the Esc key to exit TRYBREAK.\n");
-
- capture(&flag); /* install new Ctrl-C and
- Ctrl-Break handler and
- pass address of flag */
-
- puts("TRYBREAK has captured interrupt vectors.\n");
-
- while(1)
- {
- hit = kbhit(); /* check for keypress */
- /* (MS-DOS sees Ctrl-C
- when keyboard polled) */
-
- if(flag != 0) /* if flag is true, an */
- { /* interrupt has occurred */
- puts("\nControl-Break detected.\n");
- flag = 0; /* reset interrupt flag */
- }
- if(hit != 0) /* if any key waiting */
- {
- c = getch(); /* read key, exit if Esc */
- if( (c & 0x7f) == 0x1b) break;
- putch(c); /* otherwise display it */
- }
- }
- release(); /* restore original Ctrl-C
- and Ctrl-Break handlers */
-
- puts("\n\nTRYBREAK has released interrupt vectors.");
- }
-
- \SAMPCODE\ADVMSDOS\CHAP05\BREAK.ASM
-
- title Ctrl-C & Ctrl-Break Handlers
- page 55,132
-
- ;
- ; Ctrl-C and Ctrl-Break handler for Microsoft C
- ; programs running on IBM PC compatibles
- ;
- ; by Ray Duncan
- ;
- ; Assemble with: C>MASM /Mx BREAK;
- ;
- ; This module allows C programs to retain control
- ; when the user enters a Ctrl-Break or Ctrl-C.
- ; It uses Microsoft C parameter passing conventions
- ; and assumes the C small memory model.
- ;
- ; The procedure _capture is called to install
- ; a new handler for the Ctrl-C and Ctrl-Break
- ; interrupts (1BH and 23H). _capture is passed
- ; the address of a static variable, which will be
- ; set to True by the handler whenever a Ctrl-C
- ; or Ctrl-Break is detected. The C syntax is:
- ;
- ; static int flag;
- ; capture(&flag);
- ;
- ; The procedure _release is called by the C program
- ; to restore the original Ctrl-Break and Ctrl-C
- ; handler. The C syntax is:
- ;
- ; release();
- ;
- ; The procedure ctrlbrk is the actual interrupt
- ; handler. It receives control when a software
- ; Int 1BH is executed by the ROM BIOS or Int 23H
- ; is executed by MS-DOS. It simply sets the C
- ; program's variable to True (1) and returns.
- ;
-
- args equ 4 ; stack offset of arguments,
- ; C small memory model
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII line feed
-
-
- _TEXT segment word public 'CODE'
-
- assume cs:_TEXT
-
-
- public _capture
- _capture proc near ; take over Control-Break
- ; and Ctrl-C interrupt vectors
-
- push bp ; set up stack frame
- mov bp,sp
-
- push ds ; save affected registers
- push di
- push si
-
- ; save address of
- ; calling program's "flag"
- mov ax,word ptr [bp+args]
- mov word ptr cs:flag,ax
- mov word ptr cs:flag+2,ds
-
- ; save address of original
- mov ax,3523h ; Int 23H handler
- int 21h
- mov word ptr cs:int23,bx
- mov word ptr cs:int23+2,es
-
- mov ax,351bh ; save address of original
- int 21h ; Int 1BH handler
- mov word ptr cs:int1b,bx
- mov word ptr cs:int1b+2,es
-
- push cs ; set DS:DX = address
- pop ds ; of new handler
- mov dx,offset _TEXT:ctrlbrk
-
- mov ax,02523H ; set Int 23H vector
- int 21h
-
- mov ax,0251bH ; set Int 1BH vector
- int 21h
-
- pop si ; restore registers
- pop di
- pop ds
-
- pop bp ; discard stack frame
- ret ; and return to caller
-
- _capture endp
-
-
- public _release
- _release proc near ; restore original Ctrl-C
- ; and Ctrl-Break handlers
-
- push bp ; save registers
- push ds
- push di
- push si
-
- lds dx,cs:int1b ; get address of previous
- ; Int 1BH handler
-
- mov ax,251bh ; set Int 1BH vector
- int 21h
-
- lds dx,cs:int23 ; get address of previous
- ; Int 23H handler
-
- mov ax,2523h ; set Int 23H vector
- int 21h
-
- pop si ; restore registers
- pop di ; and return to caller
- pop ds
- pop bp
- ret
-
- _release endp
-
-
- ctrlbrk proc far ; Ctrl-C and Ctrl-Break
- ; interrupt handler
-
- push bx ; save registers
- push ds
-
-
- lds bx,cs:flag ; get address of C program's
- ; "flag variable"
-
- ; and set the flag "true"
- mov word ptr ds:[bx],1
-
- pop ds ; restore registers
- pop bx
-
- iret ; return from handler
-
- ctrlbrk endp
-
-
- flag dd 0 ; far pointer to caller's
- ; Ctrl-Break or Ctrl-C flag
-
- int23 dd 0 ; address of original
- ; Ctrl-C handler
-
- int1b dd 0 ; address of original
- ; Ctrl-Break handler
-
- _TEXT ends
-
- end
-
-
- \SAMPCODE\ADVMSDOS\CHAP07
- \SAMPCODE\ADVMSDOS\CHAP07\TALK.ASM
-
- title TALK --- Simple terminal emulator
- page 55,132
- .lfcond ;list false conditionals too
-
- ;
- ; TALK.ASM --- Simple IBM PC terminal emulator
- ;
- ; Copyright (c) 1988 Ray Duncan
- ;
- ; Build: MASM TALK;
- ; LINK TALK;
- ;
- ; Usage: TALK
- ;
-
- stdin equ 0 ; standard input handle
- stdout equ 1 ; standard output handle
- stderr equ 2 ; standard error handle
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII line feed
- bsp equ 08h ; ASCII backspace
- escape equ 1bh ; ASCII escape code
-
- dattr equ 07h ; display attribute to use
- ; while in emulation mode
-
- bufsiz equ 4096 ; size of serial port buffer
-
- echo equ 0 ; 0=full-duplex, -1=half-duplex
-
- true equ -1
- false equ 0
-
- com1 equ true ; Use COM1 if nonzero
- com2 equ not com1 ; Use COM2 if nonzero
-
- pic_mask equ 21h ; 8259 int. mask port
- pic_eoi equ 20h ; 8259 EOI port
-
- if com1
- com_data equ 03f8h ; port assignments for COM1
- com_ier equ 03f9h
- com_mcr equ 03fch
- com_sts equ 03fdh
- com_int equ 0ch ; COM1 interrupt number
- int_mask equ 10h ; IRQ4 mask for 8259
- endif
-
- if com2
- com_data equ 02f8h ; port assignments for COM2
- com_ier equ 02f9h
- com_mcr equ 02fch
- com_sts equ 02fdh
- com_int equ 0bh ; COM2 interrupt number
- int_mask equ 08h ; IRQ3 mask for 8259
- endif
-
- _TEXT segment word public 'CODE'
-
- assume cs:_TEXT,ds:_DATA,es:_DATA,ss:STACK
-
- talk proc far ; entry point from MS-DOS
-
- mov ax,_DATA ; make data segment addressable
- mov ds,ax
- mov es,ax
- ; initialize display for
- ; terminal emulator mode...
-
- mov ah,15 ; get display width and
- int 10h ; current display mode
- dec ah ; save display width for use
- mov columns,ah ; by the screen clear routine
-
- cmp al,7 ; enforce text display mode
- je talk2 ; mode 7 ok, proceed
-
- cmp al,3
- jbe talk2 ; modes 0-3 ok,proceed
-
- mov dx,offset msg1
- mov cx,msg1_len
- jmp talk6 ; print error message and exit
-
- talk2: mov bh,dattr ; clear screen and home cursor
- call cls
-
- call asc_enb ; capture serial port interrupt
- ; vector and enable interrupts
-
- mov dx,offset msg2 ; display message
- mov cx,msg2_len ; 'Terminal emulator running'
- mov bx,stdout ; BX = standard output handle
- mov ah,40h ; Fxn 40H = write file or device
- int 21h ; transfer to MS-DOS
-
- talk3: call pc_stat ; keyboard character waiting?
- jz talk4 ; nothing waiting, jump
-
- call pc_in ; read keyboard character
-
- cmp al,0 ; is it a function key?
- jne talk32 ; not function key, jump
-
- call pc_in ; function key, discard 2nd
- ; character of sequence
- jmp talk5 ; then terminate program
-
- talk32: ; keyboard character received
- if echo
- push ax ; if half-duplex, echo
- call pc_out ; character to PC display
- pop ax
- endif
-
- call com_out ; write char. to serial port
-
- talk4: call com_stat ; serial port character waiting?
- jz talk3 ; nothing waiting, jump
-
- call com_in ; read serial port character
-
- cmp al,20h ; is it control code?
- jae talk45 ; jump if not
-
- call ctrl_code ; control code, process it
-
- jmp talk3 ; check keyboard again
-
- talk45: ; non-control char. received,
- call pc_out ; write it to PC display
-
- jmp talk4 ; see if any more waiting
-
- talk5: ; function key detected,
- ; prepare to terminate...
-
- mov bh,07h ; clear screen and home cursor
- call cls
-
- mov dx,offset msg3 ; display farewell message
- mov cx,msg3_len
-
- talk6: push dx ; save message address
- push cx ; and message length
-
- call asc_dsb ; disable serial port interrupts
- ; and release interrupt vector
-
- pop cx ; restore message length
- pop dx ; and address
-
- mov bx,stdout ; handle for standard output
- mov ah,40h ; Fxn 40H = write device
- int 21h ; transfer to MS-DOS
-
- mov ax,4c00h ; terminate program with
- int 21h ; return code = 0
-
- talk endp
-
-
- com_stat proc near ; Check asynch status, returns
- ; Z=false if character ready
- ; Z=true if nothing waiting
- push ax
- mov ax,asc_in ; compare ring buffer pointers
- cmp ax,asc_out
- pop ax
- ret ; return to caller
-
- com_stat endp
-
-
- com_in proc near ; get character from serial
- ; port buffer, returns
- ; new character in AL
-
- push bx ; save register BX
-
- com_in1: ; if no char waiting, wait
- mov bx,asc_out ; until one is received
- cmp bx,asc_in
- je com_in1 ; jump, nothing waiting
-
- mov al,[bx+asc_buf] ; character is ready,
- ; extract it from buffer
-
- inc bx ; update buffer pointer
- cmp bx,bufsiz
- jne com_in2
- xor bx,bx ; reset pointer if wrapped
- com_in2:
- mov asc_out,bx ; store updated pointer
- pop bx ; restore register BX
- ret ; and return to caller
-
- com_in endp
-
-
- com_out proc near ; write character in AL
- ; to serial port
-
- push dx ; save register DX
- push ax ; save character to send
- mov dx,com_sts ; DX = status port address
-
- com_out1: ; check if transmit buffer
- in al,dx ; is empty (TBE bit = set)
- and al,20h
- jz com_out1 ; no, must wait
-
- pop ax ; get character to send
- mov dx,com_data ; DX = data port address
- out dx,al ; transmit the character
- pop dx ; restore register DX
- ret ; and return to caller
-
- com_out endp
-
-
- pc_stat proc near ; read keyboard status, returns
- ; Z=false if character ready
- ; Z=true if nothing waiting.
- ; register DX destroyed.
-
- mov al,in_flag ; if character already
- or al,al ; waiting, return status
- jnz pc_stat1
-
- mov ah,6 ; otherwise call MS-DOS to
- mov dl,0ffh ; determine keyboard status
- int 21h
-
- jz pc_stat1 ; jump if no key ready
-
- mov in_char,al ; got key, save it for
- mov in_flag,0ffh ; "pc_in" routine
-
- pc_stat1: ; return to caller with
- ret ; Z flag set appropriately
-
- pc_stat endp
-
-
- pc_in proc near ; read keyboard character,
- ; return it in AL
- ; DX may be destroyed.
-
- mov al,in_flag ; key already waiting?
- or al,al
- jnz pc_in1 ; yes,return it to caller
-
- call pc_stat ; try and read a character
- jmp pc_in
-
- pc_in1: mov in_flag,0 ; clear char. waiting flag
- mov al,in_char ; and return AL = character
- ret
-
- pc_in endp
-
-
- pc_out proc near ; write character in AL
- ; to the PC's display.
-
- mov ah,0eh ; ROM BIOS Fxn 0EH =
- ; "teletype output"
- push bx ; save register BX
- xor bx,bx ; assume page 0
- int 10h ; transfer to ROM BIOS
- pop bx ; restore register BX
- ret ; and return to caller
-
- pc_out endp
-
-
- cls proc near ; clear display using
- ; char. attribute in BH
- ; registers AX, CX,
- ; and DX destroyed.
-
- mov dl,columns ; set DL,DH = X,Y of
- mov dh,24 ; lower right corner
- mov cx,0 ; set CL,CH=X,Y of
- ; upper left corner
- mov ax,600h ; ROM BIOS Fxn 06H =
- ; "scroll or initialize
- ; window"
- int 10h ; transfer to ROM BIOS
- call home ; set cursor at (0,0)
- ret ; and return to caller
-
- cls endp
-
-
- clreol proc near ; clear from cursor to end
- ; of line using attribute
- ; in BH. Register AX, CX,
- ; and DX destroyed.
-
- call getxy ; get current cursor pos'n
- mov cx,dx ; current position = "upper
- ; left corner" of window
- mov dl,columns ; "lower right corner" X is
- ; max columns, Y is same
- ; as upper left corner
- mov ax,600h ; ROM BIOS Fxn 06H =
- ; "scroll or initialize
- ; window"
- int 10h ; transfer to ROM BIOS
- ret ; return to caller
-
- clreol endp
-
-
- home proc near ; put cursor at home position
-
- mov dx,0 ; set (X,Y) = (0,0)
- call gotoxy ; position the cursor
- ret ; return to caller
-
- home endp
-
-
- gotoxy proc near ; position the cursor
- ; call with DL=X, DH=Y
-
- push bx ; save registers
- push ax
-
- mov bh,0 ; assume page 0
- mov ah,2 ; ROM BIOS Fxn 02H =
- ; set cursor position
- int 10h ; transfer to ROM BIOS
-
- pop ax ; restore registers
- pop bx
- ret ; and return to caller
-
- gotoxy endp
-
-
- getxy proc near ; get cursor position,
- ; Returns DL=X, DH=Y
-
- push ax ; save registers
- push bx
- push cx
-
- mov ah,3 ; ROM BIOS Fxn 03H =
- ; get cursor position
- mov bh,0 ; assume page 0
- int 10h ; transfer to ROM BIOS
-
- pop cx ; restore registers
- pop bx
- pop ax
- ret ; and return to caller
-
- getxy endp
-
-
- ctrl_code proc near ; process control code
- ; call with AL=char
-
- cmp al,cr ; if carriage return
- je ctrl8 ; just send it
-
- cmp al,lf ; if line feed
- je ctrl8 ; just send it
-
- cmp al,bsp ; if backspace
- je ctrl8 ; just send it
-
- cmp al,26 ; is it cls control code?
- jne ctrl7 ; no, jump
-
- mov bh,dattr ; cls control code, clear
- call cls ; screen and home cursor
-
- jmp ctrl9
-
- ctrl7:
- cmp al,escape ; is it Escape character?
- jne ctrl9 ; no, throw it away
-
- call esc_seq ; yes, emulate CRT terminal
- jmp ctrl9
-
- ctrl8: call pc_out ; send CR, LF, or backspace
- ; to the display
-
- ctrl9: ret ; return to caller
-
- ctrl_code endp
-
-
- esc_seq proc near ; decode Televideo 950 escape
- ; sequence for screen control
-
- call com_in ; get next character
- cmp al,84 ; is it clear to end of line?
- jne esc_seq1 ; no, jump
-
- mov bh,dattr ; yes, clear to end of line
- call clreol
- jmp esc_seq2 ; then exit
-
- esc_seq1:
- cmp al,61 ; is it cursor positioning?
- jne esc_seq2 ; no jump
-
- call com_in ; yes, get Y parameter
- sub al,33 ; and remove offset
- mov dh,al
-
- call com_in ; get X parameter
- sub al,33 ; and remove offset
- mov dl,al
- call gotoxy ; position the cursor
-
- esc_seq2: ; return to caller
- ret
-
- esc_seq endp
-
-
- asc_enb proc near ; capture serial port interrupt
- ; vector and enable interrupt
-
- ; save address of previous
- ; interrupt handler...
- mov ax,3500h+com_int ; Fxn 35H = get vector
- int 21h ; transfer to MS-DOS
- mov word ptr oldvec+2,es
- mov word ptr oldvec,bx
-
- ; now install our handler...
- push ds ; save our data segment
- mov ax,cs ; set DS:DX = address
- mov ds,ax ; of our interrupt handler
- mov dx,offset asc_int
- mov ax,2500h+com_int ; Fxn 25H = set vector
- int 21h ; transfer to MS-DOS
- pop ds ; restore data segment
-
- mov dx,com_mcr ; set modem control register
- mov al,0bh ; DTR and OUT2 bits
- out dx,al
-
- mov dx,com_ier ; set interrupt enable
- mov al,1 ; register on serial
- out dx,al ; port controller
-
- in al,pic_mask ; read current 8259 mask
- and al,not int_mask ; set mask for COM port
- out pic_mask,al ; write new 8259 mask
-
- ret ; back to caller
-
- asc_enb endp
-
-
- asc_dsb proc near ; disable interrupt and
- ; release interrupt vector
-
- in al,pic_mask ; read current 8259 mask
- or al,int_mask ; reset mask for COM port
- out pic_mask,al ; write new 8259 mask
-
- push ds ; save our data segment
- lds dx,oldvec ; load address of
- ; previous interrupt handler
- mov ax,2500h+com_int ; Fxn 25H = set vector
- int 21h ; transfer to MS-DOS
- pop ds ; restore data segment
-
- ret ; back to caller
-
- asc_dsb endp
-
-
- asc_int proc far ; interrupt service routine
- ; for serial port
-
- sti ; turn interrupts back on
-
- push ax ; save registers
- push bx
- push dx
- push ds
-
- mov ax,_DATA ; make our data segment
- mov ds,ax ; addressable
-
- cli ; clear interrupts for
- ; pointer manipulation
-
- mov dx,com_data ; DX = data port address
- in al,dx ; read this character
-
- mov bx,asc_in ; get buffer pointer
- mov [asc_buf+bx],al ; store this character
- inc bx ; bump pointer
- cmp bx,bufsiz ; time for wrap?
- jne asc_int1 ; no, jump
- xor bx,bx ; yes,reset pointer
-
- asc_int1: ; store updated pointer
- mov asc_in,bx
-
- sti ; turn interrupts back on
-
- mov al,20h ; send EOI to 8259
- out pic_eoi,al
-
- pop ds ; restore all registers
- pop dx
- pop bx
- pop ax
-
- iret ; return from interrupt
-
- asc_int endp
-
- _TEXT ends
-
-
- _DATA segment word public 'DATA'
-
- in_char db 0 ; PC keyboard input char.
- in_flag db 0 ; <>0 if char waiting
-
- columns db 0 ; highest numbered column in
- ; current display mode (39 or 79)
-
- msg1 db cr,lf
- db 'Display must be text mode.'
- db cr,lf
- msg1_len equ $-msg1
-
- msg2 db 'Terminal emulator running...'
- db cr,lf
- msg2_len equ $-msg2
-
- msg3 db 'Exit from terminal emulator.'
- db cr,lf
- msg3_len equ $-msg3
-
- oldvec dd 0 ; original contents of serial
- ; port interrupt vector
-
- asc_in dw 0 ; input pointer to ring buffer
- asc_out dw 0 ; output pointer to ring buffer
-
- asc_buf db bufsiz dup (?) ; communications buffer
-
- _DATA ends
-
-
- STACK segment para stack 'STACK'
-
- db 128 dup (?)
-
- STACK ends
-
- end talk ; defines entry point
-
-
- \SAMPCODE\ADVMSDOS\CHAP08
- \SAMPCODE\ADVMSDOS\CHAP08\DUMP.C
-
- /*
- DUMP.C Displays the binary contents of a file in
- hex and ASCII on the standard output device.
-
- Compile: C>CL DUMP.C
-
- Usage: C>DUMP unit:path\filename.ext [ >device ]
-
- Copyright (C) 1988 Ray Duncan
- */
-
- #include <stdio.h>
- #include <io.h>
- #include <fcntl.h>
-
- #define REC_SIZE 16 /* input file record size */
-
- main(int argc, char *argv[])
- {
- int fd; /* input file handle */
- int status = 0; /* status from file read */
- long fileptr = 0L; /* current file byte offset */
- char filebuf[REC_SIZE]; /* data from file */
-
- if(argc != 2) /* abort if missing filename */
- { fprintf(stderr,"\ndump: wrong number of parameters\n");
- exit(1);
- }
-
- /* open file in binary mode,
- abort if open fails */
- if((fd = open(argv[1],O_RDONLY | O_BINARY) ) == -1)
- { fprintf(stderr, "\ndump: can't find file %s \n", argv[1]);
- exit(1);
- }
-
- /* read and dump records
- until end of file */
- while((status = read(fd,filebuf,REC_SIZE) ) != 0)
- { dump_rec(filebuf, fileptr, status);
- fileptr += REC_SIZE;
- }
-
- close(fd); /* close input file */
- exit(0); /* return success code */
- }
-
-
- /*
- Display record (16 bytes) in hex and ASCII on standard output
- */
-
- dump_rec(char *filebuf, long fileptr, int length)
- {
- int i; /* index to current record */
-
- if(fileptr % 128 == 0) /* display heading if needed */
- printf("\n\n 0 1 2 3 4 5 6 7 8 9 A B C D E F");
-
- printf("\n%04lX ",fileptr); /* display file offset */
-
- /* display hex equivalent of
- each byte from file */
- for(i = 0; i < length; i++)
- printf(" %02X", (unsigned char) filebuf[i]);
-
- if(length != 16) /* spaces if partial record */
- for (i=0; i<(16-length); i++) printf(" ");
-
- /* display ASCII equivalent of
- each byte from file */
- printf(" ");
- for(i = 0; i < length; i++)
- { if(filebuf[i] < 32 || filebuf[i] > 126) putchar('.');
- else putchar(filebuf[i]);
- }
- }
-
- \SAMPCODE\ADVMSDOS\CHAP08\DUMP.ASM
-
- title DUMP --- display file contents
- page 55,132
-
- ;
- ; DUMP --- Display contents of file in hex and ASCII
- ;
- ; Build: C>MASM DUMP;
- ; C>LINK DUMP;
- ;
- ; Usage: C>DUMP unit:\path\filename.exe [ >device ]
- ;
- ; Copyright 1988 Ray Duncan
- ;
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII line feed
- tab equ 09h ; ASCII tab code
- blank equ 20h ; ASCII space code
-
- cmd equ 80h ; buffer for command tail
-
- blksize equ 16 ; input file record size
-
- stdin equ 0 ; standard input handle
- stdout equ 1 ; standard output handle
- stderr equ 2 ; standard error handle
-
-
- _TEXT segment word public 'CODE'
-
- assume cs:_TEXT,ds:_DATA,es:_DATA,ss:STACK
-
-
- dump proc far ; entry point from MS-DOS
-
- push ds ; save DS:0000 for final
- xor ax,ax ; return to MS-DOS, in case
- push ax ; Function 4CH can't be used.
-
- mov ax,_DATA ; make our data segment
- mov ds,ax ; addressable via DS register.
-
- ; check MS-DOS version
- mov ax,3000h ; Fxn 30H = get version
- int 21h ; transfer to MS-DOS
- cmp al,2 ; major version 2 or later?
- jae dump1 ; yes, proceed
-
- ; if MS-DOS 1.x, display
- ; error message and exit
- mov dx,offset msg3 ; DS:DX = message address
- mov ah,9 ; Fxn 9 = print string
- int 21h ; transfer to MS-DOS
- ret ; then exit the old way
-
- dump1: ; check if filename present
- mov bx,offset cmd ; ES:BX = command tail
- call argc ; count command arguments
- cmp ax,2 ; are there 2 arguments?
- je dump2 ; yes, proceed
-
- ; missing filename, display
- ; error message and exit
- mov dx,offset msg2 ; DS:DX = message address
- mov cx,msg2_len ; CX = message length
- jmp dump9 ; go display it
-
- dump2: ; get address of filename
- mov ax,1 ; AX = argument number
- ; ES:BX still = command tail
- call argv ; returns ES:BX = address,
- ; and AX = length
-
- mov di,offset fname ; copy filename to buffer
- mov cx,ax ; CX = length
-
- dump3: mov al,es:[bx] ; copy one byte
- mov [di],al
- inc bx ; bump string pointers
- inc di
- loop dump3 ; loop until string done
- mov byte ptr [di],0 ; add terminal null byte
-
- mov ax,ds ; make our data segment
- mov es,ax ; addressable by ES too
-
- ; now open the file
- mov ax,3d00h ; Fxn 3DH = open file
- ; mode 0 = read only
- mov dx,offset fname ; DS:DX = filename
- int 21h ; transfer to MS-DOS
- jnc dump4 ; jump, open successful
-
- ; open failed, display
- ; error message and exit
- mov dx,offset msg1 ; DS:DX = message address
- mov cx,msg1_len ; CX = message length
- jmp dump9 ; go display it
-
- dump4: mov fhandle,ax ; save file handle
-
- dump5: ; read block of file data
- mov bx,fhandle ; BX = file handle
- mov cx,blksize ; CX = record length
- mov dx,offset fbuff ; DS:DX = buffer
- mov ah,3fh ; Fxn 3FH = read
- int 21h ; transfer to MS-DOS
-
- mov flen,ax ; save actual length
- cmp ax,0 ; end of file reached?
- jne dump6 ; no, proceed
-
- cmp word ptr fptr,0 ; was this the first read?
- jne dump8 ; no, exit normally
-
- ; display empty file
- ; message and exit
- mov dx,offset msg4 ; DS:DX = message address
- mov cx,msg4_len ; CX = length
- jmp dump9 ; go display it
-
- dump6: ; display heading at
- ; each 128 byte boundary
- test fptr,07fh ; time for a heading?
- jnz dump7 ; no, proceed
-
- ; display a heading
- mov dx,offset hdg ; DS:DX = heading address
- mov cx,hdg_len ; CX = heading length
- mov bx,stdout ; BX = standard output
- mov ah,40h ; Fxn 40H = write
- int 21h ; transfer to MS-DOS
-
- dump7: call conv ; convert binary record
- ; to formatted ASCII
-
- ; display formatted output
- mov dx,offset fout ; DX:DX = output address
- mov cx,fout_len ; CX = output length
- mov bx,stdout ; BX = standard output
- mov ah,40h ; Fxn 40H = write
- int 21h ; transfer to MS-DOS
-
- jmp dump5 ; go get another record
-
- dump8: ; close input file
- mov bx,fhandle ; BX = file handle
- mov ah,3eh ; Fxn 3EH = close
- int 21h ; transfer to MS-DOS
-
- mov ax,4c00h ; Fxn 4CH = terminate,
- ; return code = 0
- int 21h ; transfer to MS-DOS
-
- dump9: ; display message on
- ; standard error device
- ; DS:DX = message address
- ; CX = message length
- mov bx,stderr ; standard error handle
- mov ah,40h ; Fxn 40H = write
- int 21h ; transfer to MS-DOS
-
- mov ax,4c01h ; Fxn 4CH = terminate,
- ; return code = 1
- int 21h ; transfer to MS-DOS
-
- dump endp
-
-
- conv proc near ; convert block of data
- ; from input file
-
- mov di,offset fout ; clear output format
- mov cx,fout_len-2 ; area to blanks
- mov al,blank
- rep stosb
-
- mov di,offset fout ; convert file offset
- mov ax,fptr ; to ASCII for output
- call w2a
-
- mov bx,0 ; init. buffer pointer
-
- conv1: mov al,[fbuff+bx] ; fetch byte from buffer
- mov di,offset foutb ; point to output area
-
- ; format ASCII part...
- ; store '.' as default
- mov byte ptr [di+bx],'.'
-
- cmp al,blank ; in range 20H - 7EH?
- jb conv2 ; jump, not alphanumeric.
-
- cmp al,7eh ; in range 20H - 7EH?
- ja conv2 ; jump, not alphanumeric.
-
- mov [di+bx],al ; store ASCII character.
-
- conv2: ; format hex part...
- mov di,offset fouta ; point to output area
- add di,bx ; base addr + (offset*3)
- add di,bx
- add di,bx
- call b2a ; convert byte to hex
-
- inc bx ; advance through record
- cmp bx,flen ; entire record converted?
- jne conv1 ; no, get another byte
-
- ; update file pointer
- add word ptr fptr,blksize
-
- ret
-
- conv endp
-
-
- w2a proc near ; convert word to hex ASCII
- ; call with AX = value
- ; DI = addr for string
- ; returns AX, DI, CX destroyed
-
- push ax ; save copy of value
- mov al,ah
- call b2a ; convert upper byte
-
- pop ax ; get back copy
- call b2a ; convert lower byte
- ret
-
- w2a endp
-
-
- b2a proc near ; convert byte to hex ASCII
- ; call with AL=binary value
- ; DI=addr for string
- ; returns AX, DI, CX modified
-
- sub ah,ah ; clear upper byte
- mov cl,16
- div cl ; divide byte by 16
- call ascii ; quotient becomes the first
- stosb ; ASCII character
- mov al,ah
- call ascii ; remainder becomes the
- stosb ; second ASCII character
- ret
-
- b2a endp
-
-
- ascii proc near ; convert value 0-0FH in AL
- ; into "hex ASCII" character
-
- add al,'0' ; offset to range 0-9
- cmp al,'9' ; is it > 9?
- jle ascii2 ; no, jump
- add al,'A'-'9'-1 ; offset to range A-F,
-
- ascii2: ret ; return AL = ASCII char.
-
- ascii endp
-
-
- argc proc near ; count command line arguments
- ; call with ES:BX = command line
- ; returns AX = argument count
-
- push bx ; save original BX and CX
- push cx ; for later
- mov ax,1 ; force count >= 1
-
- argc1: mov cx,-1 ; set flag = outside argument
-
- argc2: inc bx ; point to next character
- cmp byte ptr es:[bx],cr
- je argc3 ; exit if carriage return
- cmp byte ptr es:[bx],blank
- je argc1 ; outside argument if ASCII blank
- cmp byte ptr es:[bx],tab
- je argc1 ; outside argument if ASCII tab
-
- ; otherwise not blank or tab,
- jcxz argc2 ; jump if already inside argument
-
- inc ax ; else found argument, count it
- not cx ; set flag = inside argument
- jmp argc2 ; and look at next character
-
- argc3: pop cx ; restore original BX and CX
- pop bx
- ret ; return AX = argument count
-
- argc endp
-
-
- argv proc near ; get address & length of
- ; command line argument
- ; call with ES:BX = command line
- ; AX = argument no.
- ; returns ES:BX = address
- ; AX = length
-
- push cx ; save original CX and DI
- push di
-
- or ax,ax ; is it argument 0?
- jz argv8 ; yes, jump to get program name
-
- xor ah,ah ; initialize argument counter
-
- argv1: mov cx,-1 ; set flag = outside argument
-
- argv2: inc bx ; point to next character
- cmp byte ptr es:[bx],cr
- je argv7 ; exit if carriage return
- cmp byte ptr es:[bx],blank
- je argv1 ; outside argument if ASCII blank
- cmp byte ptr es:[bx],tab
- je argv1 ; outside argument if ASCII tab
-
- ; if not blank or tab...
- jcxz argv2 ; jump if already inside argument
-
- inc ah ; else count arguments found
- cmp ah,al ; is this the one we're looking for?
- je argv4 ; yes, go find its length
- not cx ; no, set flag = inside argument
- jmp argv2 ; and look at next character
-
- argv4: ; found desired argument, now
- ; determine its length...
- mov ax,bx ; save param. starting address
-
- argv5: inc bx ; point to next character
- cmp byte ptr es:[bx],cr
- je argv6 ; found end if carriage return
- cmp byte ptr es:[bx],blank
- je argv6 ; found end if ASCII blank
- cmp byte ptr es:[bx],tab
- jne argv5 ; found end if ASCII tab
-
- argv6: xchg bx,ax ; set ES:BX = argument address
- sub ax,bx ; and AX = argument length
- jmp argvx ; return to caller
-
- argv7: xor ax,ax ; set AX = 0, argument not found
- jmp argvx ; return to caller
-
- argv8: ; special handling for argv=0
- mov ax,3000h ; check if DOS 3.0 or later
- int 21h ; (force AL=0 in case DOS 1)
- cmp al,3
- jb argv7 ; DOS 1 or 2, return null param.
- mov es,es:[2ch] ; get environment segment from PSP
- xor di,di ; find the program name by
- xor al,al ; first skipping over all the
- mov cx,-1 ; environment variables...
- cld
- argv9: repne scasb ; scan for double null (can't use
- scasb ; (SCASW since might be odd addr.)
- jne argv9 ; loop if it was a single null
- add di,2 ; skip count word in environment
- mov bx,di ; save program name address
- mov cx,-1 ; now find its length...
- repne scasb ; scan for another null byte
- not cx ; convert CX to length
- dec cx
- mov ax,cx ; return length in AX
-
- argvx: ; common exit point
- pop di ; restore original CX and DI
- pop cx
- ret ; return to caller
-
- argv endp
-
- _TEXT ends
-
-
- _DATA segment word public 'DATA'
-
- fname db 64 dup (0) ; buffer for input filespec
-
- fhandle dw 0 ; token from PCDOS for input file.
-
- flen dw 0 ; actual length read
-
- fptr dw 0 ; relative address in file
-
- fbuff db blksize dup (?) ; data from input file
-
- fout db 'nnnn' ; formatted output area
- db blank,blank
- fouta db 16 dup ('nn',blank)
- db blank
- foutb db 16 dup (blank),cr,lf
- fout_len equ $-fout
-
- hdg db cr,lf ; heading for each 128 bytes
- db 7 dup (blank) ; of formatted output
- db '0 1 2 3 4 5 6 7 '
- db '8 9 A B C D E F',cr,lf
- hdg_len equ $-hdg
-
-
- msg1 db cr,lf
- db 'dump: file not found'
- db cr,lf
- msg1_len equ $-msg1
-
- msg2 db cr,lf
- db 'dump: missing file name'
- db cr,lf
- msg2_len equ $-msg2
-
- msg3 db cr,lf
- db 'dump: wrong MS-DOS version'
- db cr,lf,'$'
-
- msg4 db cr,lf
- db 'dump: empty file'
- db cr,lf
- msg4_len equ $-msg4
-
- _DATA ends
-
-
- STACK segment para stack 'STACK'
-
- db 64 dup (?)
-
- STACK ends
-
- end dump
-
-
- \SAMPCODE\ADVMSDOS\CHAP08\INT24.ASM
-
- title INT24 Critical Error Handler
- page 55,132
-
- ;
- ; INT24.ASM -- Replacement critical error handler
- ;
- ; Copyright (C) September 1987 Ray Duncan
- ;
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII line feed
-
- DGROUP group _DATA
-
- _DATA segment word public 'DATA'
-
- save24 dd 0 ; previous contents of Int 24H
- ; critical error handler vector
-
- ; prompt message used by
- ; critical error handler
- prompt db cr,lf,'Critical Error Occurred: '
- db 'Abort, Retry, Ignore, Fail? $'
-
- keys db 'aArRiIfF' ; possible user response keys
- keys_len equ $-keys ; (both cases of each allowed)
-
- codes db 2,2,1,1,0,0,3,3 ; codes returned to MS-DOS kernel
- ; for corresponding response keys
-
- _DATA ends
-
-
- _TEXT segment word public 'CODE'
-
- assume cs:_TEXT,ds:DGROUP
-
- public get24
- get24 proc near ; set Int 24H vector to point
- ; to new critical error handler
-
- push ds ; save segment registers
- push es
-
- mov ax,3524h ; get address of previous
- int 21h ; INT 24H handler and save it
-
- mov word ptr save24,bx
- mov word ptr save24+2,es
-
- push cs ; set DS:DX to point to
- pop ds ; new INT 24H handler
- mov dx,offset _TEXT:int24
- mov ax,2524h ; then call MS-DOS to
- int 21h ; set the INT 24H vector
-
- pop es ; restore segment registers
- pop ds
- ret ; and return to caller
-
- get24 endp
-
-
- public res24
- res24 proc near ; restore original contents
- ; of Int 24H vector
-
- push ds ; save our data segment
-
- lds dx,save24 ; put address of old handler
- mov ax,2524h ; back into INT 24H vector
- int 21h
-
- pop ds ; restore data segment
- ret ; and return to caller
-
- res24 endp
-
- ;
- ; This is the replacement Critical Error handler. It
- ; prompts the user for Abort, Retry, Ignore, or Fail, and
- ; returns the appropriate code to the MS-DOS kernel.
- ;
- int24 proc far ; entered from MS-DOS kernel
-
- push bx ; save registers
- push cx
- push dx
- push si
- push di
- push bp
- push ds
- push es
-
- int24a: mov ax,DGROUP ; display prompt for user
- mov ds,ax ; using Function 9 (print string
- mov es,ax ; terminated by $ character)
- mov dx,offset prompt
- mov ah,9
- int 21h
-
- mov ah,1 ; get user's response
- int 21h ; Function 1 = read one character
-
- mov di,offset keys ; look up code for response key
- mov cx,keys_len
- cld
- repne scasb
- jnz int24a ; prompt again if bad response
-
- ; set AL = action code for MS-DOS
- ; according to key that was entered:
- ; 0=ignore, 1=retry, 2=abort, 3=fail
- mov al,[di+keys_len-1]
-
- pop es ; restore registers
- pop ds
- pop bp
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- iret ; exit critical error handler
-
- int24 endp
-
- _TEXT ends
-
- end
-
- \SAMPCODE\ADVMSDOS\CHAP08\TRYINT24.ASM
-
- title TRYINT24 -- tests critical error handler
- page 55,132
- ;
- ; TRYINT24.ASM - Test program for INT24.ASM
- ; replacement critical-error handler
- ;
- ; Copyright (C) June 1987 Ray Duncan
- ;
- ; Build: MASM TRYINT24;
- ; MASM INT24;
- ; LINK TRYINT24+INT24;
- ;
- ; Usage: TRYINT24
- ;
-
- stdin equ 0 ; standard input device
- stdout equ 1 ; standard output device
- stderr equ 2 ; standard error device
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII line feed
-
-
- DGROUP group _DATA,STACK ; 'automatic data group'
-
- extrn get24:near
- extrn res24:near
-
- _TEXT segment word public 'CODE'
-
- assume cs:_TEXT,ds:DGROUP,ss:STACK
-
- main proc far ; entry point from MS-DOS
-
- mov ax,DGROUP ; set DS = our data segment
- mov ds,ax
-
- call get24 ; capture int 24h for our
- ; own handler
-
- ; display sign-on message...
- mov dx,offset DGROUP:msg ; DS:DX = address of message
- mov cx,msg_len ; CX = length of message
- mov bx,stdout ; BX = handle for std output
- mov ah,40h ; AH = 40h, write file or device
- int 21h ; transfer to MS-DOS
-
- err: mov dl,'*' ; write character to printer
- mov ah,05 ; to generate a critical error
- int 21h
- jmp err
-
- call res24 ; restore previous int 24h handler
-
- mov ax,4c00h ; no error, terminate program
- int 21h ; with return code = 0
-
- main2: call res24 ; restore previous int 24h handler
-
- mov ax,4c01h ; error, terminate program
- int 21h ; with return code = 1
-
- main endp ; end of main procedure
-
- _TEXT ends
-
-
- _DATA segment word public 'DATA'
-
- msg db cr,lf,'Int 24H Handler Demo',cr,lf
- msg_len equ $-msg
-
- _DATA ends
-
-
- STACK segment para stack 'STACK'
-
- dw 64 dup (?)
-
- STACK ends
-
- end main ; defines program entry point
-
-
- \SAMPCODE\ADVMSDOS\CHAP11
- \SAMPCODE\ADVMSDOS\CHAP11\EXTMEM.ASM
-
- title EXTMEM --- get/put extended memory
- page 55,132
-
- ;
- ; EXTMEM.ASM --- Demonstration of access to
- ; extended memory using ROM BIOS
- ; Int 15H Function 87H
- ;
- ; Copyright (C) June 1988 Ray Duncan
- ;
- ; Build: MASM EXTMEM;
- ; LINK EXTMEM;
- ;
- ; Usage: EXTMEM
- ;
-
- stdin equ 0 ; standard input device
- stdout equ 1 ; standard output device
- stderr equ 2 ; standard error device
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII line feed
-
-
- DGROUP group _DATA,STACK ; 'automatic data group'
-
-
- _DATA segment word public 'DATA'
-
- bmdt db 30h dup (0) ; block move descriptor table
-
- buff1 db 80h dup ('?') ; source buffer
- buff2 db 80h dup (0) ; destination buffer
-
- _DATA ends
-
-
- STACK segment para stack 'STACK'
-
- dw 64 dup (?)
-
- STACK ends
-
-
- _TEXT segment word public 'CODE'
-
- assume cs:_TEXT,ds:DGROUP,ss:STACK
-
- main proc far ; entry point from MS-DOS
-
- mov ax,DGROUP ; set DS = our data segment
- mov ds,ax
- mov es,ax
-
- ; copy 'buff1' to extended
- ; memory address 100000H
- mov dx,10h ; DX:AX = destination
- mov ax,0 ; extended mem. address
- mov bx,seg buff1 ; DS:BX = source conv.
- mov ds,bx ; memory address
- mov bx,offset buff1
- mov cx,80h ; CX = bytes to move
- mov si,seg bmdt ; ES:SI = block move
- mov es,si ; descriptor table
- mov si,offset bmdt
- call putblk ; request transfer
-
-
- ; fill buff2 from extended
- ; memory address 100000H
- mov dx,10h ; DX:AX = source extended
- mov ax,0 ; memory address
- mov bx,seg buff2 ; DS:BX = destination
- mov ds,bx ; conventional mem. address
- mov bx,offset buff2
- mov cx,80h ; CX = bytes to move
- mov si,seg bmdt ; ES:SI = block move
- mov es,si ; descriptor table
- mov si,offset bmdt
- call getblk ; request transfer
-
- mov ax,4c00h ; no error, terminate program
- int 21h ; with return code = 0
-
- main2: mov ax,4c01h ; error, terminate program
- int 21h ; with return code = 1
-
- main endp ; end of main procedure
-
-
-
-
- getblk proc near ; Transfer block from extended
- ; memory to real memory
- ; Call with
- ; DX:AX = linear 32-bit
- ; extended memory address
- ; DS:BX = segment and offset
- ; destination address
- ; CX = length in bytes
- ; ES:SI = block move descriptor table
- ; Returns
- ; AH = 0 if transfer OK
-
- mov es:[si+10h],cx ; store length into descriptors
- mov es:[si+18h],cx
-
- ; store access rights bytes
- mov byte ptr es:[si+15h],93h
- mov byte ptr es:[si+1dh],93h
-
- mov es:[si+12h],ax ; source extended memory address
- mov es:[si+14h],dl
-
- ; convert destination segment
- ; and offset to linear address
- mov ax,ds ; segment * 16
- mov dx,16
- mul dx
- add ax,bx ; + offset -> linear address
- adc dx,0
-
- mov es:[si+1ah],ax ; store destination address
- mov es:[si+1ch],dl
-
- shr cx,1 ; convert length to words
- mov ah,87h ; Int 15H Fxn 87h = block move
- int 15h ; transfer to ROM BIOS
-
- ret ; back to caller
-
- getblk endp
-
-
- putblk proc near ; Transfer block from real
- ; memory to extended memory
- ; Call with
- ; DX:AX = linear 32-bit
- ; extended memory address
- ; DS:BX = segment and offset
- ; source address
- ; CX = length in bytes
- ; ES:SI = block move descriptor table
- ; Returns
- ; AH = 0 if transfer OK
-
- mov es:[si+10h],cx ; store length into descriptors
- mov es:[si+18h],cx
-
- ; store access rights bytes
- mov byte ptr es:[si+15h],93h
- mov byte ptr es:[si+1dh],93h
-
- mov es:[si+1ah],ax ; store destination extended
- mov es:[si+1ch],dl ; memory address
-
- ; convert source segment and
- ; offset to linear address
- mov ax,ds ; segment * 16
- mov dx,16
- mul dx
- add ax,bx ; + offset -> linear address
- adc dx,0
-
- mov es:[si+12h],ax ; store source address
- mov es:[si+14h],dl
-
- shr cx,1 ; convert length to words
- mov ah,87h ; Int 15H Fxn 87h = block move
- int 15h ; transfer to ROM BIOS
-
- ret ; back to caller
-
- putblk endp
-
- _TEXT ends
-
- end main ; defines program entry point
-
-
- \SAMPCODE\ADVMSDOS\CHAP12
- \SAMPCODE\ADVMSDOS\CHAP12\SHELL.C
-
- /*
- SHELL.C Simple extendable command interpreter
- for MS-DOS version 2.0 and later
-
- Copyright 1988 Ray Duncan
-
- Compile: C>CL SHELL.C
-
- Usage: C>SHELL
- */
-
- #include <stdio.h>
- #include <process.h>
- #include <stdlib.h>
- #include <signal.h>
-
- /* ma
- el
- #define dim(x) (sizeof(x) / sizeof(x[0]))
-
- unsigned intrinsic(char *); /* function prototypes */
- void extrinsic(char *);
- void get_cmd(char *);
- void get_comspec(char *);
- void break_handler(void);
- void cls_cmd(void);
- void dos_cmd(void);
- void exit_cmd(void);
-
- struct cmd_table { /* intrinsic commands
- char *cmd_name;
- int (*cmd_fxn)();
- } commands[] =
-
- { "CLS", cls_cmd,
- "DOS", dos_cmd,
- "EXIT", exit_cmd, };
-
- static char com_spec[64]; /* COMMAND.COM filespec */
-
-
- main(int argc, char *argv[])
- {
- char inp_buf[80]; /* keyboard input buffer */
-
- get_comspec(com_spec); /* get COMMAND.COM filespec *
-
- /* re
- for Ctrl-C
- if(signal(SIGINT, break_handler) == (int(*)()) -1)
- {
- fputs("Can't capture Control-C Interrupt", stderr);
- exit(1);
- }
-
- while(1) /* main interpreter loop */
- {
- get_cmd(inp_buf); /* get a command */
- if (! intrinsic(inp_buf) ) /* if it's intrinsic,
- run its subroutine */
- extrinsic(inp_buf); /* else pass to COMMAND.COM */
- }
- }
-
-
- /*
- Try and match user's command with intrinsic command
- table. If a match is found, run the associated routine
- and return true, else return false.
- */
-
- unsigned intrinsic(char *input_string)
- {
- int i, j; /* some scrat
-
- /* sc
- while(*input_string == '\x20') input_string++ ;
-
- /* se
- for(i=0; i < dim(commands); i++)
- {
- j = strcmp(commands[i].cmd_name, input_string);
-
- if(j == 0) /* if match, run rout
- {
- (*commands[i].cmd_fxn)();
- return(1); /* and return true */
- }
- }
- return(0); /* no match, return f
- }
-
-
- /*
- Process an extrinsic command by passing it
- to an EXEC'd copy of COMMAND.COM.
- */
-
- void extrinsic(char *input_string)
- {
- int status;
-
- status = system(input_string); /* call EXEC function */
-
- if(status) /* if failed, display
- er
- fputs("\nEXEC of COMMAND.COM failed\n", stderr);
- }
-
-
- /*
- Issue prompt, get user's command from standard input,
- fold it to upper case.
- */
-
- void get_cmd(char *buffer)
- {
- printf("\nsh: "); /* display prompt */
- gets(buffer); /* get keyboard entry */
- strupr(buffer); /* fold to upper case */
- }
-
-
- /*
- Get the full path and file specification for COMMAND.COM
- from the "COMSPEC=" variable in the environment.
- */
-
- void get_comspec(char *buffer)
- {
- strcpy(buffer, getenv("COMSPEC"));
-
- if(buffer[0] == NULL)
- {
- fputs("\nNo COMSPEC in environment\n", stderr);
- exit(1);
- }
- }
-
-
- /*
- This Ctrl-C handler keeps SHELL from losing control.
- It just re-issues the prompt and returns.
- */
-
- void break_handler(void)
- {
- signal(SIGINT, break_handler); /* reset handler */
- printf("\nsh: "); /* display prompt */
- }
-
-
- /*
- These are the subroutines for the intrinsic commands.
- */
-
- void cls_cmd(void) /* CLS command */
- {
- printf("\033[2J"); /* ANSI escape sequen
- }
-
- void dos_cmd(void) /* DOS command */
- {
- int status;
-
- status = spawnlp(P_WAIT, com_spec, com_spec, NULL);
-
- if (status)
- fputs("\nEXEC of COMMAND.COM failed\n",stderr);
- }
-
- void exit_cmd(void) /* EXIT command */
- {
- exit(0); /* te
- }
-
- \SAMPCODE\ADVMSDOS\CHAP12\SHELL.ASM
-
- name shell
- page 55,132
- title SHELL.ASM -- simple MS-DOS shell
- ;
- ; SHELL.ASM Simple extendable command interpreter
- ; for MS-DOS version 2.0 and later
- ;
- ; Copyright 1988 by Ray Duncan
- ;
- ; Build: C>MASM SHELL;
- ; C>LINK SHELL;
- ;
- ; Usage: C>SHELL;
- ;
-
- stdin equ 0 ; standard input handle
- stdout equ 1 ; standard output handle
- stderr equ 2 ; standard error handle
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII line feed
- blank equ 20h ; ASCII blank code
- escape equ 01bh ; ASCII escape code
-
- _TEXT segment word public 'CODE'
-
- assume cs:_TEXT,ds:_DATA,ss:STACK
-
- shell proc far ; at entry DS = ES = PSP
-
- mov ax,_DATA ; make our data segment
- mov ds,ax ; addressable
-
- mov ax,es:[002ch] ; get environment segment
- mov env_seg,ax ; from PSP and save it
-
- ; release unneeded memory...
- ; ES already = PSP segment
- mov bx,100h ; BX = paragraphs needed
- mov ah,4ah ; Function 4AH = resize block
- int 21h ; transfer to MS-DOS
- jnc shell1 ; jump if resize OK
-
- mov dx,offset msg1 ; resize failed, display
- mov cx,msg1_length ; error message and exit
- jmp shell4
-
- shell1: call get_comspec ; get COMMAND.COM filespec
- jnc shell2 ; jump if it was found
-
- mov dx,offset msg3 ; COMSPEC not found in
- mov cx,msg3_length ; environment, display error
- jmp shell4 ; message and exit
-
- shell2: mov dx,offset shell3 ; set Ctrl-C vector (Int 23H)
- mov ax,cs ; for this program's handler
- mov ds,ax ; DS:DX = handler address
- mov ax,2523H ; Fxn 25H = set vector
- int 21h ; transfer to MS-DOS
-
- mov ax,_DATA ; make our data segment
- mov ds,ax ; addressable again
- mov es,ax
-
- shell3: ; main interpreter loop
-
- call get_cmd ; get a command from user
-
- call intrinsic ; check if intrinsic function
- jnc shell3 ; yes, it was processed
-
- call extrinsic ; no, pass it to COMMAND.COM
- jmp shell3 ; then get another command
-
- shell4: ; come here if error detected
- ; DS:DX = message address
- ; CX = message length
- mov bx,stderr ; BX = standard error handle
- mov ah,40h ; Fxn 40H = write
- int 21h ; transfer to MS-DOS
-
- mov ax,4c01h ; Fxn 4CH = terminate with
- ; return code = 1
- int 21h ; transfer to MS-DOS
-
- shell endp
-
-
- intrinsic proc near ; Decode user entry against
- ; the table "COMMANDS"
- ; If match, run the routine,
- ; and return Carry = False
- ; If no match, Carry = True
- ; return Carry = True.
-
- mov si,offset commands ; DS:SI = command table
-
- intr1: cmp byte ptr [si],0 ; end of table?
- je intr7 ; jump, end of table found
-
- mov di,offset inp_buf ; no, let DI = addr of user input
-
- intr2: cmp byte ptr [di],blank ; scan off any leading blanks
- jne intr3
-
- inc di ; found blank, go past it
- jmp intr2
-
- intr3: mov al,[si] ; next character from table
-
- or al,al ; end of string?
- jz intr4 ; jump, entire string matched
-
- cmp al,[di] ; compare to input character
- jnz intr6 ; jump, found mismatch
-
- inc si ; advance string pointers
- inc di
- jmp intr3
-
- intr4: cmp byte ptr [di],cr ; make sure user's entry
- je intr5 ; is the same length...
- cmp byte ptr [di],blank ; next character in entry
- jne intr6 ; must be blank or Return
-
- intr5: call word ptr [si+1] ; run the command routine
-
- clc ; return Carry Flag = False
- ret ; as success flag
-
- intr6: lodsb ; look for end of this
- or al,al ; command string (null byte)
- jnz intr6 ; not end yet, loop
-
- add si,2 ; skip over routine address
- jmp intr1 ; try to match next command
-
- intr7: stc ; command not matched, exit
- ret ; with Carry = True
-
- intrinsic endp
-
-
- extrinsic proc near ; process extrinsic command
- ; by passing it to
- ; COMMAND.COM with a
- ; " /C " command tail.
-
- mov al,cr ; find length of command
- mov cx,cmd_tail_length ; by scanning for carriage
- mov di,offset cmd_tail+1 ; return
- cld
- repnz scasb
-
- mov ax,di ; calculate command tail
- sub ax,offset cmd_tail+2 ; length without carriage
- mov cmd_tail,al ; return, and store it
-
- ; set command tail address
- mov word ptr par_cmd,offset cmd_tail
- call exec ; and run COMMAND.COM
- ret
-
- extrinsic endp
-
-
- get_cmd proc near ; prompt user, get command
-
- ; display the shell prompt
- mov dx,offset prompt ; DS:DX = message address
- mov cx,prompt_length ; CX = message length
- mov bx,stdout ; BX = standard output handle
- mov ah,40h ; Fxn 40H = write
- int 21h ; transfer to MS-DOS
-
- ; get entry from user
- mov dx,offset inp_buf ; DS:DX = input buffer
- mov cx,inp_buf_length ; CX = max length to read
- mov bx,stdin ; BX = standard input handle
- mov ah,3fh ; Fxn 3FH = read
- int 21h ; transfer to MS-DOS
-
- mov si,offset inp_buf ; fold lower case characters
- mov cx,inp_buf_length ; in entry to upper case
-
- gcmd1: cmp byte ptr [si],'a' ; check if 'a-z'
- jb gcmd2 ; jump, not in range
- cmp byte ptr [si],'z' ; check if 'a-z'
- ja gcmd2 ; jump, not in range
- sub byte ptr [si],'a'-'A' ; convert to upper case
-
- gcmd2: inc si ; advance through entry
- loop gcmd1
- ret ; back to caller
-
- get_cmd endp
-
-
- get_comspec proc near ; get location of COMMAND.COM
- ; from environment "COMSPEC="
- ; Returns Carry = False
- ; if COMSPEC found.
- ; Returns Carry=True
- ; if no COMSPEC.
-
- mov si,offset com_var ; DS:SI = string to match...
- call get_env ; search Environment Block
- jc gcsp2 ; jump if COMSPEC not found
-
- ; ES:DI points past "="
- mov si,offset com_spec ; DS:SI = local buffer
-
- gcsp1: mov al,es:[di] ; copy COMSPEC variable
- mov [si],al ; to local buffer
- inc si
- inc di
- or al,al ; null char? (turns off Carry)
- jnz gcsp1 ; no, get next character
-
- gcsp2: ret ; back to caller
-
- get_comspec endp
-
-
- get_env proc near ; search environment
- ; Call DS:SI = "NAME="
- ; uses contents of "ENV_SEG"
- ; Returns Carry=False and ES:DI
- ; pointing to parameter if found,
- ; Returns Carry=True if no match
-
- mov es,env_seg ; get environment segment
- xor di,di ; initialize env. offset
-
- genv1: mov bx,si ; initialize pointer to name
- cmp byte ptr es:[di],0 ; end of environment?
- jne genv2 ; jump, end not found
-
- stc ; no match, return Carry set
- ret
-
- genv2: mov al,[bx] ; get character from name
- or al,al ; end of name? (turns off Carry)
- jz genv3 ; yes, name matched
-
- cmp al,es:[di] ; compare to environment
- jne genv4 ; jump if match failed
-
- inc bx ; advance environment
- inc di ; and name pointers
- jmp genv2
-
- genv3: ; match found, Carry = clear,
- ret ; ES:DI = variable
-
- genv4: xor al,al ; scan forward in environment
- mov cx,-1 ; for zero byte
- cld
- repnz scasb
- jmp genv1 ; go compare next string
-
- get_env endp
-
-
- exec proc near ; call MS-DOS EXEC function
- ; to run COMMAND.COM.
-
- mov stkseg,ss ; save stack pointer
- mov stkptr,sp
-
- ; now run COMMAND.COM
- mov dx,offset com_spec ; DS:DX = filename
- mov bx,offset par_blk ; ES:BX = parameter block
- mov ax,4b00h ; Fxn 4BH = EXEC
- ; Subf. 0 = load and execute
- int 21h ; transfer to MS-DOS
-
- mov ax,_DATA ; make data segment
- mov ds,ax ; addressable again
- mov es,ax
-
- cli ; (for bug in some 8088s)
- mov ss,stkseg ; restore stack pointer
- mov sp,stkptr
- sti ; (for bug in some 8088s)
-
- jnc exec1 ; jump if no errors
-
- ; display error message
- mov dx,offset msg2 ; DS:DX = message address
- mov cx,msg2_length ; CX = message length
- mov bx,stderr ; BX = standard error handle
- mov ah,40h ; Fxn 40H = write
- int 21h ; transfer to MS-DOS
-
- exec1: ret ; back to caller
-
- exec endp
-
-
- cls_cmd proc near ; intrinsic CLS command
-
- mov dx,offset cls_str ; send the ANSI escape
- mov cx,cls_str_length ; sequence to clear
- mov bx,stdout ; the screen
- mov ah,40h
- int 21h
- ret
-
- cls_cmd endp
-
-
- dos_cmd proc near ; intrinsic DOS command
-
- ; set null command tail
- mov word ptr par_cmd,offset nultail
- call exec ; and run COMMAND.COM
- ret
-
- dos_cmd endp
-
-
- exit_cmd proc near ; intrinsic EXIT Command
-
- mov ax,4c00h ; call MS-DOS terminate
- int 21h ; function with
- ; return code of zero
- exit_cmd endp
-
- _TEXT ends
-
-
- STACK segment para stack 'STACK' ; declare stack segment
-
- dw 64 dup (?)
-
- STACK ends
-
-
- _DATA segment word public 'DATA'
-
- commands equ $ ; "intrinsic" commands table
- ; each entry is ASCIIZ string
- ; followed by the offset
- ; of the procedure to be
- ; executed for that command.
- db 'CLS',0
- dw cls_cmd
-
- db 'DOS',0
- dw dos_cmd
-
- db 'EXIT',0
- dw exit_cmd
-
- db 0 ; end of table
-
- com_var db 'COMSPEC=',0 ; environment variable
-
- ; COMMAND.COM filespec
- com_spec db 80 dup (0) ; from environment COMSPEC=
-
- nultail db 0,cr ; null command tail for
- ; invoking COMMAND.COM
- ; as another shell
-
- cmd_tail db 0,' /C ' ; command tail for invoking
- ; COMMAND.COM as a transient
-
- inp_buf db 80 dup (0) ; command line from Standard Input
-
- inp_buf_length equ $-inp_buf
- cmd_tail_length equ $-cmd_tail-1
-
- prompt db cr,lf,'sh: ' ; SHELL's user prompt
- prompt_length equ $-prompt
-
- env_seg dw 0 ; segment of Environment Block
-
- msg1 db cr,lf
- db 'Unable to release memory.'
- db cr,lf
- msg1_length equ $-msg1
-
- msg2 db cr,lf
- db 'EXEC of COMMAND.COM failed.'
- db cr,lf
- msg2_length equ $-msg2
-
- msg3 db cr,lf
- db 'No COMSPEC variable in environment.'
- db cr,lf
- msg3_length equ $-msg3
-
- cls_str db escape,'[2J' ; ANSI escape sequence
- cls_str_length equ $-cls_str ; to clear the screen
-
- ; EXEC parameter block
- par_blk dw 0 ; environment segment
- par_cmd dd cmd_tail ; command line
- dd fcb1 ; file control block #1
- dd fcb2 ; file control block #2
-
- fcb1 db 0 ; file control block #1
- db 11 dup (' ')
- db 25 dup (0)
-
- fcb2 db 0 ; file control block #2
- db 11 dup (' ')
- db 25 dup (0)
-
- stkseg dw 0 ; original SS contents
- stkptr dw 0 ; original SP contents
-
- _DATA ends
-
- end shell
-
- \SAMPCODE\ADVMSDOS\CHAP13
- \SAMPCODE\ADVMSDOS\CHAP13\TEST0DIV.ASM
-
- title TEST0DIV - test for ZERODIV.COM
- page 55,132
-
- ;
- ; TEST0DIV.ASM: Test program for the ZERODIV.ASM
- ; divide-by-zero interrupt handler
- ;
- ; Copyright (C) 1988 Ray Duncan
- ;
- ; Build: MASM TEST0DIV;
- ; LINK TEST0DIV;
- ;
- ; Usage: ZERODIV (load divide by zero handler)
- ; TEST0DIV (exercise the handler)
- ;
-
- cr equ 0dh ;ASCII carriage return
- lf equ 0ah ;ASCII line feed
-
- _TEXT segment word public 'CODE'
-
- org 100H
-
- assume cs:_TEXT,ds:_TEXT,es:_TEXT,ss:_TEXT
-
- main proc near
-
- mov dx,offset signon ; display sign-on message
- mov ah,9
- int 21h
-
- mov dx,0 ; try register divide
- mov ax,1
- mov bx,0
- div bx
-
- mov dx,offset msg1 ; display success message
- mov ah,9
- int 21h
-
- mov dx,0 ; try direct divide
- mov ax,1
- div word ptr zerow
-
- mov dx,offset msg2 ; display success message
- mov ah,9
- int 21h
-
- mov dx,0 ; try mod = 1 divide
- mov ax,1
- mov bx,offset zerow
- dec bx
- div word ptr [bx+1]
-
- mov dx,offset msg3 ; display success message
- mov ah,9
- int 21h
-
- mov dx,0 ; try mod = 2 divide
- mov ax,1
- mov bx,0
- div word ptr [bx+offset zerow2]
-
- mov dx,offset msg4 ; display success message
- mov ah,9
- int 21h
-
- mov ax,4c00h ; exit to MS-DOS
- int 21h
-
- main endp
-
- signon db cr,lf,'Zero Divide Test program',cr,lf,'$'
-
- msg1 db cr,lf,'Back from register divide',cr,lf,'$'
-
- msg2 db cr,lf,'Back from direct mem divide',cr,lf,'$'
-
- msg3 db cr,lf,'Back from mod = 1 divide',cr,lf,'$'
-
- msg4 db cr,lf,'Back from mod = 2 divide',cr,lf,'$'
-
- zerob db 0 ; byte-sized operand
- zerow dw 0 ; word-sized operand
-
- db 256 dup (?) ; some empty space
-
- zerow2 dw 0
-
- _TEXT ends
-
- end main
-
-
- \SAMPCODE\ADVMSDOS\CHAP13\ZERODIV.ASM
-
- title ZERODIV --- Divide by zero handler
- page 55,132
-
- ;
- ; ZERODIV.ASM --- Terminate-and-stay-resident handler
- ; for divide-by-zero interrupts
- ;
- ; Copyright 1988 Ray Duncan
- ;
- ; Build: C>MASM ZERODIV;
- ; C>LINK ZERODIV;
- ; C>EXE2BIN ZERODIV.EXE ZERODIV.COM
- ; C>DEL ZERODIV.EXE
- ;
- ; Usage: C>ZERODIV
- ;
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII line feed
- beep equ 07h ; ASCII bell code
- backsp equ 08h ; ASCII backspace code
-
- _TEXT segment word public 'CODE'
-
- org 100H
-
- assume cs:_TEXT,ds:_TEXT,es:_TEXT,ss:_TEXT
-
-
- init proc near ; entry point at load time
-
- ; capture vector for
- ; interrupt zero ...
- mov dx,offset zdiv ; DS:DX = handler address
- mov ax,2500h ; Fxn 25H = set vector
- ; interrupt type = 0
- int 21h ; transfer to MS-DOS
-
- ; print sign-on message
- mov dx,offset msg1 ; DS:DX = message address
- mov ah,9 ; Fxn 09H = display string
- int 21h ; transfer to MS-DOS
-
- ; DX = paragraphs to reserve
- mov dx,((offset pgm_len+15)/16)+10h
- mov ax,3100h ; Fxn 31H = terminate and
- ; stay resident
- int 21h ; transfer to MS-DOS
-
- init endp
-
-
- zdiv proc far ; this is the divide by
- ; zero interrupt handler
-
- sti ; enable interrupts
-
- push ax ; save registers
- push bx
- push cx
- push dx
- push si
- push di
- push bp
- push ds
- push es
-
- mov ax,cs ; make data addressable
- mov ds,ax
-
- ; display message
- ; "Continue or Quit?"
- mov dx,offset msg2 ; DS:DX = message address
- mov ah,9 ; Fxn 09H = display string
- int 21h ; transfer to MS-DOS
-
- zdiv1: mov ah,1 ; Fxn 01H = read keyboard
- int 21h ; transfer to MS-DOS
-
- or al,20h ; fold char. to lower case
-
- cmp al,'c' ; is it C or Q?
- je zdiv3 ; jump, it's a C
-
- cmp al,'q'
- je zdiv2 ; jump, it's a Q
-
- ; illegal entry, send beep
- ; and erase the character
- mov dx,offset msg3 ; DS:DX = message address
- mov ah,9 ; Fxn 09H = display string
- int 21h ; transfer to MS-DOS
-
- jmp zdiv1 ; try again
-
- zdiv2: ; user picked "Quit"
- mov ax,4cffh ; terminate current program
- int 21h ; with return code = 255
-
- zdiv3: ; user picked "Continue"
- ; send CR-LF pair
- mov dx,offset msg4 ; DS:DX = message address
- mov ah,9 ; Fxn 09H = print string
- int 21h ; transfer to MS-DOS
-
- ; what CPU type is this?
- xor ax,ax ; to find out, we'll put
- push ax ; zero in the CPU flags
- popf ; and see what happens
- pushf
- pop ax
- and ax,0f000h ; 8086/88 forces
- cmp ax,0f000h ; bits 12-15 true
- je zdiv5 ; jump if 8086/88
-
- ; otherwise we must adjust
- ; return address to bypass
- ; the divide instruction...
- mov bp,sp ; make stack addressable
-
- lds bx,[bp+18] ; get address of the
- ; faulting instruction
-
- mov bl,[bx+1] ; get addressing byte
- and bx,0c7h ; isolate mod & r/m fields
-
- cmp bl,6 ; mod 0, r/m 6 = direct
- jne zdiv4 ; not direct, jump
-
- add word ptr [bp+18],4
- jmp zdiv5
-
- zdiv4: mov cl,6 ; otherwise isolate mod
- shr bx,cl ; field and get instruction
- mov bl,cs:[bx+itab] ; size from table
- add [bp+18],bx
-
- zdiv5: pop es ; restore registers
- pop ds
- pop bp
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- iret ; return from interrupt
-
- zdiv endp
-
-
- msg1 db cr,lf ; load-time signon message
- db 'Divide by Zero Interrupt '
- db 'Handler installed.'
- db cr,lf,'$'
-
- msg2 db cr,lf,lf ; interrupt-time message
- db 'Divide by Zero detected: '
- db cr,lf,'Continue or Quit (C/Q) ? '
- db '$'
-
- msg3 db beep ; used if bad entry
- db backsp,' ',backsp,'$'
-
- msg4 db cr,lf,'$' ; carriage return-line feed
-
- ; instruction size table
- itab db 2 ; mod = 0
- db 3 ; mod = 1
- db 4 ; mod = 2
- db 2 ; mod = 3
-
- pgm_len equ $-init ; program length
-
- _TEXT ends
-
- end init
-
-
- \SAMPCODE\ADVMSDOS\CHAP14
- \SAMPCODE\ADVMSDOS\CHAP14\DRIVER.ASM
-
- title DRIVER.ASM Device Driver Skeleton
- page 55,132
-
- ;
- ; DRIVER.ASM MS-DOS device driver skeleton
- ;
- ; The driver command code routines are stubs only and have
- ; no effect but to return a non-error "Done" status.
- ;
- ; Copyright (C) 1988 Ray Duncan
- ;
- ; Build: MASM DRIVER;
- ; LINK DRIVER;
- ; EXE2BIN DRIVER.EXE DRIVER.SYS
- ; DEL DRIVER.EXE
- ;
- ; Usage: DEVICE=DRIVER.SYS (in file CONFIG.SYS)
- ;
-
- _TEXT segment word public 'CODE'
-
- assume cs:_TEXT,ds:_TEXT,es:NOTHING
-
- org 0
-
- MaxCmd equ 24 ; maximum allowed command code
- ; 12 for MS-DOS 2.x
- ; 16 for MS-DOS 3.0-3.1
- ; 24 for MS-DOS 3.2-3.3
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII line feed
- eom equ '$' ; end of message signal
-
-
- Header: ; device driver header
- dd -1 ; link to next device driver
- dw 0c840h ; device attribute word
- dw Strat ; "Strategy" routine entry point
- dw Intr ; "Interrupt" routine entry point
- db 'SKELETON' ; logical device name
-
-
- RHPtr dd ? ; pointer to request header, passed
- ; by MS-DOS kernel to Strategy routine
-
-
- Dispatch: ; Interrupt routine command code
- ; dispatch table.
- dw Init ; 0 = initialize driver
- dw MediaChk ; 1 = media check
- dw BuildBPB ; 2 = build BIOS parameter block
- dw IoctlRd ; 3 = I/O control read
- dw Read ; 4 = read
- dw NdRead ; 5 = non-destructive read
- dw InpStat ; 6 = input status
- dw InpFlush ; 7 = flush input buffers
- dw Write ; 8 = write
- dw WriteVfy ; 9 = write with verify
- dw OutStat ; 10 = output status
- dw OutFlush ; 11 = flush output buffers
- dw IoctlWt ; 12 = I/O control write
- dw DevOpen ; 13 = device open (MS-DOS 3.0+)
- dw DevClose ; 14 = device close (MS-DOS 3.0+)
- dw RemMedia ; 15 = removeable media (MS-DOS 3.0+)
- dw OutBusy ; 16 = output until busy (MS-DOS 3.0+)
- dw Error ; 17 = not used
- dw Error ; 18 = not used
- dw GenIOCTL ; 19 = generic IOCTL (MS-DOS 3.2+)
- dw Error ; 20 = not used
- dw Error ; 21 = not used
- dw Error ; 22 = not used
- dw GetLogDev ; 23 = get logical device (MS-DOS 3.2+)
- dw SetLogDev ; 24 = set logical device (MS-DOS 3.2+)
-
-
- Strat proc far ; device driver Strategy routine,
- ; called by MS-DOS kernel with
- ; ES:BX = address of request header
-
- ; save pointer to request header
- mov word ptr cs:[RHPtr],bx
- mov word ptr cs:[RHPtr+2],es
-
- ret ; back to MS-DOS kernel
-
- Strat endp
-
-
- Intr proc far ; device driver Interrupt routine,
- ; called by MS-DOS kernel immediately
- ; after call to Strategy routine
-
- push ax ; save general registers
- push bx
- push cx
- push dx
- push ds
- push es
- push di
- push si
- push bp
-
- push cs ; make local data addressable
- pop ds ; by setting DS = CS
-
- les di,[RHPtr] ; let ES:DI = request header
-
- ; get BX = command code
- mov bl,es:[di+2]
- xor bh,bh
- cmp bx,MaxCmd ; make sure it's legal
- jle Intr1 ; jump, function code is ok
- call Error ; set error bit, "Unknown Command" code
- jmp Intr2
-
- Intr1: shl bx,1 ; form index to dispatch table
- ; and branch to command code routine
- call word ptr [bx+Dispatch]
-
- les di,[RHPtr] ; ES:DI = addr. of request header
-
- Intr2: or ax,0100h ; merge 'Done' bit into status, and
- mov es:[di+3],ax ; store status into request header
-
- pop bp ; restore general registers
- pop si
- pop di
- pop es
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- ret ; back to MS-DOS kernel
-
-
- ; Command code routines are called by the Interrupt routine
- ; via the Dispatch table with ES:DI pointing to the request
- ; header. Each routine should return AX=0 if function was
- ; completed successfully, or AX = 8000h + error code if
- ; function failed.
-
-
- MediaChk proc near ; function 1 = Media Check
-
- xor ax,ax
- ret
-
- MediaChk endp
-
-
- BuildBPB proc near ; function 2 = Build BPB
-
- xor ax,ax
- ret
-
- BuildBPB endp
-
-
- IoctlRd proc near ; function 3 = I/O Control Read
-
- xor ax,ax
- ret
-
- IoctlRd endp
-
-
- Read proc near ; function 4 = Read (Input)
-
- xor ax,ax
- ret
-
- Read endp
-
-
- NdRead proc near ; function 5 = Non-Destructive Read
-
- xor ax,ax
- ret
-
- NdRead endp
-
-
- InpStat proc near ; function 6 = Input Status
-
- xor ax,ax
- ret
-
- InpStat endp
-
-
- InpFlush proc near ; function 7 = Flush Input Buffers
-
- xor ax,ax
- ret
-
- InpFlush endp
-
-
- Write proc near ; function 8 = Write (Output)
-
- xor ax,ax
- ret
-
- Write endp
-
-
- WriteVfy proc near ; function 9 = Write with Verify
-
- xor ax,ax
- ret
-
- WriteVfy endp
-
-
- OutStat proc near ; function 10 = Output Status
-
- xor ax,ax
- ret
-
- OutStat endp
-
-
- OutFlush proc near ; function 11 = Flush Output Buffers
-
- xor ax,ax
- ret
-
- OutFlush endp
-
-
- IoctlWt proc near ; function 12 = I/O Control Write
-
- xor ax,ax
- ret
-
- IoctlWt endp
-
-
- DevOpen proc near ; function 13 = Device Open
-
- xor ax,ax
- ret
-
- DevOpen endp
-
-
- DevClose proc near ; function 14 = Device Close
-
- xor ax,ax
- ret
-
- DevClose endp
-
-
- RemMedia proc near ; function 15 = Removable Media
-
- xor ax,ax
- ret
-
- RemMedia endp
-
-
- OutBusy proc near ; function 16 = Output Until Busy
-
- xor ax,ax
- ret
-
- OutBusy endp
-
-
- GenIOCTL proc near ; function 19 = Generic IOCTL
-
- xor ax,ax
- ret
-
- GenIOCTL endp
-
-
- GetLogDev proc near ; function 23 = Get Logical Device
-
- xor ax,ax
- ret
-
- GetLogDev endp
-
-
- SetLogDev proc near ; function 24 = Set Logical Device
-
- xor ax,ax
- ret
-
- SetLogDev endp
-
-
- Error proc near ; bad command code in request header
-
- mov ax,8003h ; error bit + "Unknown Command" code
- ret
-
- Error endp
-
-
- Init proc near ; function 0 = initialize driver
-
- push es ; save address of request header
- push di
-
- mov ax,cs ; convert load address to ASCII
- mov bx,offset Ident1
- call hexasc
-
- mov ah,9 ; display driver sign-on message
- mov dx,offset Ident
- int 21h
-
- pop di ; restore request header address
- pop es
-
- ; set addr. of free memory
- ; above driver (break address)
- mov word ptr es:[di+14],offset Init
- mov word ptr es:[di+16],cs
-
- xor ax,ax ; return status
- ret
-
- Init endp
-
-
- hexasc proc near ; converts word to hex ASCII
- ; call with AX = value,
- ; DS:BX = address for string
- ; returns AX, BX destroyed
-
- push cx ; save registers
- push dx
-
- mov dx,4 ; initialize character counter
-
- hexasc1:
- mov cx,4 ; isolate next four bits
- rol ax,cl
- mov cx,ax
- and cx,0fh
- add cx,'0' ; convert to ASCII
- cmp cx,'9' ; is it 0-9?
- jbe hexasc2 ; yes, jump
- add cx,'A'-'9'-1 ; add fudge factor for A-F
-
- hexasc2: ; store this character
- mov [bx],cl
- inc bx ; bump string pointer
-
- dec dx ; count characters converted
- jnz hexasc1 ; loop, not four yet
-
- pop dx ; restore registers
- pop cx
- ret ; back to caller
-
- hexasc endp
-
-
- Ident db cr,lf,lf
- db 'Advanced MS-DOS Example Device Driver'
- db cr,lf
- db 'Device driver header at: '
- Ident1 db 'XXXX:0000'
- db cr,lf,lf,eom
-
- Intr endp
-
- _TEXT ends
-
- end
-
-
- \SAMPCODE\ADVMSDOS\CHAP15
- \SAMPCODE\ADVMSDOS\CHAP15\CLEAN.C
-
- /*
- CLEAN.C Filter to turn document files into
- normal text files.
-
- Copyright 1988 Ray Duncan
-
- Compile: C>CL CLEAN.C
-
- Usage: C>CLEAN <infile >outfile
-
- All text characters are passed through with high bit stripped
- off. Form feeds, carriage returns, and line feeds are passed
- through. Tabs are expanded to spaces. All other control codes
- are discarded.
- */
-
- #include <stdio.h>
-
- #define TAB_WIDTH 8 /* width of a tab stop */
-
- #define TAB '\x09' /* ASCII tab character */
- #define LF '\x0A' /* ASCII line feed */
- #define FF '\x0C' /* ASCII form feed */
- #define CR '\x0D' /* ASCII carriage return */
- #define BLANK '\x20' /* ASCII space code */
- #define EOFMK '\x1A' /* Ctrl-Z end of file */
-
-
- main(int argc, char *argv[])
- {
- char c; /* char. from stdin */
- int col = 0; /* column counter */
-
- while((c = getchar()) != EOF) /* read input character */
- {
- c &= 0x07F; /* strip high bit */
-
- switch(c) /* decode character */
- {
- case LF: /* if line feed or */
- case CR: /* carriage return, */
- col=0; /* reset column count */
-
- case FF: /* if form feed, carriage */
- wchar(c); /* return, or line feed */
- break; /* pass character through */
-
- case TAB: /* if tab expand to spaces */
- do wchar(BLANK);
- while((++col % TAB_WIDTH) != 0);
- break;
-
- default: /* discard other control */
- if(c >= BLANK) /* characters, pass text */
- { /* characters through */
- wchar(c);
- col++; /* bump column counter */
- }
- break;
- }
- }
- wchar(EOFMK); /* write end-of-file mark */
- exit(0);
- }
-
-
- /*
- Write a character to the standard output. If
- write fails, display error message and terminate.
- */
-
- wchar(char c)
- {
- if((putchar(c) == EOF) && (c != EOFMK))
- {
- fputs("clean: disk full",stderr);
- exit(1);
- }
- }
-
- \SAMPCODE\ADVMSDOS\CHAP15\PROTO.C
-
- /*
- PROTO.C: prototype character-oriented filter
-
- Copyright 1988 Ray Duncan
-
- Build: CL PROTO.C
-
- */
-
- #include <stdio.h>
-
- main(int argc, char *argv[])
- {
- char ch;
-
- while((ch=getchar()) != EOF) /* read a character */
- {
- ch = translate(ch); /* translate it if necessary */
-
- putchar(ch); /* write the character */
- }
- exit(0); /* terminate at end of file */
- }
-
-
- /*
- Perform any necessary translation on character
- from input file. This example just returns
- the same character.
- */
-
- int translate(char ch)
- {
- return (ch);
- }
-
- \SAMPCODE\ADVMSDOS\CHAP15\CLEAN.ASM
-
- title CLEAN - Text file filter
- page 55,132
- ;
- ; CLEAN.ASM Filter to turn document files into
- ; normal text files.
- ;
- ; Copyright 1988 Ray Duncan
- ;
- ; Build: C>MASM CLEAN;
- ; C>LINK CLEAN;
- ;
- ; Usage: C>CLEAN <infile >outfile
- ;
- ; All text characters are passed through with high
- ; bit stripped off. Form feeds, carriage returns,
- ; and line feeds are passed through. Tabs are expanded
- ; to spaces. All other control codes are discarded.
- ;
-
- tab equ 09h ; ASCII tab code
- lf equ 0ah ; ASCII line feed
- ff equ 0ch ; ASCII form feed
- cr equ 0dh ; ASCII carriage return
- blank equ 020h ; ASCII space code
- eof equ 01ah ; Ctrl-Z End-of-file
-
- tabsiz equ 8 ; width of tab stop
-
- bufsiz equ 128 ; size of input and
- ; output buffers
-
- stdin equ 0000 ; standard input handle
- stdout equ 0001 ; standard output handle
- stderr equ 0002 ; standard error handle
-
-
- _TEXT segment word public 'CODE'
-
- assume cs:_TEXT,ds:_DATA,es:_DATA,ss:STACK
-
- clean proc far ; entry point from MS-DOS.
-
- push ds ; save DS:0000 for final
- xor ax,ax ; return to MS-DOS, in case
- push ax ; Function 4CH can't be used.
-
- mov ax,_DATA ; make data segment addressable
- mov ds,ax
- mov es,ax
-
- mov ah,30h ; check version of MS-DOS
- int 21h
- cmp al,2 ; MS-DOS 2.0 or later?
- jae clean1 ; jump if version OK
-
- ; MS-DOS 1.x, display error
- ; message and exit...
- mov dx,offset msg1 ; DS:DX = message address
- mov ah,9 ; Fxn 9 = display string
- int 21h ; transfer to MS-DOS
- ret ; then exit the old way
-
- clean1: call init ; initialize input buffer
-
- clean2: call getc ; get character from input
- jc clean9 ; exit if end of stream
-
- and al,07fh ; strip off high bit
-
- cmp al,blank ; is it a control char?
- jae clean4 ; no, write it
-
- cmp al,eof ; is it end of file?
- je clean8 ; yes, write EOF and exit
-
- cmp al,tab ; is it a tab?
- je clean6 ; yes, expand it to spaces
-
- cmp al,cr ; is it a carriage return?
- je clean3 ; yes, go process it.
-
- cmp al,lf ; is it a line feed?
- je clean3 ; yes, go process it.
-
- cmp al,ff ; is it a form feed?
- jne clean2 ; no, discard it
-
- clean3: mov column,0 ; if CR, LF, or FF
- jmp clean5 ; reset column to zero
-
- clean4: inc column ; if non-control char.
- ; increment column counter
-
- clean5: call putc ; write char. to stdout
- jnc clean2 ; if disk not full,
- ; get another character
-
- ; write failed...
- mov dx,offset msg2 ; DS:DX = error message
- mov cx,msg2_len ; CX = message length
- mov bx,stderr ; BX = standard error handle
- mov ah,40h ; Fxn 40H = write
- int 21h ; transfer to MS-DOS
-
- mov ax,4c01h ; Fxn 4CH = terminate
- ; return code = 1
- int 21h ; transfer to MS-DOS
-
- clean6: mov ax,column ; tab code detected
- cwd ; tabsiz - (column MOD tabsiz)
- mov cx,tabsiz ; is number of spaces needed
- idiv cx ; to move to next tab stop
- sub cx,dx
-
- add column,cx ; also update column counter
-
- clean7: push cx ; save spaces counter
-
- mov al,blank ; write an ASCII space
- call putc
-
- pop cx ; restore spaces counter
- loop clean7 ; loop until tab stop
-
- jmp clean2 ; get another character
-
- clean8: call putc ; write EOF mark
-
- clean9: call flush ; write last output buffer
- mov ax,4c00h ; Fxn 4CH = terminate
- ; return code =0
- int 21h ; transfer to MS-DOS
-
- clean endp
-
-
- getc proc near ; get char. from stdin
- ; returns Carry = 1 if
- ; end of input, else
- ; AL = char, Carry = 0
-
- mov bx,iptr ; get input buffer pointer
- cmp bx,ilen ; end of buffer reached?
- jne getc1 ; not yet, jump
-
- ; more data is needed...
- mov bx,stdin ; BX = standard input handle
- mov cx,bufsiz ; CX = length to read
- mov dx,offset ibuff ; DS:DX = buffer address
- mov ah,3fh ; Fxn 3FH = read
- int 21h ; transfer to MS-DOS
- jc getc2 ; jump if read failed
-
- or ax,ax ; was anything read?
- jz getc2 ; jump if end of input
-
- mov ilen,ax ; save length of data
- xor bx,bx ; reset buffer pointer
-
- getc1: mov al,[ibuff+bx] ; get char. from buffer
- inc bx ; bump buffer pointer
-
- mov iptr,bx ; save updated pointer
- clc ; return char in AL
- ret ; and Carry = 0 (clear)
-
- getc2: stc ; end of input stream
- ret ; return Carry = 1 (set)
-
- getc endp
-
-
- putc proc near ; send char. to stdout
- ; returns Carry = 1 if
- ; error, else Carry = 0
-
- mov bx,optr ; store character into
- mov [obuff+bx],al ; output buffer
-
- inc bx ; bump buffer pointer
- cmp bx,bufsiz ; buffer full?
- jne putc1 ; no, jump
-
- mov bx,stdout ; BX = standard output handle
- mov cx,bufsiz ; CX = length to write
- mov dx,offset obuff ; DS:DX = buffer address
- mov ah,40h ; Fxn 40H = write
- int 21h ; transfer to MS-DOS
- jc putc2 ; jump if write failed
-
- cmp ax,cx ; was write complete?
- jne putc2 ; jump if disk full
-
- xor bx,bx ; reset buffer pointer
-
- putc1: mov optr,bx ; save buffer pointer
- clc ; write successful,
- ret ; return Carry = 0 (clear)
-
- putc2: stc ; write failed or disk full,
- ret ; return Carry = 1 (set)
-
- putc endp
-
-
- init proc near ; initialize input buffer
-
- mov bx,stdin ; BX = standard input handle
- mov cx,bufsiz ; CX = length to read
- mov dx,offset ibuff ; DS:DX = buffer address
- mov ah,3fh ; Fxn 3FH = read
- int 21h ; transfer to MS-DOS
- jc init1 ; jump if read failed
- mov ilen,ax ; save actual bytes read
- init1: ret
-
- init endp
-
-
- flush proc near ; flush output buffer
-
- mov cx,optr ; CX = bytes to write
- jcxz flush1 ; exit if buffer empty
- mov dx,offset obuff ; DS:DX = buffer address
- mov bx,stdout ; BX = standard output handle
- mov ah,40h ; Fxn 40H = write
- int 21h ; transfer to MS-DOS
- flush1: ret
-
- flush endp
-
- _TEXT ends
-
-
- _DATA segment word public 'DATA'
-
- ibuff db bufsiz dup (0) ; input buffer
- obuff db bufsiz dup (0) ; output buffer
-
- iptr dw 0 ; ibuff pointer
- ilen dw 0 ; bytes in ibuff
- optr dw 0 ; obuff pointer
-
- column dw 0 ; current column counter
-
- msg1 db cr,lf
- db 'clean: need MS-DOS version 2 or greater.'
- db cr,lf,'$'
-
- msg2 db cr,lf
- db 'clean: disk is full.'
- db cr,lf
- msg2_len equ $-msg2
-
- _DATA ends
-
-
- STACK segment para stack 'STACK'
-
- dw 64 dup (?)
-
- STACK ends
-
- end clean
-
- \SAMPCODE\ADVMSDOS\CHAP15\PROTO.ASM
-
- name proto
- page 55,132
- title PROTO.ASM --- prototype filter
- ;
- ; PROTO.ASM: prototype character-oriented filter
- ;
- ; Copyright 1988 Ray Duncan
- ;
- ; Build: MASM PROTO;
- ; LINK PROTO;
- ;
- ; Usage: PROTO
- ;
-
- stdin equ 0 ; standard input handle
- stdout equ 1 ; standard output handle
- stderr equ 2 ; standard error handle
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII linefeed
-
-
- _TEXT segment word public 'CODE'
-
- assume cs:_TEXT,ds:_DATA,ss:STACK
-
- main proc far ; entry point from MS-DOS
-
- mov ax,_DATA ; set DS = our data segment
- mov ds,ax
-
- main1: ; read char. from stdin...
- mov dx,offset char ; DS:DX = buffer address
- mov cx,1 ; CX = length to read
- mov bx,stdin ; BX = standard input handle
- mov ah,3fh ; Fxn 3FH = read
- int 21h ; transfer to MS-DOS
- jc main3 ; if error, terminate
-
- cmp ax,1 ; any character read?
- jne main2 ; if end of file, terminate
-
- call translate ; translate character
-
- ; write char. to stdout...
- mov dx,offset char ; DS:DX = buffer address
- mov cx,1 ; CX = length to write
- mov bx,stdout ; BX = standard output handle
- mov ah,40h ; Fxn 40H = write
- int 21h ; transfer to MS-DOS
- jc main3 ; if error, terminate
-
- cmp ax,1 ; was character written?
- jne main3 ; if disk full, terminate
-
- jmp main1 ; get another character
-
- main2: ; end of file reached
- mov ax,4c00h ; Fxn 4CH = terminate
- ; return code = 0
- int 21h ; transfer to MS-DOS
-
- main3: ; error or disk full
- mov ax,4c01h ; Fxn 4CH = terminate
- ; return code = 1
- int 21h ; transfer to MS-DOS
-
- main endp
-
- ;
- ; Perform any necessary translation on character
- ; from standard input stored in variable 'char'.
- ; This example just leaves character unchanged.
- ;
- translate proc near
-
- ret ; does nothing
-
- translate endp
-
- _TEXT ends
-
-
- _DATA segment word public 'DATA'
-
- char db 0 ; storage for input character
-
- _DATA ends
-
-
- STACK segment para stack 'STACK'
-
- dw 64 dup (?)
-
- STACK ends
-
- end main ; defines program entry point
-
- \SAMPCODE\DOS_ENCY
- \SAMPCODE\DOS_ENCY\10
- \SAMPCODE\DOS_ENCY\10\CHILD.ASM
-
- name child
- title 'CHILD process'
- ;
- ; CHILD.EXE --- a simple process loaded by PARENT.EXE
- ; to demonstrate the MS-DOS EXEC call, Subfunction 00H.
- ;
- ; Ray Duncan, June 1987
- ;
-
- stdin equ 0 ; standard input
- stdout equ 1 ; standard output
- stderr equ 2 ; standard error
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII linefeed
-
-
- DGROUP group _DATA,STACK
-
-
- _TEXT segment byte public 'CODE' ; executable code segment
-
- assume cs:_TEXT,ds:_DATA,ss:STACK
-
- main proc far ; entry point from MS-DOS
-
- mov ax,_DATA ; set DS = our data segment
- mov ds,ax
-
- ; display child message ...
- mov dx,offset msg ; DS:DX = address of message
- mov cx,msg_len ; CX = length of message
- mov bx,stdout ; BX = standard output handle
- mov ah,40h ; AH = fxn 40H, write file/device
- int 21h ; transfer to MS-DOS
- jc main2 ; jump if any error
-
- mov ax,4c00h ; no error, terminate child
- int 21h ; with return code = 0
-
- main2: mov ax,4c01h ; error, terminate child
- int 21h ; with return code = 1
-
- main endp ; end of main procedure
-
- _TEXT ends
-
-
- _DATA segment para public 'DATA' ; static & variable data segment
-
- msg db cr,lf,'Child executing!',cr,lf
- msg_len equ $-msg
-
- _DATA ends
-
-
- STACK segment para stack 'STACK'
-
- dw 64 dup (?)
-
- STACK ends
-
-
- end main ; defines program entry point
-
- \SAMPCODE\DOS_ENCY\10\OVERLAY.ASM
-
- name overlay
- title 'OVERLAY segment'
- ;
- ; OVERLAY.EXE --- a simple overlay segment
- ; loaded by ROOT.EXE to demonstrate use of
- ; the MS-DOS EXEC call Subfunction 03H.
- ;
- ; The overlay does not contain a STACK segment
- ; because it uses the ROOT segment's stack.
- ;
- ; Ray Duncan, June 1987
- ;
-
- stdin equ 0 ; standard input
- stdout equ 1 ; standard output
- stderr equ 2 ; standard error
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII linefeed
-
-
- _TEXT segment byte public 'CODE' ; executable code segment
-
- assume cs:_TEXT,ds:_DATA
- ovlay proc far ; entry point from root segment
-
- mov ax,_DATA ; set DS = local data segment
- mov ds,ax
-
- ; display overlay message ...
- mov dx,offset msg ; DS:DX = address of message
- mov cx,msg_len ; CX = length of message
- mov bx,stdout ; BX = standard output handle
- mov ah,40h ; AH = fxn 40H, write file/device
- int 21h ; transfer to MS-DOS
-
- ret ; return to root segment
-
- ovlay endp ; end of ovlay procedure
-
- _TEXT ends
-
-
- _DATA segment para public 'DATA' ; static & variable data segment
-
- msg db cr,lf,'Overlay executing!',cr,lf
- msg_len equ $-msg
-
- _DATA ends
-
- end
-
- \SAMPCODE\DOS_ENCY\10\PARENT.ASM
-
- name parent
- title 'PARENT --- demonstrate EXEC call'
- ;
- ; PARENT.EXE --- demonstration of EXEC to run process
- ;
- ; Uses MS-DOS EXEC (Int 21H Function 4BH Subfunction 00H)
- ; to load and execute a child process named CHILD.EXE,
- ; then displays CHILD's return code.
- ;
- ; Ray Duncan, June 1987
- ;
-
- stdin equ 0 ; standard input
- stdout equ 1 ; standard output
- stderr equ 2 ; standard error
-
- stksize equ 128 ; size of stack
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII linefeed
-
-
- DGROUP group _DATA,_ENVIR,_STACK
-
-
- _TEXT segment byte public 'CODE' ; executable code segment
-
- assume cs:_TEXT,ds:_DATA,ss:_STACK
-
-
- stk_seg dw ? ; original SS contents
- stk_ptr dw ? ; original SP contents
-
-
- main proc far ; entry point from MS-DOS
-
- mov ax,_DATA ; set DS = our data segment
- mov ds,ax
-
- ; now give back extra memory
- ; so child has somewhere to run...
- mov ax,es ; let AX = segment of PSP base
- mov bx,ss ; and BX = segment of stack base
- sub bx,ax ; reserve seg stack - seg psp
- add bx,stksize/16 ; plus paragraphs of stack
- mov ah,4ah ; fxn 4AH = modify memory block
- int 21h
- jc main1
- ; display parent message ...
- mov dx,offset DGROUP:msg1 ; DS:DX = address of message
- mov cx,msg1_len ; CX = length of message
- call pmsg
-
- push ds ; save parent's data segment
- mov stk_seg,ss ; save parent's stack pointer
- mov stk_ptr,sp
-
- ; now EXEC the child process...
- mov ax,ds ; set ES = DS
- mov es,ax
- mov dx,offset DGROUP:cname ; DS:DX = child pathname
- mov bx,offset DGROUP:pars ; EX:BX = parameter block
- mov ax,4b00h ; function 4BH subfunction 00H
- int 21h ; transfer to MS-DOS
-
- cli ; (for bug in some early 8088s)
- mov ss,stk_seg ; restore parent's stack pointer
- mov sp,stk_ptr
- sti ; (for bug in some early 8088s)
- pop ds ; restore DS = our data segment
-
- jc main2 ; jump if EXEC failed
-
- ; otherwise EXEC succeeded,
- ; convert and display child's
- ; termination and return codes...
- mov ah,4dh ; fxn 4DH = get return code
- int 21h ; transfer to MS-DOS
- xchg al,ah ; convert termination code
- mov bx,offset DGROUP:msg4a
- call b2hex
- mov al,ah ; get back return code
- mov bx,offset DGROUP:msg4b ; and convert it
- call b2hex
- mov dx,offset DGROUP:msg4 ; DS:DX = address of message
- mov cx,msg4_len ; CX = length of message
- call pmsg ; display it
-
- mov ax,4c00h ; no error, terminate program
- int 21h ; with return code = 0
-
- main1: mov bx,offset DGROUP:msg2a ; convert error code
- call b2hex
- mov dx,offset DGROUP:msg2 ; display message 'Memory
- mov cx,msg2_len ; resize failed...'
- call pmsg
- jmp main3
-
- main2: mov bx,offset DGROUP:msg3a ; convert error code
- call b2hex
- mov dx,offset DGROUP:msg3 ; display message 'EXEC
- mov cx,msg3_len ; call failed...'
- call pmsg
-
- main3: mov ax,4c01h ; error, terminate program
- int 21h ; with return code = 1
-
- main endp ; end of main procedure
-
-
- b2hex proc near ; convert byte to hex ASCII
- ; call with AL = binary value
- ; BX = addr to store string
- push ax
- shr al,1
- shr al,1
- shr al,1
- shr al,1
- call ascii ; become first ASCII character
- mov [bx],al ; store it
- pop ax
- and al,0fh ; isolate lower 4 bits, which
- call ascii ; become the second ASCII character
- mov [bx+1],al ; store it
- ret
- b2hex endp
-
-
- ascii proc near ; convert value 00-0FH in AL
- add al,'0' ; into a "hex ASCII" character
- cmp al,'9'
- jle ascii2 ; jump if in range 00-09H,
- add al,'A'-'9'-1 ; offset it to range 0A-0FH,
-
- ascii2: ret ; return ASCII char. in AL
- ascii endp
-
-
- pmsg proc near ; displays message on standard output
- ; call with DS:DX = address,
- ; CX = length
-
- mov bx,stdout ; BX = standard output handle
- mov ah,40h ; function 40h = write file/device
- int 21h ; transfer to MS-DOS
- ret ; back to caller
-
- pmsg endp
-
- _TEXT ends
-
-
- _DATA segment para public 'DATA' ; static & variable data segment
-
- cname db 'CHILD.EXE',0 ; pathname of child process
-
- pars dw _ENVIR ; segment of environment block
- dd tail ; long address, command tail
- dd fcb1 ; long address, default FCB #1
- dd fcb2 ; long address, default FCB #2
-
- tail db fcb1-tail-2 ; command tail for child
- db 'dummy command tail',cr
-
- fcb1 db 0 ; copied into default FCB #1 in
- db 11 dup (' ') ; child's program segment prefix
- db 25 dup (0)
-
- fcb2 db 0 ; copied into default FCB #2 in
- db 11 dup (' ') ; child's program segment prefix
- db 25 dup (0)
-
- msg1 db cr,lf,'Parent executing!',cr,lf
- msg1_len equ $-msg1
-
- msg2 db cr,lf,'Memory resize failed, error code='
- msg2a db 'xxh.',cr,lf
- msg2_len equ $-msg2
-
- msg3 db cr,lf,'EXEC call failed, error code='
- msg3a db 'xxh.',cr,lf
- msg3_len equ $-msg3
-
- msg4 db cr,lf,'Parent regained control!'
- db cr,lf,'Child termination type='
- msg4a db 'xxh, return code='
- msg4b db 'xxh.',cr,lf
- msg4_len equ $-msg4
-
- _DATA ends
-
-
- _ENVIR segment para public 'DATA' ; example environment block
- ; to be passed to child
-
- db 'PATH=',0 ; basic PATH, PROMPT,
- db 'PROMPT=$p$_$n$g',0 ; and COMSPEC strings
- db 'COMSPEC=C:\COMMAND.COM',0
- db 0 ; extra null terminates block
-
- _ENVIR ends
-
-
- _STACK segment para stack 'STACK'
-
- db stksize dup (?)
-
- _STACK ends
-
-
- end main ; defines program entry point
-
- \SAMPCODE\DOS_ENCY\10\ROOT.ASM
-
- name root
- title 'ROOT --- demonstrate EXEC overlay'
- ;
- ; ROOT.EXE --- demonstration of EXEC for overlays
- ;
- ; Uses MS-DOS EXEC (Int 21H Function 4BH Subfunction 03H)
- ; to load an overlay named OVERLAY.EXE, calls a routine
- ; within the OVERLAY, then recovers control and terminates.
- ;
- ; Ray Duncan, June 1987
- ;
-
- stdin equ 0 ; standard input
- stdout equ 1 ; standard output
- stderr equ 2 ; standard error
-
- stksize equ 128 ; size of stack
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII linefeed
-
-
- DGROUP group _DATA,_STACK
-
-
- _TEXT segment byte public 'CODE' ; executable code segment
-
- assume cs:_TEXT,ds:_DATA,ss:_STACK
-
-
- stk_seg dw ? ; original SS contents
- stk_ptr dw ? ; original SP contents
-
-
- main proc far ; entry point from MS-DOS
-
- mov ax,_DATA ; set DS = our data segment
- mov ds,ax
-
- ; now give back extra memory
- mov ax,es ; AX = segment of PSP base
- mov bx,ss ; BX = segment of stack base
- sub bx,ax ; reserve seg stack - seg psp
- add bx,stksize/16 ; plus paragraphs of stack
- mov ah,4ah ; fxn 4AH = modify memory block
- int 21h ; transfer to MS-DOS
- jc main1 ; jump if resize failed
-
- ; display message 'Root
- ; 'segment executing...'
- mov dx,offset DGROUP:msg1 ; DS:DX = address of message
- mov cx,msg1_len ; CX = length of message
- call pmsg
-
- ; allocate memory for overlay
- mov bx,1000h ; get 64 KB (4096 paragraphs)
- mov ah,48h ; fxn 48h, allocate mem block
- int 21h ; transfer to MS-DOS
- jc main2 ; jump if allocation failed
-
- mov pars,ax ; set load address for overlay
- mov pars+2,ax ; set relocation segment for overlay
- mov word ptr entry+2,ax ; set segment of entry point
-
- push ds ; save root's data segment
- mov stk_seg,ss ; save root's stack pointer
- mov stk_ptr,sp
-
- ; now use EXEC to load overlay
- mov ax,ds ; set ES = DS
- mov es,ax
- mov dx,offset DGROUP:oname ; DS:DX = overlay pathname
- mov bx,offset DGROUP:pars ; EX:BX = parameter block
- mov ax,4b03h ; function 4BH, subfunction 03H
- int 21h ; transfer to MS-DOS
-
- cli ; (for bug in some early 8088s)
- mov ss,stk_seg ; restore root's stack pointer
- mov sp,stk_ptr
- sti ; (for bug in some early 8088s)
- pop ds ; restore DS = our data segment
-
- jc main3 ; jump if EXEC failed
-
- ; otherwise EXEC succeeded...
- push ds ; save our data segment
- call dword ptr entry ; now call the overlay
- pop ds ; restore our data segment
-
- ; display message that root
- ; segment regained control...
- mov dx,offset DGROUP:msg5 ; DS:DX = address of message
- mov cx,msg5_len ; CX = length of message
- call pmsg ; display it
-
- mov ax,4c00h ; no error, terminate program
- int 21h ; with return code = 0
-
- main1: mov bx,offset DGROUP:msg2a ; convert error code
- call b2hex
- mov dx,offset DGROUP:msg2 ; display message 'Memory
- mov cx,msg2_len ; resize failed...'
- call pmsg
- jmp main4
-
- main2: mov bx,offset DGROUP:msg3a ; convert error code
- call b2hex
- mov dx,offset DGROUP:msg3 ; display message 'Memory
- mov cx,msg3_len ; allocation failed...'
- call pmsg
- jmp main4
-
- main3: mov bx,offset DGROUP:msg4a ; convert error code
- call b2hex
- mov dx,offset DGROUP:msg4 ; display message 'EXEC
- mov cx,msg4_len ; call failed...'
- call pmsg
-
- main4: mov ax,4c01h ; error, terminate program
- int 21h ; with return code = 1
-
- main endp ; end of main procedure
-
-
- b2hex proc near ; convert byte to hex ASCII
- ; call with AL = binary value
- ; BX = addr to store string
- push ax
- shr al,1
- shr al,1
- shr al,1
- shr al,1
- call ascii ; become first ASCII character
- mov [bx],al ; store it
- pop ax
- and al,0fh ; isolate lower 4 bits, which
- call ascii ; become the second ASCII character
- mov [bx+1],al ; store it
- ret
- b2hex endp
-
-
- ascii proc near ; convert value 00-0FH in AL
- add al,'0' ; into a "hex ASCII" character
- cmp al,'9'
- jle ascii2 ; jump if in range 00-09H,
- add al,'A'-'9'-1 ; offset it to range 0A-0FH,
- ascii2: ret ; return ASCII char. in AL.
- ascii endp
-
-
- pmsg proc near ; displays message on standard output
- ; call with DS:DX = address,
- ; CX = length
-
- mov bx,stdout ; BX = standard output handle
- mov ah,40h ; function 40H = write file/device
- int 21h ; transfer to MS-DOS
- ret ; back to caller
-
- pmsg endp
-
- _TEXT ends
-
-
- _DATA segment para public 'DATA' ; static & variable data segment
-
- oname db 'OVERLAY.OVL',0 ; pathname of overlay file
-
- pars dw 0 ; load address (segment) for file
- dw 0 ; relocation (segment) for file
-
- entry dd 0 ; entry point for overlay
-
- msg1 db cr,lf,'Root segment executing!',cr,lf
- msg1_len equ $-msg1
-
- msg2 db cr,lf,'Memory resize failed, error code='
- msg2a db 'xxh.',cr,lf
- msg2_len equ $-msg2
-
- msg3 db cr,lf,'Memory allocation failed, error code='
- msg3a db 'xxh.',cr,lf
- msg3_len equ $-msg3
-
- msg4 db cr,lf,'EXEC call failed, error code='
- msg4a db 'xxh.',cr,lf
- msg4_len equ $-msg4
-
- msg5 db cr,lf,'Root segment regained control!',cr,lf
- msg5_len equ $-msg5
-
- _DATA ends
-
-
- _STACK segment para stack 'STACK'
-
- db stksize dup (?)
-
- _STACK ends
-
-
- end main ; defines program entry point
-
- \SAMPCODE\DOS_ENCY\11
- \SAMPCODE\DOS_ENCY\11\HELLO.ASM
-
- ;
- ; Name: hello
- ;
- ; Description: This RAM-resident (terminate-and-stay-resident) utility
- ; displays the message "Hello, World" in response to a
- ; software interrupt.
- ;
- ; Comments: Assemble and link to create HELLO.EXE.
- ;
- ; Execute HELLO.EXE to make resident.
- ;
- ; Execute INT 64h to display the message.
- ;
-
-
- TSRInt EQU 64h
- STDOUT EQU 1
-
- RESIDENT_TEXT SEGMENT byte public 'CODE'
- ASSUME cs:RESIDENT_TEXT,ds:RESIDENT_DATA
-
- TSRAction PROC far
-
- sti ; enable interrupts
-
- push ds ; preserve registers
- push ax
- push bx
- push cx
- push dx
-
- mov dx,seg RESIDENT_DATA
- mov ds,dx
- mov dx,offset Message ; DS:DX -> message
- mov cx,16 ; CX = length
- mov bx,STDOUT ; BX = file handle
- mov ah,40h ; AH = INT 21h function 40h
- ; (Write File)
- int 21h ; display the message
-
- pop dx ; restore registers and exit
- pop cx
- pop bx
- pop ax
- pop ds
- iret
-
- TSRAction ENDP
-
- RESIDENT_TEXT ENDS
-
-
- RESIDENT_DATA SEGMENT word public 'DATA'
-
- Message DB 0Dh,0Ah,'Hello, World',0Dh,0Ah
-
- RESIDENT_DATA ENDS
-
-
- TRANSIENT_TEXT SEGMENT para public 'TCODE'
- ASSUME cs:TRANSIENT_TEXT,ss:TRANSIENT_STACK
-
- HelloTSR PROC far ; At entry: CS:IP -> SnapTSR
- ; SS:SP -> stack
- ; DS,ES -> PSP
- ; Install this TSR's interrupt handler
-
- mov ax,seg RESIDENT_TEXT
- mov ds,ax
- mov dx,offset RESIDENT_TEXT:TSRAction
- mov al,TSRInt
- mov ah,25h
- int 21h
-
- ; Terminate and stay resident
-
- mov dx,cs ; DX = paragraph address of start of
- ; transient portion (end of resident
- ; portion)
- mov ax,es ; ES = PSP segment
- sub dx,ax ; DX = size of resident portion
-
- mov ax,3100h ; AH = INT 21h function number (TSR)
- ; AL = 00H (return code)
- int 21h
-
- HelloTSR ENDP
-
- TRANSIENT_TEXT ENDS
-
-
- TRANSIENT_STACK SEGMENT word stack 'TSTACK'
-
- DB 80h dup(?)
-
- TRANSIENT_STACK ENDS
-
-
- END HelloTSR
-
- \SAMPCODE\DOS_ENCY\11\INDOS_1.ASM
-
- test ss:[CriticalErrorFlag],0FFH ;(versions 3.1 and later)
- jne NearLabel
- push ss:[NearWord]
- int 28H
-
- \SAMPCODE\DOS_ENCY\11\INDOS_2.ASM
-
- cmp ss:[CriticalErrorFlag],00 ;(versions earlier than 3.
- jne NearLabel
- int 28H
-
- \SAMPCODE\DOS_ENCY\11\SNAP.ASM
-
- ;
- ; Name: snap
- ;
- ; Description: This RAM-resident (terminate-and-stay-resident) utility
- ; produces a video "snapshot" by copying the contents of the
- ; video regeneration buffer to a disk file. It may be used
- ; in 80-column alphanumeric video modes on IBM PCs and PS/2s.
- ;
- ; Comments: Assemble and link to create SNAP.EXE.
- ;
- ; Execute SNAP.EXE to make resident.
- ;
- ; Press Alt-Enter to dump current contents of video buffer
- ; to a disk file.
- ;
-
- MultiplexID EQU 0CAh ; unique INT 2FH ID value
-
- TSRStackSize EQU 100h ; resident stack size in bytes
-
- KB_FLAG EQU 17h ; offset of shift-key status flag in
- ; ROM BIOS keyboard data area
-
- KBIns EQU 80h ; bit masks for KB_FLAG
- KBCaps EQU 40h
- KBNum EQU 20h
- KBScroll EQU 10h
- KBAlt EQU 8
- KBCtl EQU 4
- KBLeft EQU 2
- KBRight EQU 1
-
- SCEnter EQU 1Ch
-
- CR EQU 0Dh
- LF EQU 0Ah
- TRUE EQU -1
- FALSE EQU 0
-
- PAGE
- ;----------------------------------------------------------------------------
- ;
- ; RAM-resident routines
- ;
- ;----------------------------------------------------------------------------
-
- RESIDENT_GROUP GROUP RESIDENT_TEXT,RESIDENT_DATA,RESIDENT_STACK
-
- RESIDENT_TEXT SEGMENT byte public 'CODE'
- ASSUME cs:RESIDENT_GROUP,ds:RESIDENT_GROUP
-
- ;----------------------------------------------------------------------------
- ; System verification routines
- ;----------------------------------------------------------------------------
-
- VerifyDOSState PROC near ; Returns: carry flag set if MS-DO
- ; is busy
-
- push ds ; preserve these registers
- push bx
- push ax
-
- lds bx,cs:ErrorModeAddr
- mov ah,[bx] ; AH = ErrorMode flag
-
- lds bx,cs:InDOSAddr
- mov al,[bx] ; AL = InDOS flag
-
- xor bx,bx ; BH = 00H, BL = 00H
- cmp bl,cs:InISR28 ; carry flag set if INT 28H handler
- ; is running
- rcl bl,01h ; BL = 01H if INT 28H handler is runn
-
- cmp bx,ax ; carry flag zero if AH = 00H
- ; and AL <= BL
-
- pop ax ; restore registers
- pop bx
- pop ds
- ret
-
- VerifyDOSState ENDP
-
-
- VerifyIntState PROC near ; Returns: carry flag set if hardw
- ; or ROM BIOS unstable
-
- push ax ; preserve AX
-
- ; Verify hardware interrupt status by interrogating Intel 8259A Programmable
- ; Interrupt Controller
-
- mov ax,00001011b ; AH = 0
- ; AL = 0CW3 for Intel 8259A (RR = 1,
- ; RIS = 1)
- out 20h,al ; request 8259A's in-service register
- jmp short L10 ; wait a few cycles
- L10: in al,20h ; AL = hardware interrupts currently
- ; being serviced (bit = 1 if in-servi
- cmp ah,al
- jc L11 ; exit if any hardware interrupts sti
- ; being serviced
-
- ; Verify status of ROM BIOS interrupt handlers
-
- xor al,al ; AL = 00H
-
- cmp al,cs:InISR5
- jc L11 ; exit if currently in INT 05H handle
-
- cmp al,cs:InISR9
- jc L11 ; exit if currently in INT 09H handle
-
- cmp al,cs:InISR10
- jc L11 ; exit if currently in INT 10H handle
-
- cmp al,cs:InISR13 ; set carry flag if currently in
- ; INT 13H handler
-
- L11: pop ax ; restore AX and return
- ret
-
- VerifyIntState ENDP
-
-
- VerifyTSRState PROC near ; Returns: carry flag set if TSR
- ; inactive
-
- rol cs:HotFlag,1 ; carry flag set if (HotFlag = TRUE)
- cmc ; carry flag set if (HotFlag = FALSE)
- jc L20 ; exit if no hot key
-
- ror cs:ActiveTSR,1 ; carry flag set if (ActiveTSR = TRUE
- jc L20 ; exit if already active
-
- call VerifyDOSState
- jc L20 ; exit if MS-DOS unstable
-
- call VerifyIntState ; set carry flag if hardware or BIOS
- ; unstable
-
- L20: ret
-
- VerifyTSRState ENDP
-
- PAGE
- ;----------------------------------------------------------------------------
- ; System monitor routines
- ;----------------------------------------------------------------------------
-
- ISR5 PROC far ; INT 05H handler
- ; (ROM BIOS print screen)
-
- inc cs:InISR5 ; increment status flag
-
- pushf
- cli
- call cs:PrevISR5 ; chain to previous INT 05H handler
-
- dec cs:InISR5 ; decrement status flag
- iret
-
- ISR5 ENDP
-
-
- ISR8 PROC far ; INT 08H handler (timer tick, IRQ0)
-
- pushf
- cli
- call cs:PrevISR8 ; chain to previous handler
-
- cmp cs:InISR8,0
- jne L31 ; exit if already in this handler
-
- inc cs:InISR8 ; increment status flag
-
- sti ; interrupts are ok
- call VerifyTSRState
- jc L30 ; jump if TSR is inactive
-
- mov byte ptr cs:ActiveTSR,TRUE
- call TSRapp
- mov byte ptr cs:ActiveTSR,FALSE
-
- L30: dec cs:InISR8
-
- L31: iret
-
- ISR8 ENDP
-
-
- ISR9 PROC far ; INT 09H handler
- ; (keyboard interrupt IRQ1)
-
- push ds ; preserve these registers
- push ax
- push bx
-
- push cs
- pop ds ; DS -> RESIDENT_GROUP
-
- in al,60h ; AL = current scan code
-
- pushf ; simulate an INT
- cli
- call ds:PrevISR9 ; let previous handler execute
-
- mov ah,ds:InISR9 ; if already in this handler ..
- or ah,ds:HotFlag ; .. or currently processing hot key
- jnz L43 ; .. jump to exit
-
- inc ds:InISR9 ; increment status flag
- sti ; now interrupts are ok
-
- ; Check scan code sequence
-
- cmp ds:HotSeqLen,0
- je L40 ; jump if no hot sequence to match
-
- mov bx,ds:HotIndex
- cmp al,[bx+HotSequence] ; test scan code sequence
- jne L41 ; jump if no match
-
- inc bx
- cmp bx,ds:HotSeqLen
- jb L42 ; jump if not last scan code to match
-
- ; Check shift-key state
-
- L40: push ds
- mov ax,40h
- mov ds,ax ; DS -> ROM BIOS data area
- mov al,ds:[KB_FLAG] ; AH = ROM BIOS shift-key flags
- pop ds
-
- and al,ds:HotKBMask ; AL = flags AND "don't care" mask
- cmp al,ds:HotKBFlag
- jne L42 ; jump if shift state does not match
-
- ; Set flag when hot key is found
-
- mov byte ptr ds:HotFlag,TRUE
-
- L41: xor bx,bx ; reinitialize index
-
- L42: mov ds:HotIndex,bx ; update index into sequence
- dec ds:InISR9 ; decrement status flag
-
- L43: pop bx ; restore registers and exit
- pop ax
- pop ds
- iret
-
- ISR9 ENDP
-
-
- ISR10 PROC far ; INT 10H handler (ROM BIOS video I/O
-
- inc cs:InISR10 ; increment status flag
-
- pushf
- cli
- call cs:PrevISR10 ; chain to previous INT 10H handler
-
- dec cs:InISR10 ; decrement status flag
- iret
-
- ISR10 ENDP
-
-
- ISR13 PROC far ; INT 13H handler
- ; (ROM BIOS fixed disk I/O)
-
- inc cs:InISR13 ; increment status flag
-
- pushf
- cli
- call cs:PrevISR13 ; chain to previous INT 13H handler
-
- pushf ; preserve returned flags
- dec cs:InISR13 ; decrement status flag
- popf ; restore flags register
-
- sti ; enable interrupts
- ret 2 ; simulate IRET without popping flags
-
- ISR13 ENDP
-
-
- ISR1B PROC far ; INT 1BH trap (ROM BIOS Ctrl-Break)
-
- mov byte ptr cs:Trap1B,TRUE
- iret
-
- ISR1B ENDP
-
-
- ISR23 PROC far ; INT 23H trap (MS-DOS Ctrl-C)
-
- mov byte ptr cs:Trap23,TRUE
- iret
-
- ISR23 ENDP
-
-
- ISR24 PROC far ; INT 24H trap (MS-DOS critical error
-
- mov byte ptr cs:Trap24,TRUE
-
- xor al,al ; AL = 00H (MS-DOS 2.x):
- ; ignore the error
- cmp cs:MajorVersion,2
- je L50
-
- mov al,3 ; AL = 03H (MS-DOS 3.x):
- ; fail the MS-DOS call in which
- ; the critical error occurred
- L50: iret
-
- ISR24 ENDP
-
-
- ISR28 PROC far ; INT 28H handler
- ; (MS-DOS idle interrupt)
-
- pushf
- cli
- call cs:PrevISR28 ; chain to previous INT 28H handler
-
- cmp cs:InISR28,0
- jne L61 ; exit if already inside this handler
-
- inc cs:InISR28 ; increment status flag
-
- call VerifyTSRState
- jc L60 ; jump if TSR is inactive
-
- mov byte ptr cs:ActiveTSR,TRUE
- call TSRapp
- mov byte ptr cs:ActiveTSR,FALSE
-
- L60: dec cs:InISR28 ; decrement status flag
-
- L61: iret
-
- ISR28 ENDP
-
-
- ISR2F PROC far ; INT 2FH handler
- ; (MS-DOS multiplex interrupt)
- ; Caller: AH = handler ID
- ; AL = function number
- ; Returns for function 0: AL = 0FFH
- ; for all other functions: nothing
-
- cmp ah,MultiplexID
- je L70 ; jump if this handler is requested
-
- jmp cs:PrevISR2F ; chain to previous INT 2FH handler
-
- L70: test al,al
- jnz MultiplexIRET ; jump if reserved or undefined funct
-
- ; Function 0: get installed state
-
- mov al,0FFh ; AL = 0FFh (this handler is installe
-
- MultiplexIRET: iret ; return from interrupt
-
- ISR2F ENDP
-
- PAGE
- ;
- ;
- ; AuxInt21--sets ErrorMode while executing INT 21h to force use of the
- ; AuxStack instead of the IOStack.
- ;
- ;
-
- AuxInt21 PROC near ; Caller: registers for INT 21H
- ; Returns: registers from INT 21H
-
- push ds
- push bx
- lds bx,ErrorModeAddr
- inc byte ptr [bx] ; ErrorMode is now nonzero
- pop bx
- pop ds
-
- int 21h ; perform MS-DOS function
-
- push ds
- push bx
- lds bx,ErrorModeAddr
- dec byte ptr [bx] ; restore ErrorMode
- pop bx
- pop ds
- ret
-
- AuxInt21 ENDP
-
-
- Int21v PROC near ; perform INT 21H or AuxInt21,
- ; depending on MS-DOS version
-
- cmp DOSVersion,30Ah
- jb L80 ; jump if earlier than 3.1
-
- int 21h ; version 3.1 and later
- ret
-
- L80: call AuxInt21 ; versions earlier than 3.1
- ret
-
- Int21v ENDP
-
- PAGE
- ;----------------------------------------------------------------------------
- ; RAM-resident application
- ;----------------------------------------------------------------------------
-
- TSRapp PROC near
-
- ; Set up a safe stack
-
- push ds ; save previous DS on previous stack
-
- push cs
- pop ds ; DS -> RESIDENT_GROUP
-
- mov PrevSP,sp ; save previous SS:SP
- mov PrevSS,ss
-
- mov ss,TSRSS ; SS:SP -> RESIDENT_STACK
- mov sp,TSRSP
-
- push es ; preserve remaining registers
- push ax
- push bx
- push cx
- push dx
- push si
- push di
- push bp
-
- cld ; clear direction flag
-
- ; Set break and critical error traps
-
- mov cx,NTrap
- mov si,offset RESIDENT_GROUP:StartTrapList
-
- L90: lodsb ; AL = interrupt number
- ; DS:SI -> byte past interrupt number
-
- mov byte ptr [si],FALSE ; zero the trap flag
-
- push ax ; preserve AX
- mov ah,35h ; INT 21H function 35H
- ; (get interrupt vector)
- int 21h ; ES:BX = previous interrupt vector
- mov [si+1],bx ; save offset and segment ..
- mov [si+3],es ; .. of previous handler
-
- pop ax ; AL = interrupt number
- mov dx,[si+5] ; DS:DX -> this TSR's trap
- mov ah,25h ; INT 21H function 25H
- int 21h ; (set interrupt vector)
- add si,7 ; DS:SI -> next in list
-
- loop L90
-
- ; Disable MS-DOS break checking during disk I/O
-
- mov ax,3300h ; AH = INT 21H function number
- ; AL = 00H (request current break sta
- int 21h ; DL = current break state
- mov PrevBreak,dl ; preserve current state
-
- xor dl,dl ; DL = 00H (disable disk I/O break
- ; checking)
- mov ax,3301h ; AL = 01H (set break state)
- int 21h
-
- ; Preserve previous extended error information
-
- cmp DOSVersion,30Ah
- jb L91 ; jump if MS-DOS version earlier
- ; than 3.1
- push ds ; preserve DS
- xor bx,bx ; BX = 00H (required for function 59H
- mov ah,59h ; INT 21H function 59H
- call Int21v ; (get extended error info)
-
- mov cs:PrevExtErrDS,ds
- pop ds
- mov PrevExtErrAX,ax ; preserve error information
- mov PrevExtErrBX,bx ; in data structure
- mov PrevExtErrCX,cx
- mov PrevExtErrDX,dx
- mov PrevExtErrSI,si
- mov PrevExtErrDI,di
- mov PrevExtErrES,es
-
- ; Inform MS-DOS about current PSP
-
- L91: mov ah,51h ; INT 21H function 51H (get PSP addre
- call Int21v ; BX = foreground PSP
-
- mov PrevPSP,bx ; preserve previous PSP
-
- mov bx,TSRPSP ; BX = resident PSP
- mov ah,50h ; INT 21H function 50H (set PSP addre
- call Int21v
-
- ; Inform MS-DOS about current DTA (not really necessary in this application
- ; because DTA is not used)
-
- mov ah,2Fh ; INT 21H function 2FH
- int 21h ; (get DTA address) into ES:BX
- mov PrevDTAoffs,bx
- mov PrevDTAseg,es
-
- push ds ; preserve DS
- mov ds,TSRPSP
- mov dx,80h ; DS:DX -> default DTA at PSP:0080
- mov ah,1Ah ; INT 21H function 1AH
- int 21h ; (set DTA address)
- pop ds ; restore DS
-
- ; Open a file, write to it, and close it
-
- mov ax,0E07h ; AH = INT 10H function number
- ; (Write Teletype)
- ; AL = 07H (bell character)
- int 10h ; emit a beep
-
- mov dx,offset RESIDENT_GROUP:SnapFile
- mov ah,3Ch ; INT 21H function 3CH
- ; (create file handle)
- mov cx,0 ; file attribute
- int 21h
- jc L94 ; jump if file not opened
-
- push ax ; push file handle
- mov ah,0Fh ; INT 10H function 0FH
- ; (get video status)
- int 10h ; AL = video mode number
- ; AH = number of character columns
- pop bx ; BX = file handle
-
- cmp ah,80
- jne L93 ; jump if not 80-column mode
-
- mov dx,0B800h ; DX = color video buffer segment
- cmp al,3
- jbe L92 ; jump if color alphanumeric mode
-
- cmp al,7
- jne L93 ; jump if not monochrome mode
-
- mov dx,0B000h ; DX = monochrome video buffer segmen
-
- L92: push ds
- mov ds,dx
- xor dx,dx ; DS:DX -> start of video buffer
- mov cx,80*25*2 ; CX = number of bytes to write
- mov ah,40h ; INT 21H function 40H (write file)
- int 21h
- pop ds
-
- L93: mov ah,3Eh ; INT 21H function 3EH (close file)
- int 21h
-
- mov ax,0E07h ; emit another beep
- int 10h
-
- ; Restore previous DTA
-
- L94: push ds ; preserve DS
- lds dx,PrevDTA ; DS:DX -> previous DTA
- mov ah,1Ah ; INT 21H function 1AH (set DTA addre
- int 21h
- pop ds
-
- ; Restore previous PSP
-
- mov bx,PrevPSP ; BX = previous PSP
- mov ah,50h ; INT 21H function 50H
- call Int21v ; (set PSP address)
-
- ; Restore previous extended error information
-
- mov ax,DOSVersion
- cmp ax,30AH
- jb L95 ; jump if MS-DOS version earlier than
- cmp ax,0A00h
- jae L95 ; jump if MS OS/2-DOS 3.x box
-
- mov dx,offset RESIDENT_GROUP:PrevExtErrInfo
- mov ax,5D0Ah
- int 21h ; (restore extended error information
-
- ; Restore previous MS-DOS break checking
-
- L95: mov dl,PrevBreak ; DL = previous state
- mov ax,3301h
- int 21h
-
- ; Restore previous break and critical error traps
-
- mov cx,NTrap
- mov si,offset RESIDENT_GROUP:StartTrapList
- push ds ; preserve DS
-
- L96: lods byte ptr cs:[si] ; AL = interrupt number
- ; ES:SI -> byte past interrupt number
-
- lds dx,cs:[si+1] ; DS:DX -> previous handler
- mov ah,25h ; INT 21H function 25H
- int 21h ; (set interrupt vector)
- add si,7 ; DS:SI -> next in list
- loop L96
-
- pop ds ; restore DS
-
- ; Restore all registers
-
- pop bp
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- pop es
-
- mov ss,PrevSS ; SS:SP -> previous stack
- mov sp,PrevSP
- pop ds ; restore previous DS
-
- ; Finally, reset status flag and return
-
- mov byte ptr cs:HotFlag,FALSE
- ret
-
- TSRapp ENDP
-
-
- RESIDENT_TEXT ENDS
-
-
- RESIDENT_DATA SEGMENT word public 'DATA'
-
- ErrorModeAddr DD ? ; address of MS-DOS ErrorMode flag
- InDOSAddr DD ? ; address of MS-DOS InDOS flag
-
- NISR DW (EndISRList-StartISRList)/8 ; number of installed ISR
-
- StartISRList DB 05h ; INT number
- InISR5 DB FALSE ; flag
- PrevISR5 DD ? ; address of previous handler
- DW offset RESIDENT_GROUP:ISR5
-
- DB 08h
- InISR8 DB FALSE
- PrevISR8 DD ?
- DW offset RESIDENT_GROUP:ISR8
-
- DB 09h
- InISR9 DB FALSE
- PrevISR9 DD ?
- DW offset RESIDENT_GROUP:ISR9
-
- DB 10h
- InISR10 DB FALSE
- PrevISR10 DD ?
- DW offset RESIDENT_GROUP:ISR10
-
- DB 13h
- InISR13 DB FALSE
- PrevISR13 DD ?
- DW offset RESIDENT_GROUP:ISR13
-
- DB 28h
- InISR28 DB FALSE
- PrevISR28 DD ?
- DW offset RESIDENT_GROUP:ISR28
-
- DB 2Fh
- InISR2F DB FALSE
- PrevISR2F DD ?
- DW offset RESIDENT_GROUP:ISR2F
-
- EndISRList LABEL BYTE
-
- TSRPSP DW ? ; resident PSP
- TSRSP DW TSRStackSize ; resident SS:SP
- TSRSS DW seg RESIDENT_STACK
- PrevPSP DW ? ; previous PSP
- PrevSP DW ? ; previous SS:SP
- PrevSS DW ?
-
- HotIndex DW 0 ; index of next scan code in sequence
- HotSeqLen DW EndHotSeq-HotSequence ; length of hot-key sequence
-
- HotSequence DB SCEnter ; hot sequence of scan codes
- EndHotSeq LABEL BYTE
-
- HotKBFlag DB KBAlt ; hot value of ROM BIOS KB_FLAG
- HotKBMask DB (KBIns OR KBCaps OR KBNum OR KBScroll) XOR 0FFh
- HotFlag DB FALSE
-
- ActiveTSR DB FALSE
-
- DOSVersion LABEL WORD
- DB ? ; minor version number
- MajorVersion DB ? ; major version number
-
- ; The following data is used by the TSR application:
-
- NTrap DW (EndTrapList-StartTrapList)/8 ; number of traps
-
- StartTrapList DB 1Bh
- Trap1B DB FALSE
- PrevISR1B DD ?
- DW offset RESIDENT_GROUP:ISR1B
-
- DB 23h
- Trap23 DB FALSE
- PrevISR23 DD ?
- DW offset RESIDENT_GROUP:ISR23
-
- DB 24h
- Trap24 DB FALSE
- PrevISR24 DD ?
- DW offset RESIDENT_GROUP:ISR24
-
- EndTrapList LABEL BYTE
-
- PrevBreak DB ? ; previous break-checking flag
-
- PrevDTA LABEL DWORD ; previous DTA address
- PrevDTAoffs DW ?
- PrevDTAseg DW ?
-
- PrevExtErrInfo LABEL BYTE ; previous extended error information
- PrevExtErrAX DW ?
- PrevExtErrBX DW ?
- PrevExtErrCX DW ?
- PrevExtErrDX DW ?
- PrevExtErrSI DW ?
- PrevExtErrDI DW ?
- PrevExtErrDS DW ?
- PrevExtErrES DW ?
- DW 3 dup(0)
-
- SnapFile DB '\snap.img' ; output filename in root directory
-
- RESIDENT_DATA ENDS
-
- RESIDENT_STACK SEGMENT word stack 'STACK'
-
- DB TSRStackSize dup(?)
-
- RESIDENT_STACK ENDS
-
- PAGE
- ;----------------------------------------------------------------------------
- ;
- ; Transient installation routines
- ;
- ;----------------------------------------------------------------------------
-
- TRANSIENT_TEXT SEGMENT para public 'TCODE'
- ASSUME cs:TRANSIENT_TEXT,ds:RESIDENT_DATA,ss:RESIDENT_STACK
-
- InstallSnapTSR PROC far ; At entry: CS:IP -> InstallSnapTSR
- ; SS:SP -> stack
- ; DS,ES -> PSP
- ; Save PSP segment
-
- mov ax,seg RESIDENT_DATA
- mov ds,ax ; DS -> RESIDENT_DATA
-
- mov TSRPSP,es ; save PSP segment
-
- ; Check the MS-DOS version
-
- call GetDOSVersion ; AH = major version number
- ; AL = minor version number
-
- ; Verify that this TSR is not already installed
- ;
- ; Before executing INT 2Fh in MS-DOS versions 2.x, test whether INT 2FH
- ; vector is in use. If so, abort if PRINT.COM is using it.
- ;
- ; (Thus, in MS-DOS 2.x, if both this program and PRINT.COM are used,
- ; this program should be made resident before PRINT.COM.)
-
- cmp ah,2
- ja L101 ; jump if version 3.0 or later
-
- mov ax,352Fh ; AH = INT 21H function number
- ; AL = interrupt number
- int 21h ; ES:BX = INT 2FH vector
-
- mov ax,es
- or ax,bx ; jump if current INT 2FH vector ..
- jnz L100 ; .. is nonzero
-
- push ds
- mov ax,252Fh ; AH = INT 21H function number
- ; AL = interrupt number
- mov dx,seg RESIDENT_GROUP
- mov ds,dx
- mov dx,offset RESIDENT_GROUP:MultiplexIRET
-
- int 21h ; point INT 2FH vector to IRET
- pop ds
- jmp short L103 ; jump to install this TSR
-
- L100: mov ax,0FF00h ; look for PRINT.COM:
- int 2Fh ; if resident, AH = print queue lengt
- ; otherwise, AH is unchanged
-
- cmp ah,0FFh ; if PRINT.COM is not resident ..
- je L101 ; .. use multiplex interrupt
-
- mov al,1
- call FatalError ; abort if PRINT.COM already installe
-
- L101: mov ah,MultiplexID ; AH = multiplex interrupt ID value
- xor al,al ; AL = 00H
- int 2Fh ; multiplex interrupt
-
- test al,al
- jz L103 ; jump if ok to install
-
- cmp al,0FFh
- jne L102 ; jump if not already installed
-
- mov al,2
- call FatalError ; already installed
-
- L102: mov al,3
- call FatalError ; can't install
-
- ; Get addresses of InDOS and ErrorMode flags
-
- L103: call GetDOSFlags
-
- ; Install this TSR's interrupt handlers
-
- push es ; preserve PSP segment
-
- mov cx,NISR
- mov si,offset StartISRList
-
- L104: lodsb ; AL = interrupt number
- ; DS:SI -> byte past interrupt number
- push ax ; preserve AX
- mov ah,35h ; INT 21H function 35H
- int 21h ; ES:BX = previous interrupt vector
- mov [si+1],bx ; save offset and segment ..
- mov [si+3],es ; .. of previous handler
-
- pop ax ; AL = interrupt number
- push ds ; preserve DS
- mov dx,[si+5]
- mov bx,seg RESIDENT_GROUP
- mov ds,bx ; DS:DX -> this TSR's handler
- mov ah,25h ; INT 21H function 25H
- int 21h ; (set interrupt vector)
- pop ds ; restore DS
- add si,7 ; DS:SI -> next in list
- loop L104
-
- ; Free the environment
-
- pop es ; ES = PSP segment
- push es ; preserve PSP segment
- mov es,es:[2Ch] ; ES = segment of environment
- mov ah,49h ; INT 21H function 49H
- int 21h ; (free memory block)
-
- ; Terminate and stay resident
-
- pop ax ; AX = PSP segment
- mov dx,cs ; DX = paragraph address of start of
- ; transient portion (end of resident
- ; portion)
- sub dx,ax ; DX = size of resident portion
-
- mov ax,3100h ; AH = INT 21H function number
- ; AL = 00H (return code)
- int 21h
-
- InstallSnapTSR ENDP
-
-
- GetDOSVersion PROC near ; Caller: DS = seg RESIDENT_DATA
- ; ES = PSP
- ; Returns: AH = major version
- ; AL = minor version
- ASSUME ds:RESIDENT_DATA
-
- mov ax,30h ; INT 21h function 30H:
- ; (get MS-DOS version)
- int 21h
- cmp al,2
- jb L110 ; jump if version 1.x
-
- xchg ah,al ; AH = major version
- ; AL = minor version
- mov DOSVersion,ax ; save with major version in
- ; high-order byte
- ret
-
- L110: mov al,00h
- call FatalError ; abort if version 1.x
-
- GetDOSVersion ENDP
- GetDOSFlags PROC near ; Caller: DS = seg RESIDENT_DATA
- ; Returns: InDOSAddr -> InDOS
- ; ErrorModeAddr -> ErrorM
- ; Destroys: AX,BX,CX,DI
- ASSUME ds:RESIDENT_DATA
-
- ; Get InDOS address from MS-DOS
-
- push es
-
- mov ah,34h ; INT 21H function number
- int 21h ; ES:BX -> InDOS
- mov word ptr InDOSAddr,bx
- mov word ptr InDOSAddr+2,es
-
- ; Determine ErrorMode address
-
- mov word ptr ErrorModeAddr+2,es ; assume ErrorMode is
- ; in the same segment
- ; as InDOS
-
- mov ax,DOSVersion
- cmp ax,30Ah
- jb L120 ; jump if MS-DOS version earlier
- ; than 3.1 ..
- cmp ax,0A00h
- jae L120 ; .. or MS OS/2-DOS 3.x box
-
- dec bx ; in MS-DOS 3.1 and later, ErrorMode
- mov word ptr ErrorModeAddr,bx ; is just before InDO
- jmp short L125
-
- L120: ; scan MS-DOS segment for ErrorMode
-
- mov cx,0FFFFh ; CX = maximum number of bytes to sca
- xor di,di ; ES:DI -> start of MS-DOS segment
-
- L121: mov ax,word ptr cs:LF2 ; AX = opcode for INT 28H
-
- L122: repne scasb ; scan for first byte of fragment
- jne L126 ; jump if not found
-
- cmp ah,es:[di] ; inspect second byte of opco
- jne L122 ; jump if not INT 28H
-
- mov ax,word ptr cs:LF1 + 1 ; AX = opcode for CMP
- cmp ax,es:[di][LF1-LF2]
- jne L123 ; jump if opcode not CMP
-
- mov ax,es:[di][(LF1-LF2)+2] ; AX = offset of ErrorMode
- jmp short L124 ; in DOS segment
-
- L123: mov ax,word ptr cs:LF3 + 1 ; AX = opcode for TEST
- cmp ax,es:[di][LF3-LF4]
- jne L121 ; jump if opcode not TEST
-
- mov ax,es:[di][(LF3-LF4)+2] ; AX = offset of ErrorMode
-
- L124: mov word ptr ErrorModeAddr,ax
-
- L125: pop es
- ret
-
- ; Come here if address of ErrorMode not found
-
- L126: mov al,04H
- call FatalError
-
-
- ; Code fragments for scanning for ErrorMode flag
-
- LFnear LABEL near ; dummy labels for addressing
- LFbyte LABEL byte
- LFword LABEL word
- ; MS-DOS versions earlier than 3.1
- LF1: cmp ss:LFbyte,0 ; CMP ErrorMode,0
- jne LFnear
- LF2: int 28h
- ; MS-DOS versions 3.1 and later
-
- LF3: test ss:LFbyte,0FFh ; TEST ErrorMode,0FFH
- jne LFnear
- push ss:LFword
- LF4: int 28h
-
- GetDOSFlags ENDP
-
- FatalError PROC near ; Caller: AL = message number
- ; ES = PSP
- ASSUME ds:TRANSIENT_DATA
-
- push ax ; save message number on stack
-
- mov bx,seg TRANSIENT_DATA
- mov ds,bx
-
- ; Display the requested message
-
- mov bx,offset MessageTable
- xor ah,ah ; AX = message number
- shl ax,1 ; AX = offset into MessageTable
- add bx,ax ; DS:BX -> address of message
- mov dx,[bx] ; DS:BX -> message
- mov ah,09h ; INT 21H function 09H (display strin
- int 21h ; display error message
-
- pop ax ; AL = message number
- or al,al
- jz L130 ; jump if message number is zero
- ; (MS-DOS versions 1.x)
-
- ; Terminate (MS-DOS 2.x and later)
-
- mov ah,4Ch ; INT 21H function 4CH
- int 21h ; (terminate process with return code
-
- ; Terminate (MS-DOS 1.x)
-
- L130 PROC far
-
- push es ; push PSP:0000H
- xor ax,ax
- push ax
- ret ; far return (jump to PSP:0000H)
-
- L130 ENDP
-
- FatalError ENDP
-
-
- TRANSIENT_TEXT ENDS
-
- PAGE
- ;
- ;
- ; Transient data segment
- ;
- ;
-
- TRANSIENT_DATA SEGMENT word public 'DATA'
-
- MessageTable DW Message0 ; MS-DOS version error
- DW Message1 ; PRINT.COM found in MS-DOS 2.x
- DW Message2 ; already installed
- DW Message3 ; can't install
- DW Message4 ; can't find flag
-
- Message0 DB CR,LF,'TSR requires MS-DOS 2.0 or later version',CR,LF,'
- Message1 DB CR,LF,'Can''t install TSR: PRINT.COM active',CR,LF,'$'
- Message2 DB CR,LF,'This TSR is already installed',CR,LF,'$'
- Message3 DB CR,LF,'Can''t install this TSR',CR,LF,'$'
- Message4 DB CR,LF,'Unable to locate MS-DOS ErrorMode flag',CR,LF,'$'
-
- TRANSIENT_DATA ENDS
-
- END InstallSnapTSR
-
- \SAMPCODE\DOS_ENCY\12
- \SAMPCODE\DOS_ENCY\12\FXN59H_1.ASM
-
- myfcb db 0 ; drive = default
- db 'MYFILE ' ; filename, 8 chars
- db 'DAT' ; extension, 3 chars
- db 25 dup (0) ; remainder of FCB
- .
- .
- .
- mov dx,seg myfcb ; DS:DX = FCB
- mov ds,dx
- mov dx,offset myfcb
- mov ah,0fh ; function 0FH = Open FCB
-
- int 21h ; transfer to MS-DOS
- or al,al ; test status
- jz success ; jump, open succeeded
- ; open failed, get
- ; extended error info
- mov bx,0 ; BX = 00H for ver. 2.x-3.x
- mov ah,59h ; function 59H = Get Info
- int 21h ; transfer to MS-DOS
- or ax,ax ; really an error?
- jz success ; no error, jump
- ; test recommended actions
- cmp bl,01h
- jz retry ; if BL = 01H retry operation
- cmp bl,04h
- jz cleanup ; if BL = 04H clean up and exit
- cmp bl,05h
- jz panic ; if BL = 05H exit immediately
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\12\FXN59H_2.ASM
-
- myfile db 'MYFILE.DAT',0 ; ASCIIZ filename
- .
- .
- .
- mov dx,seg myfile ; DS:DX = ASCIIZ filename
- mov ds,dx
- mov dx,offset myfile
- mov ax,3d02h ; open, read/write
- int 21h ; transfer to MS-DOS
- jnc success ; jump, open succeeded
- ; open failed, get
- ; extended error info
- mov bx,0 ; BX = 00H for ver. 2.x-3.x
- mov ah,59h ; function 59H = Get Info
- int 21h ; transfer to MS-DOS
- or ax,ax ; really an error?
- jz success ; no error, jump
- ; test recommended actions
- cmp bl,01h
- jz retry ; if BL = 01H retry operation
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\12\INT24.ASM
-
- name int24
- title INT24 Critical Error Handler
-
- ;
- ; INT24.ASM -- Replacement critical error handler
- ; by Ray Duncan, September 1987
- ;
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII linefeed
-
- DGROUP group _DATA
-
- _DATA segment word public 'DATA'
-
- save24 dd 0 ; previous contents of Int 24H
- ; critical error handler vector
-
- ; prompt message used by
- ; critical error handler
- prompt db cr,lf,'Critical Error Occurred: '
- db 'Abort, Retry, Ignore, Fail? $'
-
- keys db 'aArRiIfF' ; possible user response keys
- keys_len equ $-keys ; (both cases of each allowed)
-
- codes db 2,2,1,1,0,0,3,3 ; codes returned to MS-DOS kernel
- ; for corresponding response keys
-
- _DATA ends
-
-
- _TEXT segment word public 'CODE'
-
- assume cs:_TEXT,ds:DGROUP
-
- public get24
- get24 proc near ; set Int 24H vector to point
- ; to new critical error handler
-
- push ds ; save segment registers
- push es
-
- mov ax,3524h ; get address of previous
- int 21h ; INT 24H handler and save it
-
- mov word ptr save24,bx
- mov word ptr save24+2,es
-
- push cs ; set DS:DX to point to
- pop ds ; new INT 24H handler
- mov dx,offset _TEXT:int24
- mov ax,2524h ; then call MS-DOS to
- int 21h ; set the INT 24H vector
-
- pop es ; restore segment registers
- pop ds
- ret ; and return to caller
-
- get24 endp
-
-
- public res24
- res24 proc near ; restore original contents
- ; of Int 24H vector
-
- push ds ; save our data segment
-
- lds dx,save24 ; put address of old handler
- mov ax,2524h ; back into INT 24H vector
- int 21h
-
- pop ds ; restore data segment
- ret ; and return to caller
-
- res24 endp
-
- ;
- ; This is the replacement critical error handler. It
- ; prompts the user for Abort, Retry, Ignore, or Fail and
- ; returns the appropriate code to the MS-DOS kernel.
- ;
- int24 proc far ; entered from MS-DOS kernel
-
- push bx ; save registers
- push cx
- push dx
- push si
- push di
- push bp
- push ds
- push es
-
- int24a: mov ax,DGROUP ; display prompt for user
- mov ds,ax ; using function 09H (print string
- mov es,ax ; terminated by $ character)
- mov dx,offset prompt
- mov ah,09h
- int 21h
-
- mov ah,01h ; get user's response
- int 21h ; Function 01H = read one character
-
- mov di,offset keys ; look up code for response key
- mov cx,keys_len
- cld
- repne scasb
- jnz int24a ; prompt again if bad response
-
- ; set AL = action code for MS-DOS
- ; according to key that was entered:
- ; 0 = ignore, 1 = retry, 2 = abort, 3 = fail
- mov al,[di+keys_len-1]
-
- pop es ; restore registers
- pop ds
- pop bp
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- iret ; exit critical error handler
-
- int24 endp
-
- _TEXT ends
-
- end
-
- \SAMPCODE\DOS_ENCY\12\REST_INT.ASM
-
- rest_int proc near
- push ds ; save our data segment
- mov dx,word ptr oldint23
- mov ds,word ptr oldint23+2
- mov ax,2523h ; restore original contents
- int 21h ; of Int 23H vector
- pop ds ; restore our data segment
- push ds ; then save it again
- mov dx,word ptr oldint1B
- mov ds,word ptr oldint1B+2
- mov ax,251Bh ; restore original contents
- int 21h ; of Int 1BH vector
- pop ds ; get back our data segment
- ret ; return to caller
- rest_int endp
-
- \SAMPCODE\DOS_ENCY\12\SET_INT.ASM
-
- _DATA segment para public 'DATA'
- oldint1b dd 0 ; original INT 1BH vector
- oldint23 dd 0 ; original INT 23H vector
- _DATA ends
- _TEXT segment byte public 'CODE'
- assume cs:_TEXT,ds:_DATA,es:NOTHING
- myint1b: ; handler for Ctrl-Break
- myint23: ; handler for Ctrl-C
- iret
-
- set_int proc near
- mov ax,351bh ; get current contents of
- int 21h ; Int 1BH vector and save it
- mov word ptr oldint1b,bx
- mov word ptr oldint1b+2,es
- mov ax,3523h ; get current contents of
- int 21h ; Int 23H vector and save it
- mov word ptr oldint23,bx
- mov word ptr oldint23+2,es
- push ds ; save our data segment
- push cs ; let DS point to our
- pop ds ; code segment
- mov dx,offset myint1b
- mov ax,251bh ; set interrupt vector 1BH
- int 21h ; to point to new handler
- mov dx,offset myint23
- mov ax,2523h ; set interrupt vector 23H
- int 21h ; to point to new handler
- pop ds ; restore our data segment
- ret ; back to caller
- set_int endp
- _TEXT ends
-
- \SAMPCODE\DOS_ENCY\13
- \SAMPCODE\DOS_ENCY\13\DIVZERO.ASM
-
- name divzero
- title 'DIVZERO - Interrupt 00H Handler'
- ;
- ; DIVZERO.ASM: Demonstration Interrupt 00H Handler
- ;
- ; To assemble, link, and convert to COM file:
- ;
- ; C>MASM DIVZERO; <Enter>
- ; C>LINK DIVZERO; <Enter>
- ; C>EXE2BIN DIVZERO.EXE DIVZERO.COM <Enter>
- ; C>DEL DIVZERO.EXE <Enter>
- ;
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII linefeed
- eos equ '$' ; end of string marker
-
- _TEXT segment word public 'CODE'
-
- assume cs:_TEXT,ds:_TEXT,es:_TEXT,ss:_TEXT
-
- org 100h
-
- entry: jmp start ; skip over data area
-
- intmsg db 'Divide by Zero Occurred!',cr,lf,eos
-
- divmsg db 'Dividing ' ; message used by demo
- par1 db '0000h' ; dividend goes here
- db ' by '
- par2 db '00h' ; divisor goes here
- db ' equals '
- par3 db '00h' ; quotient here
- db ' remainder '
- par4 db '00h' ; and remainder here
- db cr,lf,eos
-
- oldint0 dd ? ; save old Int 00H vector
-
- intflag db 0 ; nonzero if divide by
- ; zero interrupt occurred
-
- oldip dw 0 ; save old IP value
-
-
- ;
- ; The routine 'int0' is the actual divide by zero
- ; interrupt handler. It gains control whenever a
- ; divide by zero or overflow occurs. Its action
- ; is to set a flag and then increment the instruction
- ; pointer saved on the stack so that the failing
- ; divide will not be reexecuted after the IRET.
- ;
- ; In this particular case we can call MS-DOS to
- ; display a message during interrupt handling
- ; because the application triggers the interrupt
- ; intentionally. Thus, it is known that MS-DOS or
- ; other interrupt handlers are not in control
- ; at the point of interrupt.
- ;
-
- int0: pop cs:oldip ; capture instruction pointer
-
- push ax
- push bx
- push cx
- push dx
- push di
- push si
- push ds
- push es
-
- push cs ; set DS = CS
- pop ds
-
- mov ah,09h ; print error message
- mov dx,offset _TEXT:intmsg
- int 21h
-
- add oldip,2 ; bypass instruction causing
- ; divide by zero error
-
- mov intflag,1 ; set divide by 0 flag
-
- pop es ; restore all registers
- pop ds
- pop si
- pop di
- pop dx
- pop cx
- pop bx
- pop ax
-
- push cs:oldip ; restore instruction pointer
-
- iret ; return from interrupt
-
-
- ;
- ; The code beginning at 'start' is the application
- ; program. It alters the vector for Interrupt 00H to
- ; point to the new handler, carries out some divide
- ; operations (including one that will trigger an
- ; interrupt) for demonstration purposes, restores
- ; the original contents of the Interrupt 00H vector,
- ; and then terminates.
- ;
-
- start: mov ax,3500h ; get current contents
- int 21h ; of Int 00H vector
-
- ; save segment:offset
- ; of previous Int 00H handler
- mov word ptr oldint0,bx
- mov word ptr oldint0+2,es
-
- ; install new handler...
- mov dx,offset int0 ; DS:DX = handler address
- mov ax,2500h ; call MS-DOS to set
- int 21h ; Int 00H vector
-
- ; now our handler is active,
- ; carry out some test divides.
-
- mov ax,20h ; test divide
- mov bx,1 ; divide by 1
- call divide
-
- mov ax,1234h ; test divide
- mov bx,5eh ; divide by 5EH
- call divide
-
- mov ax,5678h ; test divide
- mov bx,7fh ; divide by 127
- call divide
-
- mov ax,20h ; test divide
- mov bx,0 ; divide by 0
- call divide ; (triggers interrupt)
-
- ; demonstration complete,
- ; restore old handler
-
- lds dx,oldint0 ; DS:DX = handler address
- mov ax,2500h ; call MS-DOS to set
- int 21h ; Int 00H vector
-
- mov ax,4c00h ; final exit to MS-DOS
- int 21h ; with return code = 0
-
- ;
- ; The routine 'divide' carries out a trial division,
- ; displaying the arguments and the results. It is
- ; called with AX = dividend and BL = divisor.
- ;
-
- divide proc near
-
- push ax ; save arguments
- push bx
-
- mov di,offset par1 ; convert dividend to
- call wtoa ; ASCII for display
-
- mov ax,bx ; convert divisor to
- mov di,offset par2 ; ASCII for display
- call btoa
-
- pop bx ; restore arguments
- pop ax
-
- div bl ; perform the division
- cmp intflag,0 ; divide by zero detected?
- jne nodiv ; yes, skip display
-
- push ax ; no, convert quotient to
- mov di,offset par3 ; ASCII for display
- call btoa
-
- pop ax ; convert remainder to
- xchg ah,al ; ASCII for display
- mov di,offset par4
- call btoa
-
- mov ah,09h ; show arguments, results
- mov dx,offset divmsg
- int 21h
-
- nodiv: mov intflag,0 ; clear divide by 0 flag
- ret ; and return to caller
-
- divide endp
-
-
-
- wtoa proc near ; convert word to hex ASCII
- ; call with AX = binary value
- ; DI = addr for string
- ; returns AX, CX, DI destroyed
-
- push ax ; save original value
- mov al,ah
- call btoa ; convert upper byte
- add di,2 ; increment output address
- pop ax
- call btoa ; convert lower byte
- ret ; return to caller
-
- wtoa endp
-
-
-
- btoa proc near ; convert byte to hex ASCII
- ; call with AL = binary value
- ; DI = addr to store string
- ; returns AX, CX destroyed
-
- mov ah,al ; save lower nibble
- mov cx,4 ; shift right 4 positions
- shr al,cl ; to get upper nibble
- call ascii ; convert 4 bits to ASCII
- mov [di],al ; store in output string
- mov al,ah ; get back lower nibble
-
- and al,0fh ; blank out upper one
- call ascii ; convert 4 bits to ASCII
- mov [di+1],al ; store in output string
- ret ; back to caller
-
- btoa endp
-
-
-
- ascii proc near ; convert AL bits 0-3 to
- ; ASCII {0...9,A...F}
- add al,'0' ; and return digit in AL
- cmp al,'9'
- jle ascii2
- add al,'A'-'9'-1 ; "fudge factor" for A-F
- ascii2: ret ; return to caller
-
- ascii endp
-
- _TEXT ends
-
- end entry
-
- \SAMPCODE\DOS_ENCY\13\INT08H.ASM
-
- .
- .
- .
- myflag dw ? ; variable to be incremented
- ; on each timer-tick interrupt
-
- oldint8 dd ? ; contains address of previous
- ; timer-tick interrupt handler
- .
- . ; get the previous contents
- . ; of the Interrupt 0BH vector...
- mov ax,3508h ; AH = 35H (Get Interrupt Vector)
- int 21h ; AL = Interrupt number (08H)
- mov word ptr oldint8,bx ; save the address of
- mov word ptr oldint8+2,es ; the previous Int 08H Handler
- mov dx,seg myint8 ; put address of the new
- mov ds,dx ; interrupt handler into DS:DX
- mov dx,offset myint8 ; and call MS-DOS to set vector
- mov ax,2508h ; AH = 25H (Set Interrupt Vector)
- int 21h ; AL = Interrupt number (08H)
- .
- .
- .
- myint8: ; this is the new handler
- ; for Interrupt 08H
-
- inc cs:myflag ; increment variable on each
- ; timer-tick interrupt
-
- jmp dword ptr cs:[oldint8] ; then chain to the
- ; previous interrupt handler
-
- \SAMPCODE\DOS_ENCY\13\MYINT8.ASM
-
- myint8: ; this is the new handler
- ; for Interrupt 08H
-
- mov ax,1 ; test and set interrupt-
- xchg cs:myflag,ax ; handling-in-progress semaphore
-
- push ax ; save the semaphore
-
- pushf ; simulate interrupt, allowing
- call dword ptr cs:oldint8 ; the previous handler for the
- ; Interrupt 08H vector to run
-
- pop ax ; get the semaphore back
- or ax,ax ; is our interrupt handler
- ; already running?
-
- jnz myint8x ; yes, skip this one
-
- . ; now perform our interrupt
- . ; processing here...
- .
-
- mov cs:myflag,0 ; clear the interrupt-handling-
- ; in-progress flag
-
- myint8x:
- iret ; return from interrupt
-
- \SAMPCODE\DOS_ENCY\14
- \SAMPCODE\DOS_ENCY\14\FIND.C
-
- /*
- FIND.C Searches text stream for a string.
-
- Usage: FIND "pattern" [< source] [> destination]
-
- by Ray Duncan, June 1987
-
- */
-
- #include <stdio.h>
-
- #define TAB '\x09' /* ASCII tab character (^I) */
- #define BLANK '\x20' /* ASCII space character */
-
- #define TAB_WIDTH 8 /* columns per tab stop */
-
- static char input[256]; /* buffer for line from input */
- static char output[256]; /* buffer for line to output */
- static char pattern[256]; /* buffer for search pattern */
-
- main(argc,argv)
- int argc;
- char *argv[];
- { int line=0; /* initialize line variable */
-
- if ( argc < 2 ) /* was search pattern supplied? */
- { puts("find: missing pattern.");
- exit(1); /* abort if not */
- }
- strcpy(pattern,argv[1]); /* save copy of string to find */
- strupr(pattern); /* fold it to uppercase */
- while( gets(input) != NULL ) /* read a line from input */
- { line++; /* count lines */
- strcpy(output,input); /* save copy of input string */
- strupr(input); /* fold input to uppercase */
- /* if line contains pattern */
- if( strstr(input,pattern) )
- /* write it to standard output */
- writeline(line,output);
- }
- exit(0); /* terminate at end of file */
- }
-
- /*
- WRITELINE: Write line number and text to standard output,
- expanding any tab characters to stops defined by TAB_WIDTH.
- */
-
- writeline(line,p)
- int line;
- char *p;
- { int i=0; /* index to original line text */
- int col=0; /* actual output column counter */
- printf("\n%4d: ",line); /* write line number */
- while( p[i]!=NULL ) /* while end of line not reached */
- { if(p[i]==TAB) /* if current char = tab, expand it *
- { do putchar(BLANK);
- while((++col % TAB_WIDTH) != 0);
- }
- else /* otherwise just send character */
- { putchar(p[i]);
- col++; /* count columns */
- }
- i++; /* advance through output line */
- }
- }
-
- \SAMPCODE\DOS_ENCY\14\LC.C
-
- /*
- LC: a simple character-oriented filter to translate
- all uppercase {A-Z} to lowercase {a-z} characters.
-
- Usage: LC [< source] [> destination]
-
- Ray Duncan, June 1987
-
- */
-
- #include <stdio.h>
-
- main(argc,argv)
- int argc;
- char *argv[];
- { char ch;
- /* read a character */
- while ( (ch=getchar() ) != EOF )
- { ch=translate(ch); /* perform any necessary
- character translation */
- putchar(ch); /* then write character */
- }
- exit(0); /* terminate at end of file */
- }
-
- /*
- Translate characters A-Z to lowercase equivalents
- */
-
- int translate(ch)
- char ch;
- { if (ch >= 'A' && ch <= 'Z') ch += 'a'-'A';
- return (ch);
- }
-
- \SAMPCODE\DOS_ENCY\14\PROTOC.C
-
- /*
- PROTOC.C: a template for a character-oriented filter.
-
- Ray Duncan, June 1987
- */
-
- #include <stdio.h>
-
- main(argc,argv)
- int argc;
- char *argv[];
- { char ch;
-
- while ( (ch=getchar())!=EOF ) /* read a character */
- { ch=translate(ch); /* translate it if necessary */
- putchar(ch); /* write the character */
- }
- exit(0); /* terminate at end of file */
- }
-
- /*
- Perform any necessary translation on character from
- input file. Template action just returns same character.
- */
-
- int translate(ch)
- char ch;
- { return (ch);
- }
-
- \SAMPCODE\DOS_ENCY\14\PROTOL.C
-
- /*
- PROTOL.C: a template for a line-oriented filter.
-
- Ray Duncan, June 1987.
- */
-
- #include <stdio.h>
-
- static char input[256]; /* buffer for input line */
- static char output[256]; /* buffer for output line */
-
- main(argc,argv)
- int argc;
- char *argv[];
- { while( gets(input) != NULL ) /* get a line from input stream */
- /* perform any necessary translation
- and possibly write result */
- { if (translate()) puts(output);
- }
- exit(0); /* terminate at end of file */
- }
-
- /*
- Perform any necessary translation on input line, leaving
- the resulting text in output buffer. Value of function
- is 'true' if output buffer should be written to standard output
- by main routine, 'false' if nothing should be written.
- */
-
- translate()
- { strcpy(output,input); /* template action is copy input */
- return(1); /* line and return true flag */
- }
-
- \SAMPCODE\DOS_ENCY\14\EXECSORT.ASM
-
- name execsort
- title 'EXECSORT --- demonstrate EXEC of filter'
- .sall
- ;
- ; EXECSORT.ASM --- demonstration of use of EXEC to run the SORT
- ; filter as a child process, redirecting its input and output.
- ; This program requires the files SORT.EXE and MYFILE.DAT in
- ; the current drive and directory.
- ;
- ; Ray Duncan, June 1987
- ;
-
- stdin equ 0 ; standard input
- stdout equ 1 ; standard output
- stderr equ 2 ; standard error
-
- stksize equ 128 ; size of stack
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII linefeed
-
- jerr macro target ;; Macro to test carry flag
- local notset ;; and jump if flag set.
- jnc notset ;; Uses JMP DISP16 to avoid
- jmp target ;; branch out of range errors
- notset:
- endm
-
-
- DGROUP group _DATA,_STACK ; 'automatic data group'
-
-
- _TEXT segment byte public 'CODE' ; executable code segment
-
- assume cs:_TEXT,ds:DGROUP,ss:_STACK
-
-
- stk_seg dw ? ; original SS contents
- stk_ptr dw ? ; original SP contents
-
-
- main proc far ; entry point from MS-DOS
-
- mov ax,DGROUP ; set DS = our data segment
- mov ds,ax
-
- ; now give back extra memory so
- ; child SORT has somewhere to run...
- mov ax,es ; let AX = segment of PSP base
- mov bx,ss ; and BX = segment of stack base
- sub bx,ax ; reserve seg stack - seg psp
- add bx,stksize/16 ; plus paragraphs of stack
- mov ah,4ah ; fxn 4AH = modify memory block
- int 21h ; transfer to MS-DOS
- jerr main1 ; jump if resize block failed
-
- ; prepare stdin and stdout
- ; handles for child SORT process
-
- mov bx,stdin ; dup the handle for stdin
- mov ah,45h
- int 21h ; transfer to MS-DOS
- jerr main1 ; jump if dup failed
- mov oldin,ax ; save dup'd handle
-
- mov dx,offset DGROUP:infile ; now open the input file
- mov ax,3d00h ; mode = read-only
- int 21h ; transfer to MS-DOS
- jerr main1 ; jump if open failed
-
- mov bx,ax ; force stdin handle to
- mov cx,stdin ; track the input file handle
- mov ah,46h
- int 21h ; transfer to MS-DOS
- jerr main1 ; jump if force dup failed
-
- mov bx,stdout ; dup the handle for stdout
- mov ah,45h
- int 21h ; transfer to MS-DOS
- jerr main1 ; jump if dup failed
- mov oldout,ax ; save dup'd handle
-
- mov dx,offset dGROUP:outfile ; now create the output file
- mov cx,0 ; normal attribute
- mov ah,3ch
- int 21h ; transfer to MS-DOS
- jerr main1 ; jump if create failed
-
- mov bx,ax ; force stdout handle to
- mov cx,stdout ; track the output file handle
- mov ah,46h
- int 21h ; transfer to MS-DOS
- jerr main1 ; jump if force dup failed
-
- ; now EXEC the child SORT,
- ; which will inherit redirected
- ; stdin and stdout handles
-
- push ds ; save EXECSORT's data segment
- mov stk_seg,ss ; save EXECSORT's stack pointer
- mov stk_ptr,sp
-
- mov ax,ds ; set ES = DS
- mov es,ax
- mov dx,offset DGROUP:cname ; DS:DX = child pathname
- mov bx,offset DGROUP:pars ; EX:BX = parameter block
- mov ax,4b00h ; function 4BH, subfunction 00H
- int 21h ; transfer to MS-DOS
-
- cli ; (for bug in some early 8088s)
- mov ss,stk_seg ; restore execsort's stack pointer
- mov sp,stk_ptr
- sti ; (for bug in some early 8088s)
- pop ds ; restore DS = our data segment
-
- jerr main1 ; jump if EXEC failed
-
- mov bx,oldin ; restore original meaning of
- mov cx,stdin ; standard input handle for
- mov ah,46h ; this process
- int 21h
- jerr main1 ; jump if force dup failed
-
- mov bx,oldout ; restore original meaning
- mov cx,stdout ; of standard output handle
- mov ah,46h ; for this process
- int 21h
- jerr main1 ; jump if force dup failed
-
- mov bx,oldin ; close dup'd handle of
- mov ah,3eh ; original stdin
- int 21h ; transfer to MS-DOS
- jerr main1 ; jump if close failed
-
- mov bx,oldout ; close dup'd handle of
- mov ah,3eh ; original stdout
- int 21h ; transfer to MS-DOS
- jerr main1 ; jump if close failed
-
- ; display success message
- mov dx,offset DGROUP:msg1 ; address of message
- mov cx,msg1_len ; message length
- mov bx,stdout ; handle for standard output
- mov ah,40h ; fxn 40H = write file or device
- int 21h ; transfer to MS-DOS
- jerr main1
-
- mov ax,4c00h ; no error, terminate program
- int 21h ; with return code = 0
-
- main1: mov ax,4c01h ; error, terminate program
- int 21h ; with return code = 1
-
- main endp ; end of main procedure
-
- _TEXT ends
-
-
- _DATA segment para public 'DATA' ; static & variable data segment
-
- infile db 'MYFILE.DAT',0 ; input file for SORT filter
- outfile db 'MYFILE.SRT',0 ; output file for SORT filter
-
- oldin dw ? ; dup of old stdin handle
- oldout dw ? ; dup of old stdout handle
-
- cname db 'SORT.EXE',0 ; pathname of child SORT process
-
- pars dw 0 ; segment of environment block
- ; (0 = inherit parent's)
- dd tail ; long address, command tail
- dd -1 ; long address, default FCB #1
- ; (-1 = none supplied)
- dd -1 ; long address, default FCB #2
- ; (-1 = none supplied)
-
- tail db 0,cr ; empty command tail for child
-
- msg1 db cr,lf,'SORT was executed as child.',cr,lf
- msg1_len equ $-msg1
-
- _DATA ends
-
-
- _STACK segment para stack 'STACK'
-
- db stksize dup (?)
-
- _STACK ends
-
-
- end main ; defines program entry point
-
- \SAMPCODE\DOS_ENCY\14\LC.ASM
-
- name lc
- title 'LC.ASM --- lowercase filter'
- ;
- ; LC.ASM: a simple character-oriented filter to translate
- ; all uppercase {A-Z} to lowercase {a-z}.
- ;
- ; Ray Duncan, June 1987
- ;
-
- stdin equ 0 ; standard input
- stdout equ 1 ; standard output
- stderr equ 2 ; standard error
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII linefeed
-
-
- DGROUP group _DATA,STACK ; 'automatic data group'
-
-
- _TEXT segment byte public 'CODE'
-
- assume cs:_TEXT,ds:DGROUP,ss:STACK
-
- main proc far ; entry point from MS-DOS
-
- mov ax,DGROUP ; set DS = our data segment
- mov ds,ax
-
- main1: ; read a character from standard input
- mov dx,offset DGROUP:char ; address to place character
- mov cx,1 ; length to read = 1
- mov bx,stdin ; handle for standard input
- mov ah,3fh ; function 3FH = read from file or device
- int 21h ; transfer to MS-DOS
- jc main3 ; error, terminate
- cmp ax,1 ; any character read?
- jne main2 ; end of file, terminate program
-
- call translt ; translate character if necessary
-
- ; now write character to standard output
- mov dx,offset DGROUP:char ; address of character
- mov cx,1 ; length to write = 1
- mov bx,stdout ; handle for standard output
- mov ah,40h ; function 40H = write to file or device
- int 21h ; transfer to MS-DOS
- jc main3 ; error, terminate
- cmp ax,1 ; was character written?
- jne main3 ; disk full, terminate program
- jmp main1 ; go process another character
-
- main2: mov ax,4c00h ; end of file reached, terminate
- int 21h ; program with return code = 0
-
- main3: mov ax,4c01h ; error or disk full, terminate
- int 21h ; program with return code = 1
-
- main endp ; end of main procedure
-
- ;
- ; Translate uppercase {A-Z} characters to corresponding
- ; lowercase characters {a-z}. Leave other characters unchanged.
- ;
- translt proc near
-
- cmp byte ptr char,'A'
- jb transx
- cmp byte ptr char,'Z'
- ja transx
- add byte ptr char,'a'-'A'
- transx: ret
-
- translt endp
-
-
- _TEXT ends
-
-
- _DATA segment word public 'DATA'
-
- char db 0 ; temporary storage for input character
-
- _DATA ends
-
-
- STACK segment para stack 'STACK'
-
- dw 64 dup (?)
-
- STACK ends
-
-
- end main ; defines program entry point
-
- \SAMPCODE\DOS_ENCY\14\PROTOC.ASM
-
- name protoc
- title 'PROTOC.ASM --- template character filter'
- ;
- ; PROTOC.ASM: a template for a character-oriented filter.
- ;
- ; Ray Duncan, June 1987
- ;
-
- stdin equ 0 ; standard input
- stdout equ 1 ; standard output
- stderr equ 2 ; standard error
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII linefeed
-
-
- DGROUP group _DATA,STACK ; 'automatic data group'
-
-
- _TEXT segment byte public 'CODE'
-
- assume cs:_TEXT,ds:DGROUP,ss:STACK
-
- main proc far ; entry point from MS-DOS
-
- mov ax,DGROUP ; set DS = our data segment
- mov ds,ax
-
- main1: ; read a character from standard input
- mov dx,offset DGROUP:char ; address to place character
- mov cx,1 ; length to read = 1
- mov bx,stdin ; handle for standard input
- mov ah,3fh ; function 3FH = read from file or device
- int 21h ; transfer to MS-DOS
- jc main3 ; error, terminate
- cmp ax,1 ; any character read?
- jne main2 ; end of file, terminate program
-
- call translt ; translate character if necessary
-
- ; now write character to standard output
- mov dx,offset DGROUP:char ; address of character
- mov cx,1 ; length to write = 1
- mov bx,stdout ; handle for standard output
- mov ah,40h ; function 40H = write to file or device
- int 21h ; transfer to MS-DOS
- jc main3 ; error, terminate
- cmp ax,1 ; was character written?
- jne main3 ; disk full, terminate program
- jmp main1 ; go process another character
-
- main2: mov ax,4c00h ; end of file reached, terminate
- int 21h ; program with return code = 0
-
- main3: mov ax,4c01h ; error or disk full, terminate
- int 21h ; program with return code = 1
-
- main endp ; end of main procedure
-
- ;
- ; Perform any necessary translation on character from input,
- ; stored in 'char'. Template action: leave character unchanged.
- ;
- translt proc near
-
- ret ; template action: do nothing
-
- translt endp
-
-
- _TEXT ends
-
-
- _DATA segment word public 'DATA'
-
- char db 0 ; temporary storage for input character
-
- _DATA ends
-
-
- STACK segment para stack 'STACK'
-
- dw 64 dup (?)
-
- STACK ends
-
-
- end main ; defines program entry point
-
- \SAMPCODE\DOS_ENCY\14\PROTOL.ASM
-
- name protol
- title 'PROTOL.ASM --- template line filter'
- ;
- ; PROTOL.ASM: a template for a line-oriented filter.
- ;
- ; Ray Duncan, June 1987
- ;
-
- stdin equ 0 ; standard input
- stdout equ 1 ; standard output
- stderr equ 2 ; standard error
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII linefeed
-
-
- DGROUP group _DATA,STACK ; 'automatic data group'
-
-
- _TEXT segment byte public 'CODE'
-
- assume cs:_TEXT,ds:DGROUP,es:DGROUP,ss:STACK
-
- main proc far ; entry point from MS-DOS
-
- mov ax,DGROUP ; set DS = ES = our data segment
- mov ds,ax
- mov es,ax
-
- main1: ; read a line from standard input
- mov dx,offset DGROUP:input ; address to place data
- mov cx,256 ; max length to read = 256
- mov bx,stdin ; handle for standard input
- mov ah,3fh ; function 3FH = read from file or device
- int 21h ; transfer to MS-DOS
- jc main3 ; if error, terminate
- or ax,ax ; any characters read?
- jz main2 ; end of file, terminate program
-
- call translt ; translate line if necessary
- or ax,ax ; anything to output after translation?
- jz main1 ; no, get next line
-
- ; now write line to standard output
- mov dx,offset DGROUP:output ; address of data
- mov cx,ax ; length to write
- mov bx,stdout ; handle for standard output
- mov ah,40h ; function 40H = write to file or device
- int 21h ; transfer to MS-DOS
- jc main3 ; if error, terminate
- cmp ax,cx ; was entire line written?
- jne main3 ; disk full, terminate program
- jmp main1 ; go process another line
-
- main2: mov ax,4c00h ; end of file reached, terminate
- int 21h ; program with return code = 0
-
- main3: mov ax,4c01h ; error or disk full, terminate
- int 21h ; program with return code = 1
-
- main endp ; end of main procedure
-
- ;
- ; Perform any necessary translation on line stored in
- ; 'input' buffer, leaving result in 'output' buffer.
- ;
- ; Call with: AX = length of data in 'input' buffer.
- ;
- ; Return: AX = length to write to standard output.
- ;
- ; Action of template routine is just to copy the line.
- ;
- translt proc near
-
- ; just copy line from input to output
- mov si,offset DGROUP:input
- mov di,offset DGROUP:output
- mov cx,ax
- rep movsb
- ret ; return length in AX unchanged
-
- translt endp
-
-
- _TEXT ends
-
-
- _DATA segment word public 'DATA'
-
- input db 256 dup (?) ; storage for input line
- output db 256 dup (?) ; storage for output line
-
- _DATA ends
-
-
- STACK segment para stack 'STACK'
-
- dw 64 dup (?)
-
- STACK ends
-
-
- end main ; defines program entry point
-
- \SAMPCODE\DOS_ENCY\15
- \SAMPCODE\DOS_ENCY\15\TEMPLATE.ASM
-
- name template
- title 'TEMPLATE --- installable driver template'
-
- ;
- ; TEMPLATE.ASM: A program skeleton for an installable
- ; device driver (MS-DOS 2.0 or later)
- ;
- ; The driver command-code routines are stubs only and have
- ; no effect but to return a nonerror "Done" status.
- ;
- ; Ray Duncan, July 1987
- ;
-
- _TEXT segment byte public 'CODE'
-
- assume cs:_TEXT,ds:_TEXT,es:NOTHING
-
- org 0
-
- MaxCmd equ 24 ; maximum allowed command code
- ; 12 for MS-DOS 2.x
- ; 16 for MS-DOS 3.0-3.1
- ; 24 for MS-DOS 3.2-3.3
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII linefeed
- eom equ '$' ; end-of-message signal
-
-
- Header: ; device driver header
- dd -1 ; link to next device driver
- dw c840h ; device attribute word
- dw Strat ; "Strategy" routine entry point
- dw Intr ; "Interrupt" routine entry point
- db 'TEMPLATE' ; logical device name
-
-
- RHPtr dd ? ; pointer to request header, passed
- ; by MS-DOS kernel to Strategy routine
-
-
- Dispatch: ; Interrupt routine command code
- ; dispatch table
- dw Init ; 0 = initialize driver
- dw MediaChk ; 1 = media check on block device
- dw BuildBPB ; 2 = build BIOS parameter block
- dw IoctlRd ; 3 = I/O control read
- dw Read ; 4 = read (input) from device
- dw NdRead ; 5 = nondestructive read
- dw InpStat ; 6 = return current input status
- dw InpFlush ; 7 = flush device input buffers
- dw Write ; 8 = write (output) to device
- dw WriteVfy ; 9 = write with verify
- dw OutStat ; 10 = return current output status
- dw OutFlush ; 11 = flush output buffers
- dw IoctlWt ; 12 = I/O control write
- dw DevOpen ; 13 = device open (MS-DOS 3.0+)
- dw DevClose ; 14 = device close (MS-DOS 3.0+)
- dw RemMedia ; 15 = removable media (MS-DOS 3.0+)
- dw OutBusy ; 16 = output until busy (MS-DOS 3.0+)
- dw Error ; 17 = not used
- dw Error ; 18 = not used
- dw GenIOCTL ; 19 = generic IOCTL (MS-DOS 3.2+)
- dw Error ; 20 = not used
- dw Error ; 21 = not used
- dw Error ; 22 = not used
- dw GetLogDev ; 23 = get logical device (MS-DOS 3.2+)
- dw SetLogDev ; 24 = set logical device (MS-DOS 3.2+)
-
-
- Strat proc far ; device driver Strategy routine,
- ; called by MS-DOS kernel with
- ; ES:BX = address of request header
-
- ; save pointer to request header
- mov word ptr cs:[RHPtr],bx
- mov word ptr cs:[RHPtr+2],es
-
- ret ; back to MS-DOS kernel
-
- Strat endp
-
-
- Intr proc far ; device driver Interrupt routine,
- ; called by MS-DOS kernel immediately
- ; after call to Strategy routine
-
- push ax ; save general registers
- push bx
- push cx
- push dx
- push ds
- push es
- push di
- push si
- push bp
-
- push cs ; make local data addressable
- pop ds ; by setting DS = CS
-
- les di,[RHPtr] ; let ES:DI = request header
-
- ; get BX = command code
- mov bl,es:[di+2]
- xor bh,bh
- cmp bx,MaxCmd ; make sure it's valid
- jle Intr1 ; jump, function code is ok
- call Error ; set error bit, "Unknown Command" code
- jmp Intr2
-
- Intr1: shl bx,1 ; form index to dispatch table
- ; and branch to command-code routine
- call word ptr [bx+Dispatch]
-
- les di,[RHPtr] ; ES:DI = address of request header
-
- Intr2: or ax,0100h ; merge Done bit into status and
- mov es:[di+3],ax ; store status into request header
-
- pop bp ; restore general registers
- pop si
- pop di
- pop es
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- ret ; return to MS-DOS kernel
-
-
- ; Command-code routines are called by the Interrupt routine
- ; via the dispatch table with ES:DI pointing to the request
- ; header. Each routine should return AX = 00H if function was
- ; completed successfully or AX = 8000H + error code if
- ; function failed.
-
-
- MediaChk proc near ; function 1 = Media Check
-
- xor ax,ax
- ret
-
- MediaChk endp
-
-
- BuildBPB proc near ; function 2 = Build BPB
-
- xor ax,ax
- ret
-
- BuildBPB endp
-
-
- IoctlRd proc near ; function 3 = I/O Control Read
-
- xor ax,ax
- ret
-
- IoctlRd endp
-
-
- Read proc near ; function 4 = Read (Input)
-
- xor ax,ax
- ret
-
- Read endp
-
-
- NdRead proc near ; function 5 = Nondestructive Read
-
- xor ax,ax
- ret
-
- NdRead endp
-
-
- InpStat proc near ; function 6 = Input Status
-
- xor ax,ax
- ret
-
- InpStat endp
-
-
- InpFlush proc near ; function 7 = Flush Input Buffers
-
- xor ax,ax
- ret
-
- InpFlush endp
-
-
- Write proc near ; function 8 = Write (Output)
-
- xor ax,ax
- ret
-
- Write endp
-
-
- WriteVfy proc near ; function 9 = Write with Verify
-
- xor ax,ax
- ret
-
- WriteVfy endp
-
-
- OutStat proc near ; function 10 = Output Status
-
- xor ax,ax
- ret
-
- OutStat endp
-
-
- OutFlush proc near ; function 11 = Flush Output Buffers
-
- xor ax,ax
- ret
-
- OutFlush endp
-
-
- IoctlWt proc near ; function 12 = I/O Control Write
-
- xor ax,ax
- ret
-
- IoctlWt endp
-
-
- DevOpen proc near ; function 13 = Device Open
-
- xor ax,ax
- ret
-
- DevOpen endp
-
-
- DevClose proc near ; function 14 = Device Close
-
- xor ax,ax
- ret
-
- DevClose endp
-
-
- RemMedia proc near ; function 15 = Removable Media
-
- xor ax,ax
- ret
-
- RemMedia endp
-
-
- OutBusy proc near ; function 16 = Output Until Busy
-
- xor ax,ax
- ret
-
- OutBusy endp
-
-
- GenIOCTL proc near ; function 19 = Generic IOCTL
-
- xor ax,ax
- ret
-
- GenIOCTL endp
-
-
- GetLogDev proc near ; function 23 = Get Logical Device
-
- xor ax,ax
- ret
-
- GetLogDev endp
-
-
- SetLogDev proc near ; function 24 = Set Logical Device
-
- xor ax,ax
- ret
-
- SetLogDev endp
-
-
- Error proc near ; bad command code in request header
-
- mov ax,8003h ; error bit + "Unknown Command" code
- ret
-
- Error endp
-
-
- Init proc near ; function 0 = initialize driver
-
- push es ; save address of request header
- push di
-
- mov ah,9 ; display driver sign-on message
- mov dx,offset Ident
- int 21h
-
- pop di ; restore request header address
- pop es
-
- ; set address of free memory
- ; above driver (break address)
- mov word ptr es:[di+14],offset Init
- mov word ptr es:[di+16],cs
-
- xor ax,ax ; return status
- ret
-
- Init endp
-
- Ident db cr,lf,lf
- db 'TEMPLATE Example Device Driver'
- db cr,lf,eom
-
- Intr endp
-
- _TEXT ends
-
- end
-
- \SAMPCODE\DOS_ENCY\15\TINYDISK.ASM
-
- name tinydisk
- title TINYDISK example block-device driver
-
- ; TINYDISK.ASM --- 64 KB RAMdisk
- ;
- ; Ray Duncan, July 1987
- ; Example of a simple installable block-device driver.
-
- _TEXT segment public 'CODE'
-
- assume cs:_TEXT,ds:_TEXT,es:_TEXT
-
- org 0
-
- MaxCmd equ 12 ; max driver command code
- ; (no MS-DOS 3.x functions)
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII linefeed
- blank equ 020h ; ASCII space code
- eom equ '$' ; end-of-message signal
-
- Secsize equ 512 ; bytes/sector, IBM-compatible media
-
- ; device-driver header
- Header dd -1 ; link to next driver in chain
- dw 0 ; device attribute word
- dw Strat ; "Strategy" routine entry point
- dw Intr ; "Interrupt" routine entry point
- db 1 ; number of units, this device
- db 7 dup (0) ; reserved area (block-device drivers)
-
- RHPtr dd ? ; segment:offset of request header
-
- Secseg dw ? ; segment base of sector storage
-
- Xfrsec dw 0 ; current sector for transfer
- Xfrcnt dw 0 ; sectors successfully transferred
- Xfrreq dw 0 ; number of sectors requested
- Xfraddr dd 0 ; working address for transfer
-
- Array dw BPB ; array of pointers to BPB
- ; for each supported unit
-
-
- Bootrec equ $
-
- jmp $ ; phony JMP at start of
- nop ; boot sector; this field
- ; must be 3 bytes
-
- db 'MS 2.0' ; OEM identity field
-
- ; BIOS Parameter Block (BPB)
- BPB dw Secsize ; 00H - bytes per sector
- db 1 ; 02H - sectors per cluster
- dw 1 ; 03H - reserved sectors
- db 1 ; 05H - number of FATs
- dw 32 ; 06H - root directory entries
- dw 128 ; 08H - sectors = 64 KB/secsize
- db 0f8h ; 0AH - media descriptor
- dw 1 ; 0BH - sectors per FAT
-
- Bootrec_len equ $-Bootrec
-
-
- Strat proc far ; RAMdisk strategy routine
-
- ; save address of request header
- mov word ptr cs:RHPtr,bx
- mov word ptr cs:[RHPtr+2],es
- ret ; back to MS-DOS kernel
-
- Strat endp
-
-
- Intr proc far ; RAMdisk interrupt routine
-
- push ax ; save general registers
- push bx
- push cx
- push dx
- push ds
- push es
- push di
- push si
- push bp
-
- mov ax,cs ; make local data addressable
- mov ds,ax
-
- les di,[RHPtr] ; ES:DI = request header
-
- mov bl,es:[di+2] ; get command code
- xor bh,bh
- cmp bx,MaxCmd ; make sure it's valid
- jle Intr1 ; jump, function code is ok
- mov ax,8003h ; set Error bit and
- jmp Intr3 ; "Unknown Command" error code
-
- Intr1: shl bx,1 ; form index to dispatch table and
- ; branch to command-code routine
- call word ptr [bx+Dispatch]
- ; should return AX = status
-
- les di,[RHPtr] ; restore ES:DI = request header
-
- Intr3: or ax,0100h ; merge Done bit into status and store
- mov es:[di+3],ax ; status into request header
-
- Intr4: pop bp ; restore general registers
- pop si
- pop di
- pop es
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- ret ; return to MS-DOS kernel
-
- Intr endp
-
-
- Dispatch: ; command-code dispatch table
- ; all command-code routines are
- ; entered with ES:DI pointing
- ; to request header and return
- ; the operation status in AX
- dw Init ; 0 = initialize driver
- dw MediaChk ; 1 = media check on block device
- dw BuildBPB ; 2 = build BIOS parameter block
- dw Dummy ; 3 = I/O control read
- dw Read ; 4 = read (input) from device
- dw Dummy ; 5 = nondestructive read
- dw Dummy ; 6 = return current input status
- dw Dummy ; 7 = flush device input buffers
- dw Write ; 8 = write (output) to device
- dw Write ; 9 = write with verify
- dw Dummy ; 10 = return current output status
- dw Dummy ; 11 = flush output buffers
- dw Dummy ; 12 = I/O control write
-
-
- MediaChk proc near ; command code 1 = Media Check
-
- ; return "not changed" code
- mov byte ptr es:[di+0eh],1
- xor ax,ax ; and success status
- ret
-
- MediaChk endp
-
-
- BuildBPB proc near ; command code 2 = Build BPB
-
- ; put BPB address in request header
- mov word ptr es:[di+12h],offset BPB
- mov word ptr es:[di+14h],cs
- xor ax,ax ; return success status
- ret
-
- BuildBPB endp
-
-
- Read proc near ; command code 4 = Read (Input)
-
- call Setup ; set up transfer variables
-
- Read1: mov ax,Xfrcnt ; done with all sectors yet?
- cmp ax,Xfrreq
- je Read2 ; jump if transfer completed
- mov ax,Xfrsec ; get next sector number
- call Mapsec ; and map it
- mov ax,es
- mov si,di
- les di,Xfraddr ; ES:DI = requester's buffer
- mov ds,ax ; DS:SI = RAMdisk address
- mov cx,Secsize ; transfer logical sector from
- cld ; RAMdisk to requestor
- rep movsb
- push cs ; restore local addressing
- pop ds
- inc Xfrsec ; advance sector number
- ; advance transfer address
- add word ptr Xfraddr,Secsize
- inc Xfrcnt ; count sectors transferred
- jmp Read1
-
- Read2: ; all sectors transferred
- xor ax,ax ; return success status
- les di,RHPtr ; put actual transfer count
- mov bx,Xfrcnt ; into request header
- mov es:[di+12h],bx
- ret
-
- Read endp
-
-
- Write proc near ; command code 8 = Write (Output)
- ; command code 9 = Write with Verify
-
- call Setup ; set up transfer variables
-
- Write1: mov ax,Xfrcnt ; done with all sectors yet?
- cmp ax,Xfrreq
- je Write2 ; jump if transfer completed
-
- mov ax,Xfrsec ; get next sector number
- call Mapsec ; and map it
- lds si,Xfraddr
- mov cx,Secsize ; transfer logical sector from
- cld ; requester to RAMdisk
- rep movsb
- push cs ; restore local addressing
- pop ds
- inc Xfrsec ; advance sector number
- ; advance transfer address
- add word ptr Xfraddr,Secsize
- inc Xfrcnt ; count sectors transferred
- jmp Write1
-
- Write2: ; all sectors transferred
- xor ax,ax ; return success status
- les di,RHPtr ; put actual transfer count
- mov bx,Xfrcnt ; into request header
- mov es:[di+12h],bx
- ret
-
- Write endp
-
-
- Dummy proc near ; called for unsupported functions
-
- xor ax,ax ; return success flag for all
- ret
-
- Dummy endp
-
-
- Mapsec proc near ; map sector number to memory address
- ; call with AX = logical sector no.
- ; return ES:DI = memory address
-
- mov di,Secsize/16 ; paragraphs per sector
- mul di ; * logical sector number
- add ax,Secseg ; + segment base of sector storage
- mov es,ax
- xor di,di ; now ES:DI points to sector
- ret
-
- Mapsec endp
-
-
- Setup proc near ; set up for read or write
- ; call ES:DI = request header
- ; extracts address, start, count
-
- push es ; save request header address
- push di
- mov ax,es:[di+14h] ; starting sector number
- mov Xfrsec,ax
- mov ax,es:[di+12h] ; sectors requested
- mov Xfrreq,ax
- les di,es:[di+0eh] ; requester's buffer address
- mov word ptr Xfraddr,di
- mov word ptr Xfraddr+2,es
- mov Xfrcnt,0 ; initialize sectors transferred count
- pop di ; restore request header address
- pop es
- ret
-
- Setup endp
-
-
- Init proc near ; command code 0 = Initialize driver
- ; on entry ES:DI = request header
-
- mov ax,cs ; calculate segment base for sector
- add ax,Driver_len ; storage and save it
- mov Secseg,ax
- add ax,1000h ; add 1000H paras (64 KB) and
- mov es:[di+10h],ax ; set address of free memory
- mov word ptr es:[di+0eh],0
-
- call Format ; format the RAMdisk
-
- call Signon ; display driver identification
-
- les di,cs:RHPtr ; restore ES:DI = request header
- ; set logical units = 1
- mov byte ptr es:[di+0dh],1
- ; set address of BPB array
- mov word ptr es:[di+12h],offset Array
- mov word ptr es:[di+14h],cs
-
- xor ax,ax ; return success status
- ret
-
- Init endp
-
-
- Format proc near ; format the RAMdisk area
-
- mov es,Secseg ; first zero out RAMdisk
- xor di,di
- mov cx,8000h ; 32 K words = 64 KB
- xor ax,ax
- cld
- rep stosw
-
- mov ax,0 ; get address of logical
- call Mapsec ; sector zero
- mov si,offset Bootrec
- mov cx,Bootrec_len
- rep movsb ; and copy boot record to it
-
- mov ax,word ptr BPB+3
- call Mapsec ; get address of 1st FAT sector
- mov al,byte ptr BPB+0ah
- mov es:[di],al ; put media ID byte into it
- mov word ptr es:[di+1],-1
-
- mov ax,word ptr BPB+3
- add ax,word ptr BPB+0bh
- call Mapsec ; get address of 1st directory sector
- mov si,offset Volname
- mov cx,Volname_len
- rep movsb ; copy volume label to it
-
- ret ; done with formatting
-
- Format endp
-
-
- Signon proc near ; driver identification message
-
- les di,RHPtr ; let ES:DI = request header
- mov al,es:[di+22] ; get drive code from header,
- add al,'A' ; convert it to ASCII, and
- mov drive,al ; store into sign-on message
-
- mov ah,30h ; get MS-DOS version
- int 21h
- cmp al,2
- ja Signon1 ; jump if version 3.0 or later
- mov Ident1,eom ; version 2.x, don't print drive
-
- Signon1: ; print sign-on message
- mov ah,09H ; Function 09H = print string
- mov dx,offset Ident ; DS:DX = address of message
- int 21h ; transfer to MS-DOS
-
- ret ; back to caller
-
- Signon endp
-
-
- Ident db cr,lf,lf ; driver sign-on message
- db 'TINYDISK 64 KB RAMdisk'
- db cr,lf
- Ident1 db 'RAMdisk will be drive '
- Drive db 'X:'
- db cr,lf,eom
-
-
- Volname db 'DOSREF_DISK' ; volume label for RAMdisk
- db 08h ; attribute byte
- db 10 dup (0) ; reserved area
- dw 0 ; time = 00:00
- dw 0f01h ; date = August 1, 1987
- db 6 dup (0) ; reserved area
-
- Volname_len equ $-volname
-
- Driver_len dw (($-header)/16)+1 ; driver size in paragraphs
-
- _TEXT ends
-
- end
-
- \SAMPCODE\DOS_ENCY\17
- \SAMPCODE\DOS_ENCY\17\SAMPLE.C
-
- /* SAMPLE.C -- Demonstration Windows Program */
-
- #include <windows.h>
- #include "sample.h"
-
- long FAR PASCAL WndProc (HWND, unsigned, WORD, LONG) ;
-
- int PASCAL WinMain (hInstance, hPrevInstance, lpszCmdLine, nCmdShow)
- HANDLE hInstance, hPrevInstance ;
- LPSTR lpszCmdLine ;
- int nCmdShow ;
- {
- WNDCLASS wndclass ;
- HWND hWnd ;
- MSG msg ;
- static char szAppName [] = "Sample" ;
-
- /*---------------------------*/
- /* Register the Window Class */
- /*---------------------------*/
-
- if (!hPrevInstance)
- {
- wndclass.style = CS_HREDRAW | CS_VREDRAW ;
- wndclass.lpfnWndProc = WndProc ;
- wndclass.cbClsExtra = 0 ;
- wndclass.cbWndExtra = 0 ;
- wndclass.hInstance = hInstance ;
- wndclass.hIcon = NULL ;
- wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
- wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;
- wndclass.lpszMenuName = szAppName ;
- wndclass.lpszClassName = szAppName ;
-
- RegisterClass (&wndclass) ;
- }
-
- /*----------------------------------*/
- /* Create the window and display it */
- /*----------------------------------*/
-
- hWnd = CreateWindow (szAppName, "Demonstration Windows Program",
- WS_OVERLAPPEDWINDOW,
- (int) CW_USEDEFAULT, 0,
- (int) CW_USEDEFAULT, 0,
- NULL, NULL, hInstance, NULL) ;
-
- ShowWindow (hWnd, nCmdShow) ;
- UpdateWindow (hWnd) ;
-
- /*----------------------------------------------*/
- /* Stay in message loop until a WM_QUIT message */
- /*----------------------------------------------*/
-
- while (GetMessage (&msg, NULL, 0, 0))
- {
- TranslateMessage (&msg) ;
- DispatchMessage (&msg) ;
- }
- return msg.wParam ;
- }
-
- long FAR PASCAL WndProc (hWnd, iMessage, wParam, lParam)
- HWND hWnd ;
- unsigned iMessage ;
- WORD wParam ;
- LONG lParam ;
- {
- PAINTSTRUCT ps ;
- HFONT hFont ;
- HMENU hMenu ;
- static short xClient, yClient, nCurrentFont = IDM_SCRIPT ;
- static BYTE cFamily [] = { FF_SCRIPT, FF_MODERN, FF_ROMAN } ;
- static char *szFace [] = { "Script", "Modern", "Roman" } ;
-
- switch (iMessage)
- {
-
- /*---------------------------------------------*/
- /* WM_COMMAND message: Change checkmarked font */
- /*---------------------------------------------*/
-
- case WM_COMMAND:
- hMenu = GetMenu (hWnd) ;
- CheckMenuItem (hMenu, nCurrentFont, MF_UNCHECKED) ;
- nCurrentFont = wParam ;
- CheckMenuItem (hMenu, nCurrentFont, MF_CHECKED) ;
- InvalidateRect (hWnd, NULL, TRUE) ;
- break ;
-
- /*--------------------------------------------*/
- /* WM_SIZE message: Save dimensions of window */
- /*--------------------------------------------*/
-
- case WM_SIZE:
- xClient = LOWORD (lParam) ;
- yClient = HIWORD (lParam) ;
- break ;
-
- /*-----------------------------------------------*/
- /* WM_PAINT message: Display "Windows" in Script */
- /*-----------------------------------------------*/
-
- case WM_PAINT:
- BeginPaint (hWnd, &ps) ;
-
- hFont = CreateFont (yClient, xClient / 8,
- 0, 0, 400, 0, 0, 0, OEM_CHARSET,
- OUT_STROKE_PRECIS, OUT_STROKE_PRECIS,
- DRAFT_QUALITY, (BYTE) VARIABLE_PITCH |
- cFamily [nCurrentFont - IDM_SCRIPT],
- szFace [nCurrentFont - IDM_SCRIPT]) ;
-
- hFont = SelectObject (ps.hdc, hFont) ;
- TextOut (ps.hdc, 0, 0, "Windows", 7) ;
-
- DeleteObject (SelectObject (ps.hdc, hFont)) ;
- EndPaint (hWnd, &ps) ;
- break ;
-
- /*---------------------------------------*/
- /* WM_DESTROY message: Post Quit message */
- /*---------------------------------------*/
-
- case WM_DESTROY:
- PostQuitMessage (0) ;
- break ;
-
- /*---------------------------------------*/
- /* Other messages: Do default processing */
- /*---------------------------------------*/
-
- default:
- return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
- }
- return 0L ;
- }
-
- \SAMPCODE\DOS_ENCY\17\SAMPLE.H
-
- #define IDM_SCRIPT 1
- #define IDM_MODERN 2
- #define IDM_ROMAN 3
-
- \SAMPCODE\DOS_ENCY\17\SAMPLE.RC
-
- #include "sample.h"
-
- Sample MENU
- BEGIN
- POPUP "&Typeface"
- BEGIN
- MENUITEM "&Script", IDM_SCRIPT, CHECKED
- MENUITEM "&Modern", IDM_MODERN
- MENUITEM "&Roman", IDM_ROMAN
- END
- END
-
- \SAMPCODE\DOS_ENCY\17\SAMPLE.DEF
-
- NAME SAMPLE
- DESCRIPTION 'Demonstration Windows Program'
- STUB 'WINSTUB.EXE'
- CODE MOVABLE
- DATA MOVABLE MULTIPLE
- HEAPSIZE 1024
- STACKSIZE 4096
- EXPORTS WndProc
-
- \SAMPCODE\DOS_ENCY\17\SAMPLE.MAK
-
- sample.obj : sample.c sample.h
- cl -c -Gsw -W2 -Zdp sample.c
-
- sample.res : sample.rc sample.h
- rc -r sample.rc
-
- sample.exe : sample.obj sample.def sample.res
- link4 sample, /align:16, /map /line, slibw, sample
- rc sample.res
- mapsym sample
-
- \SAMPCODE\DOS_ENCY\18
- \SAMPCODE\DOS_ENCY\18\ASCTBL1.C
-
- /*************************************************************************
- * *
- * ASCTBL.C *
- * This program generates an ASCII lookup table for all displayable *
- * ASCII and extended IBM PC codes, leaving blanks for nondisplayable *
- * codes. *
- * *
- ************************************************************************/
-
- #include <ctype.h>
- #include <stdio.h>
-
- main()
- {
- int i, j, k;
- /* Print table title. */
- printf("\n\n\n ASCII LOOKUP TABLE\n\n");
-
- /* Print column headers. */
- printf(" ");
- for (i = 0; i < 16; i++)
- printf("%X ", i);
- fputchar("\n");
-
- /* Print each line of the table. */
- for ( i = 0, k = 0; i < 16; i++)
- {
- /* Print first hex digit of symbols on this line. */
- printf("%X ", i);
- /* Print each of the 16 symbols for this line. */
- for (j = 0; j < 16; j++)
- {
- /* Filter nonprintable characters. */
- if ((k >= 7 && k <= 13) || (k >= 28 && k <= 31))
- printf(" ");
- else
- printf("%c ", k);
- k++;
- }
- fputchar("\n");
- }
- }
-
- \SAMPCODE\DOS_ENCY\18\ASCTBL2.C
-
- /*************************************************************************
- * *
- * ASCTBL.C *
- * This program generates an ASCII lookup table for all displayable *
- * ASCII and extended IBM PC codes, leaving blanks for nondisplayable *
- * codes. *
- * *
- ************************************************************************/
-
- #define LINT_ARGS
- #include <ctype.h>
- #include <stdio.h>
-
- main()
- {
- int i, j, k;
- /* Print table title. */
- printf("\n\n\n ASCII LOOKUP TABLE\n\n");
-
- /* Print column headers. */
- printf(" ");
- for (i = 0; i < 16; i++)
- printf("%X ", i);
- fputchar('\n');
-
- /* Print each line of the table. */
- for ( i = 0, k = 0; i < 16; i++)
- {
- /* Print first hex digit of symbols on this line. */
- printf("%X ", i);
- /* Print each of the 16 symbols for this line. */
- for (j = 0; j < 16; j++)
- {
- /* Filter nonprintable characters. */
- if ((k >= 7 && k <= 13) || (k >= 28 && k <= 31))
- printf(" ");
- else
- printf("%c ", k);
- k++;
- }
- fputchar('\n');
- }
- }
-
- \SAMPCODE\DOS_ENCY\18\COMMSCMD.C
-
- /***********************************************************************
- * *
- * COMMSCMD *
- * *
- * This routine controls the COMMSCOP program that has been in- *
- * stalled as a resident routine. The operation performed is de- *
- * termined by the command line. The COMMSCMD program is invoked *
- * as follows: *
- * *
- * COMMSCMD [[cmd][ port]] *
- * *
- * where cmd is the command to be executed *
- * STOP -- stop trace *
- * START -- flush trace buffer and start trace *
- * RESUME -- resume a stopped trace *
- * port is the COMM port to be traced (1=COM1, 2=COM2, etc.) *
- * *
- * If cmd is omitted, STOP is assumed. If port is omitted, 1 is *
- * assumed. *
- * *
- ***********************************************************************/
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <dos.h>
- #define COMMCMD 0x60
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int cmd, port, result;
- static char commands[3] [10] = {"STOPPED", "STARTED", "RESUMED"};
- union REGS inregs, outregs;
-
- cmd = 0;
- port = 0;
-
- if (argc > 1)
- {
- if (0 == stricmp(argv[1], "STOP"))
- cmd = 0;
- else if (0 == stricmp(argv[1], "START"))
- cmd = 1;
- else if (0 == stricmp(argv[1], "RESUME"))
- cmd = 2;
- }
-
- if (argc == 3)
- {
- port = atoi(argv[2]);
- if (port > 0)
- port = port - 1;
- }
-
- inregs.h.ah = cmd;
- inregs.x.dx = port;
- result = int86(COMMCMD, &inregs, &outregs);
-
-
- printf("\nCommunications tracing %s for port COM%1d:\n",
- commands[cmd], port + 1);
- }
-
- \SAMPCODE\DOS_ENCY\18\UPERCAS1.C
-
- /************************************************************************
- * *
- * UPPERCAS.C *
- * This routine converts a fixed string to uppercase and prints it. *
- * *
- ************************************************************************/
-
- #include <ctype.h>
- #include <string.h>
- #include <stdio.h>
-
- main(argc,argv)
-
- int argc;
- char *argv[];
-
- {
- char *cp,c;
-
- cp = "a string\n";
-
- /* Convert *cp to uppercase and write to standard output */
-
- while (*cp != '\0')
- {
- c = toupper(*cp++);
- putchar(c);
- }
-
- }
-
- \SAMPCODE\DOS_ENCY\18\UPERCAS2.C
-
- /************************************************************************
- * *
- * UPPERCAS.C *
- * This routine converts a fixed string to uppercase and prints it. *
- * *
- ***********************************************************************/
-
- #include <ctype.h>
- #undef toupper
- #undef tolower
- #include <string.h>
- #include <stdio.h>
-
- main(argc,argv)
-
- int argc;
- char *argv[];
-
- {
- char *cp,c;
-
- cp = "a string\n";
-
- /* Convert *cp to uppercase and write to standard output */
-
- while (*cp != '\0')
- {
- c = toupper(*cp++);
- putchar(c);
- }
-
- }
-
- \SAMPCODE\DOS_ENCY\18\BADSCOP.ASM
-
- TITLE BADSCOP -- BAD VERSION OF COMMUNICATIONS TRACE UTILITY
- ; ***********************************************************************
- ; * *
- ; * BADSCOP -- *
- ; * THIS PROGRAM MONITORS THE ACTIVITY ON A SPECIFIED COMM PORT *
- ; * AND PLACES A COPY OF ALL COMM ACTIVITY IN A RAM BUFFER. EACH *
- ; * ENTRY IN THE BUFFER IS TAGGED TO INDICATE WHETHER THE BYTE *
- ; * WAS SENT BY OR RECEIVED BY THE SYSTEM. *
- ; * *
- ; * BADSCOP IS INSTALLED BY ENTERING *
- ; * *
- ; * BADSCOP *
- ; * *
- ; * THIS WILL INSTALL BADSCOP AND SET UP A 64K BUFFER TO BE USED *
- ; * FOR DATA LOGGING. REMEMBER THAT 2 BYTES ARE REQUIRED FOR *
- ; * EACH COMM BYTE, SO THE BUFFER IS ONLY 32K EVENTS LONG, OR ABOUT *
- ; * 30 SECONDS OF CONTINUOUS 9600 BAUD DATA. IN THE REAL WORLD, *
- ; * ASYNC DATA IS RARELY CONTINUOUS, SO THE BUFFER WILL PROBABLY *
- ; * HOLD MORE THAN 30 SECONDS WORTH OF DATA. *
- ; * *
- ; * WHEN INSTALLED, BADSCOP INTERCEPTS ALL INT 14H CALLS. IF THE *
- ; * PROGRAM HAS BEEN ACTIVATED AND THE INT IS EITHER SEND OR RE- *
- ; * CEIVE DATA, A COPY OF THE DATA BYTE, PROPERLY TAGGED, IS PLACED *
- ; * IN THE BUFFER. IN ANY CASE, DATA IS PASSED ON TO THE REAL *
- ; * INT 14H HANDLER. *
- ; * *
- ; * BADSCOP IS INVOKED BY ISSUING AN INT 60H CALL. THE INT HAS *
- ; * THE FOLLOWING CALLING SEQUENCE: *
- ; * *
- ; * AH -- COMMAND *
- ; * 0 -- STOP TRACING, PLACE STOP MARK IN BUFFER *
- ; * 1 -- FLUSH BUFFER AND START TRACE *
- ; * 2 -- RESUME TRACE *
- ; * 3 -- RETURN COMM BUFFER ADDRESSES *
- ; * DX -- COMM PORT (ONLY USED WITH AH = 1 or 2) *
- ; * 0 -- COM1 *
- ; * 1 -- COM2 *
- ; * *
- ; * THE FOLLOWING DATA IS RETURNED IN REPONSE TO AH = 3: *
- ; * *
- ; * CX -- BUFFER COUNT IN BYTES *
- ; * DX -- SEGMENT ADDRESS OF THE START OF THE BUFFER *
- ; * BX -- OFFSET ADDRESS OF THE START OF THE BUFFER *
- ; * *
- ; * THE COMM BUFFER IS FILLED WITH 2-BYTE DATA ENTRIES OF THE *
- ; * FOLLOWING FORM: *
- ; * *
- ; * BYTE 0 -- CONTROL *
- ; * BIT 0 -- ON FOR RECEIVED DATA, OFF FOR TRANS. *
- ; * BIT 7 -- STOP MARK -- INDICATES COLLECTION WAS *
- ; * INTERRUPTED AND RESUMED. *
- ; * BYTE 1 -- 8-BIT DATA *
- ; * *
- ; ***********************************************************************
-
- PUBLIC INITIALIZE,CONTROL,VECTOR_INIT,COMMSCOPE
- PUBLIC OLD_COMM_INT,COUNT,STATUS,PORT,BUFPNTR
-
- CSEG SEGMENT
- ASSUME CS:CSEG,DS:CSEG
- ORG 100H ;TO MAKE A COM FILE
-
- INITIALIZE:
- JMP VECTOR_INIT ;JUMP TO THE INITIALIZATION
- ; ROUTINE WHICH, TO SAVE SPACE,
- ; IS IN THE COMM BUFFER
-
- ;
- ; SYSTEM VARIABLES
- ;
- OLD_COMM_INT DD ? ;ADDRESS OF REAL COMM INT
- COUNT DW 0 ;BUFFER COUNT
- COMMSCOPE_INT EQU 60H ;COMMSCOPE CONTROL INT
- STATUS DB 0 ;PROCESSING STATUS
- ; 0 -- OFF
- ; 1 -- ON
- PORT DB 0 ;COMM PORT BEING TRACED
- BUFPNTR DW VECTOR_INIT ;NEXT BUFFER LOCATION
-
- SUBTTL DATA INTERRUPT HANDLER
- PAGE
- ; ***********************************************************************
- ; * *
- ; * COMMSCOPE *
- ; * THIS PROCEDURE INTERCEPTS ALL INT 14H CALLS AND LOGS THE DATA *
- ; * IF APPROPRIATE. *
- ; * *
- ; ***********************************************************************
- COMMSCOPE PROC NEAR
-
- TEST CS:STATUS,1 ;ARE WE ON?
- JZ OLD_JUMP ; NO, SIMPLY JUMP TO OLD HANDLER
-
- CMP AH,00H ;SKIP SETUP CALLS
- JE OLD_JUMP ; .
-
- CMP AH,03H ;SKIP STATUS REQUESTS
- JAE OLD_JUMP ; .
-
- CMP AH,02H ;IS THIS A READ REQUEST?
- JE GET_READ ; YES, GO PROCESS
-
- ;
- ; DATA WRITE REQUEST -- SAVE IF APPROPRIATE
- ;
- CMP DL,CS:PORT ;IS WRITE FOR PORT BEING TRACED?
- JNE OLD_JUMP ; NO, JUST PASS IT THROUGH
-
- PUSH DS ;SAVE CALLER'S REGISTERS
- PUSH BX ; .
- PUSH CS ;SET UP DS FOR OUR PROGRAM
- POP DS ; .
- MOV BX,BUFPNTR ;GET ADDRESS OF NEXT BUFFER LOCATION
- MOV [BX],BYTE PTR 0 ;MARK AS TRANSMITTED BYTE
- MOV [BX+1],AL ;SAVE DATA IN BUFFER
- INC COUNT ;INCREMENT BUFFER BYTE COUNT
- INC COUNT ; .
- INC BX ;POINT TO NEXT LOCATION
- INC BX ; .
- MOV BUFPNTR,BX ;SAVE NEW POINTER
- JNZ WRITE_DONE ;ZERO INDICATES BUFFER HAS WRAPPED
-
- MOV STATUS,0 ;TURN COLLECTION OFF -- BUFFER FULL
- WRITE_DONE:
- POP BX ;RESTORE CALLER'S REGISTERS
- POP DS ; .
- JMP OLD_JUMP ;PASS REQUEST ON TO BIOS ROUTINE
- ;
- ; PROCESS A READ DATA REQUEST AND WRITE TO BUFFER IF APPROPRIATE
- ;
- GET_READ:
- CMP DL,CS:PORT ;IS READ FOR PORT BEING TRACED?
- JNE OLD_JUMP ; NO, JUST PASS IT THROUGH
-
- PUSH DS ;SAVE CALLER'S REGISTERS
- PUSH BX ; .
- PUSH CS ;SET UP DS FOR OUR PROGRAM
- POP DS ; .
-
- PUSHF ;FAKE INT 14H CALL
- CLI ; .
- CALL OLD_COMM_INT ;PASS REQUEST ON TO BIOS
- TEST AH,80H ;VALID READ?
- JNZ READ_DONE ; NO, SKIP BUFFER UPDATE
-
- MOV BX,BUFPNTR ;GET ADDRESS OF NEXT BUFFER LOCATION
- MOV [BX],BYTE PTR 1 ;MARK AS RECEIVED BYTE
- MOV [BX+1],AL ;SAVE DATA IN BUFFER
- INC COUNT ;INCREMENT BUFFER BYTE COUNT
- INC COUNT ; .
- INC BX ;POINT TO NEXT LOCATION
- INC BX ; .
- MOV BUFPNTR,BX ;SAVE NEW POINTER
- JNZ READ_DONE ;ZERO INDICATES BUFFER HAS WRAPPED
-
- MOV STATUS,0 ;TURN COLLECTION OFF -- BUFFER FULL
- READ_DONE:
- POP BX ;RESTORE CALLER'S REGISTERS
- POP DS ; .
- IRET
-
- ;
- ; JUMP TO COMM BIOS ROUTINE
- ;
- OLD_JUMP:
- JMP OLD_COMM_INT
-
- COMMSCOPE ENDP
-
- SUBTTL CONTROL INTERRUPT HANDLER
- PAGE
- ; ***********************************************************************
- ; * *
- ; * CONTROL *
- ; * THIS ROUTINE PROCESSES CONTROL REQUESTS. *
- ; * *
- ; ***********************************************************************
-
- CONTROL PROC NEAR
- CMP AH,00H ;STOP REQUEST?
- JNE CNTL_START ; NO, CHECK START
- PUSH DS ;SAVE REGISTERS
- PUSH BX ; .
- PUSH CS ;SET DS FOR OUR ROUTINE
- POP DS
- MOV STATUS,0 ;TURN PROCESSING OFF
- MOV BX,BUFPNTR ;PLACE STOP MARK IN BUFFER
- MOV [BX],BYTE PTR 80H ; .
- MOV [BX+1],BYTE PTR 0FFH ; .
- INC COUNT ;INCREMENT COUNT
- INC COUNT ; .
- POP BX ;RESTORE REGISTERS
- POP DS ; .
- JMP CONTROL_DONE
-
- CNTL_START:
- CMP AH,01H ;START REQUEST?
- JNE CNTL_RESUME ; NO, CHECK RESUME
- MOV CS:PORT,DL ;SAVE PORT TO TRACE
- MOV CS:BUFPNTR,OFFSET VECTOR_INIT ;RESET BUFFER TO START
- MOV CS:COUNT,0 ;ZERO COUNT
- MOV CS:STATUS,1 ;START LOGGING
- JMP CONTROL_DONE
-
- CNTL_RESUME:
- CMP AH,02H ;RESUME REQUEST?
- JNE CNTL_STATUS ; NO, CHECK STATUS
- CMP CS:BUFPNTR,0 ;END OF BUFFER CONDITION?
- JE CONTROL_DONE ; YES, DO NOTHING
- MOV CS:PORT,DL ;SAVE PORT TO TRACE
- MOV CS:STATUS,1 ;START LOGGING
- JMP CONTROL_DONE
-
- CNTL_STATUS:
- CMP AH,03H ;RETURN STATUS REQUEST?
- JNE CONTROL_DONE ; NO, ERROR -- DO NOTHING
- MOV CX,CS:COUNT ;RETURN COUNT
- PUSH CS ;RETURN SEGMENT ADDR OF BUFFER
- POP DX ; .
- MOV BX,OFFSET VECTOR_INIT ;RETURN OFFSET ADDR OF BUFFER
-
- CONTROL_DONE:
- IRET
-
- CONTROL ENDP
-
-
- SUBTTL INITIALIZE INTERRUPT VECTORS
- PAGE
- ; ***********************************************************************
- ; * *
- ; * VECTOR_INIT *
- ; * THIS PROCEDURE INITIALIZES THE INTERRUPT VECTORS AND THEN *
- ; * EXITS VIA THE MS-DOS TERMINATE-AND-STAY-RESIDENT FUNCTION. *
- ; * A BUFFER OF 64K IS RETAINED. THE FIRST AVAILABLE BYTE *
- ; * IN THE BUFFER IS THE OFFSET OF VECTOR_INIT. *
- ; * *
- ; ***********************************************************************
-
- EVEN ;ASSURE BUFFER ON EVEN BOUNDARY
- VECTOR_INIT PROC NEAR
- ;
- ; GET ADDRESS OF COMM VECTOR (INT 14H)
- ;
- MOV AH,35H
- MOV AL,14H
- INT 21H
- ;
- ; SAVE OLD COMM INT ADDRESS
- ;
- MOV WORD PTR OLD_COMM_INT,BX
- MOV AX,ES
- MOV WORD PTR OLD_COMM_INT[2],AX
- ;
- ; SET UP COMM INT TO POINT TO OUR ROUTINE
- ;
- MOV DX,OFFSET COMMSCOPE
- MOV AH,25H
- MOV AL,14H
- INT 21H
- ;
- ; INSTALL CONTROL ROUTINE INT
- ;
- MOV DX,OFFSET CONTROL
- MOV AH,25H
- MOV AL,COMMSCOPE_INT
- INT 21H
- ;
- ; SET LENGTH TO 64K, EXIT AND STAY RESIDENT
- ;
- MOV AX,3100H ;TERM AND STAY RES COMMAND
- MOV DX,1000H ;64K RESERVED
- INT 21H ;DONE
- VECTOR_INIT ENDP
-
- CSEG ENDS
- END INITIALIZE
-
- \SAMPCODE\DOS_ENCY\18\COMMSCOP.ASM
-
- TITLE COMMSCOP -- COMMUNICATIONS TRACE UTILITY
- ; ***********************************************************************
- ; * *
- ; * COMMSCOPE -- *
- ; * THIS PROGRAM MONITORS THE ACTIVITY ON A SPECIFIED COMM PORT *
- ; * AND PLACES A COPY OF ALL COMM ACTIVITY IN A RAM BUFFER. EACH *
- ; * ENTRY IN THE BUFFER IS TAGGED TO INDICATE WHETHER THE BYTE *
- ; * WAS SENT BY OR RECEIVED BY THE SYSTEM. *
- ; * *
- ; * COMMSCOPE IS INSTALLED BY ENTERING *
- ; * *
- ; * COMMSCOP *
- ; * *
- ; * THIS WILL INSTALL COMMSCOP AND SET UP A 64K BUFFER TO BE USED *
- ; * FOR DATA LOGGING. REMEMBER THAT 2 BYTES ARE REQUIRED FOR *
- ; * EACH COMM BYTE, SO THE BUFFER IS ONLY 32K EVENTS LONG, OR ABOUT *
- ; * 30 SECONDS OF CONTINUOUS 9600 BAUD DATA. IN THE REAL WORLD, *
- ; * ASYNC DATA IS RARELY CONTINUOUS, SO THE BUFFER WILL PROBABLY *
- ; * HOLD MORE THAN 30 SECONDS WORTH OF DATA. *
- ; * *
- ; * WHEN INSTALLED, COMMSCOP INTERCEPTS ALL INT 14H CALLS. IF THE *
- ; * PROGRAM HAS BEEN ACTIVATED AND THE INT IS EITHER SEND OR RE- *
- ; * CEIVE DATA, A COPY OF THE DATA BYTE, PROPERLY TAGGED, IS PLACED *
- ; * IN THE BUFFER. IN ANY CASE, DATA IS PASSED ON TO THE REAL *
- ; * INT 14H HANDLER. *
- ; * *
- ; * COMMSCOP IS INVOKED BY ISSUING AN INT 60H CALL. THE INT HAS *
- ; * THE FOLLOWING CALLING SEQUENCE: *
- ; * *
- ; * AH -- COMMAND *
- ; * 0 -- STOP TRACING, PLACE STOP MARK IN BUFFER *
- ; * 1 -- FLUSH BUFFER AND START TRACE *
- ; * 2 -- RESUME TRACE *
- ; * 3 -- RETURN COMM BUFFER ADDRESSES *
- ; * DX -- COMM PORT (ONLY USED WITH AH = 1 or 2) *
- ; * 0 -- COM1 *
- ; * 1 -- COM2 *
- ; * *
- ; * THE FOLLOWING DATA IS RETURNED IN RESPONSE TO AH = 3: *
- ; * *
- ; * CX -- BUFFER COUNT IN BYTES *
- ; * DX -- SEGMENT ADDRESS OF THE START OF THE BUFFER *
- ; * BX -- OFFSET ADDRESS OF THE START OF THE BUFFER *
- ; * *
- ; * THE COMM BUFFER IS FILLED WITH 2-BYTE DATA ENTRIES OF THE *
- ; * FOLLOWING FORM: *
- ; * *
- ; * BYTE 0 -- CONTROL *
- ; * BIT 0 -- ON FOR RECEIVED DATA, OFF FOR TRANS. *
- ; * BIT 7 -- STOP MARK -- INDICATES COLLECTION WAS *
- ; * INTERRUPTED AND RESUMED. *
- ; * BYTE 1 -- 8-BIT DATA *
- ; * *
- ; ***********************************************************************
-
- CSEG SEGMENT
- ASSUME CS:CSEG,DS:CSEG
- ORG 100H ;TO MAKE A COMM FILE
-
- INITIALIZE:
- JMP VECTOR_INIT ;JUMP TO THE INITIALIZATION
- ; ROUTINE WHICH, TO SAVE SPACE,
- ; IS IN THE COMM BUFFER
-
- ;
- ; SYSTEM VARIABLES
- ;
- OLD_COMM_INT DD ? ;ADDRESS OF REAL COMM INT
- COUNT DW 0 ;BUFFER COUNT
- COMMSCOPE_INT EQU 60H ;COMMSCOPE CONTROL INT
- STATUS DB 0 ;PROCESSING STATUS
- ; 0 -- OFF
- ; 1 -- ON
- PORT DB 0 ;COMM PORT BEING TRACED
- BUFPNTR DW VECTOR_INIT ;NEXT BUFFER LOCATION
-
- SUBTTL DATA INTERRUPT HANDLER
- PAGE
- ; ***********************************************************************
- ; * *
- ; * COMMSCOPE *
- ; * THIS PROCEDURE INTERCEPTS ALL INT 14H CALLS AND LOGS THE DATA *
- ; * IF APPROPRIATE. *
- ; * *
- ; ***********************************************************************
- COMMSCOPE PROC NEAR
-
- TEST CS:STATUS,1 ;ARE WE ON?
- JZ OLD_JUMP ; NO, SIMPLY JUMP TO OLD HANDLER
-
- CMP AH,00H ;SKIP SETUP CALLS
- JE OLD_JUMP ; .
-
- CMP AH,03H ;SKIP STATUS REQUESTS
- JAE OLD_JUMP ; .
-
- CMP AH,02H ;IS THIS A READ REQUEST?
- JE GET_READ ; YES, GO PROCESS
-
- ;
- ; DATA WRITE REQUEST -- SAVE IF APPROPRIATE
- ;
- CMP DL,CS:PORT ;IS WRITE FOR PORT BEING TRACED?
- JNE OLD_JUMP ; NO, JUST PASS IT THROUGH
-
- PUSH DS ;SAVE CALLER'S REGISTERS
- PUSH BX ; .
- PUSH CS ;SET UP DS FOR OUR PROGRAM
- POP DS ; .
- MOV BX,BUFPNTR ;GET ADDR OF NEXT BUFFER LOC
- MOV [BX],BYTE PTR 0 ;MARK AS TRANSMITTED BYTE
- MOV [BX+1],AL ;SAVE DATA IN BUFFER
- INC COUNT ;INCREMENT BUFFER BYTE COUNT
- INC COUNT ; .
- INC BX ;POINT TO NEXT LOCATION
- INC BX ; .
- MOV BUFPNTR,BX ;SAVE NEW POINTER
- JNZ WRITE_DONE ;ZERO MEANS BUFFER HAS WRAPPED
-
- MOV STATUS,0 ;TURN COLLECTION OFF
- WRITE_DONE:
- POP BX ;RESTORE CALLER'S REGISTERS
- POP DS ; .
- JMP OLD_JUMP ;PASS REQUEST ON TO BIOS ROUTINE
- ;
- ; PROCESS A READ DATA REQUEST AND WRITE TO BUFFER IF APPROPRIATE
- ;
- GET_READ:
- CMP DL,CS:PORT ;IS READ FOR PORT BEING TRACED?
- JNE OLD_JUMP ; NO, JUST PASS IT THROUGH
-
- PUSH DS ;SAVE CALLER'S REGISTERS
- PUSH BX ; .
- PUSH CS ;SET UP DS FOR OUR PROGRAM
- POP DS ; .
-
- PUSHF ;FAKE INT 14H CALL
- CLI ; .
- CALL OLD_COMM_INT ;PASS REQUEST ON TO BIOS
- TEST AH,80H ;VALID READ?
- JNZ READ_DONE ; NO, SKIP BUFFER UPDATE
-
- MOV BX,BUFPNTR ;GET ADDR OF NEXT BUFFER LOC
- MOV [BX],BYTE PTR 1 ;MARK AS RECEIVED BYTE
- MOV [BX+1],AL ;SAVE DATA IN BUFFER
- INC COUNT ;INCREMENT BUFFER BYTE COUNT
- INC COUNT ; .
- INC BX ;POINT TO NEXT LOCATION
- INC BX ; .
- MOV BUFPNTR,BX ;SAVE NEW POINTER
- JNZ READ_DONE ;ZERO MEANS BUFFER HAS WRAPPED
-
- MOV STATUS,0 ;TURN COLLECTION OFF
- READ_DONE:
- POP BX ;RESTORE CALLER'S REGISTERS
- POP DS ; .
- IRET
-
- ;
- ; JUMP TO COMM BIOS ROUTINE
- ;
- OLD_JUMP:
- JMP CS:OLD_COMM_INT
-
- COMMSCOPE ENDP
-
- SUBTTL CONTROL INTERRUPT HANDLER
- PAGE
- ; ***********************************************************************
- ; * *
- ; * CONTROL *
- ; * THIS ROUTINE PROCESSES CONTROL REQUESTS. *
- ; * *
- ; ***********************************************************************
-
- CONTROL PROC NEAR
- CMP AH,00H ;STOP REQUEST?
- JNE CNTL_START ; NO, CHECK START
- PUSH DS ;SAVE REGISTERS
- PUSH BX ; .
- PUSH CS ;SET DS FOR OUR ROUTINE
- POP DS
- MOV STATUS,0 ;TURN PROCESSING OFF
- MOV BX,BUFPNTR ;PLACE STOP MARK IN BUFFER
- MOV [BX],BYTE PTR 80H ; .
- MOV [BX+1],BYTE PTR 0FFH ; .
- INC BX ;INCREMENT BUFFER POINTER
- INC BX ; .
- MOV BUFPNTR,BX ; .
- INC COUNT ;INCREMENT COUNT
- INC COUNT ; .
- POP BX ;RESTORE REGISTERS
- POP DS ; .
- JMP CONTROL_DONE
-
- CNTL_START:
- CMP AH,01H ;START REQUEST?
- JNE CNTL_RESUME ; NO, CHECK RESUME
- MOV CS:PORT,DL ;SAVE PORT TO TRACE
- MOV CS:BUFPNTR,OFFSET VECTOR_INIT ;RESET BUFFER TO START
- MOV CS:COUNT,0 ;ZERO COUNT
- MOV CS:STATUS,1 ;START LOGGING
- JMP CONTROL_DONE
-
- CNTL_RESUME:
- CMP AH,02H ;RESUME REQUEST?
- JNE CNTL_STATUS ; NO, CHECK STATUS
- CMP CS:BUFPNTR,0 ;END OF BUFFER CONDITION?
- JE CONTROL_DONE ; YES, DO NOTHING
- MOV CS:PORT,DL ;SAVE PORT TO TRACE
- MOV CS:STATUS,1 ;START LOGGING
- JMP CONTROL_DONE
-
- CNTL_STATUS:
- CMP AH,03H ;RETURN STATUS REQUEST?
- JNE CONTROL_DONE ; NO, ERROR -- DO NOTHING
- MOV CX,CS:COUNT ;RETURN COUNT
- PUSH CS ;RETURN SEGMENT ADDR OF BUFFER
- POP DX ; .
- MOV BX,OFFSET VECTOR_INIT ;RETURN OFFSET ADDR OF BUFFER
-
- CONTROL_DONE:
- IRET
-
- CONTROL ENDP
-
-
- SUBTTL INITIALIZE INTERRUPT VECTORS
- PAGE
- ; ***********************************************************************
- ; * *
- ; * VECTOR_INIT *
- ; * THIS PROCEDURE INITIALIZES THE INTERRUPT VECTORS AND THEN *
- ; * EXITS VIA THE MS-DOS TERMINATE-AND-STAY-RESIDENT FUNCTION. *
- ; * A BUFFER OF 64K IS RETAINED. THE FIRST AVAILABLE BYTE *
- ; * IN THE BUFFER IS THE OFFSET OF VECTOR_INIT. *
- ; * *
- ; ***********************************************************************
-
- EVEN ;ASSURE BUFFER ON EVEN BOUNDARY
- VECTOR_INIT PROC NEAR
- ;
- ; GET ADDRESS OF COMM VECTOR (INT 14H)
- ;
- MOV AH,35H
- MOV AL,14H
- INT 21H
- ;
- ; SAVE OLD COMM INT ADDRESS
- ;
- MOV WORD PTR OLD_COMM_INT,BX
- MOV AX,ES
- MOV WORD PTR OLD_COMM_INT[2],AX
- ;
- ; SET UP COMM INT TO POINT TO OUR ROUTINE
- ;
- MOV DX,OFFSET COMMSCOPE
- MOV AH,25H
- MOV AL,14H
- INT 21H
- ;
- ; INSTALL CONTROL ROUTINE INT
- ;
- MOV DX,OFFSET CONTROL
- MOV AH,25H
- MOV AL,COMMSCOPE_INT
- INT 21H
- ;
- ; SET LENGTH TO 64K, EXIT AND STAY RESIDENT
- ;
- MOV AX,3100H ;TERM AND STAY RES COMMAND
- MOV DX,1000H ;64K RESERVED
- INT 21H ;DONE
- VECTOR_INIT ENDP
- CSEG ENDS
- END INITIALIZE
-
- \SAMPCODE\DOS_ENCY\18\TESTCOM1.ASM
-
- TITLE TESTCOMM -- TEST COMMSCOP ROUTINE
- ; ***********************************************************************
- ; * *
- ; * TESTCOMM *
- ; * THIS ROUTINE PROVIDES DATA FOR THE COMMSCOP ROUTINE. IT READS *
- ; * CHARACTERS FROM THE KEYBOARD AND WRITES THEM TO COM1 USING *
- ; * INT 14H. DATA IS ALSO READ FROM INT 14H AND DISPLAYED ON THE *
- ; * SCREEN. THE ROUTINE RETURNS TO MS-DOS WHEN Ctrl-C IS PRESSED *
- ; * ON THE KEYBOARD. *
- ; * *
- ; ***********************************************************************
-
- SSEG SEGMENT PARA STACK 'STACK'
- DW 128 DUP(?)
- SSEG ENDS
-
- CSEG SEGMENT
- ASSUME CS:CSEG,SS:SSEG
- BEGIN PROC FAR
- PUSH DS ;SET UP FOR RET TO MS-DOS
- XOR AX,AX ; .
- PUSH AX ; .
-
- MAINLOOP:
- MOV AH,6 ;USE MS-DOS CALL TO CHECK FOR
- MOV DL,0FFH ; KEYBOARD ACTIVITY
- INT 21 ; IF NO CHARACTER, JUMP TO
- JZ TESTCOMM ; COMM ACTIVITY TEST
-
- CMP AL,03 ;WAS CHARACTER A Ctrl-C?
- JNE SENDCOMM ; NO, SEND IT TO SERIAL PORT
- RET ; YES, RETURN TO MS-DOS
-
- SENDCOMM:
- MOV AH,01 ;USE INT 14H WRITE FUNCTION TO
- MOV DX,0 ; SEND DATA TO SERIAL PORT
- INT 14H ; .
-
- TESTCOMM:
- MOV AH,3 ;GET SERIAL PORT STATUS
- MOV DX,0 ; .
- INT 14H ; .
- AND AH,1 ;ANY DATA WAITING?
- JZ MAINLOOP ; NO, GO BACK TO KEYBOARD TEST
- MOV AH,2 ;READ SERIAL DATA
- MOV DX,0 ; .
- INT 14H ; .
- MOV AH,6 ;WRITE SERIAL DATA TO SCREEN
- INT 21H ; .
- JMP MAINLOOP ;CONTINUE
-
- BEGIN ENDP
- CSEG ENDS
- END BEGIN
-
- \SAMPCODE\DOS_ENCY\18\TESTCOM2.ASM
-
- TITLE TESTCOMM -- TEST COMMSCOP ROUTINE
- ; ***********************************************************************
- ; * *
- ; * TESTCOMM *
- ; * THIS ROUTINE PROVIDES DATA FOR THE COMMSCOP ROUTINE. IT READS *
- ; * CHARACTERS FROM THE KEYBOARD AND WRITES THEM TO COM1 USING *
- ; * INT 14H. DATA IS ALSO READ FROM INT 14H AND DISPLAYED ON THE *
- ; * SCREEN. THE ROUTINE RETURNS TO MS-DOS WHEN Ctrl-C IS PRESSED *
- ; * ON THE KEYBOARD. *
- ; * *
- ; ***********************************************************************
-
- SSEG SEGMENT PARA STACK 'STACK'
- DW 128 DUP(?)
- SSEG ENDS
-
- CSEG SEGMENT
- ASSUME CS:CSEG,SS:SSEG
- BEGIN PROC FAR
- PUSH DS ;SET UP FOR RET TO MS-DOS
- XOR AX,AX ; .
- PUSH AX ; .
-
- MAINLOOP:
- MOV AH,6 ;USE DOS CALL TO CHECK FOR
- MOV DL,0FFH ; KEYBOARD ACTIVITY
- INT 21H ; IF NO CHARACTER, JUMP TO
- JZ TESTCOMM ; COMM ACTIVITY TEST
-
- CMP AL,03 ;WAS CHARACTER A Ctrl-C?
- JNE SENDCOMM ; NO, SEND IT TO SERIAL PORT
- RET ; YES, RETURN TO MS-DOS
-
- SENDCOMM:
- MOV AH,01 ;USE INT 14H WRITE FUNCTION TO
- MOV DX,0 ; SEND DATA TO SERIAL PORT
- INT 14H ; .
-
- TESTCOMM:
- MOV AH,3 ;GET SERIAL PORT STATUS
- MOV DX,0 ; .
- INT 14H ; .
- AND AH,1 ;ANY DATA WAITING?
- JZ MAINLOOP ; NO, GO BACK TO KEYBOARD TEST
- MOV AH,2 ;READ SERIAL DATA
- MOV DX,0 ; .
- INT 14H ; .
- MOV AH,6 ;WRITE SERIAL DATA TO SCREEN
- MOV DL,AL ; .
- INT 21H ; .
- JMP MAINLOOP ;CONTINUE
-
- BEGIN ENDP
- CSEG ENDS
- END BEGIN
-
- \SAMPCODE\DOS_ENCY\18\COMMDUMP.BAS
-
- ' **********************************************************************
- ' * *
- ' * COMMDUMP *
- ' * *
- ' * This routine dumps the contents of the COMMSCOP trace buffer to *
- ' * the screen in a formatted manner. Received data is shown in *
- ' * reverse video. Where possible, the ASCII character for the byte *
- ' * is shown; otherwise a dot is shown. The value of the byte is *
- ' * displayed in hex below the character. Points where tracing was *
- ' * stopped are shown by a solid bar. *
- ' * *
- ' **********************************************************************
-
- '
- ' Establish system constants and variables
- '
- DEFINT A-Z
-
- DIM INREG(7), OUTREG(7) 'Define register arrays
-
- RAX = 0 'Establish values for 8086
- RBX = 1 ' registers
- RCX = 2 ' .
- RDX = 3 ' .
- RBP = 4 ' .
- RSI = 5 ' .
- RDI = 6 ' .
- RFL = 7 ' .
-
- '
- ' Interrogate COMMSCOP to obtain addresses and count of data in
- ' trace buffer
- '
- INREG(RAX) = &H0300 'Request address data and count
- CALL INT86(&H60, VARPTR(INREG(0)), VARPTR(OUTREG(0)))
-
- NUM = OUTREG(RCX) 'Number of bytes in buffer
- BUFSEG = OUTREG(RDX) 'Buffer segment address
- BUFOFF = OUTREG(RBX) 'Offset of buffer start
-
- IF NUM = 0 THEN END
-
- '
- ' Set screen up and display control data
- '
- CLS
- KEY OFF
- LOCATE 25, 1
- PRINT "NUM ="; NUM;"BUFSEG = "; HEX$(BUFSEG); " BUFOFF = ";
- PRINT HEX$(BUFOFF);
- LOCATE 4, 1
- PRINT STRING$(80,"-")
- DEF SEG = BUFSEG
-
- '
- ' Set up display control variables
- '
- DLINE = 1
- DCOL = 1
- DSHOWN = 0
-
- '
- ' Fetch and display each character in buffer
- '
- FOR I= BUFOFF TO BUFOFF+NUM-2 STEP 2
- STAT = PEEK(I)
- DAT = PEEK(I + 1)
-
- IF (STAT AND 1) = 0 THEN
- COLOR 7, 0
- ELSE
- COLOR 0, 7
- END IF
-
- RLINE = (DLINE-1) * 4 + 1
- IF (STAT AND &H80) = 0 THEN
- LOCATE RLINE, DCOL
- C$ = CHR$(DAT)
- IF DAT < 32 THEN C$ = "."
- PRINT C$;
- H$ = RIGHT$("00" + HEX$(DAT), 2)
- LOCATE RLINE + 1, DCOL
- PRINT LEFT$(H$, 1);
- LOCATE RLINE + 2, DCOL
- PRINT RIGHT$(H$, 1);
- ELSE
- LOCATE RLINE, DCOL
- PRINT CHR$(178);
- LOCATE RLINE + 1, DCOL
- PRINT CHR$(178);
- LOCATE RLINE + 2, DCOL
- PRINT CHR$(178);
- END IF
-
- DCOL = DCOL + 1
- IF DCOL > 80 THEN
- COLOR 7, 0
- DCOL = 1
- DLINE = DLINE + 1
- SHOWN = SHOWN + 1
- IF SHOWN = 6 THEN
- LOCATE 25, 50
- COLOR 0, 7
- PRINT "ENTER ANY KEY TO CONTINUE: ";
- WHILE LEN(INKEY$) = 0
- WEND
- COLOR 7, 0
- LOCATE 25, 50
- PRINT SPACE$(29);
- SHOWN = 0
- END IF
- IF DLINE > 6 THEN
- LOCATE 24, 1
- PRINT : PRINT : PRINT : PRINT
- LOCATE 24, 1
- PRINT STRING$(80, "-");
- DLINE = 6
- ELSE
- LOCATE DLINE * 4, 1
- PRINT STRING$(80, "-");
- END IF
- END IF
-
- NEXT I
-
- END
-
- \SAMPCODE\DOS_ENCY\18\COMMSCMD.BAS
-
- ' ************************************************************************
- ' * *
- ' * COMMSCMD *
- ' * *
- ' * This routine controls the COMMSCOP program that has been in- *
- ' * stalled as a resident routine. The operation performed is de- *
- ' * termined by the command line. The COMMSCMD program is invoked *
- ' * as follows: *
- ' * *
- ' * COMMSCMD [[cmd][,port]] *
- ' * *
- ' * where cmd is the command to be executed *
- ' * STOP -- stop trace *
- ' * START -- flush trace buffer and start trace *
- ' * RESUME -- resume a stopped trace *
- ' * port is the COMM port to be traced (1=COM1, 2=COM2, etc.) *
- ' * *
- ' * If cmd is omitted, STOP is assumed. If port is omitted, 1 is *
- ' * assumed. *
- ' * *
- ' ************************************************************************
-
- '
- ' Establish system constants and variables
- '
- DEFINT A-Z
-
- DIM INREG(7), OUTREG(7) 'Define register arrays
-
- RAX = 0 'Establish values for 8086
- RBX = 1 ' registers
- RCX = 2 ' .
- RDX = 3 ' .
- RBP = 4 ' .
- RSI = 5 ' .
- RDI = 6 ' .
- RFL = 7 ' .
-
- DIM TEXT$(2)
-
- TEXT$(0) = "STOPPED"
- TEXT$(1) = "STARTED"
- TEXT$(2) = "RESUMED"
-
- '
- ' Process command-line tail
- '
- C$ = COMMAND$ 'Get command-line data
-
- IF LEN(C$) = 0 THEN 'If no command line specified
- CMD = 0 'Set CMD to STOP
- PORT = 0 'Set PORT to COM1
- GOTO SENDCMD
- END IF
-
- COMMA = INSTR(C$, ", ") 'Extract operands
- IF COMMA = 0 THEN
- CMDTXT$ = C$
- PORT = 0
- ELSE
- CMDTXT$ = LEFT$(C$, COMMA - 1)
- PORT = VAL(MID$(C$, COMMA + 1)) - 1
- END IF
-
- IF PORT < 0 THEN PORT = 0
-
- IF CMDTXT$ = "STOP" THEN
- CMD = 0
- ELSEIF CMDTXT$ = "START" THEN
- CMD = 1
- ELSEIF CMDTXT$ = "RESUME" THEN
- CMD = 2
- ELSE
- CMD = 0
- END IF
-
- '
- ' Send command to COMMSCOP routine
- '
- SENDCMD:
- INREG(RAX) = 256 * CMD
- INREG(RDX) = PORT
- CALL INT86(&H60, VARPTR(INREG(0)), VARPTR(OUTREG(0)))
- '
- ' Notify user that action is complete
- '
- PRINT : PRINT
- PRINT "Communications tracing "; TEXT$(CMD);
- IF CMD <> 0 THEN
- PRINT " for port COM"; MID$(STR$(PORT + 1), 2); ":"
- ELSE
- PRINT
- END IF
-
- END
-
- \SAMPCODE\DOS_ENCY\18\EXP1.BAS
-
- ' EXP.BAS -- COMPUTE EXPONENTIAL WITH INFINITE SERIES
- '
- ' ***********************************************************************
- ' * *
- ' * EXP *
- ' * *
- ' * This routine computes EXP(x) using the following infinite series: *
- ' * *
- ' * x x^2 x^3 x^4 x^5 *
- ' * EXP(x) = 1 + --- + --- + --- + --- + --- + ... *
- ' * 1! 2! 3! 4! 5! *
- ' * *
- ' * *
- ' * The program requests a value for x and a value for the convergence *
- ' * criterion, C. The program will continue evaluating the terms of *
- ' * the series until the difference between two terms is less than C. *
- ' * *
- ' * The result of the calculation and the number of terms required to *
- ' * converge are printed. The program will repeat until an x of 0 is *
- ' * entered. *
- ' * *
- ' ***********************************************************************
-
- '
- ' Initialize program variables
- '
- INITIALIZE:
- TERMS = 1
- FACT = 1
- LAST = 1.E35
- DELTA = 1.E34
- EX = 1
- '
- ' Input user data
- '
- INPUT "Enter number: "; X
- IF X = 0 THEN END
- INPUT "Enter convergence criterion (.0001 for 4 places): "; C
-
- '
- ' Compute exponential until difference of last 2 terms is < C
- '
- WHILE ABS(LAST - DELTA) >= C
- LAST = DELTA
- FACT = FACT * TERMS
- DELTA = X^TERMS / FACT
- EX = EX + DELTA
- TERMS = TERMS + 1
- WEND
-
- '
- ' Display answer and number of terms required to converge
- '
- PRINT EX
- PRINT TERMS; "elements required to converge"
- PRINT
-
- GOTO INITIALIZE
-
- \SAMPCODE\DOS_ENCY\18\EXP2.BAS
-
- ' EXP.BAS -- COMPUTE EXPONENTIAL WITH INFINITE SERIES
- '
- ' ***********************************************************************
- ' * *
- ' * EXP *
- ' * *
- ' * This routine computes EXP(x) using the following infinite series: *
- ' * *
- ' * x x^2 x^3 x^4 x^5 *
- ' * EXP(x) = 1 + --- + --- + --- + --- + --- + ... *
- ' * 1! 2! 3! 4! 5! *
- ' * *
- ' * *
- ' * The program requests a value for x and a value for the convergence *
- ' * criterion, C. The program will continue evaluating the terms of *
- ' * the series until the amount added with a term is less than C. *
- ' * *
- ' * The result of the calculation and the number of terms required to *
- ' * converge are printed. The program will repeat until an x of 0 is *
- ' * entered. *
- ' * *
- ' ***********************************************************************
-
- '
- ' INITIALIZE program variables
- '
- Initialize:
- TERMS = 1
- FACT = 1
- DELTA = 1.E35
- EX = 1
- '
- ' Input user data
- '
- INPUT "Enter number: "; X
- IF X = 0 THEN END
- INPUT "Enter convergence criterion (.0001 for 4 places): "; C
-
- '
- ' Compute exponential until difference of last 2 terms is < C
- '
- WHILE DELTA > C
- FACT = FACT * TERMS
- DELTA = X^TERMS / FACT
- EX = EX + DELTA
- TERMS = TERMS + 1
- WEND
-
- '
- ' Display answer and number of terms required to converge
- '
- PRINT EX
- PRINT TERMS; "elements required to converge"
- PRINT
-
- GOTO INITIALIZE
-
- \SAMPCODE\DOS_ENCY\19
- \SAMPCODE\DOS_ENCY\19\HELLO.ASM
-
- NAME HELLO
-
- _TEXT SEGMENT byte public 'CODE'
-
- ASSUME cs:_TEXT,ds:_DATA
-
- start: ;program entry point
- mov ax,seg msg
- mov ds,ax
- mov dx,offset msg ;DS:DX -> msg
- mov ah,09h
- int 21h ;perform int 21H function 09H
- ;(Output character string)
- mov ax,4C00h
- int 21h ;perform int 21H function 4CH
- ;(Terminate with return code)
- _TEXT ENDS
-
-
- _DATA SEGMENT word public 'DATA'
-
- msg DB 'Hello, world',0Dh,0Ah,'$'
-
- _DATA ENDS
-
-
- _STACK SEGMENT stack 'STACK'
-
- DW 80h dup(?) ;stack depth = 128 words
-
- _STACK ENDS
-
- END start
-
- \SAMPCODE\DOS_ENCY\2
- \SAMPCODE\DOS_ENCY\2\SHELL.ASM
-
- ; SHELL.ASM A simple program to run an application as an
- ; MS-DOS shell program. The program name and
- ; startup parameters must be adjusted before
- ; SHELL is assembled.
- ;
- ; Written by William Wong
- ;
- ; To create SHELL.COM:
- ;
- ; C>MASM SHELL;
- ; C>LINK SHELL;
- ; C>EXE2BIN SHELL.EXE SHELL.COM
-
- stderr equ 2 ; standard error
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII linefeed
- cseg segment para public 'CODE'
- ;
- ; ---- Set up DS, ES, and SS:SP to run as .COM ----
- ;
- assume cs:cseg
- start proc far
- mov ax,cs ; set up segment registers
- add ax,10h ; AX = segment after PSP
- mov ds,ax
- mov ss,ax ; set up stack pointer
- mov sp,offset stk
- mov ax,offset shell
- push cs ; push original CS
- push ds ; push segment of shell
- push ax ; push offset of shell
- ret ; jump to shell
- start endp
- ;
- ; ---- Main program running as .COM ----
- ;
- ; CS, DS, SS = cseg
- ; Original CS value on top of stack
- ;
- assume cs:cseg,ds:cseg,ss:cseg
- seg_size equ (((offset last) - (offset start)) + 10fh)/16
- shell proc near
- pop es ; ES = segment to shrink
- mov bx,seg_size ; BX = new segment size
- mov ah,4ah ; AH = modify memory block
- int 21h ; free excess memory
- mov cmd_seg,ds ; setup segments in
- mov fcb1_seg,ds ; parameter block for EXEC
- mov fcb2_seg,ds
- mov dx,offset main_loop
- mov ax,2523h ; AX = set Control-C handler
- int 21h ; set handler to DS:DX
- mov dx,offset main_loop
- mov ax,2524h ; AX = set critical error handler
- int 21h ; set handler to DS:DX
- ; Note: DS is equal to CS
- main_loop:
- push ds ; save segment registers
- push es
- mov cs:stk_seg,ss ; save stack pointer
- mov cs:stk_off,sp
- mov dx,offset pgm_name
- mov bx,offset par_blk
- mov ax,4b00h ; AX = EXEC/run program
- int 21h ; carry = EXEC failed
- mov ss,cs:stk_seg ; restore stack pointer
- mov sp,cs:stk_off
- pop es ; restore segment registers
- pop ds
- jnc main_loop ; loop if program run
- mov dx,offset load_msg
- mov cx,load_msg_length
- call print ; display error message
- mov ah,08h ; AH = read without echo
- int 21h ; wait for any character
- jmp main_loop ; execute forever
- shell endp
- ;
- ; ---- Print string ----
- ;
- ; DS:DX = address of string
- ; CX = size
- ;
- print proc near
- mov ah,40h ; AH = write to file
- mov bx,stderr ; BX = file handle
- int 21h ; print string
- ret
- print endp
- ;
- ; ---- Message strings ----
- ;
- load_msg db cr,lf
- db 'Cannot load program.',cr,lf
- db 'Press any key to try again.',cr,lf
- load_msg_length equ $-load_msg
- ;
- ; ---- Program data area ----
- ;
- stk_seg dw 0 ; stack segment pointer
- stk_off dw 0 ; save area during EXEC
- pgm_name db '\NEWSHELL.COM',0 ; any program will do
- par_blk dw 0 ; use current environment
- dw offset cmd_line ; command-line address
- cmd_seg dw 0 ; fill in at initialization
- dw offset fcb1 ; default FCB #1
- fcb1_seg dw 0 ; fill in at initialization
- dw offset fcb2 ; default FCB #2
- fcb2_seg dw 0 ; fill in at initialization
- cmd_line db 0,cr ; actual command line
- fcb1 db 0
- db 11 dup (' ')
- db 25 dup ( 0 )
- fcb2 db 0
- db 11 dup (' ')
- db 25 dup ( 0 )
- dw 200 dup ( 0 ) ; program stack area
- stk dw 0
- last equ $ ; last address used
- cseg ends
- end start
-
- \SAMPCODE\DOS_ENCY\4
- \SAMPCODE\DOS_ENCY\4\FIG4_10.ASM
-
- ;Source Module MODULE_C
-
- ;Constant declarations ******************************************************
-
- CONST SEGMENT WORD PUBLIC 'CONST'
-
- CONST_FIELD_C DB 'Constant C' ;declare a MODULE_C constant
-
- CONST ENDS
-
-
- ;Preinitialized data fields *************************************************
-
- _DATA SEGMENT WORD PUBLIC 'DATA'
-
- DATA_FIELD_C DB 'Data C' ;declare a MODULE_C preinitialized fi
-
- _DATA ENDS
-
-
- ;Uninitialized data fields **************************************************
-
- _BSS SEGMENT WORD PUBLIC 'BSS'
-
- BSS_FIELD_C DB 5 DUP(?) ;declare a MODULE_C uninitialized fie
-
- _BSS ENDS
-
-
- ;Program text ***************************************************************
-
- DGROUP GROUP _DATA,CONST,_BSS
-
- _TEXT SEGMENT BYTE PUBLIC 'CODE'
-
- ASSUME CS:_TEXT,DS:DGROUP,ES:NOTHING,SS:NOTHING
-
- PUBLIC PROC_C ;referenced in MODULE_A
- PROC_C PROC NEAR
-
- RET
-
- PROC_C ENDP
-
- _TEXT ENDS
-
- END
-
- \SAMPCODE\DOS_ENCY\4\FIG4_15.ASM
-
- COMSEG SEGMENT BYTE PUBLIC 'CODE'
- ASSUME CS:COMSEG,DS:COMSEG,ES:COMSEG,SS:COMSEG
- ORG 0100H
-
- BEGIN:
- JMP START ;skip over data fields
- ;Place your data fields here.
-
- START:
- ;Place your program text here.
- MOV AX,4C00H ;terminate (MS-DOS 2.0 or later only)
- INT 21H
- COMSEG ENDS
- END BEGIN
-
- \SAMPCODE\DOS_ENCY\4\FIG4_16.ASM
-
- CSEG SEGMENT BYTE PUBLIC 'CODE' ;establish segment order
- CSEG ENDS
- DSEG SEGMENT BYTE PUBLIC 'DATA'
- DSEG ENDS
- COMGRP GROUP CSEG,DSEG ;establish joint address base
- DSEG SEGMENT
- ;Place your data fields here.
- DSEG ENDS
- CSEG SEGMENT
-
- ASSUME CS:COMGRP,DS:COMGRP,ES:COMGRP,SS:COMGRP
- ORG 0100H
-
- BEGIN:
- ;Place your program text here. Remember to use
- ;OFFSET COMGRP:LABEL whenever you use OFFSET.
- MOV AX,4C00H ;terminate (MS-DOS 2.0 or later only)
- INT 21H
- CSEG ENDS
- END BEGIN
-
- \SAMPCODE\DOS_ENCY\4\FIG4_3.ASM
-
- TEXT SEGMENT PARA PUBLIC 'CODE'
-
- ASSUME CS:TEXT,DS:NOTHING,ES:NOTHING,SS:NOTHING
-
- TERM_VECTOR DD ?
-
- ENTRY_PROC PROC FAR
-
- ;save pointer to termination vector in PSP
-
- MOV WORD PTR CS:TERM_VECTOR+0,0000h ;save offset of Warm Boot vec
- MOV WORD PTR CS:TERM_VECTOR+2,DS ;save segment address of PSP
-
- ;***** Place main task here *****
-
- ;determine which MS-DOS version is active, take jump if 2.0 or later
-
- MOV AH,30h ;load Get MS-DOS Version Number function code
- INT 21h ;call MS-DOS to get version number
- OR AL,AL ;see if pre-2.0 MS-DOS
- JNZ TERM_0200 ;jump if 2.0 or later
-
- ;terminate under pre-2.0 MS-DOS
-
- JMP CS:TERM_VECTOR ;jump to Warm Boot vector in PSP
-
- ;terminate under MS-DOS 2.0 or later
-
- TERM_0200:
- MOV AX,4C00h ;load MS-DOS termination function code
- ;and return code
- INT 21h ;call MS-DOS to terminate
-
- ENTRY_PROC ENDP
-
- TEXT ENDS
-
- END ENTRY_PROC ;define entry point
-
- \SAMPCODE\DOS_ENCY\4\FIG4_4.ASM
-
- TEXT SEGMENT PARA PUBLIC 'CODE'
-
- ASSUME CS:TEXT,DS:NOTHING,ES:NOTHING,SS:NOTHING
-
- ENTRY_PROC PROC FAR ;make proc FAR so RET will be FAR
-
- ;Push pointer to termination vector in PSP
- PUSH DS ;push PSP's segment address
- XOR AX,AX ;ax = 0 = offset of Warm Boot vector in PSP
- PUSH AX ;push Warm Boot vector offset
-
- ;***** Place main task here *****
-
- ;Determine which MS-DOS version is active, take jump if 2.0 or later
-
- MOV AH,30h ;load Get MS-DOS Version Number function code
- INT 21h ;call MS-DOS to get version number
- OR AL,AL ;see if pre-2.0 MS-DOS
- JNZ TERM_0200 ;jump if 2.0 or later
-
- ;Terminate under pre-2.0 MS-DOS (this is a FAR proc, so RET will be FAR)
- RET ;pop PSP:00H into CS:IP to terminate
-
- ;Terminate under MS-DOS 2.0 or later
- TERM_0200:
- MOV AX,4C00h ;AH = MS-DOS Terminate Process with Return Co
- ;function code, AL = return code of 00H
- INT 21h ;call MS-DOS to terminate
-
- ENTRY_PROC ENDP
-
- TEXT ENDS
-
- END ENTRY_PROC ;declare the program's entry point
-
- \SAMPCODE\DOS_ENCY\4\FIG4_8.ASM
-
- ;Source Module MODULE_A
-
- ;Predeclare all segments to force the linker's segment ordering *************
-
- _TEXT SEGMENT BYTE PUBLIC 'CODE'
- _TEXT ENDS
-
- _DATA SEGMENT WORD PUBLIC 'DATA'
- _DATA ENDS
-
- CONST SEGMENT WORD PUBLIC 'CONST'
- CONST ENDS
-
- _BSS SEGMENT WORD PUBLIC 'BSS'
- _BSS ENDS
-
- STACK SEGMENT PARA STACK 'STACK'
- STACK ENDS
-
- DGROUP GROUP _DATA,CONST,_BSS,STACK
-
-
- ;Constant declarations ******************************************************
-
- CONST SEGMENT WORD PUBLIC 'CONST'
-
- CONST_FIELD_A DB 'Constant A' ;declare a MODULE_A constant
-
- CONST ENDS
-
-
- ;Preinitialized data fields *************************************************
-
- _DATA SEGMENT WORD PUBLIC 'DATA'
-
- DATA_FIELD_A DB 'Data A' ;declare a MODULE_A preinitialized fi
-
- _DATA ENDS
-
-
- ;Uninitialized data fields **************************************************
-
- _BSS SEGMENT WORD PUBLIC 'BSS'
-
- BSS_FIELD_A DB 5 DUP(?) ;declare a MODULE_A uninitialized fie
-
- _BSS ENDS
-
-
- ;Program text ***************************************************************
-
- _TEXT SEGMENT BYTE PUBLIC 'CODE'
-
- ASSUME CS:_TEXT,DS:DGROUP,ES:NOTHING,SS:NOTHING
-
- EXTRN PROC_B:NEAR ;label is in _TEXT segment (NEAR)
- EXTRN PROC_C:NEAR ;label is in _TEXT segment (NEAR)
-
- PROC_A PROC NEAR
-
- CALL PROC_B ;call into MODULE_B
- CALL PROC_C ;call into MODULE_C
-
- MOV AX,4C00H ;terminate (MS-DOS 2.0 or later only)
- INT 21H
-
- PROC_A ENDP
-
- _TEXT ENDS
-
-
- ;Stack **********************************************************************
-
- STACK SEGMENT PARA STACK 'STACK'
-
- DW 128 DUP(?) ;declare some space to use as stack
- STACK_BASE LABEL WORD
-
- STACK ENDS
-
-
-
- END PROC_A ;declare PROC_A as entry point
-
- \SAMPCODE\DOS_ENCY\4\FIG4_9.ASM
-
- ;Source Module MODULE_B
-
- ;Constant declarations ******************************************************
-
- CONST SEGMENT WORD PUBLIC 'CONST'
-
- CONST_FIELD_B DB 'Constant B' ;declare a MODULE_B constant
-
- CONST ENDS
-
-
- ;Preinitialized data fields *************************************************
-
- _DATA SEGMENT WORD PUBLIC 'DATA'
-
- DATA_FIELD_B DB 'Data B' ;declare a MODULE_B preinitialized fi
-
- _DATA ENDS
-
-
- ;Uninitialized data fields **************************************************
-
- _BSS SEGMENT WORD PUBLIC 'BSS'
-
- BSS_FIELD_B DB 5 DUP(?) ;declare a MODULE_B uninitialized fie
-
- _BSS ENDS
-
-
- ;Program text ***************************************************************
-
- DGROUP GROUP _DATA,CONST,_BSS
-
- _TEXT SEGMENT BYTE PUBLIC 'CODE'
-
- ASSUME CS:_TEXT,DS:DGROUP,ES:NOTHING,SS:NOTHING
-
- PUBLIC PROC_B ;reference in MODULE_A
- PROC_B PROC NEAR
-
- RET
-
- PROC_B ENDP
-
- _TEXT ENDS
-
- END
-
- \SAMPCODE\DOS_ENCY\5
- \SAMPCODE\DOS_ENCY\5\FXN02H.ASM
-
- mov ah,02h ; function 02H = display character
- mov dl,'*' ; DL = character to display
- int 21h ; transfer to MS-DOS
-
- \SAMPCODE\DOS_ENCY\5\FXN04H.ASM
-
- msg db 'This is a test message'
- msg_len equ $-msg
- .
- .
- .
- mov bx,seg msg ; set DS:BX = address of message
- mov ds,bx
- mov bx,offset msg
- mov cx,msg_len ; set CX = length of message
- L1: mov dl,[bx] ; get next character into DL
- mov ah,04H ; function 04H = auxiliary output
- int 21h ; transfer to MS-DOS
- inc bx ; bump pointer to output string
- loop L1 ; and loop until all chars. sent
-
- \SAMPCODE\DOS_ENCY\5\FXN05H.ASM
-
- msg db 'This is a test message'
- msg_len equ $-msg
- .
- .
- .
- mov bx,seg msg ; DS:BX = address of message
- mov ds,bx
- mov bx,offset msg
- mov cx,msg_len ; CX = length of message
- L1: mov dl,[bx] ; get next character into DL
- mov ah,05H ; function 05H = printer output
- int 21h ; transfer to MS-DOS
- inc bx ; bump pointer to output string
- loop L1 ; and loop until all chars. sent
-
- \SAMPCODE\DOS_ENCY\5\FXN08H.ASM
-
- mov ah,08h ; function 08H = character input
- ; without echo
- int 21h ; transfer to MS-DOS
- ; now AL = character
-
- \SAMPCODE\DOS_ENCY\5\FXN09H.ASM
-
- msg db 'This is a test message','$'
- .
- .
- .
- mov dx,seg msg ; DS:DX = address of text
- mov ds,dx ; to display
- mov dx,offset msg
- mov ah,09H ; function 09H = display string
- int 21h ; transfer to MS-DOS
-
- \SAMPCODE\DOS_ENCY\5\FXN0AH.ASM
-
- kbuf db 80 ; maximum length of read
- db 0 ; actual length of read
- db 80 dup (0) ; keyboard input goes here
- .
- .
- .
- mov dx,seg kbuf ; set DS:DX = address of
- mov ds,dx ; keyboard input buffer
- mov dx,offset kbuf
- mov ah,0ah ; function 0AH = read buffered line
- int 21h ; transfer to MS-DOS
- ; terminated by a carriage return,
- ; and kbuf+1 = length of input,
- ; not including the carriage return
-
- \SAMPCODE\DOS_ENCY\5\FXN3FH.ASM
-
- kbuf db 80 dup (0) ; buffer for keyboard input
- .
- .
- .
- mov dx,seg kbuf ; set DS:DX = address of
- mov ds,dx ; keyboard input buffer
- mov dx,offset kbuf
- mov cx,80 ; CX = maximum length of input
- mov bx,0 ; standard input handle = 0
- mov ah,3fh ; function 3FH = read file/device
- int 21h ; transfer to MS-DOS
- jc error ; jump if function failed
- ; otherwise AX = actual
- ; length of keyboard input,
- ; including carriage-return and
- ; linefeed, and the data is
- ; in the buffer 'kbuf'
-
- \SAMPCODE\DOS_ENCY\5\FXN40H_1.ASM
-
- msg db 'This is a test message'
- msg_len equ $-msg
- .
- .
- .
- mov dx,seg msg ; DS:DX = address of text
- mov ds,dx ; to display
- mov dx,offset msg
- mov cx,msg_len ; CX = length of text
- mov bx,1 ; BX = handle for standard output
- mov ah,40h ; function 40H = write file/device
- int 21h ; transfer to MS-DOS
-
- \SAMPCODE\DOS_ENCY\5\FXN40H_2.ASM
-
- msg db 'This is a test message'
- msg_len equ $-msg
- .
- .
- .
- mov dx,seg msg ; DS:DX = address of message
- mov ds,dx
- mov dx,offset msg
- mov cx,msg_len ; CX = length of message
- mov bx,3 ; BX = handle for standard aux.
- mov ah,40h ; function 40H = write file/device
- int 21h ; transfer to MS-DOS
- jc error ; jump if write operation failed
-
- \SAMPCODE\DOS_ENCY\5\FXN40H_3.ASM
-
- msg db 'This is a test message'
- msg_len equ $-msg
- .
- .
- .
- mov dx,seg msg ; DS:DX = address of message
- mov ds,dx
- mov dx,offset msg
- mov cx,msg_len ; CX = length of message
- mov bx,4 ; BX = handle for standard printer
- mov ah,40h ; function 40H = write file/device
- int 21h ; transfer to MS-DOS
- jc error ; jump if write operation failed
-
- \SAMPCODE\DOS_ENCY\5\INT10H.ASM
-
- mov ah,0eh ; subfunction 0EH = write character
- ; in teletype mode
- mov al,'*' ; AL = character to display
- mov bh,0 ; select display page 0
- int 10h ; transfer to ROM BIOS video driver
-
- \SAMPCODE\DOS_ENCY\5\INT14H.ASM
-
- msg db 'This is a test message'
- msg_len equ $-msg
- .
- .
- .
- mov bx,seg msg ; DS:BX = address of message
- mov ds,bx
- mov bx,offset msg
- mov cx,msg_len ; CX = length of message
- mov dx,0 ; DX = 0 for COM1
- L1: mov al,[bx] ; get next character into AL
- mov ah,01h ; subfunction 01H = output
- int 14h ; transfer to ROM BIOS
- inc bx ; bump pointer to output string
- loop L1 ; and loop until all chars. sent
-
- \SAMPCODE\DOS_ENCY\5\INT16H.ASM
-
- mov ah,00h ; subfunction 00H = read character
- int 16h ; transfer to ROM BIOS
- ; now AH = scan code, AL = character
-
- \SAMPCODE\DOS_ENCY\5\INT17H.ASM
-
- msg db 'This is a test message'
- msg_len equ $-msg
- .
- .
- .
- mov bx,seg msg ; DS:BX = address of message
- mov ds,bx
- mov bx,offset msg
- mov cx,msg_len ; CX = length of message
- mov dx,0 ; DX = 0 for LPT1
- L1: mov al,[bx] ; get next character into AL
- mov ah,00H ; subfunction 00H = output
- int 17h ; transfer to ROM BIOS
- inc bx ; bump pointer to output string
- loop L1 ; and loop until all chars. sent
-
- \SAMPCODE\DOS_ENCY\5\IOCTL_1.ASM
-
- info dw ? ; save device information word here
- .
- .
- .
- mov ax,4400h ; AH = function 44H, IOCTL
- ; AL = subfunction 00H, get device
- ; information word
- mov bx,0 ; BX = handle for standard input
- int 21h ; transfer to MS-DOS
- mov info,dx ; save device information word
- ; (assumes DS = data segment)
- or dl,20h ; set raw mode bit
- mov dh,0 ; and clear DH as MS-DOS requires
- mov ax,4401h ; AL = subfunction 01H, set device
- ; information word
- ; (BX still contains handle)
- int 21h ; transfer to MS-DOS
-
- \SAMPCODE\DOS_ENCY\5\IOCTL_2.ASM
-
- mov ax,4406H ; AH = function 44H, IOCTL
- ; AL = subfunction 06H, get
- ; input status
- mov bx,3 ; BX = handle for standard aux
- int 21h ; transfer to MS-DOS
- or al,al ; test status of AUX driver
- jnz ready ; jump if input character ready
- ; else no character is waiting
-
- \SAMPCODE\DOS_ENCY\6
- \SAMPCODE\DOS_ENCY\6\CDVUTL.C
-
- /* cdvutl.c - COMDVR Utility
- * Jim Kyle - 1987
- * for use with COMDVR.SYS Device Driver
- */
-
- #include <stdio.h> /* i/o definitions */
- #include <conio.h> /* special console i/o */
- #include <stdlib.h> /* misc definitions */
- #include <dos.h> /* defines intdos() */
-
- /* the following define the driver status bits */
-
- #define HWINT 0x0800 /* MCR, first word, HW Ints gated */
- #define o_DTR 0x0200 /* MCR, first word, output DTR */
- #define o_RTS 0x0100 /* MCR, first word, output RTS */
-
- #define m_PG 0x0010 /* LCR, first word, parity ON */
- #define m_PE 0x0008 /* LCR, first word, parity EVEN */
- #define m_XS 0x0004 /* LCR, first word, 2 stop bits */
- #define m_WL 0x0003 /* LCR, first word, wordlen mask */
-
- #define i_CD 0x8000 /* MSR, 2nd word, Carrier Detect */
- #define i_RI 0x4000 /* MSR, 2nd word, Ring Indicator */
- #define i_DSR 0x2000 /* MSR, 2nd word, Data Set Ready */
- #define i_CTS 0x1000 /* MSR, 2nd word, Clear to Send */
-
- #define l_SRE 0x0040 /* LSR, 2nd word, Xmtr SR Empty */
- #define l_HRE 0x0020 /* LSR, 2nd word, Xmtr HR Empty */
- #define l_BRK 0x0010 /* LSR, 2nd word, Break Received */
- #define l_ER1 0x0008 /* LSR, 2nd word, FrmErr */
- #define l_ER2 0x0004 /* LSR, 2nd word, ParErr */
- #define l_ER3 0x0002 /* LSR, 2nd word, OveRun */
- #define l_RRF 0x0001 /* LSR, 2nd word, Rcvr DR Full */
-
- /* now define CLS string for ANSI.SYS */
- #define CLS "\033[2J"
-
- FILE * dvp;
- union REGS rvs;
- int iobf [ 5 ];
-
- main ()
- { cputs ( "\nCDVUTL - COMDVR Utility Version 1.0 - 1987\n" );
- disp (); /* do dispatch loop */
- }
-
- disp () /* dispatcher; infinite loop */
- { int c,
- u;
- u = 1;
- while ( 1 )
- { cputs ( "\r\n\tCommand (? for help): " );
- switch ( tolower ( c = getche ())) /* dispatch */
- {
- case '1' : /* select port 1 */
- fclose ( dvp );
- dvp = fopen ( "ASY1", "rb+" );
- u = 1;
- break;
-
- case '2' : /* select port 2 */
- fclose ( dvp );
- dvp = fopen ( "ASY2", "rb+" );
- u = 2;
- break;
-
- case 'b' : /* set baud rate */
- if ( iobf [ 4 ] == 300 )
- iobf [ 4 ] = 1200;
- else
- if ( iobf [ 4 ] == 1200 )
- iobf [ 4 ] = 2400;
- else
- if ( iobf [ 4 ] == 2400 )
- iobf [ 4 ] = 9600;
- else
- iobf [ 4 ] = 300;
- iocwr ();
- break;
-
- case 'e' : /* set parity even */
- iobf [ 0 ] |= ( m_PG + m_PE );
- iocwr ();
- break;
-
- case 'f' : /* toggle flow control */
- if ( iobf [ 3 ] == 1 )
- iobf [ 3 ] = 2;
- else
- if ( iobf [ 3 ] == 2 )
- iobf [ 3 ] = 4;
- else
- if ( iobf [ 3 ] == 4 )
- iobf [ 3 ] = 0;
- else
- iobf [ 3 ] = 1;
- iocwr ();
- break;
-
- case 'i' : /* initialize MCR/LCR to 8N1 : */
- iobf [ 0 ] = ( HWINT + o_DTR + o_RTS + m_WL );
- iocwr ();
- break;
-
- case '?' : /* this help list */
- cputs ( CLS ) /* clear the display */
- center ( "COMMAND LIST \n" );
- center ( "1 = select port 1 L = toggle word LENGTH " );
- center ( "2 = select port 2 N = set parity to NONE " );
- center ( "B = set BAUD rate O = set parity to ODD " );
- center ( "E = set parity to EVEN R = toggle error REPORTS" );
- center ( "F = toggle FLOW control S = toggle STOP bits " );
- center ( "I = INITIALIZE ints, etc. Q = QUIT " );
- continue;
-
- case 'l' : /* toggle word length */
- iobf [ 0 ] ^= 1;
- iocwr ();
- break;
-
- case 'n' : /* set parity off */
- iobf [ 0 ] &=~ ( m_PG + m_PE );
- iocwr ();
- break;
-
- case 'o' : /* set parity odd */
- iobf [ 0 ] |= m_PG;
- iobf [ 0 ] &=~ m_PE;
- iocwr ();
- break;
-
- case 'r' : /* toggle error reports */
- iobf [ 2 ] ^= 1;
- iocwr ();
- break;
-
- case 's' : /* toggle stop bits */
- iobf [ 0 ] ^= m_XS;
- iocwr ();
- break;
-
- case 'q' :
- fclose ( dvp );
- exit ( 0 ); /* break the loop, get out */
- }
- cputs ( CLS ); /* clear the display */
- center ( "CURRENT COMDVR STATUS" );
- report ( u, dvp ); /* report current status */
- }
- }
-
- center ( s ) char * s; /* centers a string on CRT */
- { int i ;
- for ( i = 80 - strlen ( s ); i > 0; i -= 2 )
- putch ( ' ' );
- cputs ( s );
- cputs ( "\r\n" );
- }
-
- iocwr () /* IOCTL Write to COMDVR */
- { rvs . x . ax = 0x4403;
- rvs . x . bx = fileno ( dvp );
- rvs . x . cx = 10;
- rvs . x . dx = ( int ) iobf;
- intdos ( & rvs, & rvs );
- }
-
- char * onoff ( x ) int x ;
- { return ( x ? " ON" : " OFF" );
- }
-
- report ( unit ) int unit ;
- { char temp [ 80 ];
- rvs . x . ax = 0x4402;
- rvs . x . bx = fileno ( dvp );
- rvs . x . cx = 10;
- rvs . x . dx = ( int ) iobf;
- intdos ( & rvs, & rvs ); /* use IOCTL Read to get data */
- sprintf ( temp, "\nDevice ASY%d\t%d BPS, %d-c-%c\r\n\n",
- unit, iobf [ 4 ], /* baud rate */
- 5 + ( iobf [ 0 ] & m_WL ), /* word length */
- ( iobf [ 0 ] & m_PG ?
- ( iobf [ 0 ] & m_PE ? 'E' : 'O' ) : 'N' ),
- ( iobf [ 0 ] & m_XS ? '2' : '1' )); /* stop bits */
- cputs ( temp );
-
- cputs ( "Hardware Interrupts are" );
- cputs ( onoff ( iobf [ 0 ] & HWINT ));
- cputs ( ", Data Terminal Rdy" );
- cputs ( onoff ( iobf [ 0 ] & o_DTR ));
- cputs ( ", Rqst To Send" );
- cputs ( onoff ( iobf [ 0 ] & o_RTS ));
- cputs ( ".\r\n" );
-
- cputs ( "Carrier Detect" );
- cputs ( onoff ( iobf [ 1 ] & i_CD ));
- cputs ( ", Data Set Rdy" );
- cputs ( onoff ( iobf [ 1 ] & i_DSR ));
- cputs ( ", Clear to Send" );
- cputs ( onoff ( iobf [ 1 ] & i_CTS ));
- cputs ( ", Ring Indicator" );
- cputs ( onoff ( iobf [ 1 ] & i_RI ));
- cputs ( ".\r\n" );
-
- cputs ( l_SRE & iobf [ 1 ] ? "Xmtr SR Empty, " : "" );
- cputs ( l_HRE & iobf [ 1 ] ? "Xmtr HR Empty, " : "" );
- cputs ( l_BRK & iobf [ 1 ] ? "Break Received, " : "" );
- cputs ( l_ER1 & iobf [ 1 ] ? "Framing Error, " : "" );
- cputs ( l_ER2 & iobf [ 1 ] ? "Parity Error, " : "" );
- cputs ( l_ER3 & iobf [ 1 ] ? "Overrun Error, " : "" );
- cputs ( l_RRF & iobf [ 1 ] ? "Rcvr DR Full, " : "" );
- cputs ( "\b\b.\r\n" );
-
- cputs ( "Reception errors " );
- if ( iobf [ 2 ] == 1 )
- cputs ( "are encoded as graphics in buffer" );
- else
- cputs ( "set failure flag" );
- cputs ( ".\r\n" );
-
- cputs ( "Outgoing Flow Control " );
- if ( iobf [ 3 ] & 4 )
- cputs ( "by XON and XOFF" );
- else
- if ( iobf [ 3 ] & 2 )
- cputs ( "by RTS and CTS" );
- else
- if ( iobf [ 3 ] & 1 )
- cputs ( "by DTR and DSR" );
- else
- cputs ( "disabled" );
- cputs ( ".\r\n" );
- }
-
- /*end of cdvutl.c */
-
- \SAMPCODE\DOS_ENCY\6\CTERM.C
-
- /* Terminal Emulator (cterm.c)
- * Jim Kyle, 1987
- *
- * Uses files CH1, CH1A, and CH2 for MASM support...
- */
-
- #include <stdio.h>
- #include <conio.h> /* special console i/o */
- #include <stdlib.h> /* misc definitions */
- #include <dos.h> /* defines intdos() */
- #include <string.h>
- #define BRK 'C'-'@' /* control characters */
- #define ESC '['-'@'
- #define XON 'Q'-'@'
- #define XOFF 'S'-'@'
-
- #define True 1
- #define False 0
-
- #define Is_Function_Key(C) ( (C) == ESC )
-
- static char capbfr [ 4096 ]; /* capture buffer */
- static int wh,
- ws;
-
- static int I,
- waitchr = 0,
- vflag = False,
- capbp,
- capbc,
- Ch,
- Want_7_Bit = True,
- ESC_Seq_State = 0; /* escape sequence state variable */
-
- int _cx ,
- _cy,
- _atr = 0x07, /* white on black */
- _pag = 0,
- oldtop = 0,
- oldbot = 0x184f;
-
- FILE * in_file = NULL; /* start with keyboard input */
- FILE * cap_file = NULL;
-
- #include "cterm.h" /* external declarations, etc. */
-
- int Wants_To_Abort () /* checks for interrupt of script */
- { return broke ();
- }
- void
-
- main ( argc, argv ) int argc ; /* main routine */
- char * argv [];
- { char * cp,
- * addext ();
- if ( argc > 1 ) /* check for script filename */
- in_file = fopen ( addext ( argv [ 1 ], ".SCR" ), "r" );
- if ( argc > 2 ) /* check for capture filename */
- cap_file = fopen ( addext ( argv [ 2 ], ".CAP" ), "w" );
- set_int (); /* install CH1 module */
- Set_Vid (); /* get video setup */
- cls (); /* clear the screen */
- cputs ( "Terminal Emulator" ); /* tell who's working */
- cputs ( "\r\n< ESC for local commands >\r\n\n" );
- Want_7_Bit = True;
- ESC_Seq_State = 0;
- Init_Comm (); /* set up drivers, etc. */
- while ( 1 ) /* main loop */
- { if (( Ch = kb_file ()) > 0 ) /* check local */
- { if ( Is_Function_Key ( Ch ))
- { if ( docmd () < 0 ) /* command */
- break;
- }
- else
- Send_Byte ( Ch & 0x7F ); /* else send it */
- }
- if (( Ch = Read_Modem ()) >= 0 ) /* check remote */
- { if ( Want_7_Bit )
- Ch &= 0x7F; /* trim off high bit */
- switch ( ESC_Seq_State ) /* state machine */
- {
- case 0 : /* no Esc sequence */
- switch ( Ch )
- {
- case ESC : /* Esc char received */
- ESC_Seq_State = 1;
- break;
-
- default :
- if ( Ch == waitchr ) /* wait if required */
- waitchr = 0;
- if ( Ch == 12 ) /* clear screen on FF */
- cls ();
- else
- if ( Ch != 127 ) /* ignore rubouts */
- { putchx ( (char) Ch ); /* handle all others */
- put_cap ( (char) Ch );
- }
- }
- break;
-
- case 1 : /* ESC -- process any escape sequences here */
- switch ( Ch )
- {
- case 'A' : /* VT52 up */
- ; /* nothing but stubs here */
- ESC_Seq_State = 0;
- break;
-
- case 'B' : /* VT52 down */
- ;
- ESC_Seq_State = 0;
- break;
-
- case 'C' : /* VT52 left */
- ;
- ESC_Seq_State = 0;
- break;
-
- case 'D' : /* VT52 right */
- ;
- ESC_Seq_State = 0;
- break;
-
- case 'E' : /* VT52 Erase CRT */
- cls (); /* actually do this one */
- ESC_Seq_State = 0;
- break;
-
- case 'H' : /* VT52 home cursor */
- locate ( 0, 0 );
- ESC_Seq_State = 0;
- break;
-
- case 'j' : /* VT52 Erase to EOS */
- deos ();
- ESC_Seq_State = 0;
- break;
-
- case '[' : /* ANSI.SYS - VT100 sequence */
- ESC_Seq_State = 2;
- break;
-
- default :
- putchx ( ESC ); /* pass thru all others */
- putchx ( (char) Ch );
- ESC_Seq_State = 0;
- }
- break;
-
- case 2 : /* ANSI 3.64 decoder */
- ESC_Seq_State = 0; /* not implemented */
- }
- }
- if ( broke ()) /* check CH1A handlers */
- { cputs ( "\r\n***BREAK***\r\n" );
- break;
- }
- } /* end of main loop */
- if ( cap_file ) /* save any capture */
- cap_flush ();
- Term_Comm (); /* restore when done */
- rst_int (); /* restore break handlers */
- exit ( 0 ); /* be nice to MS-DOS */
- }
-
- docmd () /* local command shell */
- { FILE * getfil ();
- int wp;
- wp = True;
- if ( ! in_file || vflag )
- cputs ( "\r\n\tCommand: " ); /* ask for command */
- else
- wp = False;
- Ch = toupper ( kbd_wait ()); /* get response */
- if ( wp )
- putchx ( (char) Ch );
- switch ( Ch ) /* and act on it */
- {
- case 'S' :
- if ( wp )
- cputs ( "low speed\r\n" );
- Set_Baud ( 300 );
- break;
-
- case 'D' :
- if ( wp )
- cputs ( "elay (1-9 sec): " );
- Ch = kbd_wait ();
- if ( wp )
- putchx ( (char) Ch );
- Delay ( 1000 * ( Ch - '0' ));
- if ( wp )
- putchx ( '\n' );
- break;
-
- case 'E' :
- if ( wp )
- cputs ( "ven Parity\r\n" );
- Set_Parity ( 2 );
- break;
-
- case 'F' :
- if ( wp )
- cputs ( "ast speed\r\n" );
- Set_Baud ( 1200 );
- break;
-
- case 'H' :
- if ( wp )
- { cputs ( "\r\n\tVALID COMMANDS:\r\n" );
- cputs ( "\tD = delay 0-9 seconds.\r\n" );
- cputs ( "\tE = even parity.\r\n" );
- cputs ( "\tF = (fast) 1200-baud.\r\n" );
- cputs ( "\tN = no parity.\r\n" );
- cputs ( "\tO = odd parity.\r\n" );
- cputs ( "\tQ = quit, return to DOS.\r\n" );
- cputs ( "\tR = reset modem.\r\n" );
- cputs ( "\tS = (slow) 300-baud.\r\n" );
- cputs ( "\tU = use script file.\r\n" );
- cputs ( "\tV = verify file input.\r\n" );
- cputs ( "\tW = wait for char." );
- }
- break;
-
- case 'N' :
- if ( wp )
- cputs ( "o Parity\r\n" );
- Set_Parity ( 1 );
- break;
-
- case 'O' :
- if ( wp )
- cputs ( "dd Parity\r\n" );
- Set_Parity ( 3 );
- break;
-
- case 'R' :
- if ( wp )
- cputs ( "ESET Comm Port\r\n" );
- Init_Comm ();
- break;
-
- case 'Q' :
- if ( wp )
- cputs ( " = QUIT Command\r\n" );
- Ch = ( - 1 );
- break;
-
- case 'U' :
- if ( in_file && ! vflag )
- putchx ( 'U' );
- cputs ( "se file: " );
- getfil ();
- cputs ( "File " );
- cputs ( in_file ? "Open\r\n" : "Bad\r\n" );
- waitchr = 0;
- break;
-
- case 'V' :
- if ( wp )
- { cputs ( "erify flag toggled " );
- cputs ( vflag ? "OFF\r\n" : "ON\r\n" );
- }
- vflag = vflag ? False : True;
- break;
-
- case 'W' :
- if ( wp )
- cputs ( "ait for: <" );
- waitchr = kbd_wait ();
- if ( waitchr == ' ' )
- waitchr = 0;
- if ( wp )
- { if ( waitchr )
- putchx ( (char) waitchr );
- else
- cputs ( "no wait" );
- cputs ( ">\r\n" );
- }
- break;
-
- default :
- if ( wp )
- { cputs ( "Don't know " );
- putchx ( (char) Ch );
- cputs ( "\r\nUse 'H' command for Help.\r\n" );
- }
- Ch = '?';
- }
- if ( wp ) /* if window open... */
- { cputs ( "\r\n[any key]\r" );
- while ( Read_Keyboard () == EOF ) /* wait for response */
- ;
- }
- return Ch ;
- }
-
- kbd_wait () /* wait for input */
- { int c ;
- while (( c = kb_file ()) == ( - 1 ))
- ;
- return c & 255;
- }
-
- kb_file () /* input from kb or file */
- { int c ;
- if ( in_file ) /* USING SCRIPT */
- { c = Wants_To_Abort (); /* use first as flag */
- if ( waitchr && ! c )
- c = ( - 1 ); /* then for char */
- else
- if ( c || ( c = getc ( in_file )) == EOF || c == 26 )
- { fclose ( in_file );
- cputs ( "\r\nScript File Closed\r\n" );
- in_file = NULL;
- waitchr = 0;
- c = ( - 1 );
- }
- else
- if ( c == '\n' ) /* ignore LF's in file */
- c = ( - 1 );
- if ( c == '\\' ) /* process Esc sequence */
- c = esc ();
- if ( vflag && c != ( - 1 )) /* verify file char */
- { putchx ( '{' );
- putchx ( (char) c );
- putchx ( '}' );
- }
- }
- else /* USING CONSOLE */
- c = Read_Keyboard (); /* if not using file */
- return ( c );
- }
-
- esc () /* script translator */
- { int c ;
- c = getc ( in_file ); /* control chars in file */
- switch ( toupper ( c ))
- {
- case 'E' :
- c = ESC;
- break;
-
- case 'N' :
- c = '\n';
- break;
-
- case 'R' :
- c = '\r';
- break;
-
- case 'T' :
- c = '\t';
- break;
-
- case '^' :
- c = getc ( in_file ) & 31;
- break;
- }
- return ( c );
- }
-
- FILE * getfil ()
- { char fnm [ 20 ];
- getnam ( fnm, 15 ); /* get the name */
- if ( ! ( strchr ( fnm, '.' )))
- strcat ( fnm, ".SCR" );
- return ( in_file = fopen ( fnm, "r" ));
- }
-
- void getnam ( b, s ) char * b; /* take input to buffer */
- int s ;
- { while ( s -- > 0 )
- { if (( * b = kbd_wait ()) != '\r' )
- putchx ( * b ++ );
- else
- break ;
- }
- putchx ( '\n' );
- * b = 0;
- }
-
- char * addext ( b, /* add default EXTension */
- e ) char * b,
- * e;
- { static char bfr [ 20 ];
- if ( strchr ( b, '.' ))
- return ( b );
- strcpy ( bfr, b );
- strcat ( bfr, e );
- return ( bfr );
- }
-
- void put_cap ( c ) char c ;
- { if ( cap_file && c != 13 ) /* strip out CR's */
- fputc ( c, cap_file ); /* use MS-DOS buffering */
- }
-
- void cap_flush () /* end Capture mode */
- { if ( cap_file )
- { fclose ( cap_file );
- cap_file = NULL;
- cputs ( "\r\nCapture file closed\r\n" );
- }
- }
-
- /* TIMER SUPPORT STUFF (IBMPC/MSDOS) */
- static long timr; /* timeout register */
-
- static union REGS rgv ;
-
- long getmr ()
- { long now ; /* msec since midnite */
- rgv.x.ax = 0x2c00;
- intdos ( & rgv, & rgv );
- now = rgv.h.ch; /* hours */
- now *= 60L; /* to minutes */
- now += rgv.h.cl; /* plus min */
- now *= 60L; /* to seconds */
- now += rgv.h.dh; /* plus sec */
- now *= 100L; /* to 1/100 */
- now += rgv.h.dl; /* plus 1/100 */
- return ( 10L * now ); /* msec value */
- }
-
- void Delay ( n ) int n ; /* sleep for n msec */
- { long wakeup ;
- wakeup = getmr () + ( long ) n; /* wakeup time */
- while ( getmr () < wakeup )
- ; /* now sleep */
- }
-
- void Start_Timer ( n ) int n ; /* set timeout for n sec */
- { timr = getmr () + ( long ) n * 1000L;
- }
-
- Timer_Expired () /* if timeout return 1 else return 0 */
- { return ( getmr () > timr );
- }
-
- Set_Vid ()
- { _i_v (); /* initialize video */
- return 0;
- }
-
- void locate ( row, col ) int row ,
- col;
- { _cy = row % 25;
- _cx = col % 80;
- _wrpos ( row, col ); /* use ML from CH2.ASM */
- }
-
- void deol ()
- { _deol (); /* use ML from CH2.ASM */
- }
-
- void deos ()
- { deol ();
- if ( _cy < 24 ) /* if not last, clear */
- { rgv.x.ax = 0x0600;
- rgv.x.bx = ( _atr << 8 );
- rgv.x.cx = ( _cy + 1 ) << 8;
- rgv.x.dx = 0x184F;
- int86 ( 0x10, & rgv, & rgv );
- }
- locate ( _cy, _cx );
- }
-
- void cls ()
- { _cls (); /* use ML */
- }
-
- void cursor ( yn ) int yn ;
- { rgv.x.cx = yn ? 0x0607 : 0x2607; /* ON/OFF */
- rgv.x.ax = 0x0100;
- int86 ( 0x10, & rgv, & rgv );
- }
-
- void revvid ( yn ) int yn ;
- { if ( yn )
- _atr = _color ( 8, 7 ); /* black on white */
- else
- _atr = _color ( 15, 0 ); /* white on black */
- }
-
- putchx ( c ) char c ; /* put char to CRT */
- { if ( c == '\n' )
- putch ( '\r' );
- putch ( c );
- return c ;
- }
-
- Read_Keyboard () /* get keyboard character
- returns -1 if none present */
- { int c ;
- if ( kbhit ()) /* no char at all */
- return ( getch ());
- return ( EOF );
- }
-
- /* MODEM SUPPORT */
- static char mparm,
- wrk [ 80 ];
-
- void Init_Comm () /* initialize comm port stuff */
- { static int ft = 0; /* firstime flag */
- if ( ft ++ == 0 )
- i_m ();
- Set_Parity ( 1 ); /* 8,N,1 */
- Set_Baud ( 1200 ); /* 1200 baud */
- }
-
- #define B1200 0x80 /* baudrate codes */
- #define B300 0x40
-
- Set_Baud ( n ) int n ; /* n is baud rate */
- { if ( n == 300 )
- mparm = ( mparm & 0x1F ) + B300;
- else
- if ( n == 1200 )
- mparm = ( mparm & 0x1F ) + B1200;
- else
- return 0; /* invalid speed */
- sprintf ( wrk, "Baud rate = %d\r\n", n );
- cputs ( wrk );
- set_mdm ( mparm );
- return n ;
- }
-
- #define PAREVN 0x18 /* MCR bits for commands */
- #define PARODD 0x10
- #define PAROFF 0x00
- #define STOP2 0x40
- #define WORD8 0x03
- #define WORD7 0x02
- #define WORD6 0x01
-
- Set_Parity ( n ) int n ; /* n is parity code */
- { static int mmode;
- if ( n == 1 )
- mmode = ( WORD8 | PAROFF ); /* off */
- else
- if ( n == 2 )
- mmode = ( WORD7 | PAREVN ); /* on and even */
- else
- if ( n == 3 )
- mmode = ( WORD7 | PARODD ); /* on and odd */
- else
- return 0; /* invalid code */
- mparm = ( mparm & 0xE0 ) + mmode;
- sprintf ( wrk, "Parity is %s\r\n", ( n == 1 ? "OFF" :
- ( n == 2 ? "EVEN" : "ODD" )));
- cputs ( wrk );
- set_mdm ( mparm );
- return n ;
- }
-
- Write_Modem ( c ) char c ; /* return 1 if ok, else 0 */
- { wrtmdm ( c );
- return ( 1 ); /* never any error */
- }
-
- Read_Modem ()
- { return ( rdmdm ()); /* from int bfr */
- }
-
- void Term_Comm () /* uninstall comm port drivers */
- { u_m ();
- }
-
- /* end of cterm.c */
-
- \SAMPCODE\DOS_ENCY\6\CH1.ASM
-
- TITLE CH1.ASM
-
- ; CH1.ASM -- support file for CTERM.C terminal emulator
- ; set up to work with COM2
- ; for use with Microsoft C and SMALL model only...
-
- _TEXT segment byte public 'CODE'
- _TEXT ends
- _DATA segment byte public 'DATA'
- _DATA ends
- CONST segment byte public 'CONST'
- CONST ends
- _BSS segment byte public 'BSS'
- _BSS ends
-
- DGROUP GROUP CONST, _BSS, _DATA
- assume cs:_TEXT, DS:DGROUP, ES:DGROUP, SS:DGROUP
-
- _TEXT segment
-
- public _i_m,_rdmdm,_Send_Byte,_wrtmdm,_set_mdm,_u_m
-
- bport EQU 02F8h ; COM2 base address, use 03F8H for COM1
- getiv EQU 350Bh ; COM2 vectors, use 0CH for COM1
- putiv EQU 250Bh
- imrmsk EQU 00001000b ; COM2 mask, use 00000100b for COM1
- oiv_o DW 0 ; old int vector save space
- oiv_s DW 0
-
- bf_pp DW in_bf ; put pointer (last used)
- bf_gp DW in_bf ; get pointer (next to use)
- bf_bg DW in_bf ; start of buffer
- bf_fi DW b_last ; end of buffer
-
- in_bf DB 512 DUP (?) ; input buffer
-
- b_last EQU $ ; address just past buffer end
-
- bd_dv DW 0417h ; baud rate divisors (0=110 bps)
- DW 0300h ; code 1 = 150 bps
- DW 0180h ; code 2 = 300 bps
- DW 00C0h ; code 3 = 600 bps
- DW 0060h ; code 4 = 1200 bps
- DW 0030h ; code 5 = 2400 bps
- DW 0018h ; code 6 = 4800 bps
- DW 000Ch ; code 7 = 9600 bps
-
- _set_mdm proc near ; replaces BIOS 'init' function
- PUSH BP
- MOV BP,SP ; establish stackframe pointer
- PUSH ES ; save registers
- PUSH DS
- MOV AX,CS ; point them to CODE segment
- MOV DS,AX
- MOV ES,AX
- MOV AH,[BP+4] ; get parameter passed by C
- MOV DX,BPORT+3 ; point to Line Control Reg
- MOV AL,80h ; set DLAB bit (see text)
- OUT DX,AL
- MOV DL,AH ; shift param to BAUD field
- MOV CL,4
- ROL DL,CL
- AND DX,00001110b ; mask out all other bits
- MOV DI,OFFSET bd_dv
- ADD DI,DX ; make pointer to true divisor
- MOV DX,BPORT+1 ; set to high byte first
- MOV AL,[DI+1]
- OUT DX,AL ; put high byte into UART
- MOV DX,BPORT ; then to low byte
- MOV AL,[DI]
- OUT DX,AL
- MOV AL,AH ; now use rest of parameter
- AND AL,00011111b ; to set Line Control Reg
- MOV DX,BPORT+3
- OUT DX,AL
- MOV DX,BPORT+2 ; Interrupt Enable Register
- MOV AL,1 ; Receive type only
- OUT DX,AL
- POP DS ; restore saved registers
- POP ES
- MOV SP,BP
- POP BP
- RET
- _set_mdm endp
-
- _wrtmdm proc near ; write char to modem
- _Send_Byte: ; name used by main program
- PUSH BP
- MOV BP,SP ; set up pointer and save regs
- PUSH ES
- PUSH DS
- MOV AX,CS
- MOV DS,AX
- MOV ES,AX
- MOV DX,BPORT+4 ; establish DTR, RTS, and OUT2
- MOV AL,0Bh
- OUT DX,AL
- MOV DX,BPORT+6 ; check for on line, CTS
- MOV BH,30h
- CALL w_tmr
- JNZ w_out ; timed out
- MOV DX,BPORT+5 ; check for UART ready
- MOV BH,20h
- CALL w_tmr
- JNZ w_out ; timed out
- MOV DX,BPORT ; send out to UART port
- MOV AL,[BP+4] ; get char passed from C
- OUT DX,AL
- w_out: POP DS ; restore saved regs
- POP ES
- MOV SP,BP
- POP BP
- RET
- _wrtmdm endp
-
- _rdmdm proc near ; reads byte from buffer
- PUSH BP
- MOV BP,SP ; set up ptr, save regs
- PUSH ES
- PUSH DS
- MOV AX,CS
- MOV DS,AX
- MOV ES,AX
- MOV AX,0FFFFh ; set for EOF flag
- MOV BX,bf_gp ; use "get" ptr
- CMP BX,bf_pp ; compare to "put"
- JZ nochr ; same, empty
- INC BX ; else char available
- CMP BX,bf_fi ; at end of bfr?
- JNZ noend ; no
- MOV BX,bf_bg ; yes, set to beg
- noend: MOV AL,[BX] ; get the char
- MOV bf_gp,BX ; update "get" ptr
- INC AH ; zero AH as flag
- nochr: POP DS ; restore regs
- POP ES
- MOV SP,BP
- POP BP
- RET
- _rdmdm endp
-
- w_tmr proc near
- MOV BL,1 ; wait timer, double loop
- w_tm1: SUB CX,CX ; set up inner loop
- w_tm2: IN AL,DX ; check for requested response
- MOV AH,AL ; save what came in
- AND AL,BH ; mask with desired bits
- CMP AL,BH ; then compare
- JZ w_tm3 ; got it, return with ZF set
- LOOP w_tm2 ; else keep trying
- DEC BL ; until double loop expires
- JNZ w_tm1
- OR BH,BH ; timed out, return NZ
- w_tm3: RET
- w_tmr endp
-
- ; hardware interrupt service routine
- rts_m: CLI
- PUSH DS ; save all regs
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH CS ; set DS same as CS
- POP DS
- MOV DX,BPORT ; grab the char from UART
- IN AL,DX
- MOV BX,bf_pp ; use "put" ptr
- INC BX ; step to next slot
- CMP BX,bf_fi ; past end yet?
- JNZ nofix ; no
- MOV BX,bf_bg ; yes, set to begin
- nofix: MOV [BX],AL ; put char in buffer
- MOV bf_pp,BX ; update "put" ptr
- MOV AL,20h ; send EOI to 8259 chip
- OUT 20h,AL
- POP DX ; restore regs
- POP CX
- POP BX
- POP AX
- POP DS
- IRET
-
- _i_m proc near ; install modem service
- PUSH BP
- MOV BP,SP ; save all regs used
- PUSH ES
- PUSH DS
- MOV AX,CS ; set DS,ES=CS
- MOV DS,AX
- MOV ES,AX
- MOV DX,BPORT+1 ; Interrupt Enable Reg
- MOV AL,0Fh ; enable all ints now
- OUT DX,AL
-
- im1: MOV DX,BPORT+2 ; clear junk from UART
- IN AL,DX ; read IID reg of UART
- MOV AH,AL ; save what came in
- TEST AL,1 ; anything pending?
- JNZ im5 ; no, all clear now
- CMP AH,0 ; yes, Modem Status?
- JNZ im2 ; no
- MOV DX,BPORT+6 ; yes, read MSR to clear
- IN AL,DX
- im2: CMP AH,2 ; Transmit HR empty?
- JNZ im3 ; no (no action needed)
- im3: CMP AH,4 ; Received Data Ready?
- JNZ im4 ; no
- MOV DX,BPORT ; yes, read it to clear
- IN AL,DX
- im4: CMP AH,6 ; Line Status?
- JNZ im1 ; no, check for more
- MOV DX,BPORT+5 ; yes, read LSR to clear
- IN AL,DX
- JMP im1 ; then check for more
-
- im5: MOV DX,BPORT+4 ; set up working conditions
- MOV AL,0Bh ; DTR, RTS, OUT2 bits
- OUT DX,AL
- MOV AL,1 ; enable RCV interrupt only
- MOV DX,BPORT+1
- OUT DX,AL
- MOV AX,GETIV ; get old int vector
- INT 21h
- MOV oiv_o,BX ; save for restoring later
- MOV oiv_s,ES
- MOV DX,OFFSET rts_m ; set in new one
- MOV AX,PUTIV
- INT 21h
- IN AL,21h ; now enable 8259 PIC
- AND AL,NOT IMRMSK
- OUT 21h,AL
- MOV AL,20h ; then send out an EOI
- OUT 20h,AL
- POP DS ; restore regs
- POP ES
- MOV SP,BP
- POP BP
- RET
- _i_m endp
-
- _u_m proc near ; uninstall modem service
- PUSH BP
- MOV BP,SP ; save registers
- IN AL,21h ; disable COM int in 8259
- OR AL,IMRMSK
- OUT 21h,AL
- PUSH ES
- PUSH DS
- MOV AX,CS ; set same as CS
- MOV DS,AX
- MOV ES,AX
- MOV AL,0 ; disable UART ints
- MOV DX,BPORT+1
- OUT DX,AL
- MOV DX,oiv_o ; restore original vector
- MOV DS,oiv_s
- MOV AX,PUTIV
- INT 21h
- POP DS ; restore registers
- POP ES
- MOV SP,BP
- POP BP
- RET
- _u_m endp
-
- _TEXT ends
-
- END
-
- \SAMPCODE\DOS_ENCY\6\CH1A.ASM
-
- TITLE CH1A.ASM
-
- ; CH1A.ASM -- support file for CTERM.C terminal emulator
- ; this set of routines replaces Ctrl-C/Ctrl-BREAK
- ; usage: void set_int(), rst_int();
- ; int broke(); /* boolean if BREAK */
- ; for use with Microsoft C and SMALL model only...
-
- _TEXT segment byte public 'CODE'
- _TEXT ends
- _DATA segment byte public 'DATA'
- _DATA ends
- CONST segment byte public 'CONST'
- CONST ends
- _BSS segment byte public 'BSS'
- _BSS ends
-
- DGROUP GROUP CONST, _BSS, _DATA
- ASSUME CS:_TEXT, DS:DGROUP, ES:DGROUP, SS:DGROUP
-
- _DATA SEGMENT BYTE PUBLIC 'DATA'
-
- OLDINT1B DD 0 ; storage for original INT 1BH vector
-
- _DATA ENDS
-
- _TEXT SEGMENT
-
- PUBLIC _set_int,_rst_int,_broke
-
- myint1b:
- mov word ptr cs:brkflg,1Bh ; make it nonzero
- iret
-
- myint23:
- mov word ptr cs:brkflg,23h ; make it nonzero
- iret
-
- brkflg dw 0 ; flag that BREAK occurred
-
- _broke proc near ; returns 0 if no break
- xor ax,ax ; prepare to reset flag
- xchg ax,cs:brkflg ; return current flag value
- ret
- _broke endp
-
- _set_int proc near
- mov ax,351bh ; get interrupt vector for 1BH
- int 21h ; (don't need to save for 23H)
- mov word ptr oldint1b,bx ; save offset in first word
- mov word ptr oldint1b+2,es ; save segment in second word
-
- push ds ; save our data segment
- mov ax,cs ; set DS to CS for now
- mov ds,ax
- lea dx,myint1b ; DS:DX points to new routine
- mov ax,251bh ; set interrupt vector
- int 21h
- mov ax,cs ; set DS to CS for now
- mov ds,ax
- lea dx,myint23 ; DS:DX points to new routine
- mov ax,2523h ; set interrupt vector
- int 21h
- pop ds ; restore data segment
- ret
- _set_int endp
-
- _rst_int proc near
- push ds ; save our data segment
- lds dx,oldint1b ; DS:DX points to original
- mov ax,251bh ; set interrupt vector
- int 21h
- pop ds ; restore data segment
- ret
- _rst_int endp
-
- _TEXT ends
-
- END
-
- \SAMPCODE\DOS_ENCY\6\CH2.ASM
-
- TITLE CH2.ASM
-
- ; CH2.ASM -- support file for CTERM.C terminal emulator
- ; for use with Microsoft C and SMALL model only...
-
- _TEXT segment byte public 'CODE'
- _TEXT ends
- _DATA segment byte public 'DATA'
- _DATA ends
- CONST segment byte public 'CONST'
- CONST ends
- _BSS segment byte public 'BSS'
- _BSS ends
-
- DGROUP GROUP CONST, _BSS, _DATA
- assume CS:_TEXT, DS:DGROUP, ES:DGROUP, SS:DGROUP
-
- _TEXT segment
-
- public __cls,__color,__deol,__i_v,__key,__wrchr,__wrpos
-
- atrib DB 0 ; attribute
- _colr DB 0 ; color
- v_bas DW 0 ; video segment
- v_ulc DW 0 ; upper left corner cursor
- v_lrc DW 184Fh ; lower right corner cursor
- v_col DW 0 ; current col/row
-
- __key proc near ; get keystroke
- PUSH BP
- MOV AH,1 ; check status via BIOS
- INT 16h
- MOV AX,0FFFFh
- JZ key00 ; none ready, return EOF
- MOV AH,0 ; have one, read via BIOS
- INT 16h
- key00: POP BP
- RET
- __key endp
-
- __wrchr proc near
- PUSH BP
- MOV BP,SP
- MOV AL,[BP+4] ; get char passed by C
- CMP AL,' '
- JNB prchr ; printing char, go do it
- CMP AL,8
- JNZ notbs
- DEC BYTE PTR v_col ; process backspace
- MOV AL,byte ptr v_col
- CMP AL,byte ptr v_ulc
- JB nxt_c ; step to next column
- JMP norml
-
- notbs: CMP AL,9
- JNZ notht
- MOV AL,byte ptr v_col ; process HTAB
- ADD AL,8
- AND AL,0F8h
- MOV byte ptr v_col,AL
- CMP AL,byte ptr v_lrc
- JA nxt_c
- JMP SHORT norml
-
- notht: CMP AL,0Ah
- JNZ notlf
- MOV AL,byte ptr v_col+1 ; process linefeed
- INC AL
- CMP AL,byte ptr v_lrc+1
- JBE noht1
- CALL scrol
- MOV AL,byte ptr v_lrc+1
- noht1: MOV byte ptr v_col+1,AL
- JMP SHORT norml
-
- notlf: CMP AL,0Ch
- JNZ ck_cr
- CALL __cls ; process formfeed
- JMP SHORT ignor
-
- ck_cr: CMP AL,0Dh
- JNZ ignor ; ignore all other CTL chars
- MOV AL,byte ptr v_ulc ; process CR
- MOV byte ptr v_col,AL
- JMP SHORT norml
-
- prchr: MOV AH,_colr ; process printing char
- PUSH AX
- XOR AH,AH
- MOV AL,byte ptr v_col+1
- PUSH AX
- MOV AL,byte ptr v_col
- PUSH AX
- CALL wrtvr
- MOV SP,BP
- nxt_c: INC BYTE PTR v_col ; advance to next column
- MOV AL,byte ptr v_col
- CMP AL,byte ptr v_lrc
- JLE norml
- MOV AL,0Dh ; went off end, do CR/LF
- PUSH AX
- CALL __wrchr
- POP AX
- MOV AL,0Ah
- PUSH AX
- CALL __wrchr
- POP AX
- norml: CALL set_cur
- ignor: MOV SP,BP
- POP BP
- RET
- __wrchr endp
-
- __i_v proc near ; establish video base segment
- PUSH BP
- MOV BP,SP
- MOV AX,0B000h ; mono, B800 for CGA
- MOV v_bas,AX ; could be made automatic
- MOV SP,BP
- POP BP
- RET
- __i_v endp
-
- __wrpos proc near ; set cursor position
- PUSH BP
- MOV BP,SP
- MOV DH,[BP+4] ; row from C program
- MOV DL,[BP+6] ; col from C program
- MOV v_col,DX ; cursor position
- MOV BH,atrib ; attribute
- MOV AH,2
- PUSH BP
- INT 10h
- POP BP
- MOV AX,v_col ; return cursor position
- MOV SP,BP
- POP BP
- RET
- __wrpos endp
-
- set_cur proc near ; set cursor to v_col
- PUSH BP
- MOV BP,SP
- MOV DX,v_col ; use where v_col says
- MOV BH,atrib
- MOV AH,2
- PUSH BP
- INT 10h
- POP BP
- MOV AX,v_col
- MOV SP,BP
- POP BP
- RET
- set_cur endp
-
- __color proc near ; _color(fg, bg)
- PUSH BP
- MOV BP,SP
- MOV AH,[BP+6] ; background from C
- MOV AL,[BP+4] ; foreground from C
- MOV CX,4
- SHL AH,CL
- AND AL,0Fh
- OR AL,AH ; pack up into 1 byte
- MOV _colr,AL ; store for handler's use
- XOR AH,AH
- MOV SP,BP
- POP BP
- RET
- __color endp
-
- scrol proc near ; scroll CRT up by one line
- PUSH BP
- MOV BP,SP
- MOV AL,1 ; count of lines to scroll
- MOV CX,v_ulc
- MOV DX,v_lrc
- MOV BH,_colr
- MOV AH,6
- PUSH BP
- INT 10h ; use BIOS
- POP BP
- MOV SP,BP
- POP BP
- RET
- scrol endp
-
- __cls proc near ; clear CRT
- PUSH BP
- MOV BP,SP
- MOV AL,0 ; flags CLS to BIOS
- MOV CX,v_ulc
- MOV v_col,CX ; set to HOME
- MOV DX,v_lrc
- MOV BH,_colr
- MOV AH,6
- PUSH BP
- INT 10h ; use BIOS scroll up
- POP BP
- CALL set_cur ; cursor to HOME
- MOV SP,BP
- POP BP
- RET
- __cls endp
-
- __deol proc near ; delete to end of line
- PUSH BP
- MOV BP,SP
- MOV AL,' '
- MOV AH,_colr ; set up blanks
- PUSH AX
- MOV AL,byte ptr v_col+1
- XOR AH,AH ; set up row value
- PUSH AX
- MOV AL,byte ptr v_col
-
- deol1: CMP AL,byte ptr v_lrc
- JA deol2 ; at RH edge
- PUSH AX ; current location
- CALL wrtvr ; write a blank
- POP AX
- INC AL ; next column
- JMP deol1 ; do it again
-
- deol2: MOV AX,v_col ; return cursor position
- MOV SP,BP
- POP BP
- RET
- __deol endp
-
- wrtvr proc near ; write video RAM (col, row, char/atr)
- PUSH BP
- MOV BP,SP ; set up arg ptr
- MOV DL,[BP+4] ; column
- MOV DH,[BP+6] ; row
- MOV BX,[BP+8] ; char/atr
- MOV AL,80 ; calc offset
- MUL DH
- XOR DH,DH
- ADD AX,DX
- ADD AX,AX ; adjust bytes to words
- PUSH ES ; save seg reg
- MOV DI,AX
- MOV AX,v_bas ; set up segment
- MOV ES,AX
- MOV AX,BX ; get the data
- STOSW ; put on screen
- POP ES ; restore regs
- MOV SP,BP
- POP BP
- RET
- wrtvr endp
-
- _TEXT ends
-
- END
-
- \SAMPCODE\DOS_ENCY\6\COMDVR.ASM
-
- Title COMDVR Driver for IBM COM Ports
- ; Jim Kyle, 1987
- ; Based on ideas from many sources......
- ; including Mike Higgins, CLM March 1985;
- ; public-domain INTBIOS program from BBS's;
- ; COMBIOS.COM from CIS Programmers' SIG; and
- ; ADVANCED MS-DOS by Ray Duncan.
- Subttl MS-DOS Driver Definitions
-
- Comment * This comments out the Dbg macro.....
- Dbg Macro Ltr1,Ltr2,Ltr3 ; used only to debug driver...
- Local Xxx
- Push Es ; save all regs used
- Push Di
- Push Ax
- Les Di,Cs:Dbgptr ; get pointer to CRT
- Mov Ax,Es:[di]
- Mov Al,Ltr1 ; move in letters
- Stosw
- Mov Al,Ltr2
- Stosw
- Mov Al,Ltr3
- Stosw
- Cmp Di,1600 ; top 10 lines only
- Jb Xxx
- Xor Di,Di
- Xxx: Mov Word Ptr Cs:Dbgptr,Di
- Pop Ax
- Pop Di
- Pop Es
- Endm
- * ; asterisk ends commented-out region
- ;
- ; Device Type Codes
- DevChr Equ 8000h ; this is a character device
- DevBlk Equ 0000h ; this is a block (disk) device
- DevIoc Equ 4000h ; this device accepts IOCTL requests
- DevNon Equ 2000h ; non-IBM disk driver (block only)
- DevOTB Equ 2000h ; MS-DOS 3.x out until busy supported (char)
- DevOCR Equ 0800h ; MS-DOS 3.x open/close/rm supported
- DevX32 Equ 0040h ; MS-DOS 3.2 functions supported
- DevSpc Equ 0010h ; accepts special interrupt 29H
- DevClk Equ 0008h ; this is the CLOCK device
- DevNul Equ 0004h ; this is the NUL device
- DevSto Equ 0002h ; this is standard output
- DevSti Equ 0001h ; this is standard input
- ;
- ; Error Status BITS
- StsErr Equ 8000h ; general error
- StsBsy Equ 0200h ; device busy
- StsDne Equ 0100h ; request completed
- ;
- ; Error Reason values for lower-order bits
- ErrWp Equ 0 ; write protect error
- ErrUu Equ 1 ; unknown unit
- ErrDnr Equ 2 ; drive not ready
- ErrUc Equ 3 ; unknown command
- ErrCrc Equ 4 ; cyclical redundancy check error
- ErrBsl Equ 5 ; bad drive request structure length
- ErrSl Equ 6 ; seek error
- ErrUm Equ 7 ; unknown media
- ErrSnf Equ 8 ; sector not found
- ErrPop Equ 9 ; printer out of paper
- ErrWf Equ 10 ; write fault
- ErrRf Equ 11 ; read fault
- ErrGf Equ 12 ; general failure
- ;
- ; Structure of an I/O request packet header.
- ;
- Pack Struc
- Len Db ? ; length of record
- Prtno Db ? ; unit code
- Code Db ? ; command code
- Stat Dw ? ; return status
- Dosq Dd ? ; (unused MS-DOS queue link pointer)
- Devq Dd ? ; (unused driver queue link pointer)
- Media Db ? ; media code on read/write
- Xfer Dw ? ; xfer address offset
- Xseg Dw ? ; xfer address segment
- Count Dw ? ; transfer byte count
- Sector Dw ? ; starting sector value (block only)
- Pack Ends
-
- Subttl IBM-PC Hardware Driver Definitions
- page
- ;
- ; 8259 data
- PIC_b Equ 020h ; port for EOI
- PIC_e Equ 021h ; port for Int enabling
- EOI Equ 020h ; EOI control word
- ;
- ; 8250 port offsets
- RxBuf Equ 0F8h ; base address
- Baud1 Equ RxBuf+1 ; baud divisor high byte
- IntEn Equ RxBuf+1 ; interrupt enable register
- IntId Equ RxBuf+2 ; interrupt identification register
- Lctrl Equ RxBuf+3 ; line control register
- Mctrl Equ RxBuf+4 ; modem control register
- Lstat Equ RxBuf+5 ; line status register
- Mstat Equ RxBuf+6 ; modem status register
- ;
- ; 8250 LCR constants
- Dlab Equ 10000000b ; divisor latch access bit
- SetBrk Equ 01000000b ; send break control bit
- StkPar Equ 00100000b ; stick parity control bit
- EvnPar Equ 00010000b ; even parity bit
- GenPar Equ 00001000b ; generate parity bit
- Xstop Equ 00000100b ; extra stop bit
- Wd8 Equ 00000011b ; word length = 8
- Wd7 Equ 00000010b ; word length = 7
- Wd6 Equ 00000001b ; word length = 6
- ;
- ; 8250 LSR constants
- xsre Equ 01000000b ; xmt SR empty
- xhre Equ 00100000b ; xmt HR empty
- BrkRcv Equ 00010000b ; break received
- FrmErr Equ 00001000b ; framing error
- ParErr Equ 00000100b ; parity error
- OveRun Equ 00000010b ; overrun error
- rdta Equ 00000001b ; received data ready
- AnyErr Equ BrkRcv+FrmErr+ParErr+OveRun
- ;
- ; 8250 MCR constants
- LpBk Equ 00010000b ; UART out loops to in (test)
- Usr2 Equ 00001000b ; Gates 8250 interrupts
- Usr1 Equ 00000100b ; aux user1 output
- SetRTS Equ 00000010b ; sets RTS output
- SetDTR Equ 00000001b ; sets DTR output
- ;
- ; 8250 MSR constants
- CDlvl Equ 10000000b ; carrier detect level
- RIlvl Equ 01000000b ; ring indicator level
- DSRlvl Equ 00100000b ; DSR level
- CTSlvl Equ 00010000b ; CTS level
- CDchg Equ 00001000b ; Carrier Detect change
- RIchg Equ 00000100b ; Ring Indicator change
- DSRchg Equ 00000010b ; DSR change
- CTSchg Equ 00000001b ; CTS change
- ;
- ; 8250 IER constants
- S_Int Equ 00001000b ; enable status interrupt
- E_Int Equ 00000100b ; enable error interrupt
- X_Int Equ 00000010b ; enable transmit interrupt
- R_Int Equ 00000001b ; enable receive interrupt
- Allint Equ 00001111b ; enable all interrupts
-
- Subttl Definitions for THIS Driver
- page
- ;
- ; Bit definitions for the output status byte
- ; ( this driver only )
- LinIdl Equ 0ffh ; if all bits off, xmitter is idle
- LinXof Equ 1 ; output is suspended by XOFF
- LinDSR Equ 2 ; output is suspended until DSR comes on again
- LinCTS Equ 4 ; output is suspended until CTS comes on again
- ;
- ; Bit definitions for the input status byte
- ; ( this driver only )
- BadInp Equ 1 ; input line errors have been detected
- LostDt Equ 2 ; receiver buffer overflowed, data lost
- OffLin Equ 4 ; device is off line now
- ;
- ; Bit definitions for the special characteristics words
- ; ( this driver only )
- ; InSpec controls how input from the UART is treated
- ;
- InEpc Equ 0001h ; errors translate to codes with parity bit on
- ;
- ; OutSpec controls how output to the UART is treated
- ;
- OutDSR Equ 0001h ; DSR is used to throttle output data
- OutCTS Equ 0002h ; CTS is used to throttle output data
- OutXon Equ 0004h ; XON/XOFF is used to throttle output data
- OutCdf Equ 0010h ; carrier detect is off-line signal
- OutDrf Equ 0020h ; DSR is off-line signal
- ;
- Unit Struc ; each unit has a structure defining its state:
- Port Dw ? ; I/O port address
- Vect Dw ? ; interrupt vector offset (NOT interrupt number!)
- Isradr Dw ? ; offset to interrupt service routine
- OtStat Db Wd8 ; default LCR bit settings during INIT,
- ; output status bits after
- InStat Db Usr2+SetRTS+SetDTR ; MCR bit settings during INIT,
- ; input status bits after
- InSpec Dw InEpc ; special mode bits for INPUT
- OutSpec Dw OutXon ; special mode bits for OUTPUT
- Baud Dw 96 ; current baud rate divisor value (1200 b)
- Ifirst Dw 0 ; offset of first character in input buffer
- Iavail Dw 0 ; offset of next available byte
- Ibuf Dw ? ; pointer to input buffer
- Ofirst Dw 0 ; offset of first character in output buffer
- Oavail Dw 0 ; offset of next avail byte in output buffer
- Obuf Dw ? ; pointer to output buffer
- Unit Ends
-
- ;
- ; Beginning of driver code and data
- ;
- Driver Segment
- Assume Cs:driver, ds:driver, es:driver
- Org 0 ; drivers start at 0
-
- Dw Async2,-1 ; pointer to next device
- Dw DevChr + DevIoc ; character device with IOCTL
- Dw Strtegy ; offset of Strategy routine
- Dw Request1 ; offset of interrupt entry point 1
- Db 'ASY1 ' ; device 1 name
- Async2:
- Dw -1,-1 ; pointer to next device: MS-DOS fills in
- Dw DevChr + DevIoc ; character device with IOCTL
- Dw Strtegy ; offset of Strategy routine
- Dw Request2 ; offset of interrupt entry point 2
- Db 'ASY2 ' ; device 2 name
-
- ;dbgptr dd 0b0000000h
- ;
- ; Following is the storage area for the request packet pointer
- ;
- PackHd Dd 0
- ;
- ; baud rate conversion table
- Asy_baudt Dw 50,2304 ; first value is desired baud rate
- Dw 75,1536 ; second is divisor register value
- Dw 110,1047
- Dw 134, 857
- Dw 150, 786
- Dw 300, 384
- Dw 600, 192
- Dw 1200, 96
- Dw 1800, 64
- Dw 2000, 58
- Dw 2400, 48
- Dw 3600, 32
- Dw 4800, 24
- Dw 7200, 16
- Dw 9600, 12
-
- ; table of structures
- ; ASY1 defaults to the COM1 port, INT 0CH vector, XON,
- ; no parity, 8 databits, 1 stop bit, and 1200 baud
- Asy_tab1:
- Unit <3f8h,30h,asy1isr,,,,,,,,in1buf,,,out1buf>
-
- ; ASY2 defaults to the COM2 port, INT 0BH vector, XON,
- ; no parity, 8 databits, 1 stop bit, and 1200 baud
- Asy_tab2:
- Unit <2f8h,2ch,asy2isr,,,,,,,,in2buf,,,out2buf>
-
- Bufsiz Equ 256 ; input buffer size
- Bufmsk = Bufsiz-1 ; mask for calculating offsets modulo bufsiz
- In1buf Db Bufsiz DUP (?)
- Out1buf Db Bufsiz DUP (?)
- In2buf Db Bufsiz DUP (?)
- Out2buf Db Bufsiz DUP (?)
- ;
- ; Following is a table of offsets to all the driver functions
-
- Asy_funcs:
- Dw Init ; 0 initialize driver
- Dw Mchek ; 1 media check (block only)
- Dw BldBPB ; 2 build BPB (block only)
- Dw Ioctlin ; 3 IOCTL read
- Dw Read ; 4 read
- Dw Ndread ; 5 nondestructive read
- Dw Rxstat ; 6 input status
- Dw Inflush ; 7 flush input buffer
- Dw Write ; 8 write
- Dw Write ; 9 write with verify
- Dw Txstat ; 10 output status
- Dw Txflush ; 11 flush output buffer
- Dw Ioctlout ; 12 IOCTL write
- ; Following are not used in this driver.....
- Dw Zexit ; 13 open (3.x only, not used)
- Dw Zexit ; 14 close (3.x only, not used)
- Dw Zexit ; 15 rem med (3.x only, not used)
- Dw Zexit ; 16 out until bsy (3.x only, not used)
- Dw Zexit ; 17
- Dw Zexit ; 18
- Dw Zexit ; 19 generic IOCTL request (3.2 only)
- Dw Zexit ; 20
- Dw Zexit ; 21
- Dw Zexit ; 22
- Dw Zexit ; 23 get logical drive map (3.2 only)
- Dw Zexit ; 24 set logical drive map (3.2 only)
-
- Subttl Driver Code
- Page
- ;
- ; The Strategy routine itself:
- ;
- Strtegy Proc Far
- ; dbg 'S','R',' '
- Mov Word Ptr CS:PackHd,BX ; store the offset
- Mov Word Ptr CS:PackHd+2,ES ; store the segment
- Ret
- Strtegy Endp
- ;
- Request1: ; async1 has been requested
- Push Si ; save SI
- Lea Si,Asy_tab1 ; get the device unit table address
- Jmp Short Gen_request
-
- Request2: ; async2 has been requested
- Push Si ; save SI
- Lea Si,Asy_tab2 ; get unit table two's address
-
- Gen_request:
- ; dbg 'R','R',' '
- Pushf ; save all regs
- Cld
- Push Ax
- Push Bx
- Push Cx
- Push Dx
- Push Di
- Push Bp
- Push Ds
- Push Es
- Push Cs ; set DS = CS
- Pop Ds
- Les Bx,PackHd ; get packet pointer
- Lea Di,Asy_funcs ; point DI to jump table
- Mov Al,es:code[bx] ; command code
- Cbw
- Add Ax,Ax ; double to word
- Add Di,ax
- Jmp [di] ; go do it
- ;
- ; Exit from driver request
- ;
- ExitP Proc Far
- Bsyexit:
- Mov Ax,StsBsy
- Jmp Short Exit
-
- Mchek:
- BldBPB:
- Zexit: Xor Ax,Ax
- Exit: Les Bx,PackHd ; get packet pointer
- Or Ax,StsDne
- Mov Es:Stat[Bx],Ax ; set return status
- Pop Es ; restore registers
- Pop Ds
- Pop Bp
- Pop Di
- Pop Dx
- Pop Cx
- Pop Bx
- Pop Ax
- Popf
- Pop Si
- Ret
- ExitP Endp
-
- Subttl Driver Service Routines
- Page
-
- ; Read data from device
-
- Read:
- ; dbg 'R','d',' '
- Mov Cx,Es:Count[bx] ; get requested nbr
- Mov Di,Es:Xfer[bx] ; get target pointer
- Mov Dx,Es:Xseg[bx]
- Push Bx ; save for count fixup
- Push Es
- Mov Es,Dx
- Test InStat[si],BadInp Or LostDt
- Je No_lerr ; no error so far...
- Add Sp,4 ; error, flush SP
- And InStat[si],Not ( BadInp Or LostDt )
- Mov Ax,ErrRf ; error, report it
- Jmp Exit
- No_lerr:
- Call Get_in ; go for one
- Or Ah,Ah
- Jnz Got_all ; none to get now
- Stosb ; store it
- Loop No_lerr ; go for more
- Got_all:
- Pop Es
- Pop Bx
- Sub Di,Es:Xfer[bx] ; calc number stored
- Mov Es:Count[bx],Di ; return as count
- Jmp Zexit
-
- ; Nondestructive read from device
-
- Ndread:
- Mov Di,ifirst[si]
- Cmp Di,iavail[si]
- Jne Ndget
- Jmp Bsyexit ; buffer empty
- Ndget:
- Push Bx
- Mov Bx,ibuf[si]
- Mov Al,[bx+di]
- Pop Bx
- Mov Es:media[bx],al ; return char
- Jmp Zexit
-
- ; Input status request
-
- Rxstat:
- Mov Di,ifirst[si]
- Cmp Di,iavail[si]
- Jne Rxful
- Jmp Bsyexit ; buffer empty
- Rxful:
- Jmp Zexit ; have data
-
- ; Input flush request
-
- Inflush:
- Mov Ax,iavail[si]
- Mov Ifirst[si],ax
- Jmp Zexit
-
- ; Output data to device
-
- Write:
- ; dbg 'W','r',' '
- Mov Cx,es:count[bx]
- Mov Di,es:xfer[bx]
- Mov Ax,es:xseg[bx]
- Mov Es,ax
- Wlup:
- Mov Al,es:[di] ; get the byte
- Inc Di
- Wwait:
- Call Put_out ; put away
- Cmp Ah,0
- Jne Wwait ; wait for room!
- Call Start_output ; get it going
- Loop Wlup
-
- Jmp Zexit
-
- ; Output status request
-
- Txstat:
- Mov Ax,ofirst[si]
- Dec Ax
- And Ax,bufmsk
- Cmp Ax,oavail[si]
- Jne Txroom
- Jmp Bsyexit ; buffer full
- Txroom:
- Jmp Zexit ; room exists
-
- ; IOCTL read request, return line parameters
-
- Ioctlin:
- Mov Cx,es:count[bx]
- Mov Di,es:xfer[bx]
- Mov Dx,es:xseg[bx]
- Mov Es,dx
- Cmp Cx,10
- Je Doiocin
- Mov Ax,errbsl
- Jmp Exit
- Doiocin:
- Mov Dx,port[si] ; base port
- Mov Dl,Lctrl ; line status
- Mov Cx,4 ; LCR, MCR, LSR, MSR
- Getport:
- In Al,dx
- Stos Byte Ptr [DI]
- Inc Dx
- Loop Getport
-
- Mov Ax,InSpec[si] ; spec in flags
- Stos Word Ptr [DI]
- Mov Ax,OutSpec[si] ; out flags
- Stos Word Ptr [DI]
- Mov Ax,baud[si] ; baud rate
- Mov Bx,di
- Mov Di,offset Asy_baudt+2
- Mov Cx,15
- Baudcin:
- Cmp [di],ax
- Je Yesinb
- Add Di,4
- Loop Baudcin
- Yesinb:
- Mov Ax,-2[di]
- Mov Di,bx
- Stos Word Ptr [DI]
- Jmp Zexit
-
- ; Flush output buffer request
-
- Txflush:
- Mov Ax,oavail[si]
- Mov Ofirst[si],ax
- Jmp Zexit
-
- ; IOCTL request: change line parameters for this driver
-
- Ioctlout:
- Mov Cx,es:count[bx]
- Mov Di,es:xfer[bx]
- Mov Dx,es:xseg[bx]
- Mov Es,dx
- Cmp Cx,10
- Je Doiocout
- Mov Ax,errbsl
- Jmp Exit
-
- Doiocout:
- Mov Dx,port[si] ; base port
- Mov Dl,Lctrl ; line ctrl
- Mov Al,es:[di]
- Inc Di
- Or Al,Dlab ; set baud
- Out Dx,al
- Clc
- Jnc $+2
- Inc Dx ; mdm ctrl
- Mov Al,es:[di]
- Or Al,Usr2 ; Int Gate
- Out Dx,al
- Add Di,3 ; skip LSR,MSR
- Mov Ax,es:[di]
- Add Di,2
- Mov InSpec[si],ax
- Mov Ax,es:[di]
- Add Di,2
- Mov OutSpec[si],ax
- Mov Ax,es:[di] ; set baud
- Mov Bx,di
- Mov Di,offset Asy_baudt
- Mov Cx,15
- Baudcout:
- Cmp [di],ax
- Je Yesoutb
- Add Di,4
- Loop Baudcout
-
- Mov Dl,Lctrl ; line ctrl
- In Al,dx ; get LCR data
- And Al,not Dlab ; strip
- Clc
- Jnc $+2
- Out Dx,al ; put back
- Mov Ax,ErrUm ; "unknown media"
- Jmp Exit
-
- Yesoutb:
- Mov Ax,2[di] ; get divisor
- Mov Baud[si],ax ; save to report later
- Mov Dx,port[si] ; set divisor
- Out Dx,al
- Clc
- Jnc $+2
- Inc Dx
- Mov Al,ah
- Out Dx,al
- Clc
- Jnc $+2
- Mov Dl,Lctrl ; line ctrl
- In Al,dx ; get LCR data
- And Al,not Dlab ; strip
- Clc
- Jnc $+2
- Out Dx,al ; put back
- Jmp Zexit
-
- Subttl Ring Buffer Routines
- Page
-
- Put_out Proc Near ; puts AL into output ring buffer
- Push Cx
- Push Di
- Pushf
- Cli
- Mov Cx,oavail[si] ; put ptr
- Mov Di,cx
- Inc Cx ; bump
- And Cx,bufmsk
- Cmp Cx,ofirst[si] ; overflow?
- Je Poerr ; yes, don't
- Add Di,obuf[si] ; no
- Mov [di],al ; put in buffer
- Mov Oavail[si],cx
- ; dbg 'p','o',' '
- Mov Ah,0
- Jmp Short Poret
- Poerr:
- Mov Ah,-1
- Poret:
- Popf
- Pop Di
- Pop Cx
- Ret
- Put_out Endp
-
- Get_out Proc Near ; gets next character from output ring buffer
- Push Cx
- Push Di
- Pushf
- Cli
- Mov Di,ofirst[si] ; get ptr
- Cmp Di,oavail[si] ; put ptr
- Jne Ngoerr
- Mov Ah,-1 ; empty
- Jmp Short Goret
- Ngoerr:
- ; dbg 'g','o',' '
- Mov Cx,di
- Add Di,obuf[si]
- Mov Al,[di] ; get char
- Mov Ah,0
- Inc Cx ; bump ptr
- And Cx,bufmsk ; wrap
- Mov Ofirst[si],cx
- Goret:
- Popf
- Pop Di
- Pop Cx
- Ret
- Get_out Endp
-
- Put_in Proc Near ; puts the char from AL into input ring buffer
- Push Cx
- Push Di
- Pushf
- Cli
- Mov Di,iavail[si]
- Mov Cx,di
- Inc Cx
- And Cx,bufmsk
- Cmp Cx,ifirst[si]
- Jne Npierr
- Mov Ah,-1
- Jmp Short Piret
- Npierr:
- Add Di,ibuf[si]
- Mov [di],al
- Mov Iavail[si],cx
- ; dbg 'p','i',' '
- Mov Ah,0
- Piret:
- Popf
- Pop Di
- Pop Cx
- Ret
- Put_in Endp
-
- Get_in Proc Near ; gets one from input ring buffer into AL
- Push Cx
- Push Di
- Pushf
- Cli
- Mov Di,ifirst[si]
- Cmp Di,iavail[si]
- Je Gierr
- Mov Cx,di
- Add Di,ibuf[si]
- Mov Al,[di]
- Mov Ah,0
- ; dbg 'g','i',' '
- Inc Cx
- And Cx,bufmsk
- Mov Ifirst[si],cx
- Jmp Short Giret
- Gierr:
- Mov Ah,-1
- Giret:
- Popf
- Pop Di
- Pop Cx
- Ret
- Get_in Endp
-
- Subttl Interrupt Dispatcher Routine
- Page
-
- Asy1isr:
- Sti
- Push Si
- Lea Si,asy_tab1
- Jmp Short Int_serve
-
- Asy2isr:
- Sti
- Push Si
- Lea Si,asy_tab2
-
- Int_serve:
- Push Ax ; save all regs
- Push Bx
- Push Cx
- Push Dx
- Push Di
- Push Ds
- Push Cs ; set DS = CS
- Pop Ds
- Int_exit:
- ; dbg 'I','x',' '
- Mov Dx,Port[si] ; base address
- Mov Dl,IntId ; check Int ID
- In Al,Dx
- Cmp Al,00h ; dispatch filter
- Je Int_modem
- Jmp Int_mo_no
- Int_modem:
- ; dbg 'M','S',' '
- Mov Dl,Mstat
- In Al,dx ; read MSR content
- Test Al,CDlvl ; carrier present?
- Jnz Msdsr ; yes, test for DSR
- Test OutSpec[si],OutCdf ; no, is CD off line?
- Jz Msdsr
- Or InStat[si],OffLin
- Msdsr:
- Test Al,DSRlvl ; DSR present?
- Jnz Dsron ; yes, handle it
- Test OutSpec[si],OutDSR ; no, is DSR throttle?
- Jz Dsroff
- Or OtStat[si],LinDSR ; yes, throttle down
- Dsroff:
- Test OutSpec[si],OutDrf ; is DSR off line?
- Jz Mscts
- Or InStat[si],OffLin ; yes, set flag
- Jmp Short Mscts
- Dsron:
- Test OtStat[si],LinDSR ; throttled for DSR?
- Jz Mscts
- Xor OtStat[si],LinDSR ; yes, clear it out
- Call Start_output
- Mscts:
- Test Al,CTSlvl ; CTS present?
- Jnz Ctson ; yes, handle it
- Test OutSpec[si],OutCTS ; no, is CTS throttle?
- Jz Int_exit2
- Or OtStat[si],LinCTS ; yes, shut it down
- Jmp Short Int_exit2
- Ctson:
- Test OtStat[si],LinCTS ; throttled for CTS?
- Jz Int_exit2
- Xor OtStat[si],LinCTS ; yes, clear it out
- Jmp Short Int_exit1
- Int_mo_no:
- Cmp Al,02h
- Jne Int_tx_no
- Int_txmit:
- ; dbg 'T','x',' '
- Int_exit1:
- Call Start_output ; try to send another
- Int_exit2:
- Jmp Int_exit
- Int_tx_no:
- Cmp Al,04h
- Jne Int_rec_no
- Int_receive:
- ; dbg 'R','x',' '
- Mov Dx,port[si]
- In Al,dx ; take char from 8250
- Test OutSpec[si],OutXon ; is XON/XOFF enabled?
- Jz Stuff_in ; no
- Cmp Al,'S' And 01FH ; yes, is this XOFF?
- Jne Isq ; no, check for XON
- Or OtStat[si],LinXof ; yes, disable output
- Jmp Int_exit2 ; don't store this one
- Isq:
- Cmp Al,'Q' And 01FH ; is this XON?
- Jne Stuff_in ; no, save it
- Test OtStat[si],LinXof ; yes, waiting?
- Jz Int_exit2 ; no, ignore it
- Xor OtStat[si],LinXof ; yes, clear the XOFF bit
- Jmp Int_exit1 ; and try to resume xmit
- Int_rec_no:
- Cmp Al,06h
- Jne Int_done
- Int_rxstat:
- ; dbg 'E','R',' '
- Mov Dl,Lstat
- In Al,dx
- Test InSpec[si],InEpc ; return them as codes?
- Jz Nocode ; no, just set error alarm
- And Al,AnyErr ; yes, mask off all but error bits
- Or Al,080h
- Stuff_in:
- Call Put_in ; put input char in buffer
- Cmp Ah,0 ; did it fit?
- Je Int_exit3 ; yes, all OK
- Or InStat[si],LostDt ; no, set DataLost bit
- Int_exit3:
- Jmp Int_exit
- Nocode:
- Or InStat[si],BadInp
- Jmp Int_exit3
- Int_done:
- Clc
- Jnc $+2
- Mov Al,EOI ; all done now
- Out PIC_b,Al
- Pop Ds ; restore regs
- Pop Di
- Pop Dx
- Pop Cx
- Pop Bx
- Pop Ax
- Pop Si
- Iret
-
- Start_output Proc Near
- Test OtStat[si],LinIdl ; Blocked?
- Jnz Dont_start ; yes, no output
- Mov Dx,port[si] ; no, check UART
- Mov Dl,Lstat
- In Al,Dx
- Test Al,xhre ; empty?
- Jz Dont_start ; no
- Call Get_out ; yes, anything waiting?
- Or Ah,Ah
- Jnz Dont_start ; no
- Mov Dl,RxBuf ; yes, send it out
- Out Dx,al
- ; dbg 's','o',' '
- Dont_start:
- ret
- Start_output Endp
-
- Subttl Initialization Request Routine
- Page
-
- Init: Lea Di,$ ; release rest...
- Mov Es:Xfer[bx],Di
- Mov Es:Xseg[bx],Cs
-
- Mov Dx,Port[si] ; base port
- Mov Dl,Lctrl
- Mov Al,Dlab ; enable divisor
- Out Dx,Al
- Clc
- Jnc $+2
- Mov Dl,RxBuf
- Mov Ax,Baud[si] ; set baud
- Out Dx,Al
- Clc
- Jnc $+2
- Inc Dx
- Mov Al,Ah
- Out Dx,Al
- Clc
- Jnc $+2
-
- Mov Dl,Lctrl ; set LCR
- Mov Al,OtStat[si] ; from table
- Out Dx,Al
- Mov OtStat[si],0 ; clear status
- Clc
- Jnc $+2
- Mov Dl,IntEn ; IER
- Mov Al,AllInt ; enable ints in 8250
- Out Dx,Al
- Clc
- Jnc $+2
- Mov Dl,Mctrl ; set MCR
- Mov Al,InStat[si] ; from table
- Out Dx,Al
- Mov InStat[si],0 ; clear status
-
- ClRgs: Mov Dl,Lstat ; clear LSR
- In Al,Dx
- Mov Dl,RxBuf ; clear RX reg
- In Al,Dx
- Mov Dl,Mstat ; clear MSR
- In Al,Dx
- Mov Dl,IntId ; IID reg
- In Al,Dx
- In Al,Dx
- Test Al,1 ; int pending?
- Jz ClRgs ; yes, repeat
-
- Cli
- Xor Ax,Ax ; set int vec
- Mov Es,Ax
- Mov Di,Vect[si]
- Mov Ax,IsrAdr[si] ; from table
- Stosw
- Mov Es:[di],cs
-
- In Al,PIC_e ; get 8259
- And Al,0E7h ; com1/2 mask
- Clc
- Jnb $+2
- Out PIC_e,Al
- Sti
-
- Mov Al,EOI ; now send EOI just in case
- Out PIC_b,Al
-
- ; dbg 'D','I',' ' ; driver installed
- Jmp Zexit
-
- Driver Ends
- End
-
- \SAMPCODE\DOS_ENCY\6\ENGINE.ASM
-
- TITLE engine
-
- CODE SEGMENT PUBLIC 'CODE'
-
- ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE
-
- ORG 0100h
-
- START: mov dx,offset devnm ; open named device (ASY1)
- mov ax,3d02h
- int 21h
- mov handle,ax ; save the handle
- jc quit
- alltim: call getmdm ; main engine loop
- call putcrt
- call getkbd
- call putmdm
- jmp alltim
- quit: mov ah,4ch ; come here to quit
- int 21h
-
- getmdm proc ; get input from modem
- mov cx,256
- mov bx,handle
- mov dx,offset mbufr
- mov ax,3F00h
- int 21h
- jc quit
- mov mdlen,ax
- ret
- getmdm endp
-
- getkbd proc ; get input from keyboard
- mov kblen,0 ; first zero the count
- mov ah,11 ; key pressed?
- int 21h
- inc al
- jnz nogk ; no
- mov ah,7 ; yes, get it
- int 21h
- cmp al,3 ; was it Ctrl-C?
- je quit ; yes, get out
- mov kbufr,al ; no, save it
- inc kblen
- cmp al,13 ; was it Enter?
- jne nogk ; no
- mov byte ptr kbufr+1,10 ; yes, add LF
- inc kblen
- nogk: ret
- getkbd endp
-
- putmdm proc ; put output to modem
- mov cx,kblen
- jcxz nopm
- mov bx,handle
- mov dx,offset kbufr
- mov ax,4000h
- int 21h
- jc quit
- nopm: ret
- putmdm endp
-
- putcrt proc ; put output to CRT
- mov cx,mdlen
- jcxz nopc
- mov bx,1
- mov dx,offset mbufr
- mov ah,40h
- int 21h
- jc quit
- nopc: ret
- putcrt endp
-
- devnm db 'ASY1',0 ; miscellaneous data and buffers
- handle dw 0
- kblen dw 0
- mdlen dw 0
- mbufr db 256 dup (0)
- kbufr db 80 dup (0)
-
- CODE ENDS
- END START
-
- \SAMPCODE\DOS_ENCY\6\ENGINE_1.ASM
-
- ;Incomplete (and Unworkable) Implementation
-
- LOOP: MOV AH,08h ; read keyboard, no echo
- INT 21h
- MOV DL,AL ; set up to send
- MOV AH,04h ; send to AUX device
- INT 21h
- MOV AH,03h ; read from AUX device
- INT 21h
- MOV DL,AL ; set up to send
- MOV AH,02h ; send to screen
- INT 21h
- JMP LOOP ; keep doing it
-
- \SAMPCODE\DOS_ENCY\6\ENGINE_2.ASM
-
- ;Improved, (but Still Unworkable) Implementation
-
- LOOP: MOV AH,0Bh ; test keyboard for char
- INT 21h
- OR AL,AL ; test for zero
- JZ RMT ; no char avail, skip
- MOV AH,08h ; have char, read it in
- INT 21h
- MOV DL,AL ; set up to send
- MOV AH,04h ; send to AUX device
- INT 21h
- RMT:
- MOV AH,03h ; read from AUX device
- INT 21h
- MOV DL,AL ; set up to send
- MOV AH,02h ; send to screen
- INT 21h
- JMP LOOP ; keep doing it
-
- \SAMPCODE\DOS_ENCY\6\UART.ASM
-
- MOV DX,03FBh ; base port COM1 (03F8) + LCR (3)
- MOV AL,080h ; enable Divisor Latch
- OUT DX,AL
- MOV DX,03F8h ; set for Baud0
- MOV AX,96 ; set divisor to 1200 BPS
- OUT DX,AL
- INC DX ; to offset 1 for Baud1
- MOV AL,AH ; high byte of divisor
- OUT DX,AL
- MOV DX,03FBh ; back to the LCR offset
- MOV AL,03 ; DLAB = 0, Parity = N, WL = 8
- OUT DX,AL
- MOV DX,03F9h ; offset 1 for IER
- MOV AL,0Fh ; enable all ints in 8250
- OUT DX,AL
- MOV DX,03FCh ; COM1 + MCR (4)
- MOV AL,0Bh ; OUT2 + RTS + DTR bits
- OUT DX,AL
- CLRGS:
- MOV DX,03FDh ; clear LSR
- IN AL,DX
- MOV DX,03F8h ; clear RX reg
- IN AL,DX
- MOV DX,03FEh ; clear MSR
- IN AL,DX
- MOV DX,03FAh ; IID reg
- IN AL,DX
- IN AL,DX ; repeat to be sure
- TEST AL,1 ; int pending?
- JZ CLRGS ; yes, repeat
-
- \SAMPCODE\DOS_ENCY\7
- \SAMPCODE\DOS_ENCY\7\CMDTAIL.ASM
-
- cmdtail equ 80h ; PSP offset of command tail
- fname db 64 dup (?)
- fhandle dw ?
-
- .
- .
- .
- ; assume that DS already
- ; contains segment of PSP
-
- ; prepare to copy filename...
- mov si,cmdtail ; DS:SI = command tail
- mov di,seg fname ; ES:DI = buffer to receive
- mov es,di ; filename from command tail
- mov di,offset fname
- cld ; safety first!
-
- lodsb ; check length of command tail
- or al,al
- jz error ; jump, command tail empty
-
- label1: ; scan off leading spaces
- lodsb ; get next character
- cmp al,20h ; is it a space?
- jz label1 ; yes, skip it
-
- label2:
- cmp al,0dh ; look for terminator
- jz label3 ; quit if return found
- cmp al,20h
- jz label3 ; quit if space found
- stosb ; else copy this character
- lodsb ; get next character
- jmp label2
-
- label3:
- xor al,al ; store final NULL to
- stosb ; create ASCIIZ string
-
- ; now open the file...
- mov dx,seg fname ; DS:DX = address of
- mov ds,dx ; pathname for file
- mov dx,offset fname
- mov ax,3d02h ; Function 3DH = open r/w
- int 21h ; transfer to MS-DOS
- jnc label4 ; jump if file found
-
- cmp ax,2 ; error 2 = file not found
- jnz error ; jump if other error
- ; else make the file...
- xor cx,cx ; CX = normal attribute
- mov ah,3ch ; Function 3CH = create
- int 21h ; transfer to MS-DOS
- jc error ; jump if create failed
-
- label4:
- mov fhandle,ax ; save handle for file
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\7\COPYFILE.ASM
-
- fcb1 db 0 ; drive = default
- db 'MYFILE ' ; 8 character filename
- db 'DAT' ; 3 character extension
- db 25 dup (0) ; remainder of fcb1
- fcb2 db 0 ; drive = default
- db 'MYFILE ' ; 8 character filename
- db 'BAK' ; 3 character extension
- db 25 dup (0) ; remainder of fcb2
- buff db 512 dup (?) ; buffer for file I/O
- .
- .
- .
- ; open MYFILE.DAT...
- mov dx,seg fcb1 ; DS:DX = address of FCB
- mov ds,dx
- mov dx,offset fcb1
- mov ah,0fh ; Function 0FH = open
- int 21h ; transfer to MS-DOS
- or al,al ; did open succeed?
- jnz error ; jump if open failed
- ; create MYFILE.BAK...
- mov dx,offset fcb2 ; DS:DX = address of FCB
- mov ah,16h ; Function 16H = create
- int 21h ; transfer to MS-DOS
- or al,al ; did create succeed?
- jnz error ; jump if create failed
- ; set record length to 512
- mov word ptr fcb1+0eh,512
- mov word ptr fcb2+0eh,512
- ; set DTA to our buffer...
- mov dx,offset buff ; DS:DX = buffer address
- mov ah,1ah ; Function 1AH = set DTA
- int 21h ; transfer to MS-DOS
- loop: ; read MYFILE.DAT
- mov dx,offset fcb1 ; DS:DX = FCB address
- mov ah,14h ; Function 14H = seq. read
- int 21h ; transfer to MS-DOS
- or al,al ; was read successful?
- jnz done ; no, quit
- ; write MYFILE.BAK...
- mov dx,offset fcb2 ; DS:DX = FCB address
- mov ah,15h ; Function 15H = seq. write
- int 21h ; transfer to MS-DOS
- or al,al ; was write successful?
- jnz error ; jump if write failed
- jmp loop ; continue to end of file
- done: ; now close files...
- mov dx,offset fcb1 ; DS:DX = FCB for MYFILE.DAT
- mov ah,10h ; Function 10H = close file
- int 21h ; transfer to MS-DOS
- or al,al ; did close succeed?
- jnz error ; jump if close failed
- mov dx,offset fcb2 ; DS:DX = FCB for MYFILE.BAK
- mov ah,10h ; Function 10H = close file
- int 21h ; transfer to MS-DOS
- or al,al ; did close succeed?
- jnz error ; jump if close failed
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\7\FXN13H.ASM
-
- delfcb db 0 ; default drive
- db 'A???????' ; wildcard filename
- db 'BAK' ; extension
- db 25 dup (0) ; remainder of FCB
-
- .
- .
- .
- mov dx,seg delfcb ; DS:DX = FCB address
- mov ds,dx
- mov dx,offset delfcb
- mov ah,13h ; Function 13H = delete
- int 21h ; transfer to MS-DOS
- or al,al ; did function succeed?
- jnz error ; jump if delete failed
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\7\FXN17H.ASM
-
- renfcb db 0 ; default drive
- db '????????' ; wildcard filename
- db 'ASM' ; old extension
- db 5 dup (0) ; reserved area
- db '????????' ; wildcard filename
- db 'COD' ; new extension
- db 15 dup (0) ; remainder of FCB
-
- .
- .
- .
- mov dx,seg renfcb ; DS:DX = address of
- mov ds,dx ; "special" FCB
- mov dx,offset renfcb
- mov ah,17h ; Function 17H = rename
- int 21h ; transfer to MS-DOS
- or al,al ; did function succeed?
- jnz error ; jump if rename failed
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\7\FXN3CH.ASM
-
- fname db 'C:\LETTERS\MEMO.TXT',0
- fhandle dw ?
- .
- .
- .
- mov dx,seg fname ; DS:DX = address of
- mov ds,dx ; pathname for file
- mov dx,offset fname
- xor cx,cx ; CX = normal attribute
- mov ah,3ch ; Function 3CH = create
- int 21h ; transfer to MS-DOS
- jc error ; jump if create failed
- mov fhandle,ax ; else save file handle
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\7\FXN41H.ASM
-
- fname db 'C:\WORK\MYFILE.DAT',0
- .
- .
- .
- mov dx,seg fname ; DS:DX = address of filename
- mov ds,dx
- mov dx,offset fname
- mov ah,41h ; Function 41H = delete
- int 21h ; transfer to MS-DOS
- jc error ; jump if delete failed
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\7\FXN43H.ASM
-
- fname db 'C:\BACKUP\MYFILE.DAT',0
- .
- .
- .
- mov dx,seg fname ; DS:DX = address of filename
- mov ds,dx
- mov dx,offset fname
- mov cx,1 ; CX = attribute (read-only)
- mov al,1 ; AL = mode (0 = get, 1 = set)
- mov ah,43h ; Function 43H = get/set attr
- int 21h ; transfer to MS-DOS
- jc error ; jump if set attrib. failed
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\7\FXN45H.ASM
-
- fhandle dw ? ; handle from previous open
-
- .
- .
- .
- ; duplicate the handle...
- mov bx,fhandle ; BX = handle for file
- mov ah,45h ; Function 45H = dup handle
- int 21h ; transfer to MS-DOS
- jc error ; jump if function call failed
-
- ; now close the new handle...
- mov bx,ax ; BX = duplicated handle
- mov ah,3eh ; Function 3EH = close
- int 21h ; transfer to MS-DOS
- jc error ; jump if close failed
- mov bx,fhandle ; replace closed handle with active handle
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\7\FXN56H.ASM
-
- file1 db '\WORK\MYFILE.DAT',0
- file2 db '\BACKUP\MYFILE.OLD',0
- .
- .
- .
- mov dx,seg file1 ; DS:DX = old filename
- mov ds,dx
- mov es,dx
- mov dx,offset file1
- mov di,offset file2 ; ES:DI = new filename
- mov ah,56h ; Function 56H = rename
- int 21h ; transfer to MS-DOS
- jc error ; jump if rename failed
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\7\FXN5AH.ASM
-
- fname db 'C:\TEMP\' ; generated ASCIIZ filename
- db 13 dup (0) ; is appended by MS-DOS
-
- fhandle dw ?
- .
- .
- .
- mov dx,seg fname ; DS:DX = address of
- mov ds,dx ; path for temporary file
- mov dx,offset fname
- xor cx,cx ; CX = normal attribute
- mov ah,5ah ; Function 5AH = create
- ; temporary file
- int 21h ; transfer to MS-DOS
- jc error ; jump if create failed
- mov fhandle,ax ; else save file handle
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\7\MYFILE.ASM
-
- file1 db 'MYFILE.DAT',0
- file2 db 'MYFILE.BAK',0
-
- handle1 dw ? ; handle for MYFILE.DAT
- handle2 dw ? ; handle for MYFILE.BAK
-
- buff db 512 dup (?) ; buffer for file I/O
- .
- .
- .
- ; open MYFILE.DAT...
- mov dx,seg file1 ; DS:DX = address of filename
- mov ds,dx
- mov dx,offset file1
- mov ax,3d00h ; Function 3DH = open (read-only)
- int 21h ; transfer to MS-DOS
- jc error ; jump if open failed
- mov handle1,ax ; save handle for file
-
- ; create MYFILE.BAK...
- mov dx,offset file2 ; DS:DX = address of filename
- mov cx,0 ; CX = normal attribute
- mov ah,3ch ; Function 3CH = create
- int 21h ; transfer to MS-DOS
- jc error ; jump if create failed
- mov handle2,ax ; save handle for file
-
- loop: ; read MYFILE.DAT
- mov dx,offset buff ; DS:DX = buffer address
- mov cx,512 ; CX = length to read
- mov bx,handle1 ; BX = handle for MYFILE.DAT
- mov ah,3fh ; Function 3FH = read
- int 21h ; transfer to MS-DOS
- jc error ; jump if read failed
- or ax,ax ; were any bytes read?
- jz done ; no, end of file reached
-
- ; write MYFILE.BAK
- mov dx,offset buff ; DS:DX = buffer address
- mov cx,ax ; CX = length to write
- mov bx,handle2 ; BX = handle for MYFILE.BAK
- mov ah,40h ; Function 40H = write
- int 21h ; transfer to MS-DOS
- jc error ; jump if write failed
- cmp ax,cx ; was write complete?
- jne error ; jump if disk full
- jmp loop ; continue to end of file
-
- done: ; now close files...
- mov bx,handle1 ; handle for MYFILE.DAT
- mov ah,3eh ; Function 3EH = close file
- int 21h ; transfer to MS-DOS
- jc error ; jump if close failed
-
- mov bx,handle2 ; handle for MYFILE.BAK
- mov ah,3eh ; Function 3EH = close file
- int 21h ; transfer to MS-DOS
- jc error ; jump if close failed
-
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\7\OPENFILE.ASM
-
- kbuf db 64,0,64 dup (0)
- prompt db 0dh,0ah,'Enter filename: $'
- myfcb db 37 dup (0)
-
- .
- .
- .
- ; display the prompt...
- mov dx,seg prompt ; DS:DX = prompt address
- mov ds,dx
- mov es,dx
- mov dx,offset prompt
- mov ah,09H ; Function 09H = print string
- int 21h ; transfer to MS-DOS
-
- ; now input filename...
- mov dx,offset kbuf ; DS:DX = buffer address
- mov ah,0ah ; Function 0AH = enter string
- int 21h ; transfer to MS-DOS
-
- ; parse filename into FCB...
- mov si,offset kbuf+2 ; DS:SI = address of filename
- mov di,offset myfcb ; ES:DI = address of fcb
- mov ax,2900h ; Function 29H = parse name
- int 21h ; transfer to MS-DOS
- or al,al ; jump if bad drive or
- jnz error ; wildcard characters in name
-
- ; try to open file...
- mov dx,offset myfcb ; DS:DX = FCB address
- mov ah,0fh ; Function 0FH = open file
- int 21h ; transfer to MS-DOS
- or al,al ; check status
- jz proceed ; jump if open successful
-
- ; else create file...
- mov dx,offset myfcb ; DS:DX = FCB address
- mov ah,16h ; Function 16H = create
- int 21h ; transfer to MS-DOS
- or al,al ; did create succeed?
- jnz error ; jump if create failed
-
- proceed:
- . ; file has been opened or
- . ; created, and FCB is valid
- . ; for read/write operations...
-
- \SAMPCODE\DOS_ENCY\7\POINTER1.ASM
-
- fhandle dw ? ; handle from previous open
- buff db 512 dup (?) ; buffer for data from file
-
- .
- .
- .
- ; position the file pointer...
- mov cx,0 ; CX = high part of file offset
- mov dx,32768 ; DX = low part of file offset
- mov bx,fhandle ; BX = handle for file
- mov al,0 ; AL = positioning mode
- mov ah,42h ; Function 42H = position
- int 21h ; transfer to MS-DOS
- jc error ; jump if function call failed
-
- ; now read 512 bytes from file
- mov dx,offset buff ; DS:DX = address of buffer
- mov cx,512 ; CX = length of 512 bytes
- mov bx,fhandle ; BX = handle for file
- mov ah,3fh ; Function 3FH = read
- int 21h ; transfer to MS-DOS
- jc error ; jump if read failed
- cmp ax,512 ; was 512 bytes read?
- jne error ; jump if partial rec. or EOF
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\7\POINTER2.ASM
-
- fhandle dw ? ; handle from previous open
-
- .
- .
- .
- ; position the file pointer
- ; to the end of file...
- mov cx,0 ; CX = high part of offset
- mov dx,0 ; DX = low part of offset
- mov bx,fhandle ; BX = handle for file
- mov al,2 ; AL = positioning mode
- mov ah,42h ; Function 42H = position
- int 21h ; transfer to MS-DOS
- jc error ; jump if function call failed
-
- ; if call succeeded, DX:AX
- ; now contains the file size
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\8
- \SAMPCODE\DOS_ENCY\8\DIRDUMP.C
-
- /* DIRDUMP.C */
-
- #define AllAttributes 0x3F /* bits set for all attributes */
-
- main()
- {
- static char CurrentDir[64];
- int ErrorCode;
- int FileCount = 0;
-
- struct
- {
- char reserved[21];
- char attrib;
- int time;
- int date;
- long size;
- char name[13];
- } DTA;
-
- /* display current directory name */
-
- ErrorCode = GetCurrentDir( CurrentDir );
- if( ErrorCode )
- {
- printf( "\nError %d: GetCurrentDir", ErrorCode );
- exit( 1 );
- }
-
- printf( "\nCurrent directory is \\%s", CurrentDir );
-
-
- /* display files and attributes */
-
- SetDTA( &DTA ); /* pass DTA to MS-DOS */
-
- ErrorCode = FindFirstFile( "*.*", AllAttributes );
-
- while( !ErrorCode )
- {
- printf( "\n%12s -- ", DTA.name );
- ShowAttributes( DTA.attrib );
- ++FileCount;
-
- ErrorCode = FindNextFile( );
- }
-
- /* display file count and exit */
-
- printf( "\nCurrent directory contains %d files\n", FileCount );
- return( 0 );
- }
-
-
- ShowAttributes( a )
- int a;
- {
- int i;
- int mask = 1;
-
- static char *AttribName[] =
- {
- "read-only ",
- "hidden ",
- "system ",
- "volume ",
- "subdirectory ",
- "archive "
- };
-
-
- for( i=0; i<6; i++ ) /* test each attribute bit */
- {
- if( a & mask )
- printf( AttribName[i] ); /* display a message if bit is set */
- mask = mask << 1;
- }
- }
-
- \SAMPCODE\DOS_ENCY\8\DIRS.ASM
-
- TITLE 'DIRS.ASM'
-
- ;
- ; Subroutines for DIRDUMP.C
- ;
-
-
- ARG1 EQU [bp + 4] ; stack frame addressing for C argume
- ARG2 EQU [bp + 6]
-
-
- _TEXT SEGMENT byte public 'CODE'
- ASSUME cs:_TEXT
-
- ;----------------------------------------------------------------------------
- ;
- ; void SetDTA( DTA );
- ; char *DTA;
- ;
- ;----------------------------------------------------------------------------
-
- PUBLIC _SetDTA
- _SetDTA PROC near
-
- push bp
- mov bp,sp
-
- mov dx,ARG1 ; DS:DX -> DTA
- mov ah,1Ah ; AH = INT 21H function number
- int 21h ; pass DTA to MS-DOS
-
- pop bp
- ret
-
- _SetDTA ENDP
-
- ;----------------------------------------------------------------------------
- ;
- ; int GetCurrentDir( *path ); /* returns error code */
- ; char *path; /* pointer to buffer to contain path
- ;
- ;----------------------------------------------------------------------------
-
- PUBLIC _GetCurrentDir
- _GetCurrentDir PROC near
-
- push bp
- mov bp,sp
- push si
-
- mov si,ARG1 ; DS:SI -> buffer
- xor dl,dl ; DL = 0 (default drive number)
- mov ah,47h ; AH = INT 21H function number
- int 21h ; call MS-DOS; AX = error code
- jc L01 ; jump if error
-
- xor ax,ax ; no error, return AX = 0
-
- L01: pop si
- pop bp
- ret
-
- _GetCurrentDir ENDP
-
- ;----------------------------------------------------------------------------
- ;
- ; int FindFirstFile( path, attribute ); /* returns error code */
- ; char *path;
- ; int attribute;
- ;
- ;----------------------------------------------------------------------------
-
- PUBLIC _FindFirstFile
- _FindFirstFile PROC near
-
- push bp
- mov bp,sp
-
- mov dx,ARG1 ; DS:DX -> path
- mov cx,ARG2 ; CX = attribute
- mov ah,4Eh ; AH = INT 21H function number
- int 21h ; call MS-DOS; AX = error code
- jc L02 ; jump if error
-
- xor ax,ax ; no error, return AX = 0
-
- L02: pop bp
- ret
-
- _FindFirstFile ENDP
-
- ;----------------------------------------------------------------------------
- ;
- ; int FindNextFile(); /* returns error code */
- ;
- ;----------------------------------------------------------------------------
-
- PUBLIC _FindNextFile
- _FindNextFile PROC near
-
- push bp
- mov bp,sp
-
- mov ah,4Fh ; AH = INT 21H function number
- int 21h ; call MS-DOS; AX = error code
- jc L03 ; jump if error
-
- xor ax,ax ; if no error, set AX = 0
-
- L03: pop bp
- ret
-
- _FindNextFile ENDP
-
- _TEXT ENDS
-
-
- _DATA SEGMENT word public 'DATA'
-
- CurrentDir DB 64 dup(?)
- DTA DB 64 dup(?)
-
- _DATA ENDS
-
- END
-
- \SAMPCODE\DOS_ENCY\8\VOLS.ASM
-
- TITLE 'VOLS.ASM'
-
- ;----------------------------------------------------------------------------
- ;
- ; C-callable routines for manipulating MS-DOS volume labels
- ; Note: These routines modify the current DTA address.
- ;
- ;----------------------------------------------------------------------------
-
- ARG1 EQU [bp + 4] ; stack frame addressing
-
- DGROUP GROUP _DATA
-
- _TEXT SEGMENT byte public 'CODE'
- ASSUME cs:_TEXT,ds:DGROUP
-
- ;----------------------------------------------------------------------------
- ;
- ; char *GetVolLabel(); /* returns pointer to volume label name */
- ;
- ;----------------------------------------------------------------------------
-
- PUBLIC _GetVolLabel
- _GetVolLabel PROC near
-
- push bp
- mov bp,sp
- push si
- push di
-
- call SetDTA ; pass DTA address to MS-DOS
- mov dx,offset DGROUP:ExtendedFCB
- mov ah,11h ; AH = INT 21H function number
- int 21h ; Search for First Entry
- test al,al
- jnz L01
- ; label found so make a copy
- mov si,offset DGROUP:DTA + 8
- mov di,offset DGROUP:VolLabel
- call CopyName
- mov ax,offset DGROUP:VolLabel ; return the copy's address
- jmp short L02
-
- L01: xor ax,ax ; no label, return 0 (null pointer)
-
- L02: pop di
- pop si
- pop bp
- ret
-
- _GetVolLabel ENDP
-
- ;----------------------------------------------------------------------------
- ;
- ; int RenameVolLabel( label ); /* returns error code */
- ; char *label; /* pointer to new volume label name *
- ;
- ;----------------------------------------------------------------------------
-
- PUBLIC _RenameVolLabel
- _RenameVolLabel PROC near
-
- push bp
- mov bp,sp
- push si
- push di
-
- mov si,offset DGROUP:VolLabel ; DS:SI -> old volume name
- mov di,offset DGROUP:Name1
- call CopyName ; copy old name to FCB
-
- mov si,ARG1
- mov di,offset DGROUP:Name2
- call CopyName ; copy new name into FCB
-
- mov dx,offset DGROUP:ExtendedFCB ; DS:DX -> FCB
- mov ah,17h ; AH = INT 21H function number
- int 21h ; rename
- xor ah,ah ; AX = 00H (success) or 0FFH (failure
-
- pop di ; restore registers and return
- pop si
- pop bp
- ret
-
- _RenameVolLabel ENDP
-
- ;----------------------------------------------------------------------------
- ;
- ; int NewVolLabel( label ); /* returns error code */
- ; char *label; /* pointer to new volume label name *
- ;
- ;----------------------------------------------------------------------------
-
- PUBLIC _NewVolLabel
- _NewVolLabel PROC near
-
- push bp
- mov bp,sp
- push si
- push di
-
- mov si,ARG1
- mov di,offset DGROUP:Name1
- call CopyName ; copy new name to FCB
-
- mov dx,offset DGROUP:ExtendedFCB
- mov ah,16h ; AH = INT 21H function number
- int 21h ; create directory entry
- xor ah,ah ; AX = 00H (success) or 0FFH (failure
-
- pop di ; restore registers and return
- pop si
- pop bp
- ret
-
- _NewVolLabel ENDP
-
- ;----------------------------------------------------------------------------
- ;
- ; int DeleteVolLabel(); /* returns error code */
- ;
- ;----------------------------------------------------------------------------
-
- PUBLIC _DeleteVolLabel
- _DeleteVolLabel PROC near
-
- push bp
- mov bp,sp
- push si
- push di
-
- mov si,offset DGROUP:VolLabel
- mov di,offset DGROUP:Name1
- call CopyName ; copy current volume name to FCB
-
- mov dx,offset DGROUP:ExtendedFCB
- mov ah,13h ; AH = INT 21H function number
- int 21h ; delete directory entry
- xor ah,ah ; AX = 0 (success) or 0FFH (failure)
-
- pop di ; restore registers and return
- pop si
- pop bp
- ret
-
- _DeleteVolLabel ENDP
-
- ;----------------------------------------------------------------------------
- ;
- ; miscellaneous subroutines
- ;
- ;----------------------------------------------------------------------------
-
- SetDTA PROC near
-
- push ax ; preserve registers used
- push dx
-
- mov dx,offset DGROUP:DTA ; DS:DX -> DTA
- mov ah,1Ah ; AH = INT 21H function number
- int 21h ; set DTA
-
- pop dx ; restore registers and return
- pop ax
- ret
-
- SetDTA ENDP
-
-
- CopyName PROC near ; Caller: SI -> ASCIIZ source
- ; DI -> destination
- push ds
- pop es ; ES = DGROUP
- mov cx,11 ; length of name field
-
- L11: lodsb ; copy new name into FCB ..
- test al,al
- jz L12 ; .. until null character is reached
- stosb
- loop L11
-
- L12: mov al,' ' ; pad new name with blanks
- rep stosb
- ret
-
- CopyName ENDP
-
- _TEXT ENDS
-
-
- _DATA SEGMENT word public 'DATA'
-
- VolLabel DB 11 dup(0),0
-
- ExtendedFCB DB 0FFh ; must be 0FFH for extended FCB
- DB 5 dup(0) ; (reserved)
- DB 1000b ; attribute byte (bit 3 = 1)
- DB 0 ; default drive ID
- Name1 DB 11 dup('?') ; global wildcard name
- DB 5 dup(0) ; (unused)
- Name2 DB 11 dup(0) ; second name (for renaming entry)
- DB 9 dup(0) ; (unused)
-
- DTA DB 64 dup(0)
-
- _DATA ENDS
-
- END
-
- \SAMPCODE\DOS_ENCY\9
- \SAMPCODE\DOS_ENCY\9\FIG9_2.ASM
-
- .
- .
- .
- _TEXT segment para public 'CODE'
-
- org 100h
-
- assume cs:_TEXT,ds:_TEXT,es:_TEXT,ss:_TEXT
-
- main proc near ; entry point from MS-DOS
- ; CS = DS = ES = SS = PSP
-
- ; first move our stack
- mov sp,offset stk ; to a safe place...
-
- ; now release extra memory...
- mov bx,offset stk ; calculate paragraphs to keep
- mov cl,4 ; (divide offset of end of
- shr bx,cl ; program by 16 and round up)
- inc bx
- mov ah,4ah ; Fxn 4AH = resize mem block
- int 21h ; transfer to MS-DOS
- jc error ; jump if resize failed
- .
- . ; otherwise go on with work...
- .
-
- main endp
-
- .
- .
- .
-
- dw 64 dup (?)
- stk equ $ ; base of new stack area
-
- _TEXT ends
-
- end main ; defines program entry point
-
- \SAMPCODE\DOS_ENCY\9\FIG9_3.ASM
-
- .
- .
- .
-
- _TEXT segment word public 'CODE' ; executable code segment
-
- assume cs:_TEXT,ds:_DATA,ss:_STACK
-
- main proc far ; entry point from MS-DOS
- ; CS = _TEXT segment,
- ; DS = ES = PSP
-
- mov ax,_DATA ; set DS = our data segment
- mov ds,ax
-
- ; give back extra memory...
- mov ax,es ; let AX = segment of PSP base
- mov bx,ss ; and BX = segment of stack base
- sub bx,ax ; reserve seg stack - seg psp
- add bx,stksize/16 ; plus paragraphs of stack
- inc bx ; round up
- mov ah,4ah ; Fxn 4AH = resize memory block
- int 21h
- jc error
-
- main endp
-
- _TEXT ends
-
-
- _DATA segment word public 'DATA' ; static & variable data
-
- .
- .
- .
-
- _DATA ends
-
-
- STACK segment para stack 'STACK'
-
- db stksize dup (?)
-
- STACK ends
-
- end main ; defines program entry point
-
- \SAMPCODE\DOS_ENCY\9\FIG9_4.ASM
-
- .
- .
- .
- mov bx,800h ; 800H paragraphs = 32 KB
- mov ah,48h ; Fxn 48H = allocate block
- int 21h ; transfer to MS-DOS
- jc error ; jump if allocation failed
- mov bufseg,ax ; save segment of block
-
- ; open working file...
- mov dx,offset file1 ; DS:DX = filename address
- mov ax,3d00h ; Fxn 3DH = open, read only
- int 21h ; transfer to MS-DOS
- jc error ; jump if open failed
- mov handle1,ax ; save handle for work file
-
- ; create backup file...
- mov dx,offset file2 ; DS:DX = filename address
- mov cx,0 ; CX = attribute (normal)
- mov ah,3ch ; Fxn 3CH = create file
- int 21h ; transfer to MS-DOS
- jc error ; jump if create failed
- mov handle2,ax ; save handle for backup file
-
- push ds ; set ES = our data segment
- pop es
- mov ds,bufseg ; set DS:DX = allocated block
- xor dx,dx
-
- assume ds:NOTHING,es:_DATA ; tell assembler
-
- next: ; read working file...
- mov bx,handle1 ; handle for work file
- mov cx,8000h ; try to read 32 KB
- mov ah,3fh ; Fxn 3FH = read
- int 21h ; transfer to MS-DOS
- jc error ; jump if read failed
- or ax,ax ; was end of file reached?
- jz done ; yes, exit this loop
-
- ; now write backup file...
- mov cx,ax ; set write length = read length
- mov bx,handle2 ; handle for backup file
- mov ah,40h ; Fxn 40H = write
- int 21h ; transfer to MS-DOS
- jc error ; jump if write failed
- cmp ax,cx ; was write complete?
- jne error ; no, disk must be full
- jmp next ; transfer another record
-
- done: push es ; restore DS = data segment
- pop ds
-
- assume ds:_DATA,es:NOTHING ; tell assembler
-
- ; release allocated block...
- mov es,bufseg ; segment base of block
- mov ah,49h ; Fxn 49H = release block
- int 21h ; transfer to MS-DOS
- jc error ; (should never fail)
-
- ; now close backup file...
- mov bx,handle2 ; handle for backup file
- mov ah,3eh ; Fxn 3EH = close
- int 21h ; transfer to MS-DOS
- jc error ; jump if close failed
- .
- .
- .
-
- file1 db 'MYFILE.DAT',0 ; name of working file
- file2 db 'MYFILE.BAK',0 ; name of backup file
-
- handle1 dw ? ; handle for working file
- handle2 dw ? ; handle for backup file
- bufseg dw ? ; segment of allocated block
-
- \SAMPCODE\DOS_ENCY\9\FIG9_6.ASM
-
- .
- .
- .
- ; attempt to "open" EMM...
- mov dx,seg emm_name ; DS:DX = address of name
- mov ds,dx ; of EMM
- mov dx,offset emm_name
- mov ax,3d00h ; Fxn 3DH, Mode = 00H
- ; = open, read-only
- int 21h ; transfer to MS-DOS
- jc error ; jump if open failed
-
- ; open succeeded, make sure
- ; it was not a file...
- mov bx,ax ; BX = handle from open
- mov ax,4400h ; Fxn 44H Subfxn 00H
- ; = IOCTL Get Device Information
- int 21h ; transfer to MS-DOS
- jc error ; jump if IOCTL call failed
- and dx,80h ; Bit 7 = 1 if character device
- jz error ; jump if it was a file
-
- ; EMM is present, make sure
- ; it is available...
- ; (BX still contains handle)
- mov ax,4407h ; Fxn 44H Subfxn 07H
- ; = IOCTL Get Output Status
- int 21h ; transfer to MS-DOS
- jc error ; jump if IOCTL call failed
- or al,al ; test device status
- jz error ; if AL = 0 EMM is not available
-
- ; now close handle ...
- ; (BX still contains handle)
- mov ah,3eh ; Fxn 3EH = Close
- int 21h ; transfer to MS-DOS
- jc error ; jump if close failed
- .
- .
- .
-
- emm_name db 'EMMXXXX0',0 ; guaranteed device name for EMM
-
- \SAMPCODE\DOS_ENCY\9\FIG9_7.ASM
-
- emm_int equ 67h ; EMM software interrupt
-
- .
- .
- .
- ; first fetch contents of
- ; EMM interrupt vector...
- mov al,emm_int ; AL = EMM int number
- mov ah,35h ; Fxn 35H = get vector
- int 21h ; transfer to MS-DOS
- ; now ES:BX = handler address
-
- ; assume ES:0000 points
- ; to base of the EMM...
- mov di,10 ; ES:DI = address of name
- ; field in device header
- mov si,seg emm_name ; DS:SI = address of
- mov ds,si ; expected EMM driver name
- mov si,offset emm_name
- mov cx,8 ; length of name field
- cld
- repz cmpsb ; compare names...
- jnz error ; jump if driver absent
- .
- .
- .
-
-
- emm_name db 'EMMXXXX0' ; guaranteed device name for EMM
-
- \SAMPCODE\DOS_ENCY\9\FIG9_8.ASM
-
- .
- .
- .
- mov ah,40h ; test EMM status
- int 67h
- or ah,ah
- jnz error ; jump if bad status from EMM
-
- mov ah,46h ; check EMM version
- int 67h
- or ah,ah
- jnz error ; jump if couldn't get version
- cmp al,30h ; make sure at least ver. 3.0
- jb error ; jump if wrong EMM version
-
- mov ah,41h ; get page frame segment
- int 67h
- or ah,ah
- jnz error ; jump if failed to get frame
- mov page_frame,bx ; save segment of page frame
-
- mov ah,42h ; get no. of available pages
- int 67h
- or ah,ah
- jnz error ; jump if get pages error
- mov total_pages,dx ; save total EMM pages
- mov avail_pages,bx ; save available EMM pages
- or bx,bx
- jz error ; abort if no pages available
-
- mov ah,43h ; try to allocate EMM pages
- mov bx,needed_pages
- int 67h ; if allocation is successful
- or ah,ah
- jnz error ; jump if allocation failed
-
- mov emm_handle,dx ; save handle for allocated pages
-
- .
- . ; now we are ready for other
- . ; processing using EMM pages
- .
- ; map in EMM memory page...
- mov bx,log_page ; BX <- EMM logical page number
- mov al,phys_page ; AL <- EMM physical page (0-3)
- mov dx,emm_handle ; EMM handle for our pages
- mov ah,44h ; Fxn 44H = map EMM page
- int 67h
- or ah,ah
- jnz error ; jump if mapping error
-
- .
- .
- .
- ; program ready to terminate,
- ; give up allocated EMM pages...
- mov dx,emm_handle ; handle for our pages
- mov ah,45h ; EMM Fxn 45H = release pages
- int 67h
- or ah,ah
- jnz error ; jump if release failed
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\APP_A
- \SAMPCODE\DOS_ENCY\APP_A\6501_BUF.ASM
-
- buffer db 1 ; Information ID code
- dw 38 ; Length of following buffer
- dw 1 ; Country ID (USA)
- dw 437 ; Code-page number
- dw 0 ; Date format
- db '$',0,0,0,0 ; Currency symbol
- db ',',0 ; Thousands separator
- db '.',0 ; Decimal separator
- db '-',0 ; Date separator
- db ':',0 ; Time separator
- db 0 ; Currency format flags
- db 2 ; Digits in currency
- db 0 ; Time format
- dd 026ah:176ch ; Monocase routine entry point
- db ',',0 ; Data list separator
- db 10 dup (0) ; Reserved
-
- \SAMPCODE\DOS_ENCY\APP_A\6502_BUF.ASM
-
- buffer db 2 ; Information ID code
- dw 0204h ; Offset of uppercase table
- dw 1140h ; Segment of uppercase table
-
- \SAMPCODE\DOS_ENCY\APP_A\FXN6501H.ASM
-
- buffer db 41 dup (0) ; Receives country information.
- .
- .
- .
- mov ax,6501h ; Function = get extended info.
- mov bx,437 ; Code page.
- mov cx,41 ; Length of buffer.
- mov dx,-1 ; Default country.
- mov di,seg buffer ; ES:DI = buffer address.
- mov es,di
- mov di,offset buffer
- int 21h ; Transfer to MS-DOS.
- jc error ; Jump if function failed.
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\APP_A\FXN6502H.ASM
-
- buffer db 5 dup (0) ; Receives pointer information.
- .
- .
- .
- mov ax,6502h ; Function = get pointer to
- ; uppercase table.
- mov bx,437 ; Code page.
- mov cx,5 ; Length of buffer.
- mov dx,-1 ; Default country.
- mov di,seg buffer ; ES:DI = buffer address.
- mov es,di
- mov di,offset buffer
- int 21h ; Transfer to MS-DOS.
- jc error ; Jump if function failed.
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\APP_A\FXN67H.ASM
-
- .
- .
- .
- mov ah,67h ; Function 67H = set handle count.
- mov bx,30 ; Maximum number of handles.
- int 21h ; Transfer to MS-DOS.
- jc error ; Jump if function failed.
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\APP_A\FXN68H.ASM
-
- fname db 'MYFILE.DAT',0 ; ASCIIZ filename.
- fhandle dw ? ; Handle from Open operation.
- .
- .
- .
- mov ah,68h ; Function 68H = commit file.
- mov bx,fhandle ; Handle from previous open.
- int 21h ; Transfer to MS-DOS.
- jc error ; Jump if function failed.
- .
- .
- .
-
- \SAMPCODE\DOS_ENCY\APP_L
- \SAMPCODE\DOS_ENCY\APP_L\BIN2HEX.BAS
-
- 'Binary-to-Hex file conversion utility.
- 'Requires Microsoft QuickBASIC version 3.0 or later.
-
- DEFINT A-Z ' All variables are integers
- ' unless otherwise declared.
- CONST FALSE = 0 ' Value of logical FALSE.
- CONST TRUE = NOT FALSE ' Value of logical TRUE.
-
- DEF FNHXB$(X) = RIGHT$(HEX$(&H100 + X), 2) ' Return 2-digit hex value for
- DEF FNHXW$(X!) = RIGHT$("000" + HEX$(X!), 4) ' Return 4-digit hex value for
- DEF FNMOD(X, Y) = X! - INT(X!/Y) * Y ' X! MOD Y (the MOD operation i
- ' only for integers).
- CONST SRCCNL = 1 ' Source (.BIN) file channel.
- CONST TGTCNL = 2 ' Target (.HEX) file channel.
-
- LINE INPUT "Enter full name of source .BIN file : ";SRCFIL$
- OPEN SCRCFIL$ FOR INPUT AS SRCCNL ' Test for source (.BIN) file.
- SRCSIZ! = LOF(SRCCNL) ' Save file's size.
- CLOSE SRCCNL
- IF (SRCSIZ! > 65536) THEN ' Reject if file exceeds 64 KB.
- PRINT "Cannot convert file larger than 64 KB."
- END
- END IF
-
- LINE INPUT "Enter full name of target .HEX file : ";TGTFIL$
- OPEN TGTFIL$ FOR OUTPUT AS TGTCNL ' Test target (.HEX) filename.
- CLOSE TGTCNL
-
- DO
- LINE INPUT "Enter starting address of .BIN file in HEX : ";L$
- ADRBGN! = VAL("&H" + L$) ' Convert ASCII HEX address val
- ' to binary value.
- IF (ADRBGN! < 0) THEN ' HEX values 8000-FFFFH convert
- ADRBGN! = 65536 + ADRBGN! ' to negative values.
- END IF
- ADREND! = ADRBGN! + SRCSIZ! - 1 ' Calculate resulting end addre
- IF (ADREND! > 65535) THEN ' Reject if address exceeds FFF
- PRINT "Entered start address causes end address to exceed FFFFH."
- END IF
- LOOP UNTIL (ADRFLD! >= 0) AND (ADRFLD! <= 65535) AND (ADREND! <= 65535)
-
- DO
- LINE INPUT "Enter byte count for each record in HEX : ";L$
- SRCRLN = VAL("&H" + L$) ' Convert ASCII HEX max record
- ' length value to binary value.
- IF (SRCRLN < 0) THEN ' HEX values 8000H-FFFFH conver
- SRCRLN = 65536 + SRCRLN ' to negative values.
- END IF
- LOOP UNTIL (SRCRLN > 0) AND (SRCRLN < 256) ' Ask again if not 1-255.
-
- OPEN SRCFIL$ AS SRCCNL LEN = SRCRLN ' Reopen source for block I/O.
- FIELD#SRCCNL,SRCRLN AS SRCBLK$
- OPEN TGTFIL$ FOR OUTPUT AS TGTCNL ' Reopen target for text output
- SRCREC = 0 ' Starting source block # minus
-
- FOR ADRFLD! = ADRBGN! TO ADREND! STEP SRCRLN ' Convert one block per loop.
- SRCREC = SRCREC + 1 ' Next source block.
- GET SRCCNL,SRCREC ' Read the source block.
- IF (ADRFLD! + SRCRLN > ADREND!) THEN ' If last block less than full
- BLK$=LEFT$(SRCBLK$,ADREND!-ADRFLD!+1) ' size: trim it.
- ELSE ' Else:
- BLK$ = SRCBLK$ ' Use full block.
- END IF
-
- PRINT#TGTCNL, ":"; ' Write record mark.
-
- PRINT#TGTCNL, FNHXB$(LEN(BLK$)); ' Write data field size.
- CHKSUM = LEN(BLK$) ' Initialize checksum accumulat
- ' with first value.
- PRINT#TGTCNL,FNHXW$(ADRFLD!); ' Write record's load address.
-
- ' The following "AND &HFF" operations limit CHKSUM to a byte value.
- CHKSUM = CHKSUM + INT(ADRFLD!/256) AND &HFF ' Add hi byte of adrs to cs
- CHKSUM = CHKSUM + FNMOD(ADRFLD!,256) AND &HFF ' Add lo byte of adrs to cs
-
- PRINT#TGTCNL,FNHXB$(0); ' Write record type.
-
- ' Don't bother to add record type byte to checksum since it's 0.
- FOR IDX = 1 TO LEN(BLK$) ' Write all bytes.
- PRINT#TGTCNL,FNHXB$(ASC(MID$(BLK$,IDX,1))); ' Write next byte.
- CHKSUM = CHKSUM + ASC(MID$(BLK$,IDX,1)) AND &HFF ' Incl byte in csum.
- NEXT IDX
-
- CHKSUM = 0 - CHKSUM AND &HFF ' Negate checksum then limit
- ' to byte value.
- PRINT #TGTCNL,FNHXB$(CHKSUM) ' End record with checksum.
-
- NEXT ADRFLD!
-
- PRINT#TGTCNL, ":00000001FF" ' Write end-of-file record.
-
- CLOSE TGTCNL ' Close target file.
- CLOSE SRCCNL ' Close source file.
-
- END
-
- \SAMPCODE\DOS_ENCY\APP_N
- \SAMPCODE\DOS_ENCY\APP_N\OBJDUMP.C
-
- /****************************************************************************
- *
- * OBJDUMP.C -- display contents of an object file
- *
- *
- * Compile: msc objdump; (Microsoft C version 4.0 or later)
- * Link: link objdump;
- * Execute: objdump <filename>
- *
- *****************************************************************************
-
- #include <fcntl.h>
-
- #define TRUE 1
- #define FALSE 0
-
- main( argc, argv )
- int argc;
- char **argv;
- {
- unsigned char CurrentByte;
- int ObjFileHandle;
- int CurrentLineLength; /* length of output line *
- int ObjRecordNumber = 0;
- int ObjRecordLength;
- int ObjRecordOffset = 0; /* offset into current object record *
- char ASCIIEquiv[17];
- char FormatString[24];
- char *ObjRecordName();
- char *memset();
-
-
- /* open the object file */
-
- ObjFileHandle = open( argv[1],O_BINARY );
-
- if( ObjFileHandle == -1 )
- {
- printf( "\nCan't open object file\n" );
- exit( 1 );
- }
-
- /* process the object file character by character */
-
- while( read( ObjFileHandle, &CurrentByte, 1 ) )
- {
- switch( ObjRecordOffset ) /* action depends on offset into record *
- {
- case(0): /* start of object record *
- printf( "\n\nRecord %d: %02Xh %s",
- ++ObjRecordNumber, CurrentByte, ObjRecordName(CurrentByte) );
- printf( "\n%02X ", CurrentByte );
- ++ObjRecordOffset;
- break;
-
- case(1): /* first byte of length field *
- ObjRecordLength = CurrentByte;
- ++ObjRecordOffset;
- break;
-
- case(2): /* second byte of length field *
- ObjRecordLength += CurrentByte << 8; /* compute record length *
- printf( "%04Xh ", ObjRecordLength ); /* show length *
- CurrentLineLength = 0;
- memset( ASCIIEquiv,'\0', 17 ); /* zero this string *
- ++ObjRecordOffset;
- break;
-
- default: /* remaining bytes in object record *
- printf( "%02X ", CurrentByte ); /* hex *
-
- if( CurrentByte < 0x20 || CurrentByte > 0x7F ) /* ASCII *
- CurrentByte = '.';
- ASCIIEquiv[CurrentLineLength++] = CurrentByte;
-
- if( CurrentLineLength == 16 || /* if end of output line ... *
- ObjRecordOffset == ObjRecordLength+2 )
- { /* ... display it *
- sprintf( FormatString, "%%%ds%%s\n ",
- 3*(16-CurrentLineLength)+2 );
- printf( FormatString, " ", ASCIIEquiv );
- memset( ASCIIEquiv, '\0', 17 );
- CurrentLineLength = 0;
- }
-
- if( ++ObjRecordOffset == ObjRecordLength+3 ) /* if done .. */
- ObjRecordOffset = 0; /* .. process another record */
- break;
- }
- }
-
- if( CurrentLineLength ) /* display remainder of last output line *
- printf( " %s", ASCIIEquiv );
-
- close( ObjFileHandle );
-
- printf( "\n%d object records\n", ObjRecordNumber );
-
- return( 0 );
- }
-
-
- char *ObjRecordName( n ) /* return object record name *
- int n; /* n = record type *
- {
- int i;
-
- static struct
- {
- int RecordNumber;
- char *RecordName;
- } RecordStruct[] =
- {
- 0x80,"THEADR",
- 0x88,"COMENT",
- 0x8A,"MODEND",
- 0x8C,"EXTDEF",
- 0x8E,"TYPDEF",
- 0x90,"PUBDEF",
- 0x94,"LINNUM",
- 0x96,"LNAMES",
- 0x98,"SEGDEF",
- 0x9A,"GRPDEF",
- 0x9C,"FIXUPP",
- 0xA0,"LEDATA",
- 0xA2,"LIDATA",
- 0xB0,"COMDEF",
- 0x00,"******"
- };
-
- int RecordTableSize = sizeof(RecordStruct)/sizeof(RecordStruct[0
-
-
- for( i=0; i<RecordTableSize-1; i++ ) /* scan table for name *
- if ( RecordStruct[i].RecordNumber == n )
- break;
-
- return( RecordStruct[i].RecordName );
- }
-
- \SAMPCODE\DOS_ENCY\SECTION5
- \SAMPCODE\DOS_ENCY\SECTION5\TESTCM.C
-
- main()
- {
- printf("The sum is %d",addnums(12,33));
- }
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN01H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 01H: Character Input with Echo ;
- ; ;
- ; int read_kbd_echo() ;
- ; ;
- ; Returns a character from standard input ;
- ; after sending it to standard output. ;
- ; ;
- ;************************************************************;
-
- cProc read_kbd_echo,PUBLIC
- cBegin
- mov ah,01h ; Set function code.
- int 21h ; Wait for character.
- mov ah,0 ; Character is in AL, so clear high
- ; byte.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN02H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 02H: Character Output ;
- ; ;
- ; int disp_ch(c) ;
- ; char c; ;
- ; ;
- ; Returns 0. ;
- ; ;
- ;************************************************************;
-
- cProc disp_ch,PUBLIC
- parmB c
- cBegin
- mov dl,c ; Get character into DL.
- mov ah,02h ; Set function code.
- int 21h ; Send character.
- xor ax,ax ; Return 0.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN03H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 03H: Auxiliary Input ;
- ; ;
- ; int aux_in() ;
- ; ;
- ; Returns next character from AUX device. ;
- ; ;
- ;************************************************************;
-
- cProc aux_in,PUBLIC
- cBegin
- mov ah,03h ; Set function code.
- int 21h ; Wait for character from AUX.
- mov ah,0 ; Character is in AL
- ; so clear high byte.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN04H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 04H: Auxiliary Output ;
- ; ;
- ; int aux_out(c) ;
- ; char c; ;
- ; ;
- ; Returns 0. ;
- ; ;
- ;************************************************************;
-
- cProc aux_out,PUBLIC
- parmB c
- cBegin
- mov dl,c ; Get character into DL.
- mov ah,04h ; Set function code.
- int 21h ; Write character to AUX.
- xor ax,ax ; Return 0.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN05H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 05H: Print Character ;
- ; ;
- ; int print_ch(c) ;
- ; char c; ;
- ; ;
- ; Returns 0. ;
- ; ;
- ;************************************************************;
-
- cProc print_ch,PUBLIC
- parmB c
- cBegin
- mov dl,c ; Get character into DL.
- mov ah,05h ; Set function code.
- int 21h ; Write character to standard printer.
- xor ax,ax ; Return 0.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN06H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 06H: Direct Console I/O ;
- ; ;
- ; int con_io(c) ;
- ; char c; ;
- ; ;
- ; Returns meaningless data if c is not 0FFH, ;
- ; otherwise returns next character from ;
- ; standard input. ;
- ; ;
- ;************************************************************;
-
- cProc con_io,PUBLIC
- parmB c
- cBegin
- mov dl,c ; Get character into DL.
- mov ah,06h ; Set function code.
- int 21h ; This function does NOT wait in
- ; input case (c = 0FFH)!
- mov ah,0 ; Return the contents of AL.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN07H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 07H: Unfiltered Character Input ;
- ; Without Echo ;
- ; ;
- ; int con_in() ;
- ; ;
- ; Returns next character from standard input. ;
- ; ;
- ;************************************************************;
-
- cProc con_in,PUBLIC
- cBegin
- mov ah,07h ; Set function code.
- int 21h ; Wait for character, no echo.
- mov ah,0 ; Clear high byte.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN08H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 08H: Unfiltered Character Input Without Echo ;
- ; ;
- ; int read_kbd() ;
- ; ;
- ; Returns next character from standard input. ;
- ; ;
- ;************************************************************;
-
- cProc read_kbd,PUBLIC
- cBegin
- mov ah,08h ; Set function code.
- int 21h ; Wait for character, no echo.
- mov ah,0 ; Clear high byte.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN09H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 09H: Display String ;
- ; ;
- ; int disp_str(pstr) ;
- ; char *pstr; ;
- ; ;
- ; Returns 0. ;
- ; ;
- ;************************************************************;
-
- cProc disp_str,PUBLIC,<ds,di>
- parmDP pstr
- cBegin
- loadDP ds,dx,pstr ; DS:DX = pointer to string.
- mov ax,0900h ; Prepare to write dollar-terminated
- ; string to standard output, but
- ; first replace the 0 at the end of
- ; the string with '$'.
- push ds ; Set ES equal to DS.
- pop es ; (MS-C does not require ES to be
- ; saved.)
- mov di,dx ; ES:DI points at string.
- mov cx,0ffffh ; Allow string to be 64KB long.
- repne scasb ; Look for 0 at end of string.
- dec di ; Scasb search always goes 1 byte too
- ; far.
- mov byte ptr [di],'$' ; Replace 0 with dollar sign.
- int 21h ; Have MS-DOS print string.
- mov [di],al ; Restore 0 terminator.
- xor ax,ax ; Return 0.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN0AH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 0AH: Buffered Keyboard Input ;
- ; ;
- ; int read_str(pbuf,len) ;
- ; char *pbuf; ;
- ; int len; ;
- ; ;
- ; Returns number of bytes read into buffer. ;
- ; ;
- ; Note: pbuf must be at least len+3 bytes long. ;
- ; ;
- ;************************************************************;
-
- cProc read_str,PUBLIC,<ds,di>
- parmDP pbuf
- parmB len
- cBegin
- loadDP ds,dx,pbuf ; DS:DX = pointer to buffer.
- mov al,len ; AL = len.
- inc al ; Add 1 to allow for CR in buf.
- mov di,dx
- mov [di],al ; Store max length into buffer.
- mov ah,0ah ; Set function code.
- int 21h ; Ask MS-DOS to read string.
- mov al,[di+1] ; Return number of characters read.
- mov ah,0
- mov bx,ax
- mov [bx+di+2],ah ; Store 0 at end of buffer.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN0BH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 0BH: Check Keyboard Status ;
- ; ;
- ; int key_ready() ;
- ; ;
- ; Returns 1 if key is ready, 0 if not. ;
- ; ;
- ;************************************************************;
-
- cProc key_ready,PUBLIC
- cBegin
- mov ah,0bh ; Set function code.
- int 21h ; Ask MS-DOS if key is available.
- and ax,0001h ; Keep least significant bit only.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN0CH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 0CH: Flush Buffer, Read Keyboard ;
- ; ;
- ; int flush_kbd() ;
- ; ;
- ; Returns 0. ;
- ; ;
- ;************************************************************;
-
- cProc flush_kbd,PUBLIC
- cBegin
- mov ax,0c00h ; Just flush type-ahead buffer.
- int 21h ; Call MS-DOS.
- xor ax,ax ; Return 0.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN0DH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 0DH: Disk Reset ;
- ; ;
- ; int reset_disk() ;
- ; ;
- ; Returns 0. ;
- ; ;
- ;************************************************************;
-
- cProc reset_disk,PUBLIC
- cBegin
- mov ah,0dh ; Set function code.
- int 21h ; Ask MS-DOS to write all dirty file
- ; buffers to the disk.
- xor ax,ax ; Return 0.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN0EH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 0EH: Select Disk ;
- ; ;
- ; int select_drive(drive_ltr) ;
- ; char drive_ltr; ;
- ; ;
- ; Returns number of logical drives present in system. ;
- ; ;
- ;************************************************************;
-
- cProc select_drive,PUBLIC
- parmB disk_ltr
- cBegin
- mov dl,disk_ltr ; Get new drive letter.
- and dl,not 20h ; Make sure letter is uppercase.
- sub dl,'A' ; Convert drive letter to number,
- ; 'A' = 0, 'B' = 1, etc.
- mov ah,0eh ; Set function code.
- int 21h ; Ask MS-DOS to set default drive.
- cbw ; Clear high byte of return value.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN0FH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 0FH: Open File, FCB-based ;
- ; ;
- ; int FCB_open(uXFCB,recsize) ;
- ; char *uXFCB; ;
- ; int recsize; ;
- ; ;
- ; Returns 0 if file opened OK, otherwise returns -1. ;
- ; ;
- ; Note: uXFCB must have the drive and filename ;
- ; fields (bytes 07H through 12H) and the extension ;
- ; flag (byte 00H) set before the call to FCB_open ;
- ; (see Function 29H). ;
- ; ;
- ;************************************************************;
-
- cProc FCB_open,PUBLIC,ds
- parmDP puXFCB
- parmW recsize
- cBegin
- loadDP ds,dx,puXFCB ; Pointer to unopened extended FCB.
- mov ah,0fh ; Ask MS-DOS to open an existing file.
- int 21h
- add dx,7 ; Advance pointer to start of regular
- ; FCB.
- mov bx,dx ; BX = FCB pointer.
- mov dx,recsize ; Get record size parameter.
- mov [bx+0eh],dx ; Store record size in FCB.
- xor dx,dx
- mov [bx+20h],dl ; Set current-record
- mov [bx+21h],dx ; and relative-record
- mov [bx+23h],dx ; fields to 0.
- cbw ; Set return value to 0 or -1.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN10H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 10H: Close file, FCB-based ;
- ; ;
- ; int FCB_close(oXFCB) ;
- ; char *oXFCB; ;
- ; ;
- ; Returns 0 if file closed OK, otherwise ;
- ; returns -1. ;
- ; ;
- ;************************************************************;
-
- cProc FCB_close,PUBLIC,ds
- parmDP poXFCB
- cBegin
- loadDP ds,dx,poXFCB ; Pointer to opened extended FCB.
- mov ah,10h ; Ask MS-DOS to close file.
- int 21h
- cbw ; Set return value to 0 or -1.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN11H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 11H: Find First File, FCB-based ;
- ; ;
- ; int FCB_first(puXFCB,attrib) ;
- ; char *puXFCB; ;
- ; char attrib; ;
- ; ;
- ; Returns 0 if match found, otherwise returns -1. ;
- ; ;
- ; Note: The FCB must have the drive and ;
- ; filename fields (bytes 07H through 12H) and ;
- ; the extension flag (byte 00H) set before ;
- ; the call to FCB_first (see Function 29H). ;
- ; ;
- ;************************************************************;
-
- cProc FCB_first,PUBLIC,ds
- parmDP puXFCB
- parmB attrib
- cBegin
- loadDP ds,dx,puXFCB ; Pointer to unopened extended FCB.
- mov bx,dx ; BX points at FCB, too.
- mov al,attrib ; Get search attribute.
- mov [bx+6],al ; Put attribute into extended FCB
- ; area.
- mov byte ptr [bx],0ffh ; Set flag for extended FCB.
- mov ah,11h ; Ask MS-DOS to find 1st matching
- ; file in current directory.
- int 21h ; If match found, directory entry can
- ; be found at DTA address.
- cbw ; Set return value to 0 or -1.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN12H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 12H: Find Next File, FCB-based ;
- ; ;
- ; int FCB_next(puXFCB) ;
- ; char *puXFCB; ;
- ; ;
- ; Returns 0 if match found, otherwise returns -1. ;
- ; ;
- ; Note: The FCB must have the drive and ;
- ; filename fields (bytes 07H through 12H) and ;
- ; the extension flag (byte 00H) set before ;
- ; the call to FCB_next (see Function 29H). ;
- ; ;
- ;************************************************************;
-
- cProc FCB_next,PUBLIC,ds
- parmDP puXFCB
- cBegin
- loadDP ds,dx,puXFCB ; Pointer to unopened extended FCB.
- mov ah,12h ; Ask MS-DOS to find next matching
- ; file in current directory.
- int 21h ; If match found, directory entry can
- ; be found at DTA address.
- cbw ; Set return value to 0 or -1.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN13H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 13H: Delete File(s), FCB-based ;
- ; ;
- ; int FCB_delete(uXFCB) ;
- ; char *uXFCB; ;
- ; ;
- ; Returns 0 if file(s) were deleted OK, otherwise ;
- ; returns -1. ;
- ; ;
- ; Note: uXFCB must have the drive and ;
- ; filename fields (bytes 07H through 12H) and ;
- ; the extension flag (byte 00H) set before ;
- ; the call to FCB_delete (see Function 29H). ;
- ; ;
- ;************************************************************;
-
- cProc FCB_delete,PUBLIC,ds
- parmDP puXFCB
- cBegin
- loadDP ds,dx,puXFCB ; Pointer to unopened extended FCB.
- mov ah,13h ; Ask MS-DOS to delete file(s).
- int 21h
- cbw ; Return value of 0 or -1.
- cEnd
- \SAMPCODE\DOS_ENCY\SECTION5\FXN14H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 14H: Sequential Read, FCB-based ;
- ; ;
- ; int FCB_sread(oXFCB) ;
- ; char *oXFCB; ;
- ; ;
- ; Returns 0 if record read OK, otherwise ;
- ; returns error code 1, 2, or 3. ;
- ; ;
- ;************************************************************;
-
- cProc FCB_sread,PUBLIC,ds
- parmDP poXFCB
- cBegin
- loadDP ds,dx,poXFCB ; Pointer to opened extended FCB.
- mov ah,14h ; Ask MS-DOS to read next record,
- ; placing it at DTA.
- int 21h
- cbw ; Clear high byte for return value.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN15H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 15H: Sequential Write, FCB-based ;
- ; ;
- ; int FCB_swrite(oXFCB) ;
- ; char *oXFCB; ;
- ; ;
- ; Returns 0 if record read OK, otherwise ;
- ; returns error code 1 or 2. ;
- ; ;
- ;************************************************************;
-
- cProc FCB_swrite,PUBLIC,ds
- parmDP poXFCB
- cBegin
- loadDP ds,dx,poXFCB ; Pointer to opened extended FCB.
- mov ah,15h ; Ask MS-DOS to write next record
- ; from DTA to disk file.
- int 21h
- cbw ; Clear high byte for return value.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN16H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 16H: Create File, FCB-based ;
- ; ;
- ; int FCB_create(uXFCB,recsize) ;
- ; char *uXFCB; ;
- ; int recsize; ;
- ; ;
- ; Returns 0 if file created OK, otherwise ;
- ; returns -1. ;
- ; ;
- ; Note: uXFCB must have the drive and filename ;
- ; fields (bytes 07H through 12H) and the ;
- ; extension flag (byte 00H) set before the ;
- ; call to FCB_create (see Function 29H). ;
- ; ;
- ;************************************************************;
-
- cProc FCB_create,PUBLIC,ds
- parmDP puXFCB
- parmW recsize
- cBegin
- loadDP ds,dx,puXFCB ; Pointer to unopened extended FCB.
- mov ah,16h ; Ask MS-DOS to create file.
- int 21h
- add dx,7 ; Advance pointer to start of regular
- ; FCB.
- mov bx,dx ; BX = FCB pointer.
- mov dx,recsize ; Get record size parameter.
- mov [bx+0eh],dx ; Store record size in FCB.
- xor dx,dx
- mov [bx+20h],dl ; Set current-record
- mov [bx+21h],dx ; and relative-record
- mov [bx+23h],dx ; fields to 0.
- cbw ; Set return value to 0 or -1.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN17H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 17H: Rename File(s), FCB-based ;
- ; ;
- ; int FCB_rename(uXFCBold,uXFCBnew) ;
- ; char *uXFCBold,*uXFCBnew; ;
- ; ;
- ; Returns 0 if file(s) renamed OK, otherwise ;
- ; returns -1. ;
- ; ;
- ; Note: Both uXFCB's must have the drive and ;
- ; filename fields (bytes 07H through 12H) and ;
- ; the extension flag (byte 00H) set before ;
- ; the call to FCB_rename (see Function 29H). ;
- ; ;
- ;************************************************************;
-
- cProc FCB_rename,PUBLIC,<ds,si,di>
- parmDP puXFCBold
- parmDP puXFCBnew
- cBegin
- loadDP es,di,puXFCBold ; ES:DI = Pointer to uXFCBold.
- mov dx,di ; Save offset in DX.
- add di,7 ; Advance pointer to start of regular
- ; FCBold.
- loadDP ds,si,puXFCBnew ; DS:SI = Pointer to uXFCBnew.
- add si,8 ; Advance pointer to filename field
- ; FCBnew.
- ; Copy name from FCBnew into FCBold
- ; at offset 11H:
- add di,11h ; DI points 11H bytes into old FCB.
- mov cx,0bh ; Copy 0BH bytes, moving new
- rep movsb ; name into old FCB.
- push es ; Set DS to segment of FCBold.
- pop ds
- mov ah,17h ; Ask MS-DOS to rename old
- int 21h ; file(s) to new name(s).
- cbw ; Set return flag to 0 or -1.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN19H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 19H: Get Current Disk ;
- ; ;
- ; int cur_drive() ;
- ; ;
- ; Returns letter of current "logged" disk. ;
- ; ;
- ;************************************************************;
-
- cProc cur_drive,PUBLIC
- cBegin
- mov ah,19h ; Set function code.
- int 21h ; Get number of logged disk.
- add al,'A' ; Convert number to letter.
- cbw ; Clear the high byte of return value.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN1AH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 1AH: Set DTA Address ;
- ; ;
- ; int set_DTA(pDTAbuffer) ;
- ; char far *pDTAbuffer; ;
- ; ;
- ; Returns 0. ;
- ; ;
- ;************************************************************;
-
- cProc set_DTA,PUBLIC,ds
- parmD pDTAbuffer
- cBegin
- lds dx,pDTAbuffer ; DS:DX = pointer to buffer.
- mov ah,1ah ; Set function code.
- int 21h ; Ask MS-DOS to change DTA address.
- xor ax,ax ; Return 0.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN1CH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 1CH: Get Drive Data ;
- ; ;
- ; Get information about the disk in the specified ;
- ; drive. Set drive_ltr to 0 for default drive info. ;
- ; ;
- ; int get_drive_data(drive_ltr, ;
- ; pbytes_per_sector, ;
- ; psectors_per_cluster, ;
- ; pclusters_per_drive) ;
- ; int drive_ltr; ;
- ; int *pbytes_per_sector; ;
- ; int *psectors_per_cluster; ;
- ; int *pclusters_per_drive; ;
- ; ;
- ; Returns -1 for invalid drive, otherwise returns ;
- ; the disk's type (from the 1st byte of the FAT). ;
- ; ;
- ;************************************************************;
-
- cProc get_drive_data,PUBLIC,<ds,si>
- parmB drive_ltr
- parmDP pbytes_per_sector
- parmDP psectors_per_cluster
- parmDP pclusters_per_drive
- cBegin
- mov si,ds ; Save DS in SI to use later.
- mov dl,drive_ltr ; Get drive letter.
- or dl,dl ; Leave 0 alone.
- jz gdd
- and dl,not 20h ; Convert letter to uppercase.
- sub dl,'A'-1 ; Convert to drive number: 'A' = 1,
- ; 'B' = 2, etc.
- gdd:
- mov ah,1ch ; Set function code.
- int 21h ; Ask MS-DOS for data.
- cbw ; Extend AL into AH.
- cmp al,0ffh ; Bad drive letter?
- je gddx ; If so, exit with error code -1.
- mov bl,[bx] ; Get FAT ID byte from DS:BX.
- mov ds,si ; Get back original DS.
- loadDP ds,si,pbytes_per_sector
- mov [si],cx ; Return bytes per sector.
- loadDP ds,si,psectors_per_cluster
- mov ah,0
- mov [si],ax ; Return sectors per cluster.
- loadDP ds,si,pclusters_per_drive
- mov [si],dx ; Return clusters per drive.
- mov al,bl ; Return FAT ID byte.
- gddx:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN21H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 21H: Random File Read, FCB-based ;
- ; ;
- ; int FCB_rread(oXFCB,recnum) ;
- ; char *oXFCB; ;
- ; long recnum; ;
- ; ;
- ; Returns 0 if record read OK, otherwise ;
- ; returns error code 1, 2, or 3. ;
- ; ;
- ;************************************************************;
-
- cProc FCB_rread,PUBLIC,ds
- parmDP poXFCB
- parmD recnum
- cBegin
- loadDP ds,dx,poXFCB ; Pointer to opened extended FCB.
- mov bx,dx ; BX points at FCB, too.
- mov ax,word ptr (recnum) ; Get low 16 bits of record
- mov [bx+28h],ax ; number and store in FCB.
- mov ax,word ptr (recnum+2) ; Get high 16 bits of record
- mov [bx+2ah],ax ; number and store in FCB.
- mov ah,21h ; Ask MS-DOS to read recnum'th
- ; record, placing it at DTA.
- int 21h
- cbw ; Clear high byte of return value.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN22H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 22H: Random File Write, FCB-based ;
- ; ;
- ; int FCB_rwrite(oXFCB,recnum) ;
- ; char *oXFCB; ;
- ; long recnum; ;
- ; ;
- ; Returns 0 if record read OK, otherwise ;
- ; returns error code 1 or 2. ;
- ; ;
- ;************************************************************;
-
- cProc FCB_rwrite,PUBLIC,ds
- parmDP poXFCB
- parmD recnum
- cBegin
- loadDP ds,dx,poXFCB ; Pointer to opened extended FCB.
- mov bx,dx ; BX points at FCB, too.
- mov ax,word ptr (recnum) ; Get low 16 bits of record
- mov [bx+28h],ax ; number and store in FCB.
- mov ax,word ptr (recnum+2) ; Get high 16 bits of record
- mov [bx+2ah],ax ; number and store in FCB.
- mov ah,22h ; Ask MS-DOS to write DTA to
- int 21h ; recnum'th record of file.
- cbw ; Clear high byte for return value.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN23H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 23H: Get File Size, FCB-based ;
- ; ;
- ; long FCB_nrecs(uXFCB,recsize) ;
- ; char *uXFCB; ;
- ; int recsize; ;
- ; ;
- ; Returns a long -1 if file not found, otherwise ;
- ; returns the number of records of size recsize. ;
- ; ;
- ; Note: uXFCB must have the drive and ;
- ; filename fields (bytes 07H through 12H) and ;
- ; the extension flag (byte 00H) set before ;
- ; the call to FCB_nrecs (see Function 29H). ;
- ; ;
- ;************************************************************;
-
- cProc FCB_nrecs,PUBLIC,ds
- parmDP puXFCB
- parmW recsize
- cBegin
- loadDP ds,dx,puXFCB ; Pointer to unopened extended FCB.
- mov bx,dx ; Copy FCB pointer into BX.
- mov ax,recsize ; Get record size
- mov [bx+15h],ax ; and store it in FCB.
- mov ah,23h ; Ask MS-DOS for file size (in
- ; records).
- int 21h
- cbw ; If AL = 0FFH, set AX to -1.
- cwd ; Extend to long.
- or dx,dx ; Is DX negative?
- js nr_exit ; If so, exit with error flag.
- mov [bx+2bh],al ; Only low 24 bits of the relative-
- ; record field are used, so clear the
- ; top 8 bits.
- mov ax,[bx+28h] ; Return file length in DX:AX.
- mov dx,[bx+2ah]
- nr_exit:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN24H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 24H: Set Relative Record ;
- ; ;
- ; int FCB_set_rrec(oXFCB) ;
- ; char *oXFCB; ;
- ; ;
- ; Returns 0. ;
- ; ;
- ;************************************************************;
-
- cProc FCB_set_rrec,PUBLIC,ds
- parmDP poXFCB
- cBegin
- loadDP ds,dx,poXFCB ; Pointer to opened extended FCB.
- mov bx,dx ; BX points at FCB, too.
- mov byte ptr [bx+2bh],0 ; Zero high byte of high word of
- ; relative-record field.
- mov ah,24h ; Ask MS-DOS to set relative record
- ; to current record.
- int 21h
- xor ax,ax ; Return 0.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN25H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 25H: Set Interrupt Vector ;
- ; ;
- ; typedef void (far *FCP)(); ;
- ; int set_vector(intnum,vector) ;
- ; int intnum; ;
- ; FCP vector; ;
- ; ;
- ; Returns 0. ;
- ; ;
- ;************************************************************;
-
- cProc set_vector,PUBLIC,ds
- parmB intnum
- parmD vector
- cBegin
- lds dx,vector ; Get vector segment:offset into
- ; DS:DX.
- mov al,intnum ; Get interrupt number into AL.
- mov ah,25h ; Select "set vector" function.
- int 21h ; Ask MS-DOS to change vector.
- xor ax,ax ; Return 0.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN26H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 26H: Create New Program Segment Prefix ;
- ; ;
- ; int create_psp(pspseg) ;
- ; int pspseg; ;
- ; ;
- ; Returns 0. ;
- ; ;
- ;************************************************************;
-
- cProc create_psp,PUBLIC
- parmW pspseg
- cBegin
- mov dx,pspseg ; Get segment address of new PSP.
- mov ah,26h ; Set function code.
- int 21h ; Ask MS-DOS to create new PSP.
- xor ax,ax ; Return 0.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN27H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 27H: Random File Block Read, FCB-based ;
- ; ;
- ; int FCB_rblock(oXFCB,nrequest,nactual,start) ;
- ; char *oXFCB; ;
- ; int nrequest; ;
- ; int *nactual; ;
- ; long start; ;
- ; ;
- ; Returns read status 0, 1, 2, or 3 and sets ;
- ; nactual to number of records actually read. ;
- ; ;
- ; If start is -1, the relative-record field is ;
- ; not changed, causing the block to be read starting ;
- ; at the current record. ;
- ; ;
- ;************************************************************;
-
- cProc FCB_rblock,PUBLIC,<ds,di>
- parmDP poXFCB
- parmW nrequest
- parmDP pnactual
- parmD start
- cBegin
- loadDP ds,dx,poXFCB ; Pointer to opened extended FCB.
- mov di,dx ; DI points at FCB, too.
- mov ax,word ptr (start) ; Get long value of start.
- mov bx,word ptr (start+2)
- mov cx,ax ; Is start = -1?
- and cx,bx
- inc cx
- jcxz rb_skip ; If so, don't change relative-record
- ; field.
- mov [di+28h],ax ; Otherwise, seek to start record.
- mov [di+2ah],bx
- rb_skip:
- mov cx,nrequest ; CX = number of records to read.
- mov ah,27h ; Get MS-DOS to read CX records,
- int 21h ; placing them at DTA.
- loadDP ds,bx,pnactual ; DS:BX = address of nactual.
- mov [bx],cx ; Return number of records read.
- cbw ; Clear high byte.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN28H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 28H: Random File Block Write, FCB-based ;
- ; ;
- ; int FCB_wblock(oXFCB,nrequest,nactual,start) ;
- ; char *oXFCB; ;
- ; int nrequest; ;
- ; int *nactual; ;
- ; long start; ;
- ; ;
- ; Returns write status of 0, 1, or 2 and sets ;
- ; nactual to number of records actually written. ;
- ; ;
- ; If start is -1, the relative-record field is ;
- ; not changed, causing the block to be written ;
- ; starting at the current record. ;
- ; ;
- ;************************************************************;
-
- cProc FCB_wblock,PUBLIC,<ds,di>
- parmDP poXFCB
- parmW nrequest
- parmDP pnactual
- parmD start
- cBegin
- loadDP ds,dx,poXFCB ; Pointer to opened extended FCB.
- mov di,dx ; DI points at FCB, too.
- mov ax,word ptr (start) ; Get long value of start.
- mov bx,word ptr (start+2)
- mov cx,ax ; Is start = -1?
- and cx,bx
- inc cx
- jcxz wb_skip ; If so, don't change relative-record
- ; field.
- mov [di+28h],ax ; Otherwise, seek to start record.
- mov [di+2ah],bx
- wb_skip:
- mov cx,nrequest ; CX = number of records to write.
- mov ah,28h ; Get MS-DOS to write CX records
- int 21h ; from DTA to file.
- loadDP ds,bx,pnactual ; DS:BX = address of nactual.
- mov ds:[bx],cx ; Return number of records written.
- cbw ; Clear high byte.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN29H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 29H: Parse Filename into FCB ;
- ; ;
- ; int FCB_parse(uXFCB,name,ctrl) ;
- ; char *uXFCB; ;
- ; char *name; ;
- ; int ctrl; ;
- ; ;
- ; Returns -1 if error, ;
- ; 0 if no wildcards found, ;
- ; 1 if wildcards found. ;
- ; ;
- ;************************************************************;
-
- cProc FCB_parse,PUBLIC,<ds,si,di>
- parmDP puXFCB
- parmDP pname
- parmB ctrl
- cBegin
- loadDP es,di,puXFCB ; Pointer to unopened extended FCB.
- push di ; Save DI.
- xor ax,ax ; Fill all 22 (decimal) words of the
- ; extended FCB with zeros.
- cld ; Make sure direction flag says UP.
- mov cx,22d
- rep stosw
- pop di ; Recover DI.
- mov byte ptr [di],0ffh ; Set flag byte to mark this as an
- ; extended FCB.
- add di,7 ; Advance pointer to start of regular
- ; FCB.
- loadDP ds,si,pname ; Get pointer to filename into DS:SI.
- mov al,ctrl ; Get parse control byte.
- mov ah,29h ; Parse filename, please.
- int 21h
- cbw ; Set return parameter.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN2AH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 2AH: Get Date ;
- ; ;
- ; long get_date(pdow,pmonth,pday,pyear) ;
- ; char *pdow,*pmonth,*pday; ;
- ; int *pyear; ;
- ; ;
- ; Returns the date packed into a long: ;
- ; low byte = day of month ;
- ; next byte = month ;
- ; next word = year. ;
- ; ;
- ;************************************************************;
-
- cProc get_date,PUBLIC,ds
- parmDP pdow
- parmDP pmonth
- parmDP pday
- parmDP pyear
- cBegin
- mov ah,2ah ; Set function code.
- int 21h ; Get date info from MS-DOS.
- loadDP ds,bx,pdow ; DS:BX = pointer to dow.
- mov [bx],al ; Return dow.
- loadDP ds,bx,pmonth ; DS:BX = pointer to month.
- mov [bx],dh ; Return month.
- loadDP ds,bx,pday ; DS:BX = pointer to day.
- mov [bx],dl ; Return day.
- loadDP ds,bx,pyear ; DS:BX = pointer to year.
- mov [bx],cx ; Return year.
- mov ax,dx ; Pack day, month, ...
- mov dx,cx ; ... and year into return value.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN2BH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 2BH: Set Date ;
- ; ;
- ; int set_date(month,day,year) ;
- ; char month,day; ;
- ; int year; ;
- ; ;
- ; Returns 0 if date was OK, -1 if not. ;
- ; ;
- ;************************************************************;
-
- cProc set_date,PUBLIC
- parmB month
- parmB day
- parmW year
- cBegin
- mov dh,month ; Get new month.
- mov dl,day ; Get new day.
- mov cx,year ; Get new year.
- mov ah,2bh ; Set function code.
- int 21h ; Ask MS-DOS to change date.
- cbw ; Return 0 or -1.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN2CH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 2CH: Get Time ;
- ; ;
- ; long get_time(phour,pmin,psec,phund) ;
- ; char *phour,*pmin,*psec,*phund; ;
- ; ;
- ; Returns the time packed into a long: ;
- ; low byte = hundredths ;
- ; next byte = seconds ;
- ; next byte = minutes ;
- ; next byte = hours ;
- ; ;
- ;************************************************************;
-
- cProc get_time,PUBLIC,ds
- parmDP phour
- parmDP pmin
- parmDP psec
- parmDP phund
- cBegin
- mov ah,2ch ; Set function code.
- int 21h ; Get time from MS-DOS.
- loadDP ds,bx,phour ; DS:BX = pointer to hour.
- mov [bx],ch ; Return hour.
- loadDP ds,bx,pmin ; DS:BX = pointer to min.
- mov [bx],cl ; Return min.
- loadDP ds,bx,psec ; DS:BX = pointer to sec.
- mov [bx],dh ; Return sec.
- loadDP ds,bx,phund ; DS:BX = pointer to hund.
- mov [bx],dl ; Return hund.
- mov ax,dx ; Pack seconds, hundredths, ...
- mov dx,cx ; ... minutes, and hour into
- ; return value.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN2DH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 2DH: Set Time ;
- ; ;
- ; int set_time(hour,min,sec,hund) ;
- ; char hour,min,sec,hund; ;
- ; ;
- ; Returns 0 if time was OK, -1 if not. ;
- ; ;
- ;************************************************************;
-
- cProc set_time,PUBLIC
- parmB hour
- parmB min
- parmB sec
- parmB hund
- cBegin
- mov ch,hour ; Get new hour.
- mov cl,min ; Get new minutes.
- mov dh,sec ; Get new seconds.
- mov dl,hund ; Get new hundredths.
- mov ah,2dh ; Set function code.
- int 21h ; Ask MS-DOS to change time.
- cbw ; Return 0 or -1.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN2EH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 2EH: Set/Reset Verify Flag ;
- ; ;
- ; int set_verify(newvflag) ;
- ; char newvflag; ;
- ; ;
- ; Returns 0. ;
- ; ;
- ;************************************************************;
-
- cProc set_verify,PUBLIC
- parmB newvflag
- cBegin
- mov al,newvflag ; Get new value of verify flag.
- mov ah,2eh ; Set function code.
- int 21h ; Ask MS-DOS to store flag.
- xor ax,ax ; Return 0.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN2FH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 2FH: Get DTA Address ;
- ; ;
- ; char far *get_DTA() ;
- ; ;
- ; Returns a far pointer to the DTA buffer. ;
- ; ;
- ;************************************************************;
-
- cProc get_DTA,PUBLIC
- cBegin
- mov ah,2fh ; Set function code.
- int 21h ; Ask MS-DOS for current DTA address.
- mov ax,bx ; Return offset in AX.
- mov dx,es ; Return segment in DX.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN30H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 30H: Get MS-DOS Version Number ;
- ; ;
- ; int DOS_version() ;
- ; ;
- ; Returns number of MS-DOS version, with ;
- ; major version in high byte, ;
- ; minor version in low byte. ;
- ; ;
- ;************************************************************;
-
- cProc DOS_version,PUBLIC
- cBegin
- mov ax,3000H ; Set function code and clear AL.
- int 21h ; Ask MS-DOS for version number.
- xchg al,ah ; Swap major and minor numbers.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN31H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 31H: Terminate and Stay Resident ;
- ; ;
- ; void keep_process(exit_code,nparas) ;
- ; int exit_code,nparas; ;
- ; ;
- ; Does NOT return! ;
- ; ;
- ;************************************************************;
-
- cProc keep_process,PUBLIC
- parmB exit_code
- parmW nparas
- cBegin
- mov al,exit_code ; Get return code.
- mov dx,nparas ; Set DX to number of paragraphs the
- ; program wants to keep.
- mov ah,31h ; Set function code.
- int 21h ; Ask MS-DOS to keep process.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN33H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 33H: Get/Set Control-C Check Flag ;
- ; ;
- ; int controlC(func,state) ;
- ; int func,state; ;
- ; ;
- ; Returns current state of Ctrl-C flag. ;
- ; ;
- ;************************************************************;
-
- cProc controlC,PUBLIC
- parmB func
- parmB state
- cBegin
- mov al,func ; Get set/reset function.
- mov dl,state ; Get new value if present.
- mov ah,33h ; MS-DOS ^C check function.
- int 21h ; Call MS-DOS.
- mov al,dl ; Return current state.
- cbw ; Clear high byte of return value.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN34H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 34H: Get Return Address of InDOS Flag ;
- ; ;
- ; char far *inDOS_ptr() ;
- ; ;
- ; Returns a far pointer to the MS-DOS inDOS flag. ;
- ; ;
- ;************************************************************;
-
- cProc inDOS_ptr,PUBLIC
- cBegin
- mov ah,34h ; InDOS flag function.
- int 21h ; Call MS-DOS.
- mov ax,bx ; Return offset in AX.
- mov dx,es ; Return segment in DX.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN35H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 35H: Get Interrupt Vector ;
- ; ;
- ; typedef void (far *FCP)(); ;
- ; FCP get_vector(intnum) ;
- ; int intnum; ;
- ; ;
- ; Returns a far code pointer that is the ;
- ; segment:offset of the interrupt vector. ;
- ; ;
- ;************************************************************;
-
- cProc get_vector,PUBLIC
- parmB intnum
- cBegin
- mov al,intnum ; Get interrupt number into AL.
- mov ah,35h ; Select "get vector" function.
- int 21h ; Call MS-DOS.
- mov ax,bx ; Return vector offset.
- mov dx,es ; Return vector segment.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN36H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 36H: Get Disk Free Space ;
- ; ;
- ; long free_space(drive_ltr) ;
- ; char drive_ltr; ;
- ; ;
- ; Returns the number of bytes free as ;
- ; a long integer. ;
- ; ;
- ;************************************************************;
-
- cProc free_space,PUBLIC
- parmB drive_ltr
- cBegin
- mov dl,drive_ltr ; Get drive letter.
- or dl,dl ; Leave 0 alone.
- jz fsp
- and dl,not 20h ; Convert letter to uppercase.
- sub dl,'A'-1 ; Convert to drive number: 'A' = 1,
- ; 'B' = 2, etc.
- fsp:
- mov ah,36h ; Set function code.
- int 21h ; Ask MS-DOS to get disk information.
- mul cx ; Bytes/sector * sectors/cluster
- mul bx ; * free clusters.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN38H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 38H: Get/Set Current Country Data ;
- ; ;
- ; int country_info(country,pbuffer) ;
- ; char country,*pbuffer; ;
- ; ;
- ; Returns -1 if the "country" code is invalid. ;
- ; ;
- ;************************************************************;
-
- cProc country_info,PUBLIC,ds
- parmB country
- parmDP pbuffer
- cBegin
- mov al,country ; Get country code.
- loadDP ds,dx,pbuffer ; Get buffer pointer (or -1).
- mov ah,38h ; Set function code.
- int 21h ; Ask MS-DOS to get country
- ; information.
- jnb cc_ok ; Branch if country code OK.
- mov ax,-1 ; Else return -1.
- cc_ok:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN39H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 39H: Create Directory ;
- ; ;
- ; int make_dir(pdirpath) ;
- ; char *pdirpath; ;
- ; ;
- ; Returns 0 if directory created OK, ;
- ; otherwise returns error code. ;
- ; ;
- ;************************************************************;
-
- cProc make_dir,PUBLIC,ds
- parmDP pdirpath
- cBegin
- loadDP ds,dx,pdirpath ; Get pointer to pathname.
- mov ah,39h ; Set function code.
- int 21h ; Ask MS-DOS to make new subdirectory.
- jb md_err ; Branch on error.
- xor ax,ax ; Else return 0.
- md_err:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN40H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 40H: Write File or Device ;
- ; ;
- ; int write(handle,pbuffer,nbytes) ;
- ; int handle,nbytes; ;
- ; char *pbuffer; ;
- ; ;
- ; Returns -1 if there was a write error, ;
- ; otherwise returns number of bytes written. ;
- ; ;
- ;************************************************************;
-
- cProc write,PUBLIC,ds
- parmW handle
- parmDP pbuffer
- parmW nbytes
- cBegin
- mov bx,handle ; Get handle.
- loadDP ds,dx,pbuffer ; Get pointer to buffer.
- mov cx,nbytes ; Get number of bytes to write.
- mov ah,40h ; Set function code.
- int 21h ; Ask MS-DOS to write CX bytes.
- jnb wr_ok ; Branch if write successful.
- mov ax,-1 ; Else return -1.
- wr_ok:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN41H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 41H: Delete File ;
- ; ;
- ; int delete(pfilepath) ;
- ; char *pfilepath; ;
- ; ;
- ; Returns 0 if file deleted, ;
- ; otherwise returns error code. ;
- ; ;
- ;************************************************************;
-
- cProc delete,PUBLIC,ds
- parmDP pfilepath
- cBegin
- loadDP ds,dx,pfilepath ; Get pointer to pathname.
- mov ah,41h ; Set function code.
- int 21h ; Ask MS-DOS to delete file.
- jb dl_err ; Branch if MS-DOS could not delete
- ; file.
- xor ax,ax ; Else return 0.
- dl_err:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN42H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 42H: Move File Pointer ;
- ; ;
- ; long seek(handle,distance,mode) ;
- ; int handle,mode; ;
- ; long distance; ;
- ; ;
- ; Modes: ;
- ; 0: from beginning of file ;
- ; 1: from the current position ;
- ; 2: from the end of the file ;
- ; ;
- ; Returns -1 if there was a seek error, ;
- ; otherwise returns long pointer position. ;
- ; ;
- ;************************************************************;
-
- cProc seek,PUBLIC
- parmW handle
- parmD distance
- parmB mode
- cBegin
- mov bx,handle ; Get handle.
- les dx,distance ; Get distance into ES:DX.
- mov cx,es ; Put high word of distance into CX.
- mov al,mode ; Get move method code.
- mov ah,42h ; Set function code.
- int 21h ; Ask MS-DOS to move file pointer.
- jnb sk_ok ; Branch if seek successful.
- mov ax,-1 ; Else return -1.
- cwd
- sk_ok:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN43H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 43H: Get/Set File Attributes ;
- ; ;
- ; int file_attr(pfilepath,func,attr) ;
- ; char *pfilepath; ;
- ; int func,attr; ;
- ; ;
- ; Returns -1 for all errors, ;
- ; otherwise returns file attribute. ;
- ; ;
- ;************************************************************;
-
- cProc file_attr,PUBLIC,ds
- parmDP pfilepath
- parmB func
- parmW attr
- cBegin
- loadDP ds,dx,pfilepath ; Get pointer to pathname.
- mov al,func ; Get/set flag into AL.
- mov cx,attr ; Get new attr (if present).
- mov ah,43h ; Set code function.
- int 21h ; Call MS-DOS.
- jnb fa_ok ; Branch if no error.
- mov cx,-1 ; Else return -1.
- fa_ok:
- mov ax,cx ; Return this value.
-
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN4400H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 44H, Subfunctions 00H,01H: ;
- ; Get/Set IOCTL Device Data ;
- ; ;
- ; int ioctl_char_flags(setflag,handle,newflags) ;
- ; int setflag; ;
- ; int handle; ;
- ; int newflags; ;
- ; ;
- ; Set setflag = 0 to get flags, 1 to set flags. ;
- ; ;
- ; Returns -1 for error, else returns flags. ;
- ; ;
- ;************************************************************;
-
- cProc ioctl_char_flags,PUBLIC
- parmB setflag
- parmW handle
- parmW newflags
- cBegin
- mov al,setflag ; Get setflag.
- and al,1 ; Save only lsb.
- mov bx,handle ; Get handle to character device.
- mov dx,newflags ; Get new flags (they are used only
- ; by "set" option).
- mov ah,44h ; Set function code.
- int 21h ; Call MS-DOS.
- mov ax,dx ; Assume success - prepare to return
- ; flags.
- jnc iocfx ; Branch if no error.
- mov ax,-1 ; Else return error flag.
- iocfx:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN4401H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 44H, Subfunctions 00H,01H: ;
- ; Get/Set IOCTL Device Data ;
- ; ;
- ; int ioctl_char_flags(setflag,handle,newflags) ;
- ; int setflag; ;
- ; int handle; ;
- ; int newflags; ;
- ; ;
- ; Set setflag = 0 to get flags, 1 to set flags. ;
- ; ;
- ; Returns -1 for error, else returns flags. ;
- ; ;
- ;************************************************************;
-
- cProc ioctl_char_flags,PUBLIC
- parmB setflag
- parmW handle
- parmW newflags
- cBegin
- mov al,setflag ; Get setflag.
- and al,1 ; Save only lsb.
- mov bx,handle ; Get handle to character device.
- mov dx,newflags ; Get new flags (they are used only
- ; by "set" option).
- mov ah,44h ; Set function code.
- int 21h ; Call MS-DOS.
- mov ax,dx ; Assume success - prepare to return
- ; flags.
- jnc iocfx ; Branch if no error.
- mov ax,-1 ; Else return error flag.
- iocfx:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN4402H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 44H, Subfunctions 02H,03H: ;
- ; IOCTL Character Device Control ;
- ; ;
- ; int ioctl_char_ctrl(recvflag,handle,pbuffer,nbytes) ;
- ; int recvflag; ;
- ; int handle; ;
- ; char *pbuffer; ;
- ; int nbytes; ;
- ; ;
- ; Set recvflag = 0 to get flags, 1 to set flags. ;
- ; ;
- ; Returns -1 for error, otherwise returns number of ;
- ; bytes sent or received. ;
- ; ;
- ;************************************************************;
-
- cProc ioctl_char_ctrl,PUBLIC,<ds>
- parmB recvflag
- parmW handle
- parmDP pbuffer
- parmW nbytes
- cBegin
- mov al,recvflag ; Get recvflag.
- and al,1 ; Keep only lsb.
- add al,2 ; AL = 02H for receive, 03H for send.
- mov bx,handle ; Get character-device handle.
- mov cx,nbytes ; Get number of bytes to receive/send.
- loadDP ds,dx,pbuffer ; Get pointer to buffer.
- mov ah,44h ; Set function code.
- int 21h ; Call MS-DOS.
- jnc iccx ; Branch if no error.
- mov ax,-1 ; Return -1 for all errors.
- iccx:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN4403H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 44H, Subfunctions 02H,03H: ;
- ; IOCTL Character Device Control ;
- ; ;
- ; int ioctl_char_ctrl(recvflag,handle,pbuffer,nbytes) ;
- ; int recvflag; ;
- ; int handle; ;
- ; char *pbuffer; ;
- ; int nbytes; ;
- ; ;
- ; Set recvflag = 0 to get flags, 1 to set flags. ;
- ; ;
- ; Returns -1 for error, otherwise returns number of ;
- ; bytes sent or received. ;
- ; ;
- ;************************************************************;
-
- cProc ioctl_char_ctrl,PUBLIC,<ds>
- parmB recvflag
- parmW handle
- parmDP pbuffer
- parmW nbytes
- cBegin
- mov al,recvflag ; Get recvflag.
- and al,1 ; Keep only lsb.
- add al,3 ; AL = 02H for receive, 03H for send.
- mov bx,handle ; Get character-device handle.
- mov cx,nbytes ; Get number of bytes to receive/send.
- loadDP ds,dx,pbuffer ; Get pointer to buffer.
- mov ah,44h ; Set function code.
- int 21h ; Call MS-DOS.
- jnc iccx ; Branch if no error.
- mov ax,-1 ; Return -1 for all errors.
- iccx:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN4404H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 44H, Subfunctions 04H,05H: ;
- ; IOCTL Block Device Control ;
- ; ;
- ; int ioctl_block_ctrl(recvflag,drive_ltr,pbuffer,nbytes) ;
- ; int recvflag; ;
- ; int drive_ltr; ;
- ; char *pbuffer; ;
- ; int nbytes; ;
- ; ;
- ; Set recvflag = 0 to receive info, 1 to send. ;
- ; ;
- ; Returns -1 for error, otherwise returns number of ;
- ; bytes sent or received. ;
- ; ;
- ;************************************************************;
-
- cProc ioctl_block_ctrl,PUBLIC,<ds>
- parmB recvflag
- parmB drive_ltr
- parmDP pbuffer
- parmW nbytes
- cBegin
- mov al,recvflag ; Get recvflag.
- and al,1 ; Keep only lsb.
- add al,4 ; AL = 04H for receive, 05H for send.
- mov bl,drive_ltr ; Get drive letter.
- or bl,bl ; Leave 0 alone.
- jz ibc
- and bl,not 20h ; Convert letter to uppercase.
- sub bl,'A'-1 ; Convert to drive number: 'A' = 1,
- ; 'B' = 2, etc.
- ibc:
- mov cx,nbytes ; Get number of bytes to recv/send.
- loadDP ds,dx,pbuffer ; Get pointer to buffer.
- mov ah,44h ; Set function code.
- int 21h ; Call MS-DOS.
- jnc ibcx ; Branch if no error.
- mov ax,-1 ; Return -1 for all errors.
- ibcx:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN4405H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 44H, Subfunctions 04H,05H: ;
- ; IOCTL Block Device Control ;
- ; ;
- ; int ioctl_block_ctrl(recvflag,drive_ltr,pbuffer,nbytes) ;
- ; int recvflag; ;
- ; int drive_ltr; ;
- ; char *pbuffer; ;
- ; int nbytes; ;
- ; ;
- ; Set recvflag = 0 to receive info, 1 to send. ;
- ; ;
- ; Returns -1 for error, otherwise returns number of ;
- ; bytes sent or received. ;
- ; ;
- ;************************************************************;
-
- cProc ioctl_block_ctrl,PUBLIC,<ds>
- parmB recvflag
- parmB drive_ltr
- parmDP pbuffer
- parmW nbytes
- cBegin
- mov al,recvflag ; Get recvflag.
- and al,1 ; Keep only lsb.
- add al,5 ; AL = 04H for receive, 05H for send.
- mov bl,drive_ltr ; Get drive letter.
- or bl,bl ; Leave 0 alone.
- jz ibc
- and bl,not 20h ; Convert letter to uppercase.
- sub bl,'A'-1 ; Convert to drive number: 'A' = 1,
- ; 'B' = 2, etc.
- ibc:
- mov cx,nbytes ; Get number of bytes to recv/send.
- loadDP ds,dx,pbuffer ; Get pointer to buffer.
- mov ah,44h ; Set function code.
- int 21h ; Call MS-DOS.
- jnc ibcx ; Branch if no error.
- mov ax,-1 ; Return -1 for all errors.
- ibcx:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN4406H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 44H, Subfunctions 06H,07H: ;
- ; IOCTL Input/Output Status ;
- ; ;
- ; int ioctl_char_status(outputflag,handle) ;
- ; int outputflag; ;
- ; int handle; ;
- ; ;
- ; Set outputflag = 0 for input status, 1 for output status.;
- ; ;
- ; Returns -1 for all errors, 0 for not ready, ;
- ; and 1 for ready. ;
- ; ;
- ;************************************************************;
-
- cProc ioctl_char_status,PUBLIC
- parmB outputflag
- parmW handle
- cBegin
- mov al,outputflag ; Get outputflag.
- and al,1 ; Keep only lsb.
- add al,6 ; AL = 06H for input status, 07H for output
- ; status.
- mov bx,handle ; Get handle.
- mov ah,44h ; Set function code.
- int 21h ; Call MS-DOS.
- jnc isnoerr ; Branch if no error.
- mov ax,-1 ; Return error code.
- jmp short isx
- isnoerr:
- and ax,1 ; Keep only lsb for return value.
- isx:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN4407H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 44H, Subfunctions 06H,07H: ;
- ; IOCTL Input/Output Status ;
- ; ;
- ; int ioctl_char_status(outputflag,handle) ;
- ; int outputflag; ;
- ; int handle; ;
- ; ;
- ; Set outputflag = 0 for input status, 1 for output status.;
- ; ;
- ; Returns -1 for all errors, 0 for not ready, ;
- ; and 1 for ready. ;
- ; ;
- ;************************************************************;
-
- cProc ioctl_char_status,PUBLIC
- parmB outputflag
- parmW handle
- cBegin
- mov al,outputflag ; Get outputflag.
- and al,1 ; Keep only lsb.
- add al,7 ; AL = 06H for input status, 07H for output
- ; status.
- mov bx,handle ; Get handle.
- mov ah,44h ; Set function code.
- int 21h ; Call MS-DOS.
- jnc isnoerr ; Branch if no error.
- mov ax,-1 ; Return error code.
- jmp short isx
- isnoerr:
- and ax,1 ; Keep only lsb for return value.
- isx:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN4408H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 44H, Subfunction 08H: ;
- ; IOCTL Removable Block Device Query ;
- ; ;
- ; int ioctl_block_fixed(drive_ltr) ;
- ; int drive_ltr; ;
- ; ;
- ; Returns -1 for all errors, 1 if disk is fixed (not ;
- ; removable), 0 if disk is not fixed. ;
- ; ;
- ;************************************************************;
-
- cProc ioctl_block_fixed,PUBLIC
- parmB drive_ltr
- cBegin
- mov bl,drive_ltr ; Get drive letter.
- or bl,bl ; Leave 0 alone.
- jz ibch
- and bl,not 20h ; Convert letter to uppercase.
- sub bl,'A'-1 ; Convert to drive number: 'A' = 1,
- ; 'B' = 2, etc.
- ibch:
- mov ax,4408h ; Set function code, Subfunction 08H.
- int 21h ; Call MS-DOS.
- jnc ibchx ; Branch if no error, AX = 0 or 1.
- cmp ax,1 ; Treat error code of 1 as "disk is
- ; fixed."
- je ibchx
- mov ax,-1 ; Return -1 for other errors.
- ibchx:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN4409H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 44H, Subfunction 09H: ;
- ; IOCTL Remote Block Device Query ;
- ; ;
- ; int ioctl_block_redir(drive_ltr) ;
- ; int drive_ltr; ;
- ; ;
- ; Returns -1 for all errors, 1 if disk is remote ;
- ; (redirected), 0 if disk is local. ;
- ; ;
- ;************************************************************;
-
- cProc ioctl_block_redir,PUBLIC
- parmB drive_ltr
- cBegin
- mov bl,drive_ltr ; Get drive letter.
- or bl,bl ; Leave 0 alone.
- jz ibr
- and bl,not 20h ; Convert letter to uppercase.
- sub bl,'A'-1 ; Convert to drive number: 'A' = 1,
- ; 'B' = 2, etc.
- ibr:
- mov ax,4409h ; Set function code, Subfunction 09H.
- int 21h ; Call MS-DOS.
- mov ax,-1 ; Assume error.
- jc ibrx ; Branch if error, returning -1.
- inc ax ; Set AX = 0.
- test dh,10h ; Is bit 12 set?
- jz ibrx ; If not, disk is local: Return 0.
- inc ax ; Return 1 for remote disk.
- ibrx:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN440AH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 44H, Subfunction 0AH: ;
- ; IOCTL Remote Handle Query ;
- ; ;
- ; int ioctl_char_redir(handle) ;
- ; int handle; ;
- ; ;
- ; Returns -1 for all errors, 1 if device/file is remote ;
- ; (redirected), 0 if it is local. ;
- ; ;
- ;************************************************************;
-
- cProc ioctl_char_redir,PUBLIC
- parmW handle
- cBegin
- mov bx,handle ; Get handle.
- mov ax,440ah ; Set function code, Subfunction 0AH.
- int 21h ; Call MS-DOS.
- mov ax,-1 ; Assume error.
- jc icrx ; Branch on error, returning -1.
- inc ax ; Set AX = 0.
- test dh,80h ; Is bit 15 set?
- jz icrx ; If not, device/file is local:
- ; Return 0.
- inc ax ; Return 1 for remote.
- icrx:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN440BH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 44H, Subfunction 0BH: ;
- ; IOCTL Change Sharing Retry Count ;
- ; ;
- ; int ioctl_set_retry(num_retries,wait_time) ;
- ; int num_retries; ;
- ; int wait_time; ;
- ; ;
- ; Returns 0 for success, otherwise returns error code. ;
- ; ;
- ;************************************************************;
-
- cProc ioctl_set_retry,PUBLIC,<ds,si>
- parmW num_retries
- parmW wait_time
- cBegin
- mov dx,num_retries ; Get parameters.
- mov cx,wait_time
- mov ax,440bh ; Set function code, Subfunction 0BH.
- int 21h ; Call MS-DOS.
- jc isrx ; Branch on error.
- xor ax,ax
- isrx:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN440CH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 44H, Subfunction 0CH: ;
- ; Generic IOCTL for Handles ;
- ; ;
- ; int ioctl_char_generic(handle,category,function,pbuffer) ;
- ; int handle; ;
- ; int category; ;
- ; int function; ;
- ; int *pbuffer; ;
- ; ;
- ; Returns 0 for success, otherwise returns error code. ;
- ; ;
- ;************************************************************;
-
- cProc ioctl_char_generic,PUBLIC,<ds>
- parmW handle
- parmB category
- parmB function
- parmDP pbuffer
- cBegin
- mov bx,handle ; Get device handle.
- mov ch,category ; Get category
- mov cl,function ; and function.
- loadDP ds,dx,pbuffer ; Get pointer to data buffer.
- mov ax,440ch ; Set function code, Subfunction 0CH.
- int 21h ; Call MS-DOS.
- jc icgx ; Branch on error.
- xor ax,ax
- icgx:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN440DH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 44H, Subfunction 0DH: ;
- ; Generic IOCTL for Block Devices ;
- ; ;
- ; int ioctl_block_generic(drv_ltr,category,func,pbuffer) ;
- ; int drv_ltr; ;
- ; int category; ;
- ; int func; ;
- ; char *pbuffer; ;
- ; ;
- ; Returns 0 for success, otherwise returns error code. ;
- ; ;
- ;************************************************************;
-
- cProc ioctl_block_generic,PUBLIC,<ds>
- parmB drv_ltr
- parmB category
- parmB func
- parmDP pbuffer
- cBegin
- mov bl,drv_ltr ; Get drive letter.
- or bl,bl ; Leave 0 alone.
- jz ibg
- and bl,not 20h ; Convert letter to uppercase.
- sub bl,'A'-1 ; Convert to drive number: 'A' = 1,
- ; 'B' = 2, etc.
- ibg:
- mov ch,category ; Get category
- mov cl,func ; and function.
- loadDP ds,dx,pbuffer ; Get pointer to data buffer.
- mov ax,440dh ; Set function code, Subfunction 0DH.
- int 21h ; Call MS-DOS.
- jc ibgx ; Branch on error.
- xor ax,ax
- ibgx:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN440EH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 44H, Subfunctions 0EH, 0FH: ;
- ; IOCTL Get/Set Logical Drive Map ;
- ; ;
- ; int ioctl_drive_owner(setflag, drv_ltr) ;
- ; int setflag; ;
- ; int drv_ltr; ;
- ; ;
- ; Set setflag = 1 to change drive's map, 0 to get ;
- ; current map. ;
- ; ;
- ; Returns -1 for all errors, otherwise returns ;
- ; the block device's current logical drive letter. ;
- ; ;
- ;************************************************************;
-
- cProc ioctl_drive_owner,PUBLIC
- parmB setflag
- parmB drv_ltr
- cBegin
- mov al,setflag ; Load setflag.
- and al,1 ; Keep only lsb.
- add al,0eh ; AL = 0EH for get, 0FH for set.
- mov bl,drv_ltr ; Get drive letter.
- or bl,bl ; Leave 0 alone.
- jz ido
- and bl,not 20h ; Convert letter to uppercase.
- sub bl,'A'-1 ; Convert to drive number: 'A' = 1,
- ; 'B' = 2, etc.
- ido:
- mov bh,0
- mov ah,44h ; Set function code.
- int 21h ; Call MS-DOS.
- mov ah,0 ; Clear high byte.
- jnc idox ; Branch if no error.
- mov ax,-1-'A' ; Return -1 for errors.
- idox:
- add ax,'A' ; Return drive letter.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN440FH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 44H, Subfunctions 0EH, 0FH: ;
- ; IOCTL Get/Set Logical Drive Map ;
- ; ;
- ; int ioctl_drive_owner(setflag, drv_ ltr) ;
- ; int setflag; ;
- ; int drv_ltr; ;
- ; ;
- ; Set setflag = 1 to change drive's map, 0 to get ;
- ; current map. ;
- ; ;
- ; Returns -1 for all errors, otherwise returns ;
- ; the block device's current logical drive letter. ;
- ; ;
- ;************************************************************;
-
- cProc ioctl_drive_owner,PUBLIC
- parmB setflag
- parmB drv_ltr
- cBegin
- mov al,setflag ; Load setflag.
- and al,1 ; Keep only lsb.
- add al,0fh ; AL = 0EH for get, 0FH for set.
- mov bl,drv_ltr ; Get drive letter.
- or bl,bl ; Leave 0 alone.
- jz ido
- and bl,not 20h ; Convert letter to uppercase.
- sub bl,'A'-1 ; Convert to drive number: 'A' = 1,
- ; 'B' = 2, etc.
- ido:
- mov bh,0
- mov ah,44h ; Set function code.
- int 21h ; Call MS-DOS.
- mov ah,0 ; Clear high byte.
- jnc idox ; Branch if no error.
- mov ax,-1-'A' ; Return -1 for errors.
- idox:
- add ax,'A' ; Return drive letter.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN45H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 45H: Duplicate File Handle ;
- ; ;
- ; int dup_handle(handle) ;
- ; int handle; ;
- ; ;
- ; Returns -1 for errors, ;
- ; otherwise returns new handle. ;
- ; ;
- ;************************************************************;
-
- cProc dup_handle,PUBLIC
- parmW handle
- cBegin
- mov bx,handle ; Get handle to copy.
- mov ah,45h ; Set function code.
- int 21h ; Ask MS-DOS to duplicate handle.
- jnb dup_ok ; Branch if copy was successful.
- mov ax,-1 ; Else return -1.
- dup_ok:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN46H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 46H: Force Duplicate File Handle ;
- ; ;
- ; int dup_handle2(existhandle,newhandle) ;
- ; int existhandle,newhandle; ;
- ; ;
- ; Returns -1 for errors, ;
- ; otherwise returns newhandle unchanged. ;
- ; ;
- ;************************************************************;
-
- cProc dup_handle2,PUBLIC
- parmW existhandle
- parmW newhandle
- cBegin
- mov bx,existhandle ; Get handle of existing file.
- mov cx,newhandle ; Get handle to copy into.
- mov ah,46h ; Close handle CX and then
- int 21h ; duplicate BX's handle into CX.
- mov ax,newhandle ; Prepare return value.
- jnb dup2_ok ; Branch if close/copy was successful.
- mov ax,-1 ; Else return -1.
- dup2_ok:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN47H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 47H: Get Current Directory ;
- ; ;
- ; int get_dir(drive_ltr,pbuffer) ;
- ; int drive_ltr; ;
- ; char *pbuffer; ;
- ; ;
- ; Returns -1 for bad drive, ;
- ; otherwise returns pointer to pbuffer. ;
- ; ;
- ;************************************************************;
-
- cProc get_dir,PUBLIC,<ds,si>
- parmB drive_ltr
- parmDP pbuffer
- cBegin
- loadDP ds,si,pbuffer ; Get pointer to buffer.
- mov dl,drive_ltr ; Get drive number.
- or dl,dl ; Leave 0 alone.
- jz gdir
- and dl,not 20h ; Convert letter to uppercase
- sub dl,'A'-1 ; Convert to drive number: 'A' = 1,
- ; 'B' = 2, etc.
- gdir:
- mov ah,47h ; Set function code.
- int 21h ; Call MS-DOS.
- mov ax,si ; Return pointer to buffer ...
- jnb gd_ok
- mov ax,-1 ; ... unless an error occurred.
- gd_ok:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN48H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 48H: Allocate Memory Block ;
- ; ;
- ; int get_block(nparas,pblocksegp,pmaxparas) ;
- ; int nparas,*pblockseg,*pmaxparas; ;
- ; ;
- ; Returns 0 if nparas are allocated OK and ;
- ; pblockseg has segment address of block, ;
- ; otherwise returns error code with pmaxparas ;
- ; set to maximum block size available. ;
- ; ;
- ;************************************************************;
-
- cProc get_block,PUBLIC,ds
- parmW nparas
- parmDP pblockseg
- parmDP pmaxparas
- cBegin
- mov bx,nparas ; Get size request.
- mov ah,48h ; Set function code.
- int 21h ; Ask MS-DOS for memory.
- mov cx,bx ; Save BX.
- loadDP ds,bx,pmaxparas
- mov [bx],cx ; Return result, assuming failure.
- jb gb_err ; Exit if error, leaving error code
- ; in AX.
- loadDP ds,bx,pblockseg
- mov [bx],ax ; No error, so store address of block.
- xor ax,ax ; Return 0.
- gb_err:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN49H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 49H: Free Memory Block ;
- ; ;
- ; int free_block(blockseg) ;
- ; int blockseg; ;
- ; ;
- ; Returns 0 if block freed OK, ;
- ; otherwise returns error code. ;
- ; ;
- ;************************************************************;
-
- cProc free_block,PUBLIC
- parmW blockseg
- cBegin
- mov es,blockseg ; Get block address.
- mov ah,49h ; Set function code.
- int 21h ; Ask MS-DOS to free memory.
- jb fb_err ; Branch on error.
- xor ax,ax ; Return 0 if successful.
- fb_err:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN4AH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 4AH: Resize Memory Block ;
- ; ;
- ; int modify_block(nparas,blockseg,pmaxparas) ;
- ; int nparas,blockseg,*pmaxparas; ;
- ; ;
- ; Returns 0 if modification was a success, ;
- ; otherwise returns error code with pmaxparas ;
- ; set to max number of paragraphs available. ;
- ; ;
- ;************************************************************;
-
- cProc modify_block,PUBLIC,ds
- parmW nparas
- parmW blockseg
- parmDP pmaxparas
- cBegin
- mov es,blockseg ; Get block address.
- mov bx,nparas ; Get nparas.
- mov ah,4ah ; Set function code.
- int 21h ; Ask MS-DOS to change block size.
- mov cx,bx ; Save BX.
- loadDP ds,bx,pmaxparas
- mov [bx],cx ; Set pmaxparas, assuming failure.
- jb mb_exit ; Branch if size change error.
- xor ax,ax ; Return 0 if successful.
- mb_exit:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN4BH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 4BH: Load and Execute Program ;
- ; ;
- ; int execute(pprogname,pcmdtail) ;
- ; char *pprogname,*pcmdtail; ;
- ; ;
- ; Returns 0 if program loaded, ran, and ;
- ; terminated successfully, otherwise returns ;
- ; error code. ;
- ; ;
- ;************************************************************;
-
- sBegin data
- $cmdlen = 126
- $cmd db $cmdlen+2 dup (?) ; Make space for command line, plus
- ; 2 extra bytes for length and
- ; carriage return.
-
- $fcb db 0 ; Make dummy FCB.
- db 'dummy fcb'
- db 0,0,0,0
-
- ; Here's the EXEC parameter block:
- $epb dw 0 ; 0 means inherit environment.
- dw dataOFFSET $cmd ; Pointer to cmd line.
- dw seg dgroup
- dw dataOFFSET $fcb ; Pointer to FCB #1.
- dw seg dgroup
- dw dataOFFSET $fcb ; Pointer to FCB #2.
- dw seg dgroup
- sEnd data
- sBegin code
-
- $sp dw ? ; Allocate space in code seg
- $ss dw ? ; for saving SS and SP.
-
- Assumes ES,dgroup
-
- cProc execute,PUBLIC,<ds,si,di>
- parmDP pprogname
- parmDP pcmdtail
- cBegin
- mov cx,$cmdlen ; Allow command line this long.
- loadDP ds,si,pcmdtail ; DS:SI = pointer to cmdtail string.
- mov ax,seg dgroup:$cmd ; Set ES = data segment.
- mov es,ax
- mov di,dataOFFSET $cmd+1 ; ES:DI = pointer to 2nd byte of
- ; our command-line buffer.
- copycmd:
- lodsb ; Get next character.
- or al,al ; Found end of command tail?
- jz endcopy ; Exit loop if so.
- stosb ; Copy to command buffer.
- loop copycmd
- endcopy:
- mov al,13
- stosb ; Store carriage return at
- ; end of command.
- neg cl
- add cl,$cmdlen ; CL = length of command tail.
- mov es:$cmd,cl ; Store length in command-tail buffer.
-
- loadDP ds,dx,pprogname ; DS:DX = pointer to program name.
- mov bx,dataOFFSET $epb ; ES:BX = pointer to parameter
- ; block.
-
- mov cs:$ss,ss ; Save current stack SS:SP (since
- mov cs:$sp,sp ; EXEC function destroys stack).
- mov ax,4b00h ; Set function code.
- int 21h ; Ask MS-DOS to load and execute
- ; program.
- cli ; Disable interrupts.
- mov ss,cs:$ss ; Restore stack.
- mov sp,cs:$sp
- sti ; Enable interrupts.
- jb ex_err ; Branch on error.
- xor ax,ax ; Return 0 if no error.
- ex_err:
- cEnd
- sEnd code
-
-
-
- ;************************************************************;
- ; ;
- ; Function 4BH: Load an Overlay Program ;
- ; ;
- ; int load_overlay(pfilename,loadseg) ;
- ; char *pfilename; ;
- ; int loadseg; ;
- ; ;
- ; Returns 0 if program has been loaded OK, ;
- ; otherwise returns error code. ;
- ; ;
- ; To call an overlay function after it has been ;
- ; loaded by load_overlay(), you can use ;
- ; a far indirect call: ;
- ; ;
- ; 1. FTYPE (far *ovlptr)(); ;
- ; 2. *((unsigned *)&ovlptr + 1) = loadseg; ;
- ; 3. *((unsigned *)&ovlptr) = offset; ;
- ; 4. (*ovlptr)(arg1,arg2,arg3,...); ;
- ; ;
- ; Line 1 declares a far pointer to a ;
- ; function with return type FTYPE. ;
- ; ;
- ; Line 2 stores loadseg into the segment ;
- ; portion (high word) of the far pointer. ;
- ; ;
- ; Line 3 stores offset into the offset ;
- ; portion (low word) of the far pointer. ;
- ; ;
- ; Line 4 does a far call to offset ;
- ; bytes into the segment loadseg ;
- ; passing the arguments listed. ;
- ; ;
- ; To return correctly, the overlay must end with a far ;
- ; return instruction. If the overlay is ;
- ; written in Microsoft C, this can be done by ;
- ; declaring the overlay function with the ;
- ; keyword "far". ;
- ; ;
- ;************************************************************;
-
- sBegin data
- ; The overlay parameter block:
- $lob dw ? ; space for load segment;
- dw ? ; space for fixup segment.
- sEnd data
-
- sBegin code
-
- cProc load_overlay,PUBLIC,<ds,si,di>
- parmDP pfilename
- parmW loadseg
- cBegin
- loadDP ds,dx,pfilename ; DS:DX = pointer to program name.
- mov ax,seg dgroup:$lob ; Set ES = data segment.
- mov es,ax
- mov bx,dataOFFSET $lob ; ES:BX = pointer to parameter
- ; block.
- mov ax,loadseg ; Get load segment parameter.
- mov es:[bx],ax ; Set both the load and fixup
- mov es:[bx+2],ax ; segments to that segment.
-
- mov cs:$ss,ss ; Save current stack SS:SP (because
- mov cs:$sp,sp ; EXEC function destroys stack).
- mov ax,4b03h ; Set function code.
- int 21h ; Ask MS-DOS to load the overlay.
- cli ; Disable interrupts.
- mov ss,cs:$ss ; Restore stack.
- mov sp,cs:$sp
- sti ; Enable interrupts.
- jb lo_err ; Branch on error.
- xor ax,ax ; Return 0 if no error.
- lo_err:
- cEnd
- sEnd code
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN4CH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 4CH: Terminate Process with Return Code ;
- ; ;
- ; int terminate(returncode) ;
- ; int returncode; ;
- ; ;
- ; Does NOT return at all! ;
- ; ;
- ;************************************************************;
-
- cProc terminate,PUBLIC
- parmB returncode
- cBegin
- mov al,returncode ; Set return code.
- mov ah,4ch ; Set function code.
- int 21h ; Call MS-DOS to terminate process.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN4DH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 4DH: Get Return Code of Child Process ;
- ; ;
- ; int child_ret_code() ;
- ; ;
- ; Returns the return code of the last ;
- ; child process. ;
- ; ;
- ;************************************************************;
-
- cProc child_ret_code,PUBLIC
- cBegin
- mov ah,4dh ; Set function code.
- int 21h ; Ask MS-DOS to return code.
- cbw ; Convert AL to a word.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN4EH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 4EH: Find First File ;
- ; ;
- ; int find_first(ppathname,attr) ;
- ; char *ppathname; ;
- ; int attr; ;
- ; ;
- ; Returns 0 if a match was found, ;
- ; otherwise returns error code. ;
- ; ;
- ;************************************************************;
-
- cProc find_first,PUBLIC,ds
- parmDP ppathname
- parmW attr
- cBegin
- loadDP ds,dx,ppathname ; Get pointer to pathname.
- mov cx,attr ; Get search attributes.
- mov ah,4eh ; Set function code.
- int 21h ; Ask MS-DOS to look for a match.
- jb ff_err ; Branch on error.
- xor ax,ax ; Return 0 if no error.
- ff_err:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN4FH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 4FH: Find Next File ;
- ; ;
- ; int find_next() ;
- ; ;
- ; Returns 0 if a match was found, ;
- ; otherwise returns error code. ;
- ; ;
- ;************************************************************;
-
- cProc find_next,PUBLIC
- cBegin
- mov ah,4fh ; Set function code.
- int 21h ; Ask MS-DOS to look for the next
- ; matching file.
- jb fn_err ; Branch on error.
- xor ax,ax ; Return 0 if no error.
- fn_err:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN54H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 54H: Get Verify Flag ;
- ; ;
- ; int get_verify() ;
- ; ;
- ; Returns current value of verify flag. ;
- ; ;
- ;************************************************************;
-
- cProc get_verify,PUBLIC
- cBegin
- mov ah,54h ; Set function code.
- int 21h ; Read flag from MS-DOS.
- cbw ; Clear high byte of return value.
-
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN56H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 56H: Rename File ;
- ; ;
- ; int rename(poldpath,pnewpath) ;
- ; char *poldpath,*pnewpath; ;
- ; ;
- ; Returns 0 if file moved OK, ;
- ; otherwise returns error code. ;
- ; ;
- ;************************************************************;
-
- cProc rename,PUBLIC,<ds,di>
- parmDP poldpath
- parmDP pnewpath
- cBegin
- loadDP es,di,pnewpath ; ES:DI = pointer to newpath.
- loadDP ds,dx,poldpath ; DS:DX = pointer to oldpath.
- mov ah,56h ; Set function code.
- int 21h ; Ask MS-DOS to rename file.
- jb rn_err ; Branch on error.
- xor ax,ax ; Return 0 if no error.
- rn_err:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN57H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 57H: Get/Set Date/Time of File ;
- ; ;
- ; long file_date_time(handle,func,packdate,packtime) ;
- ; int handle,func,packdate,packtime; ;
- ; ;
- ; Returns a long -1 for all errors, otherwise packs ;
- ; date and time into a long integer, ;
- ; date in high word, time in low word. ;
- ; ;
- ;************************************************************;
-
- cProc file_date_time,PUBLIC
- parmW handle
- parmB func
- parmW packdate
- parmW packtime
- cBegin
- mov bx,handle ; Get handle.
- mov al,func ; Get function: 0 = read, 1 = write.
- mov dx,packdate ; Get date (if present).
- mov cx,packtime ; Get time (if present).
- mov ah,57h ; Set function code.
- int 21h ; Call MS-DOS.
- mov ax,cx ; Set DX:AX = date/time, assuming no
- ; error.
- jnb dt_ok ; Branch if no error.
- mov ax,-1 ; Return -1 for errors.
- cwd ; Extend the -1 into DX.
- dt_ok:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN58H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 58H: Get/Set Allocation Strategy ;
- ; ;
- ; int alloc_strategy(func,strategy) ;
- ; int func,strategy; ;
- ; ;
- ; Strategies: ;
- ; 0: First fit ;
- ; 1: Best fit ;
- ; 2: Last fit ;
- ; ;
- ; Returns -1 for all errors, otherwise ;
- ; returns the current strategy. ;
- ; ;
- ;************************************************************;
-
- cProc alloc_strategy,PUBLIC
- parmB func
- parmW strategy
- cBegin
- mov al,func ; AL = get/set selector.
- mov bx,strategy ; BX = new strategy (for AL = 01H).
- mov ah,58h ; Set function code.
- int 21h ; Call MS-DOS.
- jnb no_err ; Branch if no error.
- mov ax,-1 ; Return -1 for all errors.
- no_err:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN59H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 59H: Get Extended Error Information ;
- ; ;
- ; int extended_error(err,class,action,locus) ;
- ; int *err; ;
- ; char *class,*action,*locus; ;
- ; ;
- ; Return value is same as err. ;
- ; ;
- ;************************************************************;
-
- cProc extended_error,PUBLIC,<ds,si,di>
- parmDP perr
- parmDP pclass
- parmDP paction
- parmDP plocus
- cBegin
- push ds ; Save DS.
- xor bx,bx
- mov ah,59h ; Set function code.
- int 21h ; Request error info from MS-DOS.
- pop ds ; Restore DS.
- loadDP ds,si,perr ; Get pointer to err.
- mov [si],ax ; Store err.
- loadDP ds,si,pclass ; Get pointer to class.
- mov [si],bh ; Store class.
- loadDP ds,si,paction ; Get pointer to action.
- mov [si],bl ; Store action.
- loadDP ds,si,plocus ; Get pointer to locus.
- mov [si],ch ; Store locus.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN5AH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 5AH: Create Temporary File ;
- ; ;
- ; int create_temp(ppathname,attr) ;
- ; char *ppathname; ;
- ; int attr; ;
- ; ;
- ; Returns -1 if file was not created, ;
- ; otherwise returns file handle. ;
- ; ;
- ;************************************************************;
-
- cProc create_temp,PUBLIC,ds
- parmDP ppathname
- parmW attr
- cBegin
- loadDP ds,dx,ppathname ; Get pointer to pathname.
- mov cx,attr ; Set function code.
- mov ah,5ah ; Ask MS-DOS to make a new file with
- ; a unique name.
- int 21h ; Ask MS-DOS to make a tmp file.
- jnb ct_ok ; Branch if MS-DOS returned handle.
- mov ax,-1 ; Else return -1.
- ct_ok:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN5BH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 5BH: Create New File ;
- ; ;
- ; int create_new(ppathname,attr) ;
- ; char *ppathname; ;
- ; int attr; ;
- ; ;
- ; Returns -2 if file already exists, ;
- ; -1 for all other errors, ;
- ; otherwise returns file handle. ;
- ; ;
- ;************************************************************;
-
- cProc create_new,PUBLIC,ds
- parmDP ppathname
- parmW attr
- cBegin
- loadDP ds,dx,ppathname ; Get pointer to pathname.
- mov cx,attr ; Get new file's attribute.
- mov ah,5bh ; Set function code.
- int 21h ; Ask MS-DOS to make a new file.
- jnb cn_ok ; Branch if MS-DOS returned handle.
- mov bx,-2
- cmp al,80 ; Did file already exist?
- jz ae_err ; Branch if so.
- inc bx ; Change -2 to -1.
- ae_err:
- mov ax,bx ; Return error code.
- cn_ok:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN5CH.ASM
-
- ;************************************************************;
- ; ;
- ; Function 5CH: Lock/Unlock File Region ;
- ; ;
- ; int locks(handle,onoff,start,length) ;
- ; int handle,onoff; ;
- ; long start,length; ;
- ; ;
- ; Returns 0 if operation was successful, ;
- ; otherwise returns error code. ;
- ; ;
- ;************************************************************;
-
- cProc locks,PUBLIC,<si,di>
- parmW handle
- parmB onoff
- parmD start
- parmD length
- cBegin
- mov al,onoff ; Get lock/unlock flag.
- mov bx,handle ; Get file handle.
- les dx,start ; Get low word of start.
- mov cx,es ; Get high word of start.
- les di,length ; Get low word of length.
- mov si,es ; Get high word of length.
- mov ah,5ch ; Set function code.
- int 21h ; Make lock/unlock request.
- jb lk_err ; Branch on error.
- xor ax,ax ; Return 0 if no error.
- lk_err:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN5E02H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 5EH Subfunction 02H: ;
- ; Set Printer Setup ;
- ; ;
- ; int printer_setup(index,pstring,len) ;
- ; int index; ;
- ; char *pstring; ;
- ; int len; ;
- ; ;
- ; Returns 0, otherwise returns -1 for all errors. ;
- ; ;
- ;************************************************************;
-
- cProc printer_setup,PUBLIC,<ds,si>
- parmW index
- parmDP pstring
- parmW len
- cBegin
- mov bx,index ; BX = index of a net printer.
- loadDP ds,si,pstring ; DS:SI = pointer to string.
- mov cx,len ; CX = length of string.
- mov ax,5e02h ; Set function code.
- int 21h ; Set printer prefix string.
- mov al,0 ; Assume no error.
- jnb ps_ok ; Branch if no error,
- mov al,-1 ; Else return -1.
- ps_ok:
- cbw
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN5F02H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 5FH Subfunction 02H: ;
- ; Get Assign-List Entry ;
- ; ;
- ; int get_alist_entry(index, ;
- ; plocalname,premotename, ;
- ; puservalue,ptype) ;
- ; int index; ;
- ; char *plocalname; ;
- ; char *premotename; ;
- ; int *puservalue; ;
- ; int *ptype; ;
- ; ;
- ; Returns 0 if the requested assign-list entry is found, ;
- ; otherwise returns error code. ;
- ; ;
- ;************************************************************;
-
- cProc get_alist_entry,PUBLIC,<ds,si,di>
- parmW index
- parmDP plocalname
- parmDP premotename
- parmDP puservalue
- parmDP ptype
- cBegin
- mov bx,index ; Get list index.
- loadDP ds,si,plocalname ; DS:SI = pointer to local name
- ; buffer.
- loadDP es,di,premotename ; ES:DI = pointer to remote name
- ; buffer.
- mov ax,5f02h ; Set function code.
- int 21h ; Get assign-list entry.
- jb ga_err ; Exit on error.
- xor ax,ax ; Else return 0.
- loadDP ds,si,puservalue ; Get address of uservalue.
- mov [si],cx ; Store user value.
- loadDP ds,si,ptype ; Get address of type.
- mov bh,0
- mov [si],bx ; Store device type to type.
- ga_err:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN5F03H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 5FH Subfunction 03H: ;
- ; Make Assign-List Entry ;
- ; int add_alist_entry(psrcname,pdestname,uservalue,type) ;
- ; char *psrcname,*pdestname; ;
- ; int uservalue,type; ;
- ; ;
- ; Returns 0 if new assign-list entry is made, otherwise ;
- ; returns error code. ;
- ; ;
- ;************************************************************;
-
- cProc add_alist_entry,PUBLIC,<ds,si,di>
- parmDP psrcname
- parmDP pdestname
- parmW uservalue
- parmW type
- cBegin
- mov bx,type ; Get device type.
- mov cx,uservalue ; Get uservalue.
- loadDP ds,si,psrcname ; DS:SI = pointer to source name.
- loadDP es,di,pdestname ; ES:DI = pointer to destination name.
- mov ax,5f03h ; Set function code.
- int 21h ; Make assign-list entry.
- jb aa_err ; Exit if there was some error.
- xor ax,ax ; Else return 0.
- aa_err:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN5F04H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 5FH Subfunction 04H: ;
- ; Cancel Assign-List Entry ;
- ; ;
- ; int cancel_alist_entry(psrcname) ;
- ; char *psrcname; ;
- ; ;
- ; Returns 0 if assignment is canceled, otherwise returns ;
- ; error code. ;
- ; ;
- ;************************************************************;
-
- cProc cancel_alist_entry,PUBLIC,<ds,si>
- parmDP psrcname
- cBegin
- loadDP ds,si,psrcname ; DS:SI = pointer to source name.
- mov ax,5f04h ; Set function code.
- int 21h ; Cancel assign-list entry.
- jb ca_err ; Exit on error.
- xor ax,ax ; Else return 0.
- ca_err:
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN62H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 62H: Get Program Segment Prefix Address ;
- ; ;
- ; int get_psp() ;
- ; ;
- ; Returns PSP segment. ;
- ; ;
- ;************************************************************;
-
- cProc get_psp,PUBLIC
- cBegin
- mov ah,62h ; Set function code.
- int 21h ; Get PSP address.
- mov ax,bx ; Return it in AX.
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\FXN63H.ASM
-
- ;************************************************************;
- ; ;
- ; Function 63H: Get Lead Byte Table ;
- ; ;
- ; char far *get_lead_byte_table() ;
- ; ;
- ; Returns far pointer to table of lead bytes for multibyte ;
- ; characters. Will work only in MS-DOS 2.25! ;
- ; ;
- ;************************************************************;
-
- cProc get_lead_byte_table,PUBLIC,<ds,si>
- cBegin
- mov ax,6300h ; Set function code.
- int 21h ; Get lead byte table.
- mov dx,ds ; Return far pointer in DX:AX.
- mov ax,si
- cEnd
-
- \SAMPCODE\DOS_ENCY\SECTION5\INT20H.ASM
-
- ;************************************************************;
- ; ;
- ; Perform a final exit. ;
- ; ;
- ;************************************************************;
- int 20H ; Transfer to MS-DOS.
-
- \SAMPCODE\DOS_ENCY\SECTION5\INT25H.ASM
-
- ;***************************************************************;
- ; ;
- ; Interrupt 25H: Absolute Disk Read ;
- ; ;
- ; Read logical sector 1 of drive A into the memory area ;
- ; named buff. (On most MS-DOS floppy disks, this sector ;
- ; contains the beginning of the file allocation table.) ;
- ; ;
- ;***************************************************************;
-
- mov al,0 ; Drive A.
- mov cx,1 ; Number of sectors.
- mov dx,1 ; Beginning sector number.
- mov bx,seg buff ; Address of buffer.
- mov ds,bx
- mov bx,offset buff
- int 25h ; Request disk read.
- jc error ; Jump if read failed.
- add sp, 2 ; Clear stack.
- .
- .
- .
- error: ; Error routine goes here.
- .
- .
- .
- buff db 512 dup (?)
-
- \SAMPCODE\DOS_ENCY\SECTION5\INT26H.ASM
-
- ;****************************************************************;
- ; ;
- ; Interrupt 26H: Absolute Disk Write ;
- ; ;
- ; Write the contents of the memory area named buff ;
- ; into logical sector 3 of drive C. ;
- ; ;
- ; WARNING: Verbatim use of this code could damage ;
- ; the file structure of the fixed disk. It is meant ;
- ; only as a general guide. There is, unfortunately, ;
- ; no way to give a really safe example of this interrupt. ;
- ; ;
- ;****************************************************************;
-
- mov al,2 ; Drive C.
- mov cx,1 ; Number of sectors.
- mov dx,3 ; Beginning sector number.
- mov bx,seg buff ; Address of buffer.
- mov ds,bx
- mov bx,offset buff
- int 26h ; Request disk write.
- jc error ; Jump if write failed.
- add sp,2 ; Clear stack.
- .
- .
- .
- error: ; Error routine goes here.
- .
- .
- .
- buff db 512 dup (?) ; Data to be written to disk.
-
- \SAMPCODE\DOS_ENCY\SECTION5\INT27H.ASM
-
- ;***************************************************************;
- ; ;
- ; Interrupt 27H: Terminate and Stay Resident ;
- ; ;
- ; Exit and stay resident, reserving enough memory ;
- ; to protect the program's code and data. ;
- ; ;
- ;***************************************************************;
-
- Start: .
- .
- .
- mov dx,offset pgm_end ; DX = bytes to reserve.
- int 27h ; Terminate, stay resident.
- .
- .
- .
- pgm_end equ $
- end start
-
- \SAMPCODE\DOS_ENCY\SECTION5\TEST.ASM
-
- memS = 0 ;Small memory model
- ?PLM = 0 ;C calling conventions
- ?WIN = 0 ;Disable Windows support
-
- include cmacros.inc
- include cmacrosx.inc
-
- sBegin CODE ;Start of code segment
- assumes CS,CODE ;Required by MASM
-
- ;Microsoft C function syntax:
- ;
- ; int addnums(firstnum, secondnum)
- ; int firstnum, secondnum;
- ;
- ;Returns firstnum + secondnum
-
- cProc addnums,PUBLIC ;Start of addnums functions
- parmW firstnum ;Declare parameters
- parmW secondnum
- cBegin
- mov ax,firstnum
- add ax,secondnum
- cEnd
- sEnd CODE
- end
-
- \SAMPCODE\DOS_ENCY\SECTION5\CMACROSX.INC
-
- ; CMACROSX.INC
- ;
- ; This file includes supplemental macros for two macros included
- ; in CMACROS.INC: parmCP and parmDP. When these macros are used,
- ; CMACROS.INC allocates either 1 or 2 words to the variables
- ; associated with these macros, depending on the memory model in
- ; use. However, parmCP and parmDP provide no support for automatically
- ; adjusting for different memory models--additional program code
- ; needs to be written to compensate for this. The loadCP and loadDP
- ; macros included in this file can be used to provide additional
- ; flexibility for overcoming this limit.
-
- ; For example, "parmDP pointer" will make space (1 word in small
- ; and middle models and 2 words in compact, large, and huge models)
- ; for the data pointer named "pointer". The statement
- ; "loadDP ds,bx,pointer" can then be used to dynamically place the
- ; value of "pointer" into DS:BX, depending on the memory model.
- ; In small-model programs, this macro would generate the instruction
- ; "mov dx,pointer" (it is assumed that DS already has the right
- ; segment value); in large-model programs, this macro would generate
- ; the statements "mov ds,SEG_pointer" and "mov dx,OFF_pointer".
-
-
- checkDS macro segmt
- diffcount = 0
- irp d,<ds,DS,Ds,dS> ; Allow for all spellings
- ifdif <segmt>,<d> ; of "ds".
- diffcount = diffcount+1
- endif
- endm
- if diffcount EQ 4
- it_is_DS = 0
- else
- it_is_DS = 1
- endif
- endm
-
- checkES macro segmt
- diffcount = 0
- irp d,<es,ES,Es,eS> ; Allow for all spellings
- ifdif <segmt>,<d> ; of "es".
- diffcount = diffcount+1
- endif
- endm
- if diffcount EQ 4
- it_is_ES = 0
- else
- it_is_ES = 1
- endif
- endm
-
- loadDP macro segmt,offst,dptr
- checkDS segmt
- if sizeD ; <-- Large data model
- if it_is_DS
- lds offst,dptr
- else
- checkES segmt
- if it_is_ES
- les offst,dptr
- else
- mov offst,OFF_&dptr
- mov segmt,SEG_&dptr
- endif
- endif
- else
- mov offst,dptr ; <-- Small data model
- if it_is_DS EQ 0
- push ds ; If "segmt" is not DS,
- pop segmt ; move ds to segmt.
- endif
- endif
- endm
-
- loadCP macro segmt,offst,cptr
- if sizeC ; <-- Large code model
- checkDS segmt
- if it_is_DS
- lds offst,cptr
- else
- checkES
- if it_is_ES
- les offst,cptr
- else
- mov segmt,SEG_&cptr
- mov offst,OFF_&cptr
- endif
- endif
- else
- push cs ; <-- Small code model
- pop segmt
- mov offst,cptr
- endif
- endm
-