737 lines
16 KiB
Prolog
737 lines
16 KiB
Prolog
page 44,100
|
||
TITLE ASMXMPLE
|
||
|
||
Video equ 10h ;video functions interrupt number
|
||
Keyboard equ 16h ;keyboard functions interrupt number
|
||
DOS equ 21h ;call DOS interrupt number
|
||
PrtSc equ 5h ;Print Screen Bios interrupt
|
||
CRTstatus equ 03DAh
|
||
CRTmode equ 03D8h
|
||
CursOff equ 16134
|
||
portb equ 61h ;I/O port B
|
||
|
||
STACK Segment Para Stack 'Stack'
|
||
Stak db 64 dup ("stack ")
|
||
STACK EndS
|
||
|
||
PARMSEG Segment Para 'data'
|
||
Asciiz db 63 dup (?) ;Device ID, path and filespec,
|
||
Xasciiz db '$' ; followed by at least one byte of
|
||
; of binary zero.
|
||
Handle dw ? ;Place to put 16 bit handle number
|
||
Bufseg dw ? ;Segment address of buffer
|
||
Bufoff dw ? ;Offset of buffer
|
||
Bufsiz dw ? ;Max bytes to read/write
|
||
Actsiz dw ? ;Actual bytes read
|
||
Dskerr dw ? ;DOS error code, if error occurs
|
||
Parmseg EndS
|
||
|
||
DATASEG Segment Para 'data'
|
||
IObuffer db 4096 dup (?) ;I/O buffer for reading screens
|
||
; from disk.
|
||
Pgmstat db 0 ;program status switch
|
||
Cover db 'ICOVER.SCN'
|
||
db 0
|
||
FileSpec db 'INSTRC**.SCN'
|
||
db 0
|
||
PageNbr db 0
|
||
NewPage db ' '
|
||
Ten db 10
|
||
EdgeTab db 7,7,3,0,0,0,0,0
|
||
db 0,0,0,0,7,7,4,0
|
||
db 6,6,3,0,3,6,6,6
|
||
db 7,0,2,5,5,5,3,6
|
||
db 6,6,6,3,6,6,6,6
|
||
db 3,3,11,15,10,0,0,0
|
||
StartOff dw 0
|
||
Keycodes dw 0
|
||
Answer db 256 dup (?)
|
||
MaxChars dw 0
|
||
Attributes dw 0
|
||
Buzzit db 0
|
||
Dataseg EndS
|
||
|
||
ScreenSeg Segment at 0B800h ;location of color screen mem
|
||
Page0 db 4096 dup (?)
|
||
Page1 db 4096 dup (?)
|
||
Page2 db 4096 dup (?)
|
||
Page3 db 4096 dup (?)
|
||
ScreenSeg EndS
|
||
|
||
CODE Segment Para 'code'
|
||
assume cs:CODE
|
||
|
||
MAIN Proc Far
|
||
|
||
push ds
|
||
mov ax,0
|
||
push ax
|
||
assume ds:dataseg
|
||
mov ax,dataseg
|
||
mov ds,ax
|
||
mov dl,0 ;set starting page number to zero
|
||
mov PageNbr,dl
|
||
call ShowCover ;Put instructions cover on screen
|
||
cmp Pgmstat,0
|
||
jne InstructX ;some was wrong
|
||
PageMore:
|
||
call PutScreen ;Get instruction screen from disk
|
||
; and display it.
|
||
call NextNumber ;get next page number, etc.
|
||
cmp PageNbr,255
|
||
jne PageMore
|
||
InstructX:
|
||
mov ah,11 ;set color palette
|
||
mov bh,0 ;set boarder color
|
||
mov bl,0 ;black
|
||
int video ;call bios video routine
|
||
mov ah,0 ;set mode function
|
||
mov al,3 ;80 x 25 color
|
||
int video ;bios call to video rom routines
|
||
mov ah,5 ;select active display page
|
||
mov al,0 ;page 0
|
||
int video ;bios call
|
||
mov ah,1
|
||
mov ch,7
|
||
mov cl,7
|
||
ret ;return to dos
|
||
MAIN EndP
|
||
|
||
ShowCover Proc Near
|
||
push ds
|
||
push es
|
||
call Cover1
|
||
assume ds:dataseg
|
||
cmp PageNbr,0
|
||
jne CoverX
|
||
AnyKey:
|
||
mov ah,0 ;read next key struck from keyboard
|
||
int keyboard ;call bios keyboard routine
|
||
CoverX:
|
||
pop es
|
||
pop ds
|
||
ret
|
||
ShowCover EndP
|
||
|
||
Cover1 Proc Near
|
||
push ds
|
||
push es
|
||
assume ds:dataseg
|
||
assume es:parmseg
|
||
mov ax,parmseg
|
||
mov es,ax
|
||
cmp PageNbr,0
|
||
jne CoverOk
|
||
;Set disk parms, start by moving file spec to Asciiz.
|
||
mov si,offset cover
|
||
mov di,offset asciiz
|
||
mov cx,64
|
||
cld
|
||
rep movsb
|
||
mov es:bufseg,ds ;set segment address of buffer
|
||
mov ax,offset IObuffer ;set offset of buffer
|
||
mov es:bufoff,ax
|
||
mov ax,4008 ;set size of screen block
|
||
mov es:bufsiz,ax
|
||
call GetFile ;get screen from disk
|
||
cmp es:DskErr,0
|
||
je CoverOK ;read was OK
|
||
mov al,1
|
||
mov pgmstat,al
|
||
jmp CoverX
|
||
Coverok:
|
||
mov al,3 ;80 x 25 color
|
||
mov ah,0 ;set mode
|
||
int video ;call bios video routine
|
||
mov ah,5 ;select active display page
|
||
mov al,3 ;active page 3
|
||
int video ;call bios video routine
|
||
mov ah,11 ;set color palette
|
||
mov bh,0 ;set boarder color
|
||
mov bl,1 ;dark blue
|
||
int video ;call bios video routine
|
||
mov ah,1 ;make cursor invisible
|
||
mov ch,31
|
||
mov cl,31
|
||
int video
|
||
cmp PageNbr,0
|
||
jne Cover1X
|
||
mov dx,CRTmode ;turn off the display
|
||
mov al,29h ;mode byte for 80 column color
|
||
and al,11110111b
|
||
out dx,al
|
||
assume es:screenseg
|
||
mov ax,screenseg
|
||
mov es,ax
|
||
mov si,offset IObuffer+7 ;Move screen from I/O buffer to
|
||
mov di,offset Page3 ; to actual screen memory.
|
||
cld
|
||
mov cx,2000
|
||
rep movsw
|
||
mov dx,CRTmode ;turn display back on
|
||
mov al,29h ;80 x 25 color mode byte
|
||
out dx,al
|
||
call beep
|
||
Cover1X:
|
||
pop es
|
||
pop ds
|
||
ret
|
||
Cover1 EndP
|
||
|
||
PutScreen Proc Near
|
||
push ds
|
||
push es
|
||
ReStart:
|
||
assume ds:dataseg
|
||
mov al,PageNbr ;get instruction screen page number
|
||
call ConvByte ;convert to decimal display
|
||
mov FileSpec+6,dh ;and put it into the file spec
|
||
mov FileSpec+7,dl
|
||
assume es:parmseg
|
||
mov ax,parmseg
|
||
mov es,ax
|
||
;Set disk parms, start by moving file spec to Asciiz.
|
||
mov si,offset FileSpec
|
||
mov di,offset asciiz
|
||
mov cx,64
|
||
cld
|
||
rep movsb
|
||
mov es:bufseg,ds ;set segment address of buffer
|
||
mov ax,offset IObuffer ;set offset of buffer
|
||
mov es:bufoff,ax
|
||
mov ax,4008 ;set size of screen block
|
||
mov es:bufsiz,ax
|
||
call GetFile ;get screen from disk
|
||
cmp es:DskErr,0
|
||
je ScreenOK ;read was OK
|
||
jmp NoPage ;not a valid screen page number
|
||
ScreenOK:
|
||
call SetEdge
|
||
mov dx,CRTmode ;turn off the display
|
||
mov al,29h ;mode byte for 80 column color
|
||
and al,11110111b
|
||
out dx,al
|
||
assume es:screenseg
|
||
mov ax,screenseg
|
||
mov es,ax
|
||
mov si,offset IObuffer+7 ;Move screen from I/O buffer to
|
||
mov di,offset Page3 ; to actual screen memory.
|
||
cld
|
||
mov cx,2000
|
||
rep movsw
|
||
mov dx,CRTmode ;turn display back on
|
||
mov al,29h ;80 x 25 color mode byte
|
||
out dx,al
|
||
call beep
|
||
jmp PSexit
|
||
NoPage:
|
||
call buzz
|
||
call ClearAns
|
||
mov al,0
|
||
mov PageNbr,al
|
||
jmp ReStart
|
||
PSexit:
|
||
pop es
|
||
pop ds
|
||
ret
|
||
PutScreen EndP
|
||
|
||
NextNumber Proc Near
|
||
push ds
|
||
push es
|
||
WaitInput:
|
||
mov si,CursOff ;offset to cursor position on screen
|
||
mov cx,2 ;max characters in answer
|
||
mov dh,0BCh ;cursor color atribute
|
||
mov dl,031h ;answer color atribute
|
||
call Xanswer
|
||
assume es:dataseg
|
||
mov ax,dataseg
|
||
mov es,ax
|
||
cmp dh,1
|
||
je PrevPage ;go to previous page
|
||
cmp dh,2
|
||
je NextPage ;go to next page
|
||
cmp cx,0
|
||
je PageZero ;go to page 0
|
||
cmp cx,01FFh
|
||
je MainMenu ;escape back to main menu
|
||
push cx
|
||
mov di,offset NewPage ;move answer to local work area
|
||
cld
|
||
mov cx,2
|
||
rep movsb
|
||
pop cx
|
||
cmp cx,1
|
||
jne TwoDigit
|
||
OneDigit:
|
||
call ConvOne
|
||
cmp ah,0
|
||
jne BadNumber
|
||
mov es:PageNbr,al
|
||
jmp NNexit
|
||
TwoDigit:
|
||
call ConvTwo
|
||
cmp ah,0
|
||
jne BadNumber
|
||
mov es:PageNbr,al
|
||
jmp NNexit
|
||
PrevPage:
|
||
cmp es:PageNbr,0
|
||
je BadNumber
|
||
dec es:PageNbr
|
||
jmp NNexit
|
||
Nextpage:
|
||
inc es:PageNbr
|
||
jmp NNexit
|
||
PageZero:
|
||
mov al,0
|
||
mov es:PageNbr,al
|
||
jmp NNexit
|
||
MainMenu:
|
||
mov al,255
|
||
mov es:PageNbr,al
|
||
jmp NNexit
|
||
BadNumber:
|
||
call buzz
|
||
call ClearAns
|
||
jmp WaitInput
|
||
NNexit:
|
||
pop es
|
||
pop ds
|
||
ret
|
||
NextNumber EndP
|
||
|
||
ConvOne Proc Near
|
||
push ds
|
||
push es
|
||
assume ds:dataseg
|
||
mov ax,dataseg
|
||
mov ds,ax
|
||
mov al,NewPage
|
||
cmp al,30h
|
||
jl NotNumber1
|
||
cmp al,39h
|
||
jg NotNumber1
|
||
sub al,30h ;convert to binary
|
||
mov ah,0
|
||
jmp COexit
|
||
NotNumber1:
|
||
mov ah,1
|
||
COexit:
|
||
pop es
|
||
pop ds
|
||
ret
|
||
ConvOne EndP
|
||
|
||
ConvTwo Proc Near
|
||
push ds
|
||
push es
|
||
assume ds:dataseg
|
||
mov ax,dataseg
|
||
mov ds,ax
|
||
mov al,NewPage
|
||
cmp al,30h
|
||
jl NotNumber2
|
||
cmp al,39h
|
||
jg NotNumber2
|
||
sub al,30h ;convert to binary
|
||
mul Ten ;multiply by 10
|
||
mov dl,al ;save in dl
|
||
mov al,NewPage+1
|
||
cmp al,30h
|
||
jl NotNumber2
|
||
cmp al,39h
|
||
jg NotNumber2
|
||
sub al,30h ;convert to binary
|
||
add al,dl ;add 10's value
|
||
mov ah,0
|
||
jmp CTexit
|
||
NotNumber2:
|
||
mov ah,1
|
||
CTexit:
|
||
pop es
|
||
pop ds
|
||
ret
|
||
ConvTwo EndP
|
||
|
||
ClearAns Proc Near
|
||
push ds
|
||
push es
|
||
assume ds:screenseg
|
||
mov ax,screenseg
|
||
mov ds,ax
|
||
mov al,20h
|
||
mov bx,CursOff
|
||
mov [page0 + bx],al
|
||
inc bx
|
||
mov [page0 + bx],al
|
||
inc bx
|
||
mov [page0 + bx],al
|
||
pop es
|
||
pop ds
|
||
ret
|
||
ClearAns EndP
|
||
|
||
SetEdge Proc Near
|
||
push ds
|
||
push es
|
||
assume ds:dataseg
|
||
mov ax,dataseg
|
||
mov ds,ax
|
||
mov bl,PageNbr
|
||
mov bh,0
|
||
mov ch,[EdgeTab + bx]
|
||
mov ah,11
|
||
mov bh,0
|
||
mov bl,ch
|
||
int video
|
||
pop es
|
||
pop ds
|
||
ret
|
||
SetEdge EndP
|
||
|
||
;Subroutine to get a binary block of data from disk.
|
||
;It opens file, reads entire file (as one block of data)
|
||
;into memory, closes file.
|
||
;
|
||
;Enter with:
|
||
; - Device, path, filespec and binary zero in Asciiz.
|
||
; - Segment address of buffer in Bufseg.
|
||
; - Offset of buffer in Bufoff.
|
||
; - Max number of bytes to read, in Bufsiz.
|
||
;
|
||
;On exit:
|
||
; - Handle will contain handle number.
|
||
; - Actsiz will contain actual number of bytes read, or
|
||
; zero if file was not found on disk.
|
||
; - Dskerr will contain the DOS error code, or zero if
|
||
; no error.
|
||
|
||
Getfile Proc Near
|
||
push ds ;save registers of calling routine
|
||
push es
|
||
push si
|
||
push di
|
||
push ax
|
||
push bx
|
||
push cx
|
||
push dx
|
||
assume ds:parmseg
|
||
mov ax,parmseg ;set DS to PARMSEG segment
|
||
mov ds,ax ; -which sets DS to Asciiz
|
||
mov dx,offset asciiz ; -set offset to Asciiz
|
||
mov al,0 ;set AL to "open for reading"
|
||
mov ah,3dh ;set AH to "open a file" function
|
||
int DOS ;call DOS
|
||
jc gfopenerr ;error on open
|
||
mov handle,ax ;save handle
|
||
mov bx,handle ;load BX with file handle
|
||
mov cx,bufsiz ;load CX with # of bytes to read
|
||
mov dx,bufoff ;load DX with offset of buffer
|
||
mov ax,bufseg ;load DS with segment address
|
||
mov ds,ax ; of buffer
|
||
mov ah,3fh ;"read from a file" function
|
||
int DOS ;call DOS
|
||
push ax ;save # of bytes read on stack
|
||
mov ax,parmseg ;restore DS to diskparms segment
|
||
mov ds,ax ;
|
||
pop ax ;get # of bytes read
|
||
jc gfreaderr ;error on read
|
||
mov actsiz,ax ;save # of bytes read, in diskparms
|
||
mov bx,handle ;load BX with file handle
|
||
mov ah,3eh ;"close a file handle" function
|
||
int DOS ;call DOS
|
||
jc gfcloserr ;error on close
|
||
mov dskerr,0 ;set error code to zero (no error)
|
||
Gfback:
|
||
pop dx ;restore registers of calling
|
||
pop cx ; routine.
|
||
pop bx
|
||
pop ax
|
||
pop di
|
||
pop si
|
||
pop es
|
||
pop ds
|
||
ret ;return to calling routine
|
||
;ERROR ON OPEN: Possible error returns are:
|
||
; 2 - File not found
|
||
; 4 - To many open files (no handles left)
|
||
; 5 - Access denied
|
||
; 12 - Invalid access code
|
||
Gfopenerr:
|
||
mov ah,1 ;set AH to 1 for open error,
|
||
;AL already contains error code
|
||
mov dskerr,ax ;put error code in diskparms
|
||
jmp gfback
|
||
;ERROR ON READ: Possible error returns are:
|
||
; 5 - Access denied
|
||
; 6 - Invalid handle
|
||
Gfreaderr:
|
||
mov ah,2 ;set AH to 2 for read error
|
||
mov dskerr,ax ;put error code in diskparms
|
||
jmp gfback
|
||
;ERROR ON CLOSE: Possible error return is:
|
||
; 6 - Invalid handle
|
||
Gfcloserr:
|
||
mov ah,3 ;set AH to 3 for close error
|
||
mov dskerr,ax ;put error code in diskparms
|
||
jmp gfback
|
||
Getfile EndP
|
||
|
||
Beep Proc Near
|
||
push ax ;save registers of calling program
|
||
push dx
|
||
push cx
|
||
push bx
|
||
mov ax,0
|
||
mov dx,12h
|
||
mov cx,7d0h
|
||
div cx
|
||
mov bx,ax
|
||
mov al,10110110b
|
||
out 43h,al
|
||
mov ax,bx
|
||
out 42h,al
|
||
mov al,ah
|
||
out 42h,al
|
||
in al,portb
|
||
or al,3
|
||
out portb,al
|
||
mov cx,07fffh ;set up counter for duration of beep
|
||
wait:
|
||
loop wait
|
||
in al,portb
|
||
and al,11111100b
|
||
out portb,al
|
||
pop bx ;restore registers of calling pgm
|
||
pop cx
|
||
pop dx
|
||
pop ax
|
||
ret
|
||
BEEP EndP
|
||
|
||
BUZZ Proc Near
|
||
push ax ;save registers of calling program
|
||
mov ax,ds
|
||
push ax
|
||
push bx
|
||
push cx
|
||
push dx
|
||
assume ds:dataseg
|
||
mov ax,dataseg ;set DS for this routine
|
||
mov ds,ax
|
||
mov buzzit,16 ;set buzz counter
|
||
Buzzone:
|
||
mov ax,0
|
||
mov dx,12h
|
||
mov cx,900
|
||
div cx
|
||
mov bx,ax
|
||
mov al,10110110b
|
||
out 43h,al
|
||
mov ax,bx
|
||
out 42h,al
|
||
mov al,ah
|
||
out 42h,al
|
||
in al,portb
|
||
or al,3
|
||
out portb,al
|
||
mov cx,0affh
|
||
Buzz1:
|
||
loop buzz1
|
||
in al,portb
|
||
and al,11111100b
|
||
out portb,al
|
||
mov cx,7ffh
|
||
Buzz2:
|
||
loop buzz2
|
||
dec buzzit
|
||
jnz buzzone
|
||
pop dx
|
||
pop cx
|
||
pop bx
|
||
pop ax
|
||
mov ds,ax
|
||
pop ax
|
||
ret
|
||
BUZZ EndP
|
||
|
||
;Enter with binary value in AL.
|
||
;On return, the result is in: (assume result is 234)
|
||
; AH = 2, DH = 3, DL = 4
|
||
Convbyte Proc Near
|
||
push ds
|
||
push es
|
||
mov ah,48
|
||
mov dh,48
|
||
mov dl,48
|
||
Test1:
|
||
cmp al,100
|
||
jl test2
|
||
sub al,100
|
||
inc ah
|
||
jmp test1
|
||
Test2:
|
||
cmp al,10
|
||
jl test3
|
||
sub al,10
|
||
inc dh
|
||
jmp test2
|
||
Test3:
|
||
add dl,al
|
||
pop es
|
||
pop ds
|
||
ret
|
||
Convbyte EndP
|
||
|
||
;Enter with:
|
||
; SI = offset of cursor position in screen memory
|
||
; CX = maximum number of characters in answer
|
||
; DH = color atribute of cursor
|
||
; DL = color atribute of answer
|
||
;On return:
|
||
; The answer is on the screen, followed by the cursor.
|
||
; The answer is also in a string pointed to by DS SI,
|
||
; with CX set to the number of characters in the answer.
|
||
; If Escape was pushed CX will = 01FFh.
|
||
; DH will = 0, unless PgUp pushed then DH = 1
|
||
; or PgDn pushed then DH = 2.
|
||
Xanswer Proc Near
|
||
push ds
|
||
push es
|
||
assume ds:screenseg
|
||
mov ax,screenseg
|
||
mov ds,ax
|
||
assume es:dataseg
|
||
mov ax,dataseg
|
||
mov es,ax
|
||
mov es:Attributes,dx ;save color attributes
|
||
mov es:StartOff,si ;save beginning offset
|
||
mov es:MaxChars,cx ;save maximum number of characters
|
||
; in answer.
|
||
mov cx,256
|
||
mov bx,0
|
||
mov al,20h
|
||
ClearAnswer:
|
||
mov [es:answer + bx],al
|
||
inc bx
|
||
loop ClearAnswer
|
||
mov cx,0 ;initialize character counter
|
||
NextChar:
|
||
call PutCursor ;Put cursor on screen
|
||
mov ah,0
|
||
int keyboard ;read next keyboard entry
|
||
mov es:keycodes,ax ;save codes
|
||
cmp al,20h
|
||
jl ChekEdit ;not a printable character
|
||
cmp al,7Eh
|
||
jg ChekEdit ;not a printable character
|
||
cmp cx,es:MaxChars
|
||
jge BadChar ;already have max number of char's
|
||
call PutChar ;put character on screen
|
||
inc si ;bump offset to screen by 1 char'
|
||
inc si ; which is 2 bytes.
|
||
mov bx,cx ;move counter to pointer
|
||
mov ax,es:keycodes ;get character code
|
||
mov [es:Answer + bx],al ;and put in answer string
|
||
inc cx ;bump character counter
|
||
jmp NextChar
|
||
ChekEdit:
|
||
cmp ax,0E08h ;backspace
|
||
je BackUp
|
||
cmp ax,4B00h ;left arrow
|
||
je BackUp
|
||
cmp ax,1C0Dh ;return
|
||
je Return
|
||
cmp ax,011Bh ;escape
|
||
je Escape
|
||
cmp ah,49h ;PgUp
|
||
je PageUp
|
||
cmp ah,51h ;PgDn
|
||
je PageDown
|
||
BadChar:
|
||
call buzz ;invalid character or control
|
||
jmp NextChar
|
||
BackUp:
|
||
cmp cx,0
|
||
jle BadChar ;can't back up
|
||
mov es:keycodes,02020h ;set keycodes to space
|
||
call PutChar ;blank out cursor on screen
|
||
dec cx ;decrement character counter
|
||
dec si ;decrement offset pointer
|
||
dec si ; (2 bytes per character)
|
||
jmp NextChar ;and start over
|
||
Escape:
|
||
mov cx,01FFh
|
||
mov dh,0
|
||
jmp Return2
|
||
PageUp:
|
||
mov dh,1
|
||
jmp Return2
|
||
PageDown:
|
||
mov dh,2
|
||
jmp Return2
|
||
Return:
|
||
mov dh,0
|
||
Return2:
|
||
mov es:keycodes,02020h ;set keycodes to space
|
||
call PutChar ;blank out cursor on screen
|
||
assume ds:dataseg
|
||
mov ax,dataseg
|
||
mov ds,ax
|
||
mov si,offset answer
|
||
pop es
|
||
pop ds
|
||
ret
|
||
Xanswer EndP
|
||
|
||
PutCursor Proc Near
|
||
assume ds:screenseg
|
||
assume es:dataseg
|
||
mov bx,es:attributes
|
||
mov bl,219
|
||
mov dx,CRTstatus
|
||
Wait1:
|
||
in al,dx
|
||
test al,1
|
||
jnz Wait1
|
||
Wait2:
|
||
in al,dx
|
||
test al,1
|
||
jz Wait2
|
||
cli
|
||
mov [Page0 + si],bl
|
||
mov [Page0 + 1 + si],bh
|
||
sti
|
||
ret
|
||
PutCursor EndP
|
||
|
||
PutChar Proc Near
|
||
push dx
|
||
assume ds:screenseg
|
||
assume es:dataseg
|
||
mov bx,es:attributes
|
||
mov bh,bl
|
||
mov ax,es:keycodes
|
||
mov bl,al
|
||
mov dx,CRTstatus
|
||
WaitA:
|
||
in al,dx
|
||
test al,1
|
||
jnz WaitA
|
||
WaitB:
|
||
in al,dx
|
||
test al,1
|
||
jz WaitB
|
||
cli
|
||
mov [Page0 + si],bl
|
||
mov [Page0 + 1 + si],bh
|
||
sti
|
||
pop dx
|
||
ret
|
||
PutChar EndP
|
||
|
||
CODE EndS
|
||
END
|
||
|