Initial commit
This commit is contained in:
parent
40a414d210
commit
b880c3ccde
136
assembly/A DOS 2.0 filter for word processing document files.asm
Normal file
136
assembly/A DOS 2.0 filter for word processing document files.asm
Normal file
@ -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
|
310
assembly/A listing into pages and give new subtitles.asm
Normal file
310
assembly/A listing into pages and give new subtitles.asm
Normal file
@ -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
|
55
assembly/Absolute Disk Read.asm
Normal file
55
assembly/Absolute Disk Read.asm
Normal file
@ -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
|
373
assembly/Alarm.asm
Normal file
373
assembly/Alarm.asm
Normal file
@ -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
|
350
assembly/BIOS-based disk I-O to access MS-DOS file structure.asm
Normal file
350
assembly/BIOS-based disk I-O to access MS-DOS file structure.asm
Normal file
@ -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
|
267
assembly/Boot loader for a roll-your-own operating system.asm
Normal file
267
assembly/Boot loader for a roll-your-own operating system.asm
Normal file
@ -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
|
70
assembly/Break Handling Utilities Module.asm
Normal file
70
assembly/Break Handling Utilities Module.asm
Normal file
@ -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
|
47
assembly/Break.asm
Normal file
47
assembly/Break.asm
Normal file
@ -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
|
127
assembly/Burnout.asm
Normal file
127
assembly/Burnout.asm
Normal file
@ -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
|
77
assembly/Calculator.asm
Normal file
77
assembly/Calculator.asm
Normal file
@ -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
|
58
assembly/Cd Check.asm
Normal file
58
assembly/Cd Check.asm
Normal file
@ -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
|
14
assembly/Char.asm
Normal file
14
assembly/Char.asm
Normal file
@ -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
|
208
assembly/Chips.asm
Normal file
208
assembly/Chips.asm
Normal file
@ -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
|
83
assembly/Circle.asm
Normal file
83
assembly/Circle.asm
Normal file
@ -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
|
137
assembly/Clock.asm
Normal file
137
assembly/Clock.asm
Normal file
@ -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
|
109
assembly/Colours routine.asm
Normal file
109
assembly/Colours routine.asm
Normal file
@ -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
|
168
assembly/Control-Break handler for Lattice C programs.asm
Normal file
168
assembly/Control-Break handler for Lattice C programs.asm
Normal file
@ -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
|
44
assembly/Demo showing how to use 'flat real mode'.asm
Normal file
44
assembly/Demo showing how to use 'flat real mode'.asm
Normal file
@ -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
|
221
assembly/Determines the type of UART in each serial port.asm
Normal file
221
assembly/Determines the type of UART in each serial port.asm
Normal file
@ -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
|
233
assembly/Device Driver Header.asm
Normal file
233
assembly/Device Driver Header.asm
Normal file
@ -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
|
106
assembly/Disk Watch.asm
Normal file
106
assembly/Disk Watch.asm
Normal file
@ -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.
|
130
assembly/Drives Exist.asm
Normal file
130
assembly/Drives Exist.asm
Normal file
@ -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
|
161
assembly/Drives.asm
Normal file
161
assembly/Drives.asm
Normal file
@ -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
|
106
assembly/Ejects a SCSI tape (or CD-ROM) from a drive.asm
Normal file
106
assembly/Ejects a SCSI tape (or CD-ROM) from a drive.asm
Normal file
@ -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
|
37
assembly/Game Port.asm
Normal file
37
assembly/Game Port.asm
Normal file
@ -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
|
74
assembly/Get Space.asm
Normal file
74
assembly/Get Space.asm
Normal file
@ -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
|
79
assembly/Get current Segment Values.asm
Normal file
79
assembly/Get current Segment Values.asm
Normal file
@ -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
|
123
assembly/Get disk free space function.asm
Normal file
123
assembly/Get disk free space function.asm
Normal file
@ -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
|
44
assembly/Inthand.asm
Normal file
44
assembly/Inthand.asm
Normal file
@ -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
|
58
assembly/MSDOS 2.00 Function Library for Lattice C.asm
Normal file
58
assembly/MSDOS 2.00 Function Library for Lattice C.asm
Normal file
@ -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
|
231
assembly/Report installed device drivers.asm
Normal file
231
assembly/Report installed device drivers.asm
Normal file
@ -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
|
96
assembly/Sets up 'flat real mode'.asm
Normal file
96
assembly/Sets up 'flat real mode'.asm
Normal file
@ -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
|
283
assembly/Show Memory.asm
Normal file
283
assembly/Show Memory.asm
Normal file
@ -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
|
90
assembly/This is a small sound example for the IBM PC.asm
Normal file
90
assembly/This is a small sound example for the IBM PC.asm
Normal file
@ -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
|
182
assembly/Writes a boot sector to the floppy disk.asm
Normal file
182
assembly/Writes a boot sector to the floppy disk.asm
Normal file
@ -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 Euclid’s 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, Euclid’s 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 v’s 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 variable’s 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 booth’s algorithm. Booth’s multiplication algorithm is a multiplication algorithm that multiplies two signed binary numbers in two’s complement notation. Booth used desk calculators that were faster at shifting than adding and created the algorithm to increase their speed. Booth’s 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 Fisher–Yates 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 Fisher–Yates shuffle, known as Sattolo’s algorithm, may be used to generate random cycles of length n instead. The Fisher–Yates 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…
Reference in New Issue
Block a user