Wednesday, May 03, 2006

ASM: Changing String Case

For fun, I pulled out the ‘ol assembler for a little bit of low level programming. The goal was to write a small (COM sized) program that will take the input from a user using DOS interrupts, change the case of the string, and display it on the screen using DOS interrupts. DOS has a whole slew of interrupts/functions for I/O, so I picked function 0ah for input, which is a powerful input function allowing for a numeric limitation on string sizes similar to using fgets (CHAR_STRING, 50, stdin) in C. This program also demonstrates the basic low-level concept of changing a characters case, which is done through a simple bit mask. The program is below.

Title change_case_of_string_demo
     ;Set to the Tiny memory model, used for COM files and small EXE
     .model tiny
     ;Start the code segment. This will be a single segment program, so no stack or data segments are declared
     .code
     org 100h
     ;First, jump to the main program
BEGIN:     jmp main

     ;Our psuedo, Data Segment
     PARA_LIST     LABEL     BYTE
     MAX_LEN DB 50 ;The max length of a string
     ACT_LEN DB ? ;A blank uninitited value, will store the actual string length
     CHAR_STRING DB 50 DUP(' ') ;The buffer to store input from the user

MAIN     PROC NEAR
     ;Set up 0aH/21h for user input using the PARA_LIST label, which has the MAX_LEN, Act_Len
     ;and CHAR_STRING memory areas
     mov ah, 0ah
     lea dx, PARA_LIST
     int 21h
     ;Set CL to the actual length of the string retrieved from the user, and load the
     ;effective memory address of CHAR_STRING into BX
     mov cl, ACT_LEN
     lea bx, CHAR_STRING
     ;Begin changing case
CHANGE_CASE:
     ;Move value pointed to from BX into AX and XOR the 6th bit to change its case, and
     ;move it back
     mov al, [bx]
     xor al, 20h
     mov [bx], al
     ;Increase the pointer and loop
     Inc bx
     Loop CHANGE_CASE
     ;Clear bx, and set BL to the size of the string
     xor bx, bx
     mov bl, ACT_LEN
     ;Set the last character in the string to a $, which is what the
     ;Goofy DOS functions use as a string terminator
     mov CHAR_STRING[BX], '$'
     mov ah, 09h
     lea dx, CHAR_STRING
     int 21h
     ;Exit program
     mov ax, 4c00h
     int 21h
MAIN ENDP
     END BEGIN

Once the program, has been written, I assemble it using the below command using Turbo Assembler.

H:\TASM>tasm code\make_low.asm
"C:\PROGRAMCannot load VDM IPX/SPX support
Turbo Assembler  Version 4.1  Copyright (c) 1988, 1993 Borland International

Assembling file:   code\make_low.asm  to  make_low.OBJ
Error messages:    None
Warning messages:  None
Passes:            1
Remaining memory:  452k

And I link the program using Turbo Link. I use the /t option to output a COM file instead of a EXE file.

H:\TASM>tlink /t make_low.obj
Turbo Link  Version 7.00 Copyright (c) 1987, 1994 Borland International

I test the program below. Although not demonstrated, the program takes in typed text and outputs on the exact same place. Apparently the input function did not change the cursor location.

H:\TASM>make_low
TEST

No comments: