Initial commit

master
Michael Reber 4 years ago
parent 40a414d210
commit b880c3ccde

@ -0,0 +1,136 @@
;
; This program reads text from the standard input device and writes
; filtered and transformed text to the standard output device.
;
; 1. High bit of all characters is stripped off.
; 2. Tabs are expanded.
; 3. Removes all control codes except for line
; feeds, carriage returns, and form feeds.
; 4. Appends an end-of-file mark to the text, if
; none was present in the input stream.
;
; Can be used to make a WordStar file acceptable for
; other screen or line editors, and vice versa.
;
;
cr equ 0dh ; ASCII carriage return
lf equ 0ah ; ASCII line feed
ff equ 0ch ; ASCII form feed
eof equ 01ah ; End-of-file marker
tab equ 09h ; ASCII tab code
command equ 80h ; buffer for command tail
; DOS 2.0 Pre-Defined Handles
stdin equ 0000 ; standard input file
stdout equ 0001 ; standard output file
stderr equ 0002 ; standard error file
stdaux equ 0003 ; standard auxilliary file
stdprn equ 0004 ; standard printer file
cseg segment para public 'CODE'
assume cs:cseg,ds:cseg
org 100H ; start .COM at 100H
clean proc far ; entry point from PC-DOS.
push ds ; push a long return back
xor ax,ax ; to DOS onto the stack.
push ax
clean3: call get_char ; get a character from input.
and al,7fh ; turn off the high bit.
cmp al,20h ; is it a control char?
jae clean4 ; no. write it to output.
cmp al,eof ; is it end of file?
je clean6 ; yes, go write EOF mark and exit.
cmp al,tab ; is it a tab?
je clean5 ; yes, go expand it to spaces.
cmp al,cr ; is it a carriage return?
je clean35 ; yes, go process it.
cmp al,lf ; is it a line feed?
je clean35 ; yes, go process it.
cmp al,ff ; is it a form feed?
jne clean3 ; no. discard it.
clean35:
mov column,0 ; if it's a legit ctrl char,
jmp clean45 ; we should be back at column 0.
clean4: inc column ; if it's a non-ctrl char,
clean45: ; col = col + 1.
call put_char ; write the char to output.
jnc clean3 ; if OK, go back for another char.
mov bx,stderr ; not OK. Set up to show error.
mov dx,offset err_msg
mov cx,err_msg_len ; error = Disk full.
mov ah,40h ; write the error message
int 21h ; to the standard error device. (CON:)
ret ; back to DOS.
clean5: mov ax,column ; tab code detected, must expand
cwd ; expand tabs to spaces.
mov cx,8 ; divide the current column counter
idiv cx ; by eight...
sub cx,dx ; eight minus the remainder is the
add column,cx ; number of spaces to send out to
clean55: ; move to the next tab position.
push cx
mov al,20h
call put_char ; send an ASCII blank
pop cx
loop clean55
jmp clean3
clean6: call put_char ; write out the EOF mark,
ret ; and return to DOS.
clean endp
get_char proc near
mov bx,stdin ; get chars from std. input
mov cx,1 ; # of chars to get = 1
mov dx,offset input_buffer ; location = input_buffer
mov ah,3fh
int 21h ; do the function call
or ax,ax ; test # of chars returned
jz get_char1 ; if none, return EOF
mov al,input_buffer ; else, return the char in AL
ret
get_char1:
mov al,eof ; no chars read, return
ret ; an End-of-File (EOF) mark.
get_char endp
put_char proc near
mov output_buffer,al ; put char to write in buffer.
mov bx,stdout ; write to std. output
mov cx,1 ; # of chars = 1
mov dx,offset output_buffer ; location = output_buffer
mov ah,40h
int 21h ; do the function call
cmp ax,1 ; check to see it was really done.
jne put_char1
clc ; really done. return carry = 0
ret ; as success signal.
put_char1:
stc ; not really done. return carry = 1
ret ; as error signal (device is full).
put_char endp
input_buffer db 0
output_buffer db 0
column dw 0
err_msg db cr,lf
db 'clean: Disk is full.'
db cr,lf
err_msg_len equ (this byte)-(offset err_msg)
cseg ends
end clean

@ -0,0 +1,310 @@
;
; Macro file for MSDOS.
;
SUBTTL BREAK a listing into pages and give new subtitles
PAGE
BREAK MACRO subtitle
SUBTTL subtitle
PAGE
ENDM
BREAK <I_NEED: declare a variable external, if necessary, and allocate a size>
;
; declare a variable external and allocate a size
;
I_NEED MACRO sym,len
CODE ENDS
DATA SEGMENT BYTE PUBLIC 'DATA'
IFIDN <len>,<WORD>
EXTRN &sym:WORD
ELSE
IFIDN <len>,<DWORD>
EXTRN &sym:DWORD
ELSE
EXTRN &sym:BYTE
ENDIF
ENDIF
DATA ENDS
CODE SEGMENT BYTE PUBLIC 'CODE'
ENDM
;
; call a procedure that may be external. The call will be short.
;
invoke MACRO name
&.xcref
add_ext name,near
&.cref
CALL name
ENDM
PAGE
;
; jump to a label that may be external. The call will be near.
;
transfer MACRO name
&.xcref
add_ext name,near
&.cref
JUMP name
ENDM
;
; get a short address in a word
;
short_addr MACRO name
IFDIF <name>,<?>
&.xcref
add_ext name,near
&.cref
DW OFFSET DOSGROUP:name
ELSE
DW ?
ENDIF
ENDM
;
; get a long address in a dword
;
long_addr MACRO name
&.xcref
add_ext name,far
&.cref
DD name
ENDM
;
; declare a PROC near or far but PUBLIC nonetheless
;
procedure MACRO name,distance
PUBLIC name
name PROC distance
ENDM
PAGE
;
; define a data item to be public and of an appropriate size/type
;
I_AM MACRO name,size
PUBLIC name
IFIDN <size>,<WORD>
name DW ?
ELSE
IFIDN <size>,<DWORD>
name DD ?
ELSE
IFIDN <size>,<BYTE>
name DB ?
ELSE
name DB size DUP (?)
ENDIF
ENDIF
ENDIF
ENDM
PAGE
;
; play games with a possible external. Create a new
; macro for the symbol and text, and string it together
; with a central invoker
;
.xcref
.xcref ?i
.xcref def_mac
.xcref ?z0
.xcref add_ext
.cref
IF1
?i=0
ENDIF
?z0 macro
endm
;
; add an external declaration to s with type t if it is not defined
;
add_ext macro s,t
&.xcref
&.xcref ?&s
&.cref
IFNDEF ?&s
?i = ?i + 1
def_mac ?z&%?i,?z&%(?i-1),s,t
ENDIF
endm
;
; define a macro called that possibly externals s:t and then calls macro n
;
def_mac macro m,n,s,t
&.xcref
&.xcref ?&s
&.xcref m
&.cref
m macro
ifndef s
extrn s:&t
endif
purge m
purge ?&s
n
endm
?&s macro
&endm
endm
;
; call the macro chain
;
do_ext macro
&.xcref
expand_mac ?z%?i
&.cref
endm
PAGE
expand_mac macro m
m
endm
;
; define an entry in a procedure
;
entry macro name
PUBLIC name
name:
endm
BREAK <ERROR - print a message and then jump to a label>
error macro code
local a
.xcref
MOV AL,code
transfer SYS_RET_ERR
.cref
ENDM
BREAK <JUMP - real jump that links up shortwise>
;
; given a label <lbl> either 2 byte jump to another label <lbl>_J
; if it is near enough or 3 byte jump to <lbl>
;
jump macro lbl
local a
.xcref
a:
ifndef lbl&_J ; is this the first invocation
JMP lbl
ELSE
IF lbl&_J GE $
JMP lbl
ELSE
IF ($-lbl&_J) GT 126 ; is the jump too far away?
JMP lbl
ELSE ; do the short one...
JMP lbl&_J
ENDIF
ENDIF
ENDIF
endm
BREAK <RETURN - return from a function>
return macro
local a
.xcref
a:
RET
ret_l = a
endm
BREAK <CONDRET - conditional return>
makelab macro l,cc,ncc
j&ncc a ; j<NCC> a:
return ; return
a: ; a:
ret_&cc = ret_l ; define ret_<CC> to be ret_l
endm
condret macro cc,ncc
local a,b
ifdef ret_l ; if ret_l is defined
if (($ - ret_l) le 126) and ($ gt ret_l)
; if ret_l is near enough then
a: j&cc ret_l ; a: j<CC> to ret_l
ret_&cc = a ; define ret_<CC> to be a:
else
makelab a,cc,ncc
endif
else
ifdef ret_&cc ; if ret_<CC> defined
if (($ - ret_&cc) le 126) and ($ gt ret_&cc)
; if ret_<CC> is near enough
a: j&cc ret_&cc ; a: j<CC> to ret_<CC>
ret_&cc = a ; define ret_<CC> to be a:
else
makelab a,cc,ncc
endif
else
makelab a,cc,ncc
endif
endif
endm
;condret macro cc,ncc
; local a,b
; ifdef ret_l ; if ret_l is defined
; if (($ - ret_l) le 126) and ($ gt ret_l)
; ; if ret_l is near enough then
; a: j&cc ret_l ; a: j<CC> to ret_l
; ret_&cc = a ; define ret_<CC> to be a:
; exitm
; endif
; endif
; ifdef ret_&cc ; if ret_<CC> defined
; if (($ - ret_&cc) le 126) and ($ gt ret_&cc)
; ; if ret_<CC> is near enough
; a: j&cc ret_&cc ; a: j<CC> to ret_<CC>
; ret_&cc = a ; define ret_<CC> to be a:
; exitm
; endif
; endif
; j&ncc a ; j<NCC> a:
; return ; return
; a: ; a:
; ret_&cc = ret_l ; define ret_<CC> to be ret_l
;endm
BREAK <RETZ - return if zero, links up shortwise if necessary>
retz macro
condret z,nz
endm
BREAK <RETNZ - return if not zero, links up shortwise if necessary>
retnz macro
condret nz,z
endm
BREAK <RETC - return if carry set, links up shortwise if necessary>
retc macro
condret c,nc
endm
BREAK <RETNC - return if not carry, links up shortwise if necessary>
retnc macro
condret nc,c
endm

@ -0,0 +1,261 @@
; fibo.asm
; assemble using nasm:
; nasm -o fibo.com -f bin fibo.asm
;
;****************************************************************************
; Alterable Constant
;****************************************************************************
; You can adjust this upward but the upper limit is around 150000 terms.
; the limitation is due to the fact that we can only address 64K of memory
; in a DOS com file, and the program is about 211 bytes long and the
; address space starts at 100h. So that leaves roughly 65000 bytes to
; be shared by the two terms (num1 and num2 at the end of this file). Since
; they're of equal size, that's about 32500 bytes each, and the 150000th
; term of the Fibonacci sequence is 31349 digits long.
;
maxTerms equ 15000 ; number of terms of the series to calculate
;****************************************************************************
; Number digits to use. This is based on a little bit of tricky math.
; One way to calculate F(n) (i.e. the nth term of the Fibonacci seeries)
; is to use the equation int(phi^n/sqrt(5)) where ^ means exponentiation
; and phi = (1 + sqrt(5))/2, the "golden number" which is a constant about
; equal to 1.618. To get the number of decimal digits, we just take the
; base ten log of this number. We can very easily see how to get the
; base phi log of F(n) -- it's just n*lp(phi)+lp(sqrt(5)), where lp means
; a base phi log. To get the base ten log of this we just divide by the
; base ten log of phi. If we work through all that math, we get:
;
; digits = terms * log(phi) + log(sqrt(5))/log(phi)
;
; the constants below are slightly high to assure that we always have
; enough room. As mentioned above the 150000th term has 31349 digits,
; but this formula gives 31351. Not too much waste there, but I'd be
; a little concerned about the stack!
;
digits equ (maxTerms*209+1673)/1000
; this is just the number of digits for the term counter
cntDigits equ 6 ; number of digits for counter
org 100h ; this is a DOS com file
;****************************************************************************
;****************************************************************************
main:
; initializes the two numbers and the counter. Note that this assumes
; that the counter and num1 and num2 areas are contiguous!
;
mov ax,'00' ; initialize to all ASCII zeroes
mov di,counter ; including the counter
mov cx,digits+cntDigits/2 ; two bytes at a time
cld ; initialize from low to high memory
rep stosw ; write the data
inc ax ; make sure ASCII zero is in al
mov [num1 + digits - 1],al ; last digit is one
mov [num2 + digits - 1],al ;
mov [counter + cntDigits - 1],al
jmp .bottom ; done with initialization, so begin
.top
; add num1 to num2
mov di,num1+digits-1
mov si,num2+digits-1
mov cx,digits ;
call AddNumbers ; num2 += num1
mov bp,num2 ;
call PrintLine ;
dec dword [term] ; decrement loop counter
jz .done ;
; add num2 to num1
mov di,num2+digits-1
mov si,num1+digits-1
mov cx,digits ;
call AddNumbers ; num1 += num2
.bottom
mov bp,num1 ;
call PrintLine ;
dec dword [term] ; decrement loop counter
jnz .top ;
.done
call CRLF ; finish off with CRLF
mov ax,4c00h ; terminate
int 21h ;
;****************************************************************************
;
; PrintLine
; prints a single line of output containing one term of the
; Fibonacci sequence. The first few lines look like this:
;
; Fibonacci(1): 1
; Fibonacci(2): 1
; Fibonacci(3): 2
; Fibonacci(4): 3
;
; INPUT: ds:bp ==> number string, cx = max string length
; OUTPUT: CF set on error, AX = error code if carry set
; DESTROYED: ax, bx, cx, dx, di
;
;****************************************************************************
PrintLine:
mov dx,eol ; print combined CRLF and msg1
mov cx,msg1len+eollen ;
call PrintString ;
mov di,counter ; print counter
mov cx,cntDigits ;
call PrintNumericString
call IncrementCount ; also increment the counter
mov dx,msg2 ; print msg2
mov cx,msg2len ;
call PrintString ;
mov di,bp ; recall address of number
mov cx,digits ;
; deliberately fall through to PrintNumericString
;****************************************************************************
;
; PrintNumericString
; prints the numeric string at DS:DI, suppressing leading zeroes
; max length is CX
;
; INPUT: ds:di ==> number string, cx = max string length
; OUTPUT: CF set on error, AX = error code if carry set
; DESTROYED: ax, bx, cx, dx, di
;
;****************************************************************************
PrintNumericString:
; first scan for the first non-zero byte
mov al,'0' ; look for ASCII zero
cld ; scan from MSD to LSD
repe scasb ;
mov dx,di ; points to one byte after
dec dx ; back up one character
inc cx ;
; deliberately fall through to PrintString
;****************************************************************************
;
; PrintString
; prints the string at DS:DX with length CX to stdout
;
; INPUT: ds:dx ==> string, cx = string length
; OUTPUT: CF set on error, AX = error code if carry set
; DESTROYED: ax, bx
;
;****************************************************************************
PrintString:
mov bx, 1 ; write to stdout
mov ah, 040h ; write to file handle
int 21h ; ignore return value
ret ;
;****************************************************************************
;
; AddNumbers
; add number 2 at ds:si to number 1 at es:di of width cx
;
;
; INPUT: es:di ==> number1, ds:si ==> number2, cx= max width
; OUTPUT: CF set on overflow
; DESTROYED: ax, si, di
;
;****************************************************************************
AddNumbers:
std ; go from LSB to MSB
clc ;
pushf ; save carry flag
.top
mov ax,0f0fh ; convert from ASCII BCD to BCD
and al,[si] ; get next digit of number2 in al
and ah,[di] ; get next digit of number1 in ah
popf ; recall carry flag
adc al,ah ; add these digits
aaa ; convert to BCD
pushf ;
add al,'0' ; convert back to ASCII BCD digit
stosb ; save it and increment both counters
dec si ;
loop .top ; keep going until we've got them all
popf ; recall carry flag
ret ;
;****************************************************************************
;
; IncrementCount
; increments a multidigit term counter by one
;
; INPUT: none
; OUTPUT: CF set on overflow
; DESTROYED: ax, cx, di
;
;****************************************************************************
IncrementCount:
mov cx,cntDigits ;
mov di,counter+cntDigits-1
std ; go from LSB to MSB
stc ; this is our increment
pushf ; save carry flag
.top
mov ax,000fh ; convert from ASCII BCD to BCD
and al,[di] ; get next digit of counter in al
popf ; recall carry flag
adc al,ah ; add these digits
aaa ; convert to BCD
pushf ;
add al,'0' ; convert back to ASCII BCD digit
stosb ; save and increment counter
loop .top ;
popf ; recall carry flag
ret ;
;****************************************************************************
;
; CRLF
; prints carriage return, line feed pair to stdout
;
; INPUT: none
; OUTPUT: CF set on error, AX = error code if carry set
; DESTROYED: ax, bx, cx, dx
;
;****************************************************************************
CRLF: mov dx,eol ;
mov cx,eollen ;
jmp PrintString ;
;****************************************************************************
; static data
;****************************************************************************
eol db 13,10 ; DOS-style end of line
eollen equ $ - eol
msg1 db 'Fibonacci(' ;
msg1len equ $ - msg1
msg2 db '): ' ;
msg2len equ $ - msg2
;****************************************************************************
; initialized data
;****************************************************************************
term dd maxTerms ;
;****************************************************************************
; unallocated data
;
; A better way to do this would be to actually ask for a memory
; allocation and use that memory space, but this is a DOS COM file
; and so we are given the entire 64K of space. Technically, this
; could fail since we *might* be running on a machine which doesn't
; have 64K free. If you're running on such a memory poor machine,
; my advice would be to not run this program.
;
;****************************************************************************
; static data
counter: ;
num1 equ counter+cntDigits ;
num2 equ num1+digits ;

@ -0,0 +1,207 @@
name free
page 60,132
title 'FREE --- Report free space on disk'
; FREE --- a utility to report free space on
; the default or selected disk drive.
;
; Requires PC-DOS or MS-DOS 2.0.
;
; Used in the form:
; A> FREE [unit:]
; (item in square brackets is optional)
;
cr equ 0dh ;ASCII carriage return
lf equ 0ah ;ASCII line feed
blank equ 20h ;ASCII space code
eom equ '$' ;end of string marker
; Here we define a dummy segment containing labels
; for the default file control block and the command tail buffer,
; so that the main program can access those locations.
;
psp segment para public 'PSP'
org 05ch
fcb label byte ;default file control block
org 080h
command label byte ;default command buffer
psp ends
cseg segment para public 'CODE'
assume cs:cseg,ds:psp,es:data,ss:stack
get_drive proc near ;get drive selection, if any,
;otherwise obtain the identity
;of the current disk drive.
;Return drive (1=A, 2=B, etc) in AL.
;
mov al,fcb ;Pick up the drive code, parsed
;by DOS into the default file
;control block.
or al,al ;Is it the default?
jnz get_drive1 ;no, use it
mov ah,19h ;Yes, get the actual current
int 21h ;drive from PC-DOS.
inc al ;Increment to match FCB code.
get_drive1: ;Return drive code in AL.
ret
get_drive endp
free proc far ;entry point from PC-DOS
push ds ;save DS:0000 for final
xor ax,ax ;return to PC-DOS
push ax
mov ax,data ;make our data segment
mov es,ax ;addressable via ES register.
mov ah,30h ;check version of PC-DOS.
int 21h
cmp al,2
jae free1 ;proceed, DOS 2.0 or greater.
mov dx,offset msg2 ;DOS 1.x --- print error message
mov ax,es ;and exit. First fix up DS register
mov ds,ax ;so error message is addressable.
jmp free4
free1: call get_drive ;get drive selection into DL.
push es ;copy ES to DS for remainder
pop ds ;of the program...
assume ds:data ;and tell assembler about it.
mov dl,al
add al,'A'-1 ;form drive letter from drive code,
mov outputb,al ;and put it into the output string.
mov ah,36h ;now call DOS to get free disk space.
int 21h
cmp ax,-1 ;was drive invalid?
je free3 ;yes,go print error message
;drive was ok, so now registers are...
;AX=number of sectors per cluster
;BX=available clusters,
;CX=number of bytes per sector,
;DX=total clusters per drive.
;calculate free space:
mul cx ;sectors per cluster * bytes per sector
;(we assume this won't overflow into DX)
mul bx ;then * available clusters
;DX:AX now contains free space in bytes.
;SI = last byte address for converted string.
mov si,offset (outputa+9)
mov cx,10 ;CX = 10, radix for conversion
call bin_to_asc ;convert free space value to ASCII,
mov dx,offset output
jmp free4 ;and print it out.
free3: mov dx,offset msg1 ;illegal drive, print error
free4: mov ah,9 ;print the string whose address
int 21h ;is in DX.
ret ;then return to DOS.
free endp
; Convert 32 bit binary value to ASCII string.
;
; Call with DX:AX = signed 32 bit value
; CX = radix
; SI = last byte of area to store resulting string
; (make sure enough room is available to store
; the string in the radix you have selected.)
;
; Destroys AX, BX, CX, DX, and SI.
;
bin_to_asc proc near ;convert DX:AX to ASCII.
;force storage of at least 1 digit.
mov byte ptr [si],'0'
or dx,dx ;test sign of 32 bit value,
pushf ;and save sign on stack.
jns bin1 ;jump if it was positive.
not dx ;it was negative, take 2's complement
not ax ;of the value.
add ax,1
adc dx,0
bin1: ;divide the 32 bit value by the radix
;to extract the next digit for the
;forming string.
mov bx,ax ;is the value zero yet?
or bx,dx
jz bin3 ;yes, we are done converting.
call divide ;no, divide by radix.
add bl,'0' ;convert the remainder to an ASCII digit.
cmp bl,'9' ;we might be converting to hex ASCII,
jle bin2 ;jump if in range 0-9,
add bl,'A'-'9'-1 ;correct it if in range A-F.
bin2: mov [si],bl ;store this character into string.
dec si ;back up through string,
jmp bin1 ;and do it again.
bin3: ;restore sign flag,
popf ;was original value negative?
jns bin4 ;no, jump
;yes,store sign into output string.
mov byte ptr [si],'-'
bin4: ret ;back to caller.
bin_to_asc endp
; General purpose 32 bit by 16 bit unsigned divide.
; This must be used instead of the plain machine unsigned divide
; for cases where the quotient may overflow 16 bits (for example,
; dividing 100,000 by 2). If called with a zero divisor, this
; routine returns the dividend unchanged and gives no warning.
;
; Call with DX:AX = 32 bit dividend
; CX = divisor
;
; Returns DX:AX = quotient
; BX = remainder
; CX = divisor (unchanged)
;
divide proc near ; Divide DX:AX by CX
jcxz div1 ; exit if divide by zero
push ax ; 0:dividend_upper/divisor
mov ax,dx
xor dx,dx
div cx
mov bx,ax ; BX = quotient1
pop ax ; remainder1:dividend_lower/divisor
div cx
xchg bx,dx ; DX:AX = quotient1:quotient2
div1: ret ; BX = remainder2
divide endp
cseg ends
data segment para public 'DATA'
output db cr,lf
outputa db 10 dup (blank)
db ' bytes free on drive '
outputb db 'x:',cr,lf,eom
msg1 db cr,lf
db 'That disk drive does not exist.'
db cr,lf,eom
msg2 db cr,lf
db 'Requires DOS version 2 or greater.'
db cr,lf,eom
data ends
stack segment para stack 'STACK'
db 64 dup (?)
stack ends
end free

@ -0,0 +1,55 @@
;
; Synopsis: int getsec(drive,numsec,begsec,buffer)
; unsigned int drive; /* 0=A, 1=B, etc. */
; unsigned int numsec; /* Number of sectors to read */
; unsigned int begsec; /* Beginning logical sector */
; char *buffer; /* Transfer address */
;
; Function: The number of sectors specified are transferred
; between the given drive and the transfer address.
; LOGICAL SECTOR NUMBERS are obtained by numbering
; each sector sequentially starting from track 0, head 0,
; sector 1 (logical sector 0) and continuing along the
; same head, then to the next head until the last sector
; on the last head of the track is counted. Thus,
; logical sector 1 is track 0, head 0, sector 2,
; logical sector 2 is track 0, head 0, sector 3, & so on.
;
; Returns: NULL if the operation is successful.
; otherwise, error codes are as follows:
;
; hex 80 Attachment failed to respond.
; hex 40 SEEK operation failed.
; hex 20 Controller failure.
; hex 10 Bad CRC on diskette read.
; hex 08 DMA overrun on operation.
; hex 04 Requested sector not found.
; hex 03 Write attempt on write-protected diskette.
; hex 02 Address mark not found.
; hex FF Unspecified (error other than those above).
;
code segment byte public ;segment registers remain intact
assume cs:code ;all other registers will be destroyed
public getsec
getsec: push bp ;save old frame pointer
mov bp,sp ;get new frame pointer
mov ax,4[bp] ;put drive number into AL
xor ah,ah
mov cx,6[bp] ;number of sectors to fetch
mov dx,8[bp] ;logical record number of 1st sector
mov bx,10[bp] ;pointer to transfer address
int 25h ;BIOS call
jc error ;error has occurred if carry flag = 1
mov al,00H ;NULL to indicate sucessful completion
jmp done
error: cmp al,00H ;detect unspecified error code 00H
jne done ;...change to 0FFh if found to
mov al,0FFH ;...differentiate it from success code
done: xor ah,ah ;return AL only
popf ;remove flags int 0x25 left on stack
pop bp ;restore original frame pointer
ret ;all done
code ends
end

@ -0,0 +1,373 @@
cseg segment para public 'code'
org 100h
alarm proc far
; Memory-resident program to intercept the timer interrupt and display the
; system time in the upper right-hand corner of the display.
; This program is run as 'ALARM hh:mm x', where hh:mm is the alarm time and
; x is '-' to turn the display off. Any other value of x or no value will
; turn the clock on
intaddr equ 1ch*4 ; interrupt address
segaddr equ 62h*4 ; segment address of first copy
mfactor equ 17478 ; minute conversion factor * 16
whozat equ 1234h ; signature
color equ 14h ; color attribute
assume cs:cseg,ds:cseg,ss:nothing,es:nothing
jmp p150 ; start-up code
jumpval dd 0 ; address of prior interrupt
signature dw whozat ; program signature
state db 0 ; '-' = off, all else = on
wait dw 18 ; wait time - 1 second or 18 ticks
hour dw 0 ; hour of the day
atime dw 0ffffh ; minutes past midnite for alarm
acount dw 0 ; alarm beep counter - number of seconds (5)
atone db 5 ; alarm tone - may be from 1 to 255 - the
; higher the number, the lower the frequency
aleng dw 8080h ; alarm length (loop count) may be from 1-FFFF
dhours dw 0 ; display hours
db ':'
dmins dw 0 ; display minutes
db ':'
dsecs dw 0 ; display seconds
db '-'
ampm db 0 ; 'A' or 'P' for am or pm
db 'm'
tstack db 16 dup('stack ') ; temporary stack
estack db 0 ; end of stack
holdsp dw 0 ; original sp
holdss dw 0 ; original ss
p000: ; interrupt code
push ax ; save registers
push ds
pushf
push cs
pop ds ; make ds=cs
mov ax,wait ; check wait time
dec ax ; zero?
jz p010 ; yes - 1 second has elapsed
mov wait,ax ; not this time
jmp p080 ; return
p010: cli ; disable interrupts
mov ax,ss ; save stack
mov holdss,ax
mov holdsp,sp
mov ax,ds
mov ss,ax ; point to internal stack
mov sp,offset estack
sti ; allow interrupts
push bx ; save other registers
push cx
push dx
push es
push si
push di
push bp
mov ax,18 ; reset wait time
mov wait,ax
mov al,state ; are we disabled?
cmp al,'-'
jnz p015 ; no
jmp p070
p015: mov ah,0 ; read time
int 1ah ; get time of day
mov ax,dx ; low part
mov dx,cx ; high part
mov cl,4
shl dx,cl ; multiply by 16
mov bx,ax
mov cl,12
shr bx,cl ; isolate top 4 bits of ax
add dx,bx ; now in upper
mov cl,4
shl ax,cl ; multiply by 16
mov bx,mfactor ; compute minutes
div bx ; minutes in ax, remainder in dx
cmp ax,atime ; time to sound the alarm?
jnz p020 ; no
call p100 ; yes - beep the speaker twice
push ax
mov ax,acount ; get beep count
dec ax ; down by 1
mov acount,ax ; save beep count
cmp ax,0 ; is it zero?
jnz p018 ; no - keep alarm on
mov ax,0ffffh ; turn off alarm
mov atime,ax
p018: pop ax
p020: mov dsecs,dx ; save remainder
mov bx,60 ; compute hours
xor dx,dx ; zero it
div bx ; hours in ax, minutes in dx
mov dmins,dx ; save minutes
cmp ax,0 ; midnight?
jnz p030 ; no
mov ax,12 ; yes
jmp p040a ; set am
p030: cmp ax,12 ; before noon?
jb p040a ; yes - set am
jz p040p ; noon - set pm
sub ax,12 ; convert the rest
p040p: mov bl,'p'
jmp p040x
p040a: mov bl,'a'
p040x: mov ampm,bl
aam ; fix up hour
cmp ax,hour ; top of the hour?
jz p060 ; no
mov hour,ax
call p120 ; beep the speaker once
p060: add ax,3030h ; convert hours to ascii
xchg ah,al
mov dhours,ax
mov ax,dmins ; get minutes
aam
add ax,3030h ; convert to ascii
xchg ah,al
mov dmins,ax
mov ax,dsecs ; get seconds (remainder)
xor dx,dx
mov bx,60
mul bx
mov bx,mfactor
div bx ; seconds in ax
aam
add ax,3030h
xchg ah,al
mov dsecs,ax
xor ax,ax ; check monitor type
mov es,ax
mov ax,es:[410h] ; get config byte
and al,30h ; isolate monitor type
cmp al,30h ; color?
mov ax,0b000h ; assume mono
jz p061 ; its mono
mov ax,0b800h ; color screen address
p061: mov dx,es:[463h] ; point to 6845 base port
add dx,6 ; point to status port
mov es,ax ; point to monitor
mov bh,color ; color in bh
mov si,offset dhours ; point to time
mov di,138 ; row 1, col 69
cld
mov cx,11 ; loop count
p062: mov bl,[si] ; get next character
p063: in al,dx ; get crt status
test al,1 ; is it low?
jnz p063 ; no - wait
cli ; no interrupts
p064: in al,dx ; get crt status
test al,1 ; is it high?
jz p064 ; no - wait
mov ax,bx ; move color & character
stosw ; move color & character again
sti ; interrupts back on
inc si ; point to next character
loop p062 ; done?
p070: pop bp ; restore registers
pop di
pop si
pop es
pop dx
pop cx
pop bx
cli ; no interrupts
mov ax,holdss
mov ss,ax
mov sp,holdsp
sti ; allow interrupts
p080: popf
pop ds
pop ax
jmp cs:[jumpval]
p100 proc near ; beep the speaker twice
call p120
push cx
mov cx,20000
p105: loop p105 ; wait around
pop cx
call p120
push cx
mov cx,20000
p106: loop p106 ; wait around
pop cx
call p120
ret
p100 endp
p120 proc near ; beep the speaker once
push ax
push cx
mov al,182
out 43h,al ; setup for sound
mov al,0
out 42h,al ; low part
mov al,atone ; get alarm tone
out 42h,al ; high part
in al,61h
push ax ; save port value
or al,3
out 61h,al ; turn speaker on
mov cx,aleng ; get loop count
p125: loop p125 ; wait around
pop ax ; restore original port value
out 61h,al ; turn speaker off
pop cx
pop ax
ret
p120 endp
p150: ; start of transient code
mov dx,offset copyr
call p220 ; print copyright
mov ax,0
mov es,ax ; segment 0
mov di,segaddr+2 ; this program's prior location
mov ax,es:[di] ; get prior code segment
mov es,ax ; point to prior program segment
mov di,offset signature
mov cx,es:[di] ; is it this program?
cmp cx,whozat
jnz p160 ; no - install it
call p200 ; set state & alarm
int 20h ; terminate
p160: mov di,segaddr+2 ; point to int 62h
mov ax,0
mov es,ax ; segment 0
mov ax,ds ; get current ds
mov es:[di],ax ; set int 62h
mov si,offset jumpval
mov di,intaddr ; point to timer interrupt
mov bx,es:[di] ; get timer ip
mov ax,es:[di+2] ; and cs
mov [si],bx ; save prior ip
mov [si+2],ax ; and cs
mov bx,offset p000
mov ax,ds
cli ; clear interrupts
mov es:[di],bx ; set new timer interrupt
mov es:[di+2],ax
sti ; set interrupts
push ds
pop es
call p200 ; set state & alarm
mov dx,offset p150 ; last byte of resident portion
inc dx
int 27h ; terminate
p200 proc near ; set state & alarm
mov si,80h ; point to command line
mov ax,0
mov di,0ffffh ; init hours
mov bh,0
mov ch,0
mov dh,0 ; : counter
mov es:[state],bh ; turn clock on
mov cl,[si] ; get length
jcxz p210 ; it's zero
p203: inc si ; point to next char
mov bl,[si] ; get it
cmp bl,'-' ; is it a minus?
jnz p204 ; no
mov es:[state],bl ; turn clock off
push dx
mov dx,offset msg3 ; print msg
call p220
pop dx
jmp p206
p204: cmp dh,2 ; seen 2nd colon?
jz p206 ; yes - ignore seconds
cmp bl,':' ; colon?
jnz p205 ; no
inc dh
cmp dh,2 ; second colon?
jz p206 ; yes - ignore seconds
push cx
push dx
mov cx,60
mul cx ; multiply current ax by 60
pop dx
pop cx
mov di,ax ; save hours
mov ax,0
jmp p206
p205: cmp bl,'0'
jb p206 ; too low
cmp bl,'9'
ja p206 ; too high - can be a problem
sub bl,'0' ; convert it to binary
push cx
push dx
mov cx,10
mul cx ; multiply current value by 10
add ax,bx ; and add latest digit
pop dx
pop cx
p206: loop p203 ; done yet?
cmp di,0ffffh ; any time to set?
jz p210 ; no
add ax,di ; add hours
cmp ax,24*60
jb p209 ; ok
mov dx,offset msg1 ; print error message
call p220
jmp p210
p209: mov es:[atime],ax ; save minutes past midnight
mov ax,5
mov es:[acount],ax ; set alarm count
mov dx,offset msg2 ; print set msg
call p220
p210: ret
p200 endp
p220 proc near ; print message
push ax
mov ah,9
int 21h
pop ax
ret
p220 endp
copyr db 'Alarm - Clock',10,13,'$'
msg1 db 'Invalid time - must be from 00:00 to 23:59',10,13,'$'
msg2 db 'Resetting alarm time',10,13,'$'
msg3 db 'Turning clock display off',10,13,'$'
alarm endp
cseg ends
end alarm

@ -0,0 +1,147 @@
; slip.asm
;
; This is an 8086+ implementation of SLIP (RFC 1055)
;
; It may be assembled using Microsoft's MASM using the command line:
; ml -Fl -c slip.asm
;
; or using Borland's TASM using the command line:
; tasm -la -m2 -jLOCALS slip.asm
;
.model small
.stack 100h
.data
SLIP_END equ 0C0h
SLIP_ESC equ 0DBh
SLIP_ESC_END equ 0DCh
SLIP_ESC_ESC equ 0DDh
; note that these are both sample macros and are very simple
; In both cases, DX is assumed to already be pointing to the
; appropriate I/O port and a character is always assumed to
; be ready.
SEND_CHAR macro char
IFDIFI <char>, <al>
mov al,char
ENDIF
out dx,al
endm
RECV_CHAR macro
in al,dx
endm
.code
;****************************************************************************
; send_packet
;
; sends the passed packet (which is in a memory buffer) to the output
; device by using the macro SEND_CHAR() which must be defined by the
; user. A sample SEND_CHAR() is defined above.
;
; Entry:
; DS:SI ==> raw packet to be sent
; CX = length of raw packet to be sent
; direction flag is assumed to be cleared (incrementing)
;
; Exit:
;
;
; Trashed:
; none
;
;****************************************************************************
send_packet proc
push cx
push si
SEND_CHAR SLIP_END ; send an end char to flush any garbage
jcxz @@bailout ; if zero length packet, bail out now
@@nextchar:
lodsb ; load next char
cmp al,SLIP_END ; Q: is it the special END char?
jne @@check_esc ; N: check for ESC
SEND_CHAR SLIP_ESC ; Y: send ESC + ESC_END instead
mov al,SLIP_ESC_END ;
jmp @@ordinary ;
@@check_esc:
cmp al,SLIP_ESC ; Q: is it the special ESC char?
jne @@ordinary ; N: send ordinary char
SEND_CHAR SLIP_ESC ; Y: send ESC + ESC_END instead
mov al,SLIP_ESC_ESC ;
; fall through to ordinary character
@@ordinary:
SEND_CHAR al ;
loop @@nextchar ; keep going until we've sent all chars
@@bailout:
SEND_CHAR SLIP_END ; send an end char to signal end of packet
pop si
pop cx
ret
send_packet endp
;****************************************************************************
; recv_packet
;
; receives a packet using the macro RECV_CHAR() which must be defined by
; the user and places the received packet into the memory buffer pointed
; to by ES:DI. The final length is returned in BX.
;
; Note that in the case of a buffer overrun, the portion of the packet
; that fit into the buffer is returned and BX and CX are equal. There
; is no way to tell the difference between a packet that just exactly
; fit and one which was truncated due to buffer overrun, so it is
; important to assure that the buffer is big enough to ALWAYS contain
; at least one spare byte.
;
; A sample RECV_CHAR() is defined above.
;
; Entry:
; ES:DI ==> packet buffer
; CX = length of buffer
; direction flag is assumed to be cleared (incrementing)
;
; Exit:
; BX = length of packet received
;
; Trashed:
; none
;
;****************************************************************************
recv_packet proc
push cx
push di
xor bx,bx ; zero received byte count
jcxz @@bailout ; if zero length packet, bail out now
@@nextchar:
RECV_CHAR ; fetch a character into al
cmp al,SLIP_END ; Q: is it the special END char?
jne @@check_esc ; N: check for ESC
or bx,bx ; YQ: is it the beginning of packet?
jz @@nextchar ; Y: keep looking
jmp @@bailout ; N: end of packet, so return it
@@check_esc:
cmp al,SLIP_ESC ; Q: is it the special ESC char?
jne @@ordinary ; N: it's an ordinary char
RECV_CHAR ; Y: get another character
cmp al,SLIP_ESC_END ; Q: is it ESC_END?
jne @@check_esc_esc ; N: check for ESC_ESC
mov al,SLIP_END ; Y: convert to ordinary END char
jmp @@ordinary ;
@@check_esc_esc:
cmp al,SLIP_ESC_ESC ; Q: is it ESC_ESC?
mov al,SLIP_ESC ; Y: convert to ordinary ESC char
; protocol violation! fall through to ordinary character
@@ordinary:
stosb ; store character in buffer
inc bx ; got another char
loop @@nextchar ; keep going until we've sent all chars
@@bailout:
pop di
pop cx
ret
recv_packet endp
END

@ -0,0 +1,325 @@
; showdate.asm
;
; prints the date and time to stdout
; equivalent to the following C++ program:
;
;#include <iostream.h>
;#include <time.h>
;
;int main()
;{
; time_t t;
; time(&t); // get the current time
; cout << ctime(&t); // convert to string and print
; return 0;
;}
;
; This code may be assembled and linked using Borland's TASM:
; tasm /la /m2 showdate
; tlink /Tdc showdate
;
STDOUT equ 01h ; handle of standard output device
DOS_GET_DATE equ 02ah ; get system date
DOS_GET_TIME equ 02ch ; get system time
DOS_WRITE_HANDLE equ 040h ; write to handle
DOS_TERMINATE equ 04ch ; terminate with error code
DOSINT macro function, subfunction
IFB <subfunction>
mov ah,(function AND 0ffh)
ELSE
mov ax,(function SHL 8) OR (subfunction AND 0ffh)
ENDIF
int 21h ; invoke DOS function
endm
MODEL tiny
;.STACK 100h
.CODE
;****************************************************************************
; main
;
; calls showdate routne and exists with 00 error code
;
; Entry:
;
; Exit:
;
; Trashed:
; none
;
;****************************************************************************
main proc far
.STARTUP ; sets up DS and stack
call showdate ;
.EXIT 0 ; return with errcode=0
main endp
;****************************************************************************
; showdate
;
; fetches the DOS system date, prints it to stdout and exits
; the format of the output is identical to that of the Posix ctime()
; function:
;
; Thu May 11 16:11:30 2000
;
; The day of week and month are always 3 characters long. The time of
; day is in 24hour form (e.g. 16:11:30 is a few minutes after four in
; the afternoon) and the year is always four digits. The whole thing is
; followed by a newline character (line feed = 0ah), making 25
; characters total.
;
; Note that ctime() returns 26 characters which is all of the above,
; followed by a terminating NUL char but this program does not emit a
; NUL.)
;
; Entry:
; DS points to segment for our data tables
;
; Exit:
; carry may be set if last write failed
;
; Trashed:
; none
;
;****************************************************************************
showdate proc
push ax bx cx dx ;
DOSINT DOS_GET_DATE ;
; returns the following
; cx = year (1980-2099)
; dh = month (1-12) == (Jan..Dec)
; dl = day (1-31)
; al = day of week (0-6) == (Sun..Sat)
push cx ;
push dx ; save the return values
; write the day of week
mov dx, offset dayname ;
mov cx,3 ; number of bytes to write
call WriteSubstring ;
; write the month
pop ax ; recall month/day
push ax ; and save it again
mov al,ah ; isolate just month
mov dx, offset monthname - 3 ; monthname array is 1-based
mov cx,3 ; number of bytes to write
call WriteSubstring ;
; write the day of the month
pop ax ;
call WriteNumber ;
call WriteSpace ;
; write the hour
DOSINT DOS_GET_TIME ; ch = hour, cl = min,
; dh = sec, dl = hundredths
push dx ; save seconds
push cx ; save minutes
mov al,ch ;
call WriteNumber ;
call WriteColon ;
; write the minutes
pop ax ;
call WriteNumber ;
call WriteColon ;
; write the seconds
pop ax ;
mov al,ah ;
call WriteNumber ;
call WriteSpace ;
; write the year (century first)
pop ax ;
xor dx,dx ; clear other reg before divide
mov cx,100 ; ax = ax/100, dx = remainder
div cx ;
push dx ; save remainder
call WriteNumber ;
; write the year (year within century)
pop ax ;
call WriteNumber ;
mov dx,offset newlinechar
call PrintOne ;
pop dx cx bx ax ; restore stack
ret ;
showdate endp
;****************************************************************************
; WriteSubstring
;
; writes a short substring to stdout
; specifically, prints CL characters, starting at DS:(DX+CL*AL)
;
; Entry:
; DS:DX ==> pointer to base of string array
; CL = size of each string
; AL = string selector (i.e. which string)
;
; Exit:
; CY set if there was an error writing last byte
; if CY clear,
; AX = 1 (number of bytes written)
; else
; AX = error code
;
; Trashed:
; BX CX DX
;
;****************************************************************************
WriteSubstring proc
mul cl ; ax = cl * al
add dx,ax ; offset now points to appropriate day string
call PrintIt ;
WriteSubstring endp
; deliberately fall through
;****************************************************************************
; WriteSpace
;
; writes a single space character (20h) to stdout
;
; Entry:
; DS points to data table segment
;
; Exit:
; CY set if there was an error writing last byte
; if CY clear,
; AX = 1 (number of bytes written)
; else
; AX = error code
;
; Trashed:
; BX CX DX
;
;****************************************************************************
WriteSpace proc
mov dx,offset spacechar;
WriteSpace endp
; deliberately fall through
;****************************************************************************
; PrintOne
;
; prints a single character pointed to by DS:DX
;
; Entry:
; DS:DX ==> points to the character to be printed
;
; Exit:
; CY set if there was an error writing last byte
; if CY clear,
; AX = 1 (number of bytes written)
; else
; AX = error code
;
; Trashed:
; BX CX DX
;
;****************************************************************************
PrintOne proc
mov cx,1 ;
PrintOne endp
; deliberately fall through
;****************************************************************************
; PrintIt
;
; prints the passed string to stdout
;
; Entry:
; DS:DX ==> points to string to be printed
; CX = number of bytes to be printed
;
; Exit:
; CY set if there was an error writing to stdout
; if CY clear,
; AX = number of bytes written
; else
; AX = error code
;
; Trashed:
; none
;
;****************************************************************************
PrintIt proc
mov bx,STDOUT ;
DOSINT DOS_WRITE_HANDLE ; write to the file
ret ;
PrintIt endp
;****************************************************************************
; WriteColon
;
; writes a colon character to stdout
;
; Entry:
; DS points to data segment
;
; Exit:
; CY set if there was an error writing to stdout
; if CY clear,
; AX = 1 (number of bytes written)
; else
; AX = error code
;
; Trashed:
; none
;
;****************************************************************************
WriteColon proc
mov dx,offset colonchar;
jmp PrintOne ;
WriteColon endp
;****************************************************************************
; WriteNumber
;
; prints the number in AL to stdout as two decimal digits
;
; Entry:
; AL = number to be printed. It must be in the range 00-99
;
; Exit:
; CY set if there was an error writing to stdout
; if CY clear,
; AX = 2 (number of bytes written)
; else
; AX = error code
;
; Trashed:
; BX CX DX
;
;****************************************************************************
WriteNumber proc
xor ah,ah ; clear out high half
mov cl,10 ; prepare to convert to decimal (base 10)
div cl ; divide it out
or ax,3030h ; convert to ASCII digits
push ds ; remember DS for later
push ax ; push converted chars on stack
mov dx,ss ;
mov ds,dx ; ds = ss
mov dx,sp ; print data from stack
mov cx,2 ; two characters only
call PrintIt ;
pop bx ; fix stack
pop ds ; restore ds pointer
ret ;
WriteNumber endp
;.DATA
dayname db "SunMonTueWedThuFriSat"
monthname db "JanFebMarAprMayJunJulAugSepOctNovDec"
spacechar db " "
colonchar db ":"
newlinechar db 0ah ; in C this is \n
end

@ -0,0 +1,350 @@
; rawread.asm
;
; this program reads a DOS cluster using only BIOS disk calls. All
; of the tasks usually done by DOS, e.g. FAT lookup, cluster to
; logical sector translation, logical to physical translation, are
; all done by this program instead. The idea is to be able to create
; a program that can access DOS disks from a bootable floppy without
; having to have DOS.
;
; well, that's what it used to do. Now it's supposed to do something
; completely different. Its job is to scan the entire surface of the
; hard drive, looking for the specified string. If that string is
; found, it is to print the full path and directory entry, including
; the file date and time.
;
; but wait! There's more. Now what we have is a number of raw
; routines which could prove useful for manipulating a DOS file
; structure outside of the DOS environment. The main routine still
; should be kept (if renamed), since the order in which these things
; are done is important (e.g. later calls depend on data set up by
; earlier calls).
;
; get filename
; parse filename into subdirs
; locate root dir and cluster size
; follow subdir routing to filename
; report file size, date & time
;
.MODEL small
.STACK 0200h
.586P
.DATA
PartEntry STRUC
Bootable db ? ;80h = bootable, 00h = nonbootable
BeginHead db ? ;beginning head
BeginSector db ? ;beginning sector
BeginCylinder db ? ;beginning cylinder
FileSystem db ? ;name of file system
EndHead db ? ;ending head
EndSector db ? ;ending sector
EndCylinder db ? ;ending cylinder
StartSector dd ? ;starting sector (relative to beg. of disk)
PartSectors dd ? ;number of sectors in partition
PartEntry ENDS
BootSector STRUC
Jump db ? ;E9 xx xx or EB xx 90
JumpTarget dw ? ;E9 xx xx or EB xx 90
OemName db '????????' ;OEM name & version
;Start of BIOS parameter block
BytesPerSec dw ? ;bytes per sector
SecPerClust db ? ;sectors per cluster
ResSectors dw ? ;number of reserved sectors
FATs db ? ;number of file allocation tables
RootDirEnts dw ? ;number of root-dir entries
Sectors dw ? ;total number of sectors
Media db ? ;media descriptor byte
FATsecs dw ? ;number of sectors per FAT
SecPerTrack dw ? ;sectors per track
Heads dw ? ;number of heads
HiddenSecs dd ? ;number of hidden sectors
HugeSectors dd ? ;num sectors if Sectors==0
;End of BIOS parameter block
BootSector ENDS
DirEntry STRUC
FileName db '????????' ;name
Extension db '???' ;extension
Attributes db ? ;attributes
Reserved db 10 dup (?) ;reserved
Time dw ? ;time stamp
Date dw ? ;date stamp
StartCluster dw ? ;starting cluster
FileSize dd ? ;file size
DirEntry ENDS
BootFileName db "CONFIG SYS" ;the boot loader for this OS
MBR DB 0200h DUP (?)
buff DB 0200h * 40h DUP (?)
ClustOffs dd ?
CR EQU 0DH
LF EQU 0AH
.CODE
main PROC
STARTUPCODE ;initialize stuff
call FetchMBR C ;fetch the master boot record
jc @@exit
mov cx,4 ;search up to four partitions
add bx,01aeh ;point to partition table (-10h)
@@FindBootable:
add bx,10h ;point to next entry
cmp BYTE ptr [bx],80h ;is it a bootable partition?
loopnz @@FindBootable
call FetchSector C, \
WORD ptr [(PartEntry PTR bx).BeginHead], \
WORD ptr [(PartEntry PTR bx).BeginSector], \
WORD ptr [(PartEntry PTR bx).BeginCylinder], \
OFFSET MBR, ds ;SEG MBR
;
; here's the point at which our OS loader would begin, with the
; BootSector structure in memory.
;
mov bx, OFFSET MBR
call CalcClustOff C, \
WORD ptr [(BootSector PTR bx).ResSectors], \
WORD ptr [(BootSector PTR bx).FATsecs], \
WORD ptr [(BootSector PTR bx).FATs], \
WORD ptr [(BootSector PTR bx).RootDirEnts], \
WORD ptr [(BootSector PTR bx).BytesPerSec], \
WORD ptr [(BootSector PTR bx).SecPerClust]
mov WORD ptr [ClustOffs],ax
mov WORD ptr [ClustOffs+2],dx
call CalcClust2 C, \
WORD ptr [(BootSector PTR bx).ResSectors], \
WORD ptr [(BootSector PTR bx).FATsecs], \
WORD ptr [(BootSector PTR bx).FATs]
; now dx:ax contains the logical sector for cluster 2
call LsectToGeom C, \
ax, dx, \
WORD ptr [(BootSector PTR bx).HiddenSecs] , \
WORD ptr [((BootSector PTR bx).HiddenSecs)+2],\
[(BootSector PTR bx).Heads], \
[(BootSector PTR bx).SecPerTrack]
mov dl,80h
mov bx,offset buff
mov al,[(BootSector PTR MBR).SecPerClust]
mov ah,2h ; get ready to read
int 13h
; now find our desired filename within buffer (which has the root dir)
call FindFile C, \
bx, 200h * 40h, offset BootFileName
xor dh,dh
mov dl,[(BootSector PTR MBR).SecPerClust]
mov si,ax
mov ax,[(DirEntry PTR si).StartCluster]
mul dx
add ax,WORD ptr [ClustOffs]
adc dx,WORD ptr [ClustOffs+2]
; now dx:ax contains logical sector number for start of file
call LsectToGeom C, \
ax, dx, \
WORD ptr [(BootSector PTR MBR).HiddenSecs] , \
WORD ptr [((BootSector PTR MBR).HiddenSecs)+2],\
[(BootSector PTR MBR).Heads], \
[(BootSector PTR MBR).SecPerTrack]
mov dl,80h
mov ax,204h ; read in 2k worth of data
int 13h
@@exit:
EXITCODE ;exit to DOS
ENDP main
;
; FetchMBR - fetches the Master Boot Record from the first physical
; hard disk and stores it in the location MBR.
;
; INPUT: none
; OUTPUT: AX is error code if CY set, ES:BX ==> MBR
; DESTROYED: none
;
FetchMBR PROC C
USES cx, dx ;save registers we'll use
mov dx,80h ;first physical disk
mov cx,1 ;head 1, sector 0
mov bx,ds ;
mov es,bx ;point to boot record buffer
mov bx,OFFSET MBR ;read into boot record
mov ax,0201h ;read one sector
int 13h ;BIOS read
ret ;return to main
FetchMBR ENDP
;
; FetchSector - fetches the physical sector described by the passed
; parameters and stores it in the named buffer
;
; INPUT: head, sector, cylinder, buffer
; OUTPUT: AX is error code if CY set, ES:BX ==> Boot
; DESTROYED: none
;
FetchSector PROC C head:BYTE, sector:BYTE, cylinder:BYTE, buffer:DWORD
USES cx, dx ;save registers we'll use
mov ch, [cylinder] ;
mov cl, [sector] ;
mov dh, [head] ;
mov dl, 80h ;first physical hard drive
les bx, [buffer] ;
mov ax,0201h ;read one sector
int 13h ;BIOS read
ret ;return to main
FetchSector ENDP
;
; GeomToLsect - converts to logical sector number from the physical
; geometry (head, cylinder, track). See LsectToGeom.
;
; INPUT: cx, dx are set with cylinder/track, and head respectively
; HiddenSecs, Heads, SecPerTrack
; OUTPUT: lsect
; DESTROYED: none
;
GeomToLsect PROC C lsect:DWORD, dHiddenSecs:DWORD, \
dHeads:WORD, dSecPerTrack:WORD, buffer:DWORD
USES ax ;save registers we'll use
mov ax, WORD ptr [lsect] ;load lsect into DX:AX
mov dx, WORD ptr [lsect+2] ;
stc ;add one additional
adc ax, WORD ptr [dHiddenSecs] ;add starting sector
adc dx, WORD ptr [dHiddenSecs+2] ;
div [dSecPerTrack] ;
mov cl,dl ;store sector in cl
xor dx,dx ;
div [dHeads] ;
mov dh,dl ;store head in dh
mov ch,al ;store low 8 bits of cylinder in ch
shr ax,1 ;
shr ax,1 ;
and al,0c0h ;pass through two hi bits only
or cl,ah ;mov bits into location
ret ;
GeomToLsect ENDP
;
; LsectToGeom - converts from logical sector number to the physical
; geometry (head, cylinder, track) in the form required
; by the BIOS (Int 13h) disk read and write calls.
;
; INPUT: lsect, HiddenSecs, Heads, SecPerTrack
; OUTPUT: cx, dx are set with cylinder/track, and head respectively
; DESTROYED: none
;
LsectToGeom PROC C lsect:DWORD, lHiddenSecs:DWORD, \
lHeads:WORD, lSecPerTrack:WORD, buffer:DWORD
USES ax ;save registers we'll use
mov ax, WORD ptr [lsect] ;load lsect into DX:AX
mov dx, WORD ptr [lsect+2] ;
stc ;add one additional
adc ax, WORD ptr [lHiddenSecs] ;add starting sector
adc dx, WORD ptr [lHiddenSecs+2] ;
div [lSecPerTrack] ;
mov cl,dl ;store sector in cl
xor dx,dx ;
div [lHeads] ;
mov dh,dl ;store head in dh
mov ch,al ;store low 8 bits of cylinder in ch
shr ax,1 ;
shr ax,1 ;
and al,0c0h ;pass through two hi bits only
or cl,ah ;mov bits into location
ret ;
LsectToGeom ENDP
;
; CalcClust2 - calculates the starting logical sector number of
; cluster 2, (the beginning of data space for
; partitions).
;
; INPUT: ResSectors, FATsecs, FATs
; OUTPUT: dx:ax contains the starting logical sector number
; DESTROYED: none
;
CalcClust2 PROC C cResSectors:WORD, cFATsecs:WORD, cFATs:BYTE
xor dx,dx ;
mov ax,[cFATsecs] ;
mul [cFATs] ;
add ax,[cResSectors] ;
adc dx,0 ;
ret
CalcClust2 ENDP
;
; CalcClustOff - calculates the starting logical sector number of
; cluster 0, which isn't really a cluster, but the
; number returned is useful for calculations converting
; cluster number to logical sector
;
; INPUT: ResSectors, FATsecs, FATs
; OUTPUT: dx:ax contains the starting logical sector number
; DESTROYED: none
;
CalcClustOff PROC C dResSectors:WORD, dFATsecs:WORD, dFATs:BYTE, \
dRootDirEnts:WORD, dBytesPerSec:WORD, dSecPerClust:BYTE
LOCAL clustLo:WORD, clustHi:WORD
xor dh,dh
mov ax,[dFatSecs]
mov dl,[dFATs]
mul dx
add ax,[dResSectors]
adc dx,0
; call CalcClust2 C, [dResSectors], [dFATsecs], [dFATs]
; now dx:ax = FATs * FATsecs + ResSectors
mov [clustLo],ax
mov [clustHi],dx
mov dx,20h ; bytes per dir entry
mov ax,[dRootDirEnts] ;
mul dx ; multiply 'em out
div [dBytesPerSec] ; and divide by bytes/sec
add [clustLo],ax ;
adc [clustHi],dx ; create the aggregate
mov al,[dSecPerClust] ;
xor ah,ah ;
shl ax,1 ; AX = SecPerClust * 2
sub [clustLo],ax ;
sbb [clustHi],0 ; propagate carry flag
mov ax,[clustLo] ;
mov dx,[clustHi] ;
ret
CalcClustOff ENDP
;
; FindFile - given a memory buffer containing the directory data
; and a static file name for which to search, this routine
; finds the file and returns a pointer to its directory
; entry in ds:si
;
; INPUT: dirbuffer, filespec
; OUTPUT: ax contains pointer to directory entry (or NULL)
; DESTROYED: none
;
FindFile PROC C dirbuffer:WORD, limit:WORD, filespec:WORD
USES cx, dx, di, si, es
mov cx,ds ;
mov es,cx ; es and ds point to same segment
cld ; always count forward
mov ax,[dirbuffer] ; load 'em up
add [limit],ax
mov dx,[filespec] ;
keepsearching:
mov cx,11 ; size of dos filename (8.3)
mov si,dx ;
mov di,ax ;
repe cmpsb ; compare 'em
jz foundit ;
add ax,20h ; size of directory entry
cmp ax,[limit]
jb keepsearching
xor ax,ax
foundit:
ret
FindFile ENDP
END

@ -0,0 +1,267 @@
; loader.asm
PartEntry STRUC
Bootable db ? ;80h = bootable, 00h = nonbootable
BeginHead db ? ;beginning head
BeginSector db ? ;beginning sector
BeginCylinder db ? ;beginning cylinder
FileSystem db ? ;name of file system
EndHead db ? ;ending head
EndSector db ? ;ending sector
EndCylinder db ? ;ending cylinder
StartSector dd ? ;starting sector (relative to beg. of disk)
PartSectors dd ? ;number of sectors in partition
PartEntry ENDS
BootSector STRUC
bsJump db 0EBh, (extra - bsJump), 090h
; E9 XX XX or EB xx 90
OemName db 8 dup (?) ; OEM name and version
; start of BIOS parameter block
BytesPerSec dw ? ; bytes per sector
SecPerClust db ? ; sectors per cluster
ResSectors dw ? ; number of reserved sectors
FATs db ? ; number of FATs
RootDirEnts dw ? ; number of root directory entries
Sectors dw ? ; total number of sectors (see HugeSectors)
Media db ? ; media descriptor byte (0f0h for floppies)
FATsecs dw ? ; number of sectors per FAT
SecPerTrack dw ? ; sectors per track
Heads dw ? ; number of heads
HiddenSecs dd ? ; number of hidden sectors
HugeSectors dd ? ; number of sectors if Sectors equals 0
; end of BIOS parameter block
DriveNumber db ? ;
Reserved1 db ? ;
BootSignature db ? ;
VolumeID dd ? ;
VolumeLabel db 11 dup (?)
FileSysType db 8 dup (?)
extra dw ?
BootSector ENDS
DirEntry STRUC
FileName db '????????' ;name
Extension db '???' ;extension
Attributes db ? ;attributes
Reserved db 10 dup (?) ;reserved
Time dw ? ;time stamp
Date dw ? ;date stamp
StartCluster dw ? ;starting cluster
FileSize dd ? ;file size
DirEntry ENDS
CR EQU 0DH
LF EQU 0AH
yonder segment para public use16 at 2000h
org 0h
destination proc far
destination endp
yonder ends
code segment para public use16 '_CODE'
.386
assume cs:code, ds:code, es:code, ss:code
org 7c00h
main PROC
MBR:
Boot bootsector < ,'BEROSET ',512,1,1,2,224,2880,0f0h,9,18,2,\
0,0,0,0,29h,02a04063ch,'BEROSET 001',\
'FAT12 ',07df1h>
over:
mov ax,cs ;
cli
mov ss,ax ; point ss:sp to CS:7c00h
mov sp,7c00h ; which sets up a stack in first 64K
sti
mov ds,ax
mov es,ax
;****************************************************************************
;
; CalcClustOff - calculates the starting logical sector number of
; cluster 0, which isn't really a cluster, but the
; number returned is useful for calculations converting
; cluster number to logical sector
;
; INPUT: ResSectors, FATsecs, FATs
; OUTPUT: dx:ax contains the starting logical sector number
; DESTROYED: none
;
;****************************************************************************
CalcClustOff PROC
xor dh,dh
mov ax,[Boot.FatSecs]
mov dl,[Boot.FATs]
mul dx
add ax,[Boot.ResSectors]
adc dx,0
; now dx:ax = FATs * FATsecs + ResSectors
mov word ptr [ClustOffs],ax
mov word ptr [ClustOffs+2],dx
mov dx,20h ; bytes per dir entry
mov ax,[Boot.RootDirEnts]
mul dx ; multiply 'em out
div word ptr [Boot.BytesPerSec] ; and divide by bytes/sec
add word ptr [ClustOffs],ax
adc word ptr [ClustOffs+2],dx ; create the aggregate
mov al,[Boot.SecPerClust] ;
xor ah,ah ;
shl ax,1 ; AX = SecPerClust * 2
sub word ptr [ClustOffs],ax ;
sbb word ptr [ClustOffs+2],0 ; propagate carry flag
; mov ax,word ptr [ClustOffs] ;
; mov dx,word ptr [ClustOffs+2] ;
; ret
CalcClustOff ENDP
; mov WORD ptr [ClustOffs],ax
; mov WORD ptr [ClustOffs+2],dx
mov bx,offset Boot
call CalcClust2 C, \
WORD ptr [(BootSector PTR bx).ResSectors], \
WORD ptr [(BootSector PTR bx).FATsecs], \
WORD ptr [(BootSector PTR bx).FATs]
; now dx:ax contains the logical sector for cluster 2
call LsectToGeom C, \
WORD ptr [(BootSector PTR bx).HiddenSecs] , \
WORD ptr [((BootSector PTR bx).HiddenSecs)+2],\
[(BootSector PTR bx).Heads], \
[(BootSector PTR bx).SecPerTrack]
mov dl,[(BootSector PTR bx).DriveNumber]
mov bx,offset buff
retry1:
mov al,[(BootSector PTR MBR).SecPerClust]
mov ah,2h ; get ready to read
int 13h
jc retry1
; now find our desired filename within buffer (which has the root dir)
call FindFile C, \
bx, 200h * 40h, offset BootFileName
xor dh,dh
mov dl,[(BootSector PTR MBR).SecPerClust]
mov si,ax
mov ax,[(DirEntry PTR si).StartCluster]
mul dx
add ax,WORD ptr [ClustOffs]
adc dx,WORD ptr [ClustOffs+2]
; now dx:ax contains logical sector number for start of file
call LsectToGeom C, \
WORD ptr [(BootSector PTR MBR).HiddenSecs] , \
WORD ptr [((BootSector PTR MBR).HiddenSecs)+2],\
[(BootSector PTR MBR).Heads], \
[(BootSector PTR MBR).SecPerTrack]
retry2:
mov si,offset Boot
mov dl,[(BootSector PTR si).DriveNumber]
mov ah,2h
; read in a cluster's worth of data
mov al,[(BootSector PTR si).SecPerClust]
; point to our magic location
mov bx,seg destination
mov es,bx
mov bx,offset destination
int 13h
jc retry2
@@exit:
jmp destination
ENDP main
;****************************************************************************
;
; LsectToGeom - converts from logical sector number to the physical
; geometry (head, cylinder, track) in the form required
; by the BIOS (Int 13h) disk read and write calls.
;
; INPUT: dx:ax=lsect, HiddenSecs, Heads, SecPerTrack
; OUTPUT: cx, dx are set with cylinder/track, and head respectively
; DESTROYED: none
;****************************************************************************
LsectToGeom PROC C lHiddenSecs:DWORD, \
lHeads:WORD, lSecPerTrack:WORD, buffer:DWORD
USES ax ;save registers we'll use
stc ;add one additional
adc ax, WORD ptr [lHiddenSecs] ;add starting sector
adc dx, WORD ptr [lHiddenSecs+2] ;
div [lSecPerTrack] ;
mov cl,dl ;store sector in cl
xor dx,dx ;
div [lHeads] ;
mov dh,dl ;store head in dh
mov ch,al ;store low 8 bits of cylinder in ch
shr ax,1 ;
shr ax,1 ;
and al,0c0h ;pass through two hi bits only
or cl,ah ;mov bits into location
ret ;
LsectToGeom ENDP
;****************************************************************************
;
; CalcClust2 - calculates the starting logical sector number of
; cluster 2, (the beginning of data space for
; partitions).
;
; INPUT: ResSectors, FATsecs, FATs
; OUTPUT: dx:ax contains the starting logical sector number
; DESTROYED: none
;
;****************************************************************************
CalcClust2 PROC C cResSectors:WORD, cFATsecs:WORD, cFATs:BYTE
xor dx,dx ;
mov ax,[cFATsecs] ;
mul [cFATs] ;
add ax,[cResSectors] ;
adc dx,0 ;
ret
CalcClust2 ENDP
;****************************************************************************
;
; FindFile - given a memory buffer containing the directory data
; and a static file name for which to search, this routine
; finds the file and returns a pointer to its directory
; entry in ds:si
;
; INPUT: dirbuffer, filespec
; OUTPUT: ax contains pointer to directory entry (or NULL)
; DESTROYED: none
;****************************************************************************
FindFile PROC C dirbuffer:WORD, limit:WORD, filespec:WORD
USES cx, dx, di, si, es
mov cx,ds ;
mov es,cx ; es and ds point to same segment
cld ; always count forward
mov ax,[dirbuffer] ; load 'em up
add [limit],ax
mov dx,[filespec] ;
keepsearching:
mov cx,11 ; size of dos filename (8.3)
mov si,dx ;
mov di,ax ;
repe cmpsb ; compare 'em
jz foundit ;
add ax,20h ; size of directory entry
cmp ax,[limit]
jb keepsearching
xor ax,ax
foundit:
ret
FindFile ENDP
BootFileName db "BEROSET SYS" ;the boot loader for this OS
; MBR db 0200h DUP (?)
buff db 0200h * 40h DUP (?)
ClustOffs dd ?
org 7dfeh
dw 0AA55h ; signature byte
code ends
END

@ -0,0 +1,70 @@
TITLE BRK2 -- Break Handling Utilities Module
TRUE EQU 01H ;boolean true
FALSE EQU 00H ;boolean false
BREAKINT EQU 23H ;dos control-break intrpt
GETVECTOR EQU 35H ;dos get vector function
SETVECTOR EQU 25H ;dos set vector function
DOS_FUNCTION EQU 21H ;dos function call
BREAK SEGMENT PUBLIC 'CODE'
BREAKFLAG DB 0H ;break key hit flag
SAVEBRK DD 0H ;saved break vec. contents
ASSUME CS:BREAK
ASSUME DS:NOTHING
;CHECK_BREAK checks if ctrl-break has been pressed. It returns
;true if ctrl-break has been pressed and false if it hasn't.
PUBLIC CHECK_BREAK
CHECK_BREAK PROC FAR
XOR AX, AX ;clear ax
MOV AL, BREAKFLAG ;return value = breakflag
MOV BREAKFLAG, FALSE ;reset breakflag
RET
CHECK_BREAK ENDP
;INSTALL_BREAK_HANDLER sets up a ctrl-break interrupt handler. It
;also saves the address of the former break handler so that it can
;be restored later.
PUBLIC INST_BRK_HANDLR
INST_BRK_HANDLR PROC FAR
PUSH DS
MOV AL, BREAKINT ;AL = break interrupt
MOV AH, GETVECTOR ;AH = dos function code
INT DOS_FUNCTION ;call dos
MOV WORD PTR SAVEBRK, BX ;save offset in int vector
MOV WORD PTR SAVEBRK+2, ES ;save base in int vector
MOV AL, BREAKINT ;AL = break interrupt
MOV AH, SETVECTOR ;AH = dos function code
MOV DX, OFFSET BRK_HANDLER ;DX = offset of brk handler
MOV BX, CS ;BX = this segment
MOV DS, BX ;DS = this segment
INT DOS_FUNCTION ;call dos
POP DS
RET
INST_BRK_HANDLR ENDP
;BRK_HANDLER is invoked by the bios when ctrl_break is pressed
BRK_HANDLER PROC FAR
MOV BREAKFLAG, TRUE ;breakflag = yes, break hit
IRET
BRK_HANDLER ENDP
;REMOVE_BREAK_HANDLER restores the previous ctrl-break handler
REM_BRK_HANDLR PROC FAR
PUSH DS
MOV AL, BREAKINT ;AL = break interrupt
MOV AH, SETVECTOR ;AH = dos function code
MOV DX, WORD PTR SAVEBRK ;DX = saved 1st word
MOV BX, WORD PTR SAVEBRK+2 ;BX = saved 2nd word
MOV DS, BX ;DS = saved 2nd word
INT DOS_FUNCTION ;call dos
POP DS
RET
REM_BRK_HANDLR ENDP
BREAK ENDS
END

@ -0,0 +1,47 @@
PGROUP Group PROG
DGROUP Group DATA
DATA Segment Public 'DATA'
public brkflag
brkflag DW 0
DATA ends
PROG Segment Para Public 'PROG'
public TrapBrea
assume cs:PGROUP,DS:DGROUP
TrapBrea proc near
push ds
push cs
pop ds
mov dx,offset PGROUP:Bret
mov ah,25h
mov al,23h
int 21h
pop ds
ret
TrapBrea endp
Bret proc far
push ds
push ax
mov ax,DGROUP
mov ds,ax
mov brkflag,1
pop ax
pop ds
iret
Bret endp
PROG ends
end

@ -0,0 +1,127 @@
COMMENT *
Demo (and semi-useful) program to read/set burnout device parameters.
Usage: burnout [ticks] [C+-] [V+-] [H+-]
Parameters can be separated by almost anything.
With no parameters, program simply returns current status.
Examples:
burnout 5000 (sets time to 5000 ticks)
burnout 5000H+ (time=5000, use hardware blanking)
burnout 5000,h+ (ditto, separators don't matter)
burnout c+h-v+ (continuous clear, software, monitor video)
burnout /C+ /H- /V+ (ditto)
burnout (return status only)
Assembly/link:
masm burnout;
link burnout; (ignore NO STACK warning message)
exe2bin burnout burnout.com
stdout equ 1 ; DOS output files
stderr equ 2
; ----- General equates
DOS equ 21H ; DOS interrupt
TERMINATE equ 20H ; Exit to DOS
PRINT equ 09H ; DOS "print" string to stdout
FOPEN equ 3D02H ; DOS file open, read/write
FREAD equ 3FH ; DOS file read
FWRITE equ 40H ; DOS file write
CR equ 13 ; ASCII carriage return
LF equ 10 ; ASCII line fine
code segment
assume cs:code,ds:code
org 80H ; Parm storage area in PSP
ParmLength label byte ; Length of parms
org 81H
Parameters label byte ; Start of parms
org 100H ; Org for .COM
main proc far
jmp start ; Hate to execute data
DevName db 'BRNDEV',0 ; Burnout device name
handle dw ? ; Storage for handle
Flush db '@' ; Char to flush device I/O
Execute db '#' ; Char to execute device commands
NotInstalled db 'Burnout device is not installed',13,10
NotInstalledL equ $ - NotInstalled
Status db 'Current status: ' ; Status message
StatInsert db 40 dup (?) ; brndev will store status here
; ----- Open the device
start:
mov dx,offset DevName ; DS:DX => device name
mov ax,FOPEN
int DOS
jnc A1 ; Continue if no error
mov bx,stderr ; Message to stderr
mov cx,NotInstalledL
mov dx,offset NotInstalled
mov ah,FWRITE
int DOS
jmp exit
; ----- Flush any pending I/O to/from the device
A1:
mov handle,ax ; Save device handle
mov dx,offset Flush ; Point to the "@"
mov cx,1 ; Writing one byte
mov bx,handle ; Device handle
mov ah,FWRITE ; Write "@" to device
int DOS
; ----- Send and execute parameters if present
mov cl,ParmLength ; Parm length to CL
or cl,cl ; Any parms present?
jz A2 ; Skip if not
xor ch,ch ; CX = parm length
mov dx,offset Parameters ; DS:DX => parms
mov bx,handle ; BX = device handle
mov ah,FWRITE ; Write parms to device
int DOS
mov dx,offset Execute ; Execute the parms
mov cx,1 ; Writing one byte
mov bx,handle ; Device handle
mov ah,FWRITE ; Write "#" to device
int DOS
; ----- Get and display device status
A2:
mov dx,offset StatInsert ; DS:DX => where to put status
mov cx,0FFH ; Ask for lots of data; DOS will ...
; ... fetch only until CR found.
mov bx,handle ; Device handle
mov ah,FREAD ; Read device info
int DOS
mov cx,ax ; CX = actual # bytes read
mov di,offset StatInsert ; Where the stat data is stored
add di,cx ; Add length of input read
mov al,CR ; Store a CR/LF/'$' at end
cld
stosb
mov al,LF
stosb
mov al,'$'
stosb
mov dx,offset Status ; Write status to stdout
mov ah,PRINT
int DOS
exit:
int TERMINATE ; Exit to DOS
main endp
code ends
end main

@ -0,0 +1,103 @@
;
input equ 080h ;command line tail buffer
cr equ 0dh ;ASCII carriage return
;
cseg segment byte
assume cs:cseg,ds:cseg
;
org 0100h ;since this will be
; a COM file
;
clear: ;initialize display...
;call BIOS video driver to
mov ah,15 ;get current display mode:
int 10h ;returns AL = mode, and
;AH = no. of columns.
cmp al,7 ;if we are in graphics modes
je clear0 ;(modes 4,5,6) then exit
cmp al,3 ;but if we are in mode 0-3
ja clear9 ;or 7 then continue.
clear0: ;set up size of window to
;be initialized...
xor cx,cx ;set upper left corner of
;window to (X,Y)=(0,0)
mov dh,24 ;set Y to 24 for lower right
mov dl,ah ;corner, and X to the number
dec dl ;of columns returned by BIOS
;minus 1
mov bh,7 ;initialize attribute byte
;to "normal" video display,
;i.e. white on black.
;set SI=address of command
;tail's length byte
mov si,offset input
cld ;clear the Direction Flag
;for "LODS" string instruction.
lodsb ;check length byte to see if
or al,al ;there's any command tail.
jz clear8 ;no,go clear the screen
;with normal video attribute
;
clear1: lodsb ;check the next byte of
;the command tail,
cmp al,cr ;if carriage return
je clear8 ;we are done.
or al,20h ;fold the character to
;lower case.
cmp al,'a' ;make sure it's in range a-z
jb clear1 ;no, skip it
cmp al,'z'
ja clear1 ;no, skip it
cmp al,'i' ;I=Set intensity
jne clear2 ;jump if not I
or bh,08 ;set intensity bit
jmp short clear1
clear2: cmp al,'r' ;R=Reverse
jne clear3 ;jump if not R
and bh,088h ;mask off old foreground/
;background bits and
or bh,070h ;change to reverse video
jmp short clear1
clear3: cmp al,'u' ;U=Underline
jne clear4 ;jump if not U
and bh,088h ;mask off old foreground/
;background bits and
or bh,01h ;change to underline
jmp short clear1
clear4: cmp al,'b' ;B=Blink
jne clear5 ;jump if not B
or bh,080h ;set blink bit
jmp short clear1
clear5: cmp al,'s' ;S=Silent
jne clear1 ;if not S try next char.
mov bh,0 ;if S command, rig for
;silent running. Clear
;the foreground/background
;display control fields, and
;don't bother to look for
;any more command characters.
;
clear8: ;now we have decoded all
;the characters in the
;command tail, and are ready
;to initialize the display.
;BH= desired attribute
;CL,CH=(X,Y),upper left
; corner of window
;DL,DH=(X,Y),lower right
; corner of window
mov ax,0600h ;AH = function type 6,
;AL = lines to scroll (zero)
int 10h ;request initialization
;of window by BIOS
;
mov ah,2 ;now set the cursor to
mov bh,0 ;(X,Y)=(0,0), Page=0
xor dx,dx
int 10h
;
clear9: int 20h ;exit to PC-DOS
;
cseg ends
;
end clear

@ -0,0 +1,77 @@
PAGE ,132
TITLE CALC
CGROUP GROUP CODESEG
CODESEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CGROUP,DS:CGROUP,ES:CGROUP
PUBLIC CALC
ORG 100H
CALC PROC FAR
JMP START
;---------------------------------------------------------------------;
; ;
; DATA AREA ;
; ;
;---------------------------------------------------------------------;
DB 'INTERRUPT NUMBER ='
INT_NUMBER DB 61h
SCREEN_HANDLE DW 0001h
MESSAGE DB 'PEMATH is not resident',13,10
MESSAGE_LEN EQU $-MESSAGE
TAG DB 'PEMATH'
TAG_LEN EQU $-TAG
;---------------------------------------------------------------------;
; ;
; CODE AREA ;
; ;
;---------------------------------------------------------------------;
START:
;---------------------------------------------------------------------;
; TEST FOR PRESENCE OF CALCULATOR ;
;---------------------------------------------------------------------;
SUB AX,AX
MOV ES,AX
SUB BH,BH
MOV BL,INT_NUMBER
SHL BX,1
SHL BX,1
MOV DI,ES:[BX]
MOV ES,ES:[BX+2]
ADD DI,4
LEA SI,TAG
MOV CX,TAG_LEN
REPE CMPSB
JE CALL_CALC
MOV BX,SCREEN_HANDLE
MOV CX,MESSAGE_LEN
LEA DX,MESSAGE
MOV AH,40h
INT 21h
JMP SHORT CALC_EXIT
;---------------------------------------------------------------------;
; CALL CALCULATOR ;
;---------------------------------------------------------------------;
CALL_CALC:
MOV AL,INT_NUMBER
MOV BYTE PTR INT_CODE,AL
DB 0CDh ; INT
INT_CODE:
DB 00h
NOP
NOP
CALC_EXIT:
INT 20h
CALC ENDP
CODESEG ENDS
END CALC

@ -0,0 +1,58 @@
.model small ; It's a flaw of mine ... I really like this model
; I know I should do a .com with the tiny model..
; but I just love the small :>
.stack 100h ; Plenty stack ;>
.386
.data
info db 30 dup (0)
right db 'Right CD$'
wrong db 'Wrong CD$'
nomscdex db 'MSCDEX not installed$'
.code
mov ax, @data ; Make DS&ES point to the DATA
mov ds,ax
mov es,ax
lea edx, nomscdex
xor ebx,ebx
mov eax, 1500h ; MSCDEX installed?
int 2fh
test ebx,ebx
jz exit
mov edi,10h
nextloop:
mov ecx,edi
mov ax, 150bh ; is drive ECX supported by MSCDEX (is it a cdrom?)
int 2fh
test ax,ax ; ax!=0 if drive is CDrom
jz continiue
mov ax, 440dh
mov dx, offset info
mov bl,5
mov ch,8
mov cl,66h
int 21h ; Fetch volume serial number (same as when you do dir)
mov eax, dword ptr [info+2]
cmp eax, 0ffb7f724h; ;<<<<calibrate this to fit your own "right" CD
jnz continiue
lea edx, right
jmp exit
continiue:
dec edi ; next drive
jnz nextloop
lea edx, wrong ; not in any drive!
exit:
mov ah, 9h
int 21h
mov ax,4c00h ; terminate!
int 21h
end

@ -0,0 +1,14 @@
ctable segment para public 'DATA
db 9 dup(' ')
db 9,10,' ',12,13
db 13 dup(' ')
db 27
db 4 dup(' ')
db ' !"#$%&',39,'()*+,-./0123456789:;<=>?@'
db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`'
db 'abcdefghijklmnopqrstuvwxyz{|}~'
db 52 dup(' ')
db '|++++++|+++++++++-++++++++-+++++++++++++'
db 36 dup(' ')
ctable ends
end

@ -0,0 +1,113 @@
; From Ed Beroset - ISBN validation
; > Anyone know how to validate the ISBN numbers from books?
; isbnchek.asm
comment ^
This file contains a C-callable routine which calculates the
check digit (tenth digit) of an ISBN and returns the ASCII
representation of that digit.
This code was written for Borland's TASM
and may be assembled with the following command:
tasm /m2 isbnchek.asm
^
.MODEL small
public isbncheck
.CODE
;/***************************************************************************
;
; Name:
; isbncheck
;
; Purpose:
; Calculates the check digit for a ten digit ISBN, converts that
; digit to its ASCII representation and returns that answer.
;
; Algorithm:
; An ISBN consists of nine digits plus a validation digit.
; Number the digits from left to right as d1, d2, ... d9, with
; d10 being the validation digit. The calculation is then
;
; d10 = (1(d1) + 2(d2) + 3(d3) + ... + i(di) + ... + 9(d9))%11
;
; or the weighted sum of each digit mod eleven.
;
; In our assembly language implementation, we simulate the
; multiplications by looping through and summing as in the
; following psuedocode:
;
; sum = 0
; for i=1 to 9
; {
; for j=i to 9
; {
; sum = sum + isbn[j]
; }
; }
;
; Entry:
;
; isbn = a nine digit ASCII string containing the ISBN
; (with or without the check digit which is not used here)
;
; Register usage within the routine:
;
; AL = current ISBN digit
; AH = sum of digits so far
; BX = start pointer into ISBN for each outer loop
; CX = digit counter (inner loop)
; DX = start value for digit counter
; SI = points to current ISBN digit
;
; Exit:
;
; AX = ASCII representation of calculated check digit
;
; Trashed:
; none
;
;***************************************************************************/
isbncheck proc C isbn:ptr byte
push bx
push cx
push dx
push si
mov bx,[isbn] ;
mov dx,9 ; number of digits in raw ISBN
xor ax,ax ; clear out our total
cld ; count up
@@bigloop: ;
mov si,bx ; point to a digit in the ISBN
mov cx,dx ; get digit count in CX
@@AddEmUp: ;
lodsb ; fetch digit into AL
and al,0fh ; convert from ASCII
add ah,al ; add it to our total in AH
loop @@AddEmUp ; do all digits
inc bx ; and advance the digit pointer
dec dx ; now decrement digit count
jnz @@bigloop ; keep going if digits left
mov al,ah ; move sum into al
xor ah,ah ; clear out high half
mov cl,11 ; we'll be doing a mod 11 operation
div cl ; ah = sum mod 11
mov al,ah ; move calculated check digit to AL
xor ah,ah ; clear out high half
or al,30h ; convert to ASCII digit
cmp al,3Ah ;
jnz NotTen ;
mov al,'X' ;
NotTen: ;
pop si
pop dx
pop cx
pop bx
ret ; return
isbncheck endp
END

@ -0,0 +1,208 @@
; calling convention:
;
; int chips( void );
;
; returns:
;
; tucked away neatly in your AX....
;
; you get back 8x if an 8088/8086
; 18x if an 80186/80188
; 28x if an 80286
; 38x if an 80386
; 20x for a NEC V20/V30
; AND
; xx0 if NO NDP is found
; xx1 if an 8087
; xx2 if an 80287
; xx3 for an 80387
;
; OR.....
;
; >>> A return of 280 means you got an 80286 machine with no NDP, <<<
; >>> 383 means you have an 80386/80387 rig to work with, and a <<<
; >>> return of 81 sez that you have 8088/8086 CPU with an 8087. <<<
; >>> A 200 tells you that you got an NEC V20/V30 without an NDP. <<<
; >>> ETC., Etc., etc. <<<
;
; NOTE:
;
; There are lotsa ways of handling the way this function returns
; it's data. For my purposes, I have elected this one because
; it requires only int arithmetic on the caller's end to extract
; all the info I need from the return value. I think that I'm
; well enough 'commented' in the following code so that you will
; be able to tinker and Putz until you find the best return tech-
; nique for Ur purposes without having to reinvent the wheel.
;
; >>>> Please see TEST.C, enclosed in this .ARC. <<<<
;
; REFERENCES:
;
; _chips is made up of two PROC's, cpu_type and ndp_type.
;
; cpu_type is based on uncopyrighted, published logic by
; Clif (that's the way he spells it) Purkiser of Intel -
; Santa Clara.
;
; ndp_type is adopted from Ted Forgeron's article in PC
; Tech Journal, Aug '87 p43.
;
; In the event of subsequent republication of this function,
; please carry forward reference to these two gentlemen as
; original authors.
;
.MODEL SMALL
.CODE
PUBLIC _chips
_chips PROC
control dw 0 ; control word needed for the NDP test
push BP ; save where Ur at
mov BP,SP ; going in.....
push DI
push SI
push CX ; not really needed for MSC but kinda
; nice to do cuz someone else might
; want to use the function and we do
; use CX later on
call cpu_type ; find out what kinda CPU you got and
; and save it in DX for future reference
call ndp_type ; check for math coprocessor (NDP) type
; and hold that result in AX
add AX,DX ; add the two results together and hold
; 'em in AX for Ur return to the caller
pop CX ; put things back the way that you
pop SI ; found 'em when you started this
pop DI ; little drill off.....
pop BP
; AND
ret ; go back to where you came from....
; ( ===> the calling program )
; with Ur results sittin' in AX !!
_chips endp
cpu_type PROC
pushf ; pump Ur flags register onto the stack
xor DX,DX ; blow out Ur DX and AX to start off
xor AX,AX ; with a clean slate
push AX ; put AX on the stack
popf ; bring it back in Ur flags
pushf ; try to set bits 12 thru 15 to a zero
pop AX ; get back Ur flags word in AX
and AX, 0f000h ; if bits 12 thru 15 are set then you got
cmp AX, 0f000h ; an Intel 8018x or a 808x or maybe even
jz dig ; a NEC V20/V30 ??? - gotta look more...
; OTHERWISE....
; Here's the BIG one.... 'tells the difference between an 80286 and
; an 80386 !!
mov AX, 07000h ; try to set FLAG bits 12 thru 14
; - NT, IOPL
push AX ; put it onto the stack
popf ; and try to pump 07000H into Ur flags
pushf ; push Ur flags, again
pop AX ; and bring back AX for a compare
and AX,07000h ; if Ur bits 12 thru 14 are set
jnz got386 ; then Ur workin' with an 80386
mov DX, 0280 ; save 280 in DX cuz it's an 80286
jmp SHORT CPUbye ; and bail out
got386: mov DX, 0380 ; save 380 in DX cuz it's an Intel 80386
jmp SHORT CPUbye ; and bail out
; here's we try to figger out whether it's an 80188/80186, an 8088/8086
; or an NEC V20/V30 - 'couple of slick tricks from Clif Purkiser.....
dig: mov AX, 0ffffh ; load up AX
mov CL, 33 ; HERE's the FIRST TRICK.... this will
; shift everything 33 times if it's
; 8088/8086, or once for a 80188/80186!
shl AX, CL ; on a shift of 33, all bits get zeroed
jz digmor ; out so if anything is left ON it's
; gotta be an 80188/80186
mov DX,0180 ; save 180 in DX cuz it's an 80188/80186
jmp SHORT CPUbye ; and bail out
digmor: xor AL,AL ; clean out AL to set ZF
mov AL,40h ; ANOTHER TRICK.... mul on an NEC duz NOT
mul AL ; effect the zero flag BUT on an Intel
jz gotNEC ; 8088/8086, the zero flag gets thrown
mov DX,0080 ; 80 into DX cuz it's an Intel 8088/8086
jmp SHORT CPUbye ; and bail out
gotNEC: mov DX,0200 ; it's an NEC V20/V30 so save 200 in DX
CPUbye: popf ; putchur flags back to where they were
ret ; and go back to where you came from
; (i.e., ===> _chips) with the CPU type
; tucked away in DX for future reference
cpu_type endp
; Check for an NDP.
;
; >>>>NOTE: If you are using an MASM version < 5.0, don't forget to
; use the /R option or you will bomb cuz of the coprocessor instruc-
; tions. /R is not needed for version 5.0.<<<<<<<<<<<<<<<<<<<<<<<<<
ndp_type PROC
do_we: fninit ; try to initialize the NDP
mov byte ptr control+1,0 ; clear memory byte
fnstcw control ; put control word in memory
mov AH,byte ptr control+1 ; iff AH is 03h, you got
cmp AH,03h ; an NDP on board !!
je chk_87 ; found somethin', keep goin'
xor AX,AX ; clean out AX to show a zero
jmp SHORT NDPbye ; return (i.e., no NDP)
; 'got an 8087 ??
chk_87: and control,NOT 0080h ; turn ON interrupts (IEM = 0)
fldcw control ; load control word
fdisi ; turn OFF interrupts (IEM = 1)
fstcw control ; store control word
test control,0080h ; iff IEM=1, 8087
jz chk287 ; 'guess not! March on....
mov AX,0001 ; set up for a 1 return to
jmp SHORT NDPbye ; show an 8087 is on board
; if not.... would you believe an 80287 maybe ??
chk287: finit ; set default infinity mode
fld1 ; make infinity
fldz ; by dividing
fdiv ; 1 by zero !!
fld st ; now make a
fchs ; negative infinity
fcompp ; compare Ur two infinities
fstsw control ; iff, for 8087 or 80287
fwait ; sit tight 'til status word is put away
mov AX,control ; getchur control word
sahf ; putchur AH into flags
jnz got387 ; NO GOOD.... march on !!
mov AX,0002 ; gotta be a 80287 cuz we already tested
jmp SHORT NDPbye ; for an 8087
; We KNOW that there is an NDP on board otherwise we would have bailed
; out after 'do_we'. It isn't an 8087 or an 80287 or we wouldn't have
; gotten this far. It's gotta be an 80387 !!
got387: mov AX,0003 ; call it an 80387 and return 3
NDPbye: ret ; and go back where you came from
; (i.e., ===> _chips) carrying the NDP
; type in Ur AX register
ndp_type endp
_text ends
end

@ -0,0 +1,83 @@
cseg segment
assume cs:cseg, ds:cseg, ss:cseg
org 100h
.386
start:
mov ax, 13h
int 10h
mov dx, 3c8h
xor al, al
out dx, al
inc dx
mov cx, 256
xor al, al
lopp: out dx, al
out dx, al
out dx, al
inc al
dec cx
jnz lopp
mov ax, 0a000h
mov es, ax
fild y_rad
fild x_rad
loopdr:
fild angle
fsincos
fmul st, st(2)
fistp x_co
fmul st, st(2)
fistp y_co
add x_co, 160
add y_co, 100
xor di, di
mov ax, y_co
shl ax, 6
add di, ax
shl ax, 2
add di, ax
add di, x_co
mov byte ptr es:[di], cl
inc cl
fadd yvel
fxch st(1)
fadd xvel
fxch st(1)
inc angle
jnz loopdr
xor ax, ax
int 16h
mov ax, 3
int 10h
int 20h
x_co dw 0
y_co dw 0
x_rad dw 10
y_rad dw 10
xvel dq 0.001
yvel dq 0.001
angle dw 0
cseg ends
end start

@ -0,0 +1,137 @@
CGROUP GROUP VECTOR,CODESEG
VECTOR SEGMENT AT 0H
DB 6CH DUP(?) ;FILLER
TIME_LO DW ? ;DOS TIME
TIME_HI DW ? ;DOS TIME
VEC_IP DW ;CLOCK UPDATE VECTOR IP
VEC_CS DW ;CLOCK UPDATE VECTOR CS
VECTOR ENDS
CODESEG SEGMENT PARA
ASSUME CS:CODESEG,DS:CGROUP
ORG 100H
CLK PROC FAR
JMP SETUP ;ATTACH TO DOS
INTRPT LABEL DWORD
INT_IP DW 0 ;OLD UPDATE VECTOR IP
INT_CS DW 0 ;OLD UPDATE VECROR CS
TICKS DW 0 ;TICK COUNTER
SCR_OFF DB 0,0 ;SCREEN OFFSET IN BUFFER
CRT_PORT DW 0 ;SCREEN STATUS PORT
flag db 0
TIME DB 8 DUP(':',0BH) ;TIME SAVE AREA
CLK_INT LABEL NEAR
PUSH AX ;SAVE REGISTERS
PUSH CX
PUSH DI
PUSH SI
PUSH DS
PUSH ES
PUSHF ; AND FLAGS
CALL CS:[INTRPT] ;DO OLD UPDATE INTERRUPT
MOV CX,0040H ;GET SEGMENT OF DOS TABLE
MOV DS,CX ;PUT IN DS
MOV CX,CS:TICKS ;GET TICK COUNT
INC CX ;INCREMENT IT
CMP CX,20 ;01F4H ;HAS A MINUTE GONE BY?
JB NO_MINUTE ;NO, MOVE ON
CALL UPDATE ;YES, UPDATE CLOCK AND
MOV CX,0 ; RESET TICK COUNTER
NO_MINUTE:
MOV CS:TICKS,CX ;SAVE UPDATED TICK COUNT
MOV CX,0B000H ;GET VIDEO SEGMENT
MOV ES,CX ;PUT IN ES
MOV DX,CS:CRT_PORT ;GET CRT STATUS PORT ADDR
MOV DI,WORD PTR CS:SCR_OFF ;GET SCREEN BUFFER OFFSET
LEA SI,CS:TIME ;GET DOS TIME
MOV CX,16 ;SET UP TO MOVE 10 BYTES
CLI ;DISABLE OTHER INTERRUPTS
WAIT1: IN AL,DX ;READ CRT STATUS
TEST AL,1 ;CHECK FOR VERTICAL RETRACE
JNZ WAIT1 ;WAIT FOR RETRACE LOW
MOV AH,CS:[SI] ;GET FIRST BYTE TO MOVE
WAIT2: IN AL,DX ;GET CRT STATUS
TEST AL,1 ;CHECK FOR VERTICAL RETRACE
JZ WAIT2 ;WAIT FOR RETRACE HIGH
MOV ES:[DI],AH ;MOVE BYTE TO SCREEN
INC DI ;INCREMENT INDEX
INC SI
LOOP WAIT1 ;MOVE NEXT BYTE
STI ;ENABLE INTERRUPTS
POP ES ;RESTORE REGISTERS
POP DS
POP SI
POP DI
POP CX
POP AX
IRET ;RETURN FROM INTERRUPT
CLK ENDP
UPDATE PROC NEAR
PUSH AX ;SAVE REGISTERS
PUSH BX
PUSH CX
PUSH DX
PUSH DS
MOV AX,0040H ;GET ADDRESS OF DOS TABLE
MOV DS,AX ;PUT IN DS
MOV AX,TIME_HI ;GET HIGH BYTE OF DOS TIME
mov flag,0 ;am flag
HOUR: CMP AX,0CH ;CONVERT TO HOURS
JLE H1
mov flag,1 ;set to pm
SUB AX,0CH
JMP HOUR
H1: AAM ;CONVERT TO ASCII
ADD AX,3030H
LEA BX,CS:TIME ;GET ADDRESS OF TIME AREA
MOV CS:[BX],AH ;SAVE HOURS FIRST DIGIT
MOV CS:[BX+2],AL ;SAVE HOURS SECOND DIGIT
MOV AX,TIME_LO ;GET DOS TIME LOW BYTE
MOV CX,8H ;CONVERT TO MINUTES
SHR AX,CL
MOV DX,3CH
MUL DL
SHR AX,CL
AAM ;CONVERT TO ASCII
ADD AX,3030H
MOV CS:[BX+6],AH ;SAVE MINUTES FIRST DIGIT
MOV CS:[BX+8],AL ;SAVE MINUTES SECOND DIGIT
mov byte ptr cs:[bx+12],'a'
cmp flag,0 ;is it am?
jz goahead
mov byte ptr cs:[bx+12],'p'
goahead:
mov byte ptr cs:[bx+14],'m'
POP DS ;RESTORE REGISTERS
POP DX
POP CX
POP BX
POP AX
RET
UPDATE ENDP
SETUP: MOV AX,0 ;GET ADDRESS OF VECTOR TABLE
MOV DS,AX ;PUT IN DS
CLI ;DISABLE FURTHER INTERRUPTS
MOV AX,[VEC_IP] ;GET ADDRESS OF OLD UPDATE IP
MOV CS:[INT_IP],AX ;SAVE IT
MOV AX,[VEC_CS] ;GET ADDRESS OF OLD UPDATE CS
MOV CS:[INT_CS],AX ;SAVE IT
MOV VEC_IP,OFFSET CLK_INT ;PUT ADDRESS OF CLK IN VECTOR IP
MOV VEC_CS,CS ;PUT CS OF CLK IN VECTOR CS
STI ;ENABLE INTERRUPTS
MOV AH,0FH ;READ VIDEO STATUS
INT 10H
SUB AH,8 ;SUBTRACT 8 CHAR TIME FROM NCOLS
SHL AH,1 ;MULTIPLY BY 2 FOR ATTRIBUTE
MOV CS:SCR_OFF,AH ;SAVE SCREEN TIME LOCATION
MOV WORD PTR CS:CRT_PORT,03BAH ;SAVE MONO STATUS PORT ADDR
TEST AL,4 ;CHECK FOR COLOR MONITOR
JNZ MONO ;IF MONO, MOVE ON
ADD WORD PTR CS:SCR_OFF,8000H ;ADD COLOR OFFSET TO TIME OFFSET
MOV WORD PTR CS:CRT_PORT,03DAH ;SAVE COLOR STATUS PORT ADDR
MONO: CALL UPDATE ;DO FIRST UPDATE & PRINT TIME
MOV DX,OFFSET SETUP ;GET END ADDRESS OF NEW INTERRUPT
INT 27H ;TERMINATE AND REMAIN RESIDENT
DB 117 DUP(0) ;FILLER
CODESEG ENDS
END CLK

@ -0,0 +1,109 @@
; for tasm
;
cseg segment
assume cs:cseg, ds:cseg
org 100H
begin:
mov es,cs:[video]
mov ax,3
int 10h
mov cs:[col],0fh
mov di,18
lea si,colr2
call mess
mov cx,16
mov di,160
xor al,al
rec1:
push cx
push di
lea si,colour
call mess
call hex2
mov bh,al
push cx
mov cx,16
col2:
mov es:[di],byte ptr "#"
mov es:[di+1],bh
inc bh
add di,2
loop col2
pop cx
pop di
add di,160
add al,10h
add cs:[col],10h
pop cx
loop rec1
mov ah,2
mov bh,0
mov dh,17
mov dl,0
int 10h
mov ah,4ch
int 21h
col db 0
colour db "Colour ",0
colr2 db "0123456789ABCDEF",0
colnum db 0
video dw 0b800h
hex2 proc near
push ax
and al,011110000b
shr al,4
call hex1
pop ax
push ax
and al,01111b
call hex1
pop ax
ret
hex2 endp
hex1 proc near
mov ah,cs:[col]
cmp al,10
jb hnum1
add al,'A'-10
jmp hnum2
hnum1:
add al,'0'
hnum2:
mov es:[di],ax
add di,2
ret
hex1 endp
mess proc
push ax
mov ah,cs:[col]
conmess:
mov al,cs:[si]
or al,al
jz endmess
mov es:[di],ax
inc si
add di,2
jmp conmess
endmess:
pop ax
ret
mess endp
cseg ends
end begin

@ -0,0 +1,132 @@
; toclip.asm
;
; This code may be assembled and linked using Borland's TASM:
; tasm /la /m2 toclip
; tlink /Tdc toclip
;
; It also works with Microsoft's MASM:
; ml /Fl toclip.asm
;
STDIN equ 00h ; handle of standard input device
STDOUT equ 01h ; handle of standard output device
STDERR equ 02h ; handle of standard error device
DOS_READ_HANDLE equ 03fh ; read from handle
DOS_WRITE_HANDLE equ 040h ; write to handle
DOS_ALLOC_MEM equ 048h ; allocate memory block
DOS_RESIZE_MEM equ 04ah ; resize memory block
DOS_TERMINATE equ 04ch ; terminate with error code
WIN_VERSION equ 01700h ; identify WinOldAp version
WIN_OPEN_CLIP equ 01701h ; open clipboard
WIN_EMPTY_CLIP equ 01702h ; empty clipboard
WIN_SET_CLIP equ 01703h ; set clipboard data
WIN_CLOSE_CLIP equ 01708h ; close clipboard
; clipboard formats:
CLIP_FMT_TXT equ 01h ; text format
CLIP_FMT_BMP equ 02h ; bitmap format
CLIP_FMT_TIFF equ 06h ; TIFF
CLIP_FMT_OEMTXT equ 07h ; OEM text
WININT macro function
mov ax,(function)
int 2fh
endm
DOSINT macro function, subfunction
IFB <subfunction>
mov ah,(function AND 0ffh)
ELSE
mov ax,(function SHL 8) OR (subfunction AND 0ffh)
ENDIF
int 21h ; invoke DOS function
endm
ERRMSG macro tag, message
LOCAL nextmsg
tag db nextmsg-$
db message
nextmsg = $
endm
.model small
.386
.stack 100h
.data
ERRMSG cantresize, <"ERROR: can't resize memory",0dh,0ah>
ERRMSG noclipboard,<"ERROR: no clipboard",0dh,0ah>
ERRMSG emptyclip, <"ERROR: cannot empty clipboard",0dh,0ah>
ERRMSG openclip, <"ERROR: cannot open clipboard",0dh,0ah>
ERRMSG allocerror, <"ERROR: can't allocate 64K buffer",0dh,0ah>
ERRMSG readerr, <"ERROR: can't read data from stdin",0dh, 0ah>
ERRMSG pasteerr, <"ERROR: can't paste data to clipboard",0dh,0ah>
.code
start proc
mov bx,ss ; stack segment
mov ax,ds ; - data segment
sub bx,ax ; = size of all but stack
add bx,10h ; add in stack size (in paragraphs)
DOSINT DOS_RESIZE_MEM ;
mov di,offset cantresize
jc error
WININT WIN_VERSION
cmp ax,WIN_VERSION
mov di,offset noclipboard
jz error ;
WININT WIN_OPEN_CLIP ; open clipboard
or ax,ax ; nonzero status means error
mov di,offset openclip
jz error ;
WININT WIN_EMPTY_CLIP ; empty clipboard
or ax,ax ; nonzero status means error
mov di,offset emptyclip
jz error ;
; allocate a big buffer
mov bx,1000h ; 1000h paragraphs = 64K
DOSINT DOS_ALLOC_MEM ;
mov di,offset allocerror
jc error ;
mov ds,ax ;
mov es,ax ;
; read from the input file
mov bx,STDIN ; stdin
mov cx,0ffffh ; read a whole bunch of data
; ds:dx ==> data buffer
xor dx,dx ;
DOSINT DOS_READ_HANDLE ;
mov di,offset readerr
jc error ;
xor si,si ;
mov cx,ax ; size
; paste the file buffer into the clipboard
; mov es:bx ==> data
xor bx,bx
; mov si:cx, size of data
mov dx,CLIP_FMT_TXT ; text data
WININT WIN_SET_CLIP ;
or ax,ax
mov di,offset pasteerr ;
jz error ;
WININT WIN_CLOSE_CLIP ; close clipboard
DOSINT DOS_TERMINATE,0 ; exit with error code = 0
error:
mov bx,@data ;
mov ds,bx ;
xor cx,cx ;
mov cl,byte ptr[di] ; fetch length
mov dx,di ; point to data
inc dx ; advance beyond length
mov bx,STDERR ; write to stderr
DOSINT DOS_WRITE_HANDLE ; write to handle
DOSINT DOS_TERMINATE,1 ; error exit
start endp
END start

@ -0,0 +1,168 @@
title Control-Break handler for Lattice C programs
name break
include dos.mac
; Control-Break Interrupt Handler for Lattice C programs
; running on IBM PCs (and ROM BIOS compatibles)
;
; This module allows C programs running on the IBM PC
; to retain control when the user enters a Control-Break
; or Control-C. This is accomplished by taking over the
; Int 23H (MS-DOS Control-Break) and Int 1BH (IBM PC
; ROM BIOS Keyboard Driver Control-Break) interrupt
; vectors. The interrupt handler sets an internal
; flag (which must be declared STATIC INT) to TRUE within
; the C program; the C program can poll or ignore this
; flag as it wishes.
;
; The module follows the Lattice C parameter passing
; conventions, and also relies on the Lattice file DOS.MAC
; for the definition of certain constants and macros.
;
; The Int 23H Control-Break handler is a function of MS-DOS
; and is present on all MS-DOS machines, however, the Int 1BH
; handler is a function of the IBM PC ROM BIOS and will not
; necessarily be present on other machines.
;
if lprog
args equ 6 ;offset of arguments, Large models
else
args equ 4 ;offset of arguments, Small models
endif
cr equ 0dh ;ASCII carriage return
lf equ 0ah ;ASCII line feed
pseg
public capture,release ;function names for C
;
; The function CAPTURE is called by the C program to
; take over the MS-DOS and keyboard driver Control-
; Break interrupts (1BH and 23H). It is passed the
; address of a flag within the C program which is set
; to TRUE whenever a Control-Break or Control-C
; is detected. The function is used in the form:
;
; static int flag;
; capture(&flag)
;
capture proc near ;take over Control-Break
push bp ;interrupt vectors
mov bp,sp
push ds
mov ax,word ptr [bp+args]
mov cs:flag,ax ;save address of integer
mov cs:flag+2,ds ;flag variable in C program
;pick up original vector contents
mov ax,3523h ;for interrupt 23H (MS-DOS
int 21h ;Control-Break handler)
mov cs:int23,bx
mov cs:int23+2,es
mov ax,351bh ;and interrupt 1BH
int 21h ;(IBM PC ROM BIOS keyboard driver
mov cs:int1b,bx ;Control-Break interrupt handler)
mov cs:int1b+2,es
push cs ;set address of new handler
pop ds
mov dx,offset ctrlbrk
mov ax,02523H ;for interrupt 23H
int 21h
mov ax,0251bH ;and interrupt 1BH
int 21h
pop ds ;restore registers and
pop bp ;return to C program
ret
capture endp
;
; The function RELEASE is called by the C program to
; return the MS-DOS and keyboard driver Control-Break
; interrupt vectors to their original state. Int 23h is
; also automatically restored by MS-DOS upon the termination
; of a process, however, calling RELEASE allows the C
; program to restore the default action of a Control-C
; without terminating. The function is used in the form:
;
; release()
;
release proc near ;restore Control-Break interrupt
;vectors to their original state
push bp
mov bp,sp
push ds
mov dx,cs:int1b ;set interrupt 1BH
mov ds,cs:int1b+2 ;(MS-DOS Control-Break
mov ax,251bh ;interrupt handler)
int 21h
mov dx,cs:int23 ;set interrupt 23H
mov ds,cs:int23+2 ;(IBM PC ROM BIOS keyboard driver
mov ax,2523h ;Control-Break interrupt handler)
int 21h
pop ds ;restore registers and
pop bp ;return to C program
ret
release endp
;
; This is the actual interrupt handler which is called by
; the ROM BIOS keyboard driver or by MS-DOS when a Control-C
; or Control-Break is detected. Since the interrupt handler
; may be called asynchronously by the keyboard driver, it
; is severely restricted in what it may do without crashing
; the system (e.g. no calls on DOS allowed). In this
; version, it simply sets a flag within the C program to
; TRUE to indicate that a Control-C or Control-Break has
; been detected; the address of this flag was passed
; by the C program during the call to the CAPTURE function.
;
ctrlbrk proc far ;Control-Break interrupt handler
push bx ;save affected registers
push ds
mov bx,cs:flag ;set flag within C program
mov ds,cs:flag+2 ;to "True"
mov word ptr ds:[bx],-1
pop ds ;restore registers and exit
pop bx
iret
ctrlbrk endp
flag dw 0,0 ;long address of C program's
;Control-Break detected flag
int23 dw 0,0 ;original contents of MS-DOS
;Control-Break Interrupt 23H
;vector
int1b dw 0,0 ;original contents of ROM BIOS
;keyboard driver Control-Break
;Interrupt 1BH vector
endps
end

@ -0,0 +1,44 @@
; test1.asm
;
; This program uses flat real mode to read the contents of arbitrary
; memory locations to the screen. It assumes that flat real mode (4G
; limit) is already in place for the FS segment.
;
; This code is intended to be run on a Pentium or better.
;
; To assemble:
;
; using Microsoft's MASM 6.11 or better
; ml /Fl flatmode.asm
;
; or Borland's TASM version 4.0 or better
; tasm /la /m2 flatmode.asm
; tlink /Tdc flatmode
;
;----------------------------------------------------------------------
.model tiny
.code
.586P
;----------------------------------------------------------------------
ORG 100h
start:
call fillscreen ; fill the screen using 4G descriptor
mov ax,4c00h ; do a standard DOS exit
int 21h ;
;----------------------------------------------------------------------
fillscreen proc
mov esi,0FFFFFF70h ; point to ROM
mov edi,0B8000h ; point to screen
mov cx,160 ; just two lines
mov ah,1Eh ; yellow on blue screen attrib
myloop:
mov al,fs:[esi] ; read ROM byte
mov fs:[edi],ax ; store to screen with attribute
inc esi ; increment source ptr
inc edi ; increment dest ptr by two
inc edi ;
loop myloop ; keep going
ret ; and quit
fillscreen endp
end start

@ -0,0 +1,221 @@
comment *
SERTYPE.ASM
Purpose:
Determines the type of UART in each serial port
*
dosseg
bdseg segment at 40h ;bios data segment
com1 dw ?
com2 dw ?
com3 dw ?
com4 dw ?
ends
_data segment para 'data'
uart1 db 0
uart2 db 0
uart3 db 0
uart4 db 0
portmsg db "COMx: $"
x8250 db "NS 8250 (non-FIFO)",13,10,"$"
x16450 db "NS 8250A/16450/16550 (non-FIFO)",13,10,"$"
xfifo db "NS 16550A/Intel 82510 (FIFO)",13,10,"$"
xdma db "IBM type 3 (FIFO/DMA)",13,10,"$"
pas_de_ports db "No serial ports detected",13,10,"$"
ends
_stack segment para stack 'stack'
db 200h dup (?)
ends
cseg segment para 'code'
mov ax, bdseg
mov es, ax ;ES := Bdseg
mov ax, _data
mov ds, ax ;DS := _data
assume cs:cseg, ds:_data, es:bdseg, ss:_stack
xor al, al ;# of serial ports = 0
mov dx, [com1]
cmp dx, 0
je eoproc
inc al ;# of serial ports = 1
push ax
call uartdet
mov [uart1], al ;remember the type of this UART
pop ax
mov dx, [com2]
cmp dx, 0
je eoproc
inc al ;# of serial ports = 2
push ax
call uartdet
mov [uart2], al
pop ax
mov dx, [com3]
cmp dx, 0
je eoproc
inc al ;# of serial ports = 3
push ax
call uartdet
mov [uart3], al
pop ax
mov dx, [com4]
cmp dx, 0
je eoproc
inc al ;# of serial ports = 4
push ax
call uartdet
mov [uart4], al
pop ax
eoproc:
call disp
mov ah, 4ch
int 21h
delay macro
jmp $+2
endm
uartdet proc near
push bx
push cx
mov bx, dx ;save starting i/o addr
add dx, 4 ;point to modem ctrl reg
in al, dx ;disable interrupts
push ax
and al, 11111011b
out dx, al
mov ch, 0 ;assume type 0
mov dx, bx
add dx, 7 ;see if scratch reg exists
mov al, 55h
cli
out dx, al ;write to scratch reg
delay
in al, dx ;read back
cmp al, 55h
jne endudet
mov al, 0AAh
out dx, al ;write to scratch reg
delay
in al, dx ;read back
sti
cmp al, 0AAh
jne endudet
inc ch ;assume type 1
mov dx, bx
add dx, 2 ;point to FIFO ctrl reg
mov al, 7 ;attempt to enable FIFOs
cli
out dx, al
delay
in al, dx ;read interrupt ID reg
sti
and al, 0c0h ;strip all but FIFO bits
jz endudet ;if bits 0, 16450/16550
inc ch ;assume type 2
mov dx, bx
add dx, 8003h ;point to enhanced reg 1
cli
in al, dx
push ax
or al, 01000000b ;enable DMA transmission
out dx, al
push dx
mov dx, bx
add dx, 2
in al, dx
mov cl, al
pop dx ;restore enhanced reg 1
pop ax
out dx, al
sti
and cl, 0c0h ;again mask all but FIFO ID
cmp cl, 40h
jne endudet ;must be type 2 (FIFO)
inc ch ;must be type 3 (DMA)
endudet:
pop ax
mov dx, bx
add dx, 4 ;point to modem ctrl reg
out dx, al ;restore initial condition
xor ax, ax
mov al, ch
mov dx, bx
pop cx
pop bx
ret
uartdet endp
disp proc near
push ax ;save AX
cmp al, 0 ;no serial ports?
je noports
mov bx, offset ds:[uart1] ;offset of UART type field
mov di, offset ds:[portmsg][3] ;offset of 4th char in message
mov cx, 0
mov cl, al ;number of iterations
@l1:
;
;write "COMx: " message substituting "x" for proper comport #
;
mov dl, 4
sub dl, cl
add dl, 30h ;convert to ASCII number
mov [di], dl
lea dx, portmsg
mov ah, 9
int 21h
;
;write the UART type now
;
mov dl, [bx]
cmp dl, 0
jne @t2
lea dx, x8250
mov ah, 9
int 21h
jmp @eot
@t2: cmp dl, 1
jne @t3
lea dx, x16450
mov ah, 9
int 21h
jmp @eot
@t3: cmp dl, 2
jne @t4
lea dx, xfifo
mov ah, 9
int 21h
jmp @eot
@t4: lea dx, xdma
mov ah, 9
int 21h
@eot: inc bx
loop @l1
jmp eoproc2
noports:
lea dx, pas_de_ports
mov ah, 9
int 21h
eoproc2:
pop ax
ret
disp endp
ends
end
; EOF SERTYPE.ASM

@ -0,0 +1,233 @@
;-----------------------------------------------------------------------|
;
; Device Driver Library
; Device Driver Header
;
;-----------------------------------------------------------------------|
PAGE
;-----------------------------------------------------------------------|
; Equates
;-----------------------------------------------------------------------|
StkSiz EQU 2048 ; local stack size
PAGE
;-----------------------------------------------------------------------|
; Group Selection
;-----------------------------------------------------------------------|
PGROUP Group PROG, TAIL
DGROUP Group DATA, DTAIL
PROG Segment Para Public 'PROG'
PROG EndS
DATA Segment Para Public 'DATA' ; define first
DATA EndS
Assume CS:PROG, DS:DATA, ES:DATA, SS:DATA
PAGE
;-----------------------------------------------------------------------|
; Program Segment
;-----------------------------------------------------------------------|
PROG Segment Para Public 'PROG'
Extrn Init:Near, MediaChe:Near, BuildBPB:Near
Extrn IoCtlIn:Near, Input:Near, ndInput:Near
Extrn InputSta:Near, InputFlu:Near, Output:Near
Extrn OutVerif:Near, OutStatu:Near, OutFlush:Near
Extrn IoCtlOut:Near, DevOpen:Near, DevClose:Near
Extrn RemMedia:Near
ORG 0
HDR Proc Far
;-----------------------------------------------------------------------|
; Device Header
;-----------------------------------------------------------------------|
DD -1 ; -> next device
; DW theAttribute ; you must enter attribute field
DW 8000H ; character only device
DW Strategy ; -> device strategy
DW Interrupt ; -> device interrupt
; DB theName ; you must put something here
DB "MON " ; mono
;-----------------------------------------------------------------------|
; Code Segment Variables
;-----------------------------------------------------------------------|
RHptr DD (?) ; -> Request Header
ssEntry DW (?) ; entry SS
spEntry DW (?) ; entry SP
PAGE
;-----------------------------------------------------------------------|
; Device Strategy
;
; ENTRY : ES:BX -> Request Header
;
; EXIT : Request Header copied to ReqHdr
; all registers preserved
;
;-----------------------------------------------------------------------|
Strategy:
MOV Word Ptr CS:RHptr,BX ; save request header ptr
MOV Word Ptr CS:RHptr + 2,ES
PUSHF ; (+1) save the world
PUSH ES ; (+2)
PUSH DS ; (+3)
PUSH SI ; (+4)
PUSH DI ; (+5)
PUSH CX ; (+6)
PUSH BX ; (+7)
MOV SI,BX
MOV BX,ES
MOV DS,BX ; DS:SI -> Request Header
MOV BX,Offset PGROUP:TAIL
MOV CL,4
SHR BX,CL
MOV CX,CS
ADD BX,CX
MOV ES,BX
MOV DI,Offset DGROUP:ReqHdr ; ES:DI -> ReqHdr
CLD
XOR CH,CH
MOV CL,[SI]
REP MOVSB ; copy Request Header
POP BX ; (+6) restore
POP CX ; (+5)
POP DI ; (+4)
POP SI ; (+3)
POP DS ; (+2)
POP ES ; (+1)
POPF ; (+0)
RET
PAGE
;-----------------------------------------------------------------------|
; Device Interrupt
;
; ENTRY : anything
;
; EXIT : all registers preserved
;
;-----------------------------------------------------------------------|
Interrupt:
PUSH DS ; (+1) save the world
PUSH ES ; (+2)
PUSH AX ; (+3)
PUSH BX ; (+4)
PUSH CX ; (+5)
PUSH DX ; (+6)
PUSH SI ; (+7)
PUSH DI ; (+8)
PUSH BP ; (+9)
MOV CS:ssEntry,SS ; save entry SS
MOV CS:spEntry,SP ; and SP
MOV AX,Offset PGROUP:TAIL ; set our DS, SS, BP, and SP
MOV CL,4
SHR AX,CL
MOV CX,CS
ADD AX,CX
MOV BX,Offset DGROUP:MyStack
MOV DS,AX
MOV ES,AX
MOV SS,AX
MOV SP,BX
MOV BP,BX
;
; call our function
;
MOV AL,ReqHdr + 2 ; AL = Command Code
SHL AL,1
CBW
MOV SI,Offset DGROUP:FuncTab
ADD SI,AX
CALL Word Ptr [SI]
;
; copy back Request Header
;
LES DI,RHptr ; ES:DI -> original space
MOV SI,Offset DGROUP:ReqHdr ; DS:SI -> our (updated) copy
CLD
XOR CH,CH
MOV CL,[SI]
REP MOVSB ; copy Request Header
MOV SS,CS:ssEntry ; restore original stuff
MOV SP,CS:spEntry
POP BP ; (+8) restore
POP DI ; (+7)
POP SI ; (+6)
POP DX ; (+5)
POP CX ; (+4)
POP BX ; (+3)
POP AX ; (+2)
POP ES ; (+1)
POP DS ; (+0)
RET
HDR EndP
PROG EndS
TAIL Segment Public 'PROG' ; for finding end of code segment
TAIL EndS
PAGE
;-----------------------------------------------------------------------|
; Data Segment
;-----------------------------------------------------------------------|
DATA Segment Para Public 'DATA'
Public ReqHdr
DB StkSiz DUP (?) ; our stack, overflows into code
MyStack Label Word
FuncTab Label Word
DW Offset PGROUP:Init
DW Offset PGROUP:MediaChe
DW Offset PGROUP:BuildBPB
DW Offset PGROUP:IoCtlIn
DW Offset PGROUP:Input
DW Offset PGROUP:ndInput
DW Offset PGROUP:InputSta
DW Offset PGROUP:InputFlu
DW Offset PGROUP:Output
DW Offset PGROUP:OutVerif
DW Offset PGROUP:OutStatu
DW Offset PGROUP:OutFlush
DW Offset PGROUP:IoCtlOut
DW Offset PGROUP:DevOpen
DW Offset PGROUP:DevClose
DW Offset PGROUP:RemMedia
ReqHdr DB 256 DUP (?) ; copy of Request Header
DATA EndS
DTAIL Segment Public 'DATA' ; for finding end of data segment
DTAIL EndS
END HDR ; of HDR.ASM

@ -0,0 +1,41 @@
; cache disable routine
;
public DisableCache
code segment ; simple but effective for demonstration purposes
;* DisableCache() *
;* *
;* This routine disables cache(s) on a 486 or Pentium processor *
;* *
;* NOTE: due to the protection schemes incorporated into the 486 and *
;* Pentium processors, it will NOT work in virtual 8086 mode. *
;* *
;* written on Thursday, 2 November 1995 by Ed Beroset *
;* and released to the public domain by the author *
.486P
CR0_CD equ 040000000h ; Cache Disable bit of CR0
CR0_NW equ 020000000h ; Not Write-through bit of CR0
DisableCache proc
pushf ; save the flags
push eax ; save eax
cli ; disable interrupts while we do this
mov eax,cr0 ; read CR0
or eax,CR0_CD ; set CD but not NW bit of CR0
mov cr0,eax ; cache is now disabled
wbinvd ; flush and invalidate cache
; the cache is effectively disabled at this point, but memory
; consistency will be maintained. To completely disable cache,
; the following two lines may used as well:
or eax,CR0_NW ; now set the NW bit
mov cr0,eax ; turn off the cache entirely
pop eax ; restore eax
popf ; restore the flags
ret ; return to caller
DisableCache endp
code ends
end

@ -0,0 +1,106 @@
interrupts segment at 0h ; This is where the disk interrupt
org 13h*4 ; holds the address of its service routine
disk_int label dword
interrupts ends
screen segment at 0B000h ; A dummy segment to use as the Extra
screen ends ; Segment so we can write to the display
code_seg segment
assume cs:code_seg
org 0100h ; ORG = 100h to make this a .COM file
first: jmp load_watch ; First time through jump to initialize routine
msg_part_1 db 'Disk error: ' ; Here are the error messages
msg_part_2 db 'No response Failed Seek NEC Error '
db 'Bad CRC SeenDMA Overrun Impos Sector'
db 'No Addr MarkW. ProtectedErr Unknown '
first_position dw ? ; Position of 1st char on screen
flags dw ?
screen_seg_offset dw 0 ; 0 for mono, 8000h for graphics
old_disk_int dd ? ; Location of old disk interrupt
ret_addr label dword ; Used in fooling around with
ret_addr_word dw 2 dup(?) ; the stack
disk_watch proc far ; The disk interrupt will now come here
assume cs:code_seg
pushf ; First, call old disk interrupt
call old_disk_int
pushf ; Save the flags in memory location "FLAGS"
pop flags ; (cunning name)
jc error ; If there was an error, carry flag will have
jmp fin ; been set by Disk Interrupt
error: push ax ; AH has the status of the error
push cx ; Push all used registers for politeness
push dx
push di
push si
push es
lea si,msg_part_1 ; Always print "Disk Error: " part.
assume es:screen ; Use screen as extra segment
mov dx,screen
mov es,dx
mov di,screen_seg_offset ; DI will be pointer to screen position
add di,first_position ; Add to point to desired area on screen
call write_to_screen ; This writes 12 chars from [SI] to [DI]
mov dx,80h ; Initialize for later comparisons
mov cx,7 ; Loop seven times
e_loop: cmp ah,dh ; Are error code and DH the same?
je e_found ; If yes, Error has been found
add si,12 ; Point to next error message
shr dh,1 ; Divide DH by 2
loop e_loop ; Keep going until matched DH = 0
cmp ah,3 ; Error code no even number; 3 perhaps?
je e_found ; If yes, have found the error
add si,12 ; Err unknown; unknown error returned
e_found:call write_to_screen ; Write the error message to the screen
pop es ; Restore the registers
pop si
pop di
pop dx
pop cx
pop ax
fin: pop ret_addr_word ; Fooling with the stack. We want to
pop ret_addr_word[2] ; preserve the flags but the old flags
add sp,2 ; are still on the stack. First remove
push flags ; return address, then flags. Fill flags
popf ; from "FLAGS", return to correct addr.
jmp ret_addr
disk_watch endp
write_to_screen proc near ; Puts 12 characters on screen
mov cx,12 ; Loop 12 times
w_loop: movs es:byte ptr[di],cs:[si] ; Move to the screen
mov al,7 ; Move screen attribute into screen buffer
mov es:[di],al
inc di ; Point to next byte in screen buffer
loop w_loop ; Keep going until done
ret
write_to_screen endp
load_watch proc near ; This procedure initializes everything
assume ds:interrupts ; The data segment will be the interrupt area
mov ax,interrupts
mov ds,ax
mov ax,disk_int ; Get the old interrupt service routine
mov old_disk_int,ax ; address and put it into our location
mov ax,disk_int[2] ; OLD_DISK_INT so we can call it.
mov old_disk_int[2],ax
mov disk_int,offset disk_watch ; Now load the address of DskWatch
mov disk_int[2],cs ; routine into the disk interrupt
mov ah,15 ; Ask for service 15 of INT 10h
int 10h ; This tells us how display is set up
sub ah,25 ; Move to twenty five places before edge
shl ah,1 ; Mult. by two (char & attribute bytes)
mov byte ptr first_position,ah ; Set screen cursor
test al,4 ; Is it a monochrome display?
jnz exit ; Yes - jump out
mov screen_seg_offset,8000h ; No, set up for graphics display
exit: mov dx,offset load_watch ; Set up everything but this program to
int 27h ; stay and attach itself to DOS
load_watch endp
code_seg ends
end first ; END "FIRST" so 8088 will go to FIRST first.

@ -0,0 +1,130 @@
; Goes through drives A-Z and determines if they:
; 1) Exist
; 2) Are removable or fixed
; 3) Are local, remote, or shared
; 4) Are a floppy, hard, RAM, subst, or CD-ROM drive
;
; Callable from C as: void Drives_Exist(void);
.model small
.286
DRIVEEXIST EQU 1
REMOVEDRV EQU 0
FIXEDDRV EQU 1
LOCALDRV EQU 0
REMOTEDRV EQU 1
SHAREDRV EQU 2
FLOPPY EQU 0
HARD EQU 1
RAM EQU 2
SUBST EQU 3
CDROM EQU 4
.data
PUBLIC _drives
_drives db 26 dup(0,1,0,1)
; default to not exist, fixed, local, hard drive
.code
PUBLIC _Drives_Exist
_Drives_Exist PROC NEAR
pusha
push es
mov ah,19h
int 21h ; get start drive
push ax ; save start drive
mov ax,40h
mov es,ax
mov bh,es:[10h] ; 40:10h is # of floppies-1
shr bh,6
inc bh ; # of actual floppy drives
mov bl,1
mov di,offset _drives
nextchkfloppy: mov ax,4409h ; check if drive exists
int 21h
jc nextsetfloppy
test dh,10000000b ; check if SUBST drive
jz chkfloppy
dec bh ; dec actual drive count
mov byte ptr [di+3],SUBST
setfloppyexist: mov byte ptr [di],DRIVEEXIST
jmp nextsetfloppy
chkfloppy: dec bh ; dec actual drive count
js nextsetfloppy
mov byte ptr [di+1],REMOVEDRV
mov byte ptr [di+3],FLOPPY
jmp setfloppyexist
nextsetfloppy: add di,4
inc bl
cmp bl,2 ; if B then jump back
je nextchkfloppy
mov ch,24 ; loop 24 times (drives C - Z)
mov cl,3 ; start at C:
drivechkloop: mov ax,4409h ; check if drive exists
mov bl,cl ; set drive letter
int 21h ; 0 = default, 1 = A:, etc.
jc nextsetdrv
mov byte ptr [di],DRIVEEXIST
mov ax,4408h ; check if removable
int 21h
mov byte ptr [di+1],al ; set REMOVABLE or FIXED
mov bx,dx
mov dl,dh
shr dl,7
and dh,00010000b
shr dh,4
mov byte ptr [di+2],dh ; set REMOTE or LOCAL
or dl,dl ; if not SUBST, then jump
jz chkremote
mov byte ptr [di+3],SUBST
jmp nextsetdrv
chkremote: cmp dh,REMOTEDRV ; if REMOTE, then check for CD ROM
je chkcdrom
test bh,00000010b ; sharable?
jz drivenoshare
mov byte ptr [di+2],SHAREDRV
drivenoshare: test bl,00000010b ; RAM drive?
jnz nextsetdrv
mov byte ptr [di+3],RAM
jmp nextsetdrv
chkcdrom: push cx
mov ax,1500h
xor bx,bx
int 2fh
pop cx
or bx,bx ; MSCDEX driver found?
jz nextsetdrv ; if not, jump to next drive setup
mov ax,150bh
dec cl ; 0=A:, etc.
int 2fh
inc cl
or ax,ax
jz nextsetdrv ; drive supported by MSCDEX?
mov byte ptr [di+3],CDROM
nextsetdrv: add di,4
inc cl
dec ch
jnz drivechkloop
pop dx
mov ah,0eh
int 21h ; reset start drive
pop es
popa
ret
_Drives_Exist ENDP
END

@ -0,0 +1,161 @@
; Goes thru drives A-Z and determines if they:
; 1) Exist
; 2) Are removable or fixed
; 3) Are local, remote, or shared
; 4) Are a floppy, hard, RAM, subst, or CD-ROM drive
.model tiny
.286
DRIVEXISTS EQU 1
REMOVEDRV EQU 0
FIXEDDRV EQU 1
LOCALDRV EQU 0
REMOTEDRV EQU 1
SHAREDRV EQU 2
FLOPPY EQU 0
HARD EQU 1
RAM EQU 2
SUBST EQU 3
CDROM EQU 4
.code
org 100h
start: mov ah,19h
int 21h ; get start drive
mov [curdrive],al
mov ax,40h
mov es,ax
mov bh,es:[10h] ; 40:10h is # of floppies-1
shr bh,6
inc bh ; # of actual floppy drives
mov bl,1
mov di,offset drives
nextchkfloppy: mov ax,4409h ; check if drive exists
int 21h
jc nextsetfloppy
test dh,10000000b ; check if SUBST drive
jz chkfloppy
dec bh ; dec actual drive count
mov byte ptr [di+3],SUBST
setfloppyexist: mov byte ptr [di],DRIVEXISTS
jmp nextsetfloppy
chkfloppy: dec bh ; dec actual drive count
js nextsetfloppy
mov byte ptr [di+1],REMOVEDRV
mov byte ptr [di+3],FLOPPY
jmp setfloppyexist
nextsetfloppy: add di,4
inc bl
cmp bl,2 ; if B then jump back
je nextchkfloppy
mov ch,24 ; loop 24 times (drives C - Z)
mov cl,3 ; start at C:
drivechkloop: mov ax,4409h ; check if drive exists
mov bl,cl ; set drive letter
int 21h ; 0 = default, 1 = A:, etc.
jc nextsetdrv
mov byte ptr [di],DRIVEXISTS
mov ax,4408h ; check if removable
int 21h
mov byte ptr [di+1],al ; set REMOVABLE or FIXED
mov bx,dx
mov dl,dh
shr dl,7
and dh,00010000b
shr dh,4
mov byte ptr [di+2],dh ; set REMOTE or LOCAL
or dl,dl ; if not SUBST, then jump
jz chkremote
mov byte ptr [di+3],SUBST
jmp nextsetdrv
chkremote: cmp dh,REMOTEDRV ; if REMOTE, then check for CD ROM
je chkcdrom
test bh,00000010b ; sharable?
jz drivenoshare
mov byte ptr [di+2],SHAREDRV
drivenoshare: test bl,00000010b ; RAM drive?
jnz nextsetdrv
mov byte ptr [di+3],RAM
jmp nextsetdrv
chkcdrom: push cx
mov ax,1500h
xor bx,bx
int 2fh
pop cx
or bx,bx ; MSCDEX driver found?
jz nextsetdrv ; if not, jump to next drive setup
mov ax,150bh
dec cl ; 0=A:, etc.
int 2fh
inc cl
or ax,ax
jz nextsetdrv ; drive supported by MSCDEX?
mov byte ptr [di+3],CDROM
nextsetdrv: add di,4
inc cl
dec ch
jnz drivechkloop
mov ah,0eh
mov dl,[curdrive]
int 21h ; reset start drive
mov cl,'A' ; output all existing drives
mov di,offset drives
mov ah,9
drvdumploop: cmp byte ptr [di],DRIVEXISTS
jne nextdrvdump
mov al,cl
int 29h
xor dh,dh
mov dl,byte ptr [di+1]
shl dx,4
add dx,offset removablemsg
int 21h
xor dh,dh
mov dl,byte ptr [di+2]
shl dx,3
add dx,offset localmsg
int 21h
xor dh,dh
mov dl,byte ptr [di+3]
shl dx,3
add dx,offset typemsg
int 21h
mov dx,offset crlf
int 21h
nextdrvdump: add di,4
inc cl
cmp cl,'Z'
jbe drvdumploop
ret
curdrive db 0
drives db 26 dup(0,1,0,1)
; default to not exist, fixed, local, hard drive
crlf db 10,13,'$'
removablemsg db ': Removable $'
db ': Fixed $'
localmsg db 'Local $'
db 'Remote $'
db 'Shared $'
typemsg db 'Floppy $'
db 'Hard $'
db 'RAM $'
db 'Subst $'
db 'CD-ROM $'
end start

@ -0,0 +1,199 @@
; This version allows one BASIC program to call another
;
; CALL EXECSUB(PROG$,PARM$,FCB1$,FCB2$,RETCD%)
; PROG$ is the program name (e.g. 'command.com')
; PARM$ is the parameter to be passed to the program (e.g. '/c dir *.bas')
; FCB1$ is the first file control block (required by some programs)
; FCB2$ is the second file control block (required by some programs)
; RETCD% is the error return code
skip equ 2 ; 1 for interpretive, 2 for compiled
cseg segment para public 'code'
public execsub
execsub proc far
assume cs:cseg,ds:cseg,ss:nothing,es:nothing
basicds equ 510h
i24ip equ 90h
i24cs equ 92h
i1bip equ 6ch
i1bcs equ 6eh
i1cip equ 70h
i1ccs equ 72h
b24ip equ 51ah
b24cs equ 51ch
b1bip equ 516h
b1bcs equ 518h
b1cip equ 512h
b1ccs equ 514h
push bp
mov bp,sp
jmp p010
stak equ this byte
dw 0 ; save sp
dw 0 ; save ss
prm1 equ this byte
dw 0 ; environment
prm2 equ this word
dw 0 ; command line - ip & cs
dw 0
prm3 equ this byte
dw 0 ; default FCB - ip & cs
dw 0
prm4 equ this byte
dw 0 ; second default FCB - ip & cs
dw 0
p010:
xor ax,ax ; get psp
mov es,ax ; es=0
mov bx,ds ; save ds
mov ds,ax ; ds=0
cli
push ds:[basicds] ; save basic's ds
push ds:[i24ip] ; save int 24h and shadow
push ds:[b24ip]
push ds:[b24ip]
pop ds:[i24ip]
push ds:[i24cs]
push ds:[b24cs]
push ds:[b24cs]
pop ds:[i24cs]
push ds:[i1bip] ; save int 1bh and shadow
push ds:[b1bip]
push ds:[b1bip]
pop ds:[i1bip]
push ds:[i1bcs]
push ds:[b1bcs]
push ds:[b1bcs]
pop ds:[i1bcs]
push ds:[i1cip] ; save int 1ch and shadow
push ds:[b1cip]
push ds:[b1cip]
pop ds:[i1cip]
push ds:[i1ccs]
push ds:[b1ccs]
push ds:[b1ccs]
pop ds:[i1ccs]
sti
mov ds,bx ; restore ds
mov di,4f2h ; point to dos comm. area
mov ax,es:[di] ; get psp segment
mov es,ax
mov di,2
mov bx,es:[di] ; get top of memory
sub bx,ax ; subtract psp
mov ah,4ah
int 21h ; free memory
jnc p020 ; no error
mov ah,0 ; memory error
jmp p090 ; to error control
p020: mov si,[bp+12] ; point to parm$
add si,skip
mov ax,[si]
mov si,offset prm2 ; establish command line
mov cs:[si],ax
mov ax,ds
mov cs:[si+2],ax
mov si,[bp+10] ; point to fcb1$
add si,skip
mov ax,[si]
mov si,offset prm3
mov cs:[si],ax
mov ax,ds
mov cs:[si+2],ax
mov si,[bp+8] ; point to fcb2$
add si,skip
mov ax,[si]
mov si,offset prm4 ; establish second fcb
mov cs:[si],ax
mov ax,ds
mov cs:[si+2],ax
push bp ; save registers
push ds
push es
pushf
mov si,offset stak ; save stack
mov cs:[si],sp
mov cs:[si+2],ss
mov ah,4bh ; load prog
mov al,0 ; load & execute
mov si,[bp+14] ; point to prog$
add si,skip
mov dx,[si]
push cs
pop es
mov bx,offset prm1 ; point to parameter
int 21h ; load & execute program
jnc p050 ; no error
mov ah,1 ; set error code
jmp p060
p050: mov ax,0 ; clear error
p060: mov bx,cs ; restore stack
mov ds,bx
mov si,offset stak
cli ; no interrupts
mov sp,cs:[si]
mov ss,cs:[si+2]
sti ; allow interrupts
popf ; restore registers
pop es
pop ds
pop bp
mov cx,ds ; save ds
xor bx,bx
mov ds,bx ; ds=0
cli
pop ds:[b1ccs] ; restore int 1ch
pop ds:[i1ccs]
pop ds:[b1cip]
pop ds:[i1cip]
pop ds:[b1bcs] ; restore int 1bh
pop ds:[i1bcs]
pop ds:[b1bip]
pop ds:[i1bip]
pop ds:[b24cs] ; restore int 24h
pop ds:[i24cs]
pop ds:[b24ip]
pop ds:[i24ip]
pop ds:[basicds] ; restore basic's ds
sti
mov ds,cx
p090: mov si,[bp+6] ; point to RETCD%
mov [si],ax ; return error, if any
pop bp ; return to caller
ret 10
execsub endp
cseg ends
end

@ -0,0 +1,106 @@
; eject a tape (or CD) from a device
;
; note that this is a VERY terse code sample! It is assumed that the
; reader is already familiar with SCSI and ASPI to some degree.
;
.MODEL small
.STACK 1000h
.386
;* structures *
SCSIRequestBlock struc
CommandCode db 2 ; SCSI request
Status db 0 ; returned after command
HostAdapterNum db 0 ; default is 0 (first adapter)
SCSIReqFlags db 0 ;
Reserved1 db 4 dup (0) ;
TargetID db 0 ; set to device target ID
LUN db 0 ; defaults to 0
DataLength dd 0 ;
SenseLength db 16 ; usu. sufficient length
DataPointer dd 0 ; no data
SRBLinkPointer dd 0 ; no linking
CDBLength db 10 ; always sufficient length
AdapterStatus db 0 ;
TargetStatus db 0 ;
PostRoutinePtr dd 0 ; no post routine is default
ASPIWorkspace db 34 dup (0) ; req'd but not used
CDB db 10 dup (0) ; SCSI Command Descriptor Blk
SenseData db 16 dup (0) ;
SCSIRequestBlock ends
.DATA
DOS_OPEN_HANDLE = 03dh
DOS_CLOSE_HANDLE = 03eh
DOS_IOCTL = 044h
IOCTL_RX_CTL_DATA = 02h
DOS_INT = 21h
ASPI_Entry dd ?
SRB SCSIRequestBlock <>
crlf equ 13,10
ErrMsg db "ERROR: no ASPI manager detected. ",crlf,'$'
OKMsg db "All is well.",crlf,'$'
SCSIMgrString db "SCSIMGR$",0
.CODE
begin proc
.STARTUP
call GetASPIAddress ;
jnb @@AllOK ;
mov dx, OFFSET ErrMsg ;
jmp @@ErrorExit ;
@@AllOK:
;
; here's the eject sequence
;
mov [(SRB.CDB) + 0],01Bh ; load/unload command
mov [(SRB.CDB) + 4],0 ; 00 = unload, 01=load, 02=retension
mov [(SRB.TargetID)], 2 ; SCSI ID of target device
push SEG SRB ;
push OFFSET SRB ;
call [ASPI_Entry] ; sometimes it takes 2 requests
call [ASPI_Entry] ;
add sp,4 ;
mov dx,OFFSET OKMsg ;
xor ah,ah ;
mov al,[(SRB.Status)] ;
@@ErrorExit: ; ds:dx ==> ASCIIZ error string
push ax
mov ah,9 ;
int 21h ;
pop ax ;
@@NoError:
.EXIT 0
begin endp
GetASPIAddress proc C
push bx
push cx
push ds
xor ax,ax ;
mov WORD PTR [ASPI_Entry],ax ;
mov WORD PTR [ASPI_Entry+2],ax ;
lea dx,[SCSIMgrString] ;ds:dx ==> 'SCSIMGR' string
mov ah,DOS_OPEN_HANDLE ; open request
int DOS_INT ;
jb @@exit ;
mov dx,ss ;
mov ds,dx ;
lea dx,[ASPI_Entry] ;
mov cx,4 ;
mov bx,ax ;
mov ax,DOS_IOCTL SHL 8 OR IOCTL_RX_CTL_DATA
int DOS_INT ;
jb @@exit ;
mov ah,DOS_CLOSE_HANDLE ;
int DOS_INT ;
@@exit:
pop ds
pop cx
pop bx
ret ;
GetASPIAddress endp
END

@ -0,0 +1,162 @@
;
cr equ 0dh ;ASCII carriage return
lf equ 0ah ;ASCII line feed
;
cseg segment para public 'CODE'
;
assume cs:cseg,ds:data,ss:stack
;
demo proc far
;at entry DS & ES = PSP
push ds ;Save address for final
xor ax,ax ;FAR RET to PC-DOS on stack
push ax
;save copy of SS:SP for use
;after return from overlay
mov cs:STK_SEG,ss
mov cs:STK_PTR,sp
;
;Reserve 1000H bytes for
;this loader and release
;the rest of memory for
;use by the overlayed program.
mov bx,100h ;ES=segment of PSP of loader
mov ah,4ah ;BX=paragraphs to reserve
int 21h
;make the messages in data
;segment addressable
mov ax,seg DATA
mov ds,ax
mov es,ax
;jump if memory
;de-allocation failed
jc ALLOC_ERR
;print memory successfully
;released
mov dx,offset MSG2
mov ah,9
int 21h
;
;now load and execute
;the overlaid program.
mov dx,offset PGM_NAME
mov bx,offset PAR_BLK
mov al,0
mov ah,4bh
int 21h
;restore stack pointers
;to state before EXEC call
mov ss,cs:STK_SEG
mov sp,cs:STK_PTR
;Make data segment
;addressable again
mov ax,seg DATA
mov ds,ax
;print message that loader
;successfully regained control
mov dx,offset MSG3
mov ah,9
int 21h
;now exit to PC-DOS
ret
alloc_err: ;come here if memory
;cannot be released
mov dx,offset MSG1
mov ah,9
int 21h ;print error message and
ret ;exit to PC-DOS
;
demo endp
;
;these two variables must
;reside in Code Segment so
;that they are addressable
;after return from overlay.
stk_seg dw 0 ;original SS contents
stk_ptr dw 0 ;original SP contents
;
cseg ends
;declare a stack area
;for use by this loader
stack segment para stack 'STACK'
;allow 64 bytes in this case
db 64 dup (?)
stack ends
;declare data segment to
;contain variables and tables
data segment para public 'DATA'
;
msg1 db cr,lf
db 'Unable to release memory.'
db cr,lf,'$'
msg2 db cr,lf
db 'Memory above loader released.'
db cr,lf,'Now loading CHKDSK.COM.'
db cr,lf,'$'
msg3 db cr,lf
db 'Loader regained control from CHKDSK,'
db cr,lf
db 'now making final exit to PC-DOS.'
db cr,lf,'$'
;
;drive, path, and name of program
;to be loaded and executed.
pgm_name db '\CHKDSK.COM',0
;
par_blk dw ENVIR ;segment address of
;environment descriptor
;
;full address of command line
;to be passed at offset 80H
dw offset CMD_LINE ;in overlaid
dw seg CMD_LINE ;program's PSP
;
;full address of default
;File Control Block to be
;passed at offset 5CH in
dw offset FCB1 ;overlaid
dw seg FCB1 ;program's PSP
;
;full address of default
;File Control Block to be
;passed at offset 6CH in
dw offset FCB2 ;overlaid
dw seg FCB2 ;program's PSP
;
;actual command line tail
;to be passed to overlay
cmd_line db 4,' *.*',cr,0
;
;first default FCB to
fcb1 db 0 ;be passed to overlay
db 11 dup ('?')
db 25 dup (0)
;second default FCB to
fcb2 db 0 ;be passed to overlay
db 11 dup (' ')
db 25 dup (0)
;
data ends
;declare separate data
;segment to contain
;environment descriptor
envir segment para 'ENVIR'
;
;Search path used by PC-DOS
;to look for commands or
;batch files not found in
db 'PATH=',0 ;the current directory
;
;Search path used by PC-DOS
;to locate COMMAND.COM
db 'COMSPEC=A:\COMMAND.COM',0
db 0 ;extra 0 byte designates
;end of environment
envir ends
end demo

@ -0,0 +1,97 @@
TITLE "NetWare serial number routine"
; Net_SN.Asm
;
; I've tested this code with Netware 386 version 3.11,
; but it may also work with 2.15. It wasn't documented
; for 2.15, but it may still have existed.
;
.MODEL SMALL
.STACK 100h
.DATA
AAMn macro num
db 0d4h, num
endm
STDOUT = 1 ; handle for stdout
SNREQBUFF struc
MyLength DW 1 ; request structure length - 2
Function DB 12h ; function number of GetNetworkSerialNumber
SNREQBUFF ends
SNREPLYBUFF struc
MyLength DW 6 ; reply structure length - 2
NetSN DD 0 ; network serial number in big endian packed BCD
AppNumber DW 0 ; Application number in same format
SNREPLYBUFF ends
U_Request SNREQBUFF <>
U_Reply SNREPLYBUFF <>
SerialNum DB "00000000",0dh, 0ah
SerialLen = $ - SerialNum
.CODE
;
; Test code gets network serial number and prints it to stdout
;
Start:
mov ax,@data
mov ds,ax ; set up the data segment
call NetworkSN
Exit:
mov ah,04ch ; return with error code preset in AL
int 21h
;
; here's the Network stuff
;
NetworkSN proc
push ds
push si
push di
push es
push dx
push cx
lea si,[U_Request] ; prepare to request data
lea di,[U_Reply ] ; prepare to receive data
mov ax,ds
mov es,ax
mov ah,0e3h ; Get File Server Serial Number
int 21h
jc @@NoMore
lea si,[U_Reply.NetSN] ; point ds:si at binary data
lea di,[SerialNum] ; and point es:di at target ASCII string
mov cx,4 ; loop four times (once for each SN digit pair)
cld ; count up
@@convbyte:
lodsb ; read a byte
AAMn 16 ; convert to two-digit BCD in ah,al
xchg ah,al ; swap so that memory image will be correct
or ax,3030h ; convert both to ASCII numbers
stosw ; put 'em in our table
loop @@convbyte
lea dx,[SerialNum] ; we're going to point ds:dx to string
mov cx,SerialLen ; load the length of the string
mov bx,STDOUT ; print to STDOUT
mov ah,40h ; DOS function to print string
int 21h ; do it
mov al,0 ; return with appropriate error code
@@NoMore:
pop cx
pop dx
pop es
pop di
pop si
pop ds
ret
NetworkSN endp
END Start

@ -0,0 +1,37 @@
; GAMEPORT.ASM
;
.MODEL TINY
.DATA
yes DB 13,10,"Game port is installed.",13,10,"$"
no DB 13,10,"Game port is not installed.",13,10,"$"
.CODE
ORG 100h
start: mov al, 1 ;value to write to port
mov dx, 201h ;port number
out dx, al ;write to port
mov cx, 0F00h ;# of loops
port_loop:
in al, dx ;read from port
and al, 0Fh ;if jstick present, then AL should be
cmp al, 0Fh ; 0Fh after ANDing with 0Fh.
je jstick_exists
loop port_loop
mov dx, OFFSET no ;gameport not installed
jmp SHORT done
jstick_exists:
mov dx, OFFSET yes ;gameport installed
done: mov ah, 9h
int 21h
mov ax, 4c00h
int 21h
END start

@ -0,0 +1,74 @@
CSEG SEGMENT
PUBLIC GETSPACE
GETSPACE PROC FAR
ASSUME CS:CSEG
PUSH BP
MOV BP,SP
MOV BX,[BP]+6
MOV DI,[BX]+2
MOV CX,8
MOV AL,' '
CLD
REP STOSB
MOV BX,[BP]+8
MOV SI,[BX]+2
MOV AX,[SI]
AND AL,0DFH
CMP AL,41H
JGE CKVER
JMP EXITSPC
CKVER:
PUSH AX
MOV AH,30H
INT 21H
XCHG AL,AH
SPACE20:
POP DX
XOR DL,40H
MOV AH,36H
INT 21H
CMP AX,0FFFFH
JE EXITSPC
XOR DX,DX
MUL CX
XCHG BX,CX
MUL CX
PUSH AX
PUSH DX
ENDSPC:
MOV BX,[BP]+6
MOV DI,[BX]+2
ADD DI,7
POP DX
POP AX
HEXTODEC:
MOV SI,10
PUSH AX
MOV AX,DX
XOR DX,DX
DIV SI
POP CX
PUSH AX
MOV AX,CX
DIV SI
POP SI
OR DL,30H
MOV BYTE PTR [DI],DL
DEC DI
XCHG DX,SI
OR AX,AX
JNZ HEXTODEC
EXITSPC:
POP BP
RET 4
RET
GETSPACE ENDP
CSEG ENDS
END

@ -0,0 +1,79 @@
;
;
; Synopsis getseg(pcs, pds, pes, pss, psi, pdi, psp, pflag);
;
; unsigned *cs Pointer to where code segment address goes
; unsigned *ds Pointer to data segment
; unsigned *es Pointer to extra segment
; unsigned *ss Pointer to stack segment
; unsigned *si Pointer to si register
; unsigned *di Pointer to di register
; unsigned *sp Pointer to sp register
; unsigned *flag Returns flag
;
;
; Returns cs value of Code segment
; ds value of Data segment
; es value of Extra segment
; ss value of Stack segment
; si value of SI register ****NOT RELIABLE****
; di value of DI register
; sp value of Stack Pointer
; flag value of Flags register
;
;
;
pgroup group prog
prog segment byte public 'PROG' ; Combine with C 'PROG' program segment
assume cs:pgroup
public getseg
getseg proc near
push bp ; Save the frame pointer
mov bp,sp
mov si,[bp + 04] ; Get the values for the registers
mov ax,[si]
mov si,[bp + 06]
mov bx, [si]
mov si,[bp + 08]
mov cx, [si]
mov si,[bp + 10]
mov dx,[si]
;==============================================================================
mov ax, cs ;Get value of code segment
mov bx, ds ;data segment
mov cx, es ;extra segment
mov dx, ss ;stack segment
;==============================================================================
uret: mov bp,sp ; Now recover the values of the
mov si,[bp + 04] ; parameters
mov [si],ax
mov si, [bp + 06]
mov [si], bx
mov si, [bp + 08]
mov [si], cx
mov si, [bp + 10]
mov [si], dx
mov si, [bp + 12]
mov [si], si
mov si, [bp + 14]
mov [si], di
mov si, [bp + 16]
mov [si], sp
mov al, 00 ;zero out al
lahf ;load flag into ah
mov si, [bp + 18]
mov [si], ax
mov ax,0 ; No error
quit: pop bp ; Get the original frame pointer.
ret
getseg endp
prog ends
end

@ -0,0 +1,123 @@
; CALL FRESPACE(AH,AL,BH,BL,CH,CL). CL SHOULD BE 0 for default
; drive 1 for A, 2 for B, 3 for C, etc. The value of the
; other variables does not matter. They will come back
; with a meaningful value.
;
; AN EXAMPLE PROGRAM:
;
; 10 defint a-z
; 20 color 7,1:cls
; 30 test1=1:ah=0:al=0:bh=0:ch=0:cl=1:test2=2
; 35 INPUT"DRIVE 0=DEFAULT, 1=A, 2=B, 3=C";CL
; 37 PRINT"JUST BEFORE CALL"
; 40 CALL FRESPACE(AH,AL,BH,BL,CH,CL)
; 45 PRINT"JUST AFTER CALL"
; 50 PRINT" AH=";AH;" AL=";AL;" BH=";BH;" BL=";BL;" CH=";CH;" CL=";CL;
; 60 UFREE!=256*AH+AL
; 70 UBYTES!=256*BH+BL
; 80 USECTOR!=256*CH+CL
; 90 PRINT"UFREE!=";UFREE!;" UBYTES!=";UBYTES!;" USECTOR!=";USECTOR!
; 100 FRESPACE!=UFREE!*UBYTES!*USECTOR!
; 110 PRINT"FRESPACE!=";FRESPACE!
; 120 PRINT"THIS SHOULD BE 1",TEST1
; 130 PRINT"THIS SHOULD BE 2",TEST2
;
get_spa equ 36h ;Get disk free space function call
doscall equ 21h ;DOS interrupt number
dgroup group datarea
datarea segment para public 'DATA'
ah_ret dw ? ;ah to be sent back
al_ret dw ? ;al to be sent back
bh_ret dw ? ;bh to be sent back
bl_ret dw ? ;bl to be sent back
ch_ret dw ? ;ch to be sent back
cl_ret dw ? ;cl to be sent back
datarea ENDS
;
cseg segment 'CODE'
assume cs:cseg
public frespace
frespace proc far
push bp ;BP from BASIC
mov bp,sp ;set base for parm list
push ds ;DS from basic work area
push es ;ES from basic work area
mov ax,datarea ;establish data addressability
mov ds,ax ;now DS is local data
assume ds:datarea
;
;
;
;
push bp
sub ax,ax
mov si,ss:[bp+6] ;get addr of parameter
mov al,es:[si] ;get value of parm
mov dx,ax ;dl contains the drive number on call
;dh will be zero
mov ah,get_spa ;get space function number
int doscall ;Call DOS
; Move the values into local work area to prepare to send back to basic
xchg dx,ax ;must have a word. Want to zero out DH.
sub ax,ax ; produce the zero
xchg dx,ax ; DX is now zero.
; DH is what we really want as zero.
mov dl,ah ;want to send back a byte
mov ah_ret,dx ; prepare to return ah
mov dl,al ;want to send back a byte
mov al_ret,dx ; prepare to return al
mov dl,bh ;want to send back a byte
mov bh_ret,dx ; prepare to return bh
mov dl,bl ;want to send back a byte
mov bl_ret,dx ; prepare to return bl
mov dl,ch ;want to send back a byte
mov ch_ret,dx ; prepare to return ch
mov dl,cl ;want to send back a byte
mov cl_ret,dx ; prepare to return cl
; Go back
pop bp ;get back Basic's workspace
mov ax,cl_ret
mov si,ss:[bp+6]
mov es:[si],ax ;return cl
mov ax,ch_ret
mov si,ss:[bp+8]
mov es:[si],ax ;return ch
mov ax,bl_ret
mov si,ss:[bp+10]
mov es:[si],ax ;return bl
mov ax,bh_ret
mov si,ss:[bp+12]
mov es:[si],ax ;return bh
mov ax,al_ret
mov si,ss:[bp+14]
mov es:[si],ax ;return al
mov ax,ah_ret
mov si,ss:[bp+16]
mov es:[si],ax ;return ah
;
pop es
pop ds
pop bp
ret 12 ;return to basic 6 parameters were sent
frespace endp
;-----------------------------------------------------------------------
cseg ends
end ;end for assembler

@ -0,0 +1,162 @@
%PAGESIZE 55,200
%SUBTTL "Get List of Queue Servers under Netware 3.11"
; Net_Q.Asm
;
.MODEL SMALL
.STACK 100h
DOSint macro function
mov ah,function
int 21h
ENDM
.DATA
STDOUT = 1 ; the stdout device handle
DOS_WRITE_TO_HANDLE = 040h ; Write to File Handle
DOS_TERMINATE_EXE = 04Ch ; Terminate Program
NOVELL_FUNCTION = 0E3h
;
; Object Types
; note that they're all big endian
;
OT_USER = 0100h
OT_USER_GROUP = 0200h
OT_PRINT_QUEUE = 0300h ; Print Queue object type
OT_FILE_SERVER = 0400h
BragMsg DB 0dh,0ah,"NET_Q.EXE",9,"WWW"
DB 9,"Version 1.00",0dh,0ah
DB 9,9,"released to the public domain by the author",0dh,0ah,0dh,0ah
BragLen = $ - BragMsg
Crlf DB 0dh,0ah,0
SCAN_REQ STRUC ; bindery ScanObject request packet structure
MyLength DW 55 ; the length of this buffer
Function DB 37h ; scan object subfunction number
ObjectID DD -1 ; all ones for initial object search
ObjectType DW -1 ; wild card -- looks for all objects
ObjNameLen DB 1 ; at least one character
ObjName DB 47 DUP ('*') ; fill with wildcards to start
SCAN_REQ ENDS
SCAN_REP STRUC ; bindery ScanObject request packet structure
MyLength DW 57
RObjectID DD 0 ; all ones for initial object search
RObjectType DW 0 ; wild card -- looks for all objects
RObjName DB 48 DUP (0) ; fill with wildcards to start
ObjFlag DB 0
ObjSecurty DB 0
ObjHasProp DB 0
ENDS
ScanObjReq SCAN_REQ <>
ScanObjRep SCAN_REP <>
.CODE
;
; This is the main part of the code
;
; Test code gets and prints the name of all print queues from the
; logged server -- NO ERROR CHECKING IS DONE, so be careful!
;
Start:
mov ax,@data
mov ds,ax ; set up the data segment
mov dx,OFFSET BragMsg ; prepare to print out brag line(s)
mov cx,BragLen
mov bx,STDOUT ; print to STDOUT
DOSint DOS_WRITE_TO_HANDLE
jc Exit ; if carry is set, there was an error
mov [ScanObjReq.ObjectType],OT_PRINT_QUEUE
;
; in this case the name is already set up, (a wildcard) but if a
; specific name were desired, it would be moved to
; ScanObjReq.ObjName, with the appropriate length (not including
; optional terminating NULL char set up in ScanObjReq.ObjNameLen.
;
@@MoreQueues:
call BindScan
jc Exit
lea dx,[ScanObjRep.ObjName]
call Puts
lea dx,[Crlf]
call Puts
jmp @@MoreQueues
Exit:
DOSint DOS_TERMINATE_EXE ; return with error code preset in AL
;
; BindScan
;
; scans the bindery for the object name set in the request buffer
;
BindScan proc
push ds si di es dx ax
lea si,[ScanObjReq] ; point DS:DI to request buffer
mov dx,ds
mov es,dx
lea di,[ScanObjRep] ; point ES:SI to reply buffer
DOSint NOVELL_FUNCTION
jb @@Exit
cld ; make sure to count up
mov si,OFFSET ScanObjRep.ObjectID
mov di,OFFSET ScanObjReq.ObjectID
movsw
movsw
clc
@@Exit:
pop ax dx es di si ds
ret
BindScan endp
; Puts
;
; prints a NUL terminated string to stdout
;
; INPUTS: ds:dx points to ASCIIZ string
;
; OUTPUTS: prints string to stdout
;
; RETURNS: ax = number of bytes actually printed
; carry set on error
;
; DESTROYED: ax
;
Puts proc
push bx cx di es
push ds
pop es
mov cx,0ffffh ; maximum length of string
mov di,dx
cld
mov al,0 ; we're looking for NUL
repne scasb
dec di
mov cx,di
sub cx,dx
mov bx,STDOUT ; write to this device
DOSint DOS_WRITE_TO_HANDLE
pop es di cx bx
ret
Puts endp
END Start

@ -0,0 +1,44 @@
;
progseg segment para public 'CODE'
public setcom
assume cs:progseg, ds:progseg, es:progseg
org 100h
doscall equ 21h
oldint equ 16h
;
startup proc far
jmp setup
;
setcom proc far
; jmp cs:[interupt]
pushf
call cs:[interupt]
RET 2
setcom endp
;
save db 0
interupt label dword
vector db 8 dup(0) ;only 4 needed 4 more for safety
;
setup:
mov ah,35h ;get interupt vector address function
mov al,oldint ;keyboard interupt vector
int doscall ;go get it
;
mov word ptr vector,bx ;save offset
mov bx,es ;get segment address
mov word ptr vector+2,bx ;save segment
;
mov dx,offset setcom ;get new vector address
mov ax,cs
mov ds,ax ;set segment
mov ah,25h ;set interupt vector address function
mov al,oldint ;set to our new interupt vector
int doscall ;set the interupt
;
mov dx,offset setup ;terminate and stay resident
int 27h
startup endp
progseg ends
;
end startup

@ -0,0 +1,72 @@
; pentid.asm
;
; this program issues the CPUID instruction (valid only on Pentium class
; processors!) and prints three hex digits which correspond to the
; family, model, and stepping ID. If you run this on a 8088, 80386, or
; 80486 processor, it will return to the command line without printing
; anything. If you run this on an 80286, NEC V20 or NEC V30, your machine
; will probably crash. If you're smart enough to run this program only
; on Pentium machines, you can remove all the code between Start and
; RealTest and you'll reduce the code size from 84 to 49 bytes.
;
; TASM /m2 pentid ; two pass mode
; TLINK /Tdc pentid ; link as COM file
;
.MODEL tiny
.586 ; allow Pentium instructions
.CODE
ORG 100h
Start:
pushf ; assure this is a Pentium
pop ax ; flags in ax
rol ah,1 ; put EFLAGS reserved bit 15 in CF
sahf ; store in regular flags
jc BailOut ; if carry flag set, it's an 8088!
; assume we're 80386+ (80286 users prepare for crash)
pushfd ; push EFLAGS
pop eax ; now pull them into reg
mov ecx,eax ; save original copy in ECX
xor eax,00200000h ; flip bit 21 (CPUID capable)
push eax ; pass altered flags back on stack
popfd ; allow cpu to balk
pushfd ; see what it did with our flag
pop eax ; let's test...
cmp eax,ecx ; if bit can't be flipped it's
je BailOut ; not a Pentium processor
RealTest: ;
xor eax,eax ; clear eax
inc al ; put a 1 in eax
cpuid ; opcode is 0fh 0a2h
mov bx,ax ; save the lower 16 bits
call hex ; convert low nybble (step ID)
mov ah,'$' ; add terminator char
push ax ; put it on stack
mov ax,bx ; recall other bits
shr al,4 ; get 'em all lined up
call hex ; convert middle nybble (model)
xchg al,ah ; swap results
call hex ; convert third nybble (family)
push ax ; put that on stack, too
mov dx,sp ; print the stack (!)
mov ah,9h ; print string function
int 21h ; DOS interrupt
pop eax ; restore stack
mov al,bl ; recall original value
BailOut:
mov ah,4Ch ; terminate program with
int 21h ; model & stepping ID as errcode
;
; convert low nybble of al to ASCII char.
; al = {00h - 0Fh } becomes al = { '0'-'9', 'A'-'F' }
;
hex proc
and al,0Fh ; use only low nybble in al
cmp al,0Ah ; set CY flag appropriately
sbb al,69h ; al = al - 069h - (al > 10)
das ; al = 30h-39h or 41h-45h
ret ; pass back our result
hex endp
END Start

@ -0,0 +1,58 @@
subttl -
;;
;;FUNCTION: Sets and returns switch char-
;; acter and device availability.
;;
;;
;;CALL:
;;
;; ret= _charop(al,dl)
;; int ret; DL return value,
;; int al; charoper function
;; int dl; charoper data
;;
;;RETURN:
;; See the DOS docs for details.
;;_charop(0,0) returns the ASCII switch char,
;;_charop(1,'-') sets the switch to -,
;;_charop(2,0) returns device availability,
;;_charop(3,i) sets device availability.
;;
;;
;;DESCRIPTION:
;;
;;EXAMPLE:
;;
;;
;;CAUTIONS:
;;
;;
;;ASSUMPTIONS:
;;
;;LONG 32 bits (4 bytes)
;;INT 16 bits (2 bytes)
;;CHAR 8 bits (1 byte)
;;
page
pgroup group prog
prog segment byte public 'prog'
assume cs:pgroup,ds:pgroup
public _charop
_charop proc near
push bp
mov bp,sp
mov al,[bp+4]
mov dl,[bp+6]
mov ah,55
int 33
mov al,dl
mov ah,0
pop bp
ret
_charop endp
prog ends
end

@ -0,0 +1,294 @@
; teeny program displays the Mandelbrot set.
;
; Home Up PgUp
; Left Right correspond to 8 obvious directions
; End Dn PgDn
;
.model TINY
;JUMPS ; without this, see caveat under 8086 above
NONE = 00h ; use this for no features
PRINTZOOM = 01h ; printout and beep features
MODECHANGE = 02h ; support video mode change?
SPEED = 04h ; use 386 instructions for speed
STARTCOORDS = 08h ; use starting coordinates (instead of 0,0)
HIRES = 10h ; use hi resolution (single mode version only)
; choose the desired features from the feature list above, and OR them
; all together as shown below:
FEATURES = PRINTZOOM OR MODECHANGE OR STARTCOORDS OR SPEED OR HIRES
if (FEATURES AND SPEED)
.386
endif
ifdef (FEATURES AND HIRES)
VIDMODE = 12h ; use mode 12h
PIXWIDTH = 640 ; ... which is 640x480
PIXHEIGHT = 480
else
VIDMODE = 13h ; use mode 13h
PIXWIDTH = 320 ; ... which is 320x200
PIXHEIGHT = 200
endif
TEXTMODE = 3 ; our exit video mode (80x25 color text mode)
ZOOMLIMIT = 13 ; can change to up to 13 for extended zoom in
VIDEO_INT = 10h ; BIOS video services interrupt
WRITE_PIXEL = 0Ch ; write pixel video service
WRITE_CHAR = 0eh ; write char in TTY mode video service
CHANGE_MODE = 00h ; change mode video service
KEYBD_INT = 16h ; BIOS keyboard services interrupt
; ASCII codes
EXTENDED = 000h ; no ASCII code for extended key codes
BELL = 007h ; the ASCII bell char to make a beep
CR = 00dh ; a carriage return character
ESCAPE = 01bh ; the escape key
PLUS = 02bh ; ASCII code for '+' key
V_KEY = 'v' ; ASCII code for video mode switch
; keyboard scan codes
MINUS = 04ah ; scan code for gray '-' key
; feel free to experiment with the following constants:
DELTA = 100 ; the unit of pan movement in pixels
THRESHOLD = 4 ; must be in the range of (0,255)
STARTSCALE = 7 ; a number from 0 to ZOOMLIMIT, inclusive
STARTX =-DELTA ; to the right by 1 delta unit (STARTCOORDS feature)
STARTY =-DELTA ; down by 1 delta unit (STARTCOORDS feature)
CHAR_COLOR = 0fh ; white on black background (for PRINTZOOM feature)
.code
org 100h
;****************************************************************************
;
; Here's the main routine, and it's a bit convoluted.
;
;****************************************************************************
Start proc
ife (FEATURES AND MODECHANGE)
mov ax,VIDMODE
int VIDEO_INT
endif
if (FEATURES AND STARTCOORDS)
mov bp,STARTX
mov di,STARTY
else
xor bp,bp ; zero initial X offset
xor di,di ; initial Y offset is identical
endif
if (FEATURES AND MODECHANGE)
mov si,offset VidTbl; point to default video table
jmp @@ChgMode
video STRUC
ScrnMode dw ? ; the mode number for BIOS' purposes
ScrnWidth dw ? ; pixel width of screen minus one
ScrnHeight dw ? ; full height of screen in pixels
NextMode dw ? ; pointer to next video structure
video ENDS
VidTbl video <54h, 800-1, 600, ($ + 2)> ; highest res
video <13h, 320-1, 200, ($ + 2)> ; lowest res
video <12h, 640-1, 480, offset VidTbl> ; next to lowest res
else
jmp @@Render ; leap right in there and draw
endif
@@TryPlus:
cmp al,PLUS ; Q: gray + key?
mov al,[scale] ; get the scale factor in al now
jnz @@TryMinus ; N: maybe it's something else
dec al ; Y: it's plus so zoom out
js @@beep ; if AL<0, balk - can't zoom that far
sar bp,1 ; adjust offsets for new scale so
sar di,1 ; we stay in the same place
jmp @@AdjustScale
@@TryMinus:
cmp ah,MINUS ; Q: gray - key?
jnz @@ReadKey ; N: it's not a valid key
inc al ; Y: zoom in
cmp al,ZOOMLIMIT ; Q: have we zoomed too far?
ja @@beep ; Y: yes, so just beep and don't adjust
sal bp,1 ; adjust offsets for new scale so
sal di,1 ; we stay in the same place
@@AdjustScale:
mov [scale],al ; update the scale value
@@Render:
if (FEATURES AND PRINTZOOM)
mov al,'0'+ZOOMLIMIT; maximum printable character
sub al,[scale] ; invert the sense
call PrintChar ; show the character
mov al,CR ; print a carriage return (no line feed -
call PrintChar ; we don't want to advance to next line)
endif
;****************************************************************************
; Draw
; This routine is the fractal drawing engine. It has been
; optimized for size, sacrificing speed.
;
;****************************************************************************
if (FEATURES AND MODECHANGE)
mov cx,(video ptr [si]).ScrnHeight
push si ; we do this because it's very slow
; if we read the Width from memory
; every inner loop iteration
mov si,(video ptr [si]).ScrnWidth
else
mov cx, PIXHEIGHT ; height of screen in pixels
endif
sub di,cx ; adjust our Y offset
@@CalcRow:
push cx ; save the row pointer on the stack
if (FEATURES AND MODECHANGE)
mov cx,si ; fetch the screen width
else
mov cx, PIXWIDTH-1 ; width of screen in pixels
endif
sub bp,cx ;
@@CalcPixel:
push cx ; save the column counter on stack
xor cx, cx ; clear out color loop counter
xor bx, bx ; zero i coefficient
xor dx, dx ; zero j coefficient
@@CycleColors:
push dx ; save j value for later
mov ax, bx ; ax = i
sub ax, dx ; ax = i - j
add dx, bx ; dx = i + j
stc ; one additional shift, please
call Shifty ; ax = ((i+j)*(i-j)) shifted right
pop dx ; retrieve our saved value for j
add ax,bp ; account for base offset...
cmp ah,THRESHOLD ; Q: is i > THRESHOLD * 256?
xchg bx,ax ; now swap new i with old i
jg @@draw ; Y: draw this pixel
clc ; no additional shifts here, please
call Shifty ; now dx:ax = old i * j
xchg dx,ax ;
add dx,di ; account for base offset...
inc cl ; increment color
jnz @@CycleColors ; keep going until we're done
@@draw:
xchg ax, cx ; mov color into al
pop cx ; retrieve our column counter
pop dx ; fetch row (column already in cx)
push dx ; must leave a copy on the stack
xor bx,bx ; write to video page zero
mov ah,WRITE_PIXEL ; write pixel command
int VIDEO_INT ; video BIOS call
inc bp ; adjust our X base value
loop @@CalcPixel ; keep going until we've done a line
inc di ; adjust our Y base value
pop cx ; keep going until we've done 'em all
loop @@CalcRow ; more rows?
if (FEATURES AND MODECHANGE)
pop si ; restore vid ptr if we use one
endif
@@beep:
if (FEATURES AND PRINTZOOM)
mov al,BELL ;
call PrintChar ;
else
mov ax,((WRITE_CHAR SHL 8) OR BELL) ; make a beep
int VIDEO_INT ; (bx=0 -- any video page, any char attr)
endif
@@ReadKey:
xor ax,ax ; fetch a keystroke
int KEYBD_INT ; keyboard request
cmp al,ESCAPE ; Q: does the user want to exit?
jz @@exit ; Y: do so immediately
if (FEATURES AND MODECHANGE)
cmp al,V_KEY ; request for video mode change?
jnz @@TestExt ; if not, go on
@@ChgMode:
mov si,(video PTR [si]).NextMode ; change pointers
mov ax,(video PTR [si]).ScrnMode ; load new video mode
int VIDEO_INT ; change modes
jmp @@Render ; draw new screen
@@TestExt:
endif
cmp al,EXTENDED ; Q: is it an extended key code?
jnz @@TryPlus ; N: it's not so see if it's '+'
@@ArrowKey:
inc ah ; increment it to make indexing easier
add ah,ah ; multiply by two
mov bl,6 ; fix template (bh is already zero)
and bl,ah ; now bx contains address of delta
if (FEATURES AND MODECHANGE)
push si ; save video ptr if we're using one
endif
mov si,offset Deltas; fetch the delta value
add bp,[bx+si] ; add it to the X offset
shr ah,2 ; now look at the Y value of keystroke
mov bl,6 ; turn it into a table offset
and bl,ah ; do it now
sub di,[bx+si] ; and subtract from Y offset
if (FEATURES AND MODECHANGE)
pop si ; restore video ptr if we're using one
endif
jmp @@Render ; go draw this thing.
@@exit:
mov ax,TEXTMODE ; back to normal now
int VIDEO_INT ; change modes
ret ; and exit via old style
Start endp
Deltas dw +DELTA,0,-DELTA,0 ; handy table for calculating
; changes in X and Y offsets
;****************************************************************************
; Shifty
;
; This routine multiplies AX by DX and shifts the result (in
; DX:AX) to the right by scale bits (or scale+1 bits if CY is
; set). The resulting value is left in AX. DX is destroyed.
;
;****************************************************************************
Shifty proc near
push cx ; save middle bits (i*i - j*j)
db 0b1h ; code for mov cl,immed8
scale db STARTSCALE
adc cl,0 ; adjust per CY flag
imul dx ; do the multiply
if (@Cpu AND 8) ; is is a 386 or better?
xchg ax,dx ;
shl eax,16 ; put hi part in hi 16 bits
xchg ax,dx
shr eax,cl ;
else
@@Rotate:
rcr dx,1 ;
rcr ax,1 ;
loop @@Rotate ; ch is always zero so this is OK
endif
pop cx ;
ret ;
Shifty endp
if (FEATURES AND PRINTZOOM)
;****************************************************************************
; PrintChar
;
; This simple subroutine prints a single character (in AL) to the
; screen using a BIOS call. AH and BX are destroyed.
;
;****************************************************************************
PrintChar proc
mov ah,WRITE_CHAR ; write a character in TTY mode
mov bx,CHAR_COLOR AND 07fh ; use page 0 (bh), non-xor color (bl)
int VIDEO_INT ; do it up
ret
PrintChar endp
endif
end Start

@ -0,0 +1,150 @@
To use it just type, from the dos prompt:
MASM NOCAD; (of course you need MASM)
LINK NOCAD; (and of course you need a linker)
NOCAD
If you type NOCAD once it has been loaded, it will tell you so.
I've used it with DOS 3.30, but it works just as well under DOS
2.00 and above.
If you have any comment of any kind please let me know.
And have a nice new decade everybody.
cut here: ************************************************************
page 255,132 ;just to get a nice list file
comment :
Program to prevent CTRL+ALT+DEL from restarting the system
WARNING: Once loaded, you only have three choices:
1) Turn power off
2) Use a reset button (not all the machines have one)
3) Generate INT 19h
WARNING: If you have a program that uses INT 0CDh, change
this value in the equates line below to the number
of a not used INT. This method is used because
there are too many programs that hook INT 9 Vector and
we can't be sure it always points to the end of our
notice (and start of our ISR).
NOTE: For memory references i use parentheses instead of
square brackets because of ASCII-EBCDIC translations.
It works the same under Microsoft's MASM 4.0
NOTE: NOCAD won't work if you press CTRL+ALT+DEL from
a program that hooked to INT 9 before NOCAD
(example: SideKick). Solution: Load NOCAD before
everything else.
ctrl equ 0100b ;bit map for ctrl key
alt equ 1000b ;bit map for alt key
free_vector equ 0CDh ;vector used to prevent double loading
;change it if your system uses INT 0CDh
nocad segment byte 'CODE'
assume cs:nocad, ds:msgs, es:nothing, ss:stack
Copyright db 'Antonio Quezada-Duarte ITESM ISC 296641 Monterrey '
db 'Nuevo Leon MEXICO'
Cright_Len equ $-Offset Copyright
new_int_9h proc near
push ax
push ds ;save registers
xor ax,ax
mov ds,ax ;point DS to BIOS data area
;well, actually BIOS data area
;starts at 0040:0000, but
; XOR AX,AX is faster than MOV AX,40h
mov al,ds:(417h) ;get keyboard flags
and al,ctrl+alt ;clear non relevant bits
cmp al,ctrl+alt ;compare to our map
jne go_ahead ;NO CTRL+ALT keys pressed
and byte ptr ds:(417h),not alt ;CTRL+ALT pressed
;clear ALT key bit to simulate
;ALT key is not pressed
go_ahead:
pushf ;old ISR returns with IRET
COMMENT :
The Following code stands for
CALL OLD_INT_9
Where OLD_INT_9 is a FAR PROC
this is faster than having the address of OLD_INT_9
stored in memory and doing a
CALL CS:(OLD_INT_9)
:
DB 9Ah
OLD_INT_9_OFS DW 0
OLD_INT_9_SEG DW 0 ;call old INT 9 ISR
pop ds
pop ax ;restore registers
iret ;return to caller
new_int_9h endp
begin proc near
push es ;save psp base address
mov dx,seg msgs
mov ds,dx
mov dx,offset msg_0
mov ah,9
int 21h
mov ax,3500h + free_vector
int 21h
mov di,bx ;ES:DI ===> start of INT 0CDh ISR
mov si,offset copyright
mov ax,cs
mov ds,ax ;DS:SI ===> THIS code copyright notice
mov cx,cright_len
cld
repe cmpsb ;compare
je loaded ;if equal then already loaded
mov ax,2500h + free_vector
mov dx,cs
mov ds,dx
mov dx,offset copyright
int 21h ;point free_vector INT vector to
;our copyright notice
mov ax,3509h
int 21h ;get pointer to INT 9 ISR
mov cs:old_int_9_ofs,bx
mov cs:old_int_9_seg,es ;put it IN the new INT 9 ISR
mov ax,2509h
mov dx,offset new_int_9h
push cs
pop ds
int 21h ;point INT 9 vector to our ISR
mov dx,seg msgs
mov ds,dx
mov dx,offset msg_1
mov ah,9
int 21h ;print loaded msg
pop ds ;get saved psp base address
mov es,ds:(2Ch)
mov ah,49h
int 21h ;free environment's memory
;assume no error
mov dx,offset begin ;everything up to BEGIN
add dx,10Fh ;and all the bytes needed to
mov cl,4 ;make a full paragraph ...
shr dx,cl
mov ax,3100h ;... stay resident
int 21h ;and return exit code = 0
loaded: pop ax ;get psp address out of stack
;any register will do
mov dx,seg msgs
mov ds,dx ;point DS to our data area
mov dx,offset msg_2
mov ah,9
int 21h ;print already loaded msg
mov ax,4C01h
int 21h ;terminate with exit code = 1
begin endp
nocad ends
msgs segment word 'DATA'
msg_0 db 10,13,'NOCAD: Prevent CTRL+ALT+DEL from restarting the '
db 'system',10,13,'Author: Antonio Quezada-Duarte',10,13,'$'
msg_1 db 10,13,'NOCAD Loaded OK.',10,13,'$'
msg_2 db 10,13,'NOCAD Already Loaded.',10,13,'$'
msgs ends
stack segment para stack 'STACK'
dw 1024 dup (?)
stack ends
end begin

@ -0,0 +1,231 @@
name dev
page 60,132
title 'DEV --- Report installed device drivers'
; DEV --- a utility to report device header information for
; all installed device drivers
;
; Requires PC-DOS or MS-DOS 2.0.
;
; Used in the form:
; A>DEV
;
cr equ 0dh ;ASCII carriage return
lf equ 0ah ;ASCII line feed
blank equ 20h ;ASCII space code
eom equ '$' ;end of string marker
cseg segment para public 'CODE'
assume cs:cseg,ds:data,es:data,ss:stack
dev proc far ;entry point from PC-DOS
push ds ;save DS:0000 for final
xor ax,ax ;return to PC-DOS
push ax
mov ax,data ;make our data segment
mov ds,ax ;addressable via DS and ES.
mov es,ax
mov ah,30h ;check version of PC-DOS.
int 21h
cmp al,2
jae dev1 ;proceed, DOS 2.0 or greater.
mov dx,offset msg2 ;DOS 1.x --- print error message.
jmp dev6
dev1: mov cx,ax ;save DOS version number.
mov ah,15 ;now try and open the "NUL" device.
mov dx,offset nulfcb
int 21h
or al,al ;opened successfully?
jz dev2 ;yes, jump.
mov dx,offset msg1 ;no, print error msg and exit.
jmp dev6
dev2: ;Pick up double pointer to device
;driver chain out of reserved
;area in fcb. This area is mapped
;differently in DOS 2.x and DOS 3.x.
cmp cl,2 ;is this DOS 2.x?
ja dev3 ;no, jump.
mov bx,word ptr nulfcb+25
mov es,word ptr nulfcb+27
jmp dev4
dev3: ;come here if DOS 3.0 or greater.
mov bx,word ptr nulfcb+26
mov es,word ptr nulfcb+28
dev4: call header ;print sign-on message and
;column headings.
dev5: ;trace through the device chain
call prdev ;print device header information
;for driver pointed to by ES:BX.
;pick up addr of next header.
les bx,dword ptr es:[bx]
cmp bx,-1 ;found last one yet?
jne dev5 ;no, try next.
mov dx,offset msg3 ;yes, print "end of device chain".
dev6: mov ah,9 ;print the string whose address
int 21h ;is in DX.
ret ;then return to DOS.
dev endp
header proc near ;print out headings for device
mov dx,offset hdr ;driver information.
mov ah,9
int 21h
ret
header endp
prdev proc near ;print out device driver info.
;ES:BX is pointer to device header,
;which must be preserved.
mov ax,es ;convert segment of device header
mov di,offset inf1
call hexasc
mov ax,bx ;convert offset of device header.
mov di,offset inf2
call hexasc
mov ax,es:[bx+4] ;get attribute word, save a
push ax ;copy of it, then convert it.
mov di,offset inf3
call hexasc
mov ax,es:[bx+6] ;convert ptr to device strategy.
mov di,offset inf4
call hexasc
mov ax,es:[bx+8] ;convert ptr to device int handler.
mov di,offset inf5
call hexasc
;if not char device, clear out name
;field and set number of units.
pop ax ;get back attribute word.
test ax,08000h ;is bit 15 = 1 ?
jnz prdev7 ;yes, it's character dev, jump.
;no, it's block device.
;set flag to skip device name.
mov byte ptr inf8,eom
mov al,es:[bx+10] ;pick up number of units.
aam ;convert to ASCII decimal and
add ax,'00' ;store into output string.
mov byte ptr inf7+1,al
mov byte ptr inf7,ah
;set type = B for Block
mov byte ptr inf6,'B'
jmp prdev9
prdev7: ;if char device, move its 8-character
;name into the output string.
xor si,si
prdev8: mov al,es:[si+bx+10]
mov [si+inf8],al
inc si
cmp si,8
jne prdev8
;remove # of units field.
mov word ptr inf7,' '
;set type = C for Character.
mov byte ptr inf6,'C'
prdev9: mov dx,offset inf ;now print device information
mov ah,9 ;and exit.
int 21h
ret
prdev endp
hexasc proc near ;convert binary word to hex ASCII.
;call with AX=binary value
; DI=addr to store string
;returns AX, CX, DI destroyed.
push ax ;save copy of 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.
hexasc endp
btoa proc near ;convert binary 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 equivalent
mov [di],al ;store into output string.
mov al,ah ;get back lower nibble.
and al,0fh
call ascii ;convert 4 bits to ASCII
mov [di+1],al ;and store into output string.
ret ;back to caller.
btoa endp
ascii proc near ;convert 4 lower bits of AL
add al,'0' ;into the equivalent ASCII char.
cmp al,'9' ;in the range {0...9,A...F}
jle ascii2 ;and return char. in AL.
add al,'A'-'9'-1 ;"fudge factor" for range A-F.
ascii2: ret ;return to caller.
ascii endp
cseg ends
data segment para public 'DATA'
msg1 db cr,lf
db 'Failed to open NUL device.'
db cr,lf,eom
msg2 db cr,lf
db 'Requires DOS version 2 or greater.'
db cr,lf,eom
msg3 db cr,lf
db 'End of device chain.'
db cr,lf,eom
hdr db cr,lf
db 'Addr Attr '
db 'Str Int Type Units Name '
db eom
inf db cr,lf
inf1 db 'XXXX:' ;seg device header
inf2 db 'XXXX ' ;offs device header
inf3 db 'XXXX ' ;attribute
inf4 db 'XXXX ' ;strategy
inf5 db 'XXXX ' ;interrupt handler
inf6 db 'X ' ;type (block or char)
inf7 db 'XX ' ;units (if block device)
inf8 db ' ' ;name (if char device)
db eom
;fcb to open NUL device
nulfcb db 0 ;drive
db 'NUL' ;name of NUL device
db 8 dup (' ')
db 25 dup (0)
data ends
stack segment para stack 'STACK'
db 64 dup (?)
stack ends
end dev

@ -0,0 +1,96 @@
;
; Functions:
; al=0 then Disable communications interupt vector
; al=1 then Enable communications interupt vector
; Issue and int 44h
;
progseg segment para public 'CODE'
public setcom
assume cs:progseg, ds:progseg, es:progseg
org 100h
doscall equ 21h
;
startup proc far
jmp setup
;
setcom proc far
push ds
push es
push dx
push ax
mov ax,cs
mov ds,ax
mov es,ax
pop ax
cmp al,1 ;is function 1
jz enable ;then enable
;
disable:
mov dx,offset interupt ;get new vector address
mov ax,cs
mov ds,ax ;set segment
mov ah,25h ;set interupt vector address function
mov al,14h ;communications interupt vector
int doscall ;set the interupt
jmp exit ;exit
enable:
mov dx,word ptr vector ;set old segment
mov ds,vector+2 ;set old communications vector
mov ah,25h ;set interupt vector address function
mov al,14h ;communications interupt vector
int doscall
exit:
pop dx
pop es
pop ds
;
interupt proc far
sub ax,ax ;zero return status
iret
interupt endp
setcom endp
;
msg db 'Serial communications intercepter installed',0ah,0dh,'$'
msg1 db 'Serial communications intercepter is already installed',0ah,0dh,'$'
vector db 8 dup(0) ;only 4 needed 4 more for safety
;
setup:
mov ah,35h ;get interupt vector address function
mov al,44h ;communications interupt vector
int doscall ;go get it
cmp bx,0 ;check if vector used
jnz lderr ;if used then exit
mov ax,es ;check segment
cmp ax,0
jnz lderr
;
mov dx,offset msg
mov ah,9
int doscall
;
mov ah,35h ;get interupt vector address function
mov al,14h ;communications interupt vector
int doscall ;go get it
;
mov word ptr vector,bx ;save offset
mov bx,es ;get segment address
mov word ptr vector+2,bx ;save segment
;
mov dx,offset setcom ;get new vector address
mov ax,cs
mov ds,ax ;set segment
mov ah,25h ;set interupt vector address function
mov al,44h ;set to our new interupt vector
int doscall ;set the interupt
;
mov dx,offset setup ;terminate and stay resident
int 27h
lderr:
mov dx,offset msg1
mov ah,9
int doscall
int 20h
startup endp
progseg ends
;
end startup

@ -0,0 +1,96 @@
; flatmode.asm
;
; This program demonstrates flat real mode, which is simply real mode
; with 4G descriptors for some segments. In this code it's done by
; going into protected mode, setting the FS register to a descriptor
; with 4G limits and then returning to real mode. The protected mode
; limit stays in effect, giving "flat real mode."
;
; The demonstration part of this code writes the first 160 bytes from
; the system ROM at F0000h (linear) to the color screen which is assumed
; to be at B8000h (linear) using a flat real mode selector. Since that
; range of the system ROM typically contains a copyright notice, one
; can easily see that the code is truly working as advertised.
;
; This code is intended to be run on a Pentium or better.
;
; To assemble:
;
; using Microsoft's MASM 6.11 or better
; ml /Fl flatmode.asm
;
;----------------------------------------------------------------------
.model tiny
.code
.586P
DESC386 STRUC
limlo dw ?
baselo dw ?
basemid db ?
dpltype db ? ; p(1) dpl(2) s(1) type(4)
limhi db ? ; g(1) d/b(1) 0(1) avl(1) lim(4)
basehi db ?
DESC386 ENDS
;----------------------------------------------------------------------
ORG 100h
start:
call flatmode ; go into flat real mode (fs reg only)
; mov dx,5 ;
; mov fs,dx ;
call fillscreen ; fill the screen using 4G descriptor
mov ax,4c00h ; do a standard DOS exit
int 21h ;
;----------------------------------------------------------------------
fillscreen proc
mov esi,0F0050h ; point to ROM
ifdef BEROSET
mov edi,0B8000h ; point to screen
else
mov di,0b800h ;
mov es,di ;
xor edi,edi ;
endif
mov cx,160 ; just two lines
mov ah,1Eh ; yellow on blue screen attrib
myloop:
mov al,fs:[esi] ; read ROM byte
ifdef BEROSET
mov fs:[edi],ax ; store to screen with attribute
else
mov es:[di],ax ; store to screen with attribute
endif
inc esi ; increment source ptr
inc edi ; increment dest ptr by two
inc edi ;
loop myloop ; keep going
ret ; and quit
fillscreen endp
;----------------------------------------------------------------------
flatmode proc
; first, calculate the linear address of GDT
xor edx,edx ; clear edx
xor eax,eax ; clear edx
mov dx,ds ; get the data segment
shl edx,4 ; shift it over a bit
add dword ptr [gdt+2],edx ; store as GDT linear base addr
; now load the GDT into the GDTR
lgdt fword ptr gdt ; load GDT base (286-style 24-bit load)
mov bx,1 * size DESC386 ; point to first descriptor
mov eax,cr0 ; prepare to enter protected mode
or al,1 ; flip the PE bit
cli ; turn off interrupts
mov cr0,eax ; we're now in protected mode
mov fs,bx ; load the FS segment register
and al,0FEh ; clear the PE bit again
mov cr0,eax ; back to real mode
sti ; resume handling interrupts
ret ;
flatmode endp
;----------------------------------------------------------------------
GDT DESC386 <GDT_END - GDT - 1, GDT, 0, 0, 0, 0> ; the GDT itself
DESC386 <0ffffh, 0, 0, 091h, 0cfh, 0> ; 4G data segment
GDT_END:
end start

@ -0,0 +1,283 @@
kbd equ 16h ;keyboard irq
msdos equ 21h ;MSDOS irq
reset equ 0dh ;disk reset
dfopen equ 0fh ;open disk file
dfclose equ 10h ;close disk file
searchf equ 11h ;search first
searchn equ 12h ;search next
seqread equ 14h ;sequential disk read
seqwrite equ 15h ; " " write
setdta equ 1ah ;set disk transfer area address
createf equ 3ch ;create file with handle
openf equ 3dh ;open file with handle
closef equ 3eh ;close file with handle
readf equ 3fh ;read from file with handle
writef equ 40h ;write to file with handle
setfp equ 42h ;set file pointer
allocmem equ 48h ;allocate memory
freemem equ 49h ;free memory
changebs equ 4ah ;change block size
findfirst equ 4eh ;find first file
exit equ 4c00h ;msdos exit
[BITS 16] ;NASM stuff
[ORG 0x100]
s1:
mov ax,cs ;get code segment
mov ds,ax ;use it now
mov [comseg],ds ;save it there
mov si,0080h ;DOS command line page 0
lodsb ;load size of command line
cmp al,0 ;anything on command line ?
jbe usage ;noo, show usage
cbw ;extend AL to AX
xchg bx,ax ;swap size to bx for indexing
mov byte [bx+si],0 ;null terminate command line
call parse ;parse command line
jmp main ;go on with main
usage: mov bx,utext ;pointer usage text
jmp errout ;skip this
main:
mov si,inbuff ;check for valid HEX input
mov bx,errt1 ;proper text
ishex: lodsb ;get the char
cmp al,'0'
jb errout
and al,0dfh ;force UPPERCASE
cmp al,'F' ;>F ?
ja errout ;yeahh, dump this
loop ishex
call hexbin ;make hex bin
;start address now in EDX
mov ax,dx ;get low word (segment)
mov es,ax ;start segment
shr edx,16 ;shift in offset
mov di,dx ;start offset
dopage:
push es ;save registers
push di
push ds
push si
mov ax,es
mov ds,ax ;make ds=es
mov si,di ;and si=di
call showpage ;show it
pop si ;restore registers
pop ds
pop di
pop es
add di,512 ;adjust memory position
;xor ah,ah ;wait for ANY key
;int kbd
mov bx,text ;show message
call write
mov ah,0 ;wanna see next screen ?
int kbd ;chek out keyboard buffer
and al,0DFh ;force UPPER CASE
cmp al,"Q" ;wanna quit ?
je quit ;yeahh
jmp dopage
errout:
call write
quit:
mov ax,exit
int msdos
;***********************************************************
;* Convert ascii hex to 32 bit binary
;* Input = command line buffer, output EDX
;***********************************************************
hexbin:
mov si,inbuff ;pointer command line buffer
xor edx,edx ;clear binary output
aschexbin:
lodsb
cmp al,'0' ;< 0
jb notasc ;yes invalid character
cmp al,'9' ;<= 9
jbe astrip ;yes, strip high 4 bits
and al,05fh ;force upper case
cmp al,'A' ;< ascii A
jb notasc ;yes, invalid character
cmp al,'F' ;> ascii F
ja notasc ;yes, invalid character
add al,9 ;ok, add 9 for strip
astrip:
and al,0fh ;strip high 4 bits
mov cx,4 ;set shift count
shl edx,cl ;rotate EDX 4 bits
xor ah,ah ;zero out AH
cbw
add edx,eax ;add digit to value
jmp aschexbin ;continue
notasc: ret
;*********************************************************************
;* Format and show the stuff in a "sector"
;* Input SI
;*********************************************************************
showpage:
mov cx,32 ;32*16=512
arow: push cx
mov di,outline ;output buffer
mov cx,16 ;process 16 bytes
hexrow: push cx
lodsb ;load al with byte
mov dl,al ;get value
mov cx,2 ;2 nibbles
chexb: push cx ;save that
mov cl,4 ;4 bits
rol dl,cl ;rotate source left
mov al,dl ;move digit into AL
and al,15 ;clear high nibble
daa ;adjust AL if A through F
add al,240 ;bump the carry
adc al,40h ;convert HEX to ASCII
stosb ;copy to buffer
pop cx ;get digit counter
loop chexb ;next digit
mov al,32 ;copy a SPACE
stosb
pop cx ;restore loop counter
loop hexrow ;loop on
mov al,32 ;copy 2 spaces
stosb
stosb
sub si,16 ;adjust source back
mov cx,16 ;copy ASCII bytes
cccp: lodsb
cmp al,32 ;< SPACE ?
jb noa ;yeahh, skip it
stosb ;no, store in buffer
jmp next
noa: mov al,'.'
stosb
next loop cccp
mov al,13
stosb
mov al,10
stosb
mov al,0 ;null terminate line
stosb
mov bx,outline ;show the line
call write
pop cx
cmp cx,17
jne nopause
push ds
mov ax,cs
mov ds,ax
mov bx,text1
call write
pop ds
xor ah,ah
int kbd
nopause:
loop arow ;next 16 bytes
ret
;************************************************************************'
;* Convert bin WORD to HEX ascii. Input DX. Result in Numbuff *
;************************************************************************
binhex: pusha
mov di,numbuff ;destination buffer
mov dx,[count] ;binary number
mov cx,4 ;four nibbles
convhex:
push cx ;save counter
mov cl, 4 ;4 bits
rol dx, cl ;rotate source left
mov al, dl ;move digit into AL
and al, 15 ;clear high nibble
daa ;adjust AL if A through F
add al, 240 ;bump the carry
adc al, 40h ;convert HEX to ASCII
stosb ;copy to buffer
pop cx ;get digit counter
loop convhex ;next digit
mov al,32 ;copy a space
stosb
mov al,0 ;null terminate
stosb
popa
ret
;*************************************************************************
;* Writes out the NULL terminated text supplied in BX. *
;* OR writes out data,BX and size,CX if called at lwrite. *
;*************************************************************************
write: pusha
mov si,bx ;copy to SI
mov cx,0 ;clear count
wloop: lodsb ;load AL with SI
cmp al,0 ;end of line ?
je lwrite ;yeahh
inc cx ;no, incrase byte count
jmp wloop ;test next byte
lwrite: mov dx,bx ;text address in DX
mov bx,1 ;filehandle standard output = 1
mov ah,writef ;MS-DOS writefile with handle is 040
int msdos ;write buffer to standard output
popa
ret ;done
;*************************************************************************
;* My kind of command line parsing. It just checks if there<72>s
;* any blankspaces between the options. The parameters ends up
;* in the inbuff separated by 0:s, binary zeroes.
;*************************************************************************
parse:
mov di,inbuff ;our buffer
ifspc: cmp byte [si],32 ;leading space ?
jne nospc ;noo
inc si ;yeahh, dump that
jmp ifspc ;check next
nospc: mov cx,1 ;were here, so we got one arg
copy1: lodsb ;load byte SI to AL
cmp al,0 ;0 ?(end of line)
je done ;yeahh
cmp al,32 ;SPACE ?
je cop2 ;yeah
stosb ;noo, move AL to DI, incrase DI
jmp copy1 ;go on
cop2: mov byte [di],0 ;null terminate
add cx,1
inc di ;dump that byte(SPACE)
jmp copy1 ;back
done: mov byte [di],0 ;null terminate
ret ;return
;*************************** DATA STUFF **********************************
XMS_SEGMENT dw 0
XMS_OFFSET dw 0
inbuff times 64 dw 0 ;128 byte command line buffer
outline times 40 dw 0 ;buffer output line
numbuff times 7 dw 0 ;word ascii number buffer
comseg dw 0
count dw 0
bcount dw 0
acount dw 0
;outbuff times 512 db 0
utext db 'WWW',13,10
db 'Usage: Showmem [start address].',13,10
db 'Start address = Hexadecimal.',13,10,0
text: db 13,10,'Q = Quit. Any key = Next page.',13,10,0
text1: db 13,10,'Any Key = Next 256 Bytes.',13,10,0
errt1: db 'That address is not hexadecimal.',13,10,0
s2:
END

@ -0,0 +1,188 @@
%SUBTTL "Scroll Window Left routine with sample driver"
;
; Scroll2.Asm
;
; see ScrollLeft description for complete explanation of this program
;
MODEL small
IDEAL
STACK 200h ; this is more than enough stack
CODESEG
start:
;
; this test stub scrolls the window at (4,3)-(22,68) left 9 columns,
; filling in with spaces of attribute white on black (07)
;
mov al,9 ; number of columns to scroll
mov bh,07 ; attribute to use for blanked chars
mov ch,4 ; row of upper left hand corner of window
mov cl,3 ; col of upper left hand corner of window
mov dh,22 ; row of lower right hand corner of window
mov dl,68 ; col of lower right hand corner of window
call ScrollLeft
mov ah,4ch ; exit with errorlevel from scroll routine
int 21h
;
; ScrollLeft
;
; PURPOSE: scrolls a rectangular region of a text screen (window) to the
; left by a variable number of columns
;
;
; INPUTS: AL = number of columns to scroll (if zero, no effect)
; BH = attribute to use for blanked characters
; CH,CL = row, col for upper left hand corner of window
; DH,DL = row, col for lower right hand corner of window
;
; NOTES: upper left hand corner of screen (home) is (0,0)
; video adapter is checked to see if it's in text mode
; screen dimensions are taken from BIOS data
; calling sequence is nearly identical to BIOS scroll routine
; display pages supported
; dual monitors supported
; MDA/CGA/EGA/VGA supported
;
; RETURNS: On error, Carry flag set, AX contains error number
; otherwise carry is clear, AX contains 0
;
; Error codes: 0 - no error
; -1 - some error occurred
;
PROC ScrollLeft
ScrRows equ 0484h ; location of BIOS rows data
ScrCols equ 044ah ; location of BIOS cols data
ScrMode equ 0449h ; location of BIOS mode data
ScrOffs equ 044eh ; location of BIOS scrn offset data
; first, save all of the registers we're going to trash
push bx
push cx
push dx
push si
push di
push bp
push es
push ds
mov bl,al ; stow cols in BL
xor ax,ax
mov ds,ax ; point data seg to 0000 to read BIOS data
cmp ch,dh ; srow > erow ?
ja @@badcoords
cmp cl,dl ; scol > ecol ?
ja @@badcoords
;
; now we need to load ScrRows, if we haven't got EGA or better
;
mov al,[ScrRows] ; is MAXROWS = 0 ?
cmp al,0 ; if so, then assume we've got MDA or CGA
jne @@ega_plus ; if not, we've got correct value already
mov al,24 ; otherwise, assume 25 rows (and load 25-1)
@@ega_plus:
cmp dh,al ; erow >= MAXROWS?
;
; note that BIOS actually stores MAXROWS-1 in this location, so the
; actual jump instruction is (correctly) written as ja
;
ja @@badcoords
cmp dl,[ScrCols] ; ecol >= MAXCOLS?
jae @@badcoords
mov ah,bl ; remember cols
add ah,cl ; cols + scol
cmp ah,dl ; (cols + scol) > ecol ?
ja @@badcoords
; figure out where the video buffer starts
mov bp,0b800h ; first guess
mov al,[ScrMode] ; get mode from BIOS' RAM
cmp al,4 ; if mode is 0 through 3, we're all set
jb @@modeOK
mov bp,0b000h ; second guess
cmp al,7 ; is it mode 7 (monochrome 80 col) ?
je @@modeOK ; if so, we're still OK
@@badcoords:
mov ax,-1 ; set error code
stc ; and set error (carry) flag
jmp @@exit
@@modeOK:
mov es,bp ; set up our video pointer segment
; ES:DI = endloc = Screen + 2 * (MAXCOLS * srow + scol)
mov di,[ScrOffs] ; offset of screen buffer
xor ah,ah ; clear out high half of AX
mov al,[ScrCols] ; get the width of the screen
mul ch ; multiply width by the row number
add al,cl ; now add the column number
adc ah,0 ; propagate carry bit to other half of AX
shl ax,1 ; now multiply by 2 bytes/char
add di,ax ; add the offset to the screen start address
; DS:DI = startloc = endloc + 2 * cols
xor ah,ah ; clear top half of ax
mov al,bl ; recall cols
mov si,di ; start address = end address
add si,ax ; add cols
add si,ax ; and again
; start on count calculation (figure ecol-scol+1)
sub dl,cl ; ecol - scol
inc dl ; now dl = ecol - scol + 1
; calculate increment and stow in BP
; increment = (MAXCOLS - (ecol - scol + 1)) * 2
xor ah,ah ; clear top half of ax
mov al,dl ; use partial count calculation
neg ax
add al,[ScrCols] ; now add in screen width
adc ah,0 ; propagate carry bit to hi half of AX
shl ax,1 ; now double it (2 bytes/char)
mov bp,ax
; finish count calculations and put in DL
; count = (ecol - scol + 1) - cols
sub dl,bl ; figure in cols
mov ax,es ; recall our video pointer
mov ds,ax ; now duplicate it
; load up AX with char and attribute for blank space
mov al,32 ; ASCII space character
mov ah,bh ; passed attribute byte
sub dh,ch ; get row count
mov dh,bh ; save loop count (rows to move) in bh
xor ch,ch ; zero out hi half of CX
cld ; assure that we move the right direction (up)
@@looptop:
mov cl,dl ; load in count (words to move)
rep movsw ; move the line over
mov cl,bl ; recall cols (blanks to insert)
rep stosw ; fill in the rest of the line
add di,bp ; advance to next line by adding increment
mov si,di ; now set up the other (source) pointer
mov cl,bl ; recall cols
add si,cx ; add in cols
add si,cx ; and again (because 2 bytes/char)
dec bh ; decrement loop counter
ja @@looptop ; skip back if we're not done yet
mov ax,0 ; set error code to zero (all OK)
clc ; and clear error (carry) flag
@@exit:
pop ds ; restore all of our registers
pop es
pop bp
pop di
pop si
pop dx
pop cx
pop bx
ret ; mosey on home again
ENDP ScrollLeft
END start
-+------- cut here -----------

@ -0,0 +1,154 @@
comment ^
Sample code to show how one might detect video cards by
using search strings.
^
.model small
.stack 400h
.data
;/***************************************************************************
; some handy equates
;***************************************************************************/
VID_BIOS_SEG equ 0c000h ; the video BIOS segment
SEARCH_AREA equ 0400h ; when we look for the video BIOS
; ID, we only seach this many bytes
CMP_LENGTH equ 7 ; the number of "significant"
; characters to compare in each
; string
DOS_INT equ 21h ; DOS' interrupt
VIDEO_INT equ 10h ; BIOS' video services int
VID_80x25 equ 03h ; 80x25 text mode number
;/***************************************************************************
; data
;***************************************************************************/
UnknownCardMsg db 'Your video card is not supported.',13,10,'$'
mode1 db 053h ; 640 x 480 x 256 mode for Oak
card1 db 'OAK VGA','$'
mode2 db 05dh ; 640 x 480 x 256 mode for Trident
card2 db 'TRIDENT','$'
cards dw card1, card2, 0
;/***************************************************************************
; some handy macros
;***************************************************************************/
@DosPrint MACRO msgptr
mov dx,msgptr ; handy macro for printing
mov ah,9 ; '$' terminated strings
int DOS_INT ; under DOS
ENDM
@SetVidMode MACRO vmode
ifnb <vmode>
mov ax,(vmode AND 0ffh)
else
xor ah,ah
endif
int VIDEO_INT
ENDM
.code
;/***************************************************************************
; main
; This is the main procedure in the code. It identifies (or
; attempts to identify) the type of video card, then switches into
; the appropriate video mode for that type of card. Right now, it
; doesn't actually do anything in that mode, but simply returns
; and restores the video mode to a fairly standard 80x25 text
; mode. Mostly as an aid to troubleshooting, the current version
; also prints out the name of the video card as discovered in the
; video BIOS area.
;
;***************************************************************************/
main proc
.STARTUP ; do the usual startup stuff
call IDVideoBios ; identify video BIOS
or si,si ; Q: unknown card?
jz NoSupport ; Y: tell the user the bad news
dec si ; point to video mode (mode1, mode2)
lodsb ; load into al & increment si
@SetVidMode ; change video mode
;
; snazzy graphics code goes here
;
@SetVidMode <VID_80x25> ; switch back to 80x25 text mode
@DosPrint <si> ; print ID string
.EXIT 0 ; exit with error code = 0
NoSupport:
@DosPrint <offset UnknownCardMsg> ; print unknown card message
.EXIT 1 ; exit with error code = 1
main endp
;/***************************************************************************
; IDVideoBios
;
; This procedure searches the first SEARCH_AREA bytes in the video
; BIOS for a byte sequence which uniquely identifies a video
; card's manufacturer. If no known card name is found, the
; function returns a null pointer.
;
; Entry: DS contains the segment of the cards array
;
; Exit: If a match was found,
; DS:SI ==> matching sequence
; otherwise
; SI = 0
;
; Destroyed: none
;
;***************************************************************************/
IDVideoBios proc
push ax ; save used regs
push bx ;
push cx ;
push es ;
mov ax,VID_BIOS_SEG ; point to video BIOS
mov es,ax ;
mov bx,OFFSET cards ; point to first card entry
cld ; we'll be scanning forward
next_card:
mov si,[bx] ;
or si,si ; Q: is it a NULL pointer?
jz @@exit ; Y: we're done, so exit now
xor di,di ; es:di ==> video BIOS area
mov cx,SEARCH_AREA ;
mov al,[si] ; get the first letter
scan:
repne scasb ; scan for AL in es:di
jnz nofind ; if we didn't find it, skip over
;
; if we got here, ES:DI points to one letter after the matching letter
; in the video BIOS. We need to compare the rest to assure that we have
; a complete match.
;
push cx ; temporarily save regs
push di ;
push si ;
inc si ; point to next letter
mov cx,CMP_LENGTH-1 ; compare the rest the string
repe cmpsb ; do it
pop si ; restore regs
pop di ;
pop cx ;
jz @@exit ; if match, we're done
nofind:
or cx,cx ; Q: is the count down to zero?
jnz scan ; N: keep scanning
inc bx ; Y: point to next card
inc bx ; point to next card entry
jmp next_card ; go back for more
@@exit:
pop es ; restore used registers
pop cx ;
pop bx ;
pop ax ;
ret ;
IDVideoBios endp
end

@ -0,0 +1,117 @@
;
;
DGROUP GROUP DATASEG
DATASEG SEGMENT PARA PUBLIC 'DATA'
FUNCT DW 0 ;function 1=6,0=7
FG_COLR DW 0 ;forground color
BG_COLR DW 0 ;backround color
LINES DW 0 ;number of lines to scroll or 0 for clear
ULROW DW 0 ;upper left row
ULCOL DW 0 ;upper left column
LRROW DW 0 ;lower right row
LRCOL DW 0 ;lower left column
ATTRIB DB 0 ;temp hold for attribute byte
CALNU DB 0 ;temp hold for call function 6 or 7
DATASEG ENDS
;
CSEG SEGMENT 'CODE'
ASSUME CS:CSEG
PUBLIC CLR
CLR PROC FAR
PUSH BP ;BP unknown (don't care)
MOV BP,SP ;set base for parm list
PUSH DS ;DS -> basic work area
PUSH ES ;ES -> basic work area
MOV AX,DATASEG ;establish data addressability
MOV DS,AX ;now DS -> my data
ASSUME DS:DATASEG
;
;
MOV SI,SS:[BP+6] ;get addr of parameter
MOV AX,ES:[SI] ;get value of parm
MOV FUNCT,AX
MOV SI,SS:[BP+8] ;get addr of parameter
MOV AX,ES:[SI] ;get value of parm
MOV BG_COLR,AX
MOV SI,SS:[BP+10] ;get addr of parameter
MOV AX,ES:[SI] ;get value of parm
MOV FG_COLR,AX
MOV SI,SS:[BP+12] ;get addr of parameter
MOV AX,ES:[SI] ;get value of parm
MOV LINES,AX
MOV SI,SS:[BP+14] ;get addr of parameter
MOV AX,ES:[SI] ;get value of parm
MOV ULROW,AX
MOV SI,SS:[BP+16] ;get addr of parameter
MOV AX,ES:[SI] ;get value of parm
MOV ULCOL,AX
MOV SI,SS:[BP+18] ;get addr of parameter
MOV AX,ES:[SI] ;get value of parm
MOV LRROW,AX
MOV SI,SS:[BP+20] ;get addr of parameter
MOV AX,ES:[SI] ;get value of parm
MOV LRCOL,AX
;
MOV AX,1
SUB LRROW,AX ;convert 1-80 cols
SUB LRCOL,AX ; and 1-25 rows into
SUB ULROW,AX ; 0-79 cols and
SUB ULCOL,AX ; 0-24 rows
;
; change forground & backround colors into single attribute byte
;
MOV BX,FG_COLR ;move foreground color to bx
MOV AL,BL ;move lower byte to al
MOV BX,BG_COLR ;move backround color to bx
MOV AH,BL ;move lower byte to ah
CMP AL,15 ;check for color > 15 ie blinking
JG BLNK ;if > 15 then set blink bit
AND AL,15 ;set normal fg color
JMP N_BLNK ;
BLNK: OR AL,128 ;set blink bit 7
AND AL,143 ;zero out bit 6,5,4 used for backround
N_BLNK: AND AH,7 ;zero out bit 7,6,5,4,3 used for forground
MOV CL,4 ;4 bit shift count
SHL AH,CL ;shift right 3 bits to pos 6,5,4
OR AL,AH ;combine for & back to form attribute byte
MOV ATTRIB,AL ;move it to STORAGE
;
; convert 1 and 0 to 6 and 7 for routine call
;
MOV BX,FUNCT ;move function into bx
CMP BL,0 ;compare to one
JG F6 ;if 1 then function is 6
MOV AH,7H ;set function 7
JMP OUT1 ;jump around
F6: MOV AH,6H ;set function 6
OUT1: MOV CALNU,AH ;move it to storage
;
;
; set up for bios rom call 10 function 6 (scroll up )
;
PUSH BX
MOV BX,LINES ;set # of lines to scroll or 0 to clear
MOV AL,BL ;put in pass register
MOV BX,ULROW ;set upper left row of block 0-24
MOV CH,BL ;put in pass register
MOV BX,ULCOL ;set upper left column of block 0-79
MOV CL,BL ;put in pass register
MOV BX,LRROW ;set lower right row of block 0-24
MOV DH,BL ;put in pass register
MOV BX,LRCOL ;set lower right column of block 0-79
MOV DL,BL ;put in pass register
MOV BL,CALNU ;set call number 6 to scroll up 7 down
MOV AH,BL ;put in pass register
MOV BL,ATTRIB ;set color attribute byte
MOV BH,BL ;put in pass register
INT 10H ; make bios call
POP BX
;
FINISH: POP ES
POP DS
POP BP
RET 16 ;return to basic
CLR ENDP
CSEG ENDS
END

@ -0,0 +1,41 @@
; pentbug.asm
;
; tests for the existence of the well-documented Pentium NPU bug
;
; assemble and run this program using Borland's TASM and run under DOS:
;
; TASM pentbug ; one pass assemble
; TLINK /Tdc pentbug ; link as COM file
; PENTBUG ; run the program...
;
.MODEL tiny
.386
.387
.CODE
ORG 100h
Start:
mov dx,OFFSET okmsg ; start out optimistically
fild [first] ; load the first number (x)
fild [second] ; and the second (y)
fdiv st(1),st ; perform y/x
fmulp st(1),st ; now st(0) = (y/x)*x
fild [first] ; reload y
fcompp ; compare the two
fnstsw ax ; put status word into ax
sahf ; load into CPU flags
jz short @@NoBug ; if they're equal, no bug
mov dx,OFFSET bugmsg ; load bad news message...
@@NoBug:
mov ah,9 ; print appropriate message
int 21h ;
mov ah,4ch ; and exit
int 21h ;
first DD 4195835 ; "magic numbers" culled from
second DD 3145727 ; the net. There are others...
okmsg DB "No "
bugmsg DB "Pentium bug found.",13,10,'$'
END Start

@ -0,0 +1,92 @@
; bcd.asm
comment ^
This is a small demonstration program to show how one might
handle the addition of IBM 370-style packed decimal numbers
(which are similar to BCD). This particular program imposes an
arbitrary simplifying limitation by only allowing the addition
of numbers which are both the same sign, but it would be easy to
extend by either converting all negative operands to ten's
complement and adding or by implementing a subtraction routine
(which would use SBB, DAS instead of ADC, DAA).
^
.MODEL small ; DOS - small model
.STACK 200h ; allocate a bit of stack
.DATA
OPLEN equ 4 ; the size of operands & result (bytes)
first db 00h, 01h, 23h, 4Ch ; 1234 in packed decimal
second db 00h, 00h, 00h, 9Ch ; 9 in packed decimal
result db OPLEN dup (?) ; allocate space for result
.CODE
.STARTUP
mov si,offset first + OPLEN - 1 ; point to first op
mov bx,offset second + OPLEN - 1 ; second op
mov di,ds ;
mov es,di ; load es
mov di,offset result + OPLEN - 1 ; point to result area
mov cx,OPLEN ; how big are they?
call AddPackedDecimal ; add 'em up!
.EXIT 0
;****************************************************************************
; AddPackedDecimal
;
; add two 370-style packed decimal numbers with identical signs
;
; Entry:
; DS:SI ==> end of first operand
; DS:BX ==> end of second operand
; ES:DI ==> end of pre-allocated result space
; CX = size of operands, result (in bytes)
;
; Exit:
; if CY set, error occurred
; otherwise, result of addition is in result space
;
; Trashed:
; none
;
;****************************************************************************
AddPackedDecimal proc
push ax ; save used regs
push bx
push cx
push dx
push di
push si
mov al,[si] ;
mov ah,[bx] ;
mov dx,ax ;
and dx,00f0fh ; use only low nybbles in DX
and ax,0f0f0h ; save high nybbles in AX
cmp dl,dh ; are they identical?
stc ; (assume they're not)
jnz Done ; if not, it's an error
std ; set dir flag (decrement ptrs)
clc ; clear carry flag
push di ; save original DI for later
AddEmUp: ;
adc al,ah ; add (with carry)
daa ; decimal adjust packed BCD
stosb ; save result
lahf ; save carry flag
dec si ; adjust pointer for first op
dec bx ; adjust pointer for second op
sahf ; restore flag
mov al,[si] ; fetch next digits of first op
mov ah,[bx] ; fetch next digits of second op
loop AddEmUp ; do 'em all (CX is counter)
pop di ; restore original DI
jc Done ; if carry, it's an overflow
or [di],dl ; place sign nybble (and clear CY)
Done: ;
pop si ; restore used registers
pop di
pop dx
pop cx
pop bx
pop ax
ret ;
AddPackedDecimal endp
END

@ -0,0 +1,218 @@
;* This is a simple litte assembler program that cleans out *
;* the documents folder in the start menu. *
;* This is version 1.2 *
;* There's no command line switches and stuff. *
;* It gives NO messages if everything goes allright. *
;* It check for a environment variable called CLEANDIR and CD:s *
;* down to that dir if the variable is found. If not it uses *
;* the default WINDOWS\RECENT directory and deletes(UNLINKS) *
;* EVERYTHING it finds there, and CD:s back to where it started *
;* from. *
;************************************************************************
;some euqates for readability
kbd equ 16h ;keyboard irq
msdos equ 21h ;MSDOS irq
reset equ 0dh ;disk reset
dfopen equ 0fh ;open disk file
dfclose equ 10h ;close disk file
searchf equ 11h ;search first
searchn equ 12h ;search next
seqread equ 14h ;sequential disk read
seqwrite equ 15h ; " " write
getdisk equ 19h ;get current disk(default)
setdta equ 1ah ;set disk transfer area address
setdir equ 3bh ;set current directory
createf equ 3ch ;create file with handle
openf equ 3dh ;open file with handle
closef equ 3eh ;close file with handle
readf equ 3fh ;read from file with handle
writef equ 40h ;write to file with handle
unlink equ 41h ;UNLINK(delete file)
getdir equ 47h ;get current directory
allocmem equ 48h ;allocate memory
freemem equ 49h ;free memory
changebs equ 4ah ;change block size
findfirst equ 4eh ;find first file
findnext equ 4fh ;find next file
exit equ 4c00h ;msdos exit
envir equ 2ch ;offset ENVIRONMENT block
[BITS 16] ;NASM STUFF !?
[ORG 100h]
mov ax,cs ;get code segment
mov ds,ax ;use it now
mov [comseg],ds
mov [extseg],es
;************************ setup and preparing ***************************
main:
mov ah,setdta ;set our DTA-area
mov dx,mydta ;buffer for it
int msdos ;call dos
mov ah,getdisk ;get default drive
int msdos ;call dos
add al,41h ;drive in al, make it ASCII
mov byte [curdir],al ;fill buffer with name (A:..etc)
mov byte [path],al ;and default path
mov word [curdir+1],":\" ;copy separator to path
mov si,curdir ;pointer path buffer
add si,3 ;offset doscall part
mov ah,getdir ;get current dir
mov dl,0 ;0 = default
int msdos ;call dos
jnc diskok ;ok
mov bx,errt0 ;could not find current dir ?? If You
jmp errout ;get an error here You probably have
diskok: ;forgot to turn on Your computer.
call getenv ;check out if any ENV var
cmp dx,-1 ;was it there
je findfile ;yeahh
mov dx,path ;noo way, use default path
mov ah,setdir ;cd down
int msdos ;call dos
jnc findfile ;all ok
mov bx,errt1 ;error
jmp errout ;skip
;*************************** the delete file loop ***********************
findfile:
mov ah,findfirst ;see if the files out there
mov cx,0fh ;all files
mov dx,files ;our NULL terminated filname(*.*)
int msdos ;do the stuff
jnc delit ;all ok, must delete first file
jmp goback ;error, CD back and skip
found: ;found something
mov dx,files ;files (*.*)
mov ah,findnext ;the function
int msdos ;call dos
jc goback ;no more files, quit
delit:
mov ah,unlink ;UNLINK (delete) file
mov dx,mydta ;pointer Disk Transfer Area
add dx,30 ;offset Filename
int msdos ;delete it
jnc found ;deleted ok
mov bx,errt2 ;could not delete it ????
call write ;let us know
mov bx,mydta ;show wich file
add bx,30 ;offset filename in DTA
call write ;write out filename
mov bx,linefeed ;linefeed
jmp errout ;and skip
goback:
mov ah,setdir ;CD back to origin
mov dx,curdir ;path to dir
int msdos ;do it
jnc quit ;all ok, proceed
mov bx,errt1 ;error, get text
;*************************** errorexit ***********************
errout: call write ;show errormessage
quit:
xor eax,eax ;clean out that
mov ax,exit ;MS-DOS successful exit
int msdos ;back to the operating system
;***************** get ENVIRONMENT var if any *****************
getenv:
push es ;now check if there's any
push ds ;environment variable
mov es,[es:+2Ch] ;ES:DI points at environment
xor di,di ;which is paragraph-aligned
floop:
cmp byte [es:di],0 ;if we got 2 zeroes in a row
jne goon ;we are at the end of the ENV
cmp byte [es:di+1],0 ;variables
je eout
goon:
equal: cmp byte [es:di],'C' ;is it our variable ?
jne flop
inc byte di
cmp byte [es:di],'L'
jne flop
inc byte di
cmp byte [es:di],'E'
jne flop
inc byte di
cmp byte [es:di],'A'
jne flop
inc byte di
cmp byte [es:di],'N'
jne flop
inc byte di
cmp byte [es:di],'D'
jne flop
inc byte di
cmp byte [es:di],'I'
jne flop
inc byte di
cmp byte [es:di],'R'
jne flop
sign: inc byte di ;dump the R
inc byte di ;dump the =
mov ax,es ;make DS:DX point to string we found
mov ds,ax
mov si,di
mov bx,si
mov dx,bx
mov ah,setdir ;func Set Current Directory(CD)
int msdos ;do it
jnc envok ;all ok, proceed
mov dx,0 ;clear flag (use default dir)
jmp eout ;return
flop: inc byte di ;next byte
cmp byte [es:di],0 ;a 0 ?
jne flop ;noo
inc byte di ;yeahh, dump it
jmp floop ;check if two
envok: mov dx,-1
eout: pop ds
pop es
ret
;*************************************************************************
;* Writes out the NULL terminated text supplied in BX. *
;* OR writes out data,BX and size,CX if called at lwrite. *
;*************************************************************************
write: pusha
mov si,bx ;copy to SI
mov cx,0 ;clear count
wloop: lodsb ;load AL with SI
cmp al,0 ;end of line ?
je lwrite ;yeahh
inc cx ;no, incrase byte count
jmp wloop ;test next byte
lwrite: mov dx,bx ;text address in DX
mov bx,1 ;filehandle standard output = 1
mov ah,writef ;MS-DOS writefile with handle is 040
int msdos ;write buffer to standard output
popa
ret ;done
;************************ DATA and BSS stuff ***************************
comseg: dw 0
extseg: dw 0
utext: db "XXX",13,10,0
errt0: db "Could not find current directory !",13,10,0
errt1: db "Directory not found.",13,10,0
errt2: db "Could not delete ",0
path: db " :\WINDOWS\RECENT",0 ;default path without DRIVE
files: db "*.*",0
linefeed: db 13,10,0
mydta times 128 db 0 ;use 128 bytes as DTA NASM stuff !
curdir times 68 db 0 ;use 64 + 4 bytes for current dir
END

@ -0,0 +1,90 @@
; It will play 12 notes of the octave starting at middle C.
;-----------------------------------------------------------------------------
; How to generate sound on the IBM PC :
;
; The 8255 (port 61H) bit 0 controls the 8253 timer
; bit 1 controls the speaker
;
; The output channel 2 from the 8253 timer will be ANDed with the
; speaker control bit in order to turn on/off the speaker.
;
; Timer channel 2 internal count register (port 42h) is loaded in
; two successive OUT operations with the lower byte being loaded first.
; For this to work properly, timer command register has to be loaded first
; with B6H.
;
; Since the input clock to the timer chip is 1.19318 MHz, the counter value
; to generate the frequency X can be calculated by 1193180 / X.
;-----------------------------------------------------------------------------
; CX is used as a note counter with the frequency effectively being
; incremented by a half tone and the corresponding count being loaded
; into the count register on each iteration.
;
; No stack segment is needed for this small program, so don't panic
; when you receive the 'No stack segment' warning.
;
; Arne Asplem 880731 (MASM 4.0)
dseg segment ; data segment
notes dw 262,277,294,311,330,349,370,392,415,440,466,494
dseg ends
cseg segment
sound proc far
assume cs:cseg, ds:dseg, ss:nothing
start:
mov ax, dseg
mov ds, ax ; set up data segment (DS) reg.
xor si, si
mov bx, 12 ; note count
; set up timer command register and counter register
mov al, 0b6h ; set 8253 command register
out 43h, al ; for channel 2, mode 3
nloop:
mov ax, 34dch ; low part of clock freq.
mov dx, 12h ; hight part of clock freq.
div [notes + si] ; get note from data segment
out 42h, al ; 8253 command register (low byte)
mov al, ah
out 42h, al ; 8253 command regsieter (high byte)
; turn on low bits in 8255 output port
in al, 61h ; read current value of 8255 port
or al, 3 ; clear low bits
out 61h, al ; send new value to port
; loop while note is sounding
mov cx, 6d60h
rpta:
loop rpta ; 1/10 sec delay
; turn off speaker, check note count, set up next note
xor al, 3
out 61h, al ; turn off speaker
mov cx, 0af0h
rptb:
loop rptb ; 1/100 sec delay
inc si ; increment note pointer
inc si
dec bx ; decrement note counter
jnz nloop ; loop until bx = 0
mov ax, 4c00h ; terminate program
int 21h
sound endp
cseg ends
end start

@ -0,0 +1,94 @@
extrn $$main:far
cseg segment para public 'code'
; It can also be used to limit the maximum memory available to a compiled
; BASIC program. The option '/M:nnn' is used on the command line, where
; nnn is the number of K-bytes the program is limited to. If no, /M option
; is specified, no memory limitation takes place. For example, '/M:64' would
; limit the program to 64*1024 bytes. The range for nnn is 64 to 1024.
; This routine gets control before BASIC, does its handiwork, and then
; passes control to the BASIC program. It must be linked as follows:
; LINK BASMAIN+yourprog,yourprog,NUL.MAP,BASCOM
; If BASMAIN is unable to limit memory as requested, a message is displayed
; and the execution of the program is continued.
public basmain
basmain proc far
assume cs:cseg,ds:cseg,ss:nothing,es:nothing
push ds ; save ds
xor ax,ax
mov ds,ax ; ds=0
mov si,4f2h ; dos communications area
mov ax,es ; get psp seg
mov [si],ax ; save psp in dos comm area
pop ds ; restore ds
mov si,80h ; point to command line
mov ch,0
mov cl,[si] ; get length of command line
jcxz p025 ; it's zero
p010: inc si
mov al,[si] ; get char from command line
cmp al,'/' ; is it a slash?
jnz p020 ; no
mov ax,[si+1] ; get next 2 chars
cmp ax,':M' ; is it M: ?
jz p030 ; yes
cmp ax,':m' ; is it m: ?
jz p030 ; yes
p020: loop p010 ; check next char
p025: jmp p080 ; no /m: or /M: found
p030: ; found /m: or /M:
add si,3 ; point to first number
mov ax,0
mov bx,0
mov cx,10
p040: mov bl,[si] ; get character
cmp bl,'0' ; out of range?
jb p050 ; yes
cmp bl,'9' ; out of range?
ja p050 ; yes
sub bl,'0' ; convert to binary
mul cx ; multiply ax by 10
add ax,bx ; add new digit
inc si ; point to next char
jmp p040 ; continue
p050: ; got value in ax
cmp ax,64 ; less than 64K?
jb p060 ; yes - print msg
cmp ax,1024 ; greater than 1024K?
ja p060 ; yes - print msg
mov cl,6
sal ax,cl ; convert from KB to paragraphs (*64)
mov bx,es ; get psp
add bx,ax ; new top of memory
mov si,2 ; point to top of memory in psp
mov ax,[si] ; get current top of memory
cmp ax,bx ; is new setting larger?
jae p055 ; no
mov dx,offset msg2 ; yes - print msg
jmp p065
p055: mov [si],bx ; save new top of memory
jmp p080
p060: mov dx,offset msg1 ; print the message
p065: add dx,100h ; fudge for the psp
mov ah,9
int 21h
p080: jmp $$main ; jump to BASIC's start point
msg1 db 'Memory specification must be from 64 to 1024',7,10,13,'$'
msg2 db 'Unable to limit memory',7,10,13,'$'
basmain endp
cseg ends
end basmain ; must be a main program!

@ -0,0 +1,85 @@
;BASLOAD.ASM
;----------------------------------------------------------------------------
;
;Inputs:
; FILE SPEC 1 - A string (len <= 80) with the complete name, including
; path, of the file to be loaded and executed.
; Example: 'MAINMENU.EXE' or 'C:\FORMAT.COM'
; PARAMETER 1 - A string (len <= 80) with the command line parameters
; to be passed to the program specified in FILE SPEC 1.
; Example: '' or 'A:'
; FILE SPEC 2 - Same as 1.
; PARAMETER 2 - Same as 1.
;
;Outputs:
; This program gives control to LOAD.
;----------------------------------------------------------------------------
CODE SEGMENT 'CODE'
ASSUME CS:CODE
PUBLIC BASLOAD ;make known to BASIC at link time
BASLOAD PROC FAR
;prologue
PUSH BP ;save BP
MOV BP,SP ;set base for parm list
PUSH DS ;DS -> basic work area
PUSH ES ;ES -> basic work area
MOV DX,'dk' ;interrupt verification switch
INT 77H ;get seg address of sysparm area in AX
MOV ES,AX ;ES -> sysparm area
CLD ;set direction for all moves
;move file spec 1 to sysparm
MOV BX,SS:[BP+12] ;get addr of string descriptor
MOV CX,DS:[BX] ;get length of string into CX
MOV SI,DS:[BX+2] ;get addr of string into SI
MOV DI,0 ;offset into sysparm
REP MOVSB ;move string
MOV BYTE PTR ES:[DI],0 ;make it asciiz string
;move parameter 1 to sysparm
MOV BX,SS:[BP+10] ;get addr of string descriptor
MOV CX,DS:[BX] ;get length of string into CX
MOV SI,DS:[BX+2] ;get addr of string into SI
MOV DI,81 ;offset into sysparm
INC CL ;adjust for cr to be added at end
MOV BYTE PTR ES:[DI],CL ;1st byte is length of string
DEC CL ;re-adjust for move operation
INC DI
REP MOVSB ;move string
MOV BYTE PTR ES:[DI],13 ;add cr to end
;move file spec 2 to sysparm
MOV BX,SS:[BP+8] ;get addr of string descriptor
MOV CX,DS:[BX] ;get length of string into CX
MOV SI,DS:[BX+2] ;get addr of string into SI
MOV DI,163 ;offset into sysparm
REP MOVSB ;move string
MOV BYTE PTR ES:[DI],0 ;make it asciiz string
;move parameter 2 to sysparm
MOV BX,SS:[BP+6] ;get addr of string descriptor
MOV CX,DS:[BX] ;get length of string into CX
MOV SI,DS:[BX+2] ;get addr of string into SI
MOV DI,244 ;offset into sysparm
INC CL ;adjust for cr to be added at end
MOV BYTE PTR ES:[DI],CL ;1st byte is length of string
DEC CL ;re-adjust for move operation
INC DI
REP MOVSB ;move string
MOV BYTE PTR ES:[DI],13 ;add cr to end
;exit to BASIC
POP ES
POP DS
POP BP
RET 8
BASLOAD ENDP
CODE ENDS
END BASLOAD

@ -0,0 +1,107 @@
;by passing parameters via the system parameter area (SYSPARM).
;
;Inputs:
;01 COBLOAD-PARMS
; 05 FILE-SPEC-1 PIC X(80). Contains complete drive, path and filename.
; 05 PARAMETER-1 PIC X(80). Contains command line parameters.
; 05 FILE-SPEC-2 PIC X(80). Same as 1.
; 05 PARAMETER-2 PIC X(80). Same as 1.
;
;Outputs:
; None.
;----------------------------------------------------------------------------
CL_CODE_SEG SEGMENT PUBLIC 'CODE'
ASSUME CS:CL_CODE_SEG,DS:CL_CODE_SEG,ES:CL_CODE_SEG
STACK_PARM STRUC
PUSHED_SI DW ?
PUSHED_DI DW ?
PUSHED_DS DW ?
PUSHED_ES DW ?
PUSHED_BP DW ?
RETURN_IP DW ?
RETURN_CS DW ?
PARM1_OFFSET DW ?
PARM1_DS DW ?
STACK_PARM ENDS
PUBLIC COBLOAD ;make known to COBOL at link time
COBLOAD PROC FAR
;prologue
PUSH BP
PUSH ES
PUSH DS
PUSH DI
PUSH SI
MOV BP,SP ;set base for stack parm structure
;address caller's parameter block
MOV AX,[BP].PARM1_DS
MOV DS,AX ;DS -> cobol data seg
MOV SI,[BP].PARM1_OFFSET ;SI -> offset to parm block
;address load's parameter block in sysparm
MOV DX,'dk' ;verification switch
INT 77H ;get seg addr in AX
MOV ES,AX ;ES -> sysparm
MOV DI,0 ;DI -> offset to LOAD parms
;move cobol's parm block to load's parm block (in sysparm)
CLD ;set direction for moves
MOV CX,80 ;length of move
REP MOVSB ;move file spec 1
ASCIIZ1: MOV BYTE PTR ES:[DI],0 ;make asciiz string
DEC DI
MOV AL,BYTE PTR ES:[DI]
CMP AL,' ' ;nullify trailing spaces
JE ASCIIZ1
MOV BX,81 ;point to parm length byte
MOV BYTE PTR ES:[BX],82 ;init length of parm, + 2
MOV DI,82 ;point to 1st parm position
MOV CX,80 ;length of move
REP MOVSB ;move parm
ADD_CR_1: MOV BYTE PTR ES:[DI],13 ;add carriage return
DEC BYTE PTR ES:[BX] ;sub 1 from length of parm
DEC DI
MOV AL,BYTE PTR ES:[DI]
CMP AL,' ' ;put cr in trailing spaces
JE ADD_CR_1
MOV DI,163
MOV CX,80 ;length of move
REP MOVSB ;move file spec 2
ASCIIZ2: MOV BYTE PTR ES:[DI],0 ;make asciiz string
DEC DI
MOV AL,BYTE PTR ES:[DI]
CMP AL,' ' ;nullify trailing spaces
JE ASCIIZ2
MOV BX,244 ;point to parm length byte
MOV BYTE PTR ES:[BX],82 ;init length of parm, + 2
MOV DI,245 ;point to 1st parm position
MOV CX,80 ;length of move
REP MOVSB ;move parm
ADD_CR_2: MOV BYTE PTR ES:[DI],13 ;add carriage return
DEC BYTE PTR ES:[BX] ;sub 1 from length of parm
DEC DI
MOV AL,BYTE PTR ES:[DI]
CMP AL,' ' ;put cr in trailing spaces
JE ADD_CR_2
;return to caller
POP SI
POP DI
POP DS
POP ES
POP BP
RET 4
COBLOAD ENDP
CL_CODE_SEG ENDS
END

@ -0,0 +1,412 @@
;
; CLEAN --- a utility to filter text files.
; This program removes all control codes except
; for line feeds, carriage returns, and form
; feeds, strips off the high bit of all characters,
; and expands tabs. Can be used to make a Wordstar
; file acceptable for other screen or line editors,
; and vice versa.
;
cr equ 0dh ;ASCII carriage return
lf equ 0ah ;ASCII line feed
ff equ 0ch ;ASCII form feed
eof equ 01ah ;End of file marker
tab equ 09h ;ASCII tab character
command equ 80h ;buffer for command tail
blksize equ 1024 ;blocking/deblocking size
cseg segment para public 'CODE'
assume cs:cseg,ds:data,es:data,ss:stack
clean proc far ;entry point from PC-DOS
push ds ;save DS:0000 for final
xor ax,ax ;return to PC-DOS
push ax
mov ax,data ;make our data segment
mov es,ax ;addressable via ES register
call infile ;get path and file spec.
;for input file
mov ax,es ;set DS=ES for remainder
mov ds,ax ;of program
jnc clean1 ;jump, got acceptable name
mov dx,offset msg4 ;missing or illegal filespec,
jmp clean9 ;print error message and exit.
clean1: call outfile ;set up output file name
call open_input ;now try to open input file
jnc clean2 ;jump,opened input ok
mov dx,offset msg1 ;open of input file failed,
jmp clean9 ;print error msg and exit.
clean2:
call open_output ;try to open output file.
jnc clean25 ;jump,opened ok
mov dx,offset msg2 ;open of output file failed,
jmp clean9 ;print error message and exit.
clean25: ;set up buffers
call init_buffs
call sign_on ;print ident and file names
;files successfully opened,
clean3: ;now filter the file.
call get_char ;read 1 character from input.
and al,07fh ;strip off the high bit
cmp al,20h ;is it a control code?
jae clean4 ;no,write it to new file
;yes it is control code,
cmp al,eof ;is it end of file marker?
je clean6 ;yes,jump to close files.
cmp al,tab ;is it a tab command?
jz clean5 ;yes,jump to special processing.
cmp al,cr ;if control code other than
je clean35 ;tab or end-of-file mark, throw
cmp al,ff ;it away unless it is a
je clean35 ;form feed, carriage return,
cmp al,lf ;or line feed.
jne clean3
clean35: ;If it is one of those three,
mov column,0 ;incidentally initialize
jmp clean45 ;column count for tab processor.
clean4: ;count alphanumeric chars. sent.
inc column
clean45: ;write this character to
call put_char ;output file,
jnc clean3 ;if CY not set, write was
;ok so go get next char.
clean47:
call close_input ;if CY set, disk is full
call close_output ;so close files and exit
mov dx,offset msg5 ;with error message.
jmp clean9
clean5: ;process tab character
mov ax,column ;let DX:AX=column count
cwd
mov cx,8 ;divide it by eight...
idiv cx
sub cx,dx ;remainder is in DX.
add column,cx ;update column pointer.
clean55: ;8 minus the remainder
push cx ;gives us the number of
mov al,20h ;spaces to send out to
call put_char ;move to the next tab position
pop cx ;restore space count
jc clean47 ;jump if disk is full
loop clean55
jmp short clean3 ;get next character
clean6: ;end of file detected,
call put_char ;write end-of-file marker,
jc clean47 ;jump if disk was full
call flush_buffs ;write remaining data to disk
jc clean47 ;if CY set,disk was full
;otherwise file was written ok
call close_input ;close input and output
call close_output ;files.
mov dx,offset msg3 ;addr of success message,
clean9: ;print message and return
mov ah,9 ;control to PC-DOS
int 21h
ret
clean endp
infile proc near ;process name of input file
;DS:SI <- addr command line
mov si,offset command
;ES:DI <- addr filespec buffer
mov di,offset input_name
cld
lodsb ;any command line present?
or al,al ;return error status if not.
jz infile4
infile1: ;scan over leading blanks
lodsb ;to file name
cmp al,cr ;if we hit carriage return
jz infile4 ;filename is missing.
cmp al,20h ;is this a blank?
jz infile1 ;if so keep scanning.
infile2: ;found first char of name,
stosb ;move last char. to output
;file name buffer.
lodsb ;check next character, found
cmp al,cr ;carriage return yet?
je infile3 ;yes,exit with success code
cmp al,20h ;is this a blank?
jne infile2 ;if not keep moving chars.
infile3: ;exit with carry =0
clc ;for success flag
ret
infile4: ;exit with carry =1
stc ;for error flag
ret
infile endp
outfile proc near ;set up path and file
cld ;name for output file.
mov cx,64 ;length to move
mov si,offset input_name ;source addr
mov di,offset output_name ;dest addr
rep movsb ;transfer the string
mov di,offset output_name
outfile1: ;scan string looking for
mov al,[di] ;"." marking start of extension
or al,al ;or zero byte marking name end.
jz outfile2 ;if either is found,jump.
cmp al,'.'
je outfile2 ;bump string pointer, loop
inc di ;if neither '.' or zero found.
jmp outfile1
outfile2: ;found zero or '.',force the
;extension of the output file
;to '.CLN'
mov si,offset outfile_ext
mov cx,5
rep movsb
ret ;back to caller
outfile endp
open_input proc near ;open input file
;DS:DX=addr filename
mov dx,offset input_name
mov al,0 ;AL=0 for read only
mov ah,3dh ;function 3dh=open
int 21h ;handle returned in AX,
mov input_handle,ax ;save it for later.
ret ;CY is set if error
open_input endp
open_output proc near ;open output file
;DS:DX=addr filename
mov dx,offset output_name
mov al,1 ;AL=1 for write only
mov ah,3ch ;function 3ch=MAKE or
int 21h ;truncate existing file
;handle returned in AX
mov output_handle,ax;save it for later.
ret ;return CY=true if error
open_output endp
close_input proc near ;close input file
mov bx,input_handle ;BX=handle
mov ah,3eh
int 21h
ret
close_input endp
close_output proc near ;close output file
mov bx,output_handle;BX=handle
mov ah,3eh
int 21h
ret
close_output endp
get_char proc near ;get one character from input buffer
mov bx,input_ptr
cmp bx,blksize
jne get_char1
call read_block
mov bx,0
get_char1:
mov al,[input_buffer+bx]
inc bx
mov input_ptr,bx
ret
get_char endp
put_char proc near ;put one character into output buffer
mov bx,output_ptr
mov [output_buffer+bx],al
inc bx
mov output_ptr,bx
cmp bx,blksize ;buffer full yet?
jne put_char1 ;no,jump
call write_block ;yes,write the block
ret ;return CY as status code
put_char1:
clc ;return CY clear for OK status
ret
put_char endp
read_block proc near
mov bx,input_handle ;read first block of input
mov cx,blksize
mov dx,offset input_buffer
mov ah,3fh
int 21h
jnc read_block1 ;jump if no error status
mov ax,0 ;simulate a zero length read if error
read_block1:
cmp ax,blksize ;was full buffer read in?
je read_block2 ;yes,jump
mov bx,ax ;no, store End-of-File mark
mov byte ptr [input_buffer+bx],eof
read_block2:
xor ax,ax ;initialize input buffer pointer
mov input_ptr,ax
ret
read_block endp
write_block proc near ;write blocked output (blksize bytes)
mov dx,offset output_buffer
mov cx,blksize
mov bx,output_handle
mov ah,40h
int 21h
xor bx,bx ;initialize pointer to blocking buffer
mov output_ptr,bx
cmp ax,blksize ;was correct length written?
jne write_block1 ;no,disk must be full
clc ;yes,return CY=0 indicating all OK
ret
write_block1: ;disk is full, return CY =1
stc ;as error code
ret
write_block endp
init_buffs proc near
call read_block ;read 1st block of input
xor ax,ax ;initialize pointer to output
mov output_ptr,ax ;output blocking buffer
ret
init_buffs endp
flush_buffs proc near ;write any data in output buffer to disk
mov cx,output_ptr
or cx,cx
jz flush_buffs1 ;jump,buffer is empty
mov bx,output_handle
mov dx,offset output_buffer
mov ah,40h
int 21h
cmp ax,output_ptr ;was write successful?
jnz flush_buffs2 ;no,jump
flush_buffs1:
clc ;yes,return CY=0 for
ret ;success flag
flush_buffs2: ;disk was full so write failed,
stc ;return CY=1 as error flag
ret
flush_buffs endp
sign_on proc near ;print sign-on message
mov dx,offset msg6 ;title...
mov ah,9
int 21h
mov dx,offset msg7 ;input file:
mov ah,9
int 21h
mov dx,offset input_name
call pasciiz
mov dx,offset msg8 ;output file:
mov ah,9
int 21h
mov dx,offset output_name
call pasciiz
mov dx,offset msg9
mov ah,9
int 21h
ret
sign_on endp
pasciiz proc near ;call DX=offset of ASCIIZ string
mov bx,dx ;which will be printed on standard output
pasciiz1:
mov dl,[bx]
or dl,dl
jz pasciiz9
cmp dl,'A'
jb pasciiz2
cmp dl,'Z'
ja pasciiz2
or dl,20h
pasciiz2:
mov ah,2
int 21h
inc bx
jmp pasciiz1
pasciiz9:
ret
pasciiz endp
cseg ends
data segment para public 'DATA'
input_name db 64 dup (0) ;buffer for input filespec
output_name db 64 dup (0) ;buffer for output filespec
input_handle dw 0 ;token returned by PCDOS
output_handle dw 0 ;token returned by PCDOS
input_ptr dw 0 ;pointer to input blocking buffer
output_ptr dw 0 ;pointer to output blocking buffer
outfile_ext db '.CLN',0 ;extension for filtered file
column dw 0 ;column count for tab processing
msg1 db cr,lf
db 'Cannot find input file.'
db cr,lf,'$'
msg2 db cr,lf
db 'Failed to open output file.'
db cr,lf,'$'
msg3 db cr,lf
db 'File processing completed'
db cr,lf,'$'
msg4 db cr,lf
db 'Missing file name.'
db cr,lf,'$'
msg5 db cr,lf
db 'Disk is full.'
db cr,lf,'$'
msg6 db cr,lf
db 'Clean Word Processing File'
db cr,lf
db 'WWW.'
db cr,lf,'$'
msg7 db cr,lf,'Input file: $'
msg8 db cr,lf,'Output file: $'
msg9 db cr,lf,'$'
input_buffer db blksize dup (?) ;buffer for deblocking of data
;from input file
output_buffer db blksize dup (?) ;buffer for blocking of data
;sent to output file
data ends
stack segment para stack 'STACK'
db 64 dup (?)
stack ends
end clean

@ -0,0 +1,182 @@
; sector.asm
;
; writes a boot sector out to the floppy disk in the A: drive
;
; The input file is assumed to be a binary file with the relevant code
; at offset 7C00h relative to the beginning of the file. This is because
; when the sector loader transfers control to the boot sector, it's at
; address 0:7C00h. Rather than clutter up the boot loader source with
; a bunch of ugly offsets, we simply use an ORG 7C00h instead and let
; the linker insert a bunch of empty space which this program skips over.
;
; Style Note:
; There aren't any hardwired numbers in this code. That is to say,
; equates and macros are used to render gibberish like this:
; mov ax,4c00h
; int 33
;
; into somewhat self-documenting code like this:
; DosInt DOS_TERMINATE, 0
;
; This is done to make the code more readable, and comprehensible, and
; to aid in maintenance by not littering mysterious constants throughout
; the code. Please be kind to animals (specifically your fellow
; programmers) and use this practice in your own code.
;
;
STACKSIZE = 200h ; this is how much stack we'll allocate
SECTORSIZE = 200h ; size of the boot sector on a floppy
CMD_LINE_LEN = 80h ; offset of the command line length (one byte)
; relative to the beginning of the PSP.
CMD_LINE = 81h ; the offset relative to the beginning of the
; PSP that is the start of the command line
; arguments.
DOS_OPEN_HANDLE = 03dh ; open file
READ_ONLY_DENY_NONE = 020h ; file open mode
DOS_MOVE_HANDLE = 042h ; move file pointer
WHENCE_BEGIN = 0 ; move pointer relative to beginning
WHENCE_CURRENT = 1 ; move pointer relative to current location
WHENCE_EOF = 2 ; move pointer relative to end of file
DOS_READ_HANDLE = 03fh ; read from an open file handle
DOS_CLOSE_HANDLE = 03eh ; close an open file handle
DOS_WRITE_HANDLE = 040h ; write to open file
DOS_TERMINATE = 04ch ; terminate and exit
DOS_INT = 021h
; various named character constants
NUL = 0
CR = 13
LF = 10
SPACE = ' '
GenericInt macro function, subfunction
ifb <subfunction>
mov ah,function
else
mov ax,(function SHL 8) OR (subfunction AND 0ffh)
endif
endm
DosInt macro function, subfunction
GenericInt <function>,<subfunction>
int DOS_INT
endm
BDISK_WRITE_SECTOR = 03h
BDISK_INT = 013h
; constants unique to this program
FILE_OFFS_LO = 7C00h ;
FILE_OFFS_HI = 0000h ;
BOOT_DRIVE = 0 ; we'll be writing to drive A:
BOOT_HEAD = 0 ; head 0 is the boot head
BOOT_CYLSECT = 0001h ; a word value with the following format
; bits 15-8 low bits of cylinder
; bits 7-6 high two bits of cylinder
; bits 5-0 sector
NUM_SECTORS = 1 ; number of sector to write to disk
model small
.386
.stack STACKSIZE
.code
;**********************************************************************
; program code start
;**********************************************************************
Start:
; parse the command line args
mov cl,byte ptr [DGROUP:CMD_LINE_LEN] ; read the length byte
; NOTE that the command line length isn't really part of the
; DGROUP group, but DS currently points to the PSP, and if we
; omit the DGROUP override, the assembler thinks we're trying
; to load a constant instead of the contents of the memory loc.
; In other words, it's ugly but it has a purpose.
or cl,cl ; check for zero
jz Usage ; no command line args
mov si,CMD_LINE ;
mov al,' ' ;
repe cmpsb ; burn off leading spaces
mov dx,si ; save that starting point
repne cmpsb ; scan for next space (if any)
cmp byte ptr [si],SPACE ; if it's > space char,
ja skip ; skip the nul termination
mov byte ptr [si],NUL ; terminate with a NUL char
skip:
; first, open the file
DosInt DOS_OPEN_HANDLE, READ_ONLY_DENY_NONE
mov si,seg DGROUP ;
mov ds,si ;
mov es,si ; point 'em all over there
mov si,offset err_fopen ; can't open input file
jc ErrorExit
; the file's open, so move the file pointer to offset 7C00h
mov bx,ax ; fetch the file handle
mov cx,FILE_OFFS_HI
mov dx,FILE_OFFS_LO
DosInt DOS_MOVE_HANDLE, WHENCE_BEGIN
mov si,offset err_fmove ;
jc ErrorExit ;
; read the data
mov cx,SECTORSIZE ; max number of bytes to read
mov dx,offset buffer ; point ds:dx to buffer
DosInt DOS_READ_HANDLE ;
mov si,offset err_fread ;
jc ErrorExit ;
; close the file
DosInt DOS_CLOSE_HANDLE ; close this file
; now write it out to the floppy disk's boot sector
mov bx,offset buffer ;
mov cx,BOOT_CYLSECT ;
mov dx,(BOOT_HEAD SHL 8) OR (BOOT_DRIVE)
GenericInt BDISK_WRITE_SECTOR, NUM_SECTORS
int BDISK_INT
mov si,offset err_write ;
jc ErrorExit ;
mov si,offset msg_ok ;
ErrorExit:
mov cx,[si] ;
inc si ;
inc si ;
mov dx,si ;
mov bx,1 ; write to stdout
DosInt DOS_WRITE_HANDLE ; write to that file
DosInt DOS_TERMINATE, 0
Usage:
mov si,seg DGROUP ;
mov ds,si ; load correct data segment
mov si,offset use_msg
jmp ErrorExit ;
;**********************************************************************
; program data starts
;**********************************************************************
.data
msgstruc macro msglabel, msgstring
local alpha
msglabel dw (alpha - $) - 2
db msgstring
alpha = $
endm
msgstruc err_fopen ,<"ERROR: couldn't open input file",CR,LF>
msgstruc err_fmove ,<"ERROR: unable to move file pointer",CR,LF>
msgstruc err_fread ,<"ERROR: couldn't read from input file",CR,LF>
msgstruc err_write ,<"ERROR: unable to write to floppy disk",CR,LF>
msgstruc msg_ok ,<"Boot sector was successfully written to floppy",CR,LF>
msgstruc use_msg ,<"Usage: SECTOR infile.bin",CR,LF>
buffer db SECTORSIZE dup (?) ; sector buffer
end Start

@ -0,0 +1,70 @@
/*This is a C++ Program to perform 2D FFT. A fast Fourier transform (FFT) is an algorithm to compute the discrete Fourier transform (DFT) and its inverse. Fourier analysis converts time (or space) to frequency and vice versa; an FFT rapidly computes such transformations by factorizing the DFT matrix into a product of sparse (mostly zero) factors.*/
#include <iostream>
#include <math.h>
using namespace std;
#define PI 3.14159265
int n;
int main(int argc, char **argv)
{
cout << "Enter the size: ";
cin >> n;
double inputData[n][n];
cout << "Enter the 2D elements ";
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
cin >> inputData[i][j];
double realOut[n][n];
double imagOut[n][n];
double amplitudeOut[n][n];
int height = n;
int width = n;
// Two outer loops iterate on output data.
for (int yWave = 0; yWave < height; yWave++)
{
for (int xWave = 0; xWave < width; xWave++)
{
// Two inner loops iterate on input data.
for (int ySpace = 0; ySpace < height; ySpace++)
{
for (int xSpace = 0; xSpace < width; xSpace++)
{
// Compute real, imag, and ampltude.
realOut[yWave][xWave] += (inputData[ySpace][xSpace] * cos(
2 * PI * ((1.0 * xWave * xSpace / width) + (1.0
* yWave * ySpace / height)))) / sqrt(
width * height);
imagOut[yWave][xWave] -= (inputData[ySpace][xSpace] * sin(
2 * PI * ((1.0 * xWave * xSpace / width) + (1.0
* yWave * ySpace / height)))) / sqrt(
width * height);
amplitudeOut[yWave][xWave] = sqrt(
realOut[yWave][xWave] * realOut[yWave][xWave]
+ imagOut[yWave][xWave]
* imagOut[yWave][xWave]);
}
cout << realOut[yWave][xWave] << " + " << imagOut[yWave][xWave]
<< " i (" << amplitudeOut[yWave][xWave] << ")\n";
}
}
}
}
/*
Enter the size:
2
Enter the 2D elements
2 3
4 2
2.5 + 0.0 i
5.5 + 0.0 i
-0.5 + -1.8369701987210297E-16 i
0.5 + -3.0616169978683826E-16 i
2.5 + 0.0 i
-0.5 + -3.6739403974420594E-16 i
-0.5 + -1.8369701987210297E-16 i
-1.5 + -1.8369701987210297E-16 i

@ -0,0 +1,40 @@
#include<conio.h>
#include<iostream>
#include<math.h>
using namespace std;
int main(int argc, char **argv)
{
cout<<"Enter the dimension of the matrix:\n ";
int rowA;
cin>>rowA;
int colA;
cin>>colA;
cout<<"Enter the dimension of the other matrix:\n ";
int rowB;
cin>>rowB;
int colB;
cin>>colB;
if(colA == rowB)
{
cout<<"Matrices are multipilcable";
}
else
{
cout<<"Matrices are not multipilcable";
}
}
/*
Enter the dimension of the matrix:
2 4
Enter the dimension of the other matrix:
2 5
Matrices are not multipilcable
Enter the dimension of the matrix:
4 5
Enter the dimension of the other matrix:
5 6
Matrices are multipilcable

@ -0,0 +1,76 @@
#include<conio.h>
#include<iostream>
#include<math.h>
using namespace std;
double d = 0;
double det(int n, double mat[10][10]);
double det(int n, double mat[10][10])
{
double submat[10][10];
if (n == 2)
return ((mat[0][0] * mat[1][1]) - (mat[1][0] * mat[0][1]));
else
{
for (int c = 0; c < n; c++)
{
int subi = 0; //submatrix's i value
for (int i = 1; i < n; i++)
{
int subj = 0;
for (int j = 0; j < n; j++)
{
if (j == c)
continue;
submat[subi][subj] = mat[i][j];
subj++;
}
subi++;
}
d = d + (pow(-1, c) * mat[0][c] * det(n - 1, submat));
}
}
return d;
}
int main(int argc, char **argv)
{
cout << "Enter the dimension of the matrix:\n";
int n;
cin >> n;
double mat[10][10];
cout << "Enter the elements of the matrix:\n";
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> mat[j][i];
}
}
if (det(n, mat) != 0)
{
cout << "The given matrix is invertible";
}
else
{
cout << "The given matrix is not invertible";
}
}
/*
Enter the dimension of the matrix:
3
Enter the elements of the matrix:
1 2 3
4 5 6
7 8 9
The given matrix is not invertible
Enter the dimension of the matrix:
5
Enter the elements of the matrix:
1 2 3 4 5
6 7 8 9 0
0 9 8 7 6
5 4 3 2 1
1 3 5 7 9
The given matrix is invertible

@ -0,0 +1,54 @@
#include <iostream>
#include <conio.h>
using namespace std;
int main(int argc, char **argv)
{
cout<<"Enter the dimensions of the matrix: ";
int m, n;
cin>>m>>n;
double mat[m][n];
int zeros = 0;
cout<<"Enter the elements of the matrix: ";
for(int i=0; i<m; i++)
{
for(int j=0; j<n; j++)
{
cin>>mat[i][j];
if(mat[i][j] == 0)
{
zeros++;
}
}
}
if(zeros > (m*n)/2)
{
cout<<"The matrix is a sparse matrix";
}
else
{
cout<<"The matrix is not a sparse matrix";
}
}
/*
Enter the dimensions of the matrix:
3 3
Enter the elements of the matrix:
1 2 3
4 5 6
0 0 0
The matrix is not a sparse matrix
Enter the dimensions of the matrix:
3 3
Enter the elements of the matrix:
1 1 0
0 0 1
1 0 0
The matrix is a sparse matrix

@ -0,0 +1,65 @@
/*This is a C++ Program to compute the coefficients of the DFT (Discrete Fourier Transform) directly. In mathematics, the discrete Fourier transform (DFT) converts a finite list of equally spaced samples of a function into the list of coefficients of a finite combination of complex sinusoids, ordered by their frequencies, that has those same sample values. It can be said to convert the sampled function from its original domain (often time or position along a line) to the frequency domain.*/
#include<iostream>
#include<math.h>
using namespace std;
#define PI 3.14159265
class DFT_Coefficient
{
public:
double real, img;
DFT_Coefficient()
{
real = 0.0;
img = 0.0;
}
};
int main(int argc, char **argv)
{
int N = 10;
cout << "Calculation DFT Coefficients\n";
cout << "Enter the coefficient of simple linear function:\n";
cout << "ax + by = c\n";
double a, b, c;
cin >> a >> b >> c;
double function[N];
for (int i = 0; i < N; i++)
{
function[i] = (((a * (double) i) + (b * (double) i)) - c);
//System.out.print( " "+function[i] + " ");
}
cout << "Enter the max K value: ";
int k;
cin >> k;
double cosine[N];
double sine[N];
for (int i = 0; i < N; i++)
{
cosine[i] = cos((2 * i * k * PI) / N);
sine[i] = sin((2 * i * k * PI) / N);
}
DFT_Coefficient dft_val;
cout << "The coefficients are: ";
for (int i = 0; i < N; i++)
{
dft_val.real += function[i] * cosine[i];
dft_val.img += function[i] * sine[i];
}
cout << "(" << dft_val.real << ") - " << "(" << dft_val.img << " i)";
}
/*
Calculation DFT Coefficients
Enter the coefficient of simple linear funtion:
ax + by = c
1 2 3
Enter the max K value:
2
The coefficients are: (-15) - (-20.6457 i)
------------------
(program exited with code: 0)
Press return to continue

@ -0,0 +1,69 @@
#include<conio.h>
#include<iostream>
#include<math.h>
using namespace std;
double d = 0;
double det(int n, double mat[10][10]);
double det(int n, double mat[10][10])
{
double submat[10][10];
if (n == 2)
return ((mat[0][0] * mat[1][1]) - (mat[1][0] * mat[0][1]));
else
{
for (int c = 0; c < n; c++)
{
int subi = 0; //submatrix's i value
for (int i = 1; i < n; i++)
{
int subj = 0;
for (int j = 0; j < n; j++)
{
if (j == c)
continue;
submat[subi][subj] = mat[i][j];
subj++;
}
subi++;
}
d = d + (pow(-1, c) * mat[0][c] * det(n - 1, submat));
}
}
return d;
}
int main(int argc, char **argv)
{
cout << "Enter the dimension of the matrix:\n";
int n;
cin >> n;
double mat[10][10];
cout << "Enter the elements of the matrix:\n";
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> mat[j][i];
}
}
cout << "The determinant of the given matrix is: " << det(n, mat);
return 0;
}
/*
Enter the dimension of the matrix:
3
Enter the elements of the matrix:
3 5 2
8 4 8
2 4 7
The determinant of the given matrix is: -164
Enter the dimension of the matrix:
4
Enter the elements of the matrix:
9 5 2 5
9 5 3 7
6 5 4 8
1 5 3 7
The determinant of the given matrix is: 0

@ -0,0 +1,84 @@
/*This is a C++ Program to perform Discrete Fourier Transform using Naive approach. In mathematics, the discrete Fourier transform (DFT) converts a finite list of equally spaced samples of a function into the list of coefficients of a finite combination of complex sinusoids, ordered by their frequencies, that has those same sample values. It can be said to convert the sampled function from its original domain (often time or position along a line) to the frequency domain.*/
#include<iostream>
#include<math.h>
using namespace std;
#define PI 3.14159265
class DFT_Coefficient
{
public:
double real, img;
DFT_Coefficient()
{
real = 0.0;
img = 0.0;
}
};
int main(int argc, char **argv)
{
int N = 10;
cout << "Discrete Fourier Transform using naive method\n";
cout << "Enter the coefficient of simple linear function:\n";
cout << "ax + by = c\n";
double a, b, c;
cin >> a >> b >> c;
double function[N];
for (int i = 0; i < N; i++)
{
function[i] = (((a * (double) i) + (b * (double) i)) - c);
//System.out.print( " "+function[i] + " ");
}
cout << "Enter the max K value: ";
int k;
cin >> k;
double cosine[N];
double sine[N];
for (int i = 0; i < N; i++)
{
cosine[i] = cos((2 * i * k * PI) / N);
sine[i] = sin((2 * i * k * PI) / N);
}
DFT_Coefficient dft_val[k];
cout << "The coefficients are: ";
for (int j = 0; j < k; j++)
{
for (int i = 0; i < N; i++)
{
dft_val[j].real += function[i] * cosine[i];
dft_val[j].img += function[i] * sine[i];
}
cout << "(" << dft_val[j].real << ") - " << "(" << dft_val[j].img << " i)\n";
}
}
/*
Discrete Fourier Transform using naive method
Enter the coefficient of simple linear function:
ax + by = c
1 2 3
Enter the max K value: 20
The coefficients are:
(105) - (-1.03386e-005 i)
(105) - (-1.03386e-005 i)
(105) - (-1.03386e-005 i)
(105) - (-1.03386e-005 i)
(105) - (-1.03386e-005 i)
(105) - (-1.03386e-005 i)
(105) - (-1.03386e-005 i)
(105) - (-1.03386e-005 i)
(105) - (-1.03386e-005 i)
(105) - (-1.03386e-005 i)
(105) - (-1.03386e-005 i)
(105) - (-1.03386e-005 i)
(105) - (-1.03386e-005 i)
(105) - (-1.03386e-005 i)
(105) - (-1.03386e-005 i)
(105) - (-1.03386e-005 i)
(105) - (-1.03386e-005 i)
(105) - (-1.03386e-005 i)
(105) - (-1.03386e-005 i)
(105) - (-1.03386e-005 i)

@ -0,0 +1,73 @@
/*This is a C++ Program to perform Fast Fourier Transform. A fast Fourier transform (FFT) is an algorithm to compute the discrete Fourier transform (DFT) and its inverse. Fourier analysis converts time (or space) to frequency and vice versa; an FFT rapidly computes such transformations by factorizing the DFT matrix into a product of sparse (mostly zero) factors.*/
#include <iostream>
#include <complex>
#include <cmath>
#include <iterator>
using namespace std;
unsigned int bitReverse(unsigned int x, int log2n)
{
int n = 0;
int mask = 0x1;
for (int i = 0; i < log2n; i++)
{
n <<= 1;
n |= (x & 1);
x >>= 1;
}
return n;
}
const double PI = 3.1415926536;
template<class Iter_T>
void fft(Iter_T a, Iter_T b, int log2n)
{
typedef typename iterator_traits<iter_t>::value_type complex;
const complex J(0, 1);
int n = 1 << log2n;
for (unsigned int i = 0; i < n; ++i)
{
b[bitReverse(i, log2n)] = a[i];
}
for (int s = 1; s <= log2n; ++s)
{
int m = 1 << s;
int m2 = m >> 1;
complex w(1, 0);
complex wm = exp(-J * (PI / m2));
for (int j = 0; j < m2; ++j)
{
for (int k = j; k < n; k += m)
{
complex t = w * b[k + m2];
complex u = b[k];
b[k] = u + t;
b[k + m2] = u - t;
}
w *= wm;
}
}
}
int main(int argc, char **argv)
{
typedef complex cx;
cx a[] = { cx(0, 0), cx(1, 1), cx(3, 3), cx(4, 4), cx(4, 4), cx(3, 3), cx(
1, 1), cx(0, 0)
};
cx b[8];
fft(a, b, 3);
for (int i = 0; i < 8; ++i)
cout << b[i] << "\n";
}
/*
(16,16)
(-4.82843,-11.6569)
(0,0)
(-0.343146,0.828427)
(0,0)
(0.828427,-0.343146)
(0,0)
(-11.6569,-4.82843)

@ -0,0 +1,25 @@
#include <iostream>
#include <stdlib.h>
using namespace std;
int main(int argc, char **argv)
{
cout << "Enter the number of dice: ";
int n;
cin >> n;
cout << "The values on dice are: ( ";
for (int i = 0; i < n; i++)
cout << (rand() % 6) + 1<<" ";
cout<<")";
}
/*
Enter the number of dice: 5
The values on dice are: ( 6 6 5 5 6 )
Enter the number of dice: 1
The values on dice are: ( 6 )
Enter the number of dice: 3
The values on dice are: ( 6 6 5 )

@ -0,0 +1,74 @@
#include<conio.h>
#include<iostream>
#include<math.h>
using namespace std;
double d = 0;
double det(int n, double mat[10][10]);
double det(int n, double mat[10][10])
{
double submat[10][10];
if (n == 2)
return ((mat[0][0] * mat[1][1]) - (mat[1][0] * mat[0][1]));
else
{
for (int c = 0; c < n; c++)
{
int subi = 0; //submatrix's i value
for (int i = 1; i < n; i++)
{
int subj = 0;
for (int j = 0; j < n; j++)
{
if (j == c)
continue;
submat[subi][subj] = mat[i][j];
subj++;
}
subi++;
}
d = d + (pow(-1, c) * mat[0][c] * det(n - 1, submat));
}
}
return d;
}
int main(int argc, char **argv)
{
cout << "Enter the number of vectors:\n";
int n;
cin >> n;
double mat[10][10];
cout << "Enter the vectors one by one:\n";
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> mat[j][i];
}
}
d = det(n, mat);
if (d != 0)
cout << "The vectors forms the basis of R" << n
<< " as the determinant is non-zero";
else
cout << "The vectors doesn't form the basis of R" << n
<< " as the determinant is zero";
}
/*
Enter the number of vectors:
3
Enter the vectors one by one:
1 2 3
2 3 4
3 4 5
The vectors doesn't form the basis of R3 as the determinant is zero
Enter the number of vectors:
4
Enter the vectors one by one:
2 3 5 8
1 6 2 9
3 4 2 7
2 5 3 9
The vectors forms the basis of R4 as the determinant is non-zero

@ -0,0 +1,137 @@
/*
* C++ Program to Find Closest Pair of Points in an Array
*/
#include <iostream>
#include <cfloat>
#include <cstdlib>
#include <cmath>
using namespace std;
/*
* Point Declaration
*/
struct Point
{
int x, y;
};
/*
* sort array of points according to X coordinate
*/
int compareX(const void* a, const void* b)
{
Point *p1 = (Point *)a, *p2 = (Point *)b;
return (p1->x - p2->x);
}
/*
* sort array of points according to Y coordinate
*/
int compareY(const void* a, const void* b)
{
Point *p1 = (Point *)a, *p2 = (Point *)b;
return (p1->y - p2->y);
}
/*
* find the distance between two points
*/
float dist(Point p1, Point p2)
{
return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
/*
* return the smallest distance between two points
*/
float small_dist(Point P[], int n)
{
float min = FLT_MAX;
for (int i = 0; i < n; ++i)
{
for (int j = i + 1; j < n; ++j)
{
if (dist(P[i], P[j]) < min)
min = dist(P[i], P[j]);
}
}
return min;
}
/*
* find the distance beween the closest points of strip of given size
*/
float stripClosest(Point strip[], int size, float d)
{
float min = d;
for (int i = 0; i < size; ++i)
{
for (int j = i + 1; j < size && (strip[j].y - strip[i].y) < min; ++j)
{
if (dist(strip[i],strip[j]) < min)
min = dist(strip[i], strip[j]);
}
}
return min;
}
/*
* find the smallest distance.
*/
float closestUtil(Point Px[], Point Py[], int n)
{
if (n <= 3)
return small_dist(Px, n);
int mid = n / 2;
Point midPoint = Px[mid];
Point Pyl[mid + 1];
Point Pyr[n - mid - 1];
int li = 0, ri = 0;
for (int i = 0; i < n; i++)
{
if (Py[i].x <= midPoint.x)
Pyl[li++] = Py[i];
else
Pyr[ri++] = Py[i];
}
float dl = closestUtil(Px, Pyl, mid);
float dr = closestUtil(Px + mid, Pyr, n-mid);
float d = min(dl, dr);
Point strip[n];
int j = 0;
for (int i = 0; i < n; i++)
{
if (abs(Py[i].x - midPoint.x) < d)
strip[j] = Py[i], j++;
}
return min(d, stripClosest(strip, j, d));
}
/*
* finds the smallest distance
*/
float closest(Point P[], int n)
{
Point Px[n];
Point Py[n];
for (int i = 0; i < n; i++)
{
Px[i] = P[i];
Py[i] = P[i];
}
qsort(Px, n, sizeof(Point), compareX);
qsort(Py, n, sizeof(Point), compareY);
return closestUtil(Px, Py, n);
}
/*
* Main
*/
int main()
{
Point P[] = {{2, 3}, {12, 30}, {40, 50}, {5, 1}, {12, 10}, {3, 4}};
int n = sizeof(P) / sizeof(P[0]);
cout << "The smallest distance is " << closest(P, n);
return 0;
}
/*
The smallest distance is 1.41421
------------------
(program exited with code: 1)
Press return to continue

@ -0,0 +1,83 @@
/*
* C++ Program to Find Factorial of Large Numbers
*/
#include <cstring>
#include <iostream>
#include <cstdlib>
#define ll long long
using namespace std;
int fact[101][200] = {0};
/*
* Find Factorial of Large Numbers
* fact[i][0] is used to store the number of digits
*/
void fact_large(int n)
{
int i;
fact[1][0] = 1;
fact[1][1] = 1;
if (fact[n][0] == 0)
{
for (i = n - 1; i > 0 ; i--)
{
if (fact[i][0] != 0)
break;
}
for ( ; i < n; i++)
{
int j = 1;
int carry = 0;
int len = fact[i][0];
while (len--)
{
int temp = (i + 1) * fact[i][j] + carry;
fact[i + 1][j] = temp % 10;
carry = temp / 10;
j++;
}
while (carry > 0)
{
fact[i + 1][j] = carry % 10;
carry /= 10;
j++;
}
fact[i + 1][0] = j - 1;
}
}
for (i = fact[n][0]; i > 0; i--)
{
cout << fact[n][i];
}
cout<<endl;
}
/*
* Main
*/
int main()
{
int n;
while (1)
{
cout<<"Enter interger to compute factorial(0 to exit): ";
cin>>n;
if (n == 0)
break;
fact_large(n);
}
return 0;
}
/*
Enter interger to compute factorial(0 to exit): 100
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
Enter interger to compute factorial(0 to exit): 50
30414093201713378043612608166064768844377641568960512000000000000
Enter interger to compute factorial(0 to exit): 72
61234458376886086861524070385274672740778091784697328983823014963978384987221689274204160000000000000000
Enter interger to compute factorial(0 to exit): 0
------------------
(program exited with code: 1)
Press return to continue

@ -0,0 +1,55 @@
/*
* C++ Program to Find Factorial of a Number using Dynamic Programming
*/
#include <cstring>
#include <iostream>
#include <cstdlib>
#define ll long long
using namespace std;
int result[1000] = {0};
/*
* Find Factorial of a Number using Dynamic Programming
*/
ll fact_dp(int n)
{
if (n >= 0)
{
result[0] = 1;
for (int i = 1; i <= n; ++i)
{
result[i] = i * result[i - 1];
}
return result[n];
}
}
/*
* Main
*/
int main()
{
int n;
while (1)
{
cout<<"Enter interger to compute factorial(0 to exit): ";
cin>>n;
if (n == 0)
break;
cout<<fact_dp(n)<<endl;
}
return 0;
}
/*
Enter interger to compute factorial(0 to exit): 10
3628800
Enter interger to compute factorial(0 to exit): 20
2432902008176640000
Enter interger to compute factorial(0 to exit): 15
1307674368000
Enter interger to compute factorial(0 to exit): 0
------------------
(program exited with code: 1)
Press return to continue

@ -0,0 +1,49 @@
/*
* C++ Program to Find Factorial of a Number using Iteration
*/
#include <cstring>
#include <iostream>
#include <cstdlib>
#define ll long long
using namespace std;
/*
* Find Factorial of a Number using Iteration
*/
ll fact_iter(int n)
{
ll result = 1;
for (int i = 1; i <= n; i++)
{
result *= i;
}
return result;
}
/*
* Main
*/
int main()
{
int n;
while (1)
{
cout<<"Enter interger to compute factorial(0 to exit): ";
cin>>n;
if (n == 0)
break;
cout<<fact_iter(n)<<endl;
}
return 0;
}
/*
Enter interger to compute factorial(0 to exit): 10
3628800
Enter interger to compute factorial(0 to exit): 20
2432902008176640000
Enter interger to compute factorial(0 to exit): 15
1307674368000
Enter interger to compute factorial(0 to exit): 0
------------------
(program exited with code: 1)
Press return to continue

@ -0,0 +1,47 @@
/*
* C++ Program to Find Factorial of a Number using Recursion
*/
#include <cstring>
#include <iostream>
#include <cstdlib>
#define ll long long
using namespace std;
/*
* Find Factorial of a Number using Recursion
*/
ll fact_recur(int n)
{
if (n == 0 || n == 1)
return 1;
else
return n * fact_recur(n - 1);
}
/*
* Main
*/
int main()
{
int n;
while (1)
{
cout<<"Enter interger to compute factorial(0 to exit): ";
cin>>n;
if (n == 0)
break;
cout<<fact_recur(n)<<endl;
}
return 0;
}
/*
Enter interger to compute factorial(0 to exit): 10
3628800
Enter interger to compute factorial(0 to exit): 20
2432902008176640000
Enter interger to compute factorial(0 to exit): 15
1307674368000
Enter interger to compute factorial(0 to exit): 0
------------------
(program exited with code: 1)
Press return to continue

@ -0,0 +1,71 @@
/*
* C++ Program to Find Fibonacci Numbers using Dynamic Programming
*/
#include <cstring>
#include <iostream>
#include <cstdlib>
#define ll long long
using namespace std;
ll fib[1000] = {0};
/*
* Fibonacci Numbers using Dp
*/
ll fibo_dp(int n)
{
fib[1] = 1;
fib[2] = 1;
if (fib[n] == 0)
{
for (int j = 3; j <= n; ++j)
{
if (fib[n] == 0)
fib[j] = fib[j - 1] + fib[j - 2];
else
continue;
}
}
return fib[n];
}
/*
* Main
*/
int main()
{
int n;
while (1)
{
cout<<"Enter the integer n to find nth fibonnaci no.(0 to exit): ";
cin>>n;
if (n == 0)
break;
cout<<fibo_dp(n)<<endl;
}
return 0;
}
/*
Enter the integer n to find nth fibonnaci no.(0 to exit): 10
55
Enter the integer n to find nth fibonnaci no.(0 to exit): 9
34
Enter the integer n to find nth fibonnaci no.(0 to exit): 8
21
Enter the integer n to find nth fibonnaci no.(0 to exit): 7
13
Enter the integer n to find nth fibonnaci no.(0 to exit): 6
8
Enter the integer n to find nth fibonnaci no.(0 to exit): 5
5
Enter the integer n to find nth fibonnaci no.(0 to exit): 4
3
Enter the integer n to find nth fibonnaci no.(0 to exit): 3
2
Enter the integer n to find nth fibonnaci no.(0 to exit): 2
1
Enter the integer n to find nth fibonnaci no.(0 to exit): 0
------------------
(program exited with code: 1)
Press return to continue

@ -0,0 +1,68 @@
/*
* C++ Program to Find Fibonacci Numbers using Iteration
*/
#include <cstring>
#include <iostream>
#include <cstdlib>
#define ll long long
using namespace std;
/*
* Iterative function to find Fibonacci Numbers
*/
ll fibo_iter(int n)
{
int previous = 1;
int current = 1;
int next = 1;
for (int i = 3; i <= n; ++i)
{
next = current + previous;
previous = current;
current = next;
}
return next;
}
/*
* Main
*/
int main()
{
int n;
while (1)
{
cout<<"Enter the integer n to find nth fibonnaci no.(0 to exit): ";
cin>>n;
if (n == 0)
break;
cout<<fibo_iter(n)<<endl;
}
return 0;
}
/*
Enter the integer n to find nth fibonnaci no.(0 to exit): 1
1
Enter the integer n to find nth fibonnaci no.(0 to exit): 2
1
Enter the integer n to find nth fibonnaci no.(0 to exit): 3
2
Enter the integer n to find nth fibonnaci no.(0 to exit): 4
3
Enter the integer n to find nth fibonnaci no.(0 to exit): 5
5
Enter the integer n to find nth fibonnaci no.(0 to exit): 6
8
Enter the integer n to find nth fibonnaci no.(0 to exit): 7
13
Enter the integer n to find nth fibonnaci no.(0 to exit): 8
21
Enter the integer n to find nth fibonnaci no.(0 to exit): 9
34
Enter the integer n to find nth fibonnaci no.(0 to exit): 10
55
Enter the integer n to find nth fibonnaci no.(0 to exit): 0
------------------
(program exited with code: 1)
Press return to continue

@ -0,0 +1,92 @@
/*
* C++ Program to Find Fibonacci Numbers using Matrix Exponentiation
*/
#include <cstring>
#include <iostream>
#include <cstdlib>
#define ll long long
using namespace std;
/*
* function to multiply two matrices
*/
void multiply(ll F[2][2], ll M[2][2])
{
ll x = F[0][0] * M[0][0] + F[0][1] * M[1][0];
ll y = F[0][0] * M[0][1] + F[0][1] * M[1][1];
ll z = F[1][0] * M[0][0] + F[1][1] * M[1][0];
ll w = F[1][0] * M[0][1] + F[1][1] * M[1][1];
F[0][0] = x;
F[0][1] = y;
F[1][0] = z;
F[1][1] = w;
}
/*
* function to calculate power of a matrix
*/
void power(ll F[2][2], int n)
{
if (n == 0 || n == 1)
return;
ll M[2][2] = {{1,1},{1,0}};
power(F, n / 2);
multiply(F, F);
if (n % 2 != 0)
multiply(F, M);
}
/*
* function that returns nth Fibonacci number
*/
ll fibo_matrix(ll n)
{
ll F[2][2] = {{1,1},{1,0}};
if (n == 0)
return 0;
power(F, n - 1);
return F[0][0];
}
/*
* Main
*/
int main()
{
int n;
while (1)
{
cout<<"Enter the integer n to find nth fibonnaci no.(0 to exit): ";
cin>>n;
if (n == 0)
break;
cout<<fibo_matrix(n)<<endl;
}
return 0;
}
/*
Enter the integer n to find nth fibonnaci no.(0 to exit): 1
1
Enter the integer n to find nth fibonnaci no.(0 to exit): 2
1
Enter the integer n to find nth fibonnaci no.(0 to exit): 3
2
Enter the integer n to find nth fibonnaci no.(0 to exit): 4
3
Enter the integer n to find nth fibonnaci no.(0 to exit): 5
5
Enter the integer n to find nth fibonnaci no.(0 to exit): 6
8
Enter the integer n to find nth fibonnaci no.(0 to exit): 7
13
Enter the integer n to find nth fibonnaci no.(0 to exit): 8
21
Enter the integer n to find nth fibonnaci no.(0 to exit): 9
34
Enter the integer n to find nth fibonnaci no.(0 to exit): 10
55
Enter the integer n to find nth fibonnaci no.(0 to exit): 0
------------------
(program exited with code: 1)
Press return to continue

@ -0,0 +1,62 @@
/*
* C++ Program to Find Fibonacci Numbers using Recursion
*/
#include <cstring>
#include <iostream>
#include <cstdlib>
#define ll long long
using namespace std;
/*
* Recursive function to find Fibonnaci Numbers
*/
ll fibo_recur(int n)
{
if (n == 1 || n == 2)
return 1;
else
return fibo_recur(n - 1) + fibo_recur(n - 2);;
}
/*
* Main
*/
int main()
{
int n;
while (1)
{
cout<<"Enter the integer n to find nth fibonnaci no.(0 to exit): ";
cin>>n;
if (n == 0)
break;
cout<<fibo_recur(n)<<endl;
}
return 0;
}
/*
Enter the integer n to find nth fibonnaci no.(0 to exit): 1
1
Enter the integer n to find nth fibonnaci no.(0 to exit): 2
1
Enter the integer n to find nth fibonnaci no.(0 to exit): 3
2
Enter the integer n to find nth fibonnaci no.(0 to exit): 4
3
Enter the integer n to find nth fibonnaci no.(0 to exit): 5
5
Enter the integer n to find nth fibonnaci no.(0 to exit): 6
8
Enter the integer n to find nth fibonnaci no.(0 to exit): 7
13
Enter the integer n to find nth fibonnaci no.(0 to exit): 8
21
Enter the integer n to find nth fibonnaci no.(0 to exit): 9
34
Enter the integer n to find nth fibonnaci no.(0 to exit): 10
55
Enter the integer n to find nth fibonnaci no.(0 to exit): 0
------------------
(program exited with code: 1)
Press return to continue

@ -0,0 +1,35 @@
/*This is a C++ Program to find GCD of two numbers using Recursive Euclid Algorithm. In mathematics, the Euclidean algorithm, or Euclids algorithm, is a method for computing the greatest common divisor (GCD) of two (usually positive) integers, also known as the greatest common factor (GCF) or highest common factor (HCF). It is named after the Greek mathematician Euclid, who described it in Books VII and X of his Elements.
The GCD of two positive integers is the largest integer that divides both of them without leaving a remainder (the GCD of two integers in general is defined in a more subtle way).
In its simplest form, Euclids algorithm starts with a pair of positive integers, and forms a new pair that consists of the smaller number and the difference between the larger and smaller numbers. The process repeats until the numbers in the pair are equal. That number then is the greatest common divisor of the original pair of integers.
The main principle is that the GCD does not change if the smaller number is subtracted from the larger number. For example, the GCD of 252 and 105 is exactly the GCD of 147 (= 252 105) and 105. Since the larger of the two numbers is reduced, repeating this process gives successively smaller numbers, so this repetition will necessarily stop sooner or later when the numbers are equal (if the process is attempted once more, one of the numbers will become 0).*/
#include<iostream>
#include<conio.h>
#include<stdlib.h>
using namespace std;
int gcd(int u, int v)
{
return (v != 0) ? gcd(v, u % v) : u;
}
int main(void)
{
int num1, num2, result;
cout << "Enter two numbers to find GCD using Euclidean algorithm: ";
cin >> num1 >> num2;
result = gcd(num1, num2);
if (gcd)
cout << "\nThe GCD of " << num1 << " and " << num2 << " is: " << result
<< endl;
else
cout << "\nInvalid input!!!\n";
return 0;
}
/*
Enter two numbers to find GCD using Euclidean algorithm: 12 30
The GCD of 12 and 30 is: 6

@ -0,0 +1,565 @@
#if !defined(MATRIX_H)
#define MATRIX_H
#include <stdio.h>
#include <iostream>
#include <tchar.h>
#include <math.h>
#include <stdlib.h>
class CMatrix
{
private:
int m_rows;
int m_cols;
char m_name[128];
CMatrix();
public:
double **m_pData;
CMatrix(const char *name, int rows, int cols) :
m_rows(rows), m_cols(cols)
{
strcpy(m_name, name);
m_pData = new double*[m_rows];
for (int i = 0; i < m_rows; i++)
m_pData[i] = new double[m_cols];
for (int i = 0; i < m_rows; i++)
{
for (int j = 0; j < m_cols; j++)
{
m_pData[i][j] = 0.0;
}
}
}
CMatrix(const CMatrix &other)
{
strcpy(m_name, other.m_name);
m_rows = other.m_rows;
m_cols = other.m_cols;
m_pData = new double*[m_rows];
for (int i = 0; i < m_rows; i++)
m_pData[i] = new double[m_cols];
for (int i = 0; i < m_rows; i++)
{
for (int j = 0; j < m_cols; j++)
{
m_pData[i][j] = other.m_pData[i][j];
}
}
}
~CMatrix()
{
for (int i = 0; i < m_rows; i++)
delete[] m_pData[i];
delete[] m_pData;
m_rows = m_cols = 0;
}
void SetName(const char *name)
{
strcpy(m_name, name);
}
const char* GetName() const
{
return m_name;
}
void GetInput()
{
std::cin >> *this;
}
void FillSimulatedInput()
{
static int factor1 = 1, factor2 = 2;
std::cout << "\n\nEnter Input For Matrix : " << m_name << " Rows: "
<< m_rows << " Cols: " << m_cols << "\n";
for (int i = 0; i < m_rows; i++)
{
for (int j = 0; j < m_cols; j++)
{
std::cout << "Input For Row: " << i + 1 << " Col: " << j
+ 1 << " = ";
int data = ((i + 1) * factor1) + (j + 1) * factor2;
m_pData[i][j] = data / 10.2;
std::cout << m_pData[i][j] << "\n";
factor1 += (rand() % 4);
factor2 += (rand() % 3);
}
std::cout << "\n";
}
std::cout << "\n";
}
double Determinant()
{
double det = 0;
double **pd = m_pData;
switch (m_rows)
{
case 2:
{
det = pd[0][0] * pd[1][1] - pd[0][1] * pd[1][0];
return det;
}
break;
case 3:
{
/***
a b c
d e f
g h i
a b c a b c
d e f d e f
g h i g h i
// det (A) = aei + bfg + cdh - afh - bdi - ceg.
***/
double a = pd[0][0];
double b = pd[0][1];
double c = pd[0][2];
double d = pd[1][0];
double e = pd[1][1];
double f = pd[1][2];
double g = pd[2][0];
double h = pd[2][1];
double i = pd[2][2];
double det = (a * e * i + b * f * g + c * d * h);
det = det - a * f * h;
det = det - b * d * i;
det = det - c * e * g;
return det;
}
break;
case 4:
{
CMatrix *temp[4];
for (int i = 0; i < 4; i++)
temp[i] = new CMatrix("", 3, 3);
for (int k = 0; k < 4; k++)
{
for (int i = 1; i < 4; i++)
{
int j1 = 0;
for (int j = 0; j < 4; j++)
{
if (k == j)
continue;
temp[k]->m_pData[i - 1][j1++]
= this->m_pData[i][j];
}
}
}
double det = this->m_pData[0][0] * temp[0]->Determinant()
- this->m_pData[0][1] * temp[1]->Determinant()
+ this->m_pData[0][2] * temp[2]->Determinant()
- this->m_pData[0][3] * temp[3]->Determinant();
return det;
}
break;
case 5:
{
CMatrix *temp[5];
for (int i = 0; i < 5; i++)
temp[i] = new CMatrix("", 4, 4);
for (int k = 0; k < 5; k++)
{
for (int i = 1; i < 5; i++)
{
int j1 = 0;
for (int j = 0; j < 5; j++)
{
if (k == j)
continue;
temp[k]->m_pData[i - 1][j1++]
= this->m_pData[i][j];
}
}
}
double det = this->m_pData[0][0] * temp[0]->Determinant()
- this->m_pData[0][1] * temp[1]->Determinant()
+ this->m_pData[0][2] * temp[2]->Determinant()
- this->m_pData[0][3] * temp[3]->Determinant()
+ this->m_pData[0][4] * temp[4]->Determinant();
return det;
}
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
default:
{
int DIM = m_rows;
CMatrix **temp = new CMatrix*[DIM];
for (int i = 0; i < DIM; i++)
temp[i] = new CMatrix("", DIM - 1, DIM - 1);
for (int k = 0; k < DIM; k++)
{
for (int i = 1; i < DIM; i++)
{
int j1 = 0;
for (int j = 0; j < DIM; j++)
{
if (k == j)
continue;
temp[k]->m_pData[i - 1][j1++]
= this->m_pData[i][j];
}
}
}
double det = 0;
for (int k = 0; k < DIM; k++)
{
if ((k % 2) == 0)
det = det + (this->m_pData[0][k]
* temp[k]->Determinant());
else
det = det - (this->m_pData[0][k]
* temp[k]->Determinant());
}
for (int i = 0; i < DIM; i++)
delete temp[i];
delete[] temp;
return det;
}
break;
}
}
CMatrix& operator =(const CMatrix &other)
{
if (this->m_rows != other.m_rows || this->m_cols != other.m_cols)
{
std::cout
<< "WARNING: Assignment is taking place with by changing the number of rows and columns of the matrix";
}
for (int i = 0; i < m_rows; i++)
delete[] m_pData[i];
delete[] m_pData;
m_rows = m_cols = 0;
strcpy(m_name, other.m_name);
m_rows = other.m_rows;
m_cols = other.m_cols;
m_pData = new double*[m_rows];
for (int i = 0; i < m_rows; i++)
m_pData[i] = new double[m_cols];
for (int i = 0; i < m_rows; i++)
{
for (int j = 0; j < m_cols; j++)
{
m_pData[i][j] = other.m_pData[i][j];
}
}
return *this;
}
CMatrix CoFactor()
{
CMatrix cofactor("COF", m_rows, m_cols);
if (m_rows != m_cols)
return cofactor;
if (m_rows < 2)
return cofactor;
else if (m_rows == 2)
{
cofactor.m_pData[0][0] = m_pData[1][1];
cofactor.m_pData[0][1] = -m_pData[1][0];
cofactor.m_pData[1][0] = -m_pData[0][1];
cofactor.m_pData[1][1] = m_pData[0][0];
return cofactor;
}
else if (m_rows >= 3)
{
int DIM = m_rows;
CMatrix ***temp = new CMatrix**[DIM];
for (int i = 0; i < DIM; i++)
temp[i] = new CMatrix*[DIM];
for (int i = 0; i < DIM; i++)
for (int j = 0; j < DIM; j++)
temp[i][j] = new CMatrix("", DIM - 1, DIM - 1);
for (int k1 = 0; k1 < DIM; k1++)
{
for (int k2 = 0; k2 < DIM; k2++)
{
int i1 = 0;
for (int i = 0; i < DIM; i++)
{
int j1 = 0;
for (int j = 0; j < DIM; j++)
{
if (k1 == i || k2 == j)
continue;
temp[k1][k2]->m_pData[i1][j1++]
= this->m_pData[i][j];
}
if (k1 != i)
i1++;
}
}
}
bool flagPositive = true;
for (int k1 = 0; k1 < DIM; k1++)
{
flagPositive = ((k1 % 2) == 0);
for (int k2 = 0; k2 < DIM; k2++)
{
if (flagPositive == true)
{
cofactor.m_pData[k1][k2]
= temp[k1][k2]->Determinant();
flagPositive = false;
}
else
{
cofactor.m_pData[k1][k2]
= -temp[k1][k2]->Determinant();
flagPositive = true;
}
}
}
for (int i = 0; i < DIM; i++)
for (int j = 0; j < DIM; j++)
delete temp[i][j];
for (int i = 0; i < DIM; i++)
delete[] temp[i];
delete[] temp;
}
return cofactor;
}
CMatrix Adjoint()
{
CMatrix cofactor("COF", m_rows, m_cols);
CMatrix adj("ADJ", m_rows, m_cols);
if (m_rows != m_cols)
return adj;
cofactor = this->CoFactor();
// adjoint is transpose of a cofactor of a matrix
for (int i = 0; i < m_rows; i++)
{
for (int j = 0; j < m_cols; j++)
{
adj.m_pData[j][i] = cofactor.m_pData[i][j];
}
}
return adj;
}
CMatrix Transpose()
{
CMatrix trans("TR", m_cols, m_rows);
for (int i = 0; i < m_rows; i++)
{
for (int j = 0; j < m_cols; j++)
{
trans.m_pData[j][i] = m_pData[i][j];
}
}
return trans;
}
CMatrix Inverse()
{
CMatrix cofactor("COF", m_rows, m_cols);
CMatrix inv("INV", m_rows, m_cols);
if (m_rows != m_cols)
return inv;
// to find out Determinant
double det = Determinant();
cofactor = this->CoFactor();
// inv = transpose of cofactor / Determinant
for (int i = 0; i < m_rows; i++)
{
for (int j = 0; j < m_cols; j++)
{
inv.m_pData[j][i] = cofactor.m_pData[i][j] / det;
}
}
return inv;
}
CMatrix operator +(const CMatrix &other)
{
if (this->m_rows != other.m_rows || this->m_cols != other.m_cols)
{
std::cout
<< "Addition could not take place because number of rows and columns are different between the two matrices";
return *this;
}
CMatrix result("", m_rows, m_cols);
for (int i = 0; i < m_rows; i++)
{
for (int j = 0; j < m_cols; j++)
{
result.m_pData[i][j] = this->m_pData[i][j]
+ other.m_pData[i][j];
}
}
return result;
}
CMatrix operator -(const CMatrix &other)
{
if (this->m_rows != other.m_rows || this->m_cols != other.m_cols)
{
std::cout
<< "Subtraction could not take place because number of rows and columns are different between the two matrices";
return *this;
}
CMatrix result("", m_rows, m_cols);
for (int i = 0; i < m_rows; i++)
{
for (int j = 0; j < m_cols; j++)
{
result.m_pData[i][j] = this->m_pData[i][j]
- other.m_pData[i][j];
}
}
return result;
}
CMatrix operator *(const CMatrix &other)
{
if (this->m_cols != other.m_rows)
{
std::cout
<< "Multiplication could not take place because number of columns of 1st Matrix and number of rows in 2nd Matrix are different";
return *this;
}
CMatrix result("", this->m_rows, other.m_cols);
for (int i = 0; i < this->m_rows; i++)
{
for (int j = 0; j < other.m_cols; j++)
{
for (int k = 0; k < this->m_cols; k++)
{
result.m_pData[i][j] += this->m_pData[i][k]
* other.m_pData[k][j];
}
}
}
return result;
}
bool operator ==(const CMatrix &other)
{
if (this->m_rows != other.m_rows || this->m_cols != other.m_cols)
{
std::cout
<< "Comparision could not take place because number of rows and columns are different between the two matrices";
return false;
}
CMatrix result("", m_rows, m_cols);
bool bEqual = true;
for (int i = 0; i < m_rows; i++)
{
for (int j = 0; j < m_cols; j++)
{
if (this->m_pData[i][j] != other.m_pData[i][j])
bEqual = false;
}
}
return bEqual;
}
friend std::istream& operator >>(std::istream &is, CMatrix &m);
friend std::ostream& operator <<(std::ostream &os, const CMatrix &m);
};
std::istream& operator >>(std::istream &is, CMatrix &m)
{
std::cout << "\n\nEnter Input For Matrix : " << m.m_name << " Rows: "
<< m.m_rows << " Cols: " << m.m_cols << "\n";
for (int i = 0; i < m.m_rows; i++)
{
for (int j = 0; j < m.m_cols; j++)
{
std::cout << "Input For Row: " << i + 1 << " Col: " << j + 1
<< " = ";
is >> m.m_pData[i][j];
}
std::cout << "\n";
}
std::cout << "\n";
return is;
}
std::ostream& operator <<(std::ostream &os, const CMatrix &m)
{
os << "\n\nMatrix : " << m.m_name << " Rows: " << m.m_rows << " Cols: "
<< m.m_cols << "\n\n";
for (int i = 0; i < m.m_rows; i++)
{
os << " | ";
for (int j = 0; j < m.m_cols; j++)
{
char buf[32];
double data = m.m_pData[i][j];
if (m.m_pData[i][j] > -0.00001 && m.m_pData[i][j] < 0.00001)
data = 0;
sprintf(buf, "%10.2lf ", data);
os << buf;
}
os << "|\n";
}
os << "\n\n";
return os;
}
#endif
int main()
{
CMatrix a("A", 5, 5);
//std::cin >> a;
a.FillSimulatedInput();
CMatrix aadj = a.Inverse();
std::cout << a;
std::cout << aadj;
CMatrix unit = (a * aadj);
unit.SetName("A * A-Inv");
std::cout << unit;
}
/*
Enter Input For Matrix :
A Rows: 5
Cols: 5
Input For Row: 1 Col: 1 = 0.294118
Input For Row: 1 Col: 2 = 0.980392
Input For Row: 1 Col: 3 = 1.86275
Input For Row: 1 Col: 4 = 2.84314
Input For Row: 1 Col: 5 = 3.62745
Input For Row: 2 Col: 1 = 2.54902
Input For Row: 2 Col: 2 = 3.92157
Input For Row: 2 Col: 3 = 5.09804
Input For Row: 2 Col: 4 = 7.05882
Input For Row: 2 Col: 5 = 9.80392
Input For Row: 3 Col: 1 = 6.66667
Input For Row: 3 Col: 2 = 8.92157
Input For Row: 3 Col: 3 = 10.8824
Input For Row: 3 Col: 4 = 12.6471
Input For Row: 3 Col: 5 = 15.3922
Input For Row: 4 Col: 1 = 12.0588
Input For Row: 4 Col: 2 = 15.098
Input For Row: 4 Col: 3 = 18.1373
Input For Row: 4 Col: 4 = 20.7843
Input For Row: 4 Col: 5 = 24.4118
Input For Row: 5 Col: 1 = 21.1765
Input For Row: 5 Col: 2 = 24.7059
Input For Row: 5 Col: 3 = 27.7451
Input For Row: 5 Col: 4 = 31.0784
Input For Row: 5 Col: 5 = 34.3137
Matrix : A Rows: 5 Cols: 5
| 0.29 0.98 1.86 2.84 3.63 |
| 2.55 3.92 5.10 7.06 9.80 |
| 6.67 8.92 10.88 12.65 15.39 |
| 12.06 15.10 18.14 20.78 24.41 |
| 21.18 24.71 27.75 31.08 34.31 |
Matrix : INV Rows: 5 Cols: 5
| -0.93 0.80 -3.74 2.86 -0.49 |
| 0.37 -0.32 5.35 -4.91 1.14 |
| -0.78 -0.93 -1.46 2.96 -1.10 |
| 2.37 -0.10 0.25 -1.65 0.84 |
| -1.21 0.57 -0.58 0.87 -0.36 |
Matrix : A * A-Inv Rows: 5 Cols: 5
| 1.00 0.00 0.00 0.00 0.00 |
| 0.00 1.00 0.00 0.00 0.00 |
| 0.00 0.00 1.00 0.00 0.00 |
| 0.00 0.00 0.00 1.00 0.00 |
| 0.00 0.00 0.00 0.00 1.00 |

@ -0,0 +1,109 @@
#include <iostream>
#include <list>
using namespace std;
// This class represents a directed graph using adjacency list representation
class Graph
{
int V; // No. of vertices
list<int> *adj; // Pointer to an array containing adjacency lists
public:
Graph(int V); // Constructor
void addEdge(int v, int w); // function to add an edge to graph
bool isReachable(int s, int d); // returns true if there is a path from s to d
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int> [V];
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to vs list.
}
// A BFS based function to check whether d is reachable from s.
bool Graph::isReachable(int s, int d)
{
// Base case
if (s == d)
return true;
// Mark all the vertices as not visited
bool *visited = new bool[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Create a queue for BFS
list<int> queue;
// Mark the current node as visited and enqueue it
visited[s] = true;
queue.push_back(s);
// it will be used to get all adjacent vertices of a vertex
list<int>::iterator i;
while (!queue.empty())
{
// Dequeue a vertex from queue and print it
s = queue.front();
queue.pop_front();
// Get all adjacent vertices of the dequeued vertex s
// If a adjacent has not been visited, then mark it visited
// and enqueue it
for (i = adj[s].begin(); i != adj[s].end(); ++i)
{
// If this adjacent node is the destination node, then return true
if (*i == d)
return true;
// Else, continue to do BFS
if (!visited[*i])
{
visited[*i] = true;
queue.push_back(*i);
}
}
}
return false;
}
// Driver program to test methods of graph class
int main()
{
// Create a graph given in the above diagram
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
cout << "Enter the source and destination vertices: (0-3)";
int u, v;
cin >> u >> v;
if (g.isReachable(u, v))
cout << "\nThere is a path from " << u << " to " << v;
else
cout << "\nThere is no path from " << u << " to " << v;
int temp;
temp = u;
u = v;
v = temp;
if (g.isReachable(u, v))
cout << "\nThere is a path from " << u << " to " << v;
else
cout << "\nThere is no path from " << u << " to " << v;
return 0;
}
/*
Enter the source and destination vertices: (0-3)
1 3
There is a path from 1 to 3
There is no path from 3 to 1
Enter the source and destination vertices: (0-3)
2 3
There is a path from 2 to 3
There is no path from 3 to 2

@ -0,0 +1,57 @@
#include<iostream>
#include<conio.h>
#include<stdlib.h>
using namespace std;
int gcd(int x, int y)
{
int r = 0, a, b;
a = (x > y) ? x : y; // a is greater number
b = (x < y) ? x : y; // b is smaller number
r = b;
while (a % b != 0)
{
r = a % b;
a = b;
b = r;
}
return r;
}
int lcm(int x, int y)
{
int a;
a = (x > y) ? x : y; // a is greater number
while (true)
{
if (a % x == 0 && a % y == 0)
return a;
++a;
}
}
int main(int argc, char **argv)
{
cout << "Enter the two numbers: ";
int x, y;
cin >> x >> y;
cout << "The GCD of two numbers is: " << gcd(x, y) << endl;
;
cout << "The LCM of two numbers is: " << lcm(x, y) << endl;
;
return 0;
}
/*
Enter the two numbers:
5
8
The GCD of two numbers is: 1
The LCM of two numbers is: 40
Enter the two numbers:
100
50
The GCD of two numbers is: 50
The LCM of two numbers is: 100

@ -0,0 +1,179 @@
#include<iostream>
#include<conio.h>
#include<stdlib.h>
using namespace std;
void permute(int *a, int k, int size)
{
if (k == size)
{
for (int i = 0; i < size; i++)
{
cout << *(a + i);
}
cout << endl;
}
else
{
for (int i = k; i < size; i++)
{
int temp = a[k];
a[k] = a[i];
a[i] = temp;
permute(a, k + 1, size);
temp = a[k];
a[k] = a[i];
a[i] = temp;
}
}
}
int main(int argc, char **argv)
{
cout << "Enter the length of the password: ";
int m;
cin >> m;
int a[m];
for (int i = 0; i < m; i++)
{
/*generates random number between 1 and 10*/
a[i] = rand() % 10;
}
for (int i = 0; i < m; i++)
{
cout << a[i] << ", ";
}
cout << "The Passwords are: ";
permute(a, 0, m);
}
/*
Enter the length of the password: 3
1, 7, 4, The Passwords are: 174
147
714
741
471
417
Enter the length of the password: 5
1, 7, 4, 0, 9, The Passwords are: 17409
17490
17049
17094
17904
17940
14709
14790
14079
14097
14907
14970
10479
10497
10749
10794
10974
10947
19407
19470
19047
19074
19704
19740
71409
71490
71049
71094
71904
71940
74109
74190
74019
74091
74901
74910
70419
70491
70149
70194
70914
70941
79401
79410
79041
79014
79104
79140
47109
47190
47019
47091
47901
47910
41709
41790
41079
41097
41907
41970
40179
40197
40719
40791
40971
40917
49107
49170
49017
49071
49701
49710
07419
07491
07149
07194
07914
07941
04719
04791
04179
04197
04917
04971
01479
01497
01749
01794
01974
01947
09417
09471
09147
09174
09714
09741
97401
97410
97041
97014
97104
97140
94701
94710
94071
94017
94107
94170
90471
90417
90741
90714
90174
90147
91407
91470
91047
91074
91704
91740

@ -0,0 +1,72 @@
#include <iostream>
using namespace std;
int main()
{
cout << "Welcome to the Sieve of Sundaram\n" << endl;
int arraySize;
int numberPrimes = 0;
cout << "Input a positive integer to find all the prime numbers up to and "
<< "\nincluding that number: ";
cin >> arraySize;
int n = arraySize / 2;
/* array to start off with that will eventually get
all the composite numbers removed and the remaining
ones output to the screen */
int isPrime[arraySize + 1];
for (int i = 0; i < n; ++i)
{
isPrime[i] = i;
}
for (int i = 1; i < n; i++)
{
for (int j = i; j <= (n - i) / (2 * i + 1); j++)
{
isPrime[i + j + 2 * i * j] = 0;/*From this list, remove all
numbers of the form i + j + 2ij */
}
}
int TheseArePrime = 0;
if (arraySize > 2)
{
isPrime[TheseArePrime++] = 2;/*this IF statement adds 2 to the output */
}
for (int i = 1; i < n; i++)
{
if (isPrime[i] != 0)
{
isPrime[TheseArePrime++] = i * 2 + 1;
}
}
int size = sizeof isPrime / sizeof(int);//total size of array/size of array data type
for (int x = 0; x <= size; x++)
{
if (isPrime[x] != 0)
{
cout << isPrime[x] << "\t";//outputs all prime numbers found
numberPrimes++;// the counter of the number of primes found
}
else
{
break;
}
}
cout << "\nNumber of Primes: " << numberPrimes << endl;
return 0;
}
/*
Welcome to the Sieve of Sundaram
Input a positive integer to find all the prime numbers up to and
including that number: 10
2 3 5 7
Number of Primes: 4
Welcome to the Sieve of Sundaram
Input a positive integer to find all the prime numbers up to and
including that number: 100
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Number of Primes: 25

@ -0,0 +1,18 @@
#include<iostream>
#include<conio.h>
#include<stdlib.h>
using namespace std;
int main(int argc, char **argv)
{
int val = rand();
char Hex[33];
itoa(val, Hex, 16);
cout<< "Random Decimal Byte:" << val;
cout << "\nEquivalent Hex Byte: " << Hex;
}
/*
Random Decimal Byte:41
Equivalent Hex Byte: 29

@ -0,0 +1,45 @@
/*This is a C++ Program to generate random numbers using Middle Square method. In mathematics, the middle-square method is a method of generating pseudorandom numbers. In practice it is not a good method, since its period is usually very short and it has some severe weaknesses, such as the output sequence almost always converging to zero.*/
#include <iostream>
#include <math.h>
#include <stdlib.h>
using namespace std;
int a[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
int middleSquareNumber(int numb, int dig)
{
int sqn = numb * numb, next_num = 0;
int trim = (dig / 2);
sqn = sqn / a[trim];
for (int i = 0; i < dig; i++)
{
next_num += (sqn % (a[trim])) * (a[i]);
sqn = sqn / 10;
}
return next_num;
}
int main(int argc, char **argv)
{
cout << "Enter the #-digit random numbers you want: ";
int n;
cin >> n;
int start = 1, end = 1;
start = a[n - 1];
end = a[n];
int number = ((rand()) % (end - start)) + start;
cout << "The random numbers are:\n" << number << ", ";
for (int i = 1; i < n; i++)
{
number = middleSquareNumber(number, n);
cout << number << ", ";
}
cout << "...";
}
/*
Enter the #-digit random numbers you want: 5
The random numbers are:
10041, 16426, 796264, -276041, -115546, ...

@ -0,0 +1,31 @@
/*This is a C++ Program to generate random numbers using Multiply with Carry method. In computer science, multiply-with-carry (MWC) is a method invented by George Marsaglia for generating sequences of random integers based on an initial set from two to many thousands of randomly chosen seed values. The main advantages of the MWC method are that it invokes simple computer integer arithmetic and leads to very fast generation of sequences of random numbers with immense periods, ranging from around 260 to 22000000.*/
#include <iostream>
#include <math.h>
#include <stdlib.h>
using namespace std;
int main(int argc, char **argv)
{
int max_Sequence_Elements = 10;
int base_b = 2000;
int multiplier_a = rand() % base_b;
int r = 1;
int c[max_Sequence_Elements];
int x[max_Sequence_Elements];
c[0] = rand() % multiplier_a;
x[0] = rand() % base_b;
cout << "The random number sequence is: " << x[0];
//generating sequence
for (int i = 1; i < max_Sequence_Elements; i++)
{
x[i] = (multiplier_a * x[i - r] + c[i - 1]) % base_b;
c[i] = (multiplier_a * x[i - r] + c[i - 1]) / base_b;
cout << " " << x[i];
}
cout << "...";
}
/*
The random number sequence is: 334 1711 157 472 1355 1564 151 223 1146 990...

@ -0,0 +1,34 @@
/*This is a C++ Program to generate random numbers using Probability Distribution Function. Probability distribution is based on probability density function. a probability density function (pdf), or density of a continuous random variable, is a function that describes the relative likelihood for this random variable to take on a given value. The probability of the random variable falling within a particular range of values is given by the integral of this variables density over that range—that is, it is given by the area under the density function but above the horizontal axis and between the lowest and greatest values of the range.*/
//pdf(x) = 1 if x>360
// = 0 if x<0
// = x/360 otherwise
#include <iostream>
#include <math.h>
#include <stdlib.h>
using namespace std;
//This is a sample program to generate a random numbers based on probability desity function of spiner
//pdf(x) = 1 if x>360
// = 0 if x<0
// = x/360 otherwise
int N = 10;
int main(int argc, char **argv)
{
int p = 0;
for (int i = 0; i < N; i++)
{
p = rand() % 400;
if (p > 360)
cout << 0 << " ";
else if (p < 0)
cout << 0 << " ";
else
cout << p * 0.1 / 360 << " ";
}
cout << "...";
}
/*
0.0113889 0.0186111 0.0927778 0.0277778 0 0.0344444 0.0772222 0.0438889 0.045 0.0177778 ...

@ -0,0 +1,26 @@
#include <iostream>
#include <cstdlib>
#include <time.h>
const int LOW = 1;
const int HIGH = 32000;
using namespace std;
int main()
{
int randomNumber;
time_t seconds;
time(&seconds);
srand((unsigned int) seconds);
for (int i = 0; i < 10; i++)
{
randomNumber = rand() % (HIGH - LOW + 1) + LOW;
cout << randomNumber << " ";
}
cout << "...";
return 0;
}
/*
312 7423 23444 16008 31816 1823 29315 17424 11753 18384 ...

@ -0,0 +1,141 @@
/*This is a C++ Program to multiply two signed numbers using booths algorithm. Booths multiplication algorithm is a multiplication algorithm that multiplies two signed binary numbers in twos complement notation. Booth used desk calculators that were faster at shifting than adding and created the algorithm to increase their speed. Booths algorithm is of interest in the study of computer architecture.*/
#include<iostream>
#include<conio.h>
using namespace std;
void add(int a[], int x[], int qrn);
void complement(int a[], int n)
{
int i;
int x[8] = { NULL };
x[0] = 1;
for (i = 0; i < n; i++)
{
a[i] = (a[i] + 1) % 2;
}
add(a, x, n);
}
void add(int ac[], int x[], int qrn)
{
int i, c = 0;
for (i = 0; i < qrn; i++)
{
ac[i] = ac[i] + x[i] + c;
if (ac[i] > 1)
{
ac[i] = ac[i] % 2;
c = 1;
}
else
c = 0;
}
}
void ashr(int ac[], int qr[], int &qn, int qrn)
{
int temp, i;
temp = ac[0];
qn = qr[0];
cout << "\t\tashr\t\t";
for (i = 0; i < qrn - 1; i++)
{
ac[i] = ac[i + 1];
qr[i] = qr[i + 1];
}
qr[qrn - 1] = temp;
}
void display(int ac[], int qr[], int qrn)
{
int i;
for (i = qrn - 1; i >= 0; i--)
cout << ac[i];
cout << " ";
for (i = qrn - 1; i >= 0; i--)
cout << qr[i];
}
int main(int argc, char **argv)
{
int mt[10], br[10], qr[10], sc, ac[10] = { 0 };
int brn, qrn, i, qn, temp;
cout
<< "\n--Enter the multiplicand and multipier in signed 2's complement form if negative--";
cout << "\n Number of multiplicand bit=";
cin >> brn;
cout << "\nmultiplicand=";
for (i = brn - 1; i >= 0; i--)
cin >> br[i]; //multiplicand
for (i = brn - 1; i >= 0; i--)
mt[i] = br[i]; // copy multipier to temp array mt[]
complement(mt, brn);
cout << "\nNo. of multiplier bit=";
cin >> qrn;
sc = qrn; //sequence counter
cout << "Multiplier=";
for (i = qrn - 1; i >= 0; i--)
cin >> qr[i]; //multiplier
qn = 0;
temp = 0;
cout << "qn\tq[n+1]\t\tBR\t\tAC\tQR\t\tsc\n";
cout << "\t\t\tinitial\t\t";
display(ac, qr, qrn);
cout << "\t\t" << sc << "\n";
while (sc != 0)
{
cout << qr[0] << "\t" << qn;
if ((qn + qr[0]) == 1)
{
if (temp == 0)
{
add(ac, mt, qrn);
cout << "\t\tsubtracting BR\t";
for (i = qrn - 1; i >= 0; i--)
cout << ac[i];
temp = 1;
}
else if (temp == 1)
{
add(ac, br, qrn);
cout << "\t\tadding BR\t";
for (i = qrn - 1; i >= 0; i--)
cout << ac[i];
temp = 0;
}
cout << "\n\t";
ashr(ac, qr, qn, qrn);
}
else if (qn - qr[0] == 0)
ashr(ac, qr, qn, qrn);
display(ac, qr, qrn);
cout << "\t";
sc--;
cout << "\t" << sc << "\n";
}
cout << "Result=";
display(ac, qr, qrn);
}
/*
--Enter the multiplicand and multipier in signed 2's complement form if negative--
Number of multiplicand bit=5
Multiplicand=1 0 1 1 1
Number of multiplier bit=5
Multiplier=1 0 0 1 1
qn q[n+1] BR AC QR sc
initial 00000 10011 5
1 0 subtracting BR 01001
ashr 00100 11001 4
1 1 ashr 00010 01100 3
0 1 adding BR 11001
ashr 11100 10110 2
0 0 ashr 11110 01011 1
1 0 subtracting BR 00111
ashr 00011 10101 0
Result=00011 10101

@ -0,0 +1,129 @@
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main(int argc, char **argv)
{
cout << "Enter the dimension of the matrices: ";
int n;
cin >> n;
cout << "Enter the 1st matrix: ";
double a[n][n];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> a[i][j];
}
}
cout << "Enter the 2nd matrix: ";
double b[n][n];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> b[i][j];
}
}
cout << "Enter the result matrix: ";
double c[n][n];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> c[i][j];
}
}
//random generation of the r vector containing only 0/1 as its elements
double r[n][1];
for (int i = 0; i < n; i++)
{
r[i][0] = rand() % 2;
cout << r[i][0] << " ";
}
//test A * (b*r) - (C*) = 0
double br[n][1];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < 1; j++)
{
for (int k = 0; k < n; k++)
{
br[i][j] = br[i][j] + b[i][k] * r[k][j];
}
}
}
double cr[n][1];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < 1; j++)
{
for (int k = 0; k < n; k++)
{
cr[i][j] = cr[i][j] + c[i][k] * r[k][j];
}
}
}
double abr[n][1];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < 1; j++)
{
for (int k = 0; k < n; k++)
{
abr[i][j] = abr[i][j] + a[i][k] * br[k][j];
}
}
}
// br = multiplyVector(b, r, n);
// cr = multiplyVector(c, r, n);
// abr = multiplyVector(a, br, n);
//abr-cr
for (int i = 0; i < n; i++)
{
abr[i][0] -= cr[i][0];
}
bool flag = true;
for (int i = 0; i < n; i++)
{
if (abr[i][0] == 0)
continue;
else
flag = false;
}
if (flag == true)
cout << "Yes";
else
cout << "No";
}
/*
Enter the dimension of the matrices: 2
Enter the 1st matrix:
1 2
2 3
Enter the 2nd matrix:
1 3
3 4
Enter the result matrix:
9 9
14 15
Yes
Enter the dimesion of the matrices:
2
Enter the 1st matrix:
2 3
3 4
Enter the 2st matrix:
1 0
1 2
Enter the result matrix:
6 5
8 7
Yes

@ -0,0 +1,37 @@
/*
* C++ Program to Implement Euler Theorem
*/
#include <iostream>
#include <vector>
using namespace std;
vector<int> inverseArray(int n, int m)
{
vector<int> modInverse(n + 1, 0);
modInverse[1] = 1;
for (int i = 2; i <= n; i++)
{
modInverse[i] = (-(m / i) * modInverse[m % i]) % m + m;
}
return modInverse;
}
//Main
int main()
{
vector<int>::iterator it;
int a, m;
cout<<"Enter number to find modular multiplicative inverse: ";
cin>>a;
cout<<"Enter Modular Value: ";
cin>>m;
cout<<inverseArray(a, m)[a]<<endl;
}
/*
Enter number to find modular multiplicative inverse: 5
Enter Modular Value: 7
3
------------------
(program exited with code: 1)
Press return to continue

@ -0,0 +1,55 @@
/*
* C++ Program to Implement Extended Eucledian Algorithm
*/
#include <iostream>
#include <utility>
using namespace std;
/* return the gcd of a and b followed by the pair x and y of
equation ax + by = gcd(a,b)
*/
pair<int, pair<int, int> > extendedEuclid(int a, int b)
{
int x = 1, y = 0;
int xLast = 0, yLast = 1;
int q, r, m, n;
while (a != 0)
{
q = b / a;
r = b % a;
m = xLast - q * x;
n = yLast - q * y;
xLast = x;
yLast = y;
x = m;
y = n;
b = a;
a = r;
}
return make_pair(b, make_pair(xLast, yLast));
}
int modInverse(int a, int m)
{
return (extendedEuclid(a, m).second.first + m) % m;
}
//Main
int main()
{
int a, m;
cout<<"Enter number to find modular multiplicative inverse: ";
cin>>a;
cout<<"Enter Modular Value: ";
cin>>m;
cout<<modInverse(a, m)<<endl;
}
/*
Enter number to find modular multiplicative inverse: 133
Enter Modular Value: 135
67
------------------
(program exited with code: 1)
Press return to continue

@ -0,0 +1,67 @@
/*
* C++ Program to Implement Fermat Primality Test
*/
#include <cstring>
#include <iostream>
#include <cstdlib>
#define ll long long
using namespace std;
/*
* modular exponentiation
*/
ll modulo(ll base, ll exponent, ll mod)
{
ll x = 1;
ll y = base;
while (exponent > 0)
{
if (exponent % 2 == 1)
x = (x * y) % mod;
y = (y * y) % mod;
exponent = exponent / 2;
}
return x % mod;
}
/*
* Fermat's test for checking primality
*/
bool Fermat(ll p, int iterations)
{
if (p == 1)
{
return false;
}
for (int i = 0; i < iterations; i++)
{
ll a = rand() % (p - 1) + 1;
if (modulo(a, p - 1, p) != 1)
{
return false;
}
}
return true;
}
/*
* Main
*/
int main()
{
int iteration = 50;
ll num;
cout<<"Enter integer to test primality: ";
cin>>num;
if (Fermat(num, iteration))
cout<<num<<" is prime"<<endl;
else
cout<<num<<" is not prime"<<endl;
return 0;
}
/*
Enter integer to test primality: 479001599
479001599 is prime
------------------
(program exited with code: 1)
Press return to continue

@ -0,0 +1,49 @@
/*
* C++ Program to Implement Fermat's Little Theorem
*/
#include <iostream>
using namespace std;
/* calculates (a^b)%MOD */
int pow(int a, int b, int MOD)
{
int x = 1, y = a;
while (b > 0)
{
if (b % 2 == 1)
{
x = (x * y);
if (x > MOD)
x %= MOD;
}
y = (y * y);
if (y > MOD)
y %= MOD;
b /= 2;
}
return x;
}
int modInverse(int a, int m)
{
return pow(a, m - 2, m);
}
//Main
int main()
{
int a, m;
cout<<"Enter number to find modular multiplicative inverse: ";
cin>>a;
cout<<"Enter Modular Value: ";
cin>>m;
cout<<modInverse(a, m)<<endl;
}
/*
Enter number to find modular multiplicative inverse: 1111
Enter Modular Value: 331
216
------------------
(program exited with code: 1)
Press return to continue

@ -0,0 +1,48 @@
/*This is a C++ Program to shuffle array using Fisher-Yates algorithm. The FisherYates shuffle (named after Ronald Fisher and Frank Yates), also known as the Knuth shuffle (after Donald Knuth), is an algorithm for generating a random permutation of a finite set—in plain terms, for randomly shuffling the set. A variant of the FisherYates shuffle, known as Sattolos algorithm, may be used to generate random cycles of length n instead. The FisherYates shuffle is unbiased, so that every permutation is equally likely. The modern version of the algorithm is also rather efficient, requiring only time proportional to the number of items being shuffled and no additional storage space.*/
#include <iostream>
#include <stdlib.h>
using namespace std;
void fisherYatesShuffling(int *arr, int n)
{
int a[n];
int ind[n];
for (int i = 0; i < n; i++)
ind[i] = 0;
int index;
for (int i = 0; i < n; i++)
{
do
{
index = rand() % n;
}
while (ind[index] != 0);
ind[index] = 1;
a[i] = *(arr + index);
}
for (int i = 0; i < n; i++)
{
cout << a[i] << " ";
}
}
int main(int argc, char **argv)
{
cout << "Enter the array size: ";
int n;
cin >> n;
cout << "Enter the array elements: ";
int a[n];
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
fisherYatesShuffling(a, n);
}
/*
Enter the array size: 7
Enter the array elements: 12 23 34 45 56 67 78
78 23 67 45 34 12 56

@ -0,0 +1,80 @@
#include<iostream>
#include<conio.h>
using namespace std;
int main(void)
{
float a[10][10], b[10], x[10], y[10];
int n = 0, m = 0, i = 0, j = 0;
cout << "Enter size of 2d array(Square matrix) : ";
cin >> n;
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
cout << "Enter values no :(" << i << ", " << j << ") ";
cin >> a[i][j];
}
}
cout << "\nEnter Values to the right side of equation\n";
for (i = 0; i < n; i++)
{
cout << "Enter values no :(" << i << ", " << j << ") ";
cin >> b[i];
}
cout << "Enter initial values of x\n";
for (i = 0; i < n; i++)
{
cout << "Enter values no. :(" << i<<"):";
cin >> x[i];
}
cout << "\nEnter the no. of iteration : ";
cin >> m;
while (m > 0)
{
for (i = 0; i < n; i++)
{
y[i] = (b[i] / a[i][i]);
for (j = 0; j < n; j++)
{
if (j == i)
continue;
y[i] = y[i] - ((a[i][j] / a[i][i]) * x[j]);
x[i] = y[i];
}
printf("x%d = %f ", i + 1, y[i]);
}
cout << "\n";
m--;
}
return 0;
}
/*
Enter size of 2d array(Square matrix) : 3
Enter values no :(0, 0) 2
Enter values no :(0, 1) 3
Enter values no :(0, 2) 1
Enter values no :(1, 0) 5
Enter values no :(1, 1) 4
Enter values no :(1, 2) 6
Enter values no :(2, 0) 8
Enter values no :(2, 1) 7
Enter values no :(2, 2) 9
Enter Values to the right side of equation
Enter values no :(0, 3) 2
Enter values no :(1, 3) 3
Enter values no :(2, 3) 4
Enter initial values of x
Enter values no. :(0): 0
Enter values no. :(1): 0
Enter values no. :(2): 0
Enter the no. of iteration : 4
x1 = 1.000000 x2 = -0.500000 x3 = -0.055556
x1 = 1.777778 x2 = -1.388889 x3 = -0.055556
x1 = 3.111111 x2 = -3.055555 x3 = 0.055555
x1 = 5.555555 x2 = -6.277777 x3 = 0.388889

@ -0,0 +1,98 @@
/*
* C++ Program to Implement Miller Rabin Primality Test
*/
#include <iostream>
#include <cstring>
#include <cstdlib>
#define ll long long
using namespace std;
/*
* calculates (a * b) % c taking into account that a * b might overflow
*/
ll mulmod(ll a, ll b, ll mod)
{
ll x = 0,y = a % mod;
while (b > 0)
{
if (b % 2 == 1)
{
x = (x + y) % mod;
}
y = (y * 2) % mod;
b /= 2;
}
return x % mod;
}
/*
* modular exponentiation
*/
ll modulo(ll base, ll exponent, ll mod)
{
ll x = 1;
ll y = base;
while (exponent > 0)
{
if (exponent % 2 == 1)
x = (x * y) % mod;
y = (y * y) % mod;
exponent = exponent / 2;
}
return x % mod;
}
/*
* Miller-Rabin primality test, iteration signifies the accuracy
*/
bool Miller(ll p,int iteration)
{
if (p < 2)
{
return false;
}
if (p != 2 && p % 2==0)
{
return false;
}
ll s = p - 1;
while (s % 2 == 0)
{
s /= 2;
}
for (int i = 0; i < iteration; i++)
{
ll a = rand() % (p - 1) + 1, temp = s;
ll mod = modulo(a, temp, p);
while (temp != p - 1 && mod != 1 && mod != p - 1)
{
mod = mulmod(mod, mod, p);
temp *= 2;
}
if (mod != p - 1 && temp % 2 == 0)
{
return false;
}
}
return true;
}
//Main
int main()
{
int iteration = 5;
ll num;
cout<<"Enter integer to test primality: ";
cin>>num;
if (Miller(num, iteration))
cout<<num<<" is prime"<<endl;
else
cout<<num<<" is not prime"<<endl;
return 0;
}
/*
Enter integer to test primality: 127
127 is prime
------------------
(program exited with code: 1)
Press return to continue

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save