MalwareSourceCode/MSDOS/N-Index/Virus.MSDOS.Unknown.npad.asm
vxunderground 4b9382ddbc re-organize
push
2022-08-21 04:07:57 -05:00

271 lines
13 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

INTERRUPTS SEGMENT AT 0H ;This is where the keyboard interrupt
ORG 9H*4 ;holds the address of its service routine
KEYBOARD_INT LABEL DWORD
INTERRUPTS 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_PAD ;First time through jump to initialize routine
CNTRL_N_FLAG DW 0 ;Cntrl-N on or off
PAD DB '_',499 DUP(' ') ;Memory storage for pad
PAD_CURSOR DW 0 ;Current position in pad
PAD_OFFSET DW 0 ;Chooses 1st 250 bytes or 2nd
FIRST_POSITION DW ? ;Position of 1st char on screen
ATTRIBUTE DB 112 ;Pad Attribute -- reverse video
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
N_PAD 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 IN ;So leave
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
CMP DX,310EH ;Is the char a Cntrl-N?
JNE NOT_CNTRL_N ;No
MOV TAIL,BX ;Yes -- delete it from buffer
NOT CNTRL_N_FLAG ;Switch Modes
CMP CNTRL_N_FLAG,0 ;Cntrl-N off?
JNE CNTRL_N_ON ;No, only other choice is on
CNTRL_N_OFF:
MOV ATTRIBUTE,7 ;Set up for normal video
MOV PAD_OFFSET,250 ;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
IN: JMP OUT ;Done
CNTRL_N_ON:
MOV PAD_OFFSET,250 ;Point to screen stroage 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_CNTRL_N:
TEST CNTRL_N_FLAG,1 ;Is Cntrl-N on?
JZ IN ;No -- leave
MOV TAIL,BX ;Yes, delete this char from buffer
CMP DX,5300H ;Decide what to do -- is it a Delete?
JNE RUBOUT_TEST ;No -- try Rubout
MOV BX,249 ;Yes -- fill pad with spaces
DEL_LOOP:
MOV PAD[BX],' ' ;Move space to current pad position
DEC BX ;and go back one
JNZ DEL_LOOP ;until done.
MOV PAD,'_' ;Put the cursor at the beginning
MOV PAD_CURSOR,0 ;And start cursor over
CALL DISPLAY ;Put up the new pad on screen
JMP OUT ;And take our leave
RUBOUT_TEST:
CMP DX,0E08H ;Is it a Rubout?
JNE CRLF_TEST ;No -- try carriage return-line feed
MOV BX,PAD_CURSOR ;Yes -- get current pad location
CMP BX,0 ;Are we at beginning?
JLE NEVER_MIND ;Yes -- can't rubout past beginning
MOV PAD[BX],' ' ;No -- move space to current position
MOV PAD[BX-1],'_' ;And move cursor back one
DEC PAD_CURSOR ;Set the pad location straight
NEVER_MIND:
CALL DISPLAY ;And put the result on the screen
JMP OUT ;Done here.
CRLF_TEST:
CMP DX,1C0DH ;Is it a carriage return-line feed?
JNE CHAR_TEST ;No -- put it in the pad
CALL CRLF ;Yes -- move to next line
CALL DISPLAY ;And display result on screen
JMP OUT ;Done.
CHAR_TEST:
MOV BX,PAD_CURSOR ;Get current pad location
CMP BX,249 ;Are we past the end of the pad?
JGE PAST_END ;Yes -- throw away char
MOV PAD[BX],DL ;No -- move ASCII code into pad
MOV PAD[BX+1],'_' ;Advance cursor
INC PAD_CURSOR ;Increment pad location
PAST_END:
CALL DISPLAY ;Put result on screen
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
N_PAD ENDP
DISPLAY PROC NEAR ;Puts the whole pad on the screen
PUSH AX
MOV ATTRIBUTE,112 ;Use reverse video
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
CMP PAD_CURSOR,225 ;Are we on last line?
JGE DONE ;Yes, can't do a carriage return, exit
NEXT_CHAR:
MOV BX,PAD_CURSOR ;Get pad location
MOV AX,BX ;Get another copy for destructive tests
EDGE_TEST:
CMP AX,24 ;Are we at the edge of the pad display?
JE AT_EDGE ;Yes -- fill pad with new cursor
JL ADD_SPACE ;No -- Advance another space
SUB AX,25 ;Subtract another line-width
JMP EDGE_TEST ;Check if at edge now
ADD_SPACE:
MOV PAD[BX],' ' ;Add a space
INC PAD_CURSOR ;Update pad location
JMP NEXT_CHAR ;Check if at edge now
AT_EDGE:
MOV PAD[BX+1],'_' ;Put cursor in next location
INC PAD_CURSOR ;Update pad location to new cursor
DONE: RET ;And out.
CRLF ENDP
GET_CHAR PROC NEAR ;Gets a char from screen and advances position
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: INC BX ;Update pad location
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
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
INC BX ;Point to next char in pad
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
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:
MOV DX,25 ;And 25 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
LOOP LINE_LOOP ;And now go back to do next line
RET ;Finished
IO ENDP
LOAD_PAD PROC NEAR ;This procedure intializes everything
ASSUME DS:INTERRUPTS ;The data segment will be the Interrupt area
MOV AX,INTERRUPTS
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 N_PAD ;Now load the address of our notepad
MOV KEYBOARD_INT[2],CS ;routine into the keyboard interrupt
MOV AH,15 ;Ask for service 15 of INT 10H
INT 10H ;This tells us how display is set up
SUB AH,25 ;Move to twenty places before edge
SHL AH,1 ;Mult by two (char & attribute bytes)
MOV BYTE PTR FIRST_POSITION,AH ;Set screen cursor
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_PAD ;Set up everything but LOAD_PAD to
INT 27H ;stay and attach itself to DOS
LOAD_PAD ENDP
CODE_SEG ENDS
END FIRST ;END "FIRST" so 8088 will go to FIRST first.