Category : Assembly Language Source Code
Archive   : ASM2.ZIP
Filename : ONEKEY.ASM

 
Output of file : ONEKEY.ASM contained in archive : ASM2.ZIP
VECTORS SEGMENT AT 0H ;Set up segment to intercept Interrupts
ORG 9H*4 ;The keyboard Interrupt
KEYBOARD_INT_VECTOR LABEL DWORD
ORG 1CH*4 ;Timer Interrupt
TIMER_VECTOR LABEL DWORD
VECTORS ENDS

ROM_BIOS_DATA SEGMENT AT 40H ;The ROM BIOS data area in low memory
ORG 1AH ;This is where the keyboard buffer is.
ROM_BUFFER_HEAD DW ? ;The position of the buffer's head
ROM_BUFFER_TAIL DW ? ;And tail.
KB_BUFFER DW 16 DUP (?) ;Reserve space for the buffer itself
KB_BUFFER_END LABEL WORD ;Buffer's end is stored here.
ROM_BIOS_DATA ENDS

CODE_SEG SEGMENT ;Begin the Code segment holding the programs
ASSUME CS:CODE_SEG
ORG 100H ;Com files start at ORG 100H
BEGIN: JMP INIT_VECTORS ;Skip over data area

COPY_RIGHT DB '(C) 1984 S. Holzner' ;The Author's signature
KEYS DW 30 DUP(0) ;The keys we replace
FINISHED_FLAG DB 1 ;If not finished, timer will stuff buffer
COMMANDS DW 1530 DUP(0) ;Scan and ASCII codes of commands
COMMAND_INDEX DW 1 ;Stores position in command (for timer)
ROM_KEYBOARD_INT DD 1 ;Called to interpret keyboard signals
ROM_TIMER DD 1 ;The Timer interrupt's address

INTERCEPT_KEYBOARD_INT PROC NEAR ;Here it is.
ASSUME DS:NOTHING ;Free DS
PUSH DS ;Save all used registers
PUSH SI
PUSH DI
PUSH DX
PUSH CX
PUSH BX
PUSH AX
PUSHF ;Pushf for Keyboard Int's IRET
CALL ROM_KEYBOARD_INT ;Have new key put into keyboard buffer
ASSUME DS:ROM_BIOS_DATA ;Set up to point at keyboard buffer.
MOV AX,ROM_BIOS_DATA
MOV DS,AX

MOV BX,ROM_BUFFER_TAIL ;Was there a character? If Tail equals
CMP BX,ROM_BUFFER_HEAD ; Head then no real character typed.
JNE NEWCHAR
JMP NO_NEW_CHARACTERS ;Jump out, no new characters.
NEWCHAR:SUB BX,2 ;Move back two bytes from tail;
CMP BX,OFFSET KB_BUFFER ;Do we have to wrap?
JAE NO_WRAP ;No
MOV BX,OFFSET KB_BUFFER_END ;Wrap by moving two bytes
SUB BX,2 ; before buffer end.
NO_WRAP:MOV AX,[BX] ;Get the character into AX

CMP FINISHED_FLAG,1 ;Done stuffing the buffer with last command?
JE FIN ;Yes, proceed
JMP NO_NEW_CHARACTERS ;No, leave.

FIN: MOV FINISHED_FLAG,1 ;Assume we'll finish

LEA SI,KEYS ;Point source index at keys to replace
MOV CX,30 ;Loop over all of them
LOOPER: CMP AX,CS:[SI] ;Match to given key (in AX)?
JE FOUND ;Yes, key found, continue on.
ADD SI,2 ;Point to next key to check it.
LOOP LOOPER ;Go back for next one.
JMP NO_NEW_CHARACTERS ;Loop finished without match - leave.

FOUND: CLI ;Turn off hardware (timer, keyboard) Interrupts
LEA SI,COMMANDS ;Set up to read command
NEG CX ;Find the location of first word of command
ADD CX,30
MOV AX,CX
MOV CX,102
MUL CL
ADD SI,AX
MOV COMMAND_INDEX,SI ;And move it into Command_Index

STUFF: MOV AX,CS:[SI] ;Here we go - get ready to stuff word in buffer.
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 KB_BUFFER_END ;Are we past the end?
JL NO_WRAP2 ;No, don't wrap
MOV DX,OFFSET KB_BUFFER ;Wrap
NO_WRAP2:
CMP DX,ROM_BUFFER_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 KB_BUFFER_END ;Wrap here?
JL NO_WRAP3 ;No, readjust buffer tail
MOV BX,OFFSET KB_BUFFER ;Yes, wrap
NO_WRAP3:
MOV ROM_BUFFER_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
IRET ;An interrupt deserves an IRET
INTERCEPT_KEYBOARD_INT 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 OUT ;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,ROM_BUFFER_TAIL ;Prepare to put charaters in at tail
MOV FINISHED_FLAG,1 ;Assume we'll finish
MOV SI,COMMAND_INDEX ;Find where we left ourselves

STUFF2: MOV AX,CS:[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 KB_BUFFER_END ;Are we past the end?
JL NO_WRAP4 ;No, don't wrap
MOV DX,OFFSET KB_BUFFER ;Do the Wrap rap.
NO_WRAP4:
CMP DX,ROM_BUFFER_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 KB_BUFFER_END ;Wrap here?
JL NO_WRAP5 ;No, readjust buffer tail
MOV BX,OFFSET KB_BUFFER ;Yes, wrap
NO_WRAP5:
MOV ROM_BUFFER_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
OUT: POPF ;And Exit.
POP DS
IRET ;With customary IRET
INTERCEPT_TIMER ENDP

INIT_VECTORS PROC NEAR ;Rest Interrupt vectors here
ASSUME DS:VECTORS
PUSH DS
MOV AX,VECTORS
MOV DS,AX
CLI ;Don't allow interrupts
MOV AX,KEYBOARD_INT_VECTOR ;Get and store old interrupt address
MOV ROM_KEYBOARD_INT,AX
MOV AX,KEYBOARD_INT_VECTOR[2]
MOV ROM_KEYBOARD_INT[2],AX

MOV KEYBOARD_INT_VECTOR,OFFSET INTERCEPT_KEYBOARD_INT
MOV KEYBOARD_INT_VECTOR[2],CS ;And put ours in place.
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.
STI
ASSUME DS:ROM_BIOS_DATA
MOV AX,ROM_BIOS_DATA
MOV DS,AX
MOV BX,OFFSET KB_BUFFER ;Clear the keyboard buffer.
MOV ROM_BUFFER_HEAD,BX
MOV ROM_BUFFER_TAIL,BX
MOV DX,OFFSET INIT_VECTORS ;Prepare to attach in memory
INT 27H ;And do so.
INIT_VECTORS ENDP
CODE_SEG ENDS
END BEGIN ;End Begin so that we jump there first.


  3 Responses to “Category : Assembly Language Source Code
Archive   : ASM2.ZIP
Filename : ONEKEY.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/