Files
86-DOS-0.11/Disk Images/86-DOS 0.11 Source Code.img
T

11726 lines
250 KiB
Plaintext

繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞86DOS A86
86DOS A86 !86DOS A86"ASM A86#$%&'()*+,-./012繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞P EQU 18 ;BP for SEARCH FIRST and SEARCH NEXT
FIRCLUS EQU 20 ;First cluster of file
LSTCLUS EQU 22 ;Last cluster accessed
FIL繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞
; INTBASE+14H: BIOS DISK READ
; INTBASE+18H: BIOS DISK WRITE
; INTBASE+40H: Long jump to CALL entry point
ESCCH EQU 1BH
ASM A863456789:;<=>?@ABASM A86bCDEFGHIJKLMNOBOOT A86PQRCHESS A86STUVWXYZ[\]^_`ab繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞SIZ EQU 24 ;Size of file in records
CLUSPOS EQU 26 ;Position of last cluster accessed
FLSFLG EQU 28 ;Flush flag
SIZCHG EQU 29繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞CANCEL EQU "X"-"@" ;Cancel with Ctrl-X
MAXCALL EQU 36
MAXCOM EQU 40
INTBASE EQU 80H
INTTAB EQU 20H
ENTRYPOINTSEG EQU 0CHCHESS A86cdefghijklmnopqrCHESS A86stuvwxyz{|}~CHESS A86CHESS A86?繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞 ;Size change flag
NR EQU 32 ;Next record
RR EQU 33 ;Random record
; Description of 16-byte directory entry (same as return繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞
ENTRYPOINT EQU INTBASE+40H
CONTC EQU INTTAB+3
EXIT EQU INTBASE+8
LONGJUMP EQU 0EAH
LONGCALL EQU 9AH
SAVEXIT EQU 10
; FCHESS DOCCOMMAND A864DOSIO A86DウЖEDLIN A86H葦桶; QDOS High-performance operating system for the 8086 version 0.11
; by Tim Paterson
; Interrupt Entry Points:
; INTB繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞ed by SEARCH FIRST
; and SEARCH NEXT, functions 17 and 18).
;
; Location bytes Description
;
; 0 11 File name and exten繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞ield definition for FCBs
FNAME EQU 0 ;Drive code and name
EXTENT EQU 12
ENTPOS EQU 16 ;Position of entry in directory
DRVBHEX2BIN A86RDCPM A86弦沙SYS A86TRANS A86~従神疎団兎波品北ASE: ABORT
; INTBASE+4: COMMAND
; INTBASE+8: BASE EXIT ADDRESS
; INTBASE+C: CONTROL-C ABORT
; INTBASE+10H: FATAL ERROR ABORTsion ( 0E5H if empty)
; 11 2 First allocation unit ( < 4080 )
; 13 3 File size, in bytes (LSB first, 24 bits max.)
;
finitions
BIOSSEG EQU 40H
BIOSINIT EQU 0 ;Reserve room for jump to init code
BIOSSTAT EQU 3 ;Console input status check
SHFT EQU 3 ;Log2 of records/cluster
FIRFAT EQU 4 ;Starting record of FATs
FATSIZ EQU 6 ;Number of records occupied by FAT
FAT
MOV ES,AX
LODB ;Get no. of drives & no. of I/O drivers
CBW
MOV CX,AX
SEG CS
MOV [NUMIO],AL
MOV DI,AX
SHL DI
the OS. Entry 1 is reserved for
; future use. The first available allocation unit is assigned entry number
; two, and even th;Skip up to specified character
DB "UH" ;Copy rest of template
DB "HH" ;Kill line with no change in template (Ctrl-X)
DB "
; The File Allocation Table uses a 12-bit entry for each allocation unit on
; the disk. These entries are packed, two for everBIOSIN EQU 6 ;Get console character
BIOSOUT EQU 9 ;Output console character
BIOSPRINT EQU 12 ;Output to printer
BIOSAUXIN ECNT EQU 7 ;Number of FATs for this drive
FIRDIR EQU 8 ;Starting record of directory
DIRSIZ EQU 10 ;Number of records occupied MOV AH,DPBSIZ ;Size of DPB
MUL AX,AH
MOV BX,DRVTAB
ADD DI,BX ;Point to first DPB
ADD AX,DI
MOV BP,AX ;Point to firsough it is the first, is called cluster 2. Entries of 0FFFH
; are end of file marks; entries of zero are unallocated. OtherwiseRM" ;Cancel line and update template
DB "DD" ;Backspace (same as Ctrl-H)
DB "P@" ;Enter Insert mode
DB "QL" ;Exit Insert my three bytes. The contents
; of entry number N is found by 1) multiplying N by 1.5; 2) adding the result
; to the base addresQU 15 ;Get byte from auxilliary
BIOSAUXOUT EQU 18 ;Output byte to auxilliary
BIOSREAD EQU 21 ;Disk read
BIOSWRITE EQU 24 ;Disby directory
FIRREC EQU 11 ;First record of first cluster
MAXCLUS EQU 13 ;Number of clusters on drive + 1
DIRTY EQU 15 ;Whetht FAT
SEG CS
MOV [FATBASE],AX
PERDEV:
SEG CS
MOV [BX],DI ;Store DPB pointer to table entry
INC BX
INC BX
MOV AL,, the
; contents of a FAT entry is the number of the next cluster in the file.
; Field definition for Drive Parameter Blocode
DB 1BH,1BH ;Escape sequence to represent escape character
DB ESCCH,ESCCH
ESCTABLEN EQU $-ESCTAB
HEADER DB 13,10,"86-s of the Allocation Table; 3) fetching the 16-bit word at
; this address; 4) If N was odd (so that N*1.5 was not an integer), sk write
BIOSFLUSH EQU 27 ;Disk buffer flush
; Start of code
ORG 0
PUT 100H
JMP DOSINIT
ESCTAB:
DB "SC" ;Copyer FAT is dirty
FAT EQU 16 ;Pointer to start of FAT
DPBSIZ EQU 18 ;Size of the structure in bytes
; BOIS entry point deCH
STOB ;DEVNUM
LODW ;Get pointer to DPT
PUSH SI ;Save INITTAB pointer
MOV SI,AX ;Load DPT
MOVB ;SECSIZ
LODBk
DEVNUM EQU 0 ;I/O driver number
SECSIZ EQU 1 ;Size of physical sector in records
CLUSMSK EQU 2 ;Records/cluster - 1
CLUSDOS version 0.11"
DB 13,10
DB "Copyright 1980 Seattle Computer Products, Inc.",13,10,"$"
DOSINIT:
CLI
CLD
MOV AX,CShift the
; word right four bits; 5) mask to 12 bits (AND with 0FFF hex). Entry number
; zero is used as an end-of-file trap in one character from template
DB "VN" ;Skip over one character in template
DB "TA" ;Copy up to specified character
DB "WB"
DEC AL
STOB ;CLUSMSK
CBW
FIGSHFT:
INC AH
SAR AL
JNZ FIGSHFT
MOV AL,AH
STOB ;CLUSSHFT
LODW
STOW ;FIRFall entry point
CMP AH,MAXCOM
JBE SAVREGS
BADCALL:
MOV AL,0
IRET: IRET
ENTRY: ;System call entry point and dispatcher [DMAADD],128
MOV [DMAADD+2],DX
MOV AX,[DRVTAB]
MOV [CURDRV],AX
MOV CX,DX ;Start scanning just after DOS
MOV BX,0FH
PEN ;15
DW CLOSE
DW SRCHFRST
DW SRCHNXT
DW DELETE
DW SEQRD ;20
DW SEQWRT
DW CREATE
DW RENAME
DW INUSE
DW G5 ;True start of free space
MOV CL,4
SHR BP,CL ;First free segment
XOR AX,AX
MOV DS,AX
MOV ES,AX
MOV DI,INTBASE
PUSH BP
PUSH DI
PUSH SI
PUSH DX
PUSH CX
PUSH BX
PUSH AX
MOV BL,AH
MOV BH,0
SHL BX
CLD
SEG CS
CALL [BX+AT
MOV DX,AX
LODB
STOB ;FATSIZ
MOV AH,AL
PUSH AX
LODB
STOB ;FATCNT
MUL AX,AH
ADD AX,DX
STOW ;FIRDIR
POP AX ;IP from the long call at 5
POP AX ;Segment from the long call at 5
SEG CS
POP [TEMP] ;IP from the CALL 5
PMEMSCAN:
INC CX
JZ SETEND
MOV DS,CX
MOV AL,[BX]
NOT AL
MOV [BX],AL
CMP AL,[BX]
NOT AL
MOV [BX],AL
JZ MEMSCANETDRV ;25
DW SETDMA
DW GETFATPT
DW GETFATPTDL
DW GETRDONLY
DW SETATTRIB ;30
DW GETDSKPT
DW USERCODE
DW RNDRD
MOV AX,QUIT
STOW ;Set abort address--displacement
MOV AX,CS
MOV B,[ENTRYPOINT],LONGJUMP
MOV [ENTRYPOINT+1],ENTRY
MOVDISPATCH]
SEG CS
MOV [AXSAVE],AL
POP AX
POP BX
POP CX
POP DX
POP SI
POP DI
POP BP
POP DS
POP ES
POP SS
MOV DX,AX
LODB
STOB ;DIRSIZ
CBW
ADD AX,DX
STOW ;FIRREC
POP DX
LODW
INC AX
STOW ;MAXCLUS
XOR AL,AL
STUSHF ;Start re-ordering the stack
CLI
PUSH AX ;Save segment
SEG CS
PUSH [TEMP] ;Stack now ordered as if INT had been
SETEND:
SEG CS
MOV [ENDMEM],CX
XOR CX,CX
MOV DS,CX
MOV [EXIT],100H
MOV [EXIT+2],DX
MOV [INTBASE+0CH],100H
MODW RNDWRT
DW FILESIZE ;35
DW SETRNDREC
; Extended Functions
DW SETVECT
DW NEWBASE
DW BLKRD
DW BLKWRT ;40
GETIO: [ENTRYPOINT+3],CS
STOW
STOW
STOW
MOV [INTBASE+4],COMMAND
MOV DI,INTBASE+14H
MOV AX,BIOSREAD
STOW
MOV AX,BIOSSEG SEG CS
MOV SP,[SPSAVE]
IRET
; Standard Functions
DISPATCH DW ABORT ;0
DW CONIN
DW CONOUT
DW READER
DW PUNCH
DWOB
POP SI
LODW ;Allocation table displacement
SEG CS
ADD AX,[FATBASE]
STOW ;FAT
MOV DL,0
SHR DX ;FAT size in used
CMP CL,MAXCALL ;This entry point doesn't get as many calls
JA BADCALL
MOV AH,CL
SAVREGS:
SEG CS
MOV [SPSAVE],SPV [INTBASE+0EH],DX
CALL SETMEM
MOV SI,HEADER
CALL OUTMES
RET L
QUIT:
MOV AH,0
JP SAVREGS
COMMAND: ;Interrupt c
SETIO:
GETVER:
GETFATPTDL:
GETRDONLY:
SETATTRIB:
USERCODE:
MOV AL,0
RET
READER:
CALL BIOSAUXIN,BIOSSEG
RET
STOW
STOW ;Add 2 to DI
STOW
MOV [INTBASE+18H],BIOSWRITE
MOV DX,CS
MOV DS,DX
ADD DX,BP ;Next free segment
MOV LIST ;5
DW RAWIO
DW GETIO
DW SETIO
DW PRTBUF
DW BUFIN ;10
DW CONSTAT
DW GETVER
DW DSKRESET
DW SELDSK
DW Obytes
ADD AX,DX
CMP AX,BP
JBE SMFAT
MOV BP,AX
SMFAT:
INC CH ;Next I/O device number
DEC CL
JNZ PERDEV
ADD BP,1
SEG CS
MOV [SSSAVE],SS
INC SP
INC SP
SEG CS
POP [TEMP]
MOV SP,CS
MOV SS,SP
MOV SP,SSSAVE
PUSH ES
PUSH DS
PUNCH:
MOV AL,DL
CALL BIOSAUXOUT,BIOSSEG
RET
UNPACK:
; Inputs:
; DS = CS
; BX = Cluster number
; BP = Base of d CMP AL,[BP+DIRSIZ]
JB RDIRREC
STC
RET
NEXTENT:
Add BX,16
CMP BX,DIRBUF+127
JA RET
CMP B,[BX],0E5H
JZ NEXTENTny
; character.
; Outputs:
; Carry set if file not found
; ELSE
; BP = Base of drive parameters
; DS = CS
; ES = CS
; AXputs:
; DS, DX point to FCB
; Outputs:
; ES = CS
; If file name OK:
; BP has base of driver parameters
; [NAME1] has name ter to drive FAT
; Outputs:
; The data is stored in the FAT at the given cluster.
; BX,DX,DI all destroyed
; No other registRT
XOR AL,AL
RET
RENAME: ;System call 23
CALL MOVNAME
JC ERRET
ADD SI,5
MOV DI,NAME2
CALL LODNAME
CALL FINDrive parameters
; SI = Pointer to drive FAT
; Outputs:
; DI = Contents of FAT for given cluster
; Zero set means DI=0 (free
MOV SI,BX
MOV DI,NAME1
MOV CX,11
WILDCRD:
REPE
CMPB
JZ RET
CMP B,[DI-1],"?"
JZ WILDCRD
JP NEXTENT
DELET = Directory record number
; BX = Pointer into directory buffer
; [DIRBUF] has directory record with match
; [NAME1] has filein upper case
; All registers except DX destroyed
; Carry set if bad file name or drive
MOV AX,CS
MOV ES,AX
MOV DI,NAMers affected
MOV DI,BX
SHR BX
ADD BX,SI
ADD BX,DI
SHR DI
MOV DI,[BX]
JNC ALIGNED
SHL DX
SHL DX
SHL DX
SHNAME
JC ERRET
SAVDREC:
MOV AH,AL
RENFIL:
MOV DI,BX
MOV SI,NAME2
MOV CX,11
NEWNAM:
LODB
CMP AL,"?"
JZ SKIPLET
cluster)
; No other registers affected. Fatal error if cluster too big.
CMP BX,[BP+MAXCLUS]
JA HURTFAT
LEA DI,[SI+BX]
E: ; System call 19
CALL GETNAME
JC ERRET
PUSH AX
PUSH BX
CALL LOADFAT
POP BX
DELFILE:
MOV B,[BX],0E5H
PUSH BX
name
; All other registers destroyed.
CALL MOVNAME
JC RET
FINDNAME:
MOV AX,CS
MOV DS,AX
MOV AL,0
RDIRREC:
PUE1
MOV SI,DX
LODB
SEG ES
CMP [NUMIO],AL
JC RET
CBW
XCHG AX,BP
SHL BP
MOV BP,[BP+CURDRV]
LODNAME:
; This entrL DX
AND DI,0FH
JP PACKIN
ALIGNED:
AND DI,0F000H
PACKIN:
OR DI,DX
MOV [BX],DI
RET
GETNAME:
; Inputs:
; DS
MOV [DI],AL
SKIPLET:
INC DI
LOOP NEWNAM
CALL NEXTENT
JZ RENFIL
MOV AL,AH
PUSH AX
CALL DIRWRITE
POP AX
CALL SHR BX
MOV DI,[DI+BX]
JNC HAVCLUS
SHR DI
SHR DI
SHR DI
SHR DI
STC
HAVCLUS:
RCL BX
AND DI,0FFFH
RET
HURTFA
MOV BX,[BX+11]
MOV SI,[BP+FAT]
OR BX,BX
JZ DELNXT
CMP BX,[BP+MAXCLUS]
JA DELNXT
CALL RELEASE
DELNXT:
POP BX
CSH AX
CALL DIRREAD
POP AX
MOV BX,DIRBUF-16
CONTSRCH:
CALL NEXTENT
JZ RET
NDIRREC:
INC AL ;Next directory record
y point copies a file name from DS,SI
; to ES,DI converting to upper case.
MOV CX,11
MOVCHK:
LODB
AND AL,7FH
CMP AL,"a,DX point to FCB
; Function:
; Find file name in disk directory. First byte is
; drive number (0=current disk). "?" matches aNDIRREC
JNC SAVDREC ;New record read, save current number
XOR AL,AL
RET
ERRET:
MOV AL,-1
RET
MOVNAME:
; InT:
MOV SI,BADFAT
CALL OUTMES
JMP ERROR
PACK:
; Inputs:
; DS = CS
; BX = Cluster number
; DX = Data
; SI = PoinALL NEXTENT
JZ DELFILE
POP AX
PUSH AX
CALL DIRWRITE
POP AX
CALL NDIRREC
PUSH AX
JNC DELFILE
POP AX
CALL FATW"-1
JLE STOLET
AND AL,5FH ;Convert to upper case
STOLET:
CMP AL," "
JB RET
STOB
LOOP MOVCHK
RET
OPEN: ;Systemnchanged
; All other registers destroyed
MOV B,[BP+DIRTY],0
CALL FIGFAT
EACHFAT:
PUSH DX
PUSH CX
PUSH BX
PUSH AX
JC BADCLOSE
MOV CX,BX
SUB CX,DIRBUF
MOV AH,CL
SEG ES
CMP AX,[DI+ENTPOS]
JNZ BADCLOSE
SEG ES
MOV CX,[DI+FIRCLUSG AL,AH
MOV CL,5
REP
STOB
XCHG AL,AH
PUSH AX
PUSH BX
CALL DIRWRITE
POP BX
POP AX
JMP OPENNAM
DIRREAD:
CX
PUSH BX
PUSH AX
CALL DREAD
OR AL,AL
POP AX
POP BX
POP CX
POP DX
JNZ FATERR
SUB AL,[BP+FATCNT]
JZ RET
X,DIRBUF
MOV CX,1
RET
CREATE: ;System call 22
CALL MOVNAME
JC ERRET3
MOV DI,NAME1
MOV CX,11
MOV AL,"?"
REPN call 15
PUSH DX
PUSH DS
CALL GETNAME
OPENNAM:
POP ES
POP DI
JC ERRET
MOV AH,[BP+DEVNUM]
INC AH
SEG ES
MOV
CALL DWRITE
POP AX
POP BX
POP CX
POP DX
ADD DX,CX
DEC AL
JNZ EACHFAT
OKRET:
MOV AL,0
RET
BADCLOSE:
MO]
MOV [BX+11],CX
SEG ES
MOV DX,[DI+FILSIZ]
SHR DX
MOV [BX+14],DX
MOV DL,0
RCR DL
MOV [BX+13],DL
CALL DIRWRITE
; Inputs:
; DS = CS
; AL = Directory block number
; BP = Base of drive parameters
; Function:
; Read the directory block NEG AL
JP FATWRT
FATERR:
ADD DX,CX
DEC AL
JNZ READFAT
POP BP
MOV SI,ALLBAD
CALL HARDERR
JP LOADFAT
CLOSE: ;SE
SCAB
JZ ERRET3
PUSH DX
PUSH DS
MOV AX,CS
MOV DS,AX
XOR AX,AX
RDIRREC2:
PUSH AX
CALL DIRREAD
POP AX
MOV [DI],AH
SEG ES
MOV [DI+EXTENT],0
ADD DI,16
MOV CX,BX
SUB CX,DIRBUF
MOV AH,CL
STOW ;ENTPOS
MOV AX,BP
STOW ;V B,[BP+DIRTY],0
MOV AL,-1
RET
FIGFAT:
; Loads registers with values needed to read or
; write a FAT.
MOV AL,[BP+FA
CHKFATWRT:
; Do FATWRT only if FAT is dirty
TEST B,[BP+DIRTY],-1
JZ OKRET
FATWRT:
; Inputs:
; DS = CS
; BP = Basinto DIRBUF.
; Outputs:
; AX,BP unchanged
; All other registers destroyed.
CALL DIRCOMP
DREAD:
; Inputs:
; BX,DS =ystem call 16
MOV DI,DX
TEST B,[DI+FLSFLG],-1
JZ NOFLSH
PUSH DI
MOV BP,[DI+DRVBP]
MOV AL,[BP+DEVNUM]
CALL BIOSFLUSDI,DIRBUF-16
MOV CX,8
FNDFRE:
ADD DI,16
CMP B,[DI],0E5H
LOOPNE FNDFRE
JZ FREESPOT
INC AL
CMP AL,[BP+DIRSIZ]
JC DRVBP
LEA SI,[BX+11]
LODW
STOW ;FIRCLUS
STOW ;LSTCLUS
LODB
SHL AL
LODW
RCL AX
STOW ;FILSIZ
XOR AX,AX
TCNT]
MOV BX,[BP+FAT]
MOV CL,[BP+FATSIZ] ;No. of records occupied by FAT
MOV CH,0
MOV DX,[BP+FIRFAT] ;Record number of se of drive parameter table
; Function:
; Write the FAT back to disk and reset FAT
; dirty flag.
; Outputs:
; AL = 0
; BP u Transfer address
; CX = Number of records
; DX = Absolute record number
; BP = Base of drive parameters
; Function:
; CallH,BIOSSEG
POP DI
NOFLSH:
TEST B,[DI+SIZCHG],-1
JZ OKRET
MOV DX,DI
PUSH DX
PUSH DS
CALL GETNAME
POP ES
POP DI
RDIRREC2
POP DS
POP DX
ERRET3:
MOV AL,-1
RET
FREESPOT:
MOV BX,DI
MOV SI,NAME1
MOV CX,5
MOVB
REP
MOVW
XCH STOW ;CLUSPOS
STOW ;FLSFLG, SIZCHG
LOADFAT:
TEST B,[BP+DIRTY],-1
JNZ RET
CALL FIGFAT
READFAT:
PUSH DX
PUSH tart of FATs
RET
DIRCOMP:
; Prepare registers for directory read or write
CBW
ADD AX,[BP+FIRDIR]
MOV DX,AX
MOV Bs BIOS to perform disk read. If BIOS reports
; errors, will call HARDERR for further action.
; BP preserved. All other registe CALL NOBUF
XOR AX,AX
MOV DS,AX
MOV SI,EXIT
MOV DI,EXITHOLD
MOVW
MOVW
POP BP
POP ES
POP ES
POP DS
POP SS
ERR:
SUB DI,CX
ADD DX,DI ;Next record to transfer
CALL RECTOBYT
ADD BX,DI ;Next location for transfer
CALL OUTMES
Ger
; BP = Base of drive parameters
; [RECCNT] = Record count
; [RECPOS] = Record position in file
; [FCB] = DX
; [NEXTADD]
; CX = Number of records
; DX = Absolute record number
; BP = Base of drive parameters
; Function:
; Calls BIOS to perform OAD
JP FINBLK
BLKWRT: ;System call 40
MOV DI,DX
MOV AX,[DI+RR]
CALL STORE
FINBLK:
MOV [CXSAVE],CX
JCXZ FINRND
rs destroyed.
MOV AL,[BP+DEVNUM]
PUSH BP
PUSH BX
PUSH CX
PUSH DX
CALL BIOSREAD,BIOSSEG
POP DX
POP DI
POP BX
MOV SP,[SPSAVE]
MOV DS,[DSSAVE]
SEG CS
JMP L,[EXITHOLD]
SEQRD: ;System call 20
CALL GETREC
MOV CX,1
CALL LOAD
ETRESP:
CALL IN
OR AL,20H ;To lower-case
CMP AL,"a"
JZ ERROR
CMP AL,"r"
JZ RET
CMP AL,"i"
JZ IGNORE
CMP AL,"c= Displacement of disk transfer within segment
; [DSKERR] = 0 (no errors yet)
; [NUMTRNS] = 0 (No transfers yet)
; If SETUP ddisk write. If BIOS reports
; errors, will call HARDERR for further action.
; BP preserved. All other registers destroyed.
INC AX
FINRND:
SEG ES
MOV [DI+RR],AX
SETNREX:
MOV CX,AX
AND AL,7FH
SEG ES
MOV [DI+NR],AL
AND CL,80H
ROL CX
X
POP BP
JC DSKRDERR
XOR AL,AL
RET
DSKRDERR:
MOV SI,RDERR
CALL HARDERR
JP DREAD
DIRWRITE:
; Inputs:
; DS =
JCXZ SETNREX
INC AX
JP SETNREX
SEQWRT: ;System call 21
CALL GETREC
MOV CX,1
CALL STORE
JCXZ SETNREX
INC AX
"
JNZ GETRESP
POP AX
MOV AL,1
RET
IGNORE:
POP AX
MOV AL,0
RET
ABORT:
SEG CS
MOV DS,[TEMP]
XOR AX,AX
MOetects no records will be transfered, it returns 1 level up
; with CX = 0.
MOV BP,[DI+DRVBP]
MOV BX,DS
MOV ES,BX
MOV MOV AL,[BP+DEVNUM]
MOV AH,0
CMP DX,[BP+FIRREC]
RCR AH
PUSH BP
PUSH BX
PUSH CX
PUSH DX
CALL BIOSWRITE,BIOSSEG
CHG CL,CH
SEG ES
MOV [DI+EXTENT],CX
MOV AL,[DSKERR]
RET
SETUP:
; Inputs:
; DS:DI point to FCB
; AX = Record posi CS
; AL = Directory block number
; BP = Base of drive parameters
; Function:
; Write the directory block into DIRBUF.
; OuJP SETNREX
RNDRD: ;System call 33
MOV CX,1
MOV DI,DX
MOV AX,[DI+RR]
CALL LOAD
JP FINRND
RNDWRT: ;System call 34
V ES,AX
MOV SI,SAVEXIT
MOV DI,EXIT
MOVW
MOVW
MOVW
MOVW
ERROR:
MOV SP,BPSAVE
MOV AX,CS
MOV DS,AX
MOV ES,AX
BX,CS
MOV DS,BX
MOV [RECPOS],AX
MOV [FCB],DX
MOV BX,[DMAADD]
MOV [NEXTADD],BX
MOV B,[DSKERR],0
MOV [NUMTRNS],0
POP DX
POP DI
POP BX
POP BP
JC DSKWRERR
XOR AL,AL
RET
DSKWRERR:
MOV SI,WRERR
CALL HARDERR
JP DWRITE
HARDtion in file of disk transfer
; CX = Record count
; Outputs:
; DS = CS
; ES:DI point to FCB
; CX = No. of records to transftputs:
; BP unchanged
; All other registers destroyed.
CALL DIRCOMP
DWRITE:
; Inputs:
; BX,DS = Transfer address
MOV CX,1
MOV DI,DX
MOV AX,[DI+RR]
CALL STORE
JP FINRND
BLKRD: ;System call 39
MOV DI,DX
MOV AX,[DI+RR]
CALL LMOV SI,[BP+FAT]
ADD BX,7FH ;See if there is any space left
JC SEGEND
AND BL,80H
NEG BX ;These instructions divide by 12
CMP BX,0FFFH
JNZ RDLP
MOV B,[DSKERR],1
SETFCB:
MOV AX,[CLUSNUM]
MOV DI,[FCB]
SEG ES
MOV [DI+LSTCLUS],AX
MOV Aead
; CX = No. of records read
; ES:DI point to FCB
; LSTCLUS, CLUSPOS fields in FCB set
CALL SETUP
SEG ES
MOV BX,[DI
DEC BX
MOV CL,[BP+CLUSSHFT]
SHR AX,CL
SHR BX,CL
MOV CX,AX
MOV AX,BX
CALL FNDCLUS
SUB AX,DX ;Last cluster minus r
; DI destroyed. No other registers affected.
SEG ES
MOV BX,[DI+LSTCLUS]
SEG ES
MOV DX,[DI+CLUSPOS]
OR BX,BX
JZ AX,CL
MOV CX,AX
CALL FNDCLUS
OR CX,CX
JNZ ADDREC
MOV DX,0FFFH
MOV B,[BP+DIRTY],-1
MOV DI,[FCB]
MOV AX,[RECPOS]
8
ROL BX
XCHG BL,BH
JNZ CHKMAX
MOV BH,2 ;All 512 records OK
CHKMAX:
CMP CX,BX
JBE SAVCNT
MOV CX,BX
MOV B,[DSKERX,[RECPOS]
MOV BX,[NUMTRNS]
ADD AX,BX
SEG ES
CMP AX,[DI+FILSIZ]
JBE NOSZINC
SEG ES
MOV [DI+FILSIZ],AX
SEG ES
M+FILSIZ]
SUB BX,AX
JBE WRTERRJ
CMP BX,CX
JNB ENUF
MOV B,[DSKERR],1
MOV [RECCNT],BX
ENUF:
MOV CL,[BP+CLUSSHFT]
Scurrent cluster
JCXZ HAVSTART ;See if no more data
PUSH CX ;No. of clusters of first
MOV CX,AX
CALL ALLOCATE
POP CX
NOCLUS
SUB CX,DX
JNB FINDIT
ADD CX,DX
XOR DX,DX
SEG ES
MOV BX,[DI+FIRCLUS]
FINDIT:
JCXZ RET
SKPCLP:
CALL UNPAC
SEG ES
MOV [DI+FILSIZ],AX
SEG ES
MOV B,[DI+SIZCHG],-1
XOR CX,CX
RET
STORE:
; Inputs:
; DS:DI point to FCB
; R],2 ;Flag that trimming took place
SAVCNT:
MOV [RECCNT],CX
RET
SEGEND:
MOV B,[DSKERR],2
MOV CX,0
POP BX
RET
OV B,[DI+SIZCHG],-1
NOSZINC:
DEC AX
MOV DX,AX
MOV CL,[BP+CLUSSHFT]
SHR DX,CL
SEG ES
MOV [DI+CLUSPOS],DX
MOV CX,BXHR AX,CL
MOV CX,AX
CALL FNDCLUS
OR CX,CX
JNZ WRTERR
MOV DL,[RECPOS]
AND DL,[BP+CLUSMSK]
MOV CX,[RECCNT]
RDLP:
C JC WRTERR
DEC CX
JZ NOSKIP
CALL SKPCLP
PUSH BX
WRCLUS:
POP BX
NOSKIP:
MOV DL,[RECPOS]
AND DL,[BP+CLUSMSK]
MOVK
CMP DI,0FFFH
JZ RET
XCHG BX,DI
INC DX
LOOP SKPCLP
RET
NOCLUS:
INC CX
DEC DX
RET
LOAD:
; Inputs:
; AX = Position in file of disk transfer
; CX = Record count
; Outputs:
; AX = Position of last record written
; CX = No. of rFNDCLUS:
; Inputs:
; DS = CS
; CX = No. of clusters
; BP = Base of drive parameters
; SI = FAT pointer
; ES:DI point to
RET
WRTERRJ:
JP WRTERR
HAVSTART:
MOV CX,AX
PUSH BX
CALL FNDCLUS
JCXZ WRCLUS
CALL ALLOCATE
POP BX
JNC NOSKALL OPTIMIZE
PUSH DI
PUSH AX
PUSH DS
MOV DS,[DMAADD+2]
CALL DREAD
POP DS
POP CX
POP BX
JCXZ SETFCB
MOV DL,0
CX,[RECCNT]
WRTLP:
CALL OPTIMIZE
PUSH DI
PUSH AX
PUSH DS
MOV DS,[DMAADD+2]
CALL DWRITE
POP DS
POP CX
POP BX
DS:DI point to FCB
; AX = Position in file to read
; CX = No. of records to read
; Outputs:
; AX = Position of last record records written
; ES:DI point to FCB
; LSTCLUS, CLUSPOS fields in FCB set
CALL SETUP
JCXZ WRTEOF
MOV BX,CX
ADD BX,AX
FCB
; Outputs:
; BX = Last cluster skipped to
; CX = No. of clusters remaining (0 unless EOF)
; DX = Position of last clusteIP
WRTERR:
MOV B,[DSKERR],1
ADDREC:
MOV AX,[RECPOS]
XOR CX,CX
MOV DI,[FCB]
RET
WRTEOF:
MOV CL,[BP+CLUSSHFT]
SHR
MOV DL,0
OR CX,CX
JNZ WRTLP
CALL SETFCB
SEG ES
MOV B,[DI+FLSFLG],-1
RET
OPTIMIZE:
; Inputs:
; DS = CS
; determined by EXTENT and NR fields
; DS:DI point to FCB
; No other registers affected.
MOV DI,DX
MOV AL,[DI+NR]
MOV BUM],BX ;Last cluster accessed
SUB DX,CX ;Number of records still needed
MOV AX,DX
MOV BX,CX
XCHG BL,BH
ROR BX
MOV S
LOOP ALLOC
MOV DX,0FFFH
CALL PACK
MOV B,[BP+DIRTY],-1
POP BX
CALL UNPACK
XCHG BX,DI
OR DI,DI
JNZ RET
MOV DI,,AL
SUB AL,DL ;AL = Number of records left in first cluster
MOV DX,CX
MOV SI,[BP+FAT]
MOV CX,0
OPTCLUS:
;AL has numbe is fully updated including dirty flag
; FIRCLUS field of FCB set if file was null
; SI,BP unchanged. All other registers destBX = Physical cluster
; CX = No. of records
; DL = record within cluster
; BP = Base of drives parameters
; [NEXTADD] = tranX,[DI+EXTENT]
SHL AL
SHR BX
RCR AL
MOV AH,BL
RET
ALLOCATE:
; Inputs:
; DS = CS
; ES = Segment of FCB
; BX =I,[NEXTADD]
ADD BX,SI ;Adjust by size of transfer
MOV [NEXTADD],BX
ADD [NUMTRNS],CX
POP DX
POP BX
PUSH CX
MOV CL,[FCB]
SEG ES
MOV [DI+FIRCLUS],BX
OR [SI],0FFFH
RET
RELEASE:
; Inputs:
; DS = CS
; BX = Cluster in file
; SI =r of records available in current cluster
;AH has number of records available in next cluster
;BX has current physical clusterroyed.
PUSH BX
MOV AX,BX
ALLOC:
MOV DX,BX
FINDFRE:
INC BX
CMP BX,[BP+MAXCLUS]
JL TRYOUT
CMP AX,1
JG TRYIN
sfer address
; Outputs:
; AX = No. of records remaining
; BX = Transfer address
; CX = No. or records to be transferred
; D Last cluster of file (0 if null file)
; CX = No. of clusters to allocate
; DX = Position of cluster BX
; BP = Base of drive [BP+CLUSSHFT]
DEC DX
DEC DX
SHL DX,CL
OR DL,BL
ADD DX,[BP+FIRREC]
POP CX
MOV BX,SI
RET
BLKDON:
MOV CX,DX ;Ma FAT pointer
; BP = Base of drive parameters
; Function:
; Frees cluster chain starting with [BX]
; AX,BX,DX,DI all destroye
;CX has number of sequential records found so far
;DX has number of records left to transfer
;SI has FAT pointer
CALL UNPAPOP BX
MOV DX,0FFFH
CALL RELBLKS
OR [SI],0FFFH
STC
RET
TRYOUT:
CALL UNPACK
JZ HAVFRE
TRYIN:
DEC AX
JLE FINX = Physical record address
; DI = Next cluster
; [CLUSNUM] = Last cluster accessed
; [NEXTADD] updated
; BP unchanged. Noteparameters
; SI = FAT pointer
; [FCB] = Displacement of FCB within segment
; Outputs:
; IF insufficient space
; THEN
; Cke the total equal to the request
JP FINCLUS
GETREC:
; Inputs:
; DS:DX point to FCB
; Outputs:
; AX = Record numberd. Other registers unchanged.
XOR DX,DX
RELBLKS:
; Enter here with DX=0FFFH to put an end-of-file mark
; in the first cluCK
ADD CL,AL
ADC CH,0
CMP CX,DX
JAE BLKDON
MOV AL,AH
INC BX
CMP DI,BX
JZ OPTCLUS
DEC BX
FINCLUS:
MOV [CLUSNDFRE
XCHG AX,BX
CALL UNPACK
JZ HAVFRE
XCHG AX,BX
JP FINDFRE
HAVFRE:
XCHG BX,DX
MOV AX,DX
CALL PACK
MOV BX,AX
that segment of transfer not set.
PUSH DX
PUSH BX
MOV AL,[BP+CLUSMSK]
INC AL ;Number of records per cluster
MOV AHarry set
; CX = max. no. of records that could be added to file
; ELSE
; Carry clear
; BX = First cluster allocated
; FATster and free the rest in the chain.
CALL UNPACK
JZ RET
MOV AX,DI
CALL PACK
CMP AX,0FFFH
MOV BX,AX
JNZ RELEASE
ROV [BXSAVE],BX
RET
DSKRESET: ;System call 13
SEG CS
MOV [DMAADD+2],DS
MOV AX,CS
MOV DS,AX
MOV [DMAADD],80H
MO
RCL AX ;Round to nearest record
STOW
MOV AL,0
RCL AL
STOB
RET
SETDMA: ;System call 26
SEG CS
MOV [DMAADD]
MOV BL,CH
EDITON:
MOV DL,AL
DEC DX
NEWLIN:
SEG CS
MOV AL,[CARPOS]
SEG CS
MOV [STARTPOS],AL
PUSH SI
MOV DI,INs starting at the disk transfer address.
MOV SI,BX
LES DI,[DMAADD]
MOV CX,8
REP
MOVW
MOV AL,0
RET
KILLSRCH:
M:
RCL BX
LOOP CHKUSE
MOV AL,BL
RET
SETRNDREC: ;System call 36
CALL GETREC
MOV [DI+RR],AX
MOV AL,0
JZ BIGRR
ET
GETEOF:
; Inputs:
; BX = Cluster in a file
; SI = Base of drive FAT
; DS = CS
; Outputs:
; BX = Last cluster in V AX,[DRVTAB]
MOV [CURDRV],AX
NOBUF:
MOV CL,[NUMIO]
MOV CH,0
MOV SI,DRVTAB
WRTFAT:
LODW
PUSH CX
PUSH SI
MOV BP,DX
SEG CS
MOV [DMAADD+2],DS
RET
GETFATPT: ;System call 27
MOV AX,CS
MOV DS,AX
MOV [DSSAVE],CS
MOV BP,[CURDRV]
BUF
MOV AH,CH
MOV BH,CH
MOV DH,CH
GETCH:
CALL IN
CMP AL,7FH
JZ BACKSP
CMP AL,8
JZ BACKSP
CMP AL,13
JZ ENDLIOV AL,-1
MOV [SRCHDON],AL
RET
SRCHNXT: ;System call 18
MOV AX,CS
MOV ES,AX
MOV DS,AX
MOV AL,[SRCHDON]
CMP AL,
INC AL
BIGRR:
MOV [DI+RR+2],AL
RET
SELDSK: ;System call 14
MOV DH,0
MOV BX,DX
PUSH CS
POP DS
CMP BL,[NUMIOthe file
; DI destroyed. No other registers affected.
CALL UNPACK
CMP DI,0FFFH
JZ RET
MOV BX,DI
JP GETEOF
SRCH,AX
CALL CHKFATWRT
POP SI
POP CX
LOOP WRTFAT
MOV AL,-1
CALL BIOSFLUSH,BIOSSEG
RET
GETDRV: ;System call 25
S
CALL LOADFAT
MOV BX,[BP+FAT]
MOV AL,[BP+CLUSMSK]
INC AL
MOV DX,[BP+MAXCLUS]
DEC DX
MOV B,[BP+DIRTY],-1
MOV [BXSAN
CMP AL,10
JZ PHYCRLF
CMP AL,CANCEL
JZ KILNEW
CMP AL,27
JZ ESC
SAVCH:
CMP DH,DL
JNB GETCH
STOB
INC DH
CA-1
JZ RET
MOV BX,[PDIR]
MOV BP,[SRCHBP]
CALL CONTSRCH
JP SAVPLCE
FILESIZE: ;System call 35
PUSH DI
PUSH DX
]
JGE RET
SHL BX
MOV AX,[BX+DRVTAB]
MOV [CURDRV],AX
RET
BUFIN: ;System call 10
MOV AX,CS
MOV ES,AX
MOV SI,DX
FRST: ;System call 17
CALL GETNAME
SAVPLCE:
; Search-for-next enters here to save place and report
; findings.
JC KILLSRCEG CS
MOV BP,[CURDRV]
MOV AL,[BP+0]
RET
INUSE: ;System call 24
MOV AX,CS
MOV DS,AX
MOV CL,[NUMIO]
MOV CH,0
VE],BX
MOV [DXSAVE],DX
RET
GETDSKPT: ;System call 31
SEG CS
MOV [DSSAVE],CS
SEG CS
MOV BX,[CURDRV]
SEG CS
MLL OUT
OR AH,AH
JNZ GETCH
CMP BH,BL
JAE GETCH
INC SI
INC BH
JP GETCH
ESC:
CALL IN
MOV CL,ESCTABLEN
PUSH DCALL GETNAME
POP DI
POP ES
MOV AL,-1
JC RET
ADD DI,33 ;Write size in RR field
LEA SI,[BX+13]
LODB
SHL AL
LODW
MOV CH,0
LODW
OR AL,AL
JZ RET
MOV BL,AH
MOV BH,CH
CMP AL,BL
JBE NOEDIT
CMP B,[BX+SI],0DH
JZ EDITON
NOEDIT:
H
MOV [SRCHDON],AL
MOV [PDIR],BX
MOV [SRCHBP],BP
;Information in directory entry must be copied into the first
; 16 byteMOV SI,CX
SHL SI
ADD SI,CURDRV
MOV BX,0
STD
CHKUSE:
LODW
MOV BP,AX
TEST B,[BP+DIRTY],-1
JZ SETBIT
STC
SETBITI
MOV DI,ESCTAB
REPNE
SCAB
POP DI
AND CL,0FEH
MOV BP,CX
JMP [BP+ESCFUNC]
ENDLIN:
STOB
CALL OUT
POP DI
MI,SI
INC DI
REPNE
SCAB
POP DI
POP ES
JNZ NOTFND
NOT CL
ADD CL,BL
SUB CL,BH
RET
NOTFND:
POP BP
JMP GETCHAVCH
COPYLIN:
MOV CL,BL
SUB CL,BH
JP COPYEACH
COPYSTR:
CALL FINDOLD
JP COPYEACH
COPYONE:
MOV CL,1
COPYEACHOS
CMP AL,8
JZ BACKPOS
CMP AL,9
JZ TAB
PUSH AX
MOV AL,"^"
CALL OUT
POP AX
OR AL,40H
JP OUT
ZERPOS:
SEG MP GETCH
BAKTAB:
PUSH DI
DEC DI
STD
MOV CL,DH
MOV AL," "
PUSH BX
MOV BL,7
JCXZ FIGTAB
FNDPOS:
SCAB
JNA CHKSOUT,BIOSSEG
SEG CS
TEST B,[PFLAG],-1
JZ STATCHK
CALL BIOSPRINT,BIOSSEG
STATCHK:
CALL BIOSSTAT,BIOSSEG
JZ RET
INOV [DI-1],DH
INC DH
COPYNEW:
MOV BP,ES
MOV BX,DS
MOV ES,BX
MOV DS,BP
MOV SI,INBUF
MOV CL,DH
REP
MOVB
RET
C
REEDIT:
MOV AL,"@"
CALL OUT
POP DI
PUSH DI
PUSH ES
PUSH DS
CALL COPYNEW
POP DS
POP ES
POP SI
MOV BL,DH:
CMP DH,DL
JZ GETCH2
CMP BH,BL
JZ GETCH2
LODB
STOB
CALL OUT
INC BH
INC DH
LOOP COPYEACH
GETCH2:
JMP GETCCS
MOV B,[CARPOS],0
JP OUTCH
BACKPOS:
SEG CS
DEC B,[CARPOS]
JP OUTCH
TAB:
MOV AL,0
SEG CS
XCHG AL,[CARPOS]CNT
SEG ES
CMP B,[DI+1],9
JZ HAVTAB
DEC BL
CHKCNT:
LOOP FNDPOS
FIGTAB:
SEG CS
SUB BL,[STARTPOS]
HAVTAB:
SUB BCHK:
CALL BIOSIN,BIOSSEG
CMP AL,'S'-'@'
JNZ NOSTOP
CALL BIOSIN,BIOSSEG ;Eat Cntrl-S
NOSTOP:
CMP AL,'P'-'@'
JZ PRINTRLF:
MOV AL,13
CALL OUT
MOV AL,10
JMP OUT
PHYCRLF:
CALL CRLF
JP GETCH
KILNEW:
MOV AL,"\"
CALL OUT
POP SI
JMP PUTNEW
ENTERINS:
MOV AH,-1
JMP GETCH
EXITINS:
MOV AH,0
JMP GETCH
ESCFUNC DW GETCH
DW TWOESC
DW EXITIH
SKIPONE:
CMP BH,BL
JZ GETCH2
INC BH
INC SI
JMP GETCH
SKIPSTR:
CALL FINDOLD
ADD SI,CX
ADD BH,CL
JMP GET
OR AL,0F8H
NEG AL
PUSH CX
MOV CL,AL
MOV CH,0
TABLP:
MOV AL," "
CALL OUTCH
LOOP TABLP
POP CX
RET
CONSTL,DH
ADD CL,BL
AND CL,7
CLD
POP BX
POP DI
JZ OLDBAK
TABBAK:
CALL BACKMES
LOOP TABBAK
JP OLDBAK
BACKUP:
DEON
CMP AL,'N'-'@'
JZ PRINTOFF
CMP AL,'C'-'@'
JNZ RET
INT CONTC ;Execute user Ctrl-C handler
RET
PRINTON:
SEG C
PUTNEW:
CALL CRLF
JMP NEWLIN
BACKSP:
OR DH,DH
JZ OLDBAK
CALL BACKUP
SEG ES
MOV AL,[DI]
CMP AL," "
JAE OLDNS
DW ENTERINS
DW BACKSP
DW REEDIT
DW KILNEW
DW COPYLIN
DW SKIPSTR
DW COPYSTR
DW SKIPONE
DW COPYONE
CONOUT:CH
FINDOLD:
CALL IN
MOV CL,BL
SUB CL,BH
JZ NOTFND
DEC CX
JZ NOTFND
PUSH ES
PUSH DS
POP ES
PUSH DI
MOV DAT: ;System call 11
CALL BIOSSTAT,BIOSSEG
JZ RET
OR AL,-1
RET
CONIN: ;System call 1
CALL INCHK
PUSH AX
CALL OC DH
DEC DI
BACKMES:
MOV AL,8
CALL OUT
MOV AL," "
CALL OUTCH
MOV AL,8
JMP OUTCH
TWOESC:
MOV AL,ESCCH
JMP SS
MOV B,[PFLAG],1
RET
PRINTOFF:
SEG CS
MOV B,[PFLAG],0
RET
CTRLOUT:
CMP AL,10
JZ OUTCH
CMP AL,13
JZ ZERPBAK
CMP AL,9
JZ BAKTAB
CALL BACKMES
OLDBAK:
OR AH,AH
JNZ GETCH1
OR BH,BH
JZ GETCH1
DEC BH
DEC SI
GETCH1:
J ;System call 2
MOV AL,DL
OUT:
CMP AL,20H
JB CTRLOUT
CMP AL,7FH
JZ OUTCH
SEG CS
INC B,[CARPOS]
OUTCH:
CALL BIOUT
POP AX
RET
IN:
CALL INCHK
JZ IN
RET
RAWIO: ;System call 6
MOV AL,DL
CMP AL,-1
JNZ RAWOUT
CALL BIOSS DI
RET
;***** DATA AREA *****
BADFAT DB 13,10,"Bad FAT",13,10,"$"
ALLBAD DB 13,10,"All FATs on disk are bad",13,10,"$"rom INT 23H)
; DX,BP unchanged. All other registers destroyed.
XOR CX,CX
MOV DS,CX
MOV ES,DX
MOV SI,EXIT
MOV DI,SAVction codes
PRINTMES: EQU 9
OPEN: EQU 15
CLOSE: EQU 16
DELETE: EQU 19
READ: EQU 20
SETDMA: EQU 26
MAKE: EQU 22
SEQWRT: EBASE: ; Interrupt call 38
MOV ES,DX
SEG CS
MOV DS,[TEMP]
XOR SI,SI
MOV DI,SI
MOV CX,80H
REP
MOVW
SETMEM:
;S DS 2
DS 50
AXSAVE DS 2
BXSAVE DS 2
CXSAVE DS 2
DXSAVE DS 2
SISAVE DS 2
DISAVE DS 2
BPSAVE DS 2
DSSAVE DS 2
ESSAVE DTAT,BIOSSEG
JZ RET
CALL BIOSIN,BIOSSEG
RET
RAWOUT:
CALL BIOSOUT,BIOSSEG
RET
LIST: ;System call 5
MOV AL,DL
CAL
RDERR DB 13,10,"Disk read error",13,10,"$"
WRERR DB 13,10,"Disk write error",13,10,"$"
CARPOS DB 0
STARTPOS DB 0
PFLAG DB EXIT
MOVW
MOVW
MOVW
MOVW
SEG CS
MOV CX,[ENDMEM]
SEG ES
MOV [2],CX
SUB CX,DX
CMP CX,0FFFH
JBE HAVDIF
MOV QU 21
;The following equates define some token values returned by GETSYM
UNDEFID:EQU 0 ;Undefined identifier (including no n Inputs:
; AX = Size of memory in paragraphs
; DX = Segment
; Function:
; Completely prepares a program base at the
; specS 2
SSSAVE DS 2
SPSAVE DS 2
CURDRV DS 2
DRVTAB: ;Address of start of DPBs
L BIOSPRINT,BIOSSEG
RET
PRTBUF: ;System call 9
MOV SI,DX
OUTSTR:
LODB
CMP AL,"$"
JZ RET
CALL OUT
JP OUTSTR
0
SRCHDON DB -1
PDIR DS 2
SRCHBP DS 2
EXITHOLD DS 4
ENDMEM DS 2
FATBASE DS 2
INBUF DS 255
DIRBUF DS 128
NUMIO DS 1 ;NuCX,0FFFH
HAVDIF:
MOV BX,ENTRYPOINTSEG
SUB BX,CX
SHL CX
SHL CX
SHL CX
SHL CX
MOV DS,DX
MOV [6],CX
MOV [8],BX
earby RET)
CONST: EQU 1 ;Constant (including $)
REG: EQU 2 ;8-bit register
XREG: EQU 3 ;16-bit register (except segment regisified segment.
; Outputs:
; DS = DX
; ES = DX
; [0] has INT 20H
; [2] = First unavailable segment ([ENDMEM])
; [5] to [9] ; Seattle Computer Products 8086 Assembler version 2.00
; by Tim Paterson
; Runs on the 8086 under 86-DOS
SYMWID: EQU 10OUTMES: ;String output for internal messages
SEG CS
LODB
CMP AL,"$"
JZ RET
CALL OUT
JP OUTMES
SETVECT: ; Interrmber of disk tables
NAME1 DS 11 ;File name buffer
NAME2 DS 11 ;File name buffer
DMAADD DS 4 ;User's disk transfer address MOV [0],20CDH ;"INT INTTAB"
MOV B,[5],LONGCALL
RET
RECTOBYT:
SHL DI
SHL DI
SHL DI
SHL DI
SHL DI
SHL DI
SHLters)
SREG: EQU 4 ;Segment register
ORG 100H
PUT 100H
JMP BEGIN
CPYRHT: DB 'Copyright 1979 by Seattle Computer Proform a long call to the entry point
; [10] to [13] have exit address (from INT 22H)
; [14] to [17] have ctrl-C exit address (f
FCB: EQU 5CH
BUFSIZ: EQU 128
EOL: EQU 13 ;ASCII carriage return
OBJECT: EQU 100H ;DEFAULT "PUT" ADDRESS
;System call funupt call 37
XOR BX,BX
MOV ES,BX
MOV BL,AL
SHL BX
SHL BX
SEG ES
MOV [BX],DX
SEG ES
MOV [BX+2],DS
RET
NEW(disp/seg)
TEMP DS 2
DSKERR DS 1
FCB DS 2 ;Address of user FCB
RECPOS DS 2
NEXTADD DS 2
RECCNT DS 2
CLUSNUM DS 2
NUMTRNducts, Inc.'
DB 13,10,13,10,'$'
BEGIN:
MOV SP,STACK
MOV DX,HEADER
MOV CL,PRINTMES
CALL SYSTEM
MOV DX,CPYRHT
CAL AL,-1 ;Flag that no tokens have been read yet
MOV [SYM],AL
CALL ASMLIN ;Assemble the line
MOV AL,[SYM]
CMP AL,-1 ;AnBX ;DEFAULT PROGRAM COUNTER
MOV [BASE],BX ;POINTER TO ROOT OF ID TREE=NIL
MOV [RETPT],BX ;Pointer to last RET record
DEC OV DX,FCB+9
MOV BX,EXTEND ;Set extension to ASM
MOV CX,7
UP
MOV SI,BX
MOV DI,DX
REP
MOVB
MOV DX,DI
MOV BX,SI
CMP AL,'X' ;PRN file to console?
JZ NOPRN
CALL CHKDSK
NOPRN:
MOV [LSTFCB],AL
CALL ADDEXT
MOV DX,FCB
MOV CL,OPEN
for linefeed
JP GETEOL
ABORT:
MOV BX,NOMEM
PRERR:
XCHG DX,BX
MOV CL,PRINTMES
CALL SYSTEM
JMP 0
MAKFIL:
MOV L SYSTEM
MOV AL,[FCB+17]
MOV [SYMFLG],AL ;Save symbol table request flag
MOV BX,FCB+9 ;Point to file extension
MOV AL,[By tokens found on line?
JNZ L0002
CALL GETSYM ;If no tokens read yet, read first one
L0002:
CMP AL,';'
JZ ENDLN
CMPBX
MOV [LSTRET],BX ;Location of last RET
MOV BX,[6] ;HL=END OF MEMORY
MOV [HEAP],BX ;BACK END OF SYMBOL TABLE SPACE
MOV RET
CHKDSK:
SUB AL,' ' ;If not present, set zero flag
JZ RET
SUB AL,20H
JZ DSKERR ;Must be in range A-W
CMP AL,' CALL SYSTEM
MOV BX,NOFILE
INC AL
JNZ $+5
JMP PRERR
XOR AL,AL
MOV [FCB+32],AL ;Zero Next Record field
MOV DX,HEXFCSI,DX
LODB ;Get drive select byte
CMP AL,20H ;If not valid, don't make file
JNC RET
PUSH DX
INC DX
MOV BX,FCB+1
X] ;Get source drive letter
CALL CHKDSK ;Valid drive?
OR AL,AL
JZ DEFAULT ;If no extension, use existing drive spec
M AL,EOL
JZ ENDLN
MOV AL,14H ;Garbage at end of line error
JP ENDLIN
ENDJ: JMP END
ENDLN:
XOR AL,AL ;Flag no errors AL,4
MOV [BCOUNT],AL ;CODE BYTES PER RELOCATION BYTE
XOR AL,AL
MOV [IFFLG],AL ;NOT WITHIN IF/ENDIF
MOV [CHKLAB],AL ;LOOX'-'@'
JC RET
DSKERR:
MOV BX,BADDSK
JP PRERR
ERROR:
MOV AL,CL
JMP ENDLIN
NEXTCHR:
XCHG BX,[HL]
XCHG DX,[DE]B
CALL MAKFIL
MOV DX,LSTFCB
CALL MAKFIL
MOV BX,0FFH
XCHG BX,[HL]
XCHG DX,[DE]
XCHG CX,[BC]
MOV BX,START+1 ;POINT MOV CX,8
UP
MOV SI,BX
MOV DI,DX
REP
MOVB ;Copy source file name
MOV DX,DI
MOV BX,SI
POP DX
MOV CL,DELETE
OV [FCB],AL
DEFAULT:
INC BX
MOV AL,[BX] ;Get HEX file drive letter
CMP AL,'Z' ;Suppress HEX file?
JZ L0000
CALL CHK on line
ENDLIN:
MOV SP,STACK
CALL NEXLIN
JP LOOP
NEXLIN:
MOV CH,0C0H ;Put end of line marker and error code (AL)
KUP ALL LABELS
;Assemble each line of code
LOOP:
CALL NEXTCHR ;Get first character on line
CMP AL,1AH
JZ ENDJ
MOV
XCHG CX,[BC]
INC BL
JNZ GETCH
;Buffer empty so refill it
MOV DX,80H
MOV CL,SETDMA
CALL SYSTEM
XCHG DX,BX
MOV DER TO NEXT BYTE OF INTERMEDIATE CODE
MOV [CODE],BX
MOV [IY],START ;POINTER TO CURRENT RELOCATION BYTE
MOV BX,0
MOV [PC],CALL SYSTEM
MOV CL,MAKE
CALL SYSTEM
MOV BX,NOSPAC
INC AL ;Success?
JZ PRERR
MOV CL,OPEN
JMP SYSTEM
ADDEXT:
MDSK
L0000:
MOV [HEXFCB],AL
INC BX
MOV AL,[BX] ;Get PRN file drive letter
CMP AL,'Z' ;Suppress PRN file?
JZ NOPRN
CALL PUTCD
CALL GEN1
MOV AL,[CHR]
GETEOL:
CMP AL,10
JZ RET
CMP AL,1AH
JZ ENDJ
CALL NEXTCHR ;Scan over comments X,FCB
MOV CL,READ
CALL SYSTEM
OR AL,AL
MOV AL,1AH ;Possibly signal End of File
JNZ NOMOD ;If nothing read
GETCH:
SUB AL,DH ;Check if source is 16-bit register
JZ RR ;If so, AL must be zero
AND CH,0FDH ;Change direction
XCHG DX,BX ber into middle position
ADD AL,AL
ADD AL,AL
OR AL,0C0H ;Set register-to-register mode
OR AL,DL ;Combine with other reord bit
AND AL,CL ;But don't use it in word-only operations
OR AL,CH ;Combine with OP code
CALL PUT
MOV AL,BL
ADD AL JZ RET
MOV AL,UNDEFID ;Check for memory reference
CMP AL,BH
JZ STORE ;Is destination memory?
CMP AL,DH
JZ LOAD ;Is
OR AL,BL ; meaning direct load/store of accumulator
JNZ NOTAC
TEST CL,8 ;See if direct load/store of accumulator
JZMOV AL,[BX]
NOMOD:
XCHG BX,[HL]
XCHG DX,[DE]
XCHG CX,[BC]
MOV [CHR],AL
RET
MROPS:
PUSH CX ;Save type flags
;Flip which operand is first and second
MOV AL,XREG
SUB AL,DH ;Let RR perform finish the test
JP RR
STORE:
TEST CL,gister number
JMP PUT
SEGCHK:
;Come here if at least one operand is a segment register
POP CX ;Restore flags
RCR SI
,AL ;Rotate to middle position
ADD AL,AL
ADD AL,AL
OR AL,DL ;Combine register field
POP CX ;Dump return address
JMPsource memory?
RCR SI
TEST CL,1 ;Check if register-to-register operation OK
RCL SI
MOV CL,27
JZ ERROR
MOV AL,DH
C NOTAC ; means anything in this case
; Process direct load/store of accumulator
MOV AL,CH
AND AL,2 ;Preserve direction CALL GETOP
PUSH DX ;Save first operand
CALL GETOP2
POP BX ;First op in BX, second op in DX
MOV AL,SREG ;Check for a s004H ;Check if storing is OK
JNZ STERR
XCHG DX,BX ;If so, flip operands
AND CH,0FDH ; and zero direction bit
LOAD:
TEST CL,8 ;Check if segment register OK
RCL SI
MOV CL,22
JZ ERR1
MOV CX,8E03H ;Segment register move OP code
MOV AL, PUTADD ;Write the address
STERR:
MOV DH,29
MRERR:
MOV CL,DH
ERR1: JMP ERROR
GETOP2:
;Get the second operand: loMP AL,BH ;Registers must be of same length
RR:
MOV CL,22
JNZ ERROR
RR1:
AND AL,1 ;Get register length (1=16 bits)
ORbit only
XOR AL,2 ; but flip it
OR AL,0A0H ;Combine with OP code
MOV CH,AL
MOV AL,BH ;Check byte/word operation
Aegment register
CMP AL,BH
JZ SEGCHK
CMP AL,DH
JZ SEGCHK
MOV AL,CONST ;Check if the first operand is immediate
MOV CL MOV DH,25
CMP AL,BH ;Check if memory-to-memory
JZ MRERR
MOV AL,BH
CMP AL,REG ;Check if 8-bit operation
JNZ XRG
MOUNDEFID
CMP AL,DH ;Check if source is memory
JZ LOAD
CMP AL,BH ;Check if destination is memory
JZ STORE
MOV AL,XREG
ok for a comma and drop into GETOP
MOV AL,[SYM]
CMP AL,','
MOV CL,21
JNZ ERR1
GETOP:
CALL GETSYM
GETOP1:
;Enter AL,CH ;Or in to OP code
CALL PUT ;And write it
POP CX ;Dump return address
MOV AL,BL
ADD AL,AL ;Rotate register numND AL,1
OR AL,CH
POP CX ;Dump return address
JMP PUTADD ;Write the address
NOTAC:
MOV AL,BH
AND AL,1 ;Get byte/w,26
CMP AL,BH
JZ ERROR ;Error if so
POP CX ;Restore type flags
CMP AL,DH ;If second operand is immediate, then done
V DH,22
TEST CL,1 ;See if 8-bit operation is OK
JZ MRERR
XRG:
MOV AL,DL
SUB AL,6 ;Check for R/M mode 6 and register 0 here if we don't need a GETSYM first
CMP AL,'[' ;Memory reference?
JZ MEM
CMP AL,5 ;Flag ("B", "W", etc.)?
JZ FLG
Check for SI
MOV CL,4
JZ SIJ
DEC AL ;Check for DI
JZ DIJ
MOV CL,2 ;Invalid base/index register
ERR2: JMP ERROR
DIJ:SAHF
LAHF
XCHG AX,BP
SAHF
CALL GETSYM
OPERATE:
CMP AL,CONST
JNZ $+5
JMP CVAL
CMP AL,UNDEFID
JNZ $+5
JMP UVAZ PJ
LAHF
XCHG AX,BP
SAHF
MOV CH,0
RCR SI
TEST AL,010H ;Test INDEX bit
RCL SI
RCL AL ;BASE bit (zero flag not CALL GETSYM
MOV BX,[CON]
MOV [ADDR],BX
MOV BX,[UNDEF]
MOV [ALABEL],BX
MOV DL,CH
MOV DH,UNDEFID
MOV AL,DH
RET
Fr BX
SAHF
JP LPCHK
BPJ:
LAHF
XCHG AX,BP
SAHF
RCR SI
TEST AL,080H ;Check if already seen base register
RCL SI
MP AL,REG ;8-Bit register?
JZ NREG
CMP AL,XREG ;16-Bit register?
JZ NREG
CMP AL,SREG ;Segment register?
JZ NREG
VA
LAHF
XCHG AX,BP
SAHF
RCR SI
TEST AL,10H ;Check if already seen index register
RCL SI
JNZ ERR2
OR AL,30H ;FlagL
CMP AL,'"'
JNZ $+5
STRINGJ:JMP STRING
CMP AL,"'"
JZ STRINGJ
CMP AL,XREG ;Only 16-bit register may index
MOV CL,2affected)
JZ NOIND ;Jump if not indexed, with BASE bit in carry
CMC
RCL CH
RCL AL ;BP bit
RCL CH
RCL AL ;DI bit
LG:
CALL GETSYM
CMP AL,','
JZ GETOP
JP GETOP1
GETVAL:
LAHF
XCHG AX,BP
SAHF
PUSH BX
MOV BX,0
MOV [CON],B JNZ ERR2
OR AL,0C0H ;Flag seeing base register BP
LPCHK:
LAHF
XCHG AX,BP
SAHF
POP AX ;Get operator
XCHG AH,AL
L: ;Must be immediate
XOR AL,AL ;No addressing modes allowed
VAL1:
CALL GETVAL
MOV BX,[CON] ;Defined part
MOV [DATA seeing index register DI
JP LPCHK
SIJ:
LAHF
XCHG AX,BP
SAHF
RCR SI
TEST AL,010H ;Check if already seen index regi0
JNZ ERR2
LAHF
XCHG AX,BP
SAHF
RCR SI
TEST AL,1 ;Check to see if indexing is OK
RCL SI
MOV CL,1
JZ ERR2
LA RCL CH ;The low 3 bits now have indexing mode
MODE:
MOV BX,[UNDEF]
MOV AL,BH
OR AL,BL
LAHF
OR CH,080H ;If undefineX
MOV [UNDEF],BX
POP BX
MOV AL,[SYM]
CMP AL,'+'
JZ PLSMNS
CMP AL,'-'
JZ PLSMNS
MOV CH,'+'
PUSH CX
JP OPERATESAHF
CMP AL,'-' ;Can't subtract a register
MOV CL,5
JZ ERR2
NEXTER:
LAHF
XCHG AX,BP
SAHF
LAHF
OR AL,4 ;Flag t],BX
MOV BX,[UNDEF] ;Undefined part
MOV [DLABEL],BX
MOV DL,CH
MOV DH,CONST
MOV AL,DH
RET
NREG:
PUSH DX
CALL GETster
RCL SI
JNZ ERR2
LAHF
OR AL,010H ;Flag seeing index register SI
SAHF
JP LPCHK
BXJ:
LAHF
XCHG AX,BP
SAHF
HF
XCHG AX,BP
SAHF
MOV AL,DL
MOV CL,3
CMP AL,3 ;Check for BX
JZ BXJ
SUB AL,5 ;Check for BP
JZ BPJ
DEC AL ;Cd label, force 16-bit displacement
SAHF
JNZ RET
MOV BX,[CON]
CALL SIGNEXT ;Check if 8-bit with sign extended
JNZ RET
PLSMNS:
LAHF
XCHG AH,AL
PUSH AX
XCHG AH,AL
LAHF
XCHG AX,BP
SAHF
LAHF
OR AL,4 ;Flag that a sign was found
hat a term was processed
SAHF
LAHF
XCHG AX,BP
SAHF
CALL GETSYM
CMP AL,'+'
JNZ $+5
PJ: JMP PLSMNS
CMP AL,'-'
JSYM
POP DX
MOV AL,DH
RET
MEM:
CALL GETSYM
MOV AL,1
CALL GETVAL
MOV AL,[SYM]
CMP AL,']'
MOV CL,24
JNZ ERR1
RCR SI
TEST AL,080H ;Check if already seen base register
RCL SI
JNZ ERR2
LAHF
OR AL,080H ;Flag seeing base registe ;If not, use 16-bit displacement
LAHF
AND CH,07FH ;Reset 16-bit displacement
SAHF
LAHF
OR CH,040H ;Set 8-bit displaX],CONST
CALL READID
LAHF
DEC BX
SAHF
MOV AL,[BX]
MOV CL,7
MOV BX,0
CMP AL,'h'
JNZ $+5
JMP HEX
INC CL
MO only be added
MOV CL,5
ERR30: JNZ ERR3
JMP NEXTER
GETSYM:
CALL GETSY
MOV AL,[SYM]
RET
SCANB:
MOV AL,[CHR]
HL BX
SHL BX
ADD BL,AL
DEC CH
JNZ HEX1
XCHG DX,BX
RET
ERR4: JMP ERROR
GETLET:
CALL SCANB
CMP AL,EOL
STC
C CH ;If not, must be BX
JP MODE
CVAL:
MOV BX,[CON]
POP AX
XCHG AH,AL
SAHF
CMP AL,'-'
JNZ ADDCON
SBB BX,DX
AL,DL
CMP AL,EOL
MOV CL,39
JZ ERR3
CALL PUT
MOV AL,[DATSIZ]
OR AL,AL
JNZ BYTSIZ
MOV AL,DH
CALL PUT
BYTSIZ:
cement
SAHF
MOV AL,BH
OR AL,BL
JNZ RET ;Use it if not zero displacement
MOV AL,CH
AND AL,7 ;Specify no displacemenV [IX],ID
DEC:
MOV SI,[IX]
MOV AL,[SI]
INC [IX]
CMP AL,'9'+1
JC $+5
ERR3: JMP ERROR
SUB AL,'0'
MOV DX,BX
SHL B
SCANT:
CMP AL,' '
JZ NEXB
CMP AL,9
JNZ RET
NEXB:
CALL NEXTCHR
JP SCANT
DOLLAR:
MOV DX,[OLDPC]
MOV AL,CONST
JZ RET
CMP AL,';'
STC
JZ RET
MOV CL,10
OR AL,20H
CMP AL,'a'
JC ERR4
CMP AL,'z'+1
JNC ERR4
READID:
MOV BX,SETCON:
MOV [CON],BX
JMP NEXTER
ADDCON:
LAHF
ADD BX,DX
RCR SI
SAHF
RCL SI
JP SETCON
UVAL:
LAHF
XCHG AX,BMOV AL,[CHR]
MOV DL,AL
CALL GETCHR
JP STRGDAT
ZERLEN:
CALL NEXTCHR
CMP AL,CH
JNZ ERR3
RET
GETCHR:
CALL NEXTCHRt
MOV CH,AL
CMP AL,6 ;Check for BP+0 addressing mode
JNZ RET
LAHF
OR CH,040H ;If BP+0, use 8-bit displacement
SAHFX
SHL BX
ADD BX,DX
SHL BX
MOV DL,AL
MOV DH,0
ADD BX,DX
DEC CH
JNZ DEC
XCHG DX,BX
RET
STRING:
MOV CH,AL
MOV [SYM],AL
NEXTCHJ:
JMP NEXTCHR
GETSY:
CALL SCANB
CMP AL,'$'
JZ DOLLAR
MOV [SYM],AL
OR AL,20H
CMP AL,'z'+1ID
MOV CH,0
MOREID:
MOV [BX],AL
INC CH
LAHF
INC BX
SAHF
CALL NEXTCHR
CMP AL,'0'
JC NOMORE
OR AL,20H
CMP AP
SAHF
MOV CL,6
RCR SI
TEST AL,008H ;Check if undefined label has been seen
RCL SI
JNZ ERR30
LAHF
OR AL,008H ;
CMP AL,CH
JNZ RET
CALL NEXTCHR
CMP AL,CH
JZ RET
POP BX
JMP CVAL
HEX:
MOV DX,ID
DEC CH
HEX1:
MOV SI,DX
RET
SIGNEXT:
MOV AL,BH
OR AL,AL
JZ HIZERO
INC AL
JNZ RET
HIZERO:
MOV AL,BL
XOR AL,BH
AND AL,80H
RET
MOV AL,[CHR]
CMP AL,CH
MOV CL,35
MOV DL,AL
MOV DH,0
JNZ L0003
CALL ZERLEN
L0003:
CALL GETCHR
LAHF
XCHG AX,
JNC NEXTCHJ
CMP AL,'a'
JC $+5
JMP LETTER
CMP AL,'9'+1
JNC NEXTCHJ
CMP AL,'0'
JC NEXTCHJ
MOV BX,SYM
MOV B,[BL,'z'+1
JNC NOMORE
CMP AL,'9'+1
JC MOREID
CMP AL,'a'
JNC MOREID
NOMORE:
MOV CL,AL
MOV AL,CH
MOV [LENID],AL
ORFlag seeing undefined label
XCHG AX,BP
SAHF
MOV [UNDEF],BX
POP AX
XCHG AH,AL
SAHF
CMP AL,'+' ;Undefined label may LODB
INC DX
SUB AL,'0'
CMP AL,10
JC GOTIT
CMP AL,'g'-'0'
JNC ERR4
SUB AL,'a'-10-'0'
GOTIT:
SHL BX
SHL BX
SNOIND:
MOV CH,6 ;Try direct address mode
JNC RET ;If no base register, that's right
RCL AL ;Check BP bit
JC MODE
INBP
SAHF
MOV CL,37
TEST AL,002H
JZ ERR3
TEST AL,004H
MOV CL,38
JNZ ERR3
LAHF
XCHG AX,BP
SAHF
STRGDAT:
MOV AL,AL
MOV AL,CL
RET
LETTER:
CALL READID
MOV AL,CH
DEC AL
JNZ NOFLG
MOV AL,[ID]
CMP AL,'l'
MOV CL,0
MOV D080H
SAHF
MOV DX,RETSTR+2
CHKRET:
MOV SI,DX
LODB
CMP AL,[BX]
JNZ LOOKIT
LAHF
DEC BX
SAHF
LAHF
DEC DX
SA
SEGTAB: DB 'dsce'
LOOK:
MOV CH,[BX]
LAHF
INC BX
SAHF
MOV DX,ID
CALL CPSLP
JZ RET
XOR AL,80H
MOV CL,AL
LAV BX,[HEAP]
MOV DL,AL
MOV DH,0
SBB BX,DX ;Heap grows downward
MOV [HEAP],BX
XCHG DX,BX
MOV BX,[CODE] ;Check to make,REG
CMP AL,'l'
JZ SCANREG
MOV DL,4
CMP AL,'h'
JZ SCANREG
MOV DH,SREG
MOV DL,0
MOV BX,SEGTAB
CMP AL,'s'
JZ STER
MOV DX,4
LAHF
ADD BX,DX
RCR SI
SAHF
RCL SI
MOV AL,[BX]
OR AL,AL
JZ RET
LAHF
INC BX
SAHF
MOV DL,[BXX,LONG
JZ BWFLAG
CMP AL,'b'
MOV DX,FLAG
JZ BWFLAG
CMP AL,'w'
MOV CL,1
JZ BWFLAG
XOR AL,AL
NOFLG:
DEC AL
PUSHF
DEC CH
JNZ CHKRET
MOV DX,[LSTRET]
MOV AL,DL
AND AL,DH
INC AL
JZ ALLRET
MOV BX,[PC]
SBB BX,DX
CALL SIGNEXTHF
DEC BX
SAHF
MOV AL,[BX]
XOR AL,80H
CMP AL,CL
JNC SMALL
INC CH
INC CH
SMALL:
MOV DL,CH
MOV DH,0
LAHF
sure there's enough
SBB BX,DX
JB $+5
JMP ABORT
PUSH DX
MOV BX,LENID
MOV CL,[BX]
INC CL
MOV CH,0
UP
MOV SI,BCANREG
MOV DH,XREG
CMP AL,'p'
JZ PREG
CMP AL,'i'
JNZ RET
MOV DL,6
MOV AL,CL
CMP AL,'s'
JZ RET
INC DL
CMP A]
LAHF
INC BX
SAHF
MOV DH,[BX]
RET
ENTER:
PUSH BX ;Save pointer to link field
CALL CREATE ;Add the node
POPH BX
JNZ L0004
CALL REGCHK
L0004:
POP BX
MOV AL,DH
JZ SYMSAV
CALL LOOKRET
SYMSAV:
MOV [SYM],AL
RET
BWFLAG:
MOV AL,1
JZ RET
ALLRET:
MOV BX,[RETPT]
MOV AL,BH
OR AL,BL
MOV AL,0
JNZ RET
MOV BX,[HEAP]
LAHF
DEC BX
SAHADD BX,DX
RCR SI
SAHF
RCL SI
MOV DL,[BX]
LAHF
INC BX
SAHF
MOV DH,[BX]
MOV AL,DH
OR AL,DL
STC
JZ RET
XCX
MOV DI,DX
REP
MOVB ;Move identifier and length into node
MOV DX,DI
MOV BX,SI
MOV CH,4
XCHG DX,BX
NILIFY:
MOL,'d'
RET
PREG:
MOV DL,4
MOV AL,CL
CMP AL,'s'
JZ RET
INC DL
CMP AL,'b'
RET
SCANREG:
MOV AL,CL
MOV CX,4
U SI
XCHG SI,BX
PUSH SI
MOV [BX],DH ;Link new node
LAHF
DEC BX
SAHF
MOV [BX],DL
POP BX
RET ;Zero was set by
XCHG DX,BX
MOV AL,[BX]
INC AL
MOV [BX],CL
MOV CL,32
JZ $+5
JMP ERROR
MOV AL,5
JP SYMSAV
REGCHK:
MOV BX,IF
LAHF
DEC BX
SAHF
LAHF
DEC BX
SAHF
MOV [HEAP],BX
XOR AL,AL
MOV [BX],AL
MOV [RETPT],BX
RET
LOOKUP:
LAHG DX,BX
JP LOOK
LOOKRET:
MOV AL,CH
CMP AL,3 ;RET has 3 letters
JNZ LOOKUP
LAHF
DEC BX
SAHF
LAHF
OR B,[BX],V [BX],CL ;Zero left and right links
INC BX
DEC CH
JNZ NILIFY
XOR AL,AL ;Set zero flag
MOV [BX],AL ;Zero defined flP
MOV DI,BX
REPNZ
SCAB
MOV BX,DI
JNZ RET
MOV AL,CL
ADD AL,DL
MOV DL,AL
XOR AL,AL
RET
REGTAB: DB 'bdca'
CREATE
EMPTY:
CALL CREATE
MOV [BASE],DX
RET
CREATE:
MOV AL,[LENID]
ADD AL,8 ;Storage needed for the node
MOD
MOV CL,[BX]
LAHF
INC BX
SAHF
MOV AL,[BX]
MOV BX,REGTAB
MOV DH,XREG
MOV DL,0
CMP AL,'x'
JZ SCANREG
MOV DHHF
DEC BX
SAHF
LAHF
OR B,[BX],080H
SAHF
LOOKIT:
MOV BX,[BASE]
MOV AL,BH
OR AL,BL
JZ EMPTY
CALL LOOK
JC ENag
POP DX ;Restore pointer to node
RET
CPSLP:
MOV SI,DX
LODB
CMP AL,[BX]
LAHF
INC DX
INC BX
SAHF
JNZ RET6H
MOV AL,BH
CMP AL,UNDEFID
JNZ L0006
CALL STIMM
L0006:
AND AL,1
JZ BYTIMM
MOV AL,0B8H
OR AL,BL
CALL PUT
J INC CH
MOV CL,CH
MOV AL,[BX]
LAHF
INC BX
SAHF
OR AL,AL
JZ OPERR
FINDOP:
MOV CH,CL
LAHF
XCHG AX,BP
SAHF
,[CODE]
MOV [BX],AL
LAHF
INC BX
SAHF
MOV [CODE],BX
POP BX
RET
PUTWOR:
PUSH CX
MOV CH,80H
PUSH DX
PUSH B
LAHF
INC BX
SAHF
MOV [BX],DH
JMP GETLET
ERR5: JMP ERROR
ASMLIN:
MOV BX,[PC]
MOV [OLDPC],BX
CALL GETLAB
J ;Flag as pure code
CALL GEN
POP CX
POP BX
RET
GEN:
CALL PUTINC ;Save it and bump code pointer
GEN1:
MOV AL,[R
DEC CH
JNZ CPSLP
RET
GETLAB:
MOV BX,0
MOV [LABPT],BX
MOV AL,-1
MOV [FLAG],AL
MOV [LONG],AL
MOV DH,0
MOV MP PUTWOR
BYTIMM:
MOV AL,0B0H
OR AL,BL
CALL PUT
PUTBJ: JMP PUTBYT
IMMED:
MOV AL,BH
CMP AL,UNDEFID
JZ STIMM
MOV DX,ID+1
CALL CPSLP
JZ HAVOP
MOV DH,0
MOV DL,CH
INC DL
INC DL
LAHF
ADD BX,DX
RCR SI
SAHF
RCL SI
LAHFX
JP PUTBW
PUTBYT:
PUSH CX
MOV CH,40H
PUSH DX
PUSH BX
MOV BX,[DLABEL]
MOV AL,BH
OR AL,BL
JNZ PUTBW
MOV BXNC $+5
JMP ENDLN
MOV BX,LENID
MOV AL,[BX]
MOV CL,12
SUB AL,2
MOV CH,AL
JC ERR5
CMP AL,5
JNC ERR5
LAHF
INC ELOC]
RCL CH
RCL AL
RCL CH
RCL AL
MOV [RELOC],AL
MOV BX,BCOUNT
DEC B,[BX]
JNZ RET
MOV B,[BX],4
MOV BX,RELOC
AL,[CHR]
CMP AL,' '+1
JC NOT1
LAHF
OR DH,001H
SAHF
NOT1:
CALL GETLET
JC RET
CMP AL,':'
JNZ LABCHK
CALL NEXTMOV AL,BL
OR AL,AL
JZ RET
MOV AL,BH
CALL IMM
OR AL,0C0H
CALL PUT
FINIMM:
MOV AL,CL
POP CX
RCR SI
TEST AL,00
XCHG AX,BP
SAHF
DEC AL
JNZ FINDOP
OPERR:
MOV CL,12
JMP ERROR
HAVOP:
MOV DL,[BX]
LAHF
INC BX
SAHF
MOV ,[DATA]
OR AL,BH
JZ PUTBW
INC BH
JZ PUTBW
MOV CL,31
JMP ERROR
PUTBW:
MOV DX,[DLABEL]
MOV BX,[DATA]
PUTCHK:
MBX
SAHF
MOV AL,[BX]
SUB AL,'a'
MOV CL,AL
ADD AL,AL
ADD AL,AL
ADD AL,CL
ADD AL,CH
ADD AL,AL
MOV BX,OPTAB
MO
MOV AL,[BX]
MOV B,[BX],0
MOV DI,[IY]
MOV [DI],AL
MOV BX,[CODE]
PUSH BX
POP [IY]
LAHF
INC BX
SAHF
MOV [CODECHR
JP LABEL
LABCHK:
OR AL,AL
RCR SI
TEST DH,001H
RCL SI
JZ RET
LABEL:
MOV AL,[CHKLAB]
OR AL,AL
JZ $+5
JMP1H
RCL SI
JZ PUTBJ
CMP AL,83H
JZ PUTBJ
JMP PUTWOR
STIMM:
MOV AL,[FLAG]
CALL IMM
CALL PUTADD
JP FINIMM
IMDH,[BX]
LAHF
INC BX
SAHF
MOV AL,[BX] ;Get opcode
XCHG DX,BX
JMP BX
GRP1:
MOV CX,8A09H
CALL MROPS
MOV CX,0COV AL,DH
OR AL,DL
JZ NOUNDEF
MOV AL,DL
CALL PUTCD
MOV AL,DH
CALL PUTCD
MOV AL,BL
CALL PUTINC
MOV AL,BH
RCR SV DL,AL
MOV DH,0
LAHF
ADD BX,DX
RCR SI
SAHF
RCL SI
MOV DL,[BX]
LAHF
INC BX
SAHF
MOV DH,[BX]
XCHG DX,BX
],BX
RET
PUTINC:
PUSH BX
MOV BX,[PC]
LAHF
INC BX
SAHF
MOV [PC],BX
JP PUTCD1
PUTCD:
PUSH BX
PUTCD1: MOV BX GETLET
CALL LOOKUP
MOV CL,11
JNZ ERR5
MOV DX,[PC]
MOV B,[BX],1
LAHF
INC BX
SAHF
MOV [BX],DL
MOV [LABPT],BX
M:
AND AL,1
OR AL,CL
MOV CL,AL
CALL PUT
MOV AL,CH
AND AL,38H
OR AL,BL
RET
PUT:
PUSH BX
PUSH CX
MOV CH,0I
TEST CH,080H
RCL SI
JZ SMPUT
CALL GEN
JP PRET
SMPUT:
CALL PUTCD
CALL GEN1
PRET:
POP BX
POP DX
POP CX
RP4:
LAHF
XCHG AH,AL
PUSH AX
XCHG AH,AL
CALL GETOP
POP CX
CMP AL,CONST
JZ FIXED
SUB AL,XREG
DEC DL
DEC DL
L,CONST
CMP AL,BH
JZ ERR6
CMP AL,DH
JZ ERR6
MOV AL,UNDEFID
CMP AL,BH
JZ EXMEM
CMP AL,DH
JZ EXMEM1
MOV AL,BH
AL,DH
OR AL,DL
JNZ ACCJ
XCHG DX,BX
MOV BX,[DATA]
CALL SIGNEXT
XCHG DX,BX
JNZ ACCJ
LAHF
OR CL,002H
SAHF
ACCJether one- or two-byte displacement
TWOBT:
MOV BX,[ADDR]
MOV DX,[ALABEL]
JP PUTCHK
GRP2:
CALL GETOP
MOV CX,0FF30H
LAHF
ADD BX,DX
RCR SI
SAHF
RCL SI
MOV [PC],BX
XCHG DX,BX
MOV AL,-4
JP NEWLOC
EQU:
XCHG DX,BX
MOV BX,[LABPT]ET
NOUNDEF:
MOV AL,BL
MOV CL,BH
PUSH CX
MOV CH,0
CALL GEN
POP CX
MOV AL,CL
RCR SI
TEST CH,080H
RCL SI
M OR AL,DL
MOV CL,20
JNZ ERR6
MOV AL,CH
OR AL,8
JMP PUT
FIXED:
MOV AL,CH
CALL PUT
JMP PUTBYT
GRP5:
LAHF
X
CMP AL,DH
MOV CL,22
JNZ ERR6
CMP AL,XREG
JZ L0008
CALL RR1
L0008: ;RR1 never returns
MOV AL,BL
OR AL,AL
JZ : JMP ACCIMM
GRP8:
MOV CL,AL
MOV CH,0FEH
JP ONEOP
GRP9:
MOV CL,AL
MOV CH,0F6H
ONEOP:
PUSH CX
CALL GETOP
ONE:
CMP AL,UNDEFID
JZ PMEM
MOV CH,50H
CMP AL,XREG
JZ PXREG
MOV CH,6
CMP AL,SREG
JNZ $+5
JMP PACKREG
MOV CL,20
MOV AL,BH
OR AL,BL
MOV CL,34
JZ ERR7
MOV [BX],DL
LAHF
INC BX
SAHF
MOV [BX],DH
RET
ORG:
MOV [PC],BX
MOVOV CH,0
JZ PRETJ
CALL GEN
PRETJ: JP PRET
PUTADD:
PUSH CX
PUSH DX
PUSH BX
MOV CH,0
MOV CL,AL
CALL GEN ;Save CHG AH,AL
PUSH AX
XCHG AH,AL
CALL GETOP
CMP AL,CONST
JNZ ERR6
MOV BX,[DLABEL]
MOV AL,BH
OR AL,BL
MOV CL,30
JEXACC
XCHG DX,BX
MOV AL,BL
OR AL,AL
MOV AL,BH
JZ EXACC
CALL RR1
EXACC:
MOV AL,90H
OR AL,DL
JMP PUT
EXMEM:
MOV CL,26
CMP AL,CONST
JZ ERR7
CMP AL,SREG
MOV CL,22
JZ ERR7
POP CX
CMP AL,UNDEFID
JZ MOP
AND AL,1
JZ ROP
JMP ERROR
PMEM:
MOV AL,CH
CALL PUT
MOV AL,CL
OR AL,DL
JMP PUTADD
PXREG:
MOV AL,CH
OR AL,DL
JMP PUT
GRP3 AL,-2
NEWLOC:
CALL PUTCD
MOV AL,BL
CALL PUTCD
MOV AL,BH
CALL PUTCD
MOV CH,0C0H
JMP GEN1
GRP6:
MOV CH,AL
MOVthe addressing mode as pure code
MOV AL,CL
MOV CH,80H
AND AL,0C7H
CMP AL,6
JZ TWOBT ;Direct address?
AND AL,0C0H
NZ ERR6
MOV BX,[DATA]
POP AX
XCHG AH,AL
SAHF
OR AL,AL
JZ ORG
DEC AL
JZ DSJ
DEC AL
JZ EQU
DEC AL
JZ $+5
XCHG DX,BX
EXMEM1:
CMP AL,BH
JZ ERR6
MOV CL,1 ;Flag word as OK
CALL NOTAC ;NOTAC never returns
ERR6: JMP ERROR
GR RCR SI
TEST CL,001H
RCL SI
JZ ROP
MOV AL,CL
AND AL,0F8H
OR AL,DL
JMP PUT
MOP:
MOV AL,[FLAG]
AND AL,1
OR AL:
CALL GETOP
PUSH DX
CALL GETOP2
POP BX
MOV CX,8614H
MOV AL,SREG
CMP AL,BH
JZ ERR6
CMP AL,DH
JZ ERR6
MOV A CL,4
CALL MROPS
MOV CL,23
ERR7: JMP ERROR
GRP7:
MOV CH,AL
MOV CL,1
CALL MROPS
MOV CL,80H
MOV DX,[DLABEL]
MOV JZ PRET ;Indirect through reg, no displacement?
CMP AL,0C0H
JZ PRET ;Register to register operation?
MOV CH,AL ;Save wh JMP IF
PUTOP:
MOV AL,-3
JP NEWLOC
ALIGN:
MOV AL,[PC]
AND AL,1
JZ RET
MOV BX,1
DSJ:
XCHG DX,BX
MOV BX,[PC]
,CH
CALL PUT
MOV AL,CL
AND AL,38H
OR AL,DL
JMP PUTADD
ROP:
OR AL,CH
CALL PUT
MOV AL,CL
AND AL,38H
OR AL,0C0JMP PUTWOR
LONGJ:
POP AX
XCHG AH,AL
SAHF
CALL PUT
CALL PUTWOR
CALL GETOP
MOV CL,20
CMP AL,CONST
JNZ ERR8
JM,20
CMP AL,REG
JZ ERR8
CMP AL,SREG
JZ ERR8
CMP AL,XREG
JNZ NOTRG
OR DL,040H
OR DL,080H
NOTRG:
MOV AL,0FFH
CATA]
CALL SIGNEXT
JZ RET
MOV CL,31
ERR10: JMP ERROR
RET
GRP18:
CALL GETOP
CMP AL,CONST
MOV CL,20
JNZ ERR10
MUB AL,REG
MOV CL,20
DEC DL
OR AL,DL
JNZ ERR8
POP DX
MOV AL,DH
POP CX
LAHF
OR CH,002H
SAHF
PUSH CX
JMP ON
JP GETSP
NODEC:
MOV BX,[PC]
MOV [LSTRET],BX
XCHG DX,BX
MOV BX,[RETPT]
MOV AL,BH
OR AL,BL
JZ DORET
MOV B,[BX],H
OR AL,DL
JMP PUT
GRP10:
MOV CL,AL
MOV CH,0F6H
PUSH CX
CALL GETOP
MOV CL,20
MOV AL,DL
OR AL,AL
JNZ ERRJ1
P PUTWOR
GRP16:
LAHF
XCHG AH,AL
PUSH AX
XCHG AH,AL
CALL GETSYM
CMP AL,5
JZ LONGR
CMP AL,EOL
JZ NODEC
CMP ALALL PUT
POP AX
XCHG AH,AL
SAHF
AND AL,38H
OR AL,DL
MOV CH,AL
MOV AL,[LONG]
OR AL,AL
MOV AL,CH
JZ PUTADDJ
AOV BX,[DLABEL]
MOV AL,BH
OR AL,BL
JNZ GENINT
MOV BX,[DATA]
MOV DX,3
SBB BX,DX
JNZ GENINT
MOV AL,0CCH
JMP PUT
E
GRP13:
MOV CH,AL
MOV CL,1
CALL MROPS
MOV CL,80H
ACCIMM:
CALL IMMED
OR CH,004H
AND CH,0FDH
AIMM:
MOV AL,BH
1
LAHF
INC BX
SAHF
MOV [BX],DL
LAHF
INC BX
SAHF
MOV [BX],DH
MOV BX,0
MOV [RETPT],BX
DORET:
POP AX
XCHG MOV AL,DH
CMP AL,XREG
JZ G10
CMP AL,REG
ERRJ1: JNZ ERR8
G10:
LAHF
XCHG AH,AL
PUSH AX
XCHG AH,AL
CALL GETOP
,';'
JZ NODEC
GETSP:
CALL GETOP1
POP CX
CMP AL,CONST
MOV CL,20
JNZ ERR9
MOV AL,CH
AND AL,0FEH
CALL PUT
JMP ND AL,0F7H
PUTADDJ:
JMP PUTADD
DIRECT:
MOV AL,[SYM]
CMP AL,','
JZ LONGJ
POP AX
XCHG AH,AL
SAHF
DEC AL
CMP ALGENINT:
MOV AL,0CDH
CALL PUT
JMP PUTBYT
GRP19: ;ESC opcode
MOV CX,0D800H
JMP ONEOP
GRP20:
MOV CH,AL
MOV CL,1 AND AL,1
LAHF
XCHG AH,AL
PUSH AX
XCHG AH,AL
OR AL,CH
CALL PUT
POP AX
XCHG AH,AL
SAHF
JNZ $+5
JMP PUTBYT
AH,AL
SAHF
JMP PUT
GRP17:
CALL PUT
CALL GETOP
CMP AL,CONST
MOV CL,20
ERR9: JNZ ERR10
MOV BX,[DATA]
MOV DX,[PC]POP AX
XCHG AH,AL
SAHF
AND AL,1
MOV [FLAG],AL
MOV AL,DH
ONEJ: JP ONE
GRP11:
CALL PUT
MOV AL,0AH
JMP PUT
GRP12PUTWOR
LONGR:
MOV AL,[LONG]
OR AL,AL
JNZ NOTLON
POP AX
XCHG AH,AL
SAHF
OR AL,8
LAHF
XCHG AH,AL
PUSH AX
XC,0E9H
JZ GOTOP
MOV AL,0E8H
GOTOP:
CALL PUT
MOV BX,[DATA]
MOV DX,[PC]
INC DX
INC DX
SUB BX,DX
MOV [DATA],BX
CALL MROPS
MOV CL,0F6H
CALL IMMED
MOV CH,0A8H
JMP AIMM
GRP21:
CALL GETOP
CMP AL,SREG
MOV CL,28
JNZ ERR10
M JMP PUTWOR
ERR8: JMP ERROR
GRP14:
LAHF
XCHG AH,AL
PUSH AX
XCHG AH,AL
CALL GETOP
CMP AL,CONST
JZ DIRECT
MOV CL
LAHF
INC DX
SAHF
SBB BX,DX
MOV [DATA],BX
CALL PUTBYT
MOV BX,[DLABEL]
MOV AL,BH
OR AL,BL
JNZ RET
MOV BX,[D:
MOV CL,AL
MOV CH,0D0H
PUSH CX
CALL GETOP
MOV AL,[SYM]
CMP AL,','
MOV AL,DH
JNZ ONEJ
PUSH DX
CALL GETOP
SHG AH,AL
NOTLON:
CALL GETSYM
CMP AL,EOL
JZ DORET
CMP AL,';'
JZ DORET
CMP AL,','
JNZ L0011
CALL GETSYM
L0011:
OV CH,26H
PACKREG:
MOV AL,DL
ADD AL,AL
ADD AL,AL
ADD AL,AL
OR AL,CH
JMP PUT
GRP22:
CALL GETOP
MOV CX,8F00H
CNEXT RECORD field to zero
MOV [COUNT],AL
CALL STRTLIN
MOV BX,START
NEXBT:
MOV CH,4
MOV CL,[BX] ;Get flag byte
LAHF***
END:
MOV CL,4
WREND:
MOV CH,0FFH
MOV AL,CH
CALL GEN
DEC CL
JNZ WREND
MOV AL,[LSTFCB]
CMP AL,'Z'
JZ NOR CALL CONV10
CALL PRNT10
CRLF:
MOV AL,13
CALL LIST
MOV AL,10
JMP LIST
DEFBYT:
CALL FIXUP
XCHG DX,BX
CALL SIG [IFFLG],AL
RET
SKIPCD:
MOV [CHKLAB],AL
SKIPLP:
XOR AL,AL
CALL NEXLIN
CALL NEXTCHR
CMP AL,1AH
JZ END
CALL GELL LIST
CALL LIST
CALL LIST
DEC CH
JNZ BLNK
NOFIL:
CALL OUTLIN
POP BX
MOV AL,[BX]
PUSH BX
CALL REPERR
MOV AMP AL,UNDEFID
JNZ $+5
JMP PMEM
MOV CH,58H
CMP AL,XREG
JNZ $+5
JMP PXREG
MOV CH,7
CMP AL,SREG
JZ PACKREG
MOV
INC BX ;Point to code
SAHF
CDLP:
RCL CL ;Get high bit
JC TESTTYP ;Word fixup or special
RCL CL
JNC $+5
JMP DEEOPN
CALL ADDEXT
MOV DX,FCB
MOV CL,OPEN
CALL SYSTEM
MOV BX,0FFH
XCHG BX,[HL]
XCHG DX,[DE]
XCHG CX,[BC]
NOREOPN:NEXT ;See if in range +127 to -128
XCHG DX,BX
JZ OBJBTE ;If so, it's always OK
MOV AL,DH
OR AL,AL ;Check for range +2TLAB
JC SKIPLP
MOV BX,LENID
MOV DX,IFEND
MOV CH,[BX]
INC CH
CALL CPSLP
JNZ SKIPLP
XOR AL,AL
MOV [CHKLAB],AL
L,[ERR]
CALL REPERR
CALL STRTLIN
POP BX
POP CX
JP NEXCD
OUTLIN:
CALL LIST
MOV AL,[LSTFCB]
CMP AL,'Z'
JZ RETCL,20
ERR11: JMP ERROR
GRP23:
MOV [DATSIZ],AL
GETDAT:
CALL GETSYM
MOV AL,2
CALL VAL1
MOV AL,[SYM]
CMP AL,','
MOFBYT ;Byte fixup
MOV AL,[BX]
OBJBT:
CALL SAVCD
NEXCD:
INC BX
DEC CH ;Still have codes left?
JNZ CDLP
JP NEXBT
T
MOV AL,-5
MOV [HEXCNT],AL ;FLAG HEX BUFFER AS EMPTY
MOV [SKPFLG],AL
MOV BX,HEXBUF
MOV [HEXPNT],BX
MOV BX,LSTBUF
M55 to -256
JZ CHKJMP
INC AL
JZ CHKJMP
RNGERR:
MOV AL,101 ;Value out of range
MOV [ERR],AL
OBJBTE:
MOV AL,DL
JMPRET
ENDIF:
MOV BX,IFFLG
MOV AL,[BX]
MOV B,[BX],0
MOV CL,36
OR AL,AL
JZ ERR11
RET
;**************************
MOV BX,LINFLG
MOV AL,[BX]
MOV B,[BX],-1
OR AL,AL
JNZ CRLF ;Output line only if first time
OUTLN:
CALL NEXTCHR
CV AL,[DATSIZ]
JNZ ENDDAT
CALL SAVDAT
JP GETDAT
ENDDAT:
CMP AL,2
JNZ SAVDAT
MOV BX,[DATA]
LAHF
OR BL,080H
SAHFESTTYP:
RCL CL
JC $+5
JMP DEFWRD
MOV AL,[BX]
CMP AL,-10
JC $+5
JMP SPCFUN
PUSH CX
PUSH BX
MOV BX,COUNT
MOVOV [LSTPNT],BX
MOV BX,0
MOV [ERRCNT],BX
MOV [PC],BX
MOV BX,OBJECT
MOV [HEXADD],BX
XOR AL,AL
MOV [FCB+20H],AL ;Set OBJBT
CHKJMP:
;Check for short jump. If so, we're out of range; otherwise we're OK
MOV AL,[COUNT]
DEC AL ;Only one other*******************************************
;
; PASS 2
;
;******************************************************************ALL LIST
CMP AL,10 ;Output until linefeed found
JNZ OUTLN
RET
PRTCNT:
MOV BX,ERCNTM
CALL PRINT
MOV BX,[ERRCNT]
MOV [DATA],BX
SAVDAT:
OR AL,AL
JZ $+5
JMP PUTBYT
JMP PUTWOR
IF:
MOV AL,BH
OR AL,BL
MOV AL,1
JZ SKIPCD
MOV AL,6
SUB AL,[BX]
MOV B,[BX],0
MOV CH,AL
MOV AL,' '
JZ NOFIL
BLNK: ;Put in 3 blanks for each byte not present
CA byte on line?
JNZ OBJBTE ;Can't be short jump if not
MOV AL,[PREV] ;Get the first byte of this line
CMP AL,0EBH ;DirectCHG AH,AL
CALL OUTA
POP AX
XCHG AH,AL
SAHF
RET
PHEX:
MOV CH,AL
CALL UHALF
CALL LIST
MOV AL,CH
CALL LHALF
TFCB]
CMP AL,'Z'
JZ OUTRET
CMP AL,'X'
JZ LSTCON
POP AX
XCHG AH,AL
SAHF
LAHF
XCHG AH,AL
PUSH AX
XCHG AH,AL
BX,[HEAP]
MOV SP,BX
CALL NODE
ENDSYM:
MOV AL,[LSTFCB]
CMP AL,'X'
JZ EXIT
CMP AL,'Z'
JZ ERRCON ;Print error countX,BX
MOV DL,[BX] ;Get constant part
LAHF
INC BX
SAHF
MOV DH,[BX]
XCHG DX,BX
LAHF
ADD BX,CX ;Add symbol value t
POP BX
JMP NEXCD
FINI:
CALL PRTCNT
MOV AL,[HEXFCB]
CMP AL,'Z'
JZ SYMDMP
MOV AL,[HEXCNT]
CMP AL,-5
JZ L0012
short jump?
JZ RNGERR
AND AL,0FCH
CMP AL,0E0H ;LOOP or JCXZ instruction?
JZ RNGERR
AND AL,0F0H
CMP AL,70H ;Condit
JMP LIST
SPCFUN:
INC AL ;End of file?
JZ FINI
LAHF
INC BX
SAHF
MOV DL,[BX] ;Get address
LAHF
INC BX
SAH
AND AL,7FH
PUSH BX
MOV BX,[LSTPNT]
MOV [BX],AL
CALL INCBUF
MOV [LSTPNT],BX
JNZ HAVSPC
MOV BX,LSTBUF
MOV [LSTPN to console
CALL LSTEOF
MOV DX,LSTFCB
MOV CL,CLOSE
CALL 5
ERRCON:
MOV AL,'X'
MOV [LSTFCB],AL
CALL PRTCNT
EXIT: Jo constant part
RCR SI
SAHF
RCL SI
POP CX
XCHG DX,BX
OR AL,AL ;See if symbol got defined
JNZ RET
MOV AL,100 ;U
CALL ENHEXL
L0012:
MOV AL,':'
CALL PUTCHR
MOV CH,10
HEXEND:
PUSH CX
MOV AL,'0'
CALL PUTCHR
POP CX
DEC CH
ional jump?
JZ RNGERR
JP OBJBTE
DEFWRD:
CALL FIXUP
MOV AL,DL
CALL SAVCD
MOV AL,DH
JMP OBJBT
FIXUP:
PUSH CXF
MOV DH,[BX]
PUSH BX
INC AL ;ORG?
JZ DORG
INC AL ;PUT?
JZ DPUT
DDS:
;Handle DS pseudo-op
MOV BX,[PC]
LAHF
T],BX
PUSH DX
XCHG DX,BX
PUSH CX
MOV CL,SETDMA
CALL 5
MOV DX,LSTFCB
MOV CL,SEQWRT
CALL 5
POP CX
POP DX
HAVSMP 0
RET
LSTEOF:
MOV AX,[LSTPNT]
CMP AX,LSTBUF
JZ RET
MOV AL,1AH
CALL LIST
JP LSTEOF
NODE:
XCHG DX,BX
PUSHndefined - flag error
MOV [ERR],AL
MOV DX,0
RET
STRTLIN:
XOR AL,AL
MOV [ERR],AL
MOV [LINFLG],AL
MOV BX,[PC]
MJNZ HEXEND
CALL HEXCRLF
JZ L0013
CALL HEXEOF
L0013:
CALL HEXEOF
MOV CL,CLOSE
MOV DX,HEXFCB
CALL SYSTEM
SYMDMP:
MOV DL,[BX] ;Get pointer to symbol
LAHF
INC BX
SAHF
MOV DH,[BX]
LAHF
INC BX
SAHF
XCHG DX,BX
MOV AL,[BX] ; ADD BX,DX
RCR SI
SAHF
RCL SI
MOV [PC],BX
MOV BX,[HEXADD]
LAHF
ADD BX,DX
RCR SI
SAHF
RCL SI
MOV [HEXADD],BPC:
POP BX
OUTRET:
POP AX
XCHG AH,AL
SAHF
RET
LSTCON:
POP AX
XCHG AH,AL
SAHF
LAHF
XCHG AH,AL
PUSH AX
X BX
MOV DL,[BX]
MOV DH,0
LAHF
INC BX
SAHF
LAHF
ADD BX,DX
RCR SI
SAHF
RCL SI
MOV DL,[BX]
LAHF
INC BX
OV AL,BH
CALL PHEX
MOV AL,BL
PHEXB:
CALL PHEX
MOV AL,' '
LIST:
LAHF
XCHG AH,AL
PUSH AX
XCHG AH,AL
MOV AL,[LS
MOV AL,[SYMFLG]
CMP AL,'S'
JNZ ENDSYM
MOV BX,SYMMES
CALL PRINT
MOV DX,[BASE]
MOV AL,DH
OR AL,DL
JZ EXIT
MOV Whether symbol was defined
LAHF
INC BX
SAHF
MOV CL,[BX] ;Get symbol value
LAHF
INC BX
SAHF
MOV CH,[BX]
XCHG DX
JP SPEND
DPUT:
;Handle PUT pseudo-op
MOV [HEXADD],DX
JP SPEND
DORG:
;Handle ORG pseudo-op
MOV [PC],DX
SPEND:
SAHF
MOV DH,[BX]
MOV AL,DL
OR AL,DH
JZ L0014
CALL NODE
L0014:
POP BX
MOV CH,[BX]
LAHF
INC BX
SAHF
MOV ALXT:
POP AX
XCHG AH,AL
SAHF
CALL PHEXB
POP CX
MOV BX,[PC]
LAHF
INC BX
SAHF
MOV [PC],BX
MOV BX,[HEXADD]
LA'
JZ SUPZ
MOV CH,0 ;Turn off zero suppression if not zero
SUPZ:
SUB AL,CH ;Convert leading zeros to blanks
JMP LIST
XCHG AH,AL
SAHF
HEXBYT:
MOV CH,AL
MOV BX,CHKSUM
ADD AL,[BX]
MOV [BX],AL
MOV AL,CH
CALL UHALF
CALL PUTCHR
MOV MOV AL,DH
OR AL,DL
JNZ NODE
RET
CONV10:
MOV CH,16
MOV DX,0
CONVLP:
LAHF
ADD BX,BX
RCR SI
SAHF
RCL SI
XCHG AH,AL
PUSH AX
XCHG AH,AL
MOV AL,[HEXFCB]
CMP AL,'Z'
JNZ $+5
JMP OUTRET
MOV DX,[LASTAD]
MOV BX,[HEXADD]
M,SYMWID
SUB AL,CH
JNC LENOK
MOV AL,1
LENOK:
MOV DH,AL
WRTSYM:
MOV AL,[BX]
LAHF
INC BX
SAHF
CALL LIST
DEC CHF
INC BX
SAHF
MOV [HEXADD],BX
POP BX
RET
REPERR:
OR AL,AL
JZ RET
LAHF
XCHG AH,AL
PUSH AX
XCHG AH,AL
HIDIG:
CALL UHALF
JP DIGIT
HEXEOF:
MOV AL,1AH
CALL PUTCHR
JNZ HEXEOF
RET
SAVCD:
MOV [PREV],AL
PUSH BX
AL,CH
CALL LHALF
CALL PUTCHR
MOV BX,HEXCNT
INC B,[BX]
MOV AL,[BX]
CMP AL,26
JNZ RET
ENHEXL:
MOV BX,[HEXLEN]
MOV AL,DL
ADC AL,AL
DAA
MOV DL,AL
MOV AL,DH
ADC AL,AL
DAA
MOV DH,AL
RCL CL
DEC CH
JNZ CONVLP
RET
PRNT10OV [LASTAD],BX
LAHF
INC DX
SAHF
MOV AL,[HEXCNT]
CMP AL,-5
JZ NEWLIN
OR AL,AL
SBB BX,DX
JZ AFHEX
CALL ENHEXL
H
JNZ WRTSYM
MOV CH,DH
INC CH
MOV AL,' '
OUTB:
CALL LIST
DEC CH
JNZ OUTB
LAHF
INC BX
SAHF
LAHF
INC BX
MOV BX,ERRMES
CALL PRINT
POP AX
XCHG AH,AL
SAHF
CALL PHEX
MOV BX,ENDMES
CALL PRINT
MOV BX,[ERRCNT]
LAHF
INC PUSH CX
LAHF
XCHG AH,AL
PUSH AX
XCHG AH,AL
PUSH DX
CALL CODBYT
POP DX
MOV BX,COUNT
INC B,[BX]
MOV AL,[BX]
MOV CH,AL
CALL UHALF
MOV [BX],AL
CALL INCBUF
MOV AL,CH
CALL LHALF
MOV [BX],AL
MOV AL,-6
MOV [HEXCNT],AL
MOV AL:
XCHG DX,BX
MOV CH,'0'-' ' ;Enable leading zero suppression
MOV AL,CL
CALL LODIG
MOV AL,BH
CALL HIDIG
MOV AL,BH
NEWLIN:
MOV AL,':'
CALL PUTCHR
MOV AL,-4
MOV [HEXCNT],AL
XOR AL,AL
MOV [CHKSUM],AL
MOV BX,[HEXPNT]
MOV [HEXLEN] SAHF
PUSH BX
LAHF
INC BX
SAHF
LAHF
INC BX
SAHF
LAHF
INC BX
SAHF
LAHF
INC BX
SAHF
MOV AL,[BX]
CALLBX
SAHF
MOV [ERRCNT],BX
RET
PRINT:
MOV AL,[BX]
CALL LIST
OR AL,AL
JS RET
LAHF
INC BX
SAHF
JP PRINT
OCMP AL,7
JNZ NOEXT
MOV B,[BX],1
MOV AL,' '
CALL OUTLIN
MOV AL,' '
MOV CH,5
TAB:
CALL LIST
DEC CH
JNZ TAB
NOE,[CHKSUM]
ADD AL,CH
NEG AL
CALL HEXBYT
HEXCRLF:
MOV AL,13
CALL PUTCHR
MOV AL,10
PUTCHR:
MOV BX,[HEXPNT]
MO CALL LODIG
MOV AL,BL
CALL HIDIG
MOV AL,BL
MOV CH,0 ;Don't suppress last digit
LODIG:
CALL LHALF
DIGIT:
CMP AL,'0,BX
CALL HEXBYT
MOV AL,[HEXADD+1]
CALL HEXBYT
MOV AL,[HEXADD]
CALL HEXBYT
XOR AL,AL
CALL HEXBYT
AFHEX:
POP AX
PHEX
LAHF
DEC BX
SAHF
MOV AL,[BX]
CALL PHEX
CALL CRLF
POP BX
MOV DL,[BX]
LAHF
INC BX
SAHF
MOV DH,[BX]
UTA:
MOV DL,AL
MOV CL,2
SYSTEM:
PUSH CX
PUSH DX
PUSH BX
CALL 5
POP BX
POP DX
POP CX
RET
CODBYT:
LAHF
V [BX],AL
CALL INCBUF
MOV [HEXPNT],BX
JNZ RET
PUSH BX
MOV BX,SKPFLG
MOV AL,[BX]
MOV B,[BX],0 ;Buffer filled, don'tW GRP19
DB 0D8H
DB 'nd'
DW END
DB 0
E5:
DB 1
DB 'ndif'
DW ENDIF
DB 0
H3:
DB 1
DB 'lt'
DW PUT
DB 0F4H
C4:
DB 3
DB 'all'
DW GRP14
DB 9AH
DB 'mpb'
DW PUT
DB 0A6H
DB 'mpw'
DW PUT
DB 0A7H
D2:
DB 5
DB 'b'
DDB 'be'
DW GRP17
DB 76H
DB 'pe'
DW GRP17
DB 7AH
DB 'np'
DW GRP17
DB 7BH
DB 'po'
DW GRP17
DB 7BH
DB 'no'
NONE: DB 0
; 8086 MNEMONIC TABLE
A3:
DB 7
DB 'dd'
DW GRP7
DB 2
DB 'nd'
DW GRP13
DB 22H
DB 'dc'
DW GR
DW GRP17
DB 72H
DB 'a'
DW GRP17
DB 77H
DB 'g'
DW GRP17
DB 7FH
DB 'o'
DW GRP17
DB 70H
DB 's'
DW GRP17
skip next time
POP BX
OR AL,AL ;Both buffers filled?
JNZ RET
MOV CL,SETDMA
XCHG DX,BX
CALL SYSTEM
MOV DX,HEXFCB
H4:
DB 1
DB 'alt'
DW PUT
DB 0F4H
I2:
DB 2
DB 'n'
DW GRP4
DB 0E4H
DB 'f'
DW GRP5
DB 4
I3:
DB 4
DB 'ncW GRP23
DB 1
DB 'w'
DW GRP23
DB 0
DB 'm'
DW GRP23
DB 2
DB 's'
DW GRP5
DB 1
DB 'i'
DW PUT
DB 0FAH
D3:
DW GRP17
DB 71H
DB 'ns'
DW GRP17
DB 79H
J4:
DB 5
DB 'cxz'
DW GRP17
DB 0E3H
DB 'nge'
DW GRP17
DB 7CH
DP7
DB 12H
DB 'aa'
DW PUT
DB 37H
DB 'as'
DW PUT
DB 3FH
DB 'am'
DW GRP11
DB 0D4H
DB 'ad'
DW GRP11
DB 0D5
DB 78H
DB 'c'
DW GRP17
DB 72H
J3:
DB 17
DB 'mp'
DW GRP14
DB 0EAH
DB 'nz'
DW GRP17
DB 75H
DB 'ne'
DW G
MOV CL,SEQWRT
CALL SYSTEM
XCHG DX,BX
OR AL,AL
JZ RET
MOV BX,WRTERR
JMP PRERR
UHALF:
RCR AL
RCR AL
RCR AL
'
DW GRP8
DB 41H
DB 'nb'
DW GRP4
DB 0E4H
DB 'nw'
DW GRP4
DB 0E5H
DB 'nt'
DW GRP18
DB 0CCH
I4:
DB 4
DB
DB 4
DB 'ec'
DW GRP8
DB 49H
DB 'iv'
DW GRP10
DB 30H
DB 'aa'
DW PUT
DB 27H
DB 'as'
DW PUT
DB 2FH
D4:
B 'nae'
DW GRP17
DB 72H
DB 'nbe'
DW GRP17
DB 77H
DB 'nle'
DW GRP17
DB 7FH
L3:
DB 3
DB 'ea'
DW GRP6
DB 8H
A5:
DB 1
DB 'lign'
DW ALIGN
DB 0
C3:
DB 7
DB 'mp'
DW GRP7
DB 3AH
DB 'lc'
DW PUT
DB 0F8H
DB 'ld'
DWRP17
DB 75H
DB 'nl'
DW GRP17
DB 7DH
DB 'ge'
DW GRP17
DB 7DH
DB 'nb'
DW GRP17
DB 73H
DB 'ae'
DW GRP17
D
RCR AL
LHALF:
AND AL,0FH
OR AL,30H
CMP AL,'9'+1
JC RET
ADD AL,7
RET
INCBUF:
INC BX
CMP BX,HEXBUF+BUFSIZ
'mul'
DW GRP10
DB 28H
DB 'div'
DW GRP10
DB 38H
DB 'ret'
DW PUT
DB 0CFH
DB 'nto'
DW PUT
DB 0CEH
J2:
DB DB 1
DB 'own'
DW PUT
DB 0FDH
E2:
DB 1
DB 'i'
DW PUT
DB 0FBH
E3:
DB 3
DB 'qu'
DW GRP5
DB 2
DB 'sc'
DDH
DB 'ds'
DW GRP6
DB 0C5H
DB 'es'
DW GRP6
DB 0C4H
L4:
DB 5
DB 'oop'
DW GRP17
DB 0E2H
DB 'odb'
DW PUT
PUT
DB 0FCH
DB 'li'
DW PUT
DB 0FAH
DB 'mc'
DW PUT
DB 0F5H
DB 'bw'
DW PUT
DB 98H
DB 'wd'
DW PUT
DB 99HB 73H
DB 'nc'
DW GRP17
DB 73H
DB 'ng'
DW GRP17
DB 7EH
DB 'le'
DW GRP17
DB 7EH
DB 'na'
DW GRP17
DB 76H
JZ RET
CMP BX,LSTBUF+BUFSIZ
JZ RET
CMP BX,HEXBUF+BUFSIZ+BUFSIZ
JNZ RET
MOV BX,HEXBUF ;Wrap back to first buffer
RET10
DB 'p'
DW GRP17
DB 0EBH
DB 'z'
DW GRP17
DB 74H
DB 'e'
DW GRP17
DB 74H
DB 'l'
DW GRP17
DB 7CH
DB 'b' DB 0ACH
DB 'odw'
DW PUT
DB 0ADH
DB 'ahf'
DW PUT
DB 9FH
DB 'ock'
DW PUT
DB 0F0H
L5:
DB 2
DB 'oope'
DW GBH
DB 'ahf'
DW PUT
DB 9EH
T4:
DB 1
DB 'est'
DW GRP20
DB 84H
U2:
DB 1
DB 'p'
DW PUT
DB 0FCH
W4:
DB 1
PUT
DB 0F2H
DB 'epne'
DW PUT
DB 0F2H
S3:
DB 11
DB 'ub'
DW GRP7
DB 2AH
DB 'bb'
DW GRP7
DB 1AH
DB 'bc'
R5
DW NONE
DW NONE ;S
DW S3
DW S4
DW NONE
DW NONE
DW NONE ;T
DW NONE
DW T4
DW NONE
DW NONE
DW U2 ;U
DW
DB 0E6H
DB 'utw'
DW GRP4
DB 0E7H
P3:
DB 2
DB 'op'
DW GRP22
DB 8FH
DB 'ut'
DW GRP5
DB 3
P4:
DB 2
DB ';H
DW H3
DW H4
DW NONE
DW NONE
DW I2 ;I
DW I3
DW I4
DW NONE
DW NONE
DW J2 ;J
DW J3
DW J4
DW NONE
DW RP17
DB 0E1H
DB 'oopz'
DW GRP17
DB 0E1H
L6:
DB 2
DB 'oopne'
DW GRP17
DB 0E0H
DB 'oopnz'
DW GRP17
DB 0E0H
DB 'ait'
DW PUT
DB 9BH
X3:
DB 1
DB 'or'
DW GRP13
DB 32H
X4:
DB 2
DB 'chg'
DW GRP3
DB 86H
DB 'lat'
DW DW GRP7
DB 1AH
DB 'tc'
DW PUT
DB 0F9H
DB 'td'
DW PUT
DB 0FDH
DB 'ti'
DW PUT
DB 0FBH
DB 'hl'
DW GRP12
NONE
DW NONE
DW NONE
DW NONE
DW NONE ;V
DW NONE
DW NONE
DW NONE
DW NONE
DW NONE ;W
DW NONE
DW W4
DW NONush'
DW GRP2
DB 0FFH
DB 'opf'
DW PUT
DB 9DH
P5:
DB 1
DB 'ushf'
DW PUT
DB 9CH
R3:
DB 6
DB 'et'
DW GRP16NONE
DW NONE ;K
DW NONE
DW NONE
DW NONE
DW NONE
DW NONE ;L
DW L3
DW L4
DW L5
DW L6
DW NONE ;M
DW M3
DW
M3:
DB 2
DB 'ov'
DW GRP1
DB 88H
DB 'ul'
DW GRP10
DB 20H
M4:
DB 2
DB 'ovb'
DW PUT
DB 0A4H
DB 'ovw'
DWPUT
DB 0D7H
OPTAB:
DW NONE
DW A3
DW NONE
DW A5
DW NONE
DW NONE ;B
DW NONE
DW NONE
DW NONE
DW NONE
DDB 20H
DB 'hr'
DW GRP12
DB 28H
DB 'al'
DW GRP12
DB 20H
DB 'ar'
DW GRP12
DB 38H
DB 'eg'
DW GRP21
DB 26H
E
DW NONE
DW NONE ;X
DW X3
DW X4
DW NONE
DW NONE
DW NONE ;Y
DW NONE
DW NONE
DW NONE
DW NONE
DW NONE ;Z
DB 0C3H
DB 'ep'
DW PUT
DB 0F3H
DB 'ol'
DW GRP12
DB 0
DB 'or'
DW GRP12
DB 8
DB 'cl'
DW GRP12
DB 10H
M4
DW NONE
DW NONE
DW NONE ;N
DW N3
DW NONE
DW NONE
DW NONE
DW O2 ;O
DW O3
DW O4
DW NONE
DW NONE
DW N PUT
DB 0A5H
N3:
DB 3
DB 'ot'
DW GRP9
DB 10H
DB 'eg'
DW GRP9
DB 18H
DB 'op'
DW PUT
DB 90H
O2:
DB 1
DW NONE ;C
DW C3
DW C4
DW NONE
DW NONE
DW D2 ;D
DW D3
DW D4
DW NONE
DW NONE
DW E2 ;E
DW E3
DW NONE
DW ES4:
DB 5
DB 'cab'
DW PUT
DB 0AEH
DB 'caw'
DW PUT
DB 0AFH
DB 'tob'
DW PUT
DB 0AAH
DB 'tow'
DW PUT
DB 0A DW NONE
DW NONE
DW NONE
DW NONE
HEADER: DB 13,10,'Seattle Computer Products 8086 Assembler Version 2.00'
DB 13,10,'$DB 'cr'
DW GRP12
DB 18H
R4:
DB 2
DB 'epz'
DW PUT
DB 0F3H
DB 'epe'
DW PUT
DB 0F3H
R5:
DB 2
DB 'epnz'
DWONE ;P
DW P3
DW P4
DW P5
DW NONE
DW NONE ;Q
DW NONE
DW NONE
DW NONE
DW NONE
DW NONE ;R
DW R3
DW R4
DW B 'r'
DW GRP13
DB 0AH
O3:
DB 2
DB 'ut'
DW GRP4
DB 0E6H
DB 'rg'
DW GRP5
DB 0
O4:
DB 2
DB 'utb'
DW GRP4
5
DW NONE
DW NONE ;F
DW NONE
DW NONE
DW NONE
DW NONE
DW NONE ;G
DW NONE
DW NONE
DW NONE
DW NONE
DW NONE '
ERRMES: DM '***** ERROR no. '
NOSPAC: DB 13,10,'No directory space',13,10,24H
ENDMES: DM 'H',13,10
NOMEM: DB 13,10,'Insuff繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞
STACK: EQU $
START: EQU $
U 0
TARBELLDOUBLE: EQU 0
LOAD: EQU 400H ;Address to load program
SEG: EQU 40H ;LOAD/10H
SECTOR: EQU 51 ;No. of 128-byte seS 2
DLABEL: DS 2
CON: DS 2
UNDEF: DS 2
LENID: DS 1
ID: DS 80
CHR: DS 1
SYM: DS 1
BASE: DS 2
HEAP: DS 2
SYMFLG: DS 1
Cize of
;program at any address. The program is assumed to
;occupy consecutive sectors starting at track 0, sector
;2, and wiicient memory',13,10,'$'
NOFILE: DB 13,10,'File not found',13,10,'$'
WRTERR: DB 13,10,'Disk write error',13,10,'$'
BADDSK: DB繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞ctors to load
BOOTER: EQU 200H ;"B" command puts booter here
;**************************************************************ODE: DS 2
DATSIZ: DS 1
RELOC: DS 1
BCOUNT: DS 1
COUNT: DS 1
ERR: DS 1
HEXPNT: DS 2
HEXLEN: DS 2
HEXADD: DS 2
LASTAD: DSll begin exection at its load address (which
;must be a 16-byte boundary) with the Instruction
;Pointer set to zero.
; Vari 13,10,'Bad disk specifier',13,10,'$'
ERCNTM: DM 13,10,13,10,'Error Count ='
SYMMES: DM 13,10,'Symbol Table',13,10,13,10
EXTE繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞
CROMEMCO: EQU CROMEMCOLARGE+CROMEMCOSMALL
TARBELL: EQU TARBELLSINGLE+TARBELLDOUBLE
WD1771: EQU CROMEMCO+TARBELLSINGLE
W 2
HEXCNT: DS 1
CHKSUM: DS 1
SKPFLG: DS 1
LINFLG: DS 1
PREV: DS 1
IFFLG: DS 1
CHKLAB: DS 1
LSTPNT: DS 2
ERRCNT: DS 2
Lations are available for the Cromemco 4FDC with
; large disks, the 4FDC with small disks, the Tarbell
; single-density controlND: DB 'ASM',0,0,0,0
IFEND: DB 5,'endif'
RETSTR: DM 'ret'
HEXFCB: DB 0,' HEX',0,0,0,0
DS 16
DB 0
LSTFCB: DB 0,' ;This is a disk boot routine for the 1771/1791 type disk
;controllers. It would normally reside on track 0,
;sector 1, to be 繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞D1791: EQU TARBELLDOUBLE
SMALL: EQU CROMEMCOSMALL
LARGE: EQU CROMEMCOLARGE+TARBELL
IF SMALL
MAXSECT:EQU 18
ENDIF
STRET: DS 2
RETPT: DS 2
HEXBUF: DS BUFSIZ+BUFSIZ
LSTBUF: DS BUFSIZ
BC: DS 2
DE: DS 2
HL: DS 2
IX: DS 2
IY: DS 2
DS 50
ler, and the Tarbell double-
; density controller. Select one.
CROMEMCOSMALL: EQU 0
CROMEMCOLARGE: EQU 1
TARBELLSINGLE: EQ PRN',0,0,0,0
DS 16
DB 0
PC: DS 2
OLDPC: DS 2
LABPT: DS 2
FLAG: DS 1
LONG: DS 1
ADDR: DS 2
ALABEL: DS 2
DATA: Dloaded by the "B" command of the
;monitor at address 200H. By changing the equates
;below, it may be configured to load any sIF LARGE
MAXSECT:EQU 26
ENDIF
IF TARBELL
DISK: EQU 78H
ENDIF
IF CROMEMCO
DISK: EQU 30H
ENDIF
IF WD1771
REA繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞TB DISK
JP GETSTAT
BOOT:
MOV AX,SEG
MOV SS,AX
MOV ES,AX
MOV DS,AX
JMP 0,SEG
ION: -- To coordinate the game moves.
;
; CALLED BY: -- None
;
; CALLS: -- INITBD
; CPTRMV
; M:
OUTB DISK
IF CROMEMCO
MOV AL,WAITBYTE
OUT DISK+4 ;Turn on hardware wait
ENDIF
READ:
INB DISK+4
IF TARBECHAR EQU 1
PRINTBUF EQU 9
INBUF EQU 10
SYSTEM EQU 5
;***********************************************************
; EQUATEDCOM:EQU 88H
ENDIF
IF WD1791
READCOM:EQU 80H
ENDIF
IF CROMEMCOLARGE
WAITBYTE:EQU 0B1H
ENDIF
IF CROMEMCOSMALL;***********************************************************
;
; SARGON
;
; Sargon is a computer chess playing program desi繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞 PLYRMV
;
; ARGUMENTS: None
;***********************************************************
DRIVER: MOV SP,STLL
ROL AL
JNC DONE
ENDIF
IF CROMEMCO
ROR AL
JC DONE
ENDIF
INB DISK+3
STOB
LOOP READ
GETSTAT:
INB DISKS
;***********************************************************
;
PAWN: EQU 1
KNIGHT: EQU 2
BISHOP: EQU 3
ROOK: EQU 4
QUEE
WAITBYTE:EQU 0A1H
ENDIF
ORG BOOTER
PUT 100H
XOR AX,AX
MOV DS,AX
MOV ES,AX
MOV SS,AX
UP
MOV DI,LOAD
MOVgned
; and coded by Dan and Kathe Spracklen. Copyright 1978. All
; rights reserved. No part of this publication may be
; re繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞ACK ; Set stack pointer
MOV DX,CLRMSG ; Request color choice
MOV CL,PRINTBUF
CALL SYSTEM
MOV CL,INCHAR ; Accept response+4
IF TARBELL
ROL AL
JC GETSTAT
ENDIF
IF CROMEMCO
ROR AL
JNC GETSTAT
ENDIF
DONE:
IN DISK
AND AL,9CH
N: EQU 5
KING: EQU 6
WHITE: EQU 0
BLACK: EQU 80H
BPAWN: EQU BLACK+PAWN
ORG 100H
PUT 100H
;************************* DX,SECTOR
MOV BL,2
SECT:
MOV AL,BL
OUTB DISK+2
MOV CX,128
IF TARBELL
INB DISK ;Get head load status
ENDIF
produced without the prior written permission.
;***********************************************************
;***************繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞
CALL SYSTEM
CMP AL,57H ; Did player request white ?
JZ DR05 ; Yes - branch
CMP AL,42H ; Did player request black ?
JNZ SECT
DEC DX
JZ BOOT
INC BL
CMP BL,MAXSECT+1
JNZ SECT
XOR BL,BL
INC DX
MOV AL,58H ;Step in with update
OU**********************************
; MAIN PROGRAM DRIVER
;***********************************************************
; FUNCT IF CROMEMCO
INB DISK+4 ;Get head load status
ENDIF
TEST AL,20H
MOV AL,READCOM
JNZ OUTCOM
MOV AL,READCOM+4
OUTCO********************************************
; SYSTEM EQUATES
;***********************************************************
IN JNZ DRIVER ; No - error
XOR AL,AL
JP DR10 ; Jump
DR05: MOV AL,BLACK ; Set computers color to black
DR10: MOV [KOLOR],ALction table for any
; given piece.
;***********************************************************
DPOINT: EQU $-TBA********************************
; DIRECT -- Direction Table. Used to determine the dir-
; ection of movement od Array. Used to hold the current position
; of the board during play. The board itself
; looks like:rd
MOV AL,[KOLOR] ; Get color
OR AL,AL ; Computer move ?
JZ DR25 ; Yes - jump
DR20: CALL PLYRMV ; Do player move
DR25*********************************************************
PVALUE: EQU $-TBASE-1
DB 1,3,3,5,9,10
;*************************
DR15: MOV DX,PLYDEP ; Request depth of search
MOV CL,PRINTBUF
CALL SYSTEM
MOV CL,INCHAR
CALL SYSTEM
SUB AL,31H ; SuSE
DB 20,16,8,0,4,0,0
;***********************************************************
; DCOUNT -- Direction Table Counter. f each piece.
;***********************************************************
DIRECT: EQU $-TBASE
DB +09,+11,-11,-09
DB +10,-
; FFFFFFFFFFFFFFFFFFFF
; FFFFFFFFFFFFFFFFFFFF
; FF0402030506030204FF
; FF01: CALL CPTRMV ; Do computer move
MOV BX,MOVENO
INC B,[BX] ; Increment move number
JP DR20 ; Back to player move
;*************************************
; PIECES -- The initial arrangement of the first rank of
; pieces on the boarbtract Ascii constant
JB DR15 ; Under minimum - prompt again
CMP AL,6 ; Over maximum of 6 ?
JNB DR15 ; Yes - prompt agaUsed to determine
; the number of directions of movement for any
; given piece.
;********************10,+01,-01
DB -21,-12,+08,+19
DB +21,+12,-08,-19
DB +10,+10,+11,+09
DB -10,-10,-11,-09
;*******************************01010101010101FF
; FF0000000000000000FF
; FF0000000000000000FF
; FF0000000000000060FF
; ********************************************************
; TABLES SECTION
;***************************************************d. Use to set up the board
; for the start of the game.
;*********************************************************in
INC AL ; Increment by one
MOV [PLYMAX],AL ; Set desired depth
MOV DX,CRLF ; Output CRLF
MOV CL,PRINTBUF
CALL SYST***************************************
DCOUNT: EQU $-TBASE
DB 4,4,8,4,4,8,8
;************************************************************************
; DPOINT -- Direction Table Pointer. Used to determine
; where to begin in the dire FF0000000000000000FF
; FF8181818181818181FF
; FF8482838586838284FF
; FFFFFFFF********
ORG 200H ; Start at 200H
START:
ORG START+80H
PUT START+80H
TBASE: EQU START+100H
;****************************
PIECES: EQU $-TBASE
DB 4,2,3,5,6,3,2,4
;***********************************************************
; BOARD -- BoarEM
XOR AL,AL
MOV [COLOR],AL ; Set color to white
INC AL
MOV [MOVENO],AL ; Set move number to 1
CALL INITBD ; Init boa***************
; PVALUE -- Point Value. Gives the point value of each
; piece, or the worth of each piece.
;**FFFFFFFFFFFF
; FFFFFFFFFFFFFFFFFFFF
; The values of FF form the border of the
; board, anQU ATKLST
BACT: EQU ATKLST+7
;***********************************************************
; PLIST -- Pinned Piece Array. half for black.
; It is used to hold the attackers of any given
; square in the order of their value.
***************************************
SCORE: DW 0,0,0,0,0,0
;***********************************************************
awn
; 2 -- Knight
; 3 -- Bishop
; 4 -- Rook
; king and the second holding the position of
; the black king.
;
; POSQ -- Position of Queens. Like d are used to indicate when a piece
; moves off the board. The individual bits of
; the other bytes in This is a two part array.
; PLISTA contains the pinned piece position.
; PLISTD contains the directio;
; WACT -- White Attack Count. This is the first
; byte of the array and tells how many pieces are
; ; PLYIX -- Ply Table. Contains pairs of pointers, a pair
; for each ply. The first pointer points to the
; 5 -- Queen
; 6 -- King
; 7 -- Not used
; 0 -- Empty Square
;**POSK,but for queens.
;***********************************************************
POSK: DB 24,95
POSQ: DB 14,94
DB -1
;* the board array are as
; follows:
; Bit 7 -- Color of the piece
; 1 -- Black
; n from the pinned
; piece to the attacker.
;***********************************************************
PLIST: EQ in the white portion of the attack list.
;
; BACT -- Black Attack Count. This is the eighth byte of
; the arr top of the list of possible moves at that ply.
; The second pointer points to which move in the
; *********************************************************
BOARD: EQU $-TBASE
BOARDA: DS 120
;****************************************************************************************
; SCORE -- Score Array. Used during Alpha-Beta pruning to
; 0 -- White
; Bit 6 -- Not used
; Bit 5 -- Not used
; Bit 4 --Castle fU $-TBASE-1
PLISTD: EQU PLIST+10
PLISTA: DW 0,0,0,0,0,0,0,0,0,0
;**********************************************************ay and does the same for black.
;***********************************************************
ATKLST: DW 0,0,0,0,0,0,0
WACT: E list is the one currently being considered.
;***********************************************************
PLYIX: DW 0,0,0,0*****************************
; ATKLIST -- Attack List. A two part array, the first
; half for white and the second hold the scores at each ply. It includes two
; "dummy" entries for ply -1 and ply 0.
;********************lag for Kings only
; Bit 3 -- Piece has moved flag
; Bits 2-0 Piece type
; 1 -- P*
; POSK -- Position of Kings. A two byte area, the first
; byte of which hold the position of the white
; ,0,0,0,0,0,0
DW 0,0,0,0,0,0,0,0,0,0
;***********************************************************
; STACK -- Contains thPTRI: DW PLYIX
MLPTRJ: DW 0
SCRIX: DW 0
BESTM: DW 0
MLLST: DW 0
MLNXT: DW MLIST
;***************************************t by the
; Alpha-Beta pruning process.
;
; MLLST -- Pointer to the previous move placed in the move
; through an exchange by the player not on the
; move.
;
; PTSW1 -- The maximum number of points whic- Number of Pins. Count and pointer into the
; pinned piece list.
;
; MLPTRI -- Pointer into the ply table whi pruning.
;
; NPLY -- Current ply number during Alpha-Beta
; pruning.
;
; CKFLG -- A non-zero value ie stack for the program.
;***********************************************************
ORG START+2FFH
STACK:
;********************************
; VARIABLES SECTION
;
; KOLOR -- Indicates computer's color. White is 0, and
; Black is list. Used during generation of the move list.
;
; MLNXT -- Pointer to the next available space in the move
; h could be won
; through an exchange by the player not on the
; move.
;
; PTSW2 -- The second higch tells
; which pair of pointers are in current use.
;
; MLPTRJ -- Pointer into the move list to the move thatndicates the king is in check.
;
; MATEF -- A zero value indicates no legal moves.
;
; VALM -- The score of the curre***********************************************
; TABLE INDICES SECTION
;
; M1-M4 -- Working indices used to index into
;80H.
;
; COLOR -- Indicates color of the side with the move.
;
; P1-P3 -- Working area to hold the contents of the boa list.
;
;***********************************************************
ORG START+0
PUT START+0
M1: DW TBASE
M2: DW TBhest number of points which could
; be won through a different exchange by the player
; not on the mov is
; currently being processed.
;
; SCRIX -- Score Index. Pointer to the score table for
; the pnt move being examined.
;
; BRDC -- A measure of mobility equal to the total number
; of squares white can mo the board array.
;
; T1-T3 -- Working indices used to index into Direction
; Count, Direction Valrd
; array for a given square.
;
; PMATE -- The move number at which a checkmate is
; discovered ASE
M3: DW TBASE
M4: DW TBASE
T1: DW TBASE
T2: DW TBASE
T3: DW TBASE
INDX1: DW TBASE
INDX2: DW TBASE
NPINS: DW TBASE
MLe.
;
; MTRL -- A measure of the difference in material
; currently on the board. It is the total value of
; ly being examined.
;
; BESTM -- Pointer into the move list for the move that
; is currently considered the besve to minus the number
; black can move to.
;
; PTSL -- The maximum number of points which could be lost
; ue, and Piece Value tables.
;
; INDX1 -- General working indices. Used for various
; INDX2 purposes.
;
; NPINS -during look ahead.
;
; MOVENO -- Current move number.
;
; PLYMAX -- Maximum depth of search using Alpha-Beta
; the white pieces minus the total value of the
; black pieces.
;
; BC0 -- The value of board contFLG -- A field in the move entry which contains flag
; information. The meaning of each bit is as
; ble location
; in the move list.
;
; MLPTR -- The Move List is a linked list of individual
; move
MLEND: EQU MLIST+2040
MLPTR: EQU 0
MLFRP: EQU 2
MLTOP: EQU 3
MLFLG: EQU 4
MLVAL: EQU 5
;*******************************G: DB 0
MATEF: DB 0
VALM: DB 0
BRDC: DB 0
PTSL: DB 0
PTSW1: DB 0
PTSW2: DB 0
MTRL: DB 0
BC0: DB 0
MV0: DB 0
PTSCK: DB move.
; Bit 3 -- This flag is set is there is a piece
; captured, and that piece has movrol(BRDC) at ply 0.
;
; MV0 -- The value of material(MTRL) at ply 0.
;
; PTSCK -- A non-zero value indicates that th follows:
; Bit 7 -- The color of any captured piece
; 0 -- White
; s each of which is 6 bytes in length. The
; move list pointer(MLPTR) is the link field
; within a move****************************
; PROGRAM CODE SECTION
;***********************************************************
; BOARD SETU0
BMOVES: DB 35,55,10H
DB 34,54,10H
DB 85,65,10H
DB 84,64,10H
;*******************************************************ed at
; least once.
; Bits 2-0 Describe the captured piece. A
; e piece has
; just moved itself into a losing exchange of
; material.
;
; BMOVES -- Our very tiny 1 -- Black
; Bit 6 -- Double move flag (set for castling and
; en passant pawn capture.
;
; MLFRP -- The field in the move entry which gives the
; board position from which the piece is moving.
;P ROUTINE
;***********************************************************
; FUNCTION: To initialize the board array, setting th****
; MOVE LIST SECTION
;
; MLIST -- A 2048 byte storage area for generated moves.
; This area must be largezero value indicates no capture.
;
; MLVAL -- The field in the move entry which contains the
; score assigned book of openings. Determines
; the first move for the computer.
;
;**********************************************s)
; Bit 5 -- Pawn Promotion flag; set when pawn
; promotes.
; Bit 4 -- Wh
; MLTOP -- The field in the move entry which gives the
; board position to which the piece is moving.
;
; MLe
; pieces in their initial positions for the
; start of the game.
;
; CALLED BY: DRIVER
;
; CALL enough to hold all
; the moves for a single leg of the move tree.
;
; MLEND -- The address of the last availato the move.
;
;***********************************************************
ORG START+300H
PUT START+300H
MLIST: DS 2048
*************
KOLOR: DB 0
COLOR: DB 0
P1: DB 0
P2: DB 0
P3: DB 0
PMATE: DB 0
MOVENO: DB 0
PLYMAX: DB 2
NPLY: DB 0
CKFLen set, this flag indicates that
; this is the first move for the
; piece on theS: None
;
; ARGUMENTS: None
;***********************************************************
INITBD: MOV CX,60 ; Pre-fillto be added for the new position.
;***********************************************************
PATH: ADD [M2],CL ; Add directon is empty
; 1 -- Encountered a piece of the
; opposite color
; wn ?
JNZ MP1 ; No-Skip
DEC AL ; Decrement for black Pawns
MP1: AND AL,7 ; Get piece type
MOV [T1],AL ; Save piece typ
MOV B,[SI+2],24
MOV B,[SI+3],94
RET
;***********************************************************
; PATH ROUTINE
;*********************
; PIECE MOVER ROUTINE
;***********************************************************
; FUNCTION: To generat board with -1's
MOV DI,BOARDA
MOV AX,-1
REP
STOW
MOV CH,8
MOV SI,BOARDA
IB2: MOV AL,[SI-8] ; Fill non-border squarion constant to previous position
MOV SI,[M2] ; Load board index
MOV AL,[SI+BOARD] ; Get contents of board
CMP AL,-1 ; I 2 -- Encountered a piece of the
; same color
; e
MOV DI,[T1] ; Load index to DCOUNT/DPOINT
MOV CH,[DI+DCOUNT] ; Get direction count
MOV AL,[DI+DPOINT] ; Get direction p*******************************************************
; FUNCTION: To generate a single possible move for a given
; e all the possible legal moves for a
; given piece.
;
; CALLED BY: GENMOV
;
; CALLS: PATH
; es
MOV [SI+21],AL ; White pieces
LAHF
OR AL,080H
SAHF ; Change to black
MOV [SI+91],AL ; Black pieces
MOV B,[SI+31n border area ?
JZ PA2 ; Yes - jump
MOV [P2],AL ; Save piece
MOV AH,AL ; Save piece in register
AND AL,7 ; Clear fla 3 -- New position is off the
; board
;
; CALLED BY: MPIECE
; ATTACK
; ointer
MOV [INDX2],AL ; Save as index to direct
MOV DI,[INDX2] ; Load index
MP5: MOV CL,[DI+DIRECT] ; Get move direction
piece along its current path of motion including:
; Fetching the contents of the board at the new
; ADMOVE
; CASTLE
; ENPSNT
;
; ARGUMENTS: The piece to be moved.
;**********************************],PAWN ; White Pawns
MOV B,[SI+81],BPAWN ; Black Pawns
MOV B,[SI+41],0 ; Empty squares
MOV B,[SI+51],0
MOV B,[SI+61],0
gs
MOV [T2],AL ; Save piece type
JZ RET ; Return if empty
XOR AH,[P1] ; Compare with moving piece
SHL AH ; Set flag
PINFND
;
; CALLS: None
;
; ARGUMENTS: Direction from the direction array giving the
; constant MOV AL,[M1] ; From position
MOV [M2],AL ; Initialize to position
MP10: CALL PATH ; Calculate next position
CMP AL,2 ; R position, and setting a flag describing the
; contents:
; 0 -- New positi*************************
MPIECE: XOR AL,[BX] ; Piece to move
AND AL,87H ; Clear flag bit
CMP AL,BPAWN ; Is it a black Pa MOV B,[SI+71],0
INC SI
DEC CH
JNZ IB2
MOV SI,POSK ; Init King/Queen position list
MOV B,[SI+0],25
MOV B,[SI+1],95
MOV AL,2
SBB AL,0
RET ; Return
PA2: MOV AL,3 ; Set off board flag
RET
;******************************************eady for new direction ?
JNC MP15 ; Yes - Jump
AND AL,AL ; Test for empty square
PUSHF
MOV AL,[T1] ; Get piece moved
OUTINE
;***********************************************************
; FUNCTION: -- To test for en passant Pawn capture and
ump
JMP MP15 ; Jump
MP30: POPF
JNZ MP15 ; No - Jump
MP31: CALL ADMOVE ; Add to move list
JMP MP15 ; Jump
MP35: POPF ; Find difference
JNS EP10 ; Positive ? Yes - Jump
NEG AL ; Else take absolute value
EP10: CMP AL,10 ; Is difference 1or direction
CMP AL,3 ; On diagonal moves ?
JC MP35 ; Yes - Jump
JZ MP30 ; -or-jump if on 2 square move
POPF
JNZ MPank ?
JNC RET ; No - return
MOV SI,[MLPTRJ] ; Get pointer to previous move
TEST B,[SI+MLFLG],010H ; First move for that p
CMP AL,PAWN+1 ; Is it a Pawn ?
JC MP20 ; Yes - Jump
CALL ADMOVE ; Add move to list
POPF
JNZ MP15 ; No - Jump
MOV
; to add it to the move list if it is
; legal.
;
; CALLED BY: -- MPIECE
;
; CALLS:
JZ MP36 ; Yes - Jump
MOV AL,[M2] ; Get "to" position
CMP AL,91 ; Promote white Pawn ?
JNC MP37 ; Yes - Jump
CMP A0 ?
JNZ RET ; No - return
OR B,[P2],040H ; Set double move flag
CALL ADMOVE ; Add Pawn move to move list
MOV AL,[M1] 15 ; No - jump
MOV AL,[M2] ; Get "to" position
CMP AL,91 ; Promote white Pawn ?
JNC MP25 ; Yes - Jump
CMP AL,29 ; Piece ?
JZ RET ; No - return
MOV AL,[SI+MLTOP] ; Get "to" position
MOV [M4],AL ; Store as index to board
MOV SI,[M4] ;AL,[T1] ; Piece type
CMP AL,KING ; King ?
JZ MP15 ; Yes - Jump
CMP AL,BISHOP ; Bishop, Rook, or Queen ?
JNC MP10 ; Y-- ADMOVE
; ADJPTR
;
; ARGUMENTS: -- None
;***********************************************************
EL,29 ; Black Pawn promotion ?
JNC MP31 ; No- Jump
MP37: OR B,[P2],020H ; Set promote flag
JP MP31 ; Jump
MP36: CALL ENP; Save initial Pawn position
MOV [M3],AL
MOV AL,[M4] ; Set "from" and "to" positions
; for dummy move
MOV [M1],AL
romote black Pawn ?
JNC MP26 ; No - Jump
MP25: OR B,[P2],020H ; Set promote flag
MP26: CALL ADMOVE ; Add to move list
IN Load board index
MOV AL,[SI+BOARD] ; Get piece moved
MOV [P3],AL ; Save it
AND AL,7 ; Get piece type
CMP AL,PAWN ; Ies - Jump
MP15: INC DI ; Increment direction index
DEC CH
JNZ MP5 ; Decr. count-jump if non-zerc
MOV AL,[T1] ; Piece tNPSNT: MOV AL,[M1] ; Set position of Pawn
TEST B,[P1],080H ; Check color, is it white ?
JZ EP5 ; Yes - skip
ADD AL,10 ;SNT ; Try en passant capture
JMP MP15 ; Jump
;***********************************************************
; EN PASSANT RMOV [M2],AL
MOV AL,[P3] ; Save captured Pawn
MOV [P2],AL
CALL ADMOVE ; Add Pawn capture to move list
MOV AL,[M3] ; ReC DI ; Adjust to two square move
DEC CH
TEST B,[P1],008H ; Check Pawn moved flag, has it moved before ?
JZ MP10 ; No - Js it a Pawn ?
JNZ RET ; No - return
MOV AL,[M4] ; Get "to" position
MOV BX,M2 ; Get present "to" position
SUB AL,[BX]ype
CMP AL,KING ; King ?
JNZ RET
JMP CASTLE ; Yes - Try Castling
; ***** PAWN LOGIC *****
MP20: MOV AL,CH ; Counter f Add 10 for black
EP5: CMP AL,61 ; On en passant capture rank ?
JC RET ; No - return
CMP AL,69 ; On en passant capture rstore "from" position
MOV [M1],AL
;***********************************************************
; ADJUST MOVE LIST POINTER ; Clear color bit
CMP AL,ROOK ; Has Rook ever moved ?
JNZ CA20 ; Yes - Jump
MOV AL,CL ; Restore Rook position
JP CAE
; ADJPTR
;
; ARGUMENTS: -- None
;***********************************************************
CASTLE:
[P2],AL ; Zero move flags
CALL ADMOVE ; Put Rook move in list
CALL ADJPTR ; Re-adjust move list pointer
MOV AL,[M3] ;
SUB BX,6 ; Back up list pointer
MOV [MLLST],BX ; Save list pointer
MOV [BX],0 ; Zero out link
RET ; Return
;*****
MOV BX,M1 ; King position
CMP AL,[BX] ; Reached King ?
JNZ CA10 ; No - jump
SUB AL,CH ; Determine King's position
FOR DOUBLE MOVE
;***********************************************************
; FUNCTION: -- To adjust move list pointer to 15 ; Jump
CA10: MOV SI,[M3] ; Load board index
MOV AL,[SI+BOARD] ; Get contents of board
AND AL,AL ; Empty ?
JNZ CA20 TEST B,[P1],008H ; Has king moved ?
JNZ RET ; Yes - return
MOV AL,[CKFLG] ; Fetch Check Flag
AND AL,AL ; Is the King in Restore King position
MOV [M1],AL ; Store
CA20: MOV AL,CH ; Scan Index
CMP AL,1 ; Done ?
JZ RET ; Yes - return
MOV******************************************************
; CASTLE ROUTINE
;***************************************************** SUB AL,CH
MOV [M2],AL ; Save it
MOV BX,P2 ; Address of flags
MOV B,[BX],40H ; Set double move flag
CALL ADMOVE ; Putlink around
; second move in double move.
;
; CALLED BY: -- ENPSNT
; CASTLE
; ; No - Jump
MOV AL,[M3] ; Current position
CMP AL,22 ; White Queen Knight square ?
JZ CA15 ; Yes - Jump
CMP AL,92 ; check ?
JNZ RET ; Yes - Return
MOV CX,0FF03H ; Initialize King-side values
CA5: ADD CL,[M1] ; Rook position
MOV AL,CL
CX,01FCH ; Set Queen-side initial values
JMP CA5 ; Jump
;***********************************************************
; A******
; FUNCTION: -- To determine whether castling is legal
; (Queen side, King side, or both) and add it
king move in list
MOV BX,M1 ; Addr of King "from" position
MOV AL,[BX] ; Get King's "from" position
MOV [BX],CL ; Stor (This mini-routine is not really called,
; but is jumped to to save time.)
;
; CALLS: -- None
;
Black Queen Knight square ?
JZ CA15 ; Yes - Jump
CALL ATTACK ; Look for attack on square
AND AL,AL ; Any attackers ?
MOV [M3],AL ; Store as board index
MOV SI,[M3] ; Load board index
MOV AL,[SI+BOARD] ; Get contents of board
AND AL,7FHDMOVE ROUTINE
;***********************************************************
; FUNCTION: -- To add a move to the move list
;
; to the move list if it is.
;
; CALLED BY: -- MPIECE
;
; CALLS: -- ATTACK
; ADMOVe Rook "from" position
SUB AL,CH ; Get Rook "to" position
MOV [M2],AL ; Store Rook "to" position
XOR AL,AL ; Zero
MOV; ARGUMENTS: -- None
;***********************************************************
ADJPTR: MOV BX,[MLLST] ; Get list pointer
JNZ CA20 ; Yes - Jump
MOV AL,[M3] ; Current position
CA15: ADD AL,CH ; Next position
MOV [M3],AL ; Save as board index
; CALLED BY: -- MPIECE
; ENPSNT
; CASTLE
;
; CALLS: -- None
;
; ARGUMENT: -- N
MOV [BX],DX ; Save move list pointer
INC BX
INC BX
MOV [MLPTRI],BX ; Save new index
MOV [MLLST],BX ; Last pointer for****************
; FUNCTION: -- To generate the move set for all of the
; pieces of a given color.
;
; CALL*******************************************
INCHK: MOV AL,[COLOR] ; Get color
INCHK1: MOV BX,POSK ; Addr of white King positiX,AX ; Store zero in link address
CLD
STOW
MOV AL,[M1] ; Store "from" move position
STOB
MOV AL,[M2] ; Store "to" mon
INC AL ; Incr to next board position
CMP AL,99 ; End of board array ?
JNZ GM5 ; No - Jump
RET ; Return
;*****one
;***********************************************************
ADMOVE: MOV DX,[MLNXT] ; Addr of next loc in move list
MOV chain init.
MOV AL,21 ; First position on board
GM5: MOV [M1],AL ; Save as index
MOV SI,[M1] ; Load board index
MOV AED BY: -- FNDMOV
;
; CALLS: -- MPIECE
; INCHK
;
; ARGUMENTS: -- None
;******************************on
AND AL,AL ; White ?
JZ IC5 ; Yes - Skip
INC BX ; Addr of black King position
IC5: MOV AL,[BX] ; Fetch King positioove position
STOB
MOV AL,[P2] ; Store move flags/capt. piece
STOB
XOR AL,AL ; Store initial move value
STOB
MOV [M******************************************************
; CHECK ROUTINE
;******************************************************BX,MLEND ; Address of list end
SUB BX,DX ; Calculate difference
JC AM10 ; Jump if out of space
MOV BX,[MLLST] ; Addr of L,[SI+BOARD] ; Fetch board contents
AND AL,AL ; Is it empty ?
JZ GM10 ; Yes - Jump
CMP AL,-1 ; Is it a border square ?
*****************************
GENMOV: CALL INCHK ; Test for King in check
MOV [CKFLG],AL ; Save attack count as flag
MOV Dn
MOV [M3],AL ; Save
MOV SI,[M3] ; Load board index
MOV AL,[SI+BOARD] ; Fetch board contents
MOV [P1],AL ; Save
ANDLNXT],DI ; Save address for next move
MOV DI,DX
RET ; Return
AM10: MOV [BX],0 ; Abort entry on table ovflow
RET
;*******
; FUNCTION: -- To determine whether or not the
; King is in check.
;
; CALLED BY: -- GENMOV
; prev. list area
MOV [MLLST],DX ; Save next as previous
MOV [BX],DX ; Store link address
TEST B,[P1],008H ; Has moved piec
JZ GM10 ; Yes - Jump
MOV [P1],AL ; Save piece
MOV BX,COLOR ; Address of color of piece
XOR AL,[BX] ; Test color of piX,[MLNXT] ; Addr of next avail list space
MOV BX,[MLPTRI] ; Ply list pointer index
INC BX ; Increment to next ply
INC BX
AL,7 ; Get piece type
MOV [T1],AL ; Save
;***********************************************************
; ATTACK ROUTINE
*********************************************************
; GENERATE MOVE ROUTINE
;******************************************* FNDMOV
; EVAL
;
; CALLS: -- ATTACK
;
; ARGUMENTS: -- Color of King
;****************e moved before ?
JNZ AM5 ; Yes - jump
OR B,[P2],010H ; Set first move flag
AM5: XCHG DX,DI ; Address of move area
XOR Aece
TEST AL,080H ; Match ?
JNZ GM10
CALL MPIECE ; Yes - call Move Piece
GM10: MOV AL,[M1] ; Fetch current board positi
;***********************************************************
; FUNCTION: -- To find all attackers on a given square
; for a Knight
CALL ATKADJ ; Scan adjacent squares
MOV AH,20H ; Bit 5 set
MOV AL,[BP+11] ; Get piece at +11
AND AL,87H
; PINFND
; CASTLE
; INCHK
;
; CALLS: -- ATKADJ
; AT attacker on adjacent
; squares.
;
; CALLED BY: -- ATTACK
;
; CALLS: -- ATKCHK
;
; ARGUMENTS: -- example a queen lined up behind a bishop
; of her same color along a diagonal.) The
; ?
JNZ AT20 ; No - jump
OR [BP-9],AH ; Turn on bit 5
AT20: MOV SI,DIRECT+TBASE ; Load direction table
MOV AH,BISHOP ; Che by scanning outward from the square
; until a piece is found that attacks
; that s; Clear flag bit
CMP AL,BPAWN ; Black Pawn ?
JNZ AT5 ; No - jump
OR [BP+11],AH ; Turn on bit 5
AT5: MOV AL,[BP+9] ; Get KOUT
;
; ARGUMENTS: -- None
;***********************************************************
ATTACK: PUSH CX ; Save Register The piece under attack. The attacker.
;***********************************************************
ATKADJ: MOV CX,8 ; 8 dir bishop is then said to be transparent to the
; queen, since both participate in the
; attack.ck for a Bishop
CALL ATKOUT ; Scan outwards
MOV AH,ROOK ; Check for a Rook
CALL ATKOUT ; Scan outwards
XOR AL,AL ; Nquare, or a piece is found that
; doesn't attack that square, or the edge
; of the board is repiece at +9
AND AL,87H ; Clear flag bit
CMP AL,BPAWN ; Black Pawn ?
JNZ AT10 ; No - jump
OR [BP+9],AH ; Turn on bit 5
CX
MOV BP,[M3] ; Get piece index
ADD BP,BOARD ; Add board pointer to it
MOV DH,0 ; Init. scan count/flags
MOV SI,DIRECections to scan
AA5: XCHG AX,BX ; Save AX
LODB ; Get direction byte
CBW ; Convert to word
XCHG AX,BX ; Save directi
;
; In the case where this routine is called
; by CASTLE or INCHK, the routine is
; o attackers
POP CX ; Restore CX reg
RET ; Return
;***********************************************************
; ATTACached.
;
; In determining which pieces attack
; a square, this routine also takes into
;
AT10: MOV AL,[BP-11] ; Get piece at -11
AND AL,87H ; Clear flag bit
CMP AL,PAWN ; White Pawn ?
JNZ AT15 ; No - jump
T+TBASE ; Load direction table
MOV AH,KING ; Check for a King
CALL ATKADJ ; Scan adjacent squares
MOV AH,KNIGHT ; Check on and restore AX
MOV DI,BP ; Load pointer to piece
ADD DI,BX ; Add direction constant
MOV AL,[DI] ; Get attacking piec terminated as soon as an attacker of the
; opposite color is encountered.
;
; CALLED BY: -- POINTSK ADJACENT SCAN ROUTINE
;***********************************************************
; FUNCTION: -- To scan for a specified account the ability of certain pieces to
; attack through another attacking piece. (For
; OR [BP-11],AH ; Turn on bit 5
AT15: MOV AL,[BP-9] ; Get piece at -9
AND AL,87H ; Clear flag bit
CMP AL,PAWN ; White Pawn e
AND AL,7 ; Get piece type
CMP AL,AH ; Same as what we want ?
JNZ AA10 ; No - jump
CALL ATKCHK ; Check and save atttack
JP AO10 ; Keeping going that direction
;***********************************************************
; ATTACK CHECK A JZ AO22 ; Yes - jump
CMP AL,QUEEN ; Queen ?
JZ AO20 ; Yes - jump
CMP AL,PAWN+20H ; Pawn with bit 5 ?
JZ AO21 ; Yes -POP AX
POP AX ; Set SP level to ATTACK
MOV AX,0DFFFH ; FF (border) in AL and DF in AH
CMP [BP+9],AL ; Is +9 border ?
JZcker.
;***********************************************************
ATKOUT: MOV CL,4 ; 4 directions to scan
AO5: MOV DX,0C0H HK, control is returned to
; the aforementioned routines as soon as an
; attacker of the opposacker
AA10: LOOP AA5 ; Go check for next direction
RET ; Return
;******************************************************ND SAVE ROUTINE
;***********************************************************
; FUNCTION: -- To check if a piece can attack jump
AO15: LOOP AO5 ; Go check for next direction
RET ; Return
AO20: INC DH ; Set Queen found flag
AO21: AND B,[DI],0D ACK5 ; Yes, jump
AND [BP+9],AH ; Remove bit 5 for piece
ACK5: CMP [BP+11],AL ; Is +11 border ?
JZ ACK6 ; Yes - jump
AN ; Bitmask for color flags
XCHG AX,BX ; Save AX
LODB ; Get direction byte
CBW ; Convert to word
XCHG AX,BX ; Save ite color is encountered.
;
; CALLED BY: -- ATTACK
;
; CALLS: -- None
;
; ARGUMENTS: -- The attacking piece. The*****
; ATTACK OUTWARD SCAN ROUTINE
;***********************************************************
; FUNCTION: -- To scan fothe target
; square and save the attacking piece value
; in the attack list.
;
; FH ; Remove bit 5 for piece
AO22: MOV AL,[DI] ; Get piece
ADD AL,80H ; CY if back, NC if white
RCR AL ; Bit 7 set if blaD [BP+11],AH ; Remove bit 5 for piece
ACK6: CMP [BP-9],AL ; Is -9 border ?
JZ ACK7 ; Yes - jump
AND [BP-9],AH ; Remove bitdirection and restore AX
MOV DI,BP ; Load pointer to piece
AO10: ADD DI,BX ; Add direction constant
MOV AL,[DI] ; Get at piece under attack.
;***********************************************************
ATKCHK: MOV AL,[DI] ; Get piece
CMP B,[T1r a specified attacker outwards
; from the piece under attack, until found
; or edge of the bo The pin piece list is checked for the
; attacking piece, and if found there, the
; piece ck, bit 6 if white
AND DL,AL ; Keep only bits 6 and 7
JZ AO15 ; Nothing, next direction
CALL ATKCHK ; Check and save at 5 for piece
ACK7: CMP [BP-11],AL ; Is -11 border ?
JZ ACK8 ; Yes - jump
AND [BP-11],AH ; Remove bit 5 for piece
ACK8: MOtacking piece
AND AL,27H ; Get piece type and bit 5
JZ AO10 ; No piece, keep going
CMP AL,AH ; Same as what we want ?
],7 ; Call from POINTS ?
JZ ACK10 ; Yes - jump
XOR AL,[BP] ; Attacker and target same color ?
JNS RET ; Yes - return
ard is reached.
;
; CALLED BY: -- ATTACK
;
; CALLS: -- ATKCHK
;
; ARGUMENTS: -- The piece under attack. The attais not included in the attack list.
;
; In the case where ATTACK is called by
; CASTLE or INCV AL,1 ; Set attacker found flag
POP CX ; Restore CX reg
RET ; Return from ATTACK
ACK10: PUSH CX ; Save regs
PUSH DI XCHG AL,CH ; Byte to AL, point value to CH
ACK35: SHL AL ; Lower bits to upper
SHL AL
SHL AL
SHL AL
OR AL,CH ; Combaddress
ACK30: OR DH,DH ; Queen found this scan ?
JZ ACK31 ; No - jump
MOV AL,QUEEN ; Use Queen slot in attack list
ACK3oard
MOV [P1],AL ; Save
MOV CH,8 ; Init scan direction count
XOR AL,AL
MOV [INDX2],AL ; Init direction index
MOV DI,pposite direction ?
CMP AH,BL ; Same as attacking direction ?
JZ ACK15 ; Yes - jump
ACK20: POP AX ; Restore regs.
POP ATTACK
;
; ARGUMENTS: -- None
;***********************************************************
PINFND: XOR AL,AL ; Zero pi
MOV CL,[NPINS] ; Number of pinned pieces
JCXZ ACK26 ; No pins - jump
PUSH AX ; Save AX
MOV AX,DI ; Load piece pointeine with point value
ACK40: MOV [DI],AL ; Put back into attack list
POP DI ; Restore regs
POP CX
RET ; Return
;***1: AND AL,7 ; Attacking piece type
INC B,[DI] ; Increment list count
XCHG AL,CL ; Save point value in AL
ADD DI,CX ; A[INDX2]
PF2: MOV AL,[M3] ; Get King/Queen position
MOV [M2],AL ; Save
XOR AL,AL
MOV [M4],AL ; Clear pinned piece savedDI
POP CX
RET ; Return to ATTACK
ACK25: POP AX ; Restore AX
ACK26: MOV CL,AL ; Put piece in CL
AND CL,7 ; Get piecen count
MOV [NPINS],AL
MOV DX,POSK ; Addr of King/Queen pos list
PF1: MOV BP,DX
MOV AL,[BP] ; Get position of royal pier in AX
SUB AX,BOARDA ; Minus BOARDA for position
MOV DI,PLISTA ; Pin list address
ACK15: OR AL,AL ; Set flags for REP
R********************************************************
; PIN FIND ROUTINE
;*************************************************ttack list slot address
MOV CH,[DI] ; Get data already there
TEST CH,0FH ; Is first slot empty ?
JZ ACK40 ; Yes - jump
pos
MOV CL,[DI+DIRECT] ; Get direction of scan
PF5: CALL PATH ; Compute next position
AND AL,AL ; Is it empty ?
JZ PF5 type
MOV DI,PVALUE+TBASE ; PVALUE list address
ADD DI,CX ; Point to piece value
MOV CL,[DI] ; Get point value of piece
ce
AND AL,AL ; Is it on board ?
JNZ PF1A ; Yes- continue
JMP PF26
PF1A: CMP AL,-1 ; At end of list ?
JZ RET ; Yes rEPZ
SCAB ; Search list for position
JNZ ACK25 ; Continue if not found
OR AH,AH ; Is this the first find ?
JNZ ACK20 **********
; FUNCTION: -- To produce a list of all pieces pinned
; against the King or Queen, for both whit
TEST CH,0F0H ; Is second slot empty ?
JZ ACK35 ; Yes - jump
INC DI ; Increment to King slot
MOV CH,[DI] ; Get byte
; Yes - jump
CMP AL,3 ; Off board ?
JZ JPF25 ; Yes - jump
CMP AL,2 ; Piece of same color
MOV AL,[M4] ; Load pinned
MOV DI,ATKLST ; Init address of attack list
TEST AL,80H ; Is it white ?
JZ ACK30 ; Yes - jump
ADD DI,7 ; Attack list eturn
MOV [M3],AL ; Save position as board index
MOV SI,[M3] ; Load index to board
MOV AL,[SI+BOARD] ; Get contents of b ; No - jump
MOV AH,[DI+9] ; Get direction
CMP AH,BL ; Same as attacking direction ?
JZ ACK15 ; Yes - jump
NEG AH ; Oe
; and black.
;
; CALLED BY: -- FNDMOV
; EVAL
;
; CALLS: -- PATH
; piece position
JZ PF15 ; Yes - jump
AND AL,AL ; Possible pin ?
JZ JPF25 ; No - jump
MOV AL,[T2] ; Piece type encounIncrement direction index
DEC CH
JZ PF26 ; Done ? Yes - Continue
JMP PF2
PF26: INC DX ; Incr King/Queen pos index
JMP XCHG DX,BX ; Reverse for black
PF19A: MOV AL,[BX] ; Number of defenders
XCHG DX,BX ; Reverse for attackers
SUB AL,[BX] V DH,[SI+PVALUE] ; Get attacked piece value
SAL DH ; Double it
MOV CH,DH ; Save
CALL NEXTAD ; Retrieve first attacker
JMP PF5 ; Jump
PF19: MOV AL,[P1] ; Load King or Queen
AND AL,7 ; Clear flags
CMP AL,QUEEN ; Queen ?
JNZ PF20 ; No - j[DE]
XCHG CX,[BC] ; Swap regs.
MOV AL,[P1] ; Piece attacked
MOV BX,WACT ; Addr of white attkrs/dfndrs
MOV DX,BACT ; tered
CMP AL,QUEEN ; Queen ?
JZ PF19 ; Yes - jump
MOV BL,AL ; Save piece type
MOV AL,CH ; Direction counter
CMP AL, PF1 ; Jump
;***********************************************************
; EXCHANGE ROUTINE
;***************************** ; Defenders minus attackers
DEC AL ; Less 1
POP DI ; Restore regs.
POP DX
POP CX
JNS PF25 ; Jump if pin not valid
JNZ XC10
JMP RET ; Return if none
XC10: MOV BL,AL ; Save attacker value
CALL NEXTAD ; Get next defender
JZ XC18 ; Juump
PUSH CX ; Save regs.
PUSH DX
PUSH DI
XOR AX,AX ; Zero out attack list
MOV CX,7
MOV BX,ATKLST
XCHG DI,BX
CLAddr of black attkrs/dfndrs
TEST AL,080H ; Is piece white ?
JZ XC5 ; Yes - jump
XCHG DX,BX ; Swap list pointers
XC5: M5 ; Non-diagonal direction ?
JC PF10 ; Yes - jump
MOV AL,BL ; Piece type
CMP AL,BISHOP ; Bishop ?
JNZ PF25 ; No - ju******************************
; FUNCTION: -- To determine the exchange value of a
; piece on a given squar
PF20: MOV BX,NPINS ; Address of pinned piece count
INC B,[BX] ; Increment
MOV SI,[NPINS] ; Load pin list index
MOV [SI+Pmp if none
LAHF
CMP CH,BL ; Attacked less than attacker ?
JNC XC19 ; No - jump
XC15: CMP AL,BL ; Defender less than atD
REP
STOW
XCHG DI,BX
MOV AL,7 ; Set attack flag
MOV [T1],AL
CALL ATTACK ; Find attackers/defenders
MOV BX,WACT OV CH,[BX] ; Init list counts
XCHG DX,BX
MOV CL,[BX]
XCHG DX,BX
XCHG BX,[HL]
XCHG DX,[DE]
XCHG CX,[BC] ; Restore rmp
JMP PF20 ; Jump
JPF25: JMP PF25
PF10: MOV AL,BL ; Piece type
CMP AL,ROOK ; Rook ?
JNZ PF25 ; No - jump
JMP PF20e by examining all
; attackers and defenders of that piece.
;
; CALLED BY: -- POINTS
;
; CALLS: -- LISTD],CL ; Save direction of pin
MOV AL,[M4] ; Position of pinned piece
MOV [SI+PLIST],AL ; Save in list
PF25: INC DI ; tacker ?
JC RET ; Yes - return
CALL NEXTAD ; Retrieve next attacker value
JZ RET ; Return if none
MOV BL,AL ; Save a ; White queen attackers
MOV DX,BACT ; Black queen attackers
TEST B,[P1],080H ; Is queen white ?
JZ PF19A ; Yes - skip
egs.
MOV CL,0 ; Init attacker/defender flag
MOV DL,0 ; Init points lost count
MOV SI,[T3] ; Load piece value index
MO ; Jump
PF15: AND AL,AL ; Possible pin ?
JNZ PF25 ; No - jump
MOV AL,[M2] ; Save possible pin position
MOV [M4],AL
NEXTAD
;
; ARGUMENTS: -- None.
;***********************************************************
XCHNG: XCHG BX,[HL]
XCHG DX,ttacker value
CALL NEXTAD ; Retrieve next defender value
JNZ XC15 ; Jump if none
XC18: LAHF
XC19: TEST CL,001H ; Attack***************************
;FUNCTION: -- To perform a static board evaluation and
; derive a score for a gi ; Decrement list count
NX5: INC BX ; Increment list pointer
CMP AL,[BX] ; Check next item in list
JZ NX5 ; Jump if emp6A ; Yes - Jump
JMP PT6X ; Jump
PT6AA: TEST B,[BX],010H ; Castled yet ?
JZ PT6A ; No - jump
MOV AL,+6 ; Bonus for cas that piece from the list.
;
; CALLED BY: -- XCHNG
;
; CALLS: -- None
;
; ARGUMENTS: -- Attack list ax
MOV SI,[M3] ; Load board index
MOV AL,[SI+BOARD] ; Get piece from board
CMP AL,-1 ; Off board edge ?
JNZ PT5A
JMP er or defender ?
JZ XC20 ; Jump if defender
NEG CH ; Negate value for attacker
XC20: ADD DL,CH ; Total points lost
SAHven board position
;
; CALLED BY: -- FNDMOV
; EVAL
;
; CALLS: -- ATTACK
; XCHNG
;ty
MOV AL,[BX] ; Get value from list
MOV AH,AL
SHR AH
SHR AH
SHR AH
SHR AH
MOV [BX],AH
AND AL,0FH
DEC BX ; Dtling
TEST B,[BX],080H ; Check piece color
JZ PT6D ; Jump if white
MOV AL,-6 ; Bonus for black castling
JP PT6D ; Jumddresses.
; Side flag
; Attack list counts
;*************************************************PT25 ; Yes - jump
PT5A: MOV BX,P1 ; Save piece, if any
MOV [BX],AL
AND AL,7 ; Save piece type, if any
MOV [T3],AL
CMF
JZ RET ; Return if none
MOV CH,BL ; Prev attckr becomes defender
JMP XC10 ; Jump
;******************************** LIMIT
;
; ARGUMENTS: -- None
;***********************************************************
POINTS: XOR AL,ecrement list pointer
ADD AL,AL ; Double it
NX6: XCHG BX,[HL]
XCHG DX,[DE]
XCHG CX,[BC] ; Restore regs.
RET ; Returp
PT6A: TEST B,[BX],008H ; Has piece moved yet ?
JZ PT6X ; No - jump
JP PT6C ; Jump
PT6B: TEST B,[BX],008H ; Has piece m**********
NEXTAD: INC CL ; Increment side flag
XCHG BX,[HL]
XCHG DX,[DE]
XCHG CX,[BC] ; Swap registers
XCHG CH,CL ;P AL,KNIGHT ; Less than a Knight (Pawn) ?
JC PT6X ; Yes - Jump
CMP AL,ROOK ; Rook, Queen or King ?
JC PT6B ; No - jump
***************************
; NEXT ATTACKER/DEFENDER ROUTINE
;***********************************************************
; FAL ; Zero out variables
MOV [MTRL],AL
MOV [BRDC],AL
MOV [PTSL],AL
MOV [PTSW1],AL
MOV [PTSW2],AL
MOV [PTSCK],AL
MOn
;***********************************************************
; POINT EVALUATION ROUTINE
;********************************oved yet ?
JNZ PT6X ; Yes - jump
PT6C: MOV AL,-2 ; Two point penalty for white
TEST B,[BX],080H ; Check piece color
JZ Swap list counts
XCHG DX,BX ; Swap list pointers
XOR AL,AL
CMP AL,CH ; At end of list ?
JZ NX6 ; Yes - jump
DEC CH
CMP AL,KING ; Is it a King ?
JZ PT6AA ; Yes - jump
MOV AL,[MOVENO] ; Get move number
CMP AL,7 ; Less than 7 ?
JC PTUNCTION: -- To retrieve the next attacker or defender
; piece value from the attack list, and delete
; V BX,T1 ; Set attacker flag
MOV B,[BX],7
MOV AL,21 ; Init to first square on board
PT5: MOV [M3],AL ; Save as board indePT6D ; Jump if white
MOV AL,+2 ; Two point penalty for black
PT6D: MOV BX,BRDC ; Get address of board control
ADD [BX],AMP AL,[BX] ; Compare to current value
JC PT23 ; Jump if greater than
MOV [BX],AL ; Store as new 2nd max lost
PT23: TEST Store new value as max lost
MOV SI,[MLPTRJ] ; Load pointer to this move
MOV AL,[M3] ; Get position of lost piece
CMP AL,[EST B,[COLOR],080H ; Is color of side just moved white ?
JZ PT28 ; Yes - jump
NEG AL ; Negate for black
PT28: MOV BX,MTRL25 ; Yes - jump
CALL XCHNG ; Evaluate exchange, if any
XOR AL,AL ; Check for a loss
CMP AL,DL ; Points lost ?
JZ PT2],AL ; Store as max points won
XOR AL,AL ; Zero out 2nd max points won
MOV [PTSW2],AL
PT25A: MOV AL,[PTSL] ; Get max pointL ; Add on penalty/bonus points
PT6X: XOR AX,AX ; Zero out attack list
MOV CX,7
MOV BX,ATKLST
XCHG DI,BX
CLD
REP
B,[P1],080H ; Test piece color
MOV AL,DH ; Value of piece
JZ PT24 ; Jump if white
NEG AL ; Negate for black
PT24: MOV SI+MLTOP] ; Is it the one moving ?
JNZ PT23 ; No - jump
MOV [PTSCK],AL ; Save position as a flag
JP PT23 ; Jump
PT20: M ; Net material on board
ADD AL,[BX] ; Add exchange adjustments
MOV BX,MV0 ; Material at ply 0
SUB AL,[BX] ; Subtract 3 ; No - Jump
DEC DH ; Deduct half a Pawn value
MOV AL,[P1] ; Get piece under attack
XOR AL,[COLOR] ; Compare color of s lost
AND AL,AL ; Is it zero ?
JZ PT26 ; Yes - jump
DEC AL ; Decrement it
PT26: MOV CH,AL ; Save it
MOV AL,[PTSW1]STOW
XCHG DI,BX
CALL ATTACK ; Build attack list for square
MOV BX,BACT ; Get black attacker count addr
MOV AL,[WACT] ;BX,MTRL ; Get addrs of material total
ADD AL,[BX] ; Add new value
MOV [BX],AL ; Store
PT25: MOV AL,[M3] ; Get current bOV BX,PTSW1 ; Previous maximum points won
CMP AL,[BX] ; Compare to current value
JC PT21 ; Jump if greater than
MOV AL,[from current
MOV CH,AL ; Save
MOV AL,30 ; Load material limit
CALL LIMIT ; Limit to plus or minus value
MOV DL,AL ; side just moved with piece
TEST AL,080H ; Do colors match ?
MOV AL,DL ; Points lost
JNZ PT20 ; Jump if no match
MOV B ; Max,points won
AND AL,AL ; Is it zero ?
JZ PT27 ; Yes - jump
MOV AL,[PTSW2] ; 2nd max points won
AND AL,AL ; Is it Get white attacker count
SUB AL,[BX] ; Compute count difference
MOV BX,BRDC ; Address of board control
ADD AL,[BX] ; Aoard position
INC AL ; Increment
CMP AL,99 ; At end of board ?
JZ PT25AA
JMP PT5 ; No - jump
PT25AA: MOV AL,[PTSCK] BX] ; Load previous max value
MOV [BX],DL ; Store new value as max won
PT21: MOV BX,PTSW2 ; Previous 2nd max points won
CSave limited value
MOV AL,[BRDC] ; Get board control points
MOV BX,BC0 ; Board control at ply zero
SUB AL,[BX] ; Get difX,PTSL ; Previous max points lost
CMP AL,[BX] ; Compare to current value
JC PT23 ; Jump if greater than
MOV [BX],DL ; zero ?
JZ PT27 ; Yes - jump
DEC AL ; Decrement it
SHR AL ; Divide it by 2
PT27: SUB AL,CH ; Subtract points lost
Tccum board control score
MOV [BX],AL ; Save
MOV AL,[P1] ; Get piece on current square
AND AL,AL ; Is it empty ?
JZ PT; Moving piece lost flag
AND AL,AL ; Was it lost ?
JZ PT25A ; No - jump
MOV AL,[PTSW2] ; 2nd max points won
MOV [PTSW1ference
MOV CH,AL ; Save
MOV AL,[PTSCK] ; Moving piece lost flag
AND AL,AL ; Is it zero ?
JZ PT29 ; Yes - jump
MOV *********************
; MOVE ROUTINE
;***********************************************************
; FUNCTION: -- To executgister
; Output - Limited value in the AL register.
;*********************************************************flag
MOV [DI+BOARD],DL ; Insert piece at new position
MOV B,[SI+BOARD],0 ; Empty previous position
TEST DH,040H ; Double MLVAL],AL ; Save score in move list
RET ; Return
;***********************************************************
; LIMIT RO ; "To" position
MOV [M2],AL ; Save
INC BX ; Increment pointer
MOV DH,[BX] ; Get captured piece/flags
MOV SI,[M1] ; CH,0 ; Zero board control points
PT29: MOV AL,6 ; Load board control limit
CALL LIMIT ; Limit to plus or minus value
MOVe a move from the move list on the
; board array.
;
; CALLED BY: -- CPTRMV
; PLYRMV
; **
LIMIT: TEST CH,080H ; Is value negative ?
JZ LIM10 ; No - jump
NEG AL ; Make positive
CMP AL,CH ; Compare to limitmove ?
JNZ MV40 ; Yes - jump
MOV AL,DH ; Get captured piece, if any
AND AL,7
CMP AL,QUEEN ; Was it a queen ?
JNZ RETUTINE
;***********************************************************
; FUNCTION: -- To limit the magnitude of a given value
Load "from" pos board index
MOV DL,[SI+BOARD] ; Get piece moved
TEST DH,020H ; Test Pawn promotion flag
JNZ MV15 ; Jump DH,AL ; Save limited value
MOV AL,DL ; Get material points
ADD AL,AL ; Multiply by 4
ADD AL,AL
ADD AL,DH ; Add boar EVAL
; FNDMOV
; VALMOV
;
; CALLS: -- None
;
; ARGUMENTS: -- None
;**
JNC RET ; Return if outside limit
MOV AL,CH ; Output value as is
RET ; Return
LIM10: CMP AL,CH ; Compare to limit
; No - return
MOV BX,POSQ ; Addr of saved Queen position
TEST DH,080H ; Is Queen white ?
JZ MV10 ; Yes - jump
INC B; to another given value.
;
; CALLED BY: -- POINTS
;
; CALLS: -- None
;
; ARGUMENTS: -- Input -if set
MOV AL,DL ; Piece moved
AND AL,7 ; Clear flag bits
CMP AL,QUEEN ; Is it a queen ?
JZ MV20 ; Yes - jump
CMP Ad control
TEST B,[COLOR],080H ; Is color of side just moved white ?
JNZ PT30 ; No - jump
NEG AL ; Negate for white
PT30*********************************************************
MOVE: MOV BX,[MLPTRJ] ; Load move list pointer
INC BX ; Increment JC RET ; Return if outside limit
MOV AL,CH ; Output value as is
RET ; Return
;**************************************X ; Increment to black Queen pos
MV10: XOR AL,AL ; Set saved position to zero
MOV [BX],AL
RET ; Return
MV15: OR DL,004 Value, to be limited in the CH
; register.
; - Value to limit to in the AL reL,KING ; Is it a king ?
JZ MV30 ; Yes - jump
MV5: MOV DI,[M2] ; Load "to" pos board index
OR DL,008H ; Set piece moved : ADD AL,80H ; Rescale score (neutral = 80H)
MOV [VALM],AL ; Save score
MOV SI,[MLPTRJ] ; Load move list pointer
MOV [SI+past link bytes
INC BX
MV1: MOV AL,[BX] ; "From" position
MOV [M1],AL ; Save
INC BX ; Increment pointer
MOV AL,[BX] H ; Change Pawn to a Queen
JMP MV5 ; Jump
MV20: MOV BX,POSQ ; Addr of saved Queen position
MV21: TEST DL,080H ; Is QueenM20 ; Yes - jump
CMP AL,KING ; Was it a King ?
JZ UM30 ; Yes - jump
UM5: TEST DH,010H ; Is this 1st move for piece ?
; Increment past link bytes
INC BX
UM1: MOV AL,[BX] ; Get "from" position
MOV [M1],AL ; Save
INC BX ; Increment poin
UM30: MOV BX,POSK ; Address of saved King pos
TEST DH,040H ; Was it a castle ?
JZ UM21 ; No - jump
AND DL,0EFH ; CleaE ROUTINE
;***********************************************************
; FUNCTION: -- To reverse the process of the move roUM10 ; Yes - jump
INC BX ; Increment to black Queen pos
UM10: MOV AL,[M2] ; Queen's previous position
MOV [BX],AL ; Sav white ?
JZ MV22 ; Yes - jump
INC BX ; Increment to black Queen pos
MV22: MOV AL,[M2] ; Get new Queen position
MOV [BXJNZ UM16 ; Yes - jump
UM6: MOV DI,[M1] ; Load "from" pos board index
MOV [DI+BOARD],DL ; Return to previous board pos
MOVter
MOV AL,[BX] ; Get "to" position
MOV [M2],AL ; Save
INC BX ; Increment pointer
MOV DH,[BX] ; Get captured piece/fr castled flag
JMP UM21 ; Jump
UM40: MOV BX,[MLPTRJ] ; Load move list pointer
ADD BX,8 ; Increment to next move
JMP UM1utine,
; thereby restoring the board array to its
; previous position.
;
; CALLED BY: -- Ve
RET ; Return
UM15: AND DL,0FBH ; Restore Queen to Pawn
JMP UM5 ; Jump
UM16: AND DL,0F7H ; Clear piece moved flag
],AL ; Save
JMP MV5 ; Jump
MV30: MOV BX,POSK ; Get saved King position
TEST DH,020H ; Castling ?
JZ MV21 ; No - jump AL,DH ; Get captured piece, if any
AND AL,8FH ; Clear flags
MOV [SI+BOARD],AL ; Return to board
TEST DH,040H ; Was it lags
MOV SI,[M2] ; Load "to" pos board index
MOV DL,[SI+BOARD] ; Get piece moved
TEST DH,020H ; Was it a Pawn promotion ; Jump (2nd part of dbl move)
;***********************************************************
; SORT ROUTINE
;**************ALMOV
; EVAL
; FNDMOV
; ASCEND
;
; CALLS: -- None
;
; ARGUMENTS: -JMP UM6 ; Jump
UM20: MOV BX,POSQ ; Addr of saved Queen position
UM21: TEST DL,080H ; Is Queen white ?
JZ UM22 ; Yes - ju
OR DL,010H ; Set King castled flag
JMP MV21 ; Jump
MV40: MOV BX,[MLPTRJ] ; Get move list pointer
ADD BX,8 ; Incrementa double move ?
JNZ UM40 ; Yes - jump
MOV AL,DH ; Get captured piece, if any
AND AL,7 ; Clear flag bits
CMP AL,QUEEN ?
JNZ UM15 ; Yes - jump
MOV AL,DL ; Get piece moved
AND AL,7 ; Clear flag bits
CMP AL,QUEEN ; Was it a Queen ?
JZ U*********************************************
; FUNCTION: -- To sort the move list in order of
; increasing- None
;***********************************************************
UNMOVE: MOV BX,[MLPTRJ] ; Load move list pointer
INC BXmp
INC BX ; Increment to black Queen pos
UM22: MOV AL,[M1] ; Get previous position
MOV [BX],AL ; Save
JMP UM5 ; Jump
to next move
JMP MV1 ; Jump (2nd part of dbl move)
;***********************************************************
; UN-MOV; Was it a Queen ?
JNZ RET ; No - return
MOV BX,POSQ ; Address of saved Queen pos
TEST DH,080H ; Is Queen white ?
JZ move value scores.
;
; CALLED BY: -- FNDMOV
;
; CALLS: -- EVAL
;
; ARGUMENTS: -- None
;************************************
EVAL: CALL MOVE ; Make move on the board array
CALL INCHK ; Determine if move is legal
AND AL,AL ; Legal m****************************************
; FUNCTION: -- To evaluate a given move in the move list.
; It fir],AL
MOV BX,0 ; Initialize best move to zero
MOV [BESTM],BX
MOV BX,MLIST ; Initialize ply list pointers
MOV [MLNXT],BX
[BX] ; Next move for compare
INC BX
MOV DH,[BX]
XOR AL,AL ; At end of list ?
CMP AL,DH
JZ SR25 ; Yes - jump
MOV S the techniques of alpha-beta pruning.
;
; CALLED BY: -- CPTRMV
;
; CALLS: -- PINFND
; POINTS
************************************
SORTM: MOV CX,[MLPTRI] ; Move list begin pointer
MOV DX,0 ; Initialize working pointersove ?
JZ EV5 ; Yes - jump
XOR AL,AL ; Score of zero
MOV [VALM],AL ; For illegal move
JMP UNMOVE ; Jump
EV5: CALL PINst makes the move on the board, then if
; the move is legal, it evaluates it, and then
; resto
MOV BX,PLYIX-2
MOV [MLPTRI],BX
MOV AL,[KOLOR] ; Initialize color
MOV [COLOR],AL
MOV BX,SCORE ; Initialize score index
I,DX ; Transfer move pointer
MOV AL,[VALM] ; Get new move value
CMP AL,[SI+MLVAL] ; Less than list value ?
JNC SR30 ; No
; GENMOV
; SORTM
; ASCEND
; UNMOVE
;
; ARGUMENTS: -- Non
SR5: MOV BH,CH
MOV BL,CL
MOV CL,[BX] ; Link to next move
INC BX
MOV CH,[BX]
MOV [BX],DH ; Store to link in list
FND ; Compile pinned list
CALL POINTS ; Assign points to move
JMP UNMOVE ; Restore board array
;**********************res the board position.
;
; CALLED BY: -- SORT
;
; CALLS: -- MOVE
; INCHK
; PINFND
MOV [SCRIX],BX
MOV AL,[PLYMAX] ; Get max ply number
ADD AL,2 ; Add 2
MOV CH,AL ; Save as counter
XOR AL,AL ; Zero o - jump
SR25: MOV [BX],CH ; Link new move into list
DEC BX
MOV [BX],CL
JMP SR5 ; Jump
SR30: XCHG DX,BX ; Swap pointere
;***********************************************************
FNDMOV: MOV AL,[MOVENO] ; Current move number
CMP AL,1 ; FirDEC BX
MOV [BX],DL
XOR AL,AL ; End of list ?
CMP AL,CH
JZ RET ; Yes - return
SR10: MOV [MLPTRJ],CX ; Save list pointe*************************************
; FIND MOVE ROUTINE
;***********************************************************
; FUNC
; POINTS
; UNMOVE
;
; ARGUMENTS: -- None
;**********************************************ut score table
FM1: MOV [BX],AL
INC BX
DEC CH
JNZ FM1
MOV [BC0],AL ; Zero ply 0 board control
MOV [MV0],AL ; Zero plys
JMP SR15 ; Jump
;***********************************************************
; EVALUATION ROUTINE
;*******************st move ?
JNZ L0003
CALL BOOK ; Yes - execute book opening
L0003:
XOR AL,AL ; Initialize ply number to zero
MOV [NPLYr
CALL EVAL ; Evaluate move
MOV BX,[MLPTRI] ; Begining of move list
MOV CX,[MLPTRJ] ; Restore list pointer
SR15: MOV DL,TION: -- To determine the computer's best move by
; performing a depth first tree search using
; 0 material
CALL PINFND ; Compile pin list
CALL POINTS ; Evaluate board at ply 0
MOV AL,[BRDC] ; Get board control pointLPTRJ] ; Load move pointer
MOV AL,[SI+MLVAL] ; Get move score
AND AL,AL ; Is it zero (illegal move) ?
JZ FM15 ; Yes - juK ; Check for legal move
AND AL,AL ; Is move legal
JZ FM16 ; Yes - jump
CALL UNMOVE ; Restore board position
JMP FM1X ; Restore pointer
DEC BX
JMP FM37 ; Jump
JFM15: JMP FM15
FM35: CALL PINFND ; Compile pin list
CALL POINTS ; Evalua
FM15: MOV BX,[MLPTRJ] ; Load last move pointer
MOV DL,[BX] ; Get next move pointer
INC BX
MOV DH,[BX]
MOV AL,DH
AND KFLG] ; Get check flag
AND AL,AL ; Was King in check ?
MOV AL,80H ; Pre-set stalemate score
JZ FM36 ; No - jump (stalems
MOV [BC0],AL ; Save
MOV AL,[MTRL] ; Get material count
MOV [MV0],AL ; Save
FM5: MOV BX,NPLY ; Address of ply counter
mp
CALL MOVE ; Execute move on board array
FM19: XOR B,[COLOR],80H ; Toggle color, is new color white ?
JS FM20 ; No - ju5 ; Jump
FM16: MOV AL,[NPLY] ; Get ply counter
MOV BX,PLYMAX ; Max ply number
CMP AL,[BX] ; Beyond max ply ?
JZ FM17
te move
CALL UNMOVE ; Restore board position
MOV AL,[VALM] ; Get value of move
FM36: OR B,[MATEF],001H ; Set mate flag
MAL,AL ; End of move list ?
JNZ FM15A
JMP FM25 ; Yes - jump
FM15A: MOV [MLPTRJ],DX ; Save current move pointer
MOV BX,[Mate)
MOV AL,[MOVENO] ; Get move number
MOV [PMATE],AL ; Save
MOV AL,0FFH ; Pre-set checkmate score
JMP FM36 ; Jump
FM INC B,[BX] ; Increment ply count
XOR AL,AL ; Initialize mate flag
MOV [MATEF],AL
CALL GENMOV ; Generate list of moves
mp
INC B,[MOVENO] ; Increment move number
FM20: MOV BX,[SCRIX] ; Load score table pointer
MOV AL,[BX] ; Get score two plysJMP FM35 ; Yes - jump
FM17: MOV AL,[COLOR] ; Get current color
XOR AL,80H ; Get opposite color
CALL INCHK1 ; Determine iOV BX,[SCRIX] ; Load score table pointer
FM37: CMP AL,[BX] ; Compare to score 2 ply above
JC FM40 ; Jump if less
JZ FM40 LPTRI] ; Save in ply pointer list
MOV [BX],DL
INC BX
MOV [BX],DH
MOV AL,[NPLY] ; Current ply counter
MOV BX,PLYMAX ; M30: MOV AL,[NPLY] ; Get ply counter
CMP AL,1 ; At top of tree ?
JZ RET ; Yes - return
CALL ASCEND ; Ascend one ply in t
MOV AL,[NPLY] ; Current ply counter
MOV BX,PLYMAX ; Address of maximum ply number
CMP AL,[BX] ; At max ply ?
JNC L0004
above
INC BX ; Increment to current ply
MOV [SCRIX],BX ; Save it
INC BX
MOV [BX],AL ; Save score as initial value
Jf King is in check
AND AL,AL ; In check ?
JZ FM35 ; No - jump
JMP FM19 ; Jump (One more ply for check)
FM18: MOV SI,[M ; Jump if equal
NEG AL ; Negate score
INC BX ; Incr score table pointer
CMP AL,[BX] ; Compare to score 1 ply above
Jaximum ply number ?
CMP AL,[BX] ; Compare
JC FM18 ; Jump if not max
CALL MOVE ; Execute move on board array
CALL INCHree
MOV BX,[SCRIX] ; Load score table pointer
INC BX ; Increment to current ply
INC BX
MOV AL,[BX] ; Get score
DEC B
CALL SORTM ; No - call sort
L0004:
MOV BX,[MLPTRI] ; Load ply index pointer
MOV [MLPTRJ],BX ; Save as last move pointer
MP FM5 ; Jump
FM25: MOV AL,[MATEF] ; Get mate flag
AND AL,AL ; Checkmate or stalemate ?
JNZ FM30 ; No - jump
MOV AL,[CC JFM15 ; Jump if less than
JZ JFM15 ; Jump if equal
MOV [BX],AL ; Save as new score 1 ply above
MOV AL,[NPLY] ; Get cuvious ply
;***********************************************************
; ONE MOVE BOOK OPENING
; **************************w color white ?
JNS AC5 ; Yes - jump
DEC B,[MOVENO] ; Decrement move number
AC5: DEC [SCRIX] ; Decrement score table inde ; return (P-K4)
CMP AL,35 ; Is it a King Pawn ?
JZ RET ; Yes - return (P-K4)
BM9: ADD B,[BX],3 ; (P-Q4)
RET ; Retuturn
FM40: CALL ASCEND ; Ascend one ply in tree
JMP FM15 ; Jump
;*******************************************************OV AL,0 ; Load random number (0)
TEST AL,001H ; Test random bit
JZ RET ; Return if zero (P-K4)
ADD B,[BX],3 ; P-Q4
RErrent ply counter
CMP AL,1 ; At top of tree ?
JNZ JFM15 ; No - jump
MOV BX,[MLPTRJ] ; Load current move pointer
MOV [B********************************
; FUNCTION: -- To provide an opening book of a single
; move.
;
; CALLEDx
DEC B,[NPLY] ; Decrement ply counter
MOV BX,[MLPTRI] ; Load ply list pointer
DEC BX ; Load pointer to move list top
rn to CPTRMV
;***********************************************************
; COMPUTER MOVE ROUTINE
;****************************
; ASCEND TREE ROUTINE
;***********************************************************
; FUNCTION: -- To adjust all necessT ; Return
BM5: ADD B,[BX],6 ; Increment to black moves
MOV SI,[MLPTRJ] ; Pointer to opponents 1st move
MOV AL,[SI+MLFRP]ESTM],BX ; Save as best move pointer
MOV AL,[SCORE+1] ; Get best move score
CMP AL,0FFH ; Was it a checkmate ?
JNZ JFM15 BY: -- FNDMOV
;
; CALLS: -- None
;
; ARGUMENTS: -- None
;*******************************************************DEC BX
MOV DX,[BX]
MOV [MLNXT],DX ; Update move list avail ptr
DEC BX ; Get ptr to next move to undo
DEC BX
MOV DX,[B***********************************
; FUNCTION: -- To control the search for the computers move
; and the dary parameters to
; ascend one ply in the tree.
;
; CALLED BY: -- FNDMOV
;
; CALLS: -- UNMOVE
;
; AR ; Get "from" position
CMP AL,22 ; Is it a Queen Knight move ?
JZ BM9 ; Yes - Jump
CMP AL,27 ; Is it a King Knight move ; No - jump
MOV BX,PLYMAX ; Get maximum ply number
SUB B,[BX],2 ; Subtract 2
MOV AL,[KOLOR] ; Get computer's color
TEST****
BOOK: POP AX
MOV B,[SCORE+1],0 ; Zero out score table
MOV [BESTM],BMOVES-2 ; Init best move ptr to book
MOV BX,BESTMX]
MOV [MLPTRI],BX ; Save new ply list pointer
MOV [MLPTRJ],DX ; Save next move pointer
JMP UNMOVE ; Restore board to preisplay of that move on the board
; and in the move list.
;
; CALLED BY: -- DRIVER
;
; CALLS: -- FNDGUMENTS: -- None
;***********************************************************
ASCEND: XOR B,[COLOR],80H ; Toggle color, is ne ?
JZ BM9 ; Yes - jump
CMP AL,34 ; Is it a Queen Pawn ?
JZ BM9 ; Yes - jump
JC RET ; If Queen side Pawn opening -
AL,080H ; Is it white ?
JZ RET ; Yes - return
MOV BX,PMATE ; Checkmate move number
DEC B,[BX] ; Decrement
RET ; Re ; Initialize address of pointer
MOV AL,[KOLOR] ; Get computer's color
AND AL,AL ; Is it white ?
JNZ BM5 ; No - jump
MMOV
; FCDMAT
; MOVE
; BITASN
; INCHK
;
; ARGUMENTS: -- N not the current move is checkmate. If it is,
; a losing player is offered another game,
; ; Output "check"
MOV CL,PRINTBUF
CALL SYSTEM
CP24: MOV AL,[SCORE+1] ; Check again for mates
CMP AL,0FFH ; Player mated
MOV CL,INCHAR ; Input any char to play again
CALL SYSTEM
JMP DRIVER ; Jump (Rest of game init)
;********************* ; Convert to Ascii
MOV [MVEMSG+3],BX ; Put in move message
MOV DH,[SI+MLFRP] ; "From" position of the move
CALL BITASN SUB AL,CH ; Number of moves till mate
AND AL,AL ; Checkmate ?
JNZ RET ; No - return
RCR AH
TEST CL,001H ; Check flaone
;***********************************************************
CPTRMV: CALL FNDMOV ; Select best move
MOV BX,[BESTM] ; Mo while a loss for the computer signals the
; King to tip over in resignation.
;
; CALLED BY: -- C?
JNZ RET ; No - return
MOV CL,0 ; Set player mate flag
CALL FCDMAT ; Full checkmate ?
RET ; Return
;*************************************************
; BOARD INDEX TO ASCII SQUARE NAME
;***************************************************; Convert to Ascii
MOV [MVEMSG],BX ; Put in move message
MOV DX,MVEMSG ; Output move
MOV CL,PRINTBUF
CALL SYSTEM
CP1C: g for who is mated
RCL AH
JZ FM04 ; Jump if player
MOV DX,CKMSG ; Print "CHECK"
MOV CL,PRINTBUF
CALL SYSTEM
MOV DX,ve list pointer variable
MOV [MLPTRJ],BX ; Pointer to move data
MOV AL,[SCORE+1] ; To check for mates
CMP AL,1 ; Mate agaPTRMV
;
; CALLS: -- None
;
; ARGUMENTS: -- The only value passed in a register is the
; flag which ************************************************
; FORCED MATE HANDLING
;*************************************************************
; FUNCTION: -- To translate a hexadecimal index in the
; board array into an ascii description
; MOV AL,[COLOR] ; Should computer call check ?
MOV CH,AL
XOR AL,80H ; Toggle color
MOV [COLOR],AL
CALL INCHK ; Check foUWIN ; Output "YOU WIN"
MOV CL,PRINTBUF
CALL SYSTEM
JP FM08 ; Jump
FM04: MOV DX,CKMSG ; Print "CHECK"
MOV CL,PRINTBUFinst computer ?
JNZ CP0C ; No - jump
MOV CL,1 ; Computer mate flag
CALL FCDMAT ; Full checkmate ?
CP0C: CALL MOVE ; Ptells FCDMAT whether the computer
; or the player is mated.
;*******************************************************
; FUNCTION: -- To examine situations where there exits
; a forced mate and determine whether or
; of the square in algebraic chess notation.
;
; CALLED BY: -- CPTRMV
;
; CALLS: -- DIVIDE
;
; ARGUMr check
AND AL,AL ; Is enemy in check ?
MOV AL,CH ; Restore color
MOV [COLOR],AL
JZ CP24 ; No - return
MOV DX,CKMSG
CALL SYSTEM
MOV DX,IWIN ; Output "I WIN"
MOV CL,PRINTBUF
CALL SYSTEM
FM08: POP BX ; Remove return addresses
POP BXroduce move on board array
MOV SI,[MLPTRJ] ; Get pointer to move
MOV DH,[SI+MLTOP] ; "To" position of the move
CALL BITASN**********
FCDMAT: MOV AL,[MOVENO] ; Current move number
MOV CH,AL ; Save
MOV AL,[PMATE] ; Move number where mate occurs
ENTS: -- Board index input in register DH and the
; Ascii square name is output in register BX.
;***********p if invalid
MOV [MVEMSG+1],AL ; Move list "to" position
CALL VALMOV ; Determines if a legal move
OR AL,AL ; Legal ?
Jpty ?
JZ PLYRMV ; Jump if empty
MOV CH,AL ; Save length
LAHF
INC BX ; Point to actual buffer
SAHF
MOV AL,[BX] ; V AL,[BX]
SUB AL,31H ; Rank 1 - 8
JC RET
CMP AL,8 ; Check upper bound
CMC
JC RET
ADD AL,AL ; Multiply rank by 10
validate the players move
; Also allows player to resign the game by
; entering R.
;
; CALL PLYRMV
;
; CALLS: -- None
;
; ARGUMENTS: -- Accepts the square name in pointer BX
; and outputs th************************************************
BITASN: SUB AL,AL ; Get ready for division
MOV DL,10
CALL DIVIDE ; DividZ RET ; Yes - return
PL08: MOV DX,INVAL ; Output "INVALID MOVE--TRY AGAIN"
MOV CL,PRINTBUF
CALL SYSTEM
JP PLYRMV ; JumpGet first char
CMP AL,"R" ; Restart game ?
JNZ PL05 ; Jump if not restart
JMP DRIVER
PL05: MOV AL,CH ; Get input lengt
MOV CL,AL
ADD AL,AL
ADD AL,AL
ADD AL,CL
ADD AL,CH ; 10 * rank + file
INC BX ; Increment pointer
ADD AL,21
RET ED BY: -- DRIVER
;
; CALLS: -- ASNTBI
; VALMOV
;
; ARGUMENTS: -- None
;*************************e board index in register AL.
; CF = 0 if ok. CF = 1 if invalid.
;********************************************e
DEC DH ; Get rank on 1-8 basis
ADD AL,60H ; Convert file to Ascii (a-h)
MOV BL,AL ; Save
MOV AL,DH ; Rank
ADD AL
;***********************************************************
; ASCII SQUARE NAME TO BOARD INDEX
;*************************h
CMP AL,5 ; Long enough ?
JC PL08 ; Jump if less than 5 chars
CALL ASNTBI ; Convert "from" to a board index
JC PL08 ; Return
;***********************************************************
; VALIDATE MOVE SUBROUTINE
;*********************************************************
PLYRMV: MOV DX,BUFFER ; Ask for input
MOV CL,INBUF
CALL SYSTEM
MOV DX,CRLF ; Output C***************
ATBINX: INC BX ; Increment pointer to skip a char
ASNTBI: MOV AL,[BX] ; Ascii file letter (a - h)
INC BX
,30H ; Convert rank to Ascii (1-8)
MOV BH,AL ; Save
RET ; Return
;*************************************************************************************
; FUNCTION: -- To convert an algebraic square name in
; Ascii to a hexad ; Jump if invalid
MOV [MVEMSG],AL ; Move list "from" position
CALL ATBINX ; Convert "to" to a board index
JC PL08 ; Jum************************************
; FUNCTION: -- To check a players move for validity.
;
; CALLED BY: -- PLYRMV
;
;RLF
MOV CL,PRINTBUF
CALL SYSTEM
MOV BX,BUFFER+1 ; Point to input length
MOV AL,[BX] ; Get input length
OR AL,AL ; Em SUB AL,41H ; File 1 - 8
JC RET ; Not file letter
CMP AL,8 ; Check upper bound
CMC
JC RET ; Invalid
MOV CH,AL
MO********
; PLAYERS MOVE ANALYSIS
;***********************************************************
; FUNCTION: -- To accept andecimal board index.
; This routine also checks the input for
; validity.
;
; CALLED BY: -- CALLS: -- GENMOV
; MOVE
; INCHK
; UNMOVE
;
; ARGUMENTS: -- ReturnsL
JS DD05
INC DH
JP DD06
DD05: ADD AL,DL
DD06: DEC CH
JNZ DD04
POP CX
RET
CLRMSG: DB 13,10,"Choose your color ( Was it a legal move ?
AND AL,AL
JNZ VA9 ; No - jump
VA8: POP BX ; Restore saved register
RET ; Return
VA9: CALL UNMtual move.
Ply depth is the number of half-turns the computer looks ahead. For
example, with a ply depth of 3, the computer moves
VA5: MOV AL,[MVEMSG] ; "From" position
CMP AL,[SI+MLFRP] ; Is it in list ?
JNZ VA6 ; No - jump
MOV AL,[MVEMSG+1] ;This chess game uses algebraic chess notation. The files are lettered
"a" to "h" and the ranks are numbered 1 to 8. The lower l flag in register AL, 0 for valid
; and 1 for invalid move.
;*************************************************W/B): $"
PLYDEP: DB 13,10,"Ply depth (1-6): $"
MVEMSG: DB " ",13,10,"$"
CKMSG: DB "CHECK",13,10,"$"
UWIN: DB "You win",1OVE ; Un-do move on board array
VA10: MOV AL,1 ; Set flag for invalid move
POP BX ; Restore saved register
MOV [MLPTRJ],will consider
1. All of his possible moves
2. All of your responses to those moves.
3. All of his possible replies to your "To" position
CMP AL,[SI+MLTOP] ; Is it in list ?
JZ VA7 ; Yes - jump
VA6: MOV DL,[SI+MLPTR] ; Pointer to next list move
eft-hand corner
(from White's viewpoint) is a1.
Moves are entered as ff-tt (f=from, t=to), so to play the white king's
pawn**********
VALMOV: MOV BX,[MLPTRJ] ; Save last move pointer
PUSH BX ; Save register
MOV AL,[KOLOR] ; Computers color
XOR3,10,"$"
IWIN: DB "I win"
CRLF: DB 13,10,"$"
INVAL: DB "INVALID MOVE--TRY AGAIN",13,10,"$"
BUFFER: DB 7
DS 6
IX: DS 2
BX ; Save move pointer
RET ; Return
;***********************************************************
; POSITIVE INTEGER DIVI responses.
Start at ply depth 2 to get the feel for it.
A move of "R" will restart the game.

MOV DH,[SI+MLPTR+1]
XOR AL,AL ; At end of list ?
CMP AL,DH
JZ VA10 ; Yes - jump
PUSH DX ; Move to SI register
POP up two squares you would enter E2-E4. You must enter your file
letters in upper case, while the computer will always use lower AL,80H ; Toggle color
MOV [COLOR],AL ; Store
MOV BX,PLYIX-2 ; Load move list index
MOV [MLPTRI],BX
MOV BX,MLIST+1024 ;IY: DS 2
BC: DS 2
DE: DS 2
HL: DS 2
SION
;***********************************************************
DIVIDE: PUSH CX
MOV CH,8
DD04: SAL DH
RCL AL
SUB AL,D繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞 SI
JP VA5 ; Jump
VA7: MOV [MLPTRJ],SI ; Save opponents move pointer
CALL MOVE ; Make move on board array
CALL INCHK ; case.
To castle, enter only the king's move. The computer castles the same way.
To capture En Passant, enter your pawn's ac Next available list pointer
MOV [MLNXT],BX
CALL GENMOV ; Generate opponents moves
MOV SI,MLIST+1024 ; Index to start of 繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞FCB EQU 5CH
DSKRESET EQU 13
SETBASE EQU 38
SRCHFRST EQU 17
SRCHNXT EQU 18
RENAM EQU 23
INCHAR EQU 1
GETFAT EQU 27
OPEN E,COMTAB
FINDCOM:
MOV DI,IDLEN
MOV CL,[SI]
JCXZ EXTERNAL
REPE
CMPB
LAHF
ADD SI,CX ;Bump to next position without SI,LINBUF+2
MOV DI,ID
CALL FILEDRV ;Get COM drive
MOV [SPECDRV],AL
MOV CX,8
CALL COPYNAM ;Copy file name
MOV AL,9LIM
SUB AL,20H ;Lower-case changed to upper-case
DELIM:
CMP AL," "
JZ RET
CMP AL,"="
JZ RET
CMP AL,","
JZ RET
RLF
MOV CL,PRINTBUF
CALL SYSTEM
MOV DX,COMMAND
MOV AX,2522H ;Set vector 34 (terminate)
INT 33
MOV AX,2523H ;Set vectSTEM
MOV BX,DS ;New segment into BX
POP DS
MOV DX,IDLEN
MOV AH,OPEN
INT 33
OR AL,AL
JNZ BADCOM
MOV [IDLEN+RR],0QU 15
CLOSE EQU 16
MAKE EQU 22
DELETE EQU 19
RDBLK EQU 39
WRBLK EQU 40
SETDMA EQU 26
SELDRV EQU 14
GETDRV EQU 25
PRINTBaffecting flags
SAHF
LODW ;Get address of command
JNZ FINDCOM
CALL AX ;Call command
JMP COMMAND
SETDRV1:
JMP SETDR
SUB AL,CL
MOV [IDLEN],AL
MOV DI,81H
MOV CX,0
PUSH SI
COMTAIL:
LODB
STOB ;Move command tail to 80H
CMP AL,13
CMP AL,";"
JZ RET
CMP AL,9 ;Check for TAB character
RET
FILEDRV:
CALL NEXTCHR
JZ FILEDRV ;Skip delim
CMP AL,13
or 35 (CTRL-C)
INT 33
GETCOM:
MOV CL,GETDRV
CALL SYSTEM
ADD AL,"A"
MOV CL,OUTCH
MOV DL,AL
CALL SYSTEM ;Print dri
MOV CX,512 ;512 records
MOV AH,RDBLK
INT 33
MOV DS,BX
MOV ES,BX
MOV SS,BX
MOV SP,40H
MOV AX,0
PUSH AX
MOV UF EQU 9
OUTCH EQU 2
INBUF EQU 10
RR EQU 33
SYSTEM EQU 5
ORG 100H
PUT 100H
MOV SP,STACK
CLD
MOV DL,0 ;Start wV
DRVCHK:
DEC DL ;Adjust for correct drive number
DEC AL ;Check if anything else is on line
JZ SETDRV1
EXTERNAL:
MOV LOOPNZ COMTAIL
NOT CL
MOV [80H],CL
POP SI
MOV DI,FCB
CALL PARSENAM
MOV DI,FCB+10H
CALL PARSENAM
MOV AL,[IDLEN]
JZ NOMATCH
CMP B,[SI],":"
JNZ NOMATCH
SUB AL,40H ;A => 1, B => 2
INC SI
RET
PARSENAM:
CALL NEXTCHR
JZ ISDELIve letter
MOV DL,":"
MOV CL,OUTCH
CALL SYSTEM ;Print :
MOV DX,LINBUF
MOV CL,INBUF
CALL SYSTEM
MOV DL,10
MOV CL,AX,100H
PUSH BX
PUSH AX
MOV CL,SETDMA
MOV DX,80H
CALL SYSTEM
RET L
BADCOM:
MOV DX,BADNAM
MOV CL,PRINTBUF
CALLith A:
SETDRV:
MOV CL,SELDRV
CALL SYSTEM
COMMAND:
MOV SP,STACK
CLD
MOV AX,CS
MOV SS,AX
MOV ES,AX
MOV DS,AX
M AL,[SPECDRV]
MOV [IDLEN],AL
PUSH DS
MOV DX,TPA
ADD DX,0FH ;Round to next paragraph
SHR DX
SHR DX
SHR DX
SHR DX
MOV DL,[SPECDRV]
OR DL,DL ;Check if drive was specified
JNZ DRVCHK
DEC AL ;Check for null command
JZ GETCOM
MOV SIM
CMP AL,13
JNZ PARSENAM
DEC SI
ISDELIM:
CALL FILEDRV
STOB
MOV CX,11
CALL COPYNAM
ADD DI,CX
CMP CX,3
JB RETOUTCH
CALL SYSTEM ;New line
MOV CH,0
MOV SI,FILIFO ;8 spaces
MOV DI,ID
CALL FILLBUF
MOV DI,FCB
CALL FILLBUF
MOV SYSTEM
JMP COMMAND
NEXTCHR:
;Convert lower case input to upper case
LODB
CMP AL,"a"-1
JB DELIM
CMP AL,"z"
JA DEOV CX,[6]
SUB CX,TPA
AND CL,80H ;Round down
ROL CX
XCHG CH,CL
MOV [NUMREC],CX ;Number of records each time
MOV DX,C ;Divide 16
MOV CX,CS
ADD DX,CX ;New segment
MOV DS,DX
MOV AH,SETBASE
INT 33
MOV DX,100H
MOV CL,SETDMA
CALL SY
SUB DI,3
CMP AL,"."
JNZ NOMATCH
MOV CX,3
COPYNAM:
CALL NEXTCHR
JZ NOMATCH
CMP AL,13
JZ NOMATCH
CMP AL,"."
V CX,DX
INC DX
SHR DX
ADD CX,DX
MOV AX,DS
MOV ES,AX
MOV DI,BX
MOV AX,0FFFFH
STOW
STOB ;Fill first 3 bytes witOPEN
INT 33
OR AL,AL
JNZ RET ; Not found
MOV [FCB+RR],0
MOV CX,512
MOV AH,RDBLK
INT 33
MOV SI,TPA
OUTLP:
LOD
NOTFND: DB "Source file not found$"
NOSPCE: DB "Insufficient disk space$"
FCBFIL: DB 11,"?"
DB 0
SPECDRV: DS 1
NUMRE SYSTEM ;Print space
MOV SI,LINBUF+2+9
MOV CX,3
CALL OUTCNT ;Print 3 chars (ext)
MOV DX,CRLF
MOV CL,PRINTBUF
CALL MOV AH,MAKE
INT 33
MOV DX,TPA
MOV AH,SETDMA
INT 33
MOV [FCB+RR],0
MOV [DSTFCB+RR],0
CPYBLK:
MOV DX,FCB
MOV CX,JZ RET
STOB
LOOP COPYNAM
NOMATCH:
XOR AL,AL
DEC SI
RET
FILLBUF:
LODB
MOV CL,AL
JCXZ RET
LODB
REP
STOB
h FF
INC AX ;AX = 0
SHR CX
JNC DOFILL
STOB ;Odd byte
DOFILL:
REP
STOW
MOV AX,CS
MOV DS,AX
MOV ES,AX
MOV SIB
CMP AL,1AH ;Is EOF?
JZ RET
MOV CL,OUTCH
MOV DL,AL
CALL SYSTEM
JP OUTLP
RET
CLEAR:
MOV DX,ERAMES
MOV CL,PC: DS 2
IDLEN: DS 1
ID: DS 8
COM: DB "COM"
DSTFCB: DS 36
LINBUF: DB 80H,1,13
DS 80H
FILIFO: DB 8," "
DB 0
DB 1SYSTEM ;Print new line
MOV CL,SRCHNXT
JP EACHFILE
OUTCNT:
LODB
PUSH CX
PUSH SI
MOV DL,AL
MOV CL,OUTCH
CALL SYS[NUMREC]
MOV AH,RDBLK
INT 33
JCXZ CPYDONE
MOV DX,DSTFCB
MOV AH,WRBLK
INT 33
OR AL,AL
JZ CPYBLK
MOV DX,NOSPCE
JP FILLBUF
DIR:
CMP B,[FCB+1]," "
JNZ HASNAME
MOV SI,FCBFIL
MOV DI,FCB+1
CALL FILLBUF ;Fill 11 bytes with "?"
H,FCBFIL
MOV DI,FCB+1
CALL FILLBUF
MOV DX,FCB
MOV CL,DELETE
CALL SYSTEM ;Delete all files
MOV CL,DSKRESET
JMP 5
RINTBUF
CALL SYSTEM ;Confirm erase
MOV CL,INCHAR
CALL SYSTEM
CMP AL,"Y"
JZ DOCLEAR
CMP AL,"y"
JZ DOCLEAR
RET
D2," ",4,0
DB 12," ",8,0
DB 0
COMTAB: DB 4,"DIR"
DW DIR
DB 7,"RENAME"
DW RENAME
DB 6,"ERASE"
DW ERASE
DB 7,"CRTEM
POP SI
POP CX
LOOP OUTCNT
RET
RENAME:
MOV CL,RENAM
MOV DX,FCB
JMP 5
ERASE:
MOV CL,DELETE
MOV DX,FCB
MOV AH,PRINTBUF
INT 33
CPYDONE:
MOV DX,DSTFCB
MOV AH,CLOSE
INT 33
RET
NOSRC:
MOV DX,NOTFND
MOV AH,PRINTBUF
INASNAME:
MOV DX,LINBUF+2+1
MOV CL,SETDMA
CALL SYSTEM
MOV CL,SRCHFRST
MOV DX,FCB
EACHFILE:
CALL SYSTEM
INC AL ;FF
COPY:
MOV SI,FCB+10H
MOV DI,DSTFCB
MOVB
CMP B,[SI]," " ;Has file name?
JNZ HASDSTNAM
MOV SI,FCB+1
HASDSTNAM:
MOOCLEAR:
MOV DL,[FCB]
OR DL,DL
JZ CLRDSK
DEC DL
MOV CL,SELDRV
CALL SYSTEM
CLRDSK:
MOV CL,GETFAT
CALL SYSTEM
MOEATE"
DW CREATE
DB 5,"TYPE"
DW TYPE
DB 6,"CLEAR"
DW CLEAR
DB 5,"COPY"
DW COPY
DB 0
TPA:

JMP 5
CREATE:
MOV CL,MAKE
MOV DX,FCB
JMP 5
TYPE:
MOV DX,TPA
MOV CL,SETDMA
CALL SYSTEM
MOV DX,FCB
MOV AH,T 33
RET
DS 40
STACK:
BADNAM: DB "Bad command or file name"
CRLF: DB 13,10,"$"
ERAMES: DB "Erase all files (Y/N)? $"= file not found
JZ RET
MOV SI,LINBUF+2+1
MOV CX,8
CALL OUTCNT ;Print 8 chars (name)
MOV CL,OUTCH
MOV DL," "
CALLVB
MOV CX,7
REP
MOVW
MOV DX,FCB
MOV AH,OPEN
INT 33
OR AL,AL
JNZ NOSRC
MOV DX,DSTFCB
MOV AH,DELETE
INT 33
繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞IN
JMP AUXOUT
JMP READ
JMP WRITE
JMP RETL ;Flush buffers
INIT:
MOV AX,CS
MOV DS,AX
MOV SS,AX
MOV SP,STACK
M: EQU DOUB1SIDE+DOUB2SIDE
WD1771: EQU CROMEMCO+SNGL1SIDE
IF WD1791
READCOM:EQU 80H
WRITECOM:EQU 0A0H
ENDIF
IF WD177
LOOP RDLP
OR AL,AL
RETL: RET L
WRITE:
CALL SEEK
WRTLP:
PUSH CX
CALL WRITESECT
POP CX
JC ERROR
INC DH
ADD co controllers.
; Select disk controller here
TARBELL:EQU 0
CROMEMCO:EQU 1
; For either disk controller, a custom drive
BADCOM: DB 13,10,"Bad or missing Command Interpreter",13,10,"$"
FCB: DB 1,"COMMAND COM"
DS 24
STATUS:
IN STAT
AND 繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞OV SI,INITTAB
CALL 0,DOSSEG
MOV DX,100H
MOV AH,26 ;Set DMA address
INT 21H
MOV BX,DS
MOV AX,CS
MOV DS,AX
MOV DX1
READCOM:EQU 88H
WRITECOM:EQU 0A8H
ENDIF
IF TARBELL
DONEBIT:EQU 80H
DISK: EQU 78H
ENDIF
IF CROMEMCO
DONEBIT:EQSI,128
LOOP WRTLP
OR AL,AL
RET L
ERROR:
SEG CS
MOV B,[DI],-1
RET L
SEEK:
; Inputs:
; AL = Drive number
; table may be defined
CUSTOM: EQU 0
; If Tarbell disk controller, select one-sided or two-sided drives
; and single or doublAL,DAV
RET L
AUXIN:
INP:
IN STAT
AND AL,DAV
JZ INP
IN DATA
AND AL,7FH
RET L
AUXOUT:
OUTP:
PUSH AX
OUTLP繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞,FCB
MOV AH,15
INT 21H
OR AL,AL
JNZ COMERR
MOV [FCB+33],0
MOV CX,200H
MOV AH,39 ;Load file
INT 21H
JCXZ COMERU 1
DISK: EQU 30H
ENDIF
DOSSEG: EQU 80H
ORG 0
PUT 100H
BASE: EQU 0F0H
STAT: EQU BASE+7
DAV: EQU 2
TBMT: EQU 1
BX = Disk transfer address in DS
; CX = Number of sectors to transfer
; DX = Logical record number of transfer
; Function:
;e density controller
DOUB1SIDE:EQU 0
DOUB2SIDE:EQU 0
SNGL1SIDE:EQU 0
; If Cromemco disk controller, select drive configura:
IN STAT
AND AL,TBMT
JZ OUTLP
POP AX
OUT DATA
RET L
PRINT:
PUSH AX
PRINLP:
IN PSTAT
AND AL,TBMT
JZ PRIN繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞R
CMP AL,1
JNZ COMERR
MOV DS,BX
MOV ES,BX
MOV SS,BX
MOV SP,40H
XOR AX,AX
PUSH AX
MOV DX,80H
MOV AH,26
INT
DATA: EQU BASE+6
PSTAT: EQU BASE+0DH
PDATA: EQU BASE+0CH
JMP INIT
JMP STATUS
JMP INP
JMP OUTP
JMP PRINT
JMP AUX Seeks to proper track.
; Outputs:
; AH = Drive select byte
; DL = Track number
; DH = Sector number
; SI = Disk transfer ation
SMALLCRO:EQU 0 ;3 small drives
COMBCRO:EQU 1 ;2 large drives and 1 small one
LARGECRO:EQU 0 ;4 large drives
WD1791LP
POP AX
OUT PDATA
RET L
READ:
CALL SEEK
RDLP:
PUSH CX
CALL READSECT
POP CX
JC ERROR
INC DH
ADD SI,128
; I/O System for 86-DOS.
; Assumes a CPU Support card at F0 hex for character I/O,
; with disk drivers for Tarbell or Cromem21H
PUSH BX
MOV AX,100H
PUSH AX
RET L
COMERR:
MOV DX,BADCOM
MOV AH,9 ;Print string
INT 21H
EI
STALL: JP STALLddress in DS
; DI = pointer to drive's track counter in CS
; CX unchanged.
MOV SI,BX ; Save transfer address
CBW
MOV n on auto-wait
XCHG AL,AH
ENDIF
NOT AL
AND AL,20H ;Check head load status
JZ CHKDRV
MOV AL,4
CHKDRV:
; Turn on IF CROMEMCO
TEST AH,10H ;Check for small disk
JNZ CHKSTP
CMP DH,18 ;Only 18 sectors/track on small ones
JA STEP
CHKSTEC BL
JNZ TRYHOM
RET
MOVHEAD:
IF CROMEMCO
TEST AH,10H ;Check 8" (PerSci) bit
JNZ FASTSK
ENDIF
DCOM:
OUT DISent into track table
ADD BX,TRKTAB ;BX now points to track counter for this drive
MOV DI,BX
MOV AL,DL
SEG CS
XCHG AL,[ET
MOV BL,10
WRTAGN:
OR AL,WRITECOM
OUT DISK
PUSH SI
WRLOOP:
IN DISK+4
TEST AL,DONEBIT
IF TARBELL
JZ WRDONEBX,AX ; Prepare to index on drive number
SEG CS
MOV AL,[BX+DRVTAB]
OUT DISK+4 ; Select drive
IF CROMEMCO
OR AL,80H15ms head load delay if selecting a different drive
SEG CS
CMP AH,[CURDRV]
SEG CS
MOV [CURDRV],AH
JZ RET
OR AL,4
RP:
ENDIF
CMP DH,26 ;Check for overflow onto next track
JBE PUTSEC
STEP:
INC DL
MOV DH,1
MOV AL,58H ;Step in witK
MOV AL,50
DELAY:
DEC AL
JNZ DELAY ;Delay 100 microseconds
GETSTAT:
IN DISK+4
TEST AL,DONEBIT
IF TARBELL
JNZDI] ;Xchange current track with desired track
OUT DISK+1 ;Inform controller chip of current track
CMP AL,DL
JZ ONTRK
M
ENDIF
IF CROMEMCO
JNZ WRDONE
ENDIF
LODB
OUT DISK+3
LOOP WRLOOP
WRDONE:
POP SI
CALL GETSTAT
AND AL,09CH ;Set auto-wait bit
ENDIF
MOV AH,AL ;Save for later
XCHG AX,DX
MOV DL,26 ;26 sectors per track
IF CROMEMCO
TEET
READSECT:
CALL SETUP
JC RET
MOV BL,10
RDAGN:
OR AL,READCOM
OUT DISK
PUSH SI
RLOOP:
IN DISK+4
TEST AL,DONh update, no verify
CALL DCOM
SEG CS
INC B,[DI] ;Update track counter
PUTSEC:
MOV AL,DH
OUT DISK+2
MOV CX,80H
GETSTAT
ENDIF
IF CROMEMCO
JZ GETSTAT
ENDIF
IN DISK
RET
IF CROMEMCO
RESTORE:
MOV AL,0C4H ;READ ADDRESS cOV BH,3 ;Seek retry count
CMP AL,-1 ;Head position known?
JNZ NOHOME ;If not, home head
TRYSK:
CALL HOME
NOHOME:
MO
JZ RET
MOV AL,0
DEC BL
JNZ WRTAGN
STC
RET
HOME:
IF CROMEMCO
TEST AH,10H ;Check 8" (PerSci) bit
JNZ RESTORST DH,10H ;Check if small disk
JNZ BIGONE
MOV DL,18 ;18 sectors on small disk track
BIGONE:
ENDIF
DIV AL,DL ;CompuEBIT
IF TARBELL
JZ RDONE
ENDIF
IF CROMEMCO
JNZ RDONE
ENDIF
IN DISK+3
MOV [SI],AL
INC SI
LOOP RLOOP
RDIF TARBELL
IN DISK ;Get head load bit
ENDIF
IF CROMEMCO
IN DISK+4 ;Get head load bit
XCHG AL,AH
OUT DISK+4 ;Turommand to keep head loaded
OUT DISK
MOV AL,77H
OUT 4
CHKRES:
IN 4
AND AL,40H
JZ RESDONE
IN DISK+4
TEST AL,DONEBV AL,DL
OUT DISK+3
MOV AL,1CH
CALL MOVHEAD
AND AL,98H
JZ ONTRK
DEC BH
JNZ TRYSK
STC
ONTRK:
RET
SETUP:
E
ENDIF
MOV BL,3
TRYHOM:
MOV AL,0CH
CALL DCOM
AND AL,98H
JZ RET
MOV AL,58H ;Step in with update
CALL DCOM
Dte track and sector
XCHG AX,DX
INC DH ;First sector is 1, not zero
SEG CS
MOV BL,[BX+TRKPT] ;Get this drive's displacemONE:
POP SI
CALL GETSTAT
AND AL,9CH
JZ RET
MOV AL,0
DEC BL
JNZ RDAGN
STC
RET
WRITESECT:
CALL SETUP
JC RIT
JZ CHKRES
IN DISK
JP RESTORE ;Reload head
RESDONE:
MOV AL,7FH
OUT 4
CALL GETSTAT
MOV AL,0
OUT DISK+1 ;TellLFAT
FAT2: DS LFAT
FAT3: DS LFAT
ENDIF
IF COMBCRO
; Table for two large drives and one small one
DRVTAB: DB 31H,32H,24mco drive select byte is derived as follows:
; Bit 7 = 0
; Bit 6 = X (unassigned)
; Bit 5 = 1 (motor on)
; Bit 4 = 0 for 5",繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞DW 330
IF DOUB1SIDE
DRVTAB: DB 0,10H,20H,30H
TRKPT: DB 0,1,2,3
TRKTAB: DB -1,-1,-1,-1
ENDIF
IF DOUB2SIDE
DRVTAB: DKPT: DB 0,1
TRKTAB: DB -1,-1
INITTAB:DB 2
DW LDRIVE
DW FAT0
DW LDRIVE
DW FAT1
ORG 0
FAT0: DS LFAT
FAT1: DS LFA 1771 we're now on track 0
RET
FASTSK:
MOV AL,6FH
OUT 4
MOV AL,18H
CALL DCOM
SKWAIT:
IN 4
TEST AL,40H
JNZ SKH
TRKPT: DB 0,0,1
TRKTAB: DB -1,-1
INITTAB:DB 3 ;Number of drives
DW LDRIVE
DW FAT0
DW LDRIVE
DW FAT1
DW SDRIVE
D 1 for 8" drives
; Bit 3 = 1 for drive 3
; Bit 2 = 1 for drive 2
; Bit 1 = 1 for drive 1
; Bit 0 = 1 for drive 0
IF LARG繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞B 0,40H,10H,50H
TRKPT: DB 0,0,1,1
TRKTAB: DB -1,-1
ENDIF
IF SNGL1SIDE
DRVTAB: DB 0F2H,0E2H,0D2H,0C0H
TRKPT: DB 0,1,2,3T
ENDIF
WAIT
MOV AL,7FH
OUT 4
MOV AL,0
RET
ENDIF
DS 20H
STACK:
LFAT: EQU 300H
SFAT: EQU 200H
CURDRV: DS 1
LDRIVW FAT2
ORG 0
FAT0: DS LFAT
FAT1: DS LFAT
FAT2: DS SFAT
ENDIF
IF SMALLCRO
; Table for 3 small drives
DRVTAB: DB 21ECRO
; Table for four large drives
DRVTAB: DB 31H,32H,34H,38H
TRKPT: DB 0,0,1,1
TRKTAB: DB -1,-1
INITTAB:DB 4 ;Number of drFCB EQU 5CH
RENAM EQU 23
OPEN EQU 15
CLOSE EQU 16
MAKE EQU 22
DELFIL EQU 19
RDBLK EQU 39
WRBLK EQU 40
SETDMA EQU 26
PRI
TRKTAB: DB -1,-1,-1,-1
ENDIF
IF TARBELL
INITTAB:DB 4 ;Number of drives
DW LDRIVE
DW FAT0
DW LDRIVE
DW FAT1
DW繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞E:
DB 1 ;Records/sector
DB 4 ;Records/cluster
DW 52 ;Reserved records
DB 6 ;FAT size (records)
DB 2 ;Number of FATs
H,22H,24H
TRKPT: DB 0,1,2
TRKTAB: DB -1,-1,-1
INITTAB:DB 3
DW SDRIVE
DW FAT0
DW SDRIVE
DW FAT1
DW SDRIVE
DW FAT2
ives
DW LDRIVE
DW FAT0
DW LDRIVE
DW FAT1
DW LDRIVE
DW FAT2
DW LDRIVE
DW FAT3
ORG 0
FAT0: DS LFAT
FAT1: DS NTBUF EQU 9
OUTCH EQU 2
INBUF EQU 10
RR EQU 33
PROMPT EQU "*"
ORG 100H
PUT 100H
MOV SP,STACK
MOV DX,BREAK
MO LDRIVE
DW FAT2
DW LDRIVE
DW FAT3
ORG 0
FAT0: DS LFAT
FAT1: DS LFAT
FAT2: DS LFAT
FAT3: DS LFAT
ENDIF
; Crome繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞DB 8 ;Number of directory records
DW 482 ;Number of clusters on drive
SDRIVE:
DB 1
DB 2
DW 54
DB 4
DB 2
DB 8
ORG 0
FAT0: DS SFAT
FAT1: DS SFAT
FAT2: DS SFAT
ENDIF
IF CUSTOM
; Table for 2 large drives
DRVTAB: DB 31H,32H
TRV AX,2523H
INT 33
MOV SI,BAK
MOV DI,FCB+9
MOV CX,3
;File must not have .BAK extension
REPE
CMPB
JZ NOTBAK
;OpeOV BX,CX
SHL BX
CALL [BX+TABLE]
JMP COMMAND
SKIP:
LODB
SKIP1:
CMP AL," "
JZ SKIP
RET
COMERR:
MOV DX,BADCO B,[EDITBUF],255
MOV [POINTER],START
MOV [CURRENT],1
COMMAND:
MOV SP,STACK
MOV AL,PROMPT
CALL OUT
MOV DX,COMBUF
MOV DI,START
CMP BX,DX
JZ RET
FINDIT:
MOV CX,[ENDTXT]
SUB CX,DI
MOV AL,10
OR AL,AL ;Clear zero flag
FINLIN:
JTOBIG
JMP ERROR
NOTEOF:
MOV DX,NOEOF
JMP ERROR
SETUP:
MOV DX,START
MOV AH,SETDMA
INT 33
MOV CX,[6]
SUB CX,80H
er of the next two tables. They are
; linked and chnges should be be to both.
TABLE DW NOCOM ;No command--edit line
Dn input file
MOV AH,OPEN
MOV DX,FCB
INT 33
MOV [HAVEOF],AL
OR AL,AL
JZ HAVFIL
MOV DX,NEWFIL
MOV AH,PRINTBUF
INM
MOV AH,PRINTBUF
INT 33
JP COMMAND
GETNUM:
CALL SKIP
CMP AL,"."
JZ CURLIN
CMP AL,"#"
JZ MAXLIN
MOV DX,0
MOV AH,INBUF
INT 33
MOV AL,10
CALL OUT
MOV [PARAM2],0
MOV B,[QFLG],0
MOV SI,2+COMBUF
CALL GETNUM
MOV [PARAM1],DCXZ RET
REPNE
SCAB
INC DX
CMP BX,DX
JNZ FINLIN
RET
SHOWNUM:
; Inputs:
; BX = Line number to be displayed
;
MOV [LAST],CX
MOV DI,START-1
TEST B,[HAVEOF],-1
JNZ SAVEND
CALL NUMRECS
MOV [FCB+RR],0
MOV DX,FCB
MOV AH,RDBLK
W ENDED
DW INSERT
DW LIST
DW DELETE
DW COMERR
DW COMERR
FINDLIN:
; Inputs
; BX = Line number to be located in bT 33
HAVFIL:
MOV SI,FCB
MOV DI,FCB2
MOV CX,9
REP
MOVB
MOV SI,BAK
MOVW
MOVB
MOV AH,DELFIL
MOV DX,FCB2
INT
NUMLP:
CMP AL,"0"
JB RET
CMP AL,"9"
JA RET
SUB AL,"0"
MOV BX,DX
SHL DX
SHL DX
ADD DX,BX
SHL DX
CBW
ADD X
CALL SKIP1
CMP AL,","
JNZ CHKNXT
INC SI
CHKNXT:
DEC SI
CALL GETNUM
MOV [PARAM2],DX
CALL SKIP1
CMP AL,"?"
Function:
; Displays line number on terminal in 8-character
; format, suppressing leading zeros.
; AX, CX, DX destroyed. No INT 33
CMP AL,2
JZ TOOBIG
JCXZ SAVEND
ROR CX
XCHG CL,CH
ADD DI,CX ;Point to last byte
DOWN
MOV AL,1AH
REPNE
uffer (0 means last line)
; Outputs:
; DX = Actual line found
; DI = Pointer to start of line DX
; Zero set if BX = DX
; AL33
MOV AL,"$"
MOV DI,FCB2+9
STOB
STOB
STOB
MOV AH,DELFIL
INT 33
;Create .$$$ file to make sure directory has rooDX,AX
LODB
JP NUMLP
CURLIN:
MOV DX,[CURRENT]
LODB
RET
MAXLIN:
MOV DX,-1
LODB
RET
COMTAB DB "SFDLIE",13
JNZ DISPATCH
MOV [QFLG],AL
CALL SKIP
DISPATCH:
AND AL,5FH
MOV DI,COMTAB
MOV CX,NUMCOM
REPNE
SCAB
JNZ COMERR
Mother registers affected.
PUSH BX
MOV AL," "
CALL OUT
CALL CONV10
MOV AL,":"
CALL OUT
MOV AL," "
CALL OUT
PO
SCAB
JNZ NOTEOF
REPE
SCAB
INC DI
SAVEND:
CLD
INC DI
MOV B,[DI],1AH
MOV [ENDTXT],DI
MOV B,[COMBUF],128
MOV,CX destroyed. No other registers affected.
MOV DX,[CURRENT]
MOV DI,[POINTER]
CMP BX,DX
JZ RET
JA FINDIT
MOV DX,1
m
MOV AH,MAKE
INT 33
OR AL,AL
JZ SETUP
MOV DX,NODIR
JMP ERROR
NOTBAK:
MOV DX,NOBAK
JMP ERROR
TOOBIG:
MOV DX,
NUMCOM EQU $-COMTAB
;-----------------------------------------------------------------------;
; Carefull changing the ordP BX
RET
CONV10:
;Inputs:
; BX = Binary number to be displayed
; Function:
; Ouputs binary number. Five digits with
LODB
STOB
INC DL
CMP AL,13
LOOPNZ LOADLP
MOV [EDITBUF+1],DL
MOV [OLDLEN],DL
MOV SI,[POINTER]
CALL DISPONE
CAX
CALL SHOWNUM
POP CX
OUTLN:
LODB
CALL OUT
CMP AL,10
LOOPNZ OUTLN
JCXZ RET
DEC DI
JZ RET
CMP BX,BP
LAHF
I
MOV BX,[PARAM2]
OR BX,BX
JNZ DELFIN2
MOV BX,DX
DELFIN2:
INC BX
CALL FINDLIN
MOV DX,DI
POP DI
SUB DX,DI
XO SUB BX,10
JA CHKP2
MOV BX,1
CHKP2:
CALL FINDLIN
JNZ RET
MOV SI,DI
MOV DI,[PARAM2]
INC DI
SUB DI,BX
JA DISPLActed.
CMP CX,DX
JZ COPYIN
PUSH SI
PUSH DI
PUSH CX
MOV SI,DI
ADD SI,DX
ADD DI,CX
MOV AX,[ENDTXT]
SUB AX,DX
leading
; zero suppression. Zero prints 5 blanks.
XOR AX,AX
MOV DL,AL
MOV CX,16
CONV:
SHL BX
ADC AL,AL
DAA
XCLL SHOWNUM
MOV AH,INBUF ;Get input buffer
MOV DX,EDITBUF
INT 33
MOV AL,10
CALL OUT
MOV CL,[EDITBUF+1]
MOV CH,0
J INC BX
SAHF
JZ OUTLF
CMP BX,BP
JNZ DISPLN
OUTLF:
MOV AL,10
CALL OUT
JP DISPLN
RET: RET
NOCOM:
MOV BX,[PAR CX,CX
JP REPLACE
GETTEXT:
; Inputs:
; SI points into command line buffer
; DI points to result buffer
; Function:Y
MOV DI,21
JP DISPLAY
DISPONE:
MOV DI,1
DISPLAY:
; Inputs:
; BX = Line number
; SI = Pointer to text buffer
ADD AX,CX
CMP AX,[LAST]
JAE MEMERR
XCHG AX,[ENDTXT]
MOV CX,AX
SUB CX,SI
CMP SI,DI
JA DOMOV
ADD SI,CX
ADD DI,HG AL,AH
ADC AL,AL
DAA
XCHG AL,AH
ADC DL,DL
LOOP CONV
MOV BL,"0"-" "
XCHG AX,DX
CALL LDIG
MOV AL,DH
CALL DIGCXZ RET
MOV DL,[OLDLEN]
MOV DH,0
MOV SI,2+EDITBUF
MOV DI,[POINTER]
REPLACE:
; Inputs:
; CX = Length of new text
RAM1]
OR BX,BX
JNZ HAVLIN
MOV BX,[CURRENT]
INC BX ;Default is current line plus one
HAVLIN:
CALL FINDLIN
MOV SI,DI
; Moves [SI] to [DI] until ctrl-Z (1AH) or
; RETURN (0DH) is found. Termination char not moved.
; Outputs:
; AL = Terminati
; DI = No. of lines
; Function:
; Ouputs specified no. of line to terminal, each
; with leading line number.
; Outputs:
; CX
STD
DOMOV:
INC CX
REP
MOVB
CLD
POP CX
POP DI
POP SI
COPYIN:
REP
MOVB
RET
DELETE:
MOV BX,[PARAMITS
MOV AL,DL
DIGITS:
MOV DH,AL
SHR AL
SHR AL
SHR AL
SHR AL
CALL LDIG
MOV AL,DH
LDIG:
AND AL,0FH
JZ ZERDIG; DX = Length of original text
; SI = Pointer to new text
; DI = Pointer to old text in buffer
; Function:
; New text replac
MOV [CURRENT],DX
MOV [POINTER],SI
JNZ RET
CMP SI,[ENDTXT]
JZ RET
MOV DI,2+EDITBUF
MOV CX,254
MOV DL,-1
LOADLP:
on character
; CX = No of characters moved.
; SI points one past termination character
; DI points to next free location
BX = Last line output.
; All registers destroyed.
MOV CX,[ENDTXT]
SUB CX,SI
JZ RET
MOV BP,[CURRENT]
DISPLN:
PUSH C1]
OR BX,BX
JNZ DELFIN1
MOV BX,[CURRENT]
DELFIN1:
CALL FINDLIN
JNZ RET
MOV [CURRENT],BX
MOV [POINTER],DI
PUSH D
MOV BL,0
ZERDIG:
ADD AL,"0"
SUB AL,BL
JMP OUT
LIST:
MOV BX,[PARAM1]
OR BX,BX
JNZ CHKP2
MOV BX,[CURRENT]
es old text in buffer and buffer
; size is adjusted. CX or DX may be zero.
; CX, SI, DI all destroyed. No other registers affeXOR CX,CX
GETIT:
LODB
CMP AL,1AH
JZ RET
CMP AL,0DH
JZ RET
STOB
INC CX
JP GETIT
MEMERR:
MOV DX,MEMFUL
MET
BAK: DB "BAK"
NOBAK: DB "Cannot edit .BAK file--rename file$"
NODIR: DB "No room in directory for file$"
TOBIG: DB "F
INT 33
MOV SI,FCB
LEA DI,[SI+16]
MOV DX,SI
MOV CX,9
REP
MOVB
MOV SI,BAK
MOVW
MOVB
;Rename original file .BAnput buffer as empty
READHEX:
CALL GETCH
CMP AL,":" ;Search for : to start line
JNZ READHEX
CALL GETBYT ;Get byte cou
ADD DX,CX
INC DX
CMP DX,BP ;Will it fit?
JNC MEMERR
REP
MOVB
MOVB
MOV AL,10
STOB
INC BX
JP INLP
ENDINS:
; HEX2BIN
; Converts Intel hex format files to straight binary
FCB: EQU 5CH
READ: EQU 20
SETDMA: EQU 26
OPEN: EQU 15
CLOOV AH,PRINTBUF
INT 33
JMP COMMAND
INSERT:
MOV BX,[PARAM1]
OR BX,BX
JNZ INS
MOV BX,[CURRENT]
INC BX
INS:
CAile too big to fit into memory$"
NOEOF: DB "No end-of-file mark found in file$"
DSKFUL: DB "Disk full--file write not completeK
MOV AH,RENAM
INT 33
MOV SI,FCB
MOV DI,FCB2+16
MOV CX,6
REP
MOVW
;Rename .$$$ file to original name
MOV DX,FCBnt
MOV CL,AL
MOV CH,0
JCXZ DONE
CALL GETBYT ;Get high byte of load address
MOV BH,AL
CALL GETBYT ;Get low byte of MOV [POINTER],DI
MOV [CURRENT],BX
MOV SI,BP
INC SI
MOV CX,[LAST]
SUB CX,BP
REP
MOVB
DEC DI
MOV [ENDTXT],DI
SE: EQU 16
CREATE: EQU 22
DELETE: EQU 19
BLKWRT: EQU 40
BUFFER: EQU 80H
BUFSIZ: EQU 128
ORG 100H
PUT 100H
HEX2BIN:LL FINDLIN
MOV CX,[ENDTXT] ;Get End-of-text marker
MOV SI,CX
SUB CX,DI ;Calculate number of bytes to copy
INC CX
MOd$"
MEMFUL: DB 13,10,"Memory full",13,10,"$"
BADCOM: DB "Entry error",13,10,"$"
NEWFIL: DB "New file",13,10,"$"
FCB2: DS 36
2
INT 33
JMP 0
WRTERR:
MOV DX,DSKFUL
ERROR:
MOV AH,PRINTBUF
INT 33
JMP 0
NUMRECS:
SUB CX,START
AND CL,8load address
MOV BL,AL
ADD BX,START-100H ;Add in offset
MOV DI,BX
CALL GETBYT ;Throw away type byte
READLN:
CMP DI,[RET
ENDED:
;Write text out to .$$$ file
MOV DI,[ENDTXT]
MOV CX,128
MOV AL,1AH
REP
STOB
MOV CX,[ENDTXT]
CALL NU
MOV DI,FCB+9
CMP B,[DI]," "
JNZ HAVEXT
MOV SI,HEX
MOVB
MOVW
HAVEXT:
;Get load offset (default is -100H)
MOV AH,V DI,[LAST]
DOWN
REP
MOVB
XCHG SI,DI
UP
INC DI
MOV BP,SI
MOV BX,DX
INLP:
CALL SHOWNUM
MOV DX,EDITBUF
MOV
PARAM1: DS 2
PARAM2: DS 2
QFLG: DS 1
HAVEOF: DS 1
OLDLEN: DS 1
CURRENT: DS 2
POINTER: DS 2
LAST: DS 2
ENDTXT: DS 2
COM0H
ROL CX
XCHG CL,CH
RET
OUT:
PUSH DX
XCHG AX,DX
MOV AH,OUTCH
INT 33
XCHG AX,DX
POP DX
RET
BREAK:
IR6]
JAE ADERR
CMP DI,START
JB ADERR
CALL GETBYT ;Get data byte
STOB
LOOP READLN
CMP DI,BP ;Check if this is the lMRECS
INC CX
MOV [FCB2+RR],0
MOV DX,FCB2
MOV AH,WRBLK
INT 33
OR AL,AL
JNZ WRTERR
;Close .$$$ file
MOV AH,CLOSE
OPEN
MOV DX,FCB
INT 33
OR AL,AL
JNZ NOFIL
MOV B,[FCB+32],0
MOV AH,READ
MOV BP,START
MOV SI,BUFFER+BUFSIZ ;Flag iAH,INBUF
INT 33
MOV AL,10
CALL OUT
MOV SI,EDITBUF+2
CMP B,[SI],1AH
JZ ENDINS
MOV CL,[SI-1]
MOV CH,0
MOV DX,SI
BUF: DS 2+128
EDITBUF: DS 2+255
DS 40
ALIGN
STACK:
START:
argest address so far
JBE READHEX
MOV BP,DI ;Save new largest
JP READHEX
NOFIL:
MOV DX,NOFILE
QUIT:
MOV AH,9
IN繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞: DB "Disk directory full$"
START:
opy file name
MOV AL,[DSTFCB]
OR AL,AL
JNZ DSTDRV
MOV CL,GETDRV
CALL SYSTEM ;Use default drive
INC AX
DSTDRV:
V DX,FCB
MOV AH,DELETE
INT 33
MOV AH,CREATE
INT 33
OR AL,AL
JNZ NOROOM
MOV W,[FCB+33],0
MOV DX,START
MOV AH,SE 0,0,0,0
INVSRC:
MOV DX,BADSRC
JMP EXIT
NONAME:
MOV DX,BADFN
JMP EXIT
RDCPM:
MOV SP,100H
CMP B,[FCB+1]," "
T 33
INT 32
ADERR:
MOV DX,ADDR
JMP ERROR
GETCH:
CMP SI,BUFFER+BUFSIZ
JNZ NOREAD
INT 33
OR AL,AL
JNZ ERROR
繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞DEC AX
CMP AL,[DRIVE]
JZ BADPARM
MOV CL,DELETE
MOV DX,DSTFCB
CALL SYSTEM
MOV CL,MAKE
MOV DX,DSTFCB
CALL SYSTEM
TDMA
INT 33
MOV CX,BP
SUB CX,START-7FH
AND CL,80H
JCXZ EXIT
ROL CX
XCHG CL,CH
MOV AH,BLKWRT
MOV DX,FCB
INT 3
JZ NONAME
XOR AL,AL
XCHG AL,[FCB]
OR AL,AL
JNZ HASDRV
MOV CL,GETDRV
CALL SYSTEM
INC AX
HASDRV:
DEC AX
MOV
MOV SI,BUFFER
NOREAD:
LODB
CMP AL,1AH
JZ DONE
RET
GETBYT:
CALL HEXDIG
MOV BL,AL
CALL HEXDIG
SHL BL
SHL B繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞 MOV CL,SETDMA
MOV DX,SECBUF
CALL SYSTEM
BEGDIR:
XOR AX,AX
MOV BX,[BP+NUMENT]
READDIR:
MOV DI,DIRBUF
PUSH AX
3
MOV AH,CLOSE
INT 33
EXIT:
INT 32
NOROOM:
MOV DX,DIRFUL
JMP QUIT
HEX: DB "HEX"
COM: DB "COM"
ERRMES: DB "Err [DRIVE],AL
CMP AL,15
JA INVSRC ;Invalid drive number
CBW
MOV BX,AX
SHL BX
MOV BP,[BX+CPMTAB]
OR BP,BP
JZ INVSRL
SHL BL
SHL BL
OR AL,BL
RET
HEXDIG:
CALL GETCH
SUB AL,"0"
JC ERROR
CMP AL,9
JBE RET
SUB AL,"A"-"0"-10
FCB EQU 5CH
FCB2 EQU 6CH
OPEN EQU 15
CLOSE EQU 16
MAKE EQU 22
DELETE EQU 19
SEQWRT EQU 21
SETDMA EQU 26
GETDRV EQU 25
P繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞 PUSH BX
CALL READSEC
POP BX
POP AX
MOV SI,DIRBUF
ENUMDIR:
MOV DI,FCB
MOV CX,13
REPE
CMPB
JZ RDENTRY
ADD or in HEX file--conversion aborted$"
NOFILE: DB "File not found$"
ADDR: DB "Address out of range--conversion aborted$"
DIRFULC
MOV SI,FCB2
MOV DI,DSTFCB
MOVB
CMP B,[FCB2+1]," "
JNZ HASDST
MOV SI,FCB+1
HASDST:
MOV CX,11
REP
MOVB ;CJC ERROR
CMP AL,15
JBE RET
ERROR:
MOV DX,ERRMES
MOV AH,9
INT 33
DONE:
MOV DI,FCB+9
MOV SI,COM
MOVB
MOVW
MORINTBUF EQU 9
SYSTEM EQU 5
ORG 100H
PUT 100H
JMP RDCPM
CPMTAB:
DW IBM,IBM,IBM,IBM
DW 0,0,0,0
DW 0,0,0,0
DWSI,CX
ADD SI,19 ;Point to next entry
DEC BX
JS DONE
CMP SI,DIRBUF+128
JB ENUMDIR
INC AX
JP READDIR
BADPARM:
e name",13,10,"$"
DRIVE: DS 1
DSTFCB: DS 32
DB 0
DIRBUF: DS 128
SECBUF: DS 128
SPT EQU 0
BLKSFT EQU 2
BLKMSK EQU 3
Eor number
READABS:
MOV CX,1
MOV BX,DI
MOV AL,[DRIVE]
PUSH BP
INT 37
POP AX
POP BP
JNC RDDONE
MOV DX,DSKERR
FCB EQU 5CH
ORG 100H
PUT 100H
JMP START
SECS: DW 52 ;Patch for different configs
START:
MOV AL,[FCB]
OR AL,AC
POP SI
POP CX
LOOP RDNXTAL
INC B,[FCB+12] ;Increment extent counter
JMP BEGDIR ;Scan from beginning of directory
MOD6:
DB 0,6,12,18,24
DB 4,10,16,22
DB 2,8,14,20
DB 1,7,13,19,25
DB 5,11,17,23
DB 3,9,15,21
CPMTAB2:
DW 0,0,0MOV DX,SAMDSK
JMP EXIT
RDENTRY:
ADD SI,3 ;Point to AL array
MOV CX,16 ;16 AL bytes per entry
RDNXTAL:
LODB
MOVXTMSK EQU 4
DSISIZ EQU 5
NUMENT EQU 7
ALBMP0 EQU 9
ALBMP1 EQU 10
DIRCKS EQU 11
RESTRK EQU 13
XLTTBL EQU 15
;Below is t
EXIT:
MOV CL,PRINTBUF
CALL SYSTEM
JMP 0
;Translation table made up of WORDs
BIGTRK:
MOV BX,CX
SHL BX
ADD BX,[L
JZ BADDRV
DEC AL
JZ BADDRV
MOV [FCB],AL
MOV CX,[SECS]
MOV DX,0
MOV BX,END
MOV AL,0
INT 37
JC RDERR
POPF
DONE:
MOV CL,CLOSE
MOV DX,DSTFCB
CALL SYSTEM
JMP 0
;Read allocation block
READSEC:
XOR DX,DX
MOV BX,[BP+SPT]
,0
DW 0,0,0,0
DW 0,0,0,0
DW 0,0,0,0
 AH,0
TEST B,[BP+DSISIZ+1],0FFH
JZ SMALDSK
MOV AH,[SI] ;Big disk, use words instead
INC SI
DEC CX
SMALDSK:
OR AXhe definition for standard single-density 8" drives
IBM:
DW 26 ;Sectors per track
DB 3 ;Block shift
DB 7 ;Block mask
BP+XLTTBL]
ADD DX,[BX]
JP READABS
RDDONE:
RET
DSKERR: DB 13,10,"HARD DISK ERROR",13,10,"$"
SAMDSK: DB 13,10,"Source
MOV CX,[SECS]
MOV DX,0
MOV BX,END
MOV AL,[FCB]
MOV AH,1
INT 38
JC WRERR
MOV DX,SYSOK
JP QUIT
RDERR:
MOV DDIV AX,BX
ADD AX,[BP+RESTRK]
MOV CX,DX
MUL AX,BX ;Tracks in sectors
MOV DX,AX
OR BH,BH ;Check for >255 sectors per t繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞,AX
JZ DONE
PUSH CX
MOV CH,0
PUSH SI
MOV CL,[BP+BLKSFT]
SHL AX,CL
RDALOC:
PUSH AX
OR AL,CH
PUSH CX
MOV DIDB 0 ;Extent mask
DW 242 ;Disk size - 1
DW 63 ;Directory entries - 1
DB 0C0H ;Directory allocation bitmap 0
DB 0 ;Direct and destination drives must not be the same",13,10,"$"
BADSRC: DB 13,10,"Bad source drive",13,10,"$"
BADFN: DB 13,10,"Bad filX,ERREAD
QUIT:
MOV AH,9
INT 33
INT 32
WRERR:
MOV DX,ERWRIT
JP QUIT
BADDRV:
MOV DX,DRVBAD
JP QUIT
SYSOKrack
JNZ BIGTRK ;Use words instead of bytes for xlat table
MOV AX,CX
MOV BX,[BP+XLTTBL]
XLAT
ADD DX,AX ;Logical sect繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞,SECBUF
CALL READSEC
MOV CL,SEQWRT
MOV DX,DSTFCB
CALL SYSTEM
POP CX
POP AX
INC CH
CMP CH,[BP+BLKMSK]
JBE RDALOory allocation bitmap 1
DW 16 ;Directory check vector size
DW 2 ;Tracks to skip
DW MOD6 ;Modulo-6 sector translate table
: DB "System transfered$"
ERREAD: DB "Disk read error$"
ERWRIT: DB "Disk write error$"
DRVBAD: DB "Bad drive specification"
MOV B,[BX],0
CALL FINDOP
ENLIN:
MOV SP,STACK
MOV AL,[CHAR]
CMP AL,';'
JNZ NOCOM
MOV AL,9
CALL PUTCH
MOV AL,'V AL,'M'
MOV [PUTFCB+11],AL
MOV DX,FCB
MOV CL,OPEN
CALL SYSTEM
INC AL
MOV DX,NOFILE
JZ ABORTJ
MOV DX,PUTFCB
MOPUSH DX
PUSH CX
MOV BX,[GETPT] ; Get buffer pointer.
CMP BX,GETBUF+80H ; Past end-of-buffer?
JNZ GETIT ; Jump if not.
ile
EOL: EQU 0DH
FCB: EQU 5CH
SYSTEM: EQU 5
OPEN: EQU 15
CLOSE: EQU 16
SETDMA: EQU 26
CREATE: EQU 22
DELETE: EQU 19
REAH
DAA
ADC AL,40H
DAA
PUTCH:
PUSH BX
PUSH DX
PUSH CX
LAHF
XCHG AH,AL
PUSH AX
XCHG AH,AL
AND AL,7FH
MOV B
END:
;'
NOCOM:
CALL PUTCH
PUTLIN:
CMP AL,EOF
JZ END
CALL GETCH
CALL PUTCH
CMP AL,10
JNZ PUTLIN
JP TRANLN
END:
MOV CL,DELETE
CALL SYSTEM
MOV DX,PUTFCB
MOV CL,CREATE
CALL SYSTEM
INC AL
MOV DX,NOROOM
ABORTJ:
JZ ABORT
MOV DX,PU MOV DX,GETBUF ; Set `DMA address'.
MOV CL,SETDMA
CALL SYSTEM
MOV DX,FCB ; Read the next record from source file.
MOV CD: EQU 20
WRITE: EQU 21
PRNBUF: EQU 9
MOV SP,STACK
MOV DX,HEADER
MOV CL,9
CALL SYSTEM
MOV BX,FCB+12
XOR AL,AL
MOX,[PUTPT]
MOV [BX],AL
LAHF
INC BX
SAHF
MOV [PUTPT],BX
CMP BX,PUTBUF+80H
JNZ POPRET
MOV DX,PUTBUF
MOV [PUTPT],D繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞V CH,127
MOV AL,1AH
FILL:
CALL PUTCH
DEC CH
JNZ FILL
MOV DX,PUTFCB
MOV CL,CLOSE
CALL SYSTEM
MOV DX,ENDMES
ABORTFCB
MOV CL,OPEN
CALL SYSTEM
MOV BX,PUTBUF
MOV [PUTPT],BX
MOV BX,GETBUF+80H
MOV [GETPT],BX
TRANLN:
XOR AL,AL
MOL,READ
CALL SYSTEM
OR AL,AL ; Entire record read OK?
MOV AL,EOF ; Force end-of-file character in case
JNZ TESEND ; tV CH,4
CLRFCB:
MOV [BX],AL
INC BX
DEC CH
JNZ CLRFCB
MOV [FCB+32],AL
MOV BX,FCB
MOV DX,PUTFCB
MOV CX,16
UP
MX
MOV CL,SETDMA
CALL SYSTEM
MOV DX,PUTFCB
MOV CL,WRITE
CALL SYSTEM
OR AL,AL
MOV DX,WRTERR
JNZ ABORT
POPRET:
P繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞T:
MOV CL,PRNBUF
CALL SYSTEM
JMP 0
DELIM:
CALL GETCH
DELCHK:
CMP AL,EOL
JZ DOLIN
CMP AL,EOF
JZ DOLIN
CMP AL,V [OP1],AL
MOV [OP2],AL
MOV BX,OPCODE
CALL LOAD
MOV BX,OP1
CALL GETOP
MOV B,[BX],0
MOV BX,OP2
CALL GETOP
DOLIN:here is nothing in the record.
MOV BX,GETBUF ; Reset buffer pointer.
GETIT:
MOV AL,[BX] ; Get next character from buffer.
OV SI,BX
MOV DI,DX
REP
MOVB
MOV DX,DI
MOV BX,SI
MOV [PUTFCB+32],AL
MOV BX,"A"+5300H ;"AS"
MOV [PUTFCB+9],BX
MOOP AX
XCHG AH,AL
SAHF
NOTAF:
POP CX
POP DX
POP BX
RET
;
; Get character from source file.
;
GETCH:
PUSH BX
; Z80 to 8086 Translator version 2.0
; Runs on the 8086 under 86-DOS
; by Tim Paterson
;
ORG 100H
EOF: EQU 1AH ;End of f';'
JZ DOLIN
CMP AL,' '
JZ RET
CMP AL,':'
JZ RET
CMP AL,','
JZ RET
CMP AL,9
RET
HEX:
AND AL,0FH
ADD AL,90
LAHF
INC BX ; Point to next character.
SAHF
MOV [GETPT],BX ; Save new pointer.
TESEND:
MOV [CHAR],AL
JP NOTAF ; P
JNZ NOTRW
PUSH BX
PUSH CX
MOV CX,LENRW-1
LAHF
ADD BX,CX
RCR SI
SAHF
RCL SI
MOV AL,[BX]
POP CX
POP BX
CRET
CMP AL,'9'+1
CMC
JNC RET
CMP AL,40H
JC RET
AND AL,5FH
CMP AL,'A'
JC RET
CMP AL,'Z'+1
CMC
RET
GETID:
DX,OPCODE+1
MOV CH,CL
LOOKLP:
MOV SI,DX
LODB
CMP AL,[BX]
JNZ NEXOP
INC DX
INC BX
DEC CH
JNZ LOOKLP
MOV DX,C AL
LAHF
XCHG AX,BP
SAHF
MOV B,[BX],'['
JP NEXCH
NOTLEF:
CMP AL,')'
JNZ NOTRIT
LAHF
XCHG AX,BP
SAHF
DEC NC BX
MOV B,[BX],']'
INC BX
JP ENDRW
RET
FINDOP:
MOV BX,OPCODE
MOV CX,5
XOR AL,AL
UP
MOV DI,BX
REPNZ
SCABop registers and return.
LOAD:
CALL DELIM
JZ LOADOP
EATLAB:
CALL PUTCH
CALL DELIM
JNZ EATLAB
ENLAB:
MOV AL,':'
MP AL,DL
JZ HAVRW
MOV AL,CL
OR AL,AL
MOV AL,DH
JNZ RWLK
NOTRW:
POP BX
NORW:
POP BX
ENDRW:
POP AX
XCHG AH,AL MOV [BX],AL
MOV CH,1
LODID:
INC BX
CALL GETCH
CALL IDCHK
JC RWCHK
MOV [BX],AL
INC CH
JP LODID
RWCHK:
LAHF
[BX]
MOV BX,[BX+2]
JMP DX
NEXOP:
RCR SI
TEST B,[BX],080H
RCL SI
LAHF
INC BX
SAHF
JZ NEXOP
MOV DX,4
LAHF
AL
LAHF
XCHG AX,BP
SAHF
MOV B,[BX],']'
JP NEXCH
NOTRIT:
MOV [BX],AL
CMP AL,''''
JZ EATQUO
CALL IDCHK
JNC GE
MOV BX,DI
JNZ OPERR
MOV AL,4
SUB AL,CL
JZ RET
DEC AL
JZ OPERR
MOV CL,AL
DEC BX
DEC BX
OR B,[BX],080H
MOCALL PUTCH
LOADOP:
MOV BX,OPCODE
EATEM:
CALL DELIM
JZ EATEM
LOADLP:
CALL IDCHK
JNC $+5
JMP OPERR
MOV [BX],AL
SAHF
JMP IDRET
HAVRW:
POP BX
INC CL
MOV [BX],CL
INC BX
POP DX
PUSH BX
MOV AL,CL
MOV BX,IXSI
CMP AL,RSI
XCHG AH,AL
PUSH AX
XCHG AH,AL
PUSH BX
DEC BX
DEC CH
MOV DL,CH
JZ LOOKRW
MOV DL,[BX]
DEC BX
DEC CH
JNZ NOR ADD BX,DX
RCR SI
SAHF
RCL SI
JP LOOKOP
OPERR:
MOV BX,OPCODE
CALL OUTSTR
CALL TWOOPS
MOV BX,OPCDER
CALL OUTSTTID
NEXCH:
INC BX
CALL GETCH
IDRET:
CALL DELCHK
JNZ OPCHAR
CMP AL,' '
JZ OPCHAR
RET
EATQUO:
INC BX
CALL GETV AL,[OPCODE]
SUB AL,'A'
JC OPERR
ADD AL,AL
MOV DL,AL
MOV DH,0
MOV BX,OPTAB
LAHF
ADD BX,DX
RCR SI
SAHF
RCLINC BX
CALL DELIM
JNZ LOADLP
MOV B,[BX],0
CMP AL,':'
JNZ RET
MOV BX,OPCODE
CALL TRANS
JP ENLAB
GETOP:
XOR AL, JZ IXIY
MOV BX,IYDI
CMP AL,RDI
JNZ NORW
IXIY:
LAHF
XCHG AX,BP
SAHF
JZ NOTENC
LAHF
XCHG AX,BP
SAHF
CALL OW
LOOKRW:
MOV AL,[BX]
MOV DH,AL
PUSH BX
MOV BX,RWTAB
MOV CX,LENRW
RWLK:
UP
MOV DI,BX
REPNZ
SCAB
MOV BX,DI
R
JMP ENLIN
LD:
CALL OUTSTR
MOV BX,OP1
MOV DX,OP2+1
CALL LCHECK
JNZ $+5
JMP LDAX
XCHG DX,BX
DEC BX
INC DX
CH
MOV [BX],AL
CMP AL,';'
JZ L0000
CALL DELCHK
L0000:
CMP AL,''''
JNZ EATQUO
JP NEXCH
IDCHK:
CMP AL,'0'
JC SI
MOV DL,[BX]
INC BX
MOV DH,[BX]
XCHG DX,BX
MOV AL,9
CALL PUTCH
LOOKOP:
MOV AL,[BX]
OR AL,AL
JZ OPERR
MOVAL
LAHF
XCHG AX,BP
SAHF
GETLP:
CALL DELIM
JZ GETLP
OPCHAR:
CMP AL,'('
JNZ NOTLEF
LAHF
XCHG AX,BP
SAHF
INUTSTR
JP NORW
NOTENC:
LAHF
XCHG AX,BP
SAHF
POP BX
DEC BX
MOV B,[BX],'['
INC BX
ADD AL,RIX-1
MOV [BX],AL
I CALL LCHECK
JNZ $+5
JMP STAX
;If immediate move, check for byte memory reference
MOV AL,[OP1]
CMP AL,'[' ;Memory refe
XCHG DX,BX
JMP TRANS
LDAX:
MOV BX,LDAX1
LSAX:
CALL OUTSTR
MOV SI,DX
LODB
CALL TRNTOK
JP OUTSTR
STAX:
MOV BRLFTB
CALL OUTSTR
MOV BX,OP1
CALL GETOUT
JP IODONE
GETPORT:
MOV AL,[BX]
CMP AL,'['
JNZ NOBRAK
LAHF
INC BX
SALL OUTSTR
CALL TWOOPS
MOV BX,DAD2
JP OUTSTR
INCDEC:
MOV AL,[OP1]
CMP AL,RCX+1 ;16-bit?
JNC ONEOPJ
MOV BX,LAHF
MP AL,RDX
RET
ONEOP:
CALL OUTSTR
TRNOP1:
MOV AL,9
TRAN1:
MOV BX,OP1
JP PTRANS
IN:
MOV AL,[OP1]
CMP AL,RAL
C BX
ADD AL,AL
JNC OUTSTR
RET
NEWOP:
MOV AL,13
CALL PUTCH
MOV AL,10
CALL PUTCH
MOV AL,9
RET
LDDR:
CALL OUTrence?
JNZ TWOOPS
MOV AL,[OP1+1] ;Referencing IX as a word?
CMP AL,RIX
JZ TWOOPS
CMP AL,RIY
JZ TWOOPS
MOV AL,[OP2]X,STAX1
JP LSAX
TRNTOK:
CMP AL,' '
JC $+5
JMP PUTCH
PUSH BX
PUSH CX
MOV CL,AL
MOV CH,0
MOV BX,TOKTAB-2
LAHFAHF
PUSH BX
MOV CX,80
MOV AL,']'
UP
MOV DI,BX
REPNZ
SCAB
MOV BX,DI
LAHF
DEC BX
SAHF
MOV B,[BX],0
POP B
CALL OUTSTR
XCHG DX,BX
MOV BX,OPCODE-1
CALL ONEOP
XCHG DX,BX
OUTSTRJ:
JMP OUTSTR
JUMP:
MOV AL,[OP1]
CMP AL,'['
XCHG DX,BX
MOV BX,OP2
JZ GETPORT
MOV BX,SAVEAX
CALL OUTSTR
CALL OUTSTR
MOV BX,OP2
CALL GETPORT
MOV BX,MOV0
CSTR
MOV BX,BLMOVE
JP OUTSTR
CPDR:
CALL OUTSTR
MOV BX,CMPREP
JP OUTSTR
ADD:
MOV AL,[OP1]
CMP AL,RBX
JZ DAD
ARI
CMP AL,20H ;Could be immediate?
MOV AL,9
JC L0001
CALL BFLAG ;Add "B,"
L0001:
CALL TRAN1
JP TRNOP2
TWOOPS:
C
ADD BX,CX
RCR SI
SAHF
RCL SI
LAHF
ADD BX,CX
RCR SI
SAHF
RCL SI
MOV AL,[BX]
CALL PUTCH
INC BX
MOV AL,[X
NOBRAK:
MOV AL,[BX]
CMP AL,RGCL
JNZ FIXPOR
MOV BX,IO1
CALL OUTSTR
XCHG DX,BX
CALL OUTSTR
MOV AL,RDX
CALL TR
JNZ DIRECT
MOV AL,[OP1+1]
MOV [OP1],AL
XOR AL,AL
MOV [OP1+1],AL
DIRECT:
MOV AL,[OP2]
OR AL,AL
JZ ONEOPJ
CALLALL ONEOP
MOV AL,','
CALL PUTCH
MOV AL,RAL
CALL TRNTOK
IODONE:
MOV BX,RESTAX
JMP OUTSTR
OUT:
MOV AL,[OP2]
XCHGTH:
CALL OUTSTR
MOV AL,[OP2]
OR AL,AL
JZ $+5
JMP TWOOPS
MOV AL,9
CALL PUTCH
MOV AL,RAL
CALL TRNTOK
MOV AL,',ALL TRNOP1
TRNOP2:
MOV AL,','
TRAN2:
MOV BX,OP2
PTRANS:
CALL PUTCH
TRANS:
MOV AL,[BX]
LAHF
INC BX
SAHF
OR ALBX]
POP CX
POP BX
OR AL,AL
JZ RET
JMP PUTCH
PUSH:
MOV DX,PUSHAF
JP AFCHK
POP:
MOV DX,POPAF
AFCHK:
MOV AL,[ONTOK
MOV BX,IO2
JMP OUTSTR
GETOUT:
CALL GETPORT
JNC RET
MOV BX,BADIO
JMP OUTSTR
FIXPOR:
XCHG DX,BX
CALL OUTSTR FIXCON
MOV BX,OP2
OUTCON:
MOV CH,AL
MOV AL,'J'
CALL PUTCH
MOV AL,CH
CALL TRNTOK
MOV AL,9
CALL PTRANS
MOV AL, DX,BX
MOV BX,OP1
CMP AL,RAL
JZ GETOUT
MOV BX,SAVEAX
CALL OUTSTR
MOV BX,MOVAL
CALL OUTSTR
CALL TRNOP2
MOV BX,C'
JMP TRAN1
ACCUM:
CALL OUTSTR
MOV AL,9
CALL PUTCH
MOV AL,RAL
JMP TRNTOK
ONEOPJ: JMP ONEOP
DAD:
MOV BX,DAD1
C,AL
JZ RET
CALL TRNTOK
JP TRANS
LCHECK:
MOV AL,[BX]
CMP AL,RAL
JNZ RET
MOV SI,DX
LODB
CMP AL,RCX
JZ RET
CP1]
CMP AL,RAX
JNZ ONEOPJ
XCHG DX,BX
OUTSTR:
MOV AL,[BX]
OR AL,AL
JNZ L0002
CALL NEWOP
L0002:
CALL PUTCH
INCH
CMP AL,ODDPAR
MOV BX,WARNPA
JZ OUTSTRJ
CMP AL,EVEPAR
JZ OUTSTRJ
RET
FIXCON:
MOV AL,[OP1]
CMP AL,RGCL
JNZ R
MOV AL,CH
CALL HEX
MOV AL,'H'
JMP PUTCH
OPTAB:
DW AOPS,BOPS,COPS,DOPS,EOPS
DW FOPS,GOPS,HOPS,IOPS,JOPS
DW KOPS,LL BFLAG
L0004:
CALL TRAN2
MOV AL,','
CALL PUTCH
CALL GETBIT
MOV BX,BITERR
JNC L0005
CALL OUTSTR
L0005:
POP BPS:
DM 'D'
DW LD,MOV
DM 'DIR'
DW OUTSTR,UP
DM 'DDR'
DW LDDR,DOWN
DB 0
MOPS:
DB 0
NOPS:
DM 'EG'
DW ACCUM,OPX]
CMP AL,'9'+1
JNZ RET
MOV B,[BX],'0'
LAHF
DEC BX
SAHF
JP NEXLAB
EX:
MOV AL,[OP1]
CMP AL,RAX
JZ OUTSTRJ1
R,OPCODE
DM 'W'
DW PSEUDO,OPCODE
DM 'B'
DW PSEUDO,OPCODE
DM 'M'
DW PSEUDO,OPCODE
DM 'S'
DW ONEOP,OPCODE
DB 0
ET
MOV AL,CY
RET
RETURN:
MOV AL,[OP1]
OR AL,AL
JZ OUTSTRJ
MOV BX,'R'+4500H ;"RE"
MOV [OP2],BX
MOV BX,'T'
MOV OPS,MOPS,NOPS,OOPS
DW POPS,QOPS,ROPS,SOPS,TOPS
DW UOPS,VOPS,WOPS,XOPS,YOPS
DW ZOPS
AOPS:
DM 'DD'
DW ADD,OPCODE
DM 'X
JMP OUTSTR
BFLAG:
CALL PUTCH
MOV AL,'B'
CALL PUTCH
MOV AL,','
RET
GETBIT:
MOV AL,[OP1+1]
OR AL,AL
STC
CODE
DB 0
OOPS:
DM 'R'
DW ARITH,OPCODE
DM 'UT'
DW OUT,OUTB
DM 'RG'
DW ONEOP,OPCODE
DB 0
POPS:
DM 'OP'
DW P MOV AL,[OP1+1]
CMP AL,STP
JZ XTHL
MOV BX,XCHG
CALL OUTSTR
JMP TWOOPS
XTHL:
MOV BX,XTHL1
CALL OUTSTR
CALL TRNOPEOPS:
DM 'X'
DW EX,EXAF
DM 'I'
DW OUTSTR,OPCODE
DM 'XX'
DW OUTSTR,EXX
DM 'QU'
DW ONEOP,OPCODE
DM 'NDIF'
DW O[OP2+2],BX
JP DIRECT
ONEOPJ1:
JMP ONEOP
DOCALL:
MOV AL,[OP2]
OR AL,AL
JZ ONEOPJ1
CALL FIXCON
DEC AL
XOR AL,1
DC'
DW ARITH,OPCODE
DM 'ND'
DW ARITH,OPCODE
DB 0
BOPS:
DM 'IT'
DW BITSET,TESBIT
DB 0
COPS:
DM 'ALL'
DW DOCAL
JNZ RET
MOV AL,[OP1]
SUB AL,'0'
JC RET
CMP AL,8
CMC
JC RET
MOV CH,AL
INC CH
XOR AL,AL
STC
SHFT:
RCL AL
OP,OPCODE
DM 'USH'
DW PUSH,OPCODE
DB 0
QOPS:
DB 0
ROPS:
DM 'ET'
DW RETURN,OPCODE
DM 'LA'
DW ACCUM,RCL
DM 'RA2
MOV BX,XTHL2
OUTSTRJ1:
JMP OUTSTR
PSEUDO:
CALL ONEOP
MOV AL,[OP2]
OR AL,AL
JZ RET
JMP TRNOP2
RET
BITSET:
UTSTR,OPCODE
DB 0
FOPS:
DB 0
GOPS:
DB 0
HOPS:
DM 'ALT'
DW OUTSTR,HLT
DB 0
IOPS:
DM 'NC'
DW INCDEC,OPCODE
D INC AL
MOV BX,LABEL
CALL OUTCON
MOV BX,OPCODE-1
CALL OUTSTR
MOV AL,[OP2]
OR AL,AL
MOV AL,9
MOV BX,OP2
JZ L000L,OPCODE
DM 'P'
DW ARITH,CMP
DM 'PL'
DW ACCUM,NOT
DM 'PIR'
DW OUTSTR,CPIR
DM 'PDR'
DW CPDR,DOWN
DM 'CF'
DW O
DEC CH
JNZ SHFT
XOR AL,CL
MOV CH,AL
MOV AL,'0'
CALL PUTCH
MOV AL,CH
RCR AL
RCR AL
RCR AL
RCR AL
CALL HEX'
DW ACCUM,RCR
DM 'LCA'
DW ACCUM,ROL
DM 'RCA'
DW ACCUM,ROR
DM 'L'
DW ONEOP,RCL
DM 'R'
DW ONEOP,RCR
DM 'LC'
MOV CL,0
JP SETRES
RES:
MOV CL,-1
SETRES:
CALL OUTSTR
PUSH BX
MOV AL,[OP2]
CMP AL,'['
MOV AL,9
JNZ L0004
CALM 'N'
DW IN,INB
DM 'F'
DW ONEOP,OPCODE
DB 0
JOPS:
DM 'R'
DW JUMP,JR
DM 'P'
DW JUMP,JMP
DB 0
KOPS:
DB 0
LO3
CALL PTRANS
L0003:
MOV BX,CRLF
CALL OUTSTR
CALL TRANS
CALL OUTSTR
MOV BX,LABEL+4
NEXLAB:
INC [BX]
MOV AL,[BUTSTR,CMC
DB 0
DOPS:
DM 'EC'
DW INCDEC,OPCODE
DM 'JNZ'
DW ONEOP,DJNZ
DM 'AA'
DW OUTSTR,OPCODE
DM 'I'
DW OUTST DW ONEOP,ROL
DM 'RC'
DW ONEOP,ROR
DM 'ES'
DW RES,RESBIT
DM 'ETI'
DW OUTSTR,IRET
DM 'ETN'
DW OUTSTR,IRET
DM 'S9,'CX,[BC]'
EXAF: DM 'LAHF',0,'XCHG',9,'AX,BP',0,'SAHF'
MOVAL: DM 0,'MOV',9,'AL'
IXSI: DM 9,'MOV',9,'SI,[IX]',13,10
IYDI: DMag not always same as Z80.'
IO1: DB 'MOV',9,'DI,DX',0,'MOV',9,'DL,CL',0
DM 'XOR',9,'DH,DH',13,10,9
IO2: DM 0,'MOV',9,'DX,DI'DS 2
CHAR: DS 1
DB 0
OPCODE: DS 80
OP1: DS 80
OP2: DS 80
PUTBUF: DS 128
GETBUF: DS 128
PUTFCB: DS 33
DS 50
STACK: EQ'AX',0,'XCHG',9,'AH,AL',0,'SAHF'
DOWN: DM 'DOWN'
UP: DB 'UP'
BLMOVE: DB 0,'MOV',9,'SI,BX',0,'MOV',9,'DI,DX'
DB 0,'REP',0,'MHCLCHALIXIY'
RWTAB:
DB 'ABCDEHLBDHSACNZNPMPPII'
LENRW: EQU $-RWTAB
DB 0,0,0,0,0,0,0,'CELPF',0,'C',0,'Z',0,0,'OEYX'
HEADERT'
DW ONEOP,CALL
DB 0
SOPS:
DM 'UB'
DW ARITH,OPCODE
DM 'BC'
DW ARITH,SBB
DM 'LA'
DW ONEOP,SAL
DM 'RA'
DW ON 9,'MOV',9,'DI,[IY]',13,10
RESTAX: DB 0
SAVEAX: DM 'XCHG',9,'AX,SI'
CRLFTB: DM 13,10,9
INB: DM 'INB',9
OUTB: DM 'OUTB',9
X
BADIO: DM 13,10,'; *** WARNING: Flags not same as Z80.'
BITERR: DM 13,10,' *** ERROR: Cannot determine bit number.'
SETBIT: U $
ORG 1 ;This is really just for equates without EQU
RSI: DS 1
RDI: DS 1
ODDPAR: DS 1
EVEPAR: DS 1
DS 5 ;MINUS,PLUS,NOOVB',0,'MOV',9,'DX,DI'
DM 0,'MOV',9,'BX,SI'
CPIR: DB 'UP'
CMPREP: DB 0,'MOV',9,'DI,BX',0,'REPNZ',0,'SCAB'
DM 0,'MOV',9,'BX: DB 13,10,'Z80 to 8086 Translator version 2.0',13,10,'$'
NOROOM: DB 13,10,'Insufficient directory space to create file',13,10EOP,SAR
DM 'RL'
DW ONEOP,SHR
DM 'CF'
DW OUTSTR,STC
DM 'ET'
DW BITSET,SETBIT
DB 0
TOPS:
DB 0
UOPS:
DB 0
VOPSCHG: DM 'XCHG'
JMP: DM 'JMP'
JR: DM 'JP'
RCL: DM 'RCL'
RCR: DM 'RCR'
ROL: DM 'ROL'
ROR: DM 'ROR'
SAL: DM 'SAL'
SAR: DM 'DM 'LAHF',0,'OR'
DM 0,'SAHF'
RESBIT: DM 'LAHF',0,'AND'
DM 0,'SAHF'
TESBIT: DM 'RCR',9,'SI',0,'TEST'
DM 0,'RCL',9,'SI'
XT ZERO,ZERO,NOT CARRY
CY: DS 1
RAX: DS 1
STP: DS 1
RBX: DS 1
RDX: DS 1
RCX: DS 1
RBL: DS 1
RBH: DS 1
RDL: DS 1
RDH: DS,DI'
DAD1: DM 'LAHF',0,'ADD'
DAD2: DM 0,'RCR',9,'SI',0,'SAHF',0,'RCL',9,'SI'
LAHF: DM 'LAHF'
DM 0,'SAHF'
DJNZ: DB 'DEC',9,,'$'
NOFILE: DB 13,10,'File not found',13,10,'$'
ENDMES: DB 13,10,'Translation complete',13,10,'$'
WRTERR: DB 13,10,'Out of d:
DB 0
WOPS:
DB 0
XOPS:
DM 'OR'
DW ARITH,OPCODE
DB 0
YOPS:
DB 0
ZOPS:
DB 0
LDAX1: DM 9,'SI,'
DM 0,'LODB'
SSAR'
SHR: DM 'SHR'
STC: DM 'STC'
IRET: DM 'IRET'
HLT: DM 'HLT'
CMC: DM 'CMC'
NOT: DM 'NOT'
MOV0: DB 0
MOV: DM 'MOV'
CMPTHL1: DM 'POP',9,'SI',0,'XCHG',9,'SI'
XTHL2: DM 0,'PUSH',9,'SI'
EXX: DB 'XCHG',9,'BX,[HL]',0,'XCHG',9,'DX,[DE]',0
DM 'XCHG', 1
RGCL: DS 1
RCH: DS 1
RAL: DS 1
RIX: DS 1
RIY: DS 1
'CH',13,10
DB '; *** WARNING: DJNZ does not affect flags - DEC does.',0
DM 'JNZ'
WARNPA: DM 13,10,'; *** WARNING: Parity flisk space',13,10,'$'
OPCDER: DM 13,10,'*** Opcode Error '
CRLF: DM 13,10
LABEL: DB 'L0000',0
DM ':',9
PUTPT: DS 2
GETPT: TAX1: DM 9,'DI,'
DM 0,'STOB'
PUSHAF: DB 'LAHF',0,'XCHG',9,'AH,AL',0,'PUSH',9,'AX',0
DM 'XCHG',9,'AH,AL'
POPAF: DM 'POP',9,: DM 'CMP'
SBB: DM 'SBB'
CALL: DM 'CALL'
TOKTAB:
DB 'SIDI'
DB 'PEPOS',0,'NSNZZ',0,'NCC',0
DB 'AXSPBXDXCX'
DB 'BLBHDLD繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞繞