Jim Lawless' Blog


Checking Shift States with DEBUG

Originally published on: Wed, 29 Jul 2009 01:03:48 +0000

This post is one in a series of "by popular demand" posts ... that is to say, posts based on search criteria that has led people to my blog due to false positives by the given search engine.

Over the course of the last month, I've seen the following items show up in the search terms section of my blog statistics reports:

dos batch file detect scroll lock dos call for caps lock debug .com to check scroll lock

The search terms probably matched against my post Safe Scripting with Scroll Lock and Caps Lock, which provides WIN32 API code in C to check the shift-state of either the Scroll Lock or Caps Lock keys.

The above three searches are specifically looking for MS-DOS versions of the utility. Okay, some folks use 16-bit DOS utilities in 32-bit console scripts, but I thought I'd take the opportunity to rebuild an old utility or two to check for the same two shift-keys using the DOS DEBUG.COM utility to assemble them.

All code entered in DEBUG in this example and the sample batch file is free to you to use as you wish, but I accept no liability from your use ( or misuse ) of the code. Please note that this code may or may not function correctly in an emulated MS-DOS session. The code presented works in a COMMAND.COM window and cmd.exe in Windows XP ( via the 16-bit subsystem ) on my machine and should work on most versions of MS-DOS 3.x or above.

DEBUG.COM is a nifty little utility that allows one to debug and diagnose machine code either in DOS EXE or DOS COM files. It has a built-in mini-assembler and was often used to provide little type-in utilities in magazines in the late 80's and early 90's before BBS's and online services made finding and downloading ready-to-run code much easier.

Let's just try and write a simple little COM file program with DEBUG. From a cmd.exe or COMMAND.COM prompt type:

debug

You should see a "-" ( dash ) for a prompt. At the dash prompt, type the following:

a 100 mov dl,41 mov ah,2 int 21 mov ax,4c00 int 21

rcx b n print_a.com w q

Make sure you enter a blank line after the INT 21. So, with responses from DEBUG, that whole session might look like this ( with prompts and responses from DEBUG in red font ):

debug -a 100 0AF2:0100 mov dl,41 0AF2:0102 mov ah,2 0AF2:0104 int 21 0AF2:0106 mov ax,4c00 0AF2:0109 int 21 0AF2:010B -rcx CX 0000 :b -n print_a.com -w Writing 0000B bytes -q

Now, from your command prompt, type

print_a

An upper-case letter 'A' should appear.

In the above example, we used DEBUG to write a small, eleven-byte program called PRINT_A.COM. The first three lines load the DL register with the value of the character we'd like to display ( a 41h or 41 in hexadecimal is an upper-case 'A' in ASCII ), we load the AH register with MS-DOS INT 21h function 2 ( display the character in DL ) and then invoke interrupt 21h. The next two lines load AH with function 4Ch ( terminate process ) and AL with the return-code ( zero, in this case ). A final call to INT 21h terminates the little program.

The other items we type are commands to the DEBUG utility.

The a command tells debug to go into mini-assembler mode. This causes DEBUG to prompt us for input that will be assembled at the displayed address. COM files always begin their execution at offset address 100h, so we begin our assembly there.

When we're done typing in assembly commands we hit ENTER and return to the dash prompt. We typed rcx at this prompt to allow us to edit the value of the CX register, which debug uses to determine how many bytes to write out once we ask it to write a file.

We enter b since that is the first unused address minus 100h in our code. That tells us that our code that occupies 100h - 10Ah is 0Bh ( or eleven ) bytes long.

We now have to tell DEBUG what to call our COM file, so we use n, the "name" command. We tell DEBUG that we want to write a file called print_a.com.

Then, we tell DEBUG to write the file with the w command ... which writes all of the data from 100h to 10Ah. The start address for the write begins with the value in the IP register, which is set to 100h as a default when one invokes DEBUG.

Now, let's write a couple of utilities via DEBUG that will check the state of the Caps Lock and Scroll Lock keys respectively and will terminate with an ERRORLEVEL 1 ( via INT 21h function 4Ch ) if the specific key has been activated and we are in that shift-state.

In pre-Windows Intel machines, the BIOS ( Basic Input/Output Subsystem ) routines that fetch keystrokes use an area at segment address 40h, offset address 17h.

Invoke DEBUG and at the dash prompt, type d 40:17 17 If all of your shift-keys are not active, you should see two '0' digits.

Now, hit the Caps Lock key and do the same thing. You should now see '40'.

Hit the Scroll Lock key. You should see '50' because you still have Caps Lock on. Turn Caps Lock off by hitting the Caps Lock key and display the byte again. You should now see '10'.

So, if we number the bits in the byte at 0040:0017, from the left beginning with 7 down to 0, bit 6 is on ( 40h ) when Caps Lock is enabled and bit 4 is on ( 10h ) when Scroll Lock is enabled.

We'll now write a couple of quick MS-DOS COM file programs with DEBUG to check each state and return a 1 if the key is "on" or 0 if it is off. By terminating using INT 21h function 4Ch, the value in AL moves to the batch file ERRORLEVEL variable.

So, let's create CHEKCAPS.COM:

-a 100 0AF2:0100 mov ax,0040 0AF2:0103 push ax 0AF2:0104 pop ds 0AF2:0105 mov al,[17] 0AF2:0108 and al,40 0AF2:010A shr al,1 0AF2:010C shr al,1 0AF2:010E shr al,1 0AF2:0110 shr al,1 0AF2:0112 shr al,1 0AF2:0114 shr al,1 0AF2:0116 mov ah,4c 0AF2:0118 int 21 0AF2:011A -rcx CX 0000 :1a -n CHEKCAPS.COM -w Writing 0001A bytes -q

The above code moves the byte at 0040:0017 into AL, masks it with a bitwise AND so that only bit 6 will be kept. Then we shift AL right six bits and use that value as the ERRORLEVEL. We'll do something similar for the Scroll Lock key, but will only have to shift four bits to the right since the bit flag for it is further to the right in the byte at 0040:0017.

Here is the code for CHEKSCRL.COM -a 100 0AF2:0100 mov ax,0040 0AF2:0103 push ax 0AF2:0104 pop ds 0AF2:0105 mov al,[17] 0AF2:0108 and al,10 0AF2:010A shr al,1 0AF2:010C shr al,1 0AF2:010E shr al,1 0AF2:0110 shr al,1 0AF2:0112 mov ah,4c 0AF2:0114 int 21 0AF2:0116 -rcx CX 0000 :16 -n CHEKSCRL.COM -w Writing 00016 bytes -q

Here's a quick batch file that will loop continously, waiting for you to press ENTER after each cycle. It will call the above two utilities and will display the current shift-states for the Scroll Lock and Caps Lock keys.

@ECHO OFF :TOP CHEKCAPS IF ERRORLEVEL 1 GOTO CAPSYES ECHO Caps Lock is OFF. GOTO SCROLLKEY :CAPSYES ECHO Caps Lock is ON.

:SCROLLKEY CHEKSCRL IF ERRORLEVEL 1 GOTO SCROLLYES Echo Scroll Lock is OFF. GOTO ALLDONE :SCROLLYES ECHO Scroll Lock is ON.

:ALLDONE PAUSE GOTO TOP

To run the sample batch file, save it as TESTER.BAT and type TESTER from a command prompt.

Unless otherwise noted, all code and text entries are Copyright ©2009 by James K. Lawless

del_icio_us Save to del.icio.us
stumbleupon Save to StumbleUpon
digg Digg it
reddit Save to Reddit
facebook Share on Facebook
twitter Share on Twitter
aolfav More bookmarks



Previous post: Blog Posts by Category
Next post:A Command-Line MP3 Player for Windows


Search this Blog (and site)

Search this Site with PicoSearch


Subscribe to this Blog

 Subscribe!


Contact Me

Email: jimbo@radiks.net


Follow me on Twitter

http://twitter.com/lawlessGuy


Recent Posts

Mad Schemes : Learning Lisp via SICP

Auto Save Clipboard Images Redux

Extending SpiderMonkey JavaScript on Windows

Rhino JavaScript to EXE with launch4j

Compiling Rhino JavaScript to Java

Directory Traversal in Rhino JavaScript

Taking Shape

We've Moved!


Popular Posts

A Command-Line MP3 Player for Windows

Auto Save Images from the Clipboard

Java in a Windows EXE with launch4j

An Interview with Tom Zimmer: Forth System Developer

Setting Windows Console Text Colors in C


Random Posts

Hiding Batch File Console Windows

TAP : A Command Processor Library

JRuby as a Java Obfuscation Utility

Generating Primes with XSLT

Getting the Windows Console Text Color

Speeding up JRuby with NailGun

Switching a Console Window to Full Screen or Windowed Mode

Along Came AWK

Preserving my Favorite HN Links

Obfuscated Ruby


Full List of Posts

http://www.mailsend-online.com/bloglist.htm


Blogroll

MicroISV on a Shoestring
DadHacker
The Bottom Feeder
Writin' That Code!
The Recursive ISV
The Thomsen Blog
Prototypically Speaking
The Reinvigorated Programmer