Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

"Must Have Reading Material"?? for Dos Programming

49 views
Skip to first unread message

themouse

unread,
Mar 23, 2009, 12:20:12 PM3/23/09
to
I am a windows programmer, interested in programing on and for
FreeDos.

What is a list of must have reading materials that I need to make the
transition.
C or C++, C++ Prefered but C is fine. Not ready for assembly
programing... yet. LOL

It can be a website, text file, pdf, a book I need to get on ebay.

I have been programming for 15 years, and know how to write basic
applications.
so the languages isn't an issue. I thinking more of the memory
management,
graphics, "GUI", lib (is that the right term for the dos equivelent of
dlls)

What ever you can think of.

Thanks,
~theMouse

Richard Bonner

unread,
Apr 1, 2009, 7:26:20 PM4/1/09
to
themouse (usul.th...@gmail.com) wrote:
> I am a windows programmer, interested in programing on and for
> FreeDos.

> What is a list of must have reading materials that I need to make the
> transition.
> C or C++, C++ Prefered but C is fine. Not ready for assembly
> programing... yet. LOL

> It can be a website, text file, pdf, a book I need to get on ebay.


(Snip)


> What ever you can think of.
>

> ~theMouse

*** Probably not quite what you want, but have a look at the list
below. There are some books in there regarding programming for DOS.

http://www.chebucto.ca/~ak621/DOS/DOS-Pub.html


Richard Bonner
http://www.chebucto.ca/~ak621/DOS/

Bill Buckels

unread,
Apr 3, 2009, 4:24:45 AM4/3/09
to
"themouse" <usul.th...@gmail.com> wrote:

>What is a list of must have reading materials that I need to make the
>transition.

Hi theMouse,

I was an MS-DOS programmer in the '80's and 90's and also have been a
Windows programmer since the early 90's. In Windows 3.1 I worked with both
Borland and Microsoft C++. I currently work with Microsoft C++ and Qt in
Windows and gcc and Qt in Linux. Other languages of course too but....

Once an ABC+D (ASM, BASIC, C, C++, DOS) programmer always an ABC+D
programmer.

I have programmed for around 30 years in C on Apple II's, Commodore 64's,
CP/M 80 and CP/M 86 systems, MS-DOS systems, most versions of Windows since
3. Also Think C on the Mac 68K and many Unises like AIX, Solaris, SunOS,
HpUX, Xenix, and several Linuxes. I can also still code in fluent DOS MASM
if I want.

Here's my pedigree:

http://en.wikipedia.org/wiki/User:Bill_Buckels

OK, so what I would do were I you:

Ralf Brown's Interrupt List:

http://www.delorie.com/djgpp/doc/rbinter/ix/

The msdos-programmer-faqFAQ

http://www.faqs.org/faqs/msdos-programmer-faq/part1/

X86 Assembly Language FAQ

http://www.faqs.org/faqs/assembly-language/x86/general/part2/section-3.html

For MS-DOS primarily use int 21h

Freedos is 100% compatible with MS-DOS but nott 100% identical.

http://www.mail-archive.com/freedos...@lists.sourceforge.net/msg02005.html

Tricks of the MS-DOS Masters was one of the books I enjoyed back in the day:

http://www.amazon.com/Waite-Groups-Tricks-MS-DOS-Masters/dp/0672227177

Anyway, I have millions of lines like the following out there. So does
everyone else.

Regards,

Bill

x--- snip ---x


/*
BSVU(C) Copyright Bill Buckels 1990-2009
All Rights Reserved.

A Loader/Viewer for .BSV Saved Text Screen files

Licence Agreement
-----------------

You have a royalty-free right to use, modify, reproduce and
distribute this source code (and/or any modified version)
in any way you find useful, provided you do not compete
with Bill Buckels or his agents, and that you agree that
Bill Buckels has no warranty obligations or liability
whatsoever resulting from any associated loss or damage.

If you do not agree with these terms, remove this source
and all associated files from your computer now.

Description
-----------

This is a companion utility to be used with BSAVED text
images. I hope this code proves informative.

Supported Screen Mode is CGA COLOR TEXT Mode

These .BSV files can be created in the THEDRAW or in
GWBASIC, etc. or aquired using a screen capture program
that saves .BSV files.

This program turns off the cursor, loads the file, waits
for a key press then turns the cursor on and returns the
key value as an exit code. can be used as a slide show
driver or batch menu.

Bill Buckels
bbuc...@mts.net

*/

#include <stdlib.h>
#include <stdio.h>
#include <dos.h>
#include <malloc.h>

#define SCREENSIZE 4000

/* this macro converts a base and offset to a far pointer */
#ifndef MK_FP
#define MK_FP(seg,off) ((char far *)(((long)(seg) << 16) | (off)))
#endif

void main(int argc, char **argv)
{
FILE *fp; /* screen image file ptr */
unsigned char *psnDataBuf; /* screen image buffer */
unsigned char far *lpCrt; /* screen memory address */
unsigned uiRetVal = 0, /* exit code */
SCREENSEG = 0xb000; /* initial screen segment */
union REGS inregs, outregs; /* regs structures for asm */
int idx; /* scratch counter */

if (argc < 2) {
/* put usage help if no args entered on command line */
puts("BSVU(C) Copyright Bill Buckels 1990-2009");
puts("All Rights Reserved.");
puts("Usage is \"BSVU [image.bsv]\"");
}
else {
/* if we can't allocate memory just bail-out */
if (NULL != (psnDataBuf=malloc(SCREENSIZE))) {
/* if we can open it... */
if (NULL != (fp = fopen(argv[1], "rb"))) {
fread(psnDataBuf,7, 1, fp);
/* check header for valid image */
if (psnDataBuf[0] == (unsigned char)'\xfd' &&
psnDataBuf[1] == (unsigned char)'\x00') {
/* if valid, read it in! */
fread(psnDataBuf,SCREENSIZE, 1, fp);
fclose(fp);
/* get equipment list from the bios */
int86(0x11, &inregs, &outregs);
/* get display type (bits 4 and 5 of ax) */
if ((outregs.x.ax & 0x30) < 0x30)
SCREENSEG=0xb800;
/* point to the screen */
lpCrt = MK_FP(SCREENSEG,0x0000);
/* turn cursor off */
inregs.x.ax = 0x0100;
inregs.x.cx = 0x2000;
int86(0x10,&inregs,&outregs);
/* read the buffer into the screen */
for(idx=0; idx<SCREENSIZE; idx++)
lpCrt[idx] = psnDataBuf[idx];
/* wait for a key press */
inregs.x.ax = 0x0000;
inregs.x.dx = 0x0000;
/* generate int 16h */
int86(0x16,&inregs,&outregs);
/* return the low order char */
uiRetVal = outregs.x.ax&0x00ff;
/* turn cursor on */
inregs.x.ax = 0x0100;
inregs.x.cx = 0x0607;
int86(0x10,&inregs,&outregs);
}
else {
fclose(fp);
puts("Invalid Screen Image!");
}
}
else
perror(argv[1]);
free(psnDataBuf);
}
}
/* exit with a keypress value if no error */
exit(uiRetVal);
}


Bill Buckels

unread,
Apr 3, 2009, 4:53:35 AM4/3/09
to

"Bill Buckels" <bbuc...@mts.net> wrote:
>A Loader/Viewer for .BSV Saved Text Screen files

See below. This code is from an old hybrid bundle that I once wrote called
WINBMP. You can download the whole old thing at:

http://www.teacherschoice.ca/cprog/winbmp30.zip

Source included.

The code below is for a tsr which is assembled with masm then made into a
com using exe2bin. It is a companion to the code I posted previously.
Instead of exe2bin a person should probably use execom today.

Assemble under Windows XP using:

Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997. All rights reserved.

Microsoft (R) Segmented Executable Linker Version 5.60.339 Dec 5 1994
Copyright (C) Microsoft Corp 1984-1993. All rights reserved.

EXECOM v.0499 Copyright (c) 1988,1989,1999 Thomas G. Hanlin III

Here are the steps:

@echo off
rem MASM.BAT
if not exist %1.asm goto NOTFOUND
c:\masm\ml /c %1.asm
c:\masm\link %1.obj, %1.exe, NUL,,NUL
if exist %1.exe erase %1.obj
c:\masm\execom %1.exe %1.com
goto END
:NOTFOUND
echo %1.ASM was not found!
echo Usage is : MASM [BaseName only - .ASM is assumed]
:END

From my point of view, if a programmer is going to call themselves an MS-DOS
programmer, the minimum I expect is a good working knowledge of interrupts,
and a a good working knowledge of low level adresses like where the screen
lives and how the file system works etc.

The goal here for you would be to take the two programs that I have posted
here and build them. Then capture some DOS screens from 80 column text
programs and display them and actually understand what you have done.

Keep in mind that also in my view a C Windows programmer should know how to
code at the Win32 API level.

Bill

x--- snip ---x

; Program Name : grabsv.asm
; Author : bill buckels
; Date : oct 1993
;;Revised jul 1996
;; removed the installation check
;; this causes some pentiums and PS2 compatible bios to
hang

; Purpose : a memory resident text screen grabber
; saves to disk in BSAVED image format

kb_data equ 60h ;keyboard data port
kb_ctrl equ 61h ;keyboard control port
eoi equ 20h ;8259 end-of-interrupt value
int_ctrl_port equ 20h ;8259 PIC port
alt_key equ 8 ;alt key shift code
period equ 34h ;hot key
_psegoff equ 22 ;interrupt vector table address for
_poffoff equ 20 ;the print screen handler vector entries

code segment para public 'code'
assume cs:code
org 100h
begin: jmp initialize ;jump to initialization code

_crt dd 0b8000000h ;CGA screen address
_vmodeptr dd 0400049h ;BIOS display mode record
_installed dd 0415h ;Our Signature
pseg dw ? ;Our Printscreen Vector Table Entries
poff dw ?
dos_seg dw ? ;Dos Busy ?
indos dw ? ;offset to indos flag
video_seg dw 0b800h ;CGA segment

ourpsp dw ? ;save our psp for context switch
theirpsp dw ? ;use their psp to restore context


; The Other ISR's in the chain must be serviced
old_int_9h label dword ;old keyboard interrupt vector
old_keyboard_int dw 2 dup (?)
old_int_1ch label dword ;old timer interrupt vector
old_timer_int dw 2 dup (?)
old_int_28h label dword ;old dos idle interrupt vector
old_dos_int dw 2 dup (?)

hotkeystat db 0 ;status of keyboard interrupt routine
dos_busy db 0 ;status of dos
vid_ctr dw 6 ;length of user defined filename
progress db 0 ;is a screen save in progress ?
tick_cnt db 0 ;timer counter

fheader db 0fdh, 0, 0b8h, 0, 0, 0a0h, 0fh ; bsaved header
footer db 1ah
buff db 'S' ; input field complete with screen attributes
db 70h
db 'V'
db 70h
db 'G'
db 70h
db 'R'
db 70h
db 'A'
db 70h
db 'B'
db 70h
db '0'
db 70h
db '0'
db 70h
db '.'
db 70h
db 'B'
db 70h
db 'S'
db 70h
db 'V'
db 70h
db ' '
db 70h
db ' ',1fh
db 'F',1fh
db 'i',1fh
db 'l',1fh
db 'e',1fh
db 'n',1fh
db 'a',1fh
db 'm',1fh
db 'e',1fh
db '?',1fh
db ' ',1fh

screenbuffer db 48 dup(?) ; save the screen under the field

fname DB 'SVGRAB00.BSV',0 ; filename buffer
fcnt1 DB '0' ; filename counters
fcnt2 DB '0'
handle DW ? ; filehandle

;-------------------------------------------------------
;Resident mainline and ISR routines
;-------------------------------------------------------

; hook the dos idle loop
; reset the dos busy flag if we are called
newdos proc near
mov dos_busy,0
jmp old_int_28h
iret
newdos endp

;check if dos is busy
;ortoo in case the printscreen vectors get messed-up
;put our routine back again
timertick proc near
sti
push ax
push cx
push dx
push bx
push sp
push bp
push si
push di
push ds
push es
mov bp,sp
cmp progress,0
jne inprogress
push cs ;put code seg into data seg
pop ds

mov dos_busy,0 ;test for dos busy?
mov ax,dos_seg
mov es,ax
mov bx,indos
cmp BYTE PTR es:[bx],0 ;if not we quietly leave
je SKIPDOS
mov dos_busy,1
SKIPDOS:
;replace the printscreen vectors
;every 5- seconds if it has been changed
inc tick_cnt
cmp tick_cnt,91
jl inprogress
mov tick_cnt,0

mov ax,0
mov es,ax

mov bx,_psegoff
mov ax, WORD PTR es:[bx]
cmp ax, pseg
je OK_SKIP
mov ax,pseg
mov WORD PTR es:[bx],ax

OK_SKIP:

mov bx,_poffoff
mov ax, WORD PTR es:[bx]
cmp ax, poff
je inprogress
mov ax, poff
mov WORD PTR es:[bx],ax

inprogress:
mov sp,bp
pop es
pop ds
pop di
pop si
pop bp
pop bx
pop bx
pop dx
pop cx
pop ax
cli
jmp old_int_1ch
iret
timertick endp

; when printscreen is pressed, save the screen to disk
printscreen proc near
sti
mov progress,1 ; don't bother us... we're busy
push ax
push cx
push dx
push bx
push sp
push bp
push si
push di
push ds
push es
mov bp,sp

les bx,DWORD PTR _vmodeptr ;are we in text mode 3 or less
cmp BYTE PTR es:[bx],3 ;if not we quietly leave
ja FALSEXIT
cmp dos_busy,0 ;is dos busy ?
jne FALSEXIT

;prepare for context switching
mov ah, 51h
int 21h
mov theirpsp,bx
mov ah, 50h
mov bx, ourpsp
int 21h

push cs ;put code seg into data seg
pop ds

;create the user name
lea dx, fname ; load the dos name buffer into es:[di]
mov di,dx
push ds
pop es

lea dx, buff ; load the field name buffer into ds:[si]
mov si, dx

doname:

mov al, BYTE PTR ds:[si] ;move the field into the dos buffer
cmp al, 32 ;skip the screen attributes
je finished ;Blank ? We are done
mov BYTE PTR es:[di],al
add si,2
inc di
jmp doname

finished:

mov al,0 ;Replace the Blank with a NULL terminator
mov BYTE PTR es:[di],al
sub di,5
mov al,fcnt1 ;Embed the Counter Values Into The Name
mov BYTE PTR es:[di],al
dec di
mov al,fcnt2
mov BYTE PTR es:[di],al

push ds ;Create/Truncate a Normal File
lea dx, fname
xor cx,cx
mov ah,3ch
int 21h
jc MYEXIT
pop ds
mov handle,ax ;save the handle for subsequent operations
inc fcnt1 ;increment filename
cmp fcnt1,'9'
jle DOIT
mov fcnt1,'0'
inc fcnt2
cmp fcnt2,'9'
jle DOIT
mov fcnt2,'0'
jmp DOIT


FALSEXIT:
jmp TRUEXIT

DOIT:
; write the header
push ds
lea dx, fheader
mov bx,handle
mov cx,7
mov ah,40h
int 21h
jc MYEXIT
pop ds

; point to the screen
; write the body... 4000 bytes
push ds
mov bx,handle
mov ds,video_seg
xor dx,dx
mov cx,4000
mov ah,40h
int 21h
jc MYEXIT
pop ds

; write the footer
push ds
lea dx, footer
mov bx,handle
mov cx,1
mov ah,40h
int 21h
jc MYEXIT
pop ds

push ds
;close the file
mov ah,3eh
mov bx,handle
int 21h
mov ah,2
mov dl,7
int 21h
MYEXIT:
pop ds
clc
mov ah, 50h
mov bx, theirpsp
int 21h
TRUEXIT:
mov sp,bp
pop es
pop ds
pop di
pop si
pop bp
pop bx
pop bx
pop dx
pop cx
pop ax
mov progress,0 ;ok! we're not saving...
cli
iret
printscreen endp


keypress proc near
cmp hotkeystat,0 ;already displayed?
jne short_exit ;yes, then exit immediately
sti ;enable interrupts
push ax ;save registers
push bx
push cx
push dx
push si
push di
push ds
push es
in al,kb_data ;get scan code from keyboard
cmp al,period ;was the period pressed?
jne exit ;no, then exit to normal routine
mov ah,2 ;get state of shift keys
int 16h
test al,alt_key ;is the Alt key depressed?
jne startup ;yes, then continue

;Exit is achieved thru here when execution is to be
;transferred to the normal
;BIOS keyboard interrupt handling routine.

exit: pop es ;restore registers
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
short_exit: jmp old_int_9h ;goto BIOS keyboard routine

;The key combination Alt-Period was just pressed.
;Reset the keyboard and issue an
;EOI to the 8259 PIC to enable hardware interrupts.

startup: call kb_reset ;reset keyboard, end 8259 int
push cs ;set DS and ES to the code segment
pop ds
push cs
pop es
assume ds:code

;Check the current video mode to see if it's 80-column text mode 3
;If it's not, gracefully abort this
;routine by exiting thru an IRET.
;Set the interrupt routine status flag and
;Save the contents of the portion of the screen
;that will underlie the input field.
;Wait for a keypress.

mov ah,15 ;get display mode
int 10h
cmp al,3 ;mode 3?
jne done ;yes, then continue
mov hotkeystat,1 ;set interrupt routine status flag
mov fcnt1,'0' ;reset the counters
mov fcnt2,'0'
call open_screen ;save screen contents

getaction: mov ah,0 ;get a keypress
int 16h
cmp al,0 ;is it an extended code?
je getaction ;yes, then ignore
cmp al,13 ;Enter key pressed?
je do_done ;no, then process
cmp al,8 ;backspace pressed
je process ;allow only alpha-numeric input
cmp al,'z'
ja getaction
cmp al,'a'
jae process
cmp al,'Z'
ja getaction
cmp al,'A'
jae process
cmp al,'9'
ja getaction
cmp al,'0'
jb getaction
process:
call update
jmp getaction

;The Enter Key has been pressed.
;Restore the original contents of the screen,
;reset the status flag, and exit to the application.

do_done:
call close_screen ;restore video memory contents
mov hotkeystat,0 ;reset status flag
done: pop es ;restore register values for exit
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
iret ;return to interrupted program
keypress endp

;KB_RESET resets the keyboard and issues an EOI to the 8259 PIC.
kb_reset proc near
in al,kb_ctrl ;get current control port value
mov ah,al ;save it in AH
or al,80h ;set bit 7
out kb_ctrl,al ;send reset value
mov al,ah ;get original value
out kb_ctrl,al ;send it out to enable keyboard
cli ;suspend interrupts
mov al,eoi ;get EOI value
out int_ctrl_port,al ;send EOI to 8259
sti ;enable interrupts
ret
kb_reset endp

;call from keyboard handler to update the field
;and the screen as required
update proc near
push es
push ds
push ax
push bx
push dx
push si
push di

push cs
pop ds

cmp al, 8 ;backspace... push everything back
jne normal ;no? then insert a character
cmp vid_ctr,0 ;first character? don't allow underflow!
jle keydone ;skip it!

dec vid_ctr
lea dx, buff
mov di, dx
mov bx,vid_ctr
shl bx,1
mov si,bx
add di,si

reverse: ;pull the current character out
add di,2
mov al,BYTE PTR ds:[di]
sub di,2
mov BYTE PTR ds:[di],al
add di,2
add si,2
cmp si,24
jl reverse

jmp keyupdate ;display the shorter field

normal:
cmp vid_ctr,5 ;6-character limit
jg keydone ;skip it!
push ax ;save the character
lea dx, buff
mov di, dx
mov bx,vid_ctr
shl bx,1
mov si,bx
add si,14
add di,si

forward: ;make a space for the character

mov al,BYTE PTR ds:[di]
add di,2
mov BYTE PTR ds:[di],al
sub di,4
sub si,2
cmp si,bx
jne forward

pop ax ;pop the character and insert it.
mov BYTE PTR ds:[di],al
inc vid_ctr

keyupdate:
lea dx, buff ;point to the field
mov di, dx
mov es, video_seg ;point to the screen
xor si,si

keydo:
mov al,BYTE PTR ds:[di] ; display the entry field
mov BYTE PTR es:[si],al ; all 24 characters
inc di
inc si
cmp si,48
jl keydo
keydone:

pop di
pop si
pop dx
pop bx
pop ax
pop ds
pop es
ret
update endp

close_screen proc near
push es
push ds
push ax
push dx
push si
push di

push cs
pop ds
lea dx, screenbuffer
mov di, dx
mov es, video_seg
xor si,si

closeit:
mov al, BYTE PTR ds:[di] ; restore the screen
mov BYTE PTR es:[si],al
inc di
inc si
cmp si,48
jl closeit

pop di
pop si
pop dx
pop ax
pop ds
pop es
ret
close_screen endp

open_screen proc near
push es
push ds
push ax
push dx
push si
push di

push cs
pop ds
lea dx, screenbuffer
mov di, dx
mov es, video_seg
xor si,si

open1:
mov al, BYTE PTR es:[si] ; save the screen
mov BYTE PTR ds:[di],al
inc di
inc si
cmp si,48
jl open1

lea dx, buff
mov di,dx
xor si,si

open2:
mov al,BYTE PTR ds:[di] ; display the entry field
mov BYTE PTR es:[si],al
inc di
inc si
cmp si,48
jl open2

pop di
pop si
pop dx
pop ax
pop ds
pop es
ret
open_screen endp

;------------------------------------------------------------
; RESIDENT PORTION ENDS *** TRANSIENT PORTION STARTS
;------------------------------------------------------------

TITLE$ db 'ษออออออออออออออออออออออออออออออออออออออออออออออออป',13,10
db 'บ GRABSV(C) Copyright by Bill Buckels 1993,1996 บ',13,10
db 'บ A Memory Resident Text-Screen Frame-Grabber บ',13,10
db 'บ บ',13,10
db 'บ Press Shift-Print Screen to Save Text Images บ',13,10
db 'บ Text Screens will be saved in BSAVED Format บ',13,10
db 'บ บ',13,10
db 'บ Press Alt-Period To Over-ride Image Name บ',13,10
db 'ศออออออออออออออออออออออออออออออออออออออออออออออออผ'
TERM$ db 32 ; replace with a terminator
db 13,10
db 'Disclaimer: Although due care and caution is exercised by GRABSV(C),'
db 13,10
db 'Conflicts may arise when used with some programs or other TSRs.'
db 13,10
db 'This is also true with any TSR, especially those that write to disk.'
db 13,10
db 'Warning!!! Do Not Load More than 1 copy. The Installation check has
been'
db 13, 10
db 'Removed for this version...'
db 13, 10
db 'Bill Buckels will not be held responsible for loss or damage caused by'
db 13,10
db 'the use of this program. Do you wish to continue ? (Y/N) $'

DUPE$ db 10,13,7,'GRABSV(C) is already installed!$'
NOWLOAD$ db 10,13,'GRABSV(C) is Now Resident!'
NICEDOS$ db 10,13,1,2,'Have a Nice Dos!$'

NEEDCGA$ db 'ษออออออออออออออออออออออออออออออออออออออออออออออออป',13,10
db 'บ GRABSV(C) Copyright by Bill Buckels 1993,1996 บ',13,10
db 'บ A Memory Resident Text-Screen Frame-Grabber บ',13,10
db 'ศออออออออออออออออออออออออออออออออออออออออออออออออผ',13,10
db 'A CGA Compatible Video Adapter is Required to Use
GRABBSV(C)',13,10
db 'It must be in 80 x 25 Text Mode...$'

;LIST$ writes a string to stdout
LIST$ proc near
mov ah,9h ; call dos function 9H
int 21h
ret
LIST$ endp

;exit if the answer is no!
YESNO$ proc near
mov ah,15 ;get display mode
int 10h
cmp al,3 ;mode 3?
jne notcga ;yes, then continue

;; removed the installation check
;; this causes some pentiums and PS2 compatible bios to hang
;; les bx,DWORD PTR _installed ;are we already installed
;; cmp BYTE PTR es:[bx],128 ;if so we leave
;; je installed

lea dx, TITLE$
call LIST$
mov ah,1
int 21h
cmp al,'Y'
je agree
cmp al,'y'
je agree
lea dx,NICEDOS$
call LIST$
int 20h
notcga:
lea dx, NEEDCGA$
call LIST$
lea dx, NICEDOS$
call LIST$
int 20h
installed:
mov TERM$,'$'
lea dx, TITLE$
call LIST$
lea dx, DUPE$
call LIST$
lea dx, NICEDOS$
call LIST$
int 20h
agree:
lea dx, NOWLOAD$
call LIST$
;; removed the installation check
;; this causes some pentiums and PS2 compatible bios to hang
;; mov al, 128
;; les bx,DWORD PTR _installed ;installed signature
;; mov BYTE PTR es:[bx],al
ret
YESNO$ endp

;INITIALIZE performs tasks to set the stage for the resident part
;of the program.

initialize proc near

;let them know who we are

call YESNO$

;prepare for context switching
;save our psp
mov ah, 51h
int 21h
mov ourpsp,bx

;get the address of the dos busy flag
mov ah, 34h
int 21h
mov dos_seg,es
mov indos,bx

;save keyboard
mov ah,35h ;get current interrupt 9 vector
mov al,9
int 21h
mov old_keyboard_int,bx ;save vector offset
mov old_keyboard_int[2],es ;save vector segment
; save dos idle
mov ah,35h ;get current interrupt 28h vector
mov al,28h
int 21h
mov old_dos_int,bx ;save vector offset
mov old_dos_int[2],es ;save vector segment
; save timer tick
mov ah,35h ;get current interrupt 1ch vector
mov al,1ch
int 21h
mov old_timer_int,bx ;save vector offset
mov old_timer_int[2],es ;save vector segment

mov ah,25h ;set new printscreen vectors
mov al,5
lea dx,printscreen ;point it to new handler
int 21h
;save the address of the printscreen vectors
mov ah, 35h
mov al, 5
int 21h
mov pseg,es
mov poff,bx

mov ah,25h ;set new keyboard vectors
mov al,9
lea dx,keypress ;point it to new handler
int 21h
mov ah,25h ;set new dos idle vectors
mov al,28h
lea dx,newdos ;point it to new handler
int 21h
mov ah,25h ;set new timertick vectors
mov al,1ch
lea dx,timertick ;point it to new handler
int 21h


;Exit thru INT 27h and reserve some room
;the offset of TITLE$ is a marker to end of resident code

mov dx,offset TITLE$ ;reserve space for code
int 27h ;terminate-but-stay-resident
initialize endp

code ends
end begin

Bill Buckels

unread,
Apr 3, 2009, 5:13:57 AM4/3/09
to

"Bill Buckels" <bbuc...@mts.net> wrote:

>See below. This code is from an old hybrid bundle that I once wrote called
>WINBMP. You can download the whole old thing at:

> http://www.teacherschoice.ca/cprog/winbmp30.zip

> Source included.

This one is for a printer capture buffer TSR. Assemble using the steps
outlined earlier in this thread for the other TSR.

I will post the C code that uses this buffer separately.

Bill

x--- snip ---x

; Program Name : REAPER.ASM
; Author : bill buckels
; Date : July, 1993
; Purpose : provide a 32K buffer in memory for printed output
; use interrupt 17h function FFh

; Uses : intercept report output passthrough on the
; way to the printer and create a copy in memory
; which can later be saved to disk using SOWER.EXE

; return ax = numberofbytes in buffer
; return bx = offset of buffer
; return cx = segment of buffer
; return dx = numberofbytes in buffer

; calling sequence : call twice. the first call will contain
; exactly the same value in ax and dx.
; The second call will show ax and cx back to 0.
; See Sower.C for more details.

cr equ 0dh ;carriage return
lf equ 0ah ;line feed


CODE SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CODE
ORG 100h

BEGIN: jmp INITIALIZE ;jump to initialization code


old_int_17h label dword ;old printer interrupt vector
old_printer_int dw 2 dup (?)

bufoff dw 0 ; segment of buffer
bufseg dw 0 ; offset of buffer
bufctr dw 0 ; buffer tail
buffer db 32767 dup('A')

;-------------------------------------------------------
;Resident mainline and Front-end routine for the printer
;interrupt handler. Execution is vectored here
;when the printer is called
;-------------------------------------------------------

PRINTIT PROC NEAR
sti


push ax ;save registers
push bx
push cx
push dx
push si
push di
push ds
push es

cmp ah, 255 ; function 255 - reset buffer
je CHANGE_ALL ; and return address

cmp ah, 0 ; function 0 - send byte to printer
jne CHANGE_NOTHING ; don't bother if not

cmp bufctr,32767 ; don't bother if buffer is full
jge CHANGE_NOTHING

mov si,bufctr
mov [buffer][si],al ; otherwise move a byte to buffer
inc bufctr

CHANGE_NOTHING:
pop es ;restore the registers


pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax

jmp old_int_17h ;goto BIOS printer routine

CHANGE_ALL:
mov cx,cs ; cx = buffer seg
mov bx,offset buffer ; bx = buffer offset
mov dx,bufctr ; dx = byte count
mov bufctr,0 ; reset the buffer head
pop es ; restore the registers


pop ds
pop di
pop si

pop ax
pop ax
pop ax
pop ax
mov ax,dx
iret
PRINTIT ENDP


;------------------------------------------------------------
; RESIDENT PORTION ENDS *** TRANSIENT PORTION STARTS
;------------------------------------------------------------

;------------------------------------------------------------
;initialization message - the requested time limit is inserted here
;------------------------------------------------------------
TITLE$ db 'ษอออออออออออออออออออออออออออออออออป',cr,lf
db 'บ Reaper(C) by Bill Buckels 1993 บ',cr,lf
db 'บ Memory resident printed output บ',cr,lf
db 'บ interception and passthrough บ',cr,lf
db 'บ Driver Module บ',cr,lf
db 'ศอออออออออออออออออออออออออออออออออผ',cr,lf,'$'

SORRY$ db 7,'Error During Loading... Reaper is Already in
Memory!',cr,lf,'$'

;------------------------------------------------------------


;LIST$ writes a string to stdout

;------------------------------------------------------------
LIST$ PROC NEAR
push ax


mov ah,9h ; call dos function 9H
int 21h

pop ax
ret
LIST$ ENDP

;----------------------------------------------------------------


;INITIALIZE performs tasks to set the stage for the resident part
;of the program.

;-----------------------------------------------------------------
INITIALIZE PROC NEAR

;let them know who we are

lea dx, TITLE$
call LIST$

;Check memory for ourselves already loaded
;and quit if we are

mov ah,255
int 17h
cmp ax,dx
jne FIRSTIME
mov ah,255
int 17h
cmp ax,dx
jne FIRSTIME
cmp dx,0
jne FIRSTIME
lea dx, SORRY$
call LIST$
int 20h

FIRSTIME:

;Now save the printer vector and replace it
;with one pointing to the
;code that we will leave behind in memory.

mov ah,35h ;get current interrupt 17H vector
mov al,17h
int 21h
mov old_printer_int,bx ;save vector offset
mov old_printer_int[2],es ;save vector segment

mov ah,25h ;set new vector
mov al,17h
lea dx,PRINTIT ;point it to new handler
int 21h

;Exit thru INT 27h and reserve enough room


;the offset of TITLE$ is a marker to end of resident code

mov dx,offset TITLE$ ;reserve space for code
int 27h ;terminate-but-stay-resident

INITIALIZE ENDP
;
CODE ENDS
END BEGIN

Bill Buckels

unread,
Apr 3, 2009, 5:17:52 AM4/3/09
to
"Bill Buckels" <bbuc...@mts.net> wrote:

>See below. This code is from an old hybrid bundle that I once wrote called
>WINBMP. You can download the whole old thing at:

> http://www.teacherschoice.ca/cprog/winbmp30.zip

> Source included.

>This one is for a printer capture buffer TSR.

>I will post the C code that uses this buffer separately.

Here it is:

x--- snip ---x

/* sower.c by bill buckels 1993 */
#include <dos.h>
#include <stdio.h>

char *hello=
"ษอออออออออออออออออออออออออออออออออป\n"
"บ SOWER(C) by Bill Buckels 1993 บ\n"
"บ Memory resident printed output บ\n"
"บ interception and passthrough บ\n"
"บ Data Aquisition Module บ\n"
"ศอออออออออออออออออออออออออออออออออผ\n";

/* this macro converts a base and offset to a far pointer */
#ifndef MK_FP
#define MK_FP(seg,off) ((char far *)(((long)(seg) << 16) | (off)))
#endif


main()
{
union REGS inregs, outregs;
unsigned numbytes,numcheck;
unsigned char far *ptr;
FILE *fp;

puts(hello);

/* call twice */
inregs.h.ah = 255;
int86(0x17,&inregs,&outregs);
numbytes = outregs.x.ax;
numcheck = outregs.x.dx;
int86(0x17,&inregs,&outregs);

if(numbytes!=numcheck)
{
puts(" Sorry... Reaper.com not in memory!");
exit(0);
}
if(outregs.x.dx != 0 || outregs.x.ax != 0)
{
puts(" Sorry... Reaper.com not in memory!");
exit(0);

}


if(numbytes == 0)
{
puts("Sorry... Nothing in Buffer.");
}
else
{
if((fp=fopen("REAPER.TXT","ab"))==NULL)
{
perror(" REAPER.TXT");
}
else
{
printf("Now appending %d bytes to REAPER.TXT\n",numbytes);
ptr=MK_FP(outregs.x.cx,outregs.x.bx);
fwrite((char far *)&ptr[0],numbytes,1,fp);
fclose(fp);
}

}
puts("Done!");
exit(0);

}


Bill Buckels

unread,
Apr 3, 2009, 6:08:25 AM4/3/09
to

"Bill Buckels" <bbuc...@mts.net> wrote:

>BSVU(C) Copyright Bill Buckels 1990-2009

For my 16 bit programs I primarily use the command line compiler that came
with MSVC 1.53; "Microsoft (R) C/C++ Optimizing Compiler Version 8.00c
Copyright (c) Microsoft Corp 1984-1993. All rights reserved". This was, as
far as I know, the last 16 bit compiler that Microsoft released.

You might want to google "Visual C 1.5 torrent" at some point. Over the
years "free" compilers that were available from Microsoft have disappeared
from their websites.

This is not to say that my programs can't be built with other 16 bit
compilers. You could also visit my Aztec C Website and get an MS-DOS C
compiler of an older vintage:

http://www.aztecmuseum.ca/

For assembly language programming, as a starting point you can obtain more
information from The MASM32 Project. Just a note again on converting
assembled EXE files to 16 bit COM files under Windows XP. You will see in a
previous post that I have used EXECOM as the last step in my assembly
language build sequence. EXE2BIN is waytoo DOS version specific.

http://www.masm32.com/

Anyway here's the makefile for the BSVU program:

Bill

x--- snip ---x

all: bsvu.exe

bsvu.obj: bsvu.c
cl -c -AL -Zp1 bsvu.c

bsvu.exe: bsvu.obj bsvu.c bsvu.mak
link bsvu.obj,, NUL, /ST:8192 /NOE /NOD oldnames llibce, NUL
del bsvu.obj


Bill Buckels

unread,
Apr 5, 2009, 11:18:47 AM4/5/09
to

"Bill Buckels" <bbuc...@mts.net> wrote:

>For assembly language programming, as a starting point you can obtain more
>information from The MASM32 Project.

The MASM32 Project Licence can be found here:

http://www.masm32.com/mlicence.htm

Some links to free C compilers can be found here:

http://www.thefreecountry.com/compilers/cpp.shtml

A good link for free assemblers is:

http://www.thefreecountry.com/compilers/assemblers.shtml

Bill

0 new messages