Thursday, February 23, 2006

Asm: Retrieve 3 Key Strokes And Display The Results

I have always been a big fan of assembly language. I miss the days of DOS where you could code little assembly applications and kind of grin at the prestige of being able to code in Assembler. A lot of people will give you all sorts of arguments as to why ASM is better than high level languages, or that there is no need for ASM anymore due to optimizing compilers, etc. I don’t really have a great technical argument for or against, I have just always liked assembly programming, and that’s not about to change. I have tried assembly programming both under Windows and Linux, but it’s just not the same as the good old days of DOS assembly programming. So I jumped at the chance to take an assembly course, although it is a little outdated material, if for nothing else than to work out the problems.

One of the problems I had to work on asked that we write a program that takes three characters from the keyboard, store them at location DS:200H, then output them using DOS interrupt 09H. They wanted it done in debug, and you would have to go back and edit the memory location at DS:204H to put in the necessary $ to terminate the string for the DOS interrupt. Balls to that I said, I prefer my programs to be standalone and able to be run from the command prompt. Below is the code for that program. To enter it and try it yourself, go to the DOS prompt and type in “debug keybrd1.com”, where keybrd1.com is the name of the COM file we will create for this program. Type in “a” and hit enter. Then enter the following code sequence below:

MOV     CX,0003
MOV     BX,0200
MOV     AH,10
INT     16
MOV     [BX],AL
INC     BX
LOOP    0106
MOV     AL,24
MOV     [BX],AL
MOV     AH,09
MOV     DX,0200
INT     21
MOV     AX,4C00
INT     21

Hit enter one more time. Then type in “r cx”. Once the prompt comes up, type “1F”. Then type “W”. You now have an executable COM file called keybrd1.com. Type “Q” to go back to the DOS prompt. Now run keybrd1.com. There are no prompts, so just hit 3 keys. They will be echoed back to you. Lets go through step-by-step how this program works.

MOV     CX,0003
MOV     BX,0200

These lines are initializing my registers for my internal loop. In this case, CX is storing the number of iterations the loop will run, and BX is storing the offset from DS to store the incoming characters. Since this is a COM program, the Stack Segment, Code Segment, Data Segment, and Extra Segment all reside in the same location, so we do not need to worry about Pushing or Popping those values.

MOV     AH,10
INT     16
MOV     [BX],AL

This is calling an interrupt to retrieve data from the keyboard. If there is no data ready, it will wait until a key is pressed. Once the interrupt is complete, the value of the key is stored in register AL. We then move that value to the memory location pointed to by register BX (which is why we have brackets around it).

INC     BX
LOOP    0106

We are now incrementing the BX register by 1 in order to point to the next memory location. By calling LOOP, we auto decrement CX by 1. If CX is zero, the next line is executed; otherwise we loop to the location indicated (in this case 106, or the MOV AH, 10 line).

MOV     AL,24
MOV     [BX],AL

This is doing some cleanup after out loop so that we can call the DOS interrupt for screen output. We are moving a “$” (ASCII value 24h) to the memory location just after our 3 stored key presses. BX is already pointing to this since we incremented on the last loop iteration.

MOV     AH,09
MOV     DX,0200
INT     21

Here, we are calling the DOS interrupt for screen output, using the string at DS:200h as the output, which is terminated by a “$”.

MOV     AX,4C00
INT     21

And now we are exiting the program and returning control to DOS. There is a lot going on here for a program that is only 38 Bytes. Although the equivalent program in C or C++ would be easier to understand and take less time and thought to code, there is just something cool about coding in ASM.

Of course, you could alternatively write the same program as follows:

-From DOS, type “debug keybrd1.com”
-Type “e CS:100”
-Enter “B9 03 00 BB 00 02 B4 10 CD 16 88 07 43 E2 F7 B0 24 88 07 B4 09 BA 00 02 CD 21 B8 00 4C CD 21”. Note the spaces between each Bytes. These are necessary. If you hit Enter, you will close out the memory edit mode in debug.
-Hit enter when you are done.
-Type “r CX”
-Type “1F”
-Type “w”
-Type “q”

This demonstrates entering programs as low level as possible without actually doing it in binary. Entering programs in this manner requires quite a bit of knowledge of the internal CPU instructions, how byte orders are swapped between memory and registers (“B8 00 4C” is moving the value of 4C00 to register AX, but is byte swapping 4C and 00).  

No comments: