Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Enlargening a letter using arrays

Status
Not open for further replies.

dumbgeek

Programmer
May 22, 2003
8
ZA
Hi! I am a very new to assembly.This question that im doing requires me to 1>clear the screen, 2>change color to ywllow on blue, set cursor position to row10,coloumn1, display a message asking the user to input a character("A" to "E") and display a message for invalid input. then use the input character(converted to number 1 to 5)as an index to the array of bit patterns corresponding to the letter entered the display the large letter in the form of spaces and '*' on the screen.I am only allowed to use NASM.Pleeeze Pleeeeze help. I did some garbage.

[ bits 16
org 0x100 ;offset 100h

jmp main ;junp to main program

str1: db 'Invalid Character!.Enter capital letters from A to E','$'
str2: db 'Enter a character please(A-E).','$'
str3: db 0x0a,0x0d,'$'

; clear the screen
;
clrscr:
mov ax,0600h ;service - scroll up the screen
mov bh,01Fh ;colour atrributes - yellow on blue
mov cx,0000 ;starting row:coloumn
mov dx,184Fh ;ending row:coloumn
int 10h ;bios system call
;

;set the cursor
;
setcursor:
mov ah,02 ;service - set cursor
mov bh,00 ;screen number 0
mov dx,0a01h ;row(10):coloumn(1)
int 10h ;bios system call
;

;Prompt for input
;
prompt:
mov ah,09 ;service - display string of characters
mov dx,str2 ;address of string to be output
int 21h ;display string
ret
;

;Read in a character from the keyboard
;Character is returned in AL
;
read_char:
mov ah,01 ;service - read character and echo to screen
int 21h ;read character from keyboard
ret
;

;Display line feed and carriage return
;
line_carr:
mov ah,09 ;service - display a string of characters
mov dx,str3 ;address of string to be output
int 21h; ;display the string
ret
;

;Display an error and ask for input
;
error1:
mov ah,09 ;service - display string of characters
mov dx,str1 ;address of string
int 21h ;
jmp main ;
;

;Terminate the program
;
exitprog:
int 20h;
;

;The main program
main:
call clrscr ;clear the screen
call setcursor ;set the cursor
call prompt ;prompt
call read_char ;get input from keyboard
label1:
cmp al,66h ;compare AL to Z
je exitprog ;if AL=Z terminate program
jmp label2 ;else jump to label2
label2:
cmp al,41h ;compare to A
jg label3 ;if >A go to label3
Jne error1 ;call error1
label3:
cmp al,45h ;compare AL to E
jl label4 ;if <E go to label4
jne error1 ;else call error1
label4:
int 20h ]


 
Haven't read in detail, but don't be too hard on yourself: it doesn't look like you're writing garbage! It takes a while to iron out errors, but this doesn't look like a bad starting point.

A couple of your subroutines don't have ret at the end (clrscr and setcursor), so they'll run on into the next one, which means some bits of your prog will run more times than you intended.

Your comparisons for A and E are greater and less, rather than greater and equal? Did you mean that? I can't remember ascii for A and E offhand, so maybe you did. Are your users allowed to enter lower-case letters?

Otherwise, how does the prog respond at the moment? In what way are you getting errors?
 
Thanks! Only capitals are allowed. It was displaying the prompt twice instead of once.
I sorted that out now. One of the problems i am having now is when i enter 'Z'(i.e 66h) the program supposed to terminate but instead it displays the error message(i.e invalid....). Also when i re-enter an incorrect letter the program terminate irrespective of what i enter. I changed my main program and error1. it now looks like this....

[][;Display an error and ask for input
;
error1:
call clrscr ;
call setcursor ;
mov ah,09 ;service - display string of characters
mov dx,str1 ;address of string
int 21h ;
call read_char ;
call label1 ;
ret ;
;

;Terminate the program
;
exitprog:
int 20h;
ret;
;

;The main program
main:
call clrscr ;clear the screen
call setcursor ;set the cursor
call prompt ;prompt
call read_char ;get input from keyboard
label1:
cmp al,66h ;compare AL to Z
je exitprog ;if AL=Z terminate program
jmp label2 ;else jump to label2
label2:
cmp al,40h ;compare to A
jl error1 ;if <A go to label3
call label3 ;call error1
label3:
cmp al,46h ;compare AL to E
jl label4 ;if <E go to label4
call error1 ;else call error1
label4:
int 20h ;exit
]]
please i know im asking alot,but my major problem lies with the last part(use the input character(converted to number 1 to 5)as an index to the array of bit patterns corresponding to the letter entered the display the large letter in the form of spaces and '*' on the screen.)
i know i have to use idiv and shl somewhere but where. i am aiming for an output that looks like this for eg A

***
* *
*****
* *
* *
 
dumbgeek,

I never use NASM, so I can't help much in this case. But here are few things I noticed.

1. As lionelhill pointed out, there is no RET instruction in your CLRSCR & SETCURSOR routine. Have you add it yet ?

2. in the main program
main:
call clrscr ;clear the screen
call setcursor ;set the cursor
call prompt ;prompt
call read_char ;get input from keyboard
label1:
cmp al,66h ;compare AL to Z
je exitprog ;if AL=Z terminate program
; jmp label2 ;else jump to label2
; jump is unnecessary. Remove this line
label2:
cmp al,40h ;compare to A
jl error1 ;if <A go to label3
; call label3 ;call error1
; why you use CALL instruction here ? Remove this line

label3:
cmp al,46h ;compare AL to E
jl label4 ;if <E go to label4
call error1 ;else call error1


Try again, good luck

-- AirCon --
 
dumbgeeks,

Forgot one, in the main program

label2:
cmp al,40h ;compare to A
jl error1 ;if <A go to label3
; here you use Jump to error1

label3:
cmp al,46h ;compare AL to E
jl label4 ;if <E go to label4
call error1 ;else call error1
; but here you use CALL to error1

In Error1 routine, you have RET instruction.
error1:
call clrscr ;
call setcursor ;
mov ah,09 ;service - display string of characters
mov dx,str1 ;address of string
int 21h ;
call read_char ;
call label1 ;
ret

I guess you need to learn the basic things first.
If you use JUMP instruction to a label/routine, you cannot have RET instruction. If you use CALL to a routine you need RET instruction at the end of the routine.

Don't mix it !! You can explore more about that later

-- AirCon --
 
(1) The explanation behind the jmp and call thing (AirCon is utterly right and good job he noticed this!): call saves the address of the next instruction after the call. It saves it on the stack. This means that ret can read that address, and return to the instruction after the call. Jmp does no such thing, being intended for jumps from which there will be no return. So if you use a jmp, and then the processor meets a ret, it will pop a value off the stack (and this may be any value at all!) and return to a potentially random place. At best you'll return a subroutine higher than you expected, by popping the address placed by a previous call. More likely you'll pop a random bit of data and return to oblivion!

(2) Indexing. You need to think about a format to contain your &quot;big&quot; letters. This will probably be a series of bytes, one for each line of stars in the big letter, and within each line, each star will be there or not according to whether a bit is set in the byte or not.
That means that each big letter will correspond to x bytes (x = No. rows of stars needed for a letter). So you need to take your ascii character, subtract something so that it is now 0...5, and then multiply by x so it's now 0...5x.
If you choose to have letters 8 rows deep, then you need to multiply by 8. This is a good choice for quick operation, because multiplying by 8 is the same as shifting left 3 bits. Shifting is a lot, lot quicker than multiplying.

(Only read this if you are not confused: Note that I'm assuming your letters are not more than 8 stars wide, so you can store them in a byte. If you were working with high-resolution characters you'd need more than 8 bits, so you might have to think about having n-byte wide letters, and for your indexing, multiplying by x * n)

(Extra bit: did you know that the VGA system has its own in-built font bit-maps? These include a friendly 8*8 and you can read the address by one of interrupt 010h's many subfunctions)

Hope that helps a bit
 
Hi again! My program doesnt ever exit when Z is entered. Any idea why? I did the check first i.e label1 shouldn't it do &quot;int20h&quot; which is label4?
 
Can you post what is your current complete code ? Because looking from your code, I can't figure out why it won't exit


-- AirCon --
 
Thank you alot for helping me. I really mean that.

[
bits 16
org 0x100 ;offset 100h

jmp main ;jump to main program

str1: db 'Invalid Character!.Enter capital letters from A to E','$'
str2: db 'Enter a character please(A-E).','$'
str3: db 0x0a,0x0d,'$'

; clear the screen
;
clrscr:
mov ax,0600h ;service - scroll up the screen
mov bh,1Eh ;colour atrributes - yellow on blue
mov cx,0000 ;starting row:coloumn
mov dx,184Fh ;ending row:coloumn
int 10h ;bios system call
ret ;
;

;set the cursor
;
setcursor:
mov ah,02 ;service - set cursor
mov bh,00 ;screen number 0
mov dx,0a01h ;row(10):coloumn(1)
int 10h ;bios system call
ret ;
;

;Prompt for input
;
prompt:
mov ah,09 ;service - display string of characters
mov dx,str2 ;address of string to be output
int 21h ;display string
ret ;
;

;Read in a character from the keyboard
;Character is returned in AL
;
read_char:
mov ah,01 ;service - read character and echo to screen
int 21h ;read character from keyboard
cmp al,66h ;compare AL to Z


;Display line feed and carriage return
;
line_carr:
mov ah,09 ;service - display a string of characters
mov dx,str3 ;address of string to be output
int 21h; ;display the string
ret
;

;Display an error and ask for input
;
error1:
call clrscr ;
call setcursor ;

mov ah,09 ;service - display string of characters
mov dx,str1 ;address of string
int 21h ;

jmp main;

;

;Display an error and ask for input - NOT USED YET
;
error2:
call clrscr ;
call setcursor ;
mov ah,09 ;service - display string of characters
mov dx,str1 ;address of string
int 21h ;
;call prompt
;call read_char
jmp main ;
jmp read_char
;



;The main program
main:
call clrscr ;clear the screen
call setcursor ;set the cursor
call prompt ;prompt
call read_char ;get input from keyboard

label1:
cmp al,66h ;compare AL to Z
je label4 ;if AL=Z terminate program

label2:
cmp al,40h ;compare to A
jg label3 ;if >A go to label3

label3:
cmp al,46h ;compare AL to E
jl label4 ;if <E go to label4
jmp error1 ;else call error1
label4:
int 20h ;exit
]

**OK now i'm gonna take a shot in the dark....Can one of you PLEEEEEZ give me the code for this.I tried and tried and as for the outputting of the letter entered in the enlarged format,im beginning to think thats not possible.
Once again the output must be like:-
eg A
***
* *
*****
* *
* *
i am com 100% sure that the bit patterns supposed to look like :-
00001110 (0E) for A
00010001 (11) for B
00011111 (1F) for C
00010001 (11) for D
00010001 (11) for E , but im lost on how to obtain these bit patterns for displaying the enlarged letter.
I am really grateful.
 
dumbgeek,

I have to say this.
First things first. Which is: fix the main program before you go into more trouble, especially when you are new to assembly. Why are you so impatient ? Don't go rush with assembly. One small mistake can kick your program to oblivion! (I take that word from lionelhill :) )

The reason I say that is because you still don't understand when to use JUMP, when to use CALL and when you need a RET instruction.
Look here:

;The main program
main:
call clrscr ;clear the screen
call setcursor ;set the cursor
call prompt ;prompt
call read_char ;get input from keyboard


;Read in a character from the keyboard
;Character is returned in AL
;
read_char:
mov ah,01 ;service - read character and echo to screen
int 21h ;read character from keyboard
; cmp al,66h ;compare AL to Z
; main program CALL this routine but this routine has no RET instruction
; add RET instruction
RET


Ok. Let's continue, this code:
label2:
cmp al,40h ;compare to A
jg label3 ;if >A go to label3
label3:
cmp al,46h ;compare AL to E
jl label4 ;if <E go to label4
jmp error1 ;else call error1


; change to this:
label2:
cmp al,40h ;compare to A
jl error1 ;if <A jump error1

label3:
cmp al,45h ;compare AL to E
jg error1 ;if >E jump error1
; if <=E then we got a character we want which is A to E
; so jump/call to print the enlarge character


About enlarging the character. My idea is to use a simple logic which is array of '*'. You can define it like this

Code:
Char_A   db   ' *** ', 13,10,
              '*   *', 13,10,
              '*****', 13,10,
              '*   *', 13,10,
              '*   *', 0
Then call a PrintChar routine
PrintChar:
mov ah,09 ;service - display string of characters
mov dx,Char_A ;address of string to be output
int 21h ;display string
ret

You can create another character your own, and print it the same way.

There is one thing I noticed from your code and make me curious. I don't know about NASM but as I remember when you want to move the address of the string into DX, we don't use &quot;MOV DX,message&quot;, usually we use &quot;LEA DX,message&quot;.
So my question is, does your &quot;prompt routine&quot; code work ? Because my &quot;PrintChar&quot; example is base on your &quot;Prompt&quot; routine.

I know it won't work with MASM. It even doesn't work with my very primitive assembly compiler

Well, it's all up to you now. I think I've had enough explaining.

Good luck!

-- AirCon --
 
I have vague memories last time I did this sort of thing I did something like
mov dx, offset message, but I might be thinking asm embedded in pascal. You definitely want the offset of &quot;message&quot; rather than the contents of message to be put in dx.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top