I got stuck at "Enter a string:" and doesn't take any input-8086 programming - masm

In the program for to find out no. of vowels in a string. I got stuck at "Enter a string:" ?? why? even tho the compiler says everything okay.
program to count the no. of vowels in a string.
;;;;;;;PROGRAM TO CHECK NO. OF VOWELS IN A STRING;;;;;
.model small
.stack 100h
.data
vowels db 'AEIOUaeiou$'
msg1 db 'Enter a string:$'
msg2 db 'The string is:$'
msg3 db 'No of vowels are:$'
string db 50 dup('$')
count db ?
.code
main proc
mov ax, #data
mov ds, ax
mov es, ax
lea dx,msg1
mov ah,09h ;for displaying enter a string
int 21h
lea di,string
cld
xor bl,bl
input:mov ah,01 ; stuck here, at taking input, why??
cmp al, 13
je endinput
stosb
inc bl
jmp input
endinput:cld
xor bh,bh
lea si,string
vowelornot: mov cx,11
lodsb
lea di,vowels
repne scasb
cmp cx, 00
je stepdown
inc bh
stepdown: dec bl
jnz vowelornot
mov ah,06 ;;;THIS FOR CLEARING SCREEN I GUESS
mov al,0 ;;;
int 10h
lea dx,msg2
mov ah,09
int 21h
mov dl, 13 ;;; NEW LINE
mov ah, 2
int 21h
mov dl, 10
mov ah, 2
int 21h
lea dx,string
mov ah, 09
int 21h
mov dl,13 ;;;NEW LINE
mov ah,2
int 21h
mov dl,10
mov ah,2
int 21h
lea dx, msg3
mov ah,09
int 21h
mov dl,13 ;;;NEW LINE
mov ah,2
int 21h
mov dl,10
mov ah,2
int 21h
mov count, bh
mov dh, count ;;; DH = VOWEL COUNT
mov ah,09
int 21h
mov ah, 4ch ;;; EXIT
int 21h
main endp
end

Multiple errors
input:mov ah,01 ; stuck here, at taking input, why??
cmp al, 13
Here your code is missing the int 21h instruction!
input:
mov ah,01
int 21h
cmp al, 13
xor bl,bl
input:
stosb
inc bl
jmp input
You're using BL to count the number of characters in the input string but the example you wrote needs much more than the 255 maximum that this byte-sized register can give you. This must fail!
Moreover the buffer that you've setup is limited to 50 bytes. No way you could store there such a long input.
lea si,string
vowelornot: mov cx,11
lodsb
lea di,vowels
repne scasb
cmp cx, 00
je stepdown
inc bh
stepdown: dec bl
jnz vowelornot
This is too complicated. Just interpret the ZeroFlag and don't look at CX at all. You don't need to terminate the vowels text with a "$" anymore (use CX=10).
lea si,string
vowelornot:
lodsb
mov cx,10
lea di,vowels
repne scasb
jne stepdown
inc bh ;Vowel found +1
stepdown:
dec bl
jnz vowelornot
mov ah,06 ;;;THIS FOR CLEARING SCREEN I GUESS
mov al,0 ;;;
int 10h
Sure, function 06h can clear the screen but you need to provide all of the required arguments. Upperleftcorner in CX, Lowerrightcorner in DX and Displaypage in BH.
mov dx, 184Fh ;(79,24) If screen is 80x25
xor cx, cx ;(0,0)
mov bh, 0
mov ax, 0600h
int 10h
lea dx,string
mov ah, 09
int 21h
This will fail because you did not put a "$" character at the end of the inputted string.
And if you're going to output a CRLF directly afterwards, why not add it to the buffer?
jmp input
endinput:
mov ax, 0A0Dh <-- ADD THIS
stosw <-- ADD THIS
mov al, "$" <-- ADD THIS
stosb <-- ADD THIS
xor bh,bh
You print msg2 and msg3 followed by a CRLF. Why don't you append it in the definition? No more need to output it separately.
msg2 db 'The string is:', 13, 10, '$'
msg3 db 'No of vowels are:', 13, 10, '$'
mov count, bh
mov dh, count ;;; DH = VOWEL COUNT
mov ah,09
int 21h
To output the count and provided it is a number in the range from 0 to 9, you need to convert the number into a character. Just add 48 or '0'.
Don't use function 09h. It requires an address and you clearly want to use a character.
mov dl, bh ;Count of vowels [0,9]
add dl, '0'
mov ah, 02h
int 21h

Related

FASM: How to input values in array using loop

This code doesn't work for me. My goal is to ask user string input, convert to capital letters, and store them one by one in an array, then output the characters(that is in all caps) back to the user. please help me :(
org 100h
mov bl, 0
mov ah, 9
mov dx, input
int 21h
again:
mov ah, 1
int 21h
sub al, 20h
mov [inp+bl], al
inc bl
cmp bl, 2
jle again
loops:
mov bl, 0
mov ah, 2
mov dl, [inp+bl]
int 21h
inc bl
cmp bl, 2
jle loops
mov ax, 4Ch
int 21h
input db 'Input: ',24h
output db 'Output: ',24h
inp db 20 dup(?), 24h
mov [inp+bl], al
The main problem here is that you use an addressing mode that simply does not exist!
You can quickly correct your code if you change every instance of BL into BX.
mov bx, 0
mov ah, 9
mov dx, input
int 21h
again:
mov ah, 1
int 21h
sub al, 20h
mov [inp+bx], al
inc bx
cmp bx, 2
jle again
loops:
mov bx, 0
mov ah, 2
mov dl, [inp+bx]
int 21h
inc bx
cmp bx, 2
jle loops
sub al, 20h
Perhaps you've over-simplified the code because this capitalization will of course only work if the user only types in small caps a..z and nothing else.

masm palindrome check output dilemma

I was trying to do a palindrome check program using masm and used the below code but I always got not palindrome as output, not able to figure it out why. Please help to modify the code. The code is given below for further clarification.
Thanks in advance.
read macro
mov ah,01h
int 21h
endm
write macro
mov ah,02h
int 21h
endm
assume cs:code,ds:data
data segment
a db 20 dup(?)
b db 20 dup(?)
msg1 db "enter text: $"
msg2 db "reverse string is: $"
msg3 db " palindrome$"
msg4 db " not palindrome$"
data ends
code segment
start:mov ax,data
mov ds,ax
mov es,ax
mov cx,0000h
lea si,a
lea dx,msg1
mov ah,09h
int 21h
r:read
cmp al,0dh
je l
mov [si],al
inc si
inc cx
jmp r
l:dec si
lea di,b
mov ax,cx
l1:mov dl,[si]
mov [di],dl
inc di
dec si
loop l1
l2:
mov cx,ax
lea si,b
lea dx,msg2
mov ah,9h
int 21h
w:mov dl,[si]
write
inc si
loop w
mov cx,ax
cld
lea si,a
lea di,b
l4:cmpsb
jne l5
loop l4
lea dx,msg3
mov ah,09h
int 21h
mov ah,4ch
int 21h
l5:lea dx,msg4
mov ah,09h
int 21h
mov ah,4ch
int 21h
code ends
end start
whatever is input string it gives not a palindrome.
Instead of doing mov ax,cx use mov bx,cx as ah is used in interrupts it might cause some problems. And every where mov cx,ax is there use mov cx,bx ....now it will be correct.
It might seem funny that I answered my own question but I figured this now and didn't delete cause it might help others from not doing the same...

8086 Assembly - Better data storage/manipulation?

I am working on a project for class, and it works as required by the rubric, though I am wondering if there is a slightly better way to implement a few things. I was docked a few points for an unnecessary 'mov' in another project. Here is problem 1.
"If—else (34 points): Write a program that asks the user to enter a single digit. If that digit is less 5, you will state so and you will add 5 to it and store it in a variable; if the digit is greater than 5, you will state so and then subtract 5 from it and store it in a variable; if the digit is 5, you will add 3 to it and state so and store it in a variable."
org 100h
mov dx, offset start ;move start of string address 'start' into dx
mov ah, 09h
int 21h ;print the string stored at DS:DX
mov ah, 01h ;function for getting keyboard input
int 21h
sub al, 30h ;subtract 30h to store our number as hexadecimal
mov bl, al ;copying data to BL as the following commands manipulate the data
;at AL.
cmp bl, 5 ;BL = AL
jz ifZero ;jump to ifZero if BL = 5
jl ifLess ;jump to isLess if BL < 5
jg ifGreater ;jump to ifGreater if BL > 5
ifZero: ;direct console output function
mov ah, 06h
mov dl, 0Ah
int 21h
mov dl, 0Dh
int 21h ;print newline and character return
add bl, 03h ;add 3 to BL, BL = 8
mov temp, bl
mov dx, offset eq ;move start of string address 'eq' into dx
mov ah, 09h
int 21h ;print string
jmp exit ;unconditional jump to end program
ifLess: ;direct console output function
mov ah, 06h
mov dl, 0aH
int 21h
mov dl, 0Dh
int 21h ;print newline and character return
add bl, 05h ;add 5 to BL
mov temp, bl
mov dx, offset less ;move start of string address 'less' into dx
mov ah, 09h
int 21h ;print string
jmp exit ;unconditional jump to end program
ifGreater:
mov ah, 06h
mov dl, 0ah
int 21h
mov dl, 0dh
int 21h ;print newline and character return
sub bl, 05h ;subtract 5 from BL
mov temp, bl
mov dx, offset great ;move starting address of string 'great' into dx
mov ah, 09h
int 21h ;print string
jmp exit ;unconditional jump to end program
exit:
ret
temp db ?
start db "Please enter a number: $"
less db "Less than 5... adding 5 $"
great db "Greater than 5... subtracting 5 $"
eq db "Equal to 5... adding 3 $"
in this case, would 'mov bl, al' be not needed? Running through the disassembler shows that the data in AL changes after most of these commands. Is this supposed to happen? Is there a better way to do so?
Problem 3:
Counter-controlled loop. The program will ask the user to enter a character and then it will display
that character with a label five times
For example:
Enter a character: A
You entered: A
org 100h
mov cx, 05h ;counter controlled loop, start as 5
LabelLoop:
mov dx, offset prompt ;move string offset to dx
mov ah, 09h ;function for printing string from dx
int 21h
mov ah, 01h ;function to read character from keyboard
int 21h
mov bl, al ;preserving character read by copying to BL
;as register data for AL will be changing
;due to various functions
mov ah, 06h ;function for direct console output
mov dl, 0ah
int 21h
mov dl, 0dh ;these just make the text appear on a new
;line
int 21h
mov dx, offset output ;move the memory offset of output to dx
mov ah, 09h ;printing another string
int 21h
mov ah, 02h ;function to write a character to console
;gets the value from DL
mov dl, bl ;so we copy BL to DL and print it
int 21h
jmp newLine ;we unconditionally jump to the newLine
;label and print a new line for the program
;to run again
newLine:
mov ah, 06h
mov dl, 0ah
int 21h
mov dl, 0dh
int 21h
loop LabelLoop ;we jump to LabelLoop and CX = CX - 1
mov dx, offset goodbye
mov ah, 09h
int 21h
ret
prompt db 'Enter a character: $'
output db 'You entered: $'
goodbye db 'Good bye!$'
So, my question for these problems, is there a better way to do this? keyboard input is stored in AL, but the register value changes for each time i do a mov function into AH, whether string printing or character printing. in order to avoid a variable (since it wasn't a part of the requirements) or allocating it to memory (which we haven't learned), I moved the data to a different register. Is this an unnecessary 'mov' for either program?
edit: i realize that AL = DL after
mov ah, 06h
mov dl, 0ah
int 21h ;AL = DL after execution
cmp bl, 5 ;BL = AL
jz ifZero ;jump to ifZero if BL = 5
jl ifLess ;jump to isLess if BL < 5
jg ifGreater ;jump to ifGreater if BL > 5
ifZero:
The first improvement you should do is making use of the possibility to fall-through in the code. Don't use jz ifZero but rather fall through as equality is the only state that remains after jl and jg. Also ifEqual would be a more correct name for this state.
cmp bl, 5 ;BL = AL
jl ifLess ;jump to isLess if BL < 5
jg ifGreater ;jump to ifGreater if BL > 5
ifEqual:
A second optimization will be to get rid of all of those direct console outputs for CR and LF. You should incorporate these in the messages that you will print. Doing so will also remove the need to copy AL to BL using mov bl, al (you specifically asked this):
less db 13,10,"Less than 5... adding 5 $"
great db 13,10,"Greater than 5... subtracting 5 $"
eq db 13,10,"Equal to 5... adding 3 $"
Here's another opportunity to fall through:
jmp exit ;unconditional jump to end program
exit:
Your second program can benefit from these advices too.

How do i print a unsigned array of numbers in assembly?

this is my code:
.model small
.stack 100h
.data
A db 2,-5,3,4,-8
N equ 5
.code
mov ax, #data
mov ds, ax
mov si,offset A
mov cl,1
start:
cmp cl,N
je sof
mov al,[si]
cmp al,[si+1]
jg change
jmp next
change:
mov ah,al
mov al,[si+1]
mov [si],ah
mov [si+1],al
jmp next
next:
inc si
inc cl
jmp start
sof:
mov ah,9
mov cx, offset A
int 21h
.exit
end
i get a weird out put a lot of weird characters :/
You need to add 30h to a number in range 0 through 9 in order to display an ascii character. To display a character, use
;al = digit to display
mov dl,al
add dl,030h
mov ah,02 ;display character (in dl)
int 21h

How to print an array in DOS x86 assembly?

I have this code to copy the array "NUMBERS" to "DEST" such that no number will repeat (in this case it should be : 1,2,5,4,7)
The code works but now I need to print the array "DEST". How can I do that ?
data segment
NUMBERS db 1,2,1,1,1,5,5,4,7,7
DEST dt ?
data ends
code segment
assume ds:data, cs:code
start: mov ax, data
mov ds, ax
mov ax, 0a0ah
mov di, offset NUMBERS
mov bx, 0h
loop2:mov cl, [di]
mov si, offset DEST
mov ch, [si]
loop1:cmp ch, cl
je dontadd
inc si
mov ch, [si]
dec ah
jnz loop1
mov si, offset DEST
add si, bx
inc bx
mov [si], cl
dontadd:mov ah, 0ah
inc di
dec al
jnz loop2
mov ah, 4ch
int 21h
code ends
end start
You can use INT 21h, AH=02h to print a single character to STDOUT.
MOV CX,10
MOV SI,OFFSET DEST
print:
MOV DL,[si]
OR DL,DL
JE done
ADD DL,'0' ; <-- Convert numeric value in DL into ASCII code
MOV AH,02h
INT 21h
MOV DL,' ' ; Throw in a space to make things pretty
INT 21h
INC SI
LOOP print
done:
If elements in NUMBERS have values over 9 then you need more elaborate conversion of the numeric values into ASCII.
First convert numbers to string then print them.You can use this two macros for printing numbers:
printstr macro str
push ax
push dx
lea dx,str
mov ah,9
int 21h
pop dx
pop cx
endm
printnum macro n
local o,w,s,n5,lb1,lb2,lb3
pusha
push si
push di
jmp w
s db 7 dup('$')
w:
mov si,0
mov cx,7
o:mov s[si],'$'
inc si
loop o
mov si,0
xor ax,ax
mov ax,n
xor dx,dx
cmp ax,0
jge n5
mov bl,'-'
mov s[si],bl
inc si
neg ax
n5:mov cx,10
div cx
or dl,30h
mov s[si],dl
xor dx,dx
inc si
cmp ax,0
jne n5
mov si,0
cmp s[si],'-'
jne lb1
inc si
lb1:mov di,si
lb3:cmp s[si],'$'
je lb2
mov al,s[si]
push ax
inc si
jmp lb3
lb2:pop ax
mov s[di],al
inc di
cmp di,si
jl lb2
printstr s
pop di
pop si
popa
endm

Resources