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
     org 100h
     ;First, jump to the main program
BEGIN:     jmp main

     ;Our psuedo, Data Segment
     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

     ;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
     ;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
     ;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

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.


No comments: