News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Print ASCII characters

Started by new_comer, February 26, 2006, 07:30:43 AM

Previous topic - Next topic

new_comer

Hi!
I want to write a program to print ASCII characters comes between the range of user specified values.

I wrote the following code, but the output is not as desired. Please help




.MODEL SMALL
.STACK 100H

.DATA
MSG1 DB 'Please Enter the Lower limit: $'
MSG2 DB 'Please Enter the Upper limit: $'
LOW1 DB ?
UP1 DB ?

.CODE
MAIN PROC

;Intialize Data Segement
MOV AX,@DATA
MOV DS,AX

;Taking input of lower limit
MOV AH,9
LEA DX,MSG1
INT 21H

MOV AH,1
INT 21H
MOV LOW1,AL

MOV AH,2
MOV DL,0DH         
INT 21H

MOV AH,2
MOV DL,0AH
INT 21H

;Taking input of Upper limit
MOV AH,9
LEA DX,MSG2
INT 21H

MOV AH,1
INT 21H
MOV UP1,AL

MOV AH,2
MOV DL,0DH
INT 21H

MOV AH,2
MOV DL,0AH
INT 21H



MOV BL,UP1
SUB BL,LOW1
MOV DL,BL

MOV AH,2
FIRST:
       INT 21H
       INC DL

       MOV BL,UP1
       CMP BL,LOW1
JNZ FIRST


;Exit To DOs
MOV AH,4CH
INT 21H

MAIN ENDP
END MAIN




I wonder, if you could suggest me a suppliment code, so that I can show that... "following ascii value is equivalent to following ascii character".

MichaelW

I'm not sure exactly what you are trying to do here, but your loop logic is wrong. The loop should start with DL = LOW1 and continue until DL = UP1. The input values are treated as characters, not ASCII codes. To accept ASCII codes in a useful range you must be able to accept multi-digit input and translate the digits to an ASCII code value.

eschew obfuscation

new_comer

Thanks for the reply Sir,

I have corrected that Stupid Mistake.


For starting, I want to test the Program with single input character.
Suppose I entered "2" for "LOW1" and "5" for "UP1", it should work?

Now my modified code is

.MODEL SMALL
.STACK 100H

.DATA
MSG1 DB 'Please Enter the Lower limit: $'
MSG2 DB 'Please Enter the Upper limit: $'
LOW1 DB ?
UP1 DB ?

.CODE
MAIN PROC

;Intialize Data Segement
MOV AX,@DATA
MOV DS,AX

;Taking input of lower limit
MOV AH,9
LEA DX,MSG1
INT 21H

MOV AH,1
INT 21H
MOV LOW1,AL

MOV AH,2
MOV DL,0DH         
INT 21H

MOV AH,2
MOV DL,0AH
INT 21H

;Taking input of Upper limit
MOV AH,9
LEA DX,MSG2
INT 21H

MOV AH,1
INT 21H
MOV UP1,AL

MOV AH,2
MOV DL,0DH
INT 21H

MOV AH,2
MOV DL,0AH
INT 21H



MOV DL,LOW1  ; MODIFIED LINE
MOV AH,2

FIRST:
       INT 21H
       INC DL

       MOV BL,UP1
       CMP BL,LOW1    ;it is UP1 minus LOW1, It will affect the zero flag of FLAGS
JNZ FIRST


;Exit To DOS
MOV AH,4CH
INT 21H

MAIN ENDP
END MAIN

new_comer

The program is running for infinity times


Please tell me the suppliment code to get desired output, as I asked in my first post.

MichaelW

Yes, like the first version, your last version hangs in an endless loop. Are you testing your code before you post it? You need to make an effort to do your own work, and that includes testing your code and at least attempting to find and correct the problems.

The loop needs to exit after the UP1 character has been displayed.

CMP  DL, UP1
JNA  FIRST


Assuming the loop problem has been corrected, if you input '2' for LOW1 and '5' for UP1 the program should display '2345'. I'm still not sure what you want to do. If you expect to input ASCII character code values and output the corresponding characters (input '65' output 'A', input '66' output 'B', etc), then you will need to change your input code to accept a multi-digit string and add some method of translating the string to a numeric value.


eschew obfuscation

etow

How do you print ASCII character for Dec 251 and Hex FB for console? 

062459335

Here are some useful subroutines:




num2asc PROC         ;outputs the number in ax to the screen (in decimal)

push ax
push bx
push cx
push dx                   ;save all our registers

num2asc_label1:
mov bx, 10d
div bx                      ;divide our number by 10. The quotient is in ax, and remainder in dx
push dx                   ;We only want the remainder. this method pushes each
                                ;DIGIT (decimal) of the number to the stack
inc cx                      ;use cx to count how many times we push onto the stack
cmp ax, 0
jne num2asc_label1

mov ah, 02h           ;int 21h/ah=02 outputs single char to screen

num2asc_label2:      ;here we pop off the stack and print to the screen
pop dx
add dl, 30h               ;convert the stored digit to ASCII
int 21h                     ;print to screen
dec cx                     ;the number of times we pop = number of times we pushed
jnz num2asc_label2

pop dx                  ;don't forget to restore the registers
pop cx
pop bx
pop ax

ret
num2asc ENDP

;////////////////////////


str2num PROC                  ;converts input string to number in ax
                                     ;bx points to the start of the string
                                     ;keeps reading until it reaches a CR, NULL, or '$'
                                     ;this proc is good for multi-digit number input, and not really much else!
                                     ;use in conjunction with int 21h/ah=0a - buffered string input
push bx
push cx
push dx                          ;save the registers

xor ax, ax
xor cx, cx                       ;ax and cx are set to 0

str2num_loop1:
xor dx, dx
mov dl, byte ptr [bx]       ;move the first byte of the string into dl
cmp dl, 0
je str2num_end
cmp dl, 0dh
je str2num_end
cmp dl, '$'                       ;checks to see if the next value is either 0 ,CR, or $ (end of string)
je str2num_end
                                   ;this section multiplies ax by 10 by using shl's and add's.
                                   ;Is more efficient than using mul
shl ax, 1
mov cx, ax
shl ax, 2
add ax, cx                      ;ax is multiplied by 10 (ax*2 + ax*8=ax*10)
                                    ;with each new digit read, we have to multiply our number by 10
                                    ;ie: a 5-byte string will have 5 digits, etc.
sub dx, 30h                     ;subtract 30h to convert from ASCII to it's number equivalent
                                     ;ie: '0' - 30h = 0
add ax, dx                      ;add it to the total
inc bx                             ;mov pointer to the next number
jmp str2num_loop1

str2num_end:

pop dx
pop cx
pop bx                           ;return all values of registers except for ax, which holds the number!
ret
str2num ENDP                 ;this proc has been tested and works quite well, the only problem is when 
                                    ;the user enters in characters, or TAB/ENTER, or other crap that this 
                                    ;wasn't designed to handle lol


I've found these very useful when you are working with numbers and ASCII values a lot.

FORTRANS

hello 062459335,

   I think you have a n error.  You need to clear DX before dividing.

num2asc_label1:
mov bx, 10d
div bx


Should be,


mov bx, 10d     ; This can be outside the loop, though that doesn't matter.
num2asc_label1:

xor dx,dx   ; but you must clear DX before dividing.

div bx


HTH,

Steve

062459335

whoops i guess i never noticed.
thanks for pointing that out!

Neil

etow this is the way of printing extended ascii characters in a console :-

print " " , highlight the space between the inverted commas, hold down the 'Alt' key & type the asciii  code on the numeric keypad using a leading zero e.g. 0251, when you release the 'Alt' key the character will appear in the space.