[comp.sys.ibm.pc] Keyboard "fix" TSRs

AHS%psuvm.bitnet@rutgers.edu (06/19/88)

Tom Almy, toma@tekgvs.TEK.COM, writes of his set of KBD*.com programs:

        All of these [AT only] programs were written by me, using the CFORTH
        Forth Compiler, and are placed in public domain for the benefit of
        other PC users who are frustrated with these keyboard designs.

        I am not supplying sources, the programs are small enough that DEBUG
        can be used to reverse-engineer them.

        Tom Almy
        toma@tekgvs.TEK.COM
-----------------------------------


I attempted a dissassembly of:

         KBDL     COM      332   6-15-88   7:03a

I include the dissassembly below.  The dissassembled code is logically
consistent in its jumps, calls, reads, and writes, but is very strange.  The
resulting flow is very simple, yet this dissassembled code is so strange that I
wonder.....  Further, the file KBDL.COM contains several CD 21 op-codes but
contains *no* CD 27 or CD 31 op-codes which are *necessary* to terminate and
stay resident.  Is it Forth, is it Almy, is it me.....  I don't know, I don't
have an AT to try it (if I would still dare try it).



TITLE   KBDL

RET_NEAR MACRO
DB	0C3H
ENDM

.RADIX	16


S0000	SEGMENT
	ASSUME DS:S0000, SS:S0000 ,CS:S0000 ,ES:S0000
        ORG     0100H


L0100:  JMP     L010B

;The following DB are bytes unused by the program
        DB      4C,2

L0105   DW      0000

L0107   DW      0000,000A

L010B:  MOV     SP, FF9A
        MOV     WORD PTR L0105, FF98
        MOV     BP, FFFE
        MOV     L0107,BP
        CLD
        CALL    L017F
        MOV     AX, 4C00   ;Terminate *normally* with exit code of 00
        INT     21

;The following DB's are bytes unused by the program
        DW      L0000
        DW      L0000
        DB      80,0FC,4F,75,2DH
        DB      3C,3A,75,1A,6
        DB      2E,8E,6,7E,0
        DB      26,0F6,6,17,4
        DB      2,75,2,0B0,1DH
        DB      0A2,7DH,0,7,0F9
        DB      2E,0FF,2E,80,0
        DB      3C,0BA,75,0BH,0A0
        DB      7DH,0,4,80,0F9
        DB      2E,0FF,2E,80,0
        DB      0F9,2E,0FF,2E,80
        DB      0,5E,58,5A,5BH
        DB      1E,8E,0DBH,0B4,25
        DB      0CDH,21,1F,0FF,0E6
        DB      0B4,35,0CDH,21,89
        DB      0D8,8C,2 DUP(0C3),0BA
        DB      0C,0,0B8,0,31
        DB      0CDH,21

L017F:  CALL    L01FE

;The following DB's are bytes unused by the program
        DB      33,43,41,50,53
        DB      4C,4F,43,4BH,20
        DB      2DH,3E,20,43,54
        DB      52,4C,2C,2 DUP(20),4C
        DB      45,46,54,53,48
        DB      49,46,54,20,2BH
        DB      20,43,41,50,53
        DB      4C,4F,43,4BH,20
        DB      2DH,3E,20,43,41
        DB      50
        DB      53,4C,4F,43,4BH
        DB      0E8,57,0,0E8,42
        DB      0
        DB      0BH,42,79,20,54
        DB      6F,6DH,20,41,6C
        DB      6DH,79,0E8,45,0
        DB      0C7,6,7E,0
        DW      L0000
        DB      0B8,15,0,0E8,97
        DB      0FF,0A3,24,1,89
        DB      1E,26,1,0BA,24
        DB      1,52,0BA,80,0
        DB      52,0BA,3C,0,52
        DB      0E8,51,0,8C,0C8
        DB      50,0BA,84,0,52
        DB      0BA,15,0,52,0E8
        DB      65,0FF,0E9,79,0FF

L01FE:  POP     BX
        MOV     AL,[BX]
        XOR     AH,AH
        INC     BX
        PUSH    BX
        PUSH    AX
        ADD     BX,AX
        POP     AX
        POP     DX
        PUSH    BX
        MOV     BX,DX
        JMP     L0231

;The following DB's are bytes unused by the program
        DB      0B8,0DH,0,0E8,9
        DB      0,0B8,0A,0,0E9
        DB      3,0


L021C   DB      1,2 DUP(0)

;The following DB's are bytes unused by the program
        DB      0A2
        DB      1E,2,0B4,40,0B9
        DB      1,0,0BA,1E,2
        DB      8BH,1E,1C,2,0CDH
        DB      21,0C3

L0231:  MOV     CX,AX
        MOV     DX,BX
        MOV     BX,L021C
        MOV     AH,40      ;Write to device having the handle 0100
        INT     21
        RET_NEAR

;The following DB's are bytes unused by the program
        DB      5BH,59,5F,5E,0E3
        DB      6,8C,0D8,8E,0C0
        DB      0F3,0A4,0FF,0E3

	S0000	ENDS
;
END	L0100

--end

AHS@PSUVM.BITNET (06/23/88)

In the article:  From: toma@tekgvs.TEK.COM (Tom Almy)
                 Date: 21 Jun 88 15:50:53 GMT
Tom replies:
>In article <8806190331.AA02653@slvblc.UUCP> AHS%psuvm.bitnet@rutgers.edu writes:
>>Tom Almy, toma@tekgvs.TEK.COM, writes of his set of KBD*.com programs:
>>
><        All of these [AT only] programs were written by me, using the CFORTH
><        Forth Compiler, and are placed in public domain for the benefit of
><        other PC users who are frustrated with these keyboard designs.
>>
><        I am not supplying sources, the programs are small enough that DEBUG
><        can be used to reverse-engineer them.
>>
>>I attempted a dissassembly of:
>>
><         KBDL     COM      332   6-15-88   7:03a
>>
>>I include the dissassembly below.  The dissassembled code is logically
>>consistent in its jumps, calls, reads, and writes, but is very strange.  The
>>resulting flow is very simple, yet this dissassembled code is so strange that I
>>wonder.....  Further, the file KBDL.COM contains several CD 21 op-codes but
>>contains *no* CD 27 or CD 31 op-codes which are *necessary* to terminate and
>>stay resident.  Is it Forth, is it Almy, is it me.....  I don't know, I don't
>>have an AT to try it (if I would still dare try it).
>
>Well, what it is is the disassembler you used!   That's why I said "DEBUG can
>be used".  The sequence
>        MOV DX, 0CH
>        MOV AX, 3100H
>        INT 21H
>exists, as part of:


                Yes, I saw these opcodes.  I list that dissassembly in one
                of my two subsequent postings on comp.binaries.ibm.pc .

                Now you said debug "can be used", you did not say "must be
                used".  Further you did not say that using debug's "U"
                command would not be enough to Unassemble the code.

                Should you have said "debug's Trace command *must* be used,
                and better watch the stack after making a call and before
                returning to that call"?.


>>;The following DB are bytes unused by the program
>....
><        DB      [...],0BA
><        DB      0C,0,0B8,0,31
><        DB      0CDH,21
>>
>>L017F:  CALL    L01FE
>
>The disassembler failed to see most of the code, because of some
>assumptions it made.


                *I* made the assumptions, not the machine, when I saw what
                followed the CALL L01FE.  In my third posting, I show in
                detail why I made those assumptions.


>                      For instance, this call is followed by by about
>50 bytes of "unused by the program", but it is!  There are few data areas,
>and some ASCII strings are embedded in the code (such as immediately after
>the above CALL L01FE).  The subroutine pops the return address into a register,
>increments through the string, and pushes the now correct return address back
>on the stack, before eventually returning.

                Please explain why you make a CALL (which means: "After
                completing the call, I want to resume execution at the line
                that follows the call"), and then play with the stack so
                that execution will *not* resume at the line following the
                call?.  Why?.  Why not use JMP?; it would be
                straighforward.

                The only reason I know for (1) destroying (in the stack)
                the normal return address of a CALL, and (2) filling the
                lines that follow the CALL with non-code (either garbage,
                or a data-area, or text) is to foil dissassembly.  Was this
                you purpose?.  If not, what was your purpose in destroying
                the normal return address of the call?.


>This program does work as advertised!

                Prove it.  Publish the correct symbolic dissassembly.  I am
                not going to load in my machine routines that deeply alter
                its guts without looking at the code first.

>Tom Almy
>toma@tekgvs.TEK.COM
>
---------------------------------------------------------------

velte@mimsy.UUCP (Jack Velte) (06/24/88)

I am running the keyboard fix routines.  One of them, anyway.  It turns
the cap's lock key into another control key.  The 101 keyboard is now
usable with emacs.  Thanks very much, Tom Alvy!
-- 
Jack Velte @ University of MD
domain:	velte@mimsy.umd.edu	path: seismo!mimsy!velte

rusty@cadnetix.COM (Rusty) (06/30/88)

In a series of articles AHS%psuvm.bitnet@rutgers.edu and toma@tekgvs.TEK.COM (Tom Almy)
have a 'discussion' (near flame-war) about Tom's code.

Well, folks, welcome to Forth.  Just about the only ways to pass things around
in forth are
	1) pass it on the (computation) stack
	2) pass it following the 'call' to the routine
		(an example of this is the doconst, dovar, etc words used
		when making your own constants, as is the <BUILDS ... DOES>
		pair for compiling words, as well as ." (print a string)).
I will NOT go into a remedial course on forth and TIL (or even Threaded compiled
languages, if such a thing exists), suffice it to say that the structure of
forth makes dissasembly somewhat less than helpful.  Fortunately for those
trying to look at Tom's code, a lot of the thread has been un-threaded.  Otherwise
you would see something like:

L123:  <some code fooling with the stack>
	jmp <indirect somewhere>  (or, even better, a return)

	Data, routine1
	data, routine2  ; or whatever your favorite assembler structure.
	data, routine3

routine1: data, routine2
	data, routine1
	data, routine8
	data,routine3

routine2: <and so forth (no pun intended)>

Isn't TIL FUN?




    Rusty Carruth	N7IKQ	DOMAIN: rusty@cadnetix.com
    Cadnetix Corp.		UUCP:   cadnetix!rusty
    5775 Flatiron Pkwy.	        	{uunet,boulder,nbires}!cadnetix!rusty
    Boulder, CO 80301		(303) 444-8075