mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2026-06-16 07:49:24 +00:00
Add files via upload
This commit is contained in:
@@ -0,0 +1,483 @@
|
||||
VECTORS SEGMENT AT 0H ;Set up segment to intercept Interrupts
|
||||
ORG 9H*4 ;The keyboard Interrupt
|
||||
KEYBOARD_INT LABEL DWORD
|
||||
ORG 1CH*4 ;Timer Interrupt
|
||||
TIMER_VECTOR LABEL DWORD
|
||||
VECTORS ENDS
|
||||
|
||||
SCREEN SEGMENT AT 0B000H ;A dummy segment to use as the
|
||||
SCREEN ENDS ;Extra Segment
|
||||
|
||||
ROM_BIOS_DATA SEGMENT AT 40H ;BIOS statuses held here, also keyboard buffer
|
||||
|
||||
ORG 1AH
|
||||
HEAD DW ? ;Unread chars go from Head to Tail
|
||||
TAIL DW ?
|
||||
BUFFER DW 16 DUP (?) ;The buffer itself
|
||||
BUFFER_END LABEL WORD
|
||||
|
||||
ROM_BIOS_DATA ENDS
|
||||
|
||||
CODE_SEG SEGMENT
|
||||
ASSUME CS:CODE_SEG
|
||||
ORG 100H ;ORG = 100H to make this into a .COM file
|
||||
FIRST: JMP LOAD_KEEPER ;First time through
|
||||
|
||||
COPY_RIGHT DB '(C)1985 S.HOLZNER' ;Ascii autograph
|
||||
PAD DB 20*102 DUP(0) ;Memory storage for pad
|
||||
PAD_CURSOR DW 9*102 ;Current position in pad
|
||||
ATTRIBUTE DB 112 ;Pad Attribute -- reverse video
|
||||
LINE_ATTRIBUTE DB 240 ;Flashing Rev video
|
||||
OLD_ATTRIBUTE DB 7 ;Original screen attrib: normal
|
||||
PAD_OFFSET DW 0 ;Chooses 1st 250 bytes or 2nd
|
||||
FIRST_POSITION DW ? ;Position of 1st char on screen
|
||||
TRIGGER_FLAG DW 0 ;Trigger on or off
|
||||
FULL_FLAG DB 0 ;Buffer Full Flag
|
||||
LINE DW 9 ;Line number, 0-9
|
||||
SCREEN_SEG_OFFSET DW 0 ;0 for mono, 8000H for graphics
|
||||
IO_CHAR DW ? ;Holds addr of Put or Get_Char
|
||||
STATUS_PORT DW ? ;Video controller status port
|
||||
OLD_KEYBOARD_INT DD ? ;Location of old kbd interrupt
|
||||
FINISHED_FLAG DB 1 ;If not finished,f buffer
|
||||
COMMAND_INDEX DW 1 ;Stores positior timer)
|
||||
ROM_TIMER DD 1 ;The Timer interrupt's address
|
||||
OLD_HEAD DW 0
|
||||
|
||||
KEEPER PROC NEAR ;The keyboard interrupt will now come here.
|
||||
ASSUME CS:CODE_SEG
|
||||
PUSH AX ;Save the used registers for good form
|
||||
PUSH BX
|
||||
PUSH CX
|
||||
PUSH DX
|
||||
PUSH DI
|
||||
PUSH SI
|
||||
PUSH DS
|
||||
PUSH ES
|
||||
PUSHF ;First, call old keyboard interrupt
|
||||
CALL OLD_KEYBOARD_INT
|
||||
ASSUME DS:ROM_BIOS_DATA ;Examine the char just put in
|
||||
MOV BX,ROM_BIOS_DATA
|
||||
MOV DS,BX
|
||||
MOV BX,TAIL ;Point to current tail
|
||||
CMP BX,HEAD ;If at head, kbd int has deleted char
|
||||
JE BYE ;So leave
|
||||
MOV DX,HEAD
|
||||
SUB DX,2 ;Point to just read in character
|
||||
CMP DX,OFFSET BUFFER ;Did we undershoot buffer?
|
||||
JAE NOWRAP ;Nope
|
||||
MOV DX,OFFSET BUFFER_END ;Yes -- move to buffer top
|
||||
SUB DX,2 ;Compare two bytes back from head
|
||||
NOWRAP: CMP DX,TAIL ;If it's the tail, buffer is full
|
||||
JNE NOTFULL ;We're OK, jump to NotFull
|
||||
CMP FULL_FLAG,1 ;Check if keyboard buffer full
|
||||
JE BYE ;Yep, leave
|
||||
MOV FULL_FLAG,1 ;Oops, full, set flag and take
|
||||
JMP CHK ; this last character
|
||||
NOTFULL:MOV FULL_FLAG,0 ;Always reset Full_Flag when buff clears
|
||||
CHK: CMP TRIGGER_FLAG,0 ;Is the window on (triggered?)
|
||||
JNE SUBT ;Yep, keep going
|
||||
MOV DX,OLD_HEAD ;Check position of buffer head
|
||||
CMP DX,HEAD
|
||||
JNE CONT
|
||||
MOV OLD_HEAD,0
|
||||
BYE: JMP OUT
|
||||
CONT: MOV DX,HEAD
|
||||
MOV OLD_HEAD,DX
|
||||
SUBT: SUB BX,2 ;Point to just read in character
|
||||
CMP BX,OFFSET BUFFER ;Did we undershoot buffer?
|
||||
JAE NO_WRAP ;Nope
|
||||
MOV BX,OFFSET BUFFER_END ;Yes -- move to buffer top
|
||||
SUB BX,2 ;
|
||||
NO_WRAP:MOV DX,[BX] ;Char in DX now
|
||||
;------ CHAR IN DX NOW -------
|
||||
CMP FINISHED_FLAG,0
|
||||
JE IN
|
||||
CMP DX,310EH ;Default trigger is a ^N here.
|
||||
JNE NOT_TRIGGER ;No
|
||||
MOV TAIL,BX
|
||||
NOT TRIGGER_FLAG ;Switch Modes
|
||||
CMP TRIGGER_FLAG,0 ;Trigger off?
|
||||
JNE TRIGGER_ON ;No, only other choice is on
|
||||
TRIGGER_OFF:
|
||||
MOV OLD_HEAD,0 ;Reset old head
|
||||
MOV AH,OLD_ATTRIBUTE ;Get ready to restore screen
|
||||
MOV ATTRIBUTE,AH ;Pad and blinking line set to orig.
|
||||
MOV LINE_ATTRIBUTE,AH ; values
|
||||
MOV PAD_OFFSET,10*102 ;Point to 2nd half of pad
|
||||
LEA AX,PUT_CHAR ;Make IO call Put_Char as it scans
|
||||
MOV IO_CHAR,AX ;over all locations in pad on screen
|
||||
CALL IO ;Restore screen
|
||||
CMP LINE,9 ;Was the window turned off without
|
||||
JE IN ; using up-down keys? If so, exit
|
||||
MOV AX,LINE ;No, there is a line to stuff in
|
||||
MOV CL,102 ; keyboard buffer
|
||||
MUL CL ;Find its location in Pad
|
||||
MOV COMMAND_INDEX,AX ;And send to Put
|
||||
CALL PUT ;Which will do actual stuffing
|
||||
IN: JMP OUT ;Done
|
||||
TRIGGER_ON: ;Window just turned on
|
||||
MOV LINE,9 ;Set blinking line to bottom
|
||||
MOV PAD_OFFSET,10*102 ;Point to screen storage part of pad
|
||||
LEA AX,GET_CHAR ;Make IO use Get_char so current screen
|
||||
MOV IO_CHAR,AX ;is stored
|
||||
CALL IO ;Store Screen
|
||||
CALL DISPLAY ;And put up the pad
|
||||
JMP OUT ;Done here.
|
||||
NOT_TRIGGER:
|
||||
TEST TRIGGER_FLAG,1 ;Is Trigger on?
|
||||
JZ RUBOUT_TEST
|
||||
MOV TAIL,BX ;Yes, delete this char from buffer
|
||||
UP: CMP DX,4800H ;An Up cursor key?
|
||||
JNE DOWN ;No, try Down
|
||||
DEC LINE ;Move blinker up one line
|
||||
CMP LINE,0 ;At top? If so, reset
|
||||
JGE NOT_TOP
|
||||
MOV LINE,9
|
||||
NOT_TOP:CALL DISPLAY ;Display result
|
||||
JMP OUT ;And leave
|
||||
DOWN: CMP DX,5000H ;Perhaps Down cusor key pushed
|
||||
JNE IN ;If not, ignore key
|
||||
INC LINE ;If so, move down one
|
||||
CMP LINE,9 ;If at bottom, wrap to top
|
||||
JLE NOT_BOT
|
||||
MOV LINE,0
|
||||
NOT_BOT:CALL DISPLAY ;Show results
|
||||
JMP OUT ;And exit
|
||||
RUBOUT_TEST:
|
||||
CMP DX,0E08H ;Is it a Rubout?
|
||||
JNE CHAR_TEST ;No -- try carriage return-line feed
|
||||
MOV BX,PAD_CURSOR ;Yes -- get current pad location
|
||||
CMP BX,9*102 ;Are we at beginning of last line?
|
||||
JLE NEVER_MIND ;Yes -- can't rubout past beginning
|
||||
SUB PAD_CURSOR,2 ;No, rubout this char
|
||||
MOV PAD[BX-2],20H ;Move a space in instead (3920H)
|
||||
MOV PAD[BX-1],39H
|
||||
NEVER_MIND:
|
||||
JMP OUT ;Done here.
|
||||
CHAR_TEST:
|
||||
CMP DL,13 ;Is this a carriage return?
|
||||
JE PLUG ;If yes, plug this line into Pad
|
||||
CMP DL,32 ;If this char < Ascii 32, delete line
|
||||
JGE PLUG
|
||||
MOV PAD_CURSOR,9*102 ;Clear the current line
|
||||
MOV CX,51
|
||||
MOV BX,9*102
|
||||
CLEAR: MOV WORD PTR PAD[BX],0
|
||||
ADD BX,2
|
||||
LOOP CLEAR
|
||||
JMP OUT ;And exit
|
||||
|
||||
PLUG: MOV BX,PAD_CURSOR ;Get current pad location
|
||||
CMP BX,10*102-2 ;Are we past the end of the pad?
|
||||
JGE CRLF_TEST ;Yes -- throw away char
|
||||
MOV WORD PTR PAD[BX],DX ;No -- move ASCII code into pad
|
||||
ADD PAD_CURSOR,2 ;Increment pad location
|
||||
CRLF_TEST:
|
||||
CMP DX,1C0DH ;Is it a carriage return-line feed?
|
||||
JNE OUT ;No -- put it in the pad
|
||||
CALL CRLF ;Yes -- move everything up in pad
|
||||
OUT: POP ES ;Having done Pushes, here are the Pops
|
||||
POP DS
|
||||
POP SI
|
||||
POP DI
|
||||
POP DX
|
||||
POP CX
|
||||
POP BX
|
||||
POP AX
|
||||
IRET ;An interrupt needs an IRET
|
||||
KEEPER ENDP
|
||||
|
||||
DISPLAY PROC NEAR ;Puts the whole pad on the screen
|
||||
PUSH AX
|
||||
MOV ATTRIBUTE,112 ;Use reverse video
|
||||
MOV LINE_ATTRIBUTE,240
|
||||
MOV PAD_OFFSET,0 ;Use 1st 250 bytes of pad memory
|
||||
LEA AX,PUT_CHAR ;Make IO use Put-Char so it does
|
||||
MOV IO_CHAR,AX
|
||||
CALL IO ;Put result on screen
|
||||
POP AX
|
||||
RET ;Leave
|
||||
DISPLAY ENDP
|
||||
|
||||
CRLF PROC NEAR ;This handles carriage returns
|
||||
PUSH BX ;Push everything conceivable
|
||||
PUSH CX
|
||||
PUSH DI
|
||||
PUSH SI
|
||||
PUSH DS
|
||||
PUSH ES
|
||||
ASSUME DS:CODE_SEG ;Set DS to Code_Seg here
|
||||
PUSH CS
|
||||
POP DS
|
||||
ASSUME ES:CODE_SEG ;And ES too
|
||||
PUSH DS
|
||||
POP ES
|
||||
LEA DI,PAD ;Get ready to move contents of Pad
|
||||
MOV SI,DI ; up one line
|
||||
ADD SI,102 ;DI-top line, SI-one below top line
|
||||
MOV CX,9*51
|
||||
MOV BX,PAD_CURSOR ;But first finish line with a 0
|
||||
CMP BX,9*102+2 ; as a flag letting Put know line is
|
||||
JE POPS ; done.
|
||||
MOV WORD PTR PAD[BX],0
|
||||
REP MOVSW ;Move up Pad contents
|
||||
MOV CX,51 ;Now fill the last line with spaces
|
||||
MOV AX,3920H
|
||||
REP STOSW ;Using Stosw
|
||||
POPS: MOV PAD_CURSOR,9*102 ;And finally reset Cursor to beginning
|
||||
POP ES ; of the last line again.
|
||||
POP DS
|
||||
POP SI
|
||||
POP DI
|
||||
POP CX
|
||||
POP BX
|
||||
DONE: RET ;And out.
|
||||
CRLF ENDP
|
||||
|
||||
GET_CHAR PROC NEAR ;Gets a char from screen and advances position
|
||||
ASSUME ES:SCREEN,DS:ROM_BIOS_DATA
|
||||
PUSH DX
|
||||
MOV SI,2 ;Loop twice, once for char, once for attribute
|
||||
MOV DX,STATUS_PORT ;Get ready to read video controller status
|
||||
G_WAIT_LOW: ;Start waiting for a new horizontal scan -
|
||||
IN AL,DX ;Make sure the video controller scan status
|
||||
TEST AL,1 ;is low
|
||||
JNZ G_WAIT_LOW
|
||||
G_WAIT_HIGH: ;After port has gone low, it must go high
|
||||
IN AL,DX ;before it is safe to read directly from
|
||||
TEST AL,1 ;the screen buffer in memory
|
||||
JZ G_WAIT_HIGH
|
||||
MOV AH,ES:[DI] ;Do the move from the screen, one byte at a time
|
||||
INC DI ;Move to next screen location
|
||||
DEC SI ;Decrement loop counter
|
||||
CMP SI,0 ;Are we done?
|
||||
JE LEAVE ;Yes
|
||||
MOV PAD[BX],AH ;No -- put char we got into the pad
|
||||
JMP G_WAIT_LOW ;Do it again
|
||||
LEAVE: MOV OLD_ATTRIBUTE,AH
|
||||
ADD BX,2
|
||||
POP DX
|
||||
RET
|
||||
GET_CHAR ENDP
|
||||
|
||||
PUT_CHAR PROC NEAR ;Puts one char on screen and advances position
|
||||
PUSH DX
|
||||
MOV AH,PAD[BX] ;Get the char to be put onto the screen
|
||||
CMP AH,32
|
||||
JAE GO
|
||||
MOV AH,32
|
||||
GO: MOV SI,2 ;Loop twice, once for char, once for attribute
|
||||
MOV DX,STATUS_PORT ;Get ready to read video controller status
|
||||
P_WAIT_LOW: ;Start waiting for a new horizontal scan -
|
||||
IN AL,DX ;Make sure the video controller scan status
|
||||
TEST AL,1 ;is low
|
||||
JNZ P_WAIT_LOW
|
||||
P_WAIT_HIGH: ;After port has gone low, it must go high
|
||||
IN AL,DX ;before it is safe to write directly to
|
||||
TEST AL,1 ;the screen buffer in memory
|
||||
JZ P_WAIT_HIGH
|
||||
MOV ES:[DI],AH ;Move to screen, one byte at a time
|
||||
MOV AH,ATTRIBUTE ;Load attribute byte for second pass
|
||||
INC DI ;Point to next screen postion
|
||||
DEC SI ;Decrement loop counter
|
||||
JNZ P_WAIT_LOW ;If not zero, do it one more time
|
||||
ADD BX,2
|
||||
POP DX
|
||||
RET ;Exeunt
|
||||
PUT_CHAR ENDP
|
||||
|
||||
IO PROC NEAR ;This scans over all screen positions of the pad
|
||||
ASSUME ES:SCREEN ;Use screen as extra segment
|
||||
MOV BX,SCREEN
|
||||
MOV ES,BX
|
||||
|
||||
PUSH DS
|
||||
MOV BX,ROM_BIOS_DATA
|
||||
MOV DS,BX
|
||||
MOV BX,4AH
|
||||
MOV BX,DS:[BX]
|
||||
SUB BX,51
|
||||
ADD BX,BX
|
||||
MOV FIRST_POSITION,BX
|
||||
POP DS
|
||||
|
||||
MOV DI,SCREEN_SEG_OFFSET ;DI will be pointer to screen postion
|
||||
ADD DI,FIRST_POSITION ;Add width of screen minus pad width
|
||||
MOV BX,PAD_OFFSET ;BX will be pad location pointer
|
||||
MOV CX,10 ;There will be 10 lines
|
||||
|
||||
LINE_LOOP:
|
||||
PUSH WORD PTR ATTRIBUTE
|
||||
PUSH CX ;Figure out whether this is blinking
|
||||
NEG CX ; line and if so, temporarily change
|
||||
ADD CX,10 ; display attribute
|
||||
CMP CX,LINE
|
||||
JNE NOLINE
|
||||
MOV CL,LINE_ATTRIBUTE
|
||||
MOV ATTRIBUTE,CL
|
||||
NOLINE: POP CX
|
||||
MOV DX,51 ;And 51 spaces across
|
||||
CHAR_LOOP:
|
||||
CALL IO_CHAR ;Call Put-Char or Get-Char
|
||||
DEC DX ;Decrement character loop counter
|
||||
JNZ CHAR_LOOP ;If not zero, scan over next character
|
||||
ADD DI,FIRST_POSITION ;Add width of screen minus pad width
|
||||
|
||||
POP WORD PTR ATTRIBUTE
|
||||
LOOP LINE_LOOP ;And now go back to do next line
|
||||
RET ;Finished
|
||||
IO ENDP
|
||||
|
||||
PUT PROC NEAR ;Here it is.
|
||||
ASSUME DS:ROM_BIOS_DATA ;Free DS
|
||||
PUSH DS ;Save all used registers
|
||||
PUSH SI
|
||||
PUSH DI
|
||||
PUSH DX
|
||||
PUSH CX
|
||||
PUSH BX
|
||||
PUSH AX
|
||||
MOV AX,ROM_BIOS_DATA ;Just to make sure
|
||||
MOV DS,AX ;Set DS correctly
|
||||
FIN: MOV FINISHED_FLAG,1 ;Assume we'll finish
|
||||
MOV BX,TAIL ;Prepare to move to buffer's tail
|
||||
MOV SI,COMMAND_INDEX ;Get our source index
|
||||
|
||||
STUFF: MOV AX,WORD PTR PAD[SI]
|
||||
ADD SI,2 ;Point to the command's next character
|
||||
CMP AX,0 ;Is it a zero? (End of command)
|
||||
JE NO_NEW_CHARACTERS ;Yes, leave with Finished_Flag=1
|
||||
MOV DX,BX ;Find position in buffer from BX
|
||||
ADD DX,2 ;Move to next position for this word
|
||||
CMP DX,OFFSET BUFFER_END ;Are we past the end?
|
||||
JL NO_WRAP2 ;No, don't wrap
|
||||
MOV DX,OFFSET BUFFER ;Wrap
|
||||
NO_WRAP2:
|
||||
CMP DX,HEAD ;Buffer full but not yet done?
|
||||
JE BUFFER_FULL ;Time to leave, set Finished_Flag=0.
|
||||
ADD COMMAND_INDEX,2 ;Move to next word in command
|
||||
MOV [BX],AX ;Put it into the buffer right here.
|
||||
ADD BX,2 ;Point to next space in buffer
|
||||
CMP BX,OFFSET BUFFER_END ;Wrap here?
|
||||
JL NO_WRAP3 ;No, readjust buffer tail
|
||||
MOV BX,OFFSET BUFFER ;Yes, wrap
|
||||
NO_WRAP3:
|
||||
MOV TAIL,BX ;Reset buffer tail
|
||||
JMP STUFF ;Back to stuff in another character.
|
||||
BUFFER_FULL: ;If buffer is full, let timer take over
|
||||
MOV FINISHED_FLAG,0 ; by setting Finished_Flag to 0.
|
||||
NO_NEW_CHARACTERS:
|
||||
POP AX ;Restore everything before departure.
|
||||
POP BX
|
||||
POP CX
|
||||
POP DX
|
||||
POP DI
|
||||
POP SI
|
||||
POP DS
|
||||
STI
|
||||
RET
|
||||
PUT ENDP
|
||||
|
||||
ASSUME DS:CODE_SEG
|
||||
INTERCEPT_TIMER PROC NEAR ;This completes filling the buffer
|
||||
PUSHF ;Store used flags
|
||||
PUSH DS ;Save DS since we'll change it
|
||||
PUSH CS ;Put current value of CS into DS
|
||||
POP DS
|
||||
CALL ROM_TIMER ;Make obligatory call
|
||||
PUSHF
|
||||
CMP FINISHED_FLAG,1 ;Do we have to do anything?
|
||||
JE OUT1 ;No, leave
|
||||
CLI ;Yes, start by clearing interrupts
|
||||
PUSH DS ;Save these.
|
||||
PUSH SI
|
||||
PUSH DX
|
||||
PUSH BX
|
||||
PUSH AX
|
||||
ASSUME DS:ROM_BIOS_DATA ;Point to the keyboard buffer again.
|
||||
MOV AX,ROM_BIOS_DATA
|
||||
MOV DS,AX
|
||||
MOV BX,TAIL ;Prepare to put characters in at tail
|
||||
MOV FINISHED_FLAG,1 ;Assume we'll finish
|
||||
MOV SI,COMMAND_INDEX ;Find where we left ourselves
|
||||
|
||||
STUFF2: MOV AX,WORD PTR PAD[SI] ;The same stuff loop as above.
|
||||
ADD SI,2 ;Point to next command character.
|
||||
CMP AX,0 ;Is it zero? (end of command)
|
||||
JNE OVER ;No, continue.
|
||||
JMP NO_NEW_CHARACTERS2 ;Yes, leave with Finished_Flag=1
|
||||
OVER: MOV DX,BX ;Find position in buffer from BX
|
||||
ADD DX,2 ;Move to next position for this word
|
||||
CMP DX,OFFSET BUFFER_END ;Are we past the end?
|
||||
JL NO_WRAP4 ;No, don't wrap
|
||||
MOV DX,OFFSET BUFFER ;Do the Wrap rap.
|
||||
NO_WRAP4:
|
||||
CMP DX,HEAD ;Buffer full but not yet done?
|
||||
JE BUFFER_FULL2 ;Time to leave, come back later.
|
||||
ADD COMMAND_INDEX,2 ;Point to next word of command.
|
||||
MOV [BX],AX ;Put into buffer
|
||||
ADD BX,2 ;Point to next space in buffer
|
||||
CMP BX,OFFSET BUFFER_END ;Wrap here?
|
||||
JL NO_WRAP5 ;No, readjust buffer tail
|
||||
MOV BX,OFFSET BUFFER ;Yes, wrap
|
||||
NO_WRAP5:
|
||||
MOV TAIL,BX ;Reset buffer tail
|
||||
JMP STUFF2 ;Back to stuff in another character
|
||||
BUFFER_FULL2:
|
||||
MOV FINISHED_FLAG,0 ;Set flag to not-done-yet.
|
||||
NO_NEW_CHARACTERS2:
|
||||
POP AX ;Restore these.
|
||||
POP BX
|
||||
POP DX
|
||||
POP SI
|
||||
POP DS
|
||||
OUT1: POPF ;And Exit.
|
||||
POP DS
|
||||
IRET ;With customary IRET
|
||||
INTERCEPT_TIMER ENDP
|
||||
|
||||
LOAD_KEEPER PROC NEAR ;This procedure intializes everything
|
||||
ASSUME DS:VECTORS ;The data segment will be the Interrupt area
|
||||
MOV AX,VECTORS
|
||||
MOV DS,AX
|
||||
|
||||
MOV AX,KEYBOARD_INT ;Get the old interrupt service routine
|
||||
MOV OLD_KEYBOARD_INT,AX ;address and put it into our location
|
||||
MOV AX,KEYBOARD_INT[2] ;OLD_KEYBOARD_INT so we can call it.
|
||||
MOV OLD_KEYBOARD_INT[2],AX
|
||||
|
||||
MOV KEYBOARD_INT,OFFSET KEEPER ;Now load the address of our notepad
|
||||
MOV KEYBOARD_INT[2],CS ;routine into the keyboard interrupt
|
||||
|
||||
MOV AX,TIMER_VECTOR ;Now same for timer
|
||||
MOV ROM_TIMER,AX
|
||||
MOV AX,TIMER_VECTOR[2]
|
||||
MOV ROM_TIMER[2],AX
|
||||
|
||||
MOV TIMER_VECTOR,OFFSET INTERCEPT_TIMER
|
||||
MOV TIMER_VECTOR[2],CS ;And intercept that too.
|
||||
|
||||
ASSUME DS:ROM_BIOS_DATA
|
||||
MOV AX,ROM_BIOS_DATA
|
||||
MOV DS,AX
|
||||
MOV BX,OFFSET BUFFER ;Clear the keyboard buffer.
|
||||
MOV HEAD,BX
|
||||
MOV TAIL,BX
|
||||
MOV AH,15 ;Ask for service 15 of INT 10H
|
||||
INT 10H ;This tells us how display is set up
|
||||
MOV STATUS_PORT,03BAH ;Assume this is a monochrome display
|
||||
TEST AL,4 ;Is it?
|
||||
JNZ EXIT ;Yes - jump out
|
||||
MOV SCREEN_SEG_OFFSET,8000H ;No - set up for graphics display
|
||||
MOV STATUS_PORT,03DAH
|
||||
|
||||
EXIT: MOV DX,OFFSET LOAD_KEEPER ;Set up everything but LOAD_PAD to
|
||||
INT 27H ;stay and attach itself to DOS
|
||||
LOAD_KEEPER ENDP
|
||||
|
||||
CODE_SEG ENDS
|
||||
|
||||
END FIRST ;END "FIRST" so 8088 will go to FIRST first.
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user