How to loop in assembly language - loops

How would I calculate the first 12 values in the Fibonacci number sequence and be able to place it in EAX reg. and display calling DumpRegs? Using Indirect addressing I know I need a for loop here but I'm not sure how to even go about this. Any help or tips are appreciated.
INCLUDE Irvine32.inc
; (insert symbol definitions here)
.data
; (insert variables here)
Fibonacci BYTE 1, 1, 10 DUP (?)
.code
main PROC
; (insert executable instructions here)
; (This below will show hexa contents of string.)
mov esi, OFFSET Fibonacci ; offset the variables
mov ebx,1 ; byte format
mov ecx, SIZEOF Fibonacci ; counter
call dumpMem
exit ; exit to operating system
main ENDP
; (insert additional procedures here)
END main

You can make a loop like this:
mov ecx,12
your_label:
; your code
loop your_label
The loop instruction decrements ecx and jumps to the specified label unless ecx is equal to zero. You could also construct the same loop like this:
mov ecx,12
your_label:
; your code
dec ecx
jnz your_label

You determined that you need a for loop to achieve your goal, so maybe the C implementation of the for loop, in assembly, will help you:
Code Generation for For Loop
for (i=0; i < 100; i++)
{
. . .
}
* Data Register D2 is used to implement i.
* Set D2 to zero (i=0)
CLR.L D2
L1
. . .
* Increment i for (i++)
ADDQ.L #1, D2
* Check for the for loop exit condition ( i < 100)
CMPI.L #100, D2
* Branch to the beginning of for loop if less than flag is set
BLT.S L1
SOURCE: eventhelix.com

.model small
.stack 100h
.data
msg db 'Enter height of the square form 1-9: $'
hash db '#$'
height db 1
length db 0
ctr dw 0
msgagain db 13,10,'Do you want to repeat the program? $'
msgend db 13,10,'Program Terminated! Press any key to exit..$'
.code
mov ax, #data
mov ds, ax
REPEAT:
mov ax, 03
int 10h
mov ah, 09
lea dx, msg
int 21h
mov ah, 01
int 21h
cmp al, '1'
jl REPEAT
cmp al, '9'
jg REPEAT
sub al, 48
mov length, al
mov bl, 1
mul bl
mov height, 1
mov di, 1
mov ctr, ax
mov cx, ax
nextline:
dec length
mov ah, 02
mov bh, 00
mov dl, length
mov dh, height
int 10h
mov cx, di
hashtags:
mov ah, 09
lea dx, hash
int 21h
loop hashtags
inc di
inc height
mov cx, ctr
dec ctr
loop nextline
mov ah, 09
lea dx, msgagain
int 21h
mov ah, 01
int 21h
cmp al, 'Y'
je REPEAT
cmp al, 'y'
je REPEAT
mov ah, 09
lea dx, msgend
int 21h
mov ah, 01
int 21h
mov ah, 4ch
int 21h
END

Related

Code stuck at an infinite loop when finding the nth fibonacci number

I was trying to find the nth Fibonacci number e.x n=3, output = 1
so my logic was this
a = 0
b = 1
input n
si 0
n>2
loop
temp = b
b = a+b
a = b
loop if si/=cx
print b
This is my pseudo code logic. When I tried to implement this I am stuck in an infinite loop
.MODEL SMALL
.STACK 100h
.DATA
STRING0 DB 'Enter INDEX $'
.CODE
MAIN PROC
MOV AX,#DATA
MOV DS,AX
LEA DX, STRING0
MOV AH,9
INT 21H
MOV AH, 2
MOV DL,0AH ;NEW LINE
INT 21H
MOV DL,0DH
INT 21H
MOV AH,1
INT 21H
SUB CX,CX
MOV CL,AL
MOV SI,0
MOV AX,0
MOV BX,1
LOOP1:
PUSH BX
ADD BX,AX
POP AX
INC SI
LOOP LOOP1
MOV DX,BX
MOV AH,9
INT 21H
MAIN ENDP
END MAIN
I use EMU 4.08. The code us stuck at an infinite loop. I have no idea why
I did SUB cx,cx to move the AL value to CL and use CL as counter otherwise it gives me error that the code failed to send 8bit data to 16bit
I was trying to find the nth Fibonacci number e.x n=3, output = 1
From your example I understand that you consider the Fibonacci sequence to begin with 0, 1, 1, 2, 3, 5, 8, 13, 21, ...
Fibonacci himself started his sequence from 1, 2, 3, 5, 8, ...
See the Wikipedia article https://en.wikipedia.org/wiki/Fibonacci_number
I didn't follow your pseudo code too much as it has flaws of its own!
Why your assembly program fails
You say your "code is stuck at an infinite loop", but that's not really the case. It is just that your loop executes an extra 50 iterations. The reason is that the DOS.GetCharacter function 01h gives you an ASCII code, that you have to convert into the digit that the pressed key represents. eg. If you press 3, DOS gives you AL=51, and you need to subtract 48 to obtain the inputted digit which is 3.
But wait, don't use this number 3 as your loop counter already! Since the 1st and 2nd Fibonacci numbers are known from the start, calculating the 3rd Fibonacci number requires just 1 iteration of the loop. Account for this and subtract 2 beforehand.
Once your program has found the answer you simply move the result from BX to DX, and expect the DOS.PrintString function 09h to output the number. It can't do that. It's a function that outputs a series of characters (so a string beginning at the address in DX), however your result is still a number in a register. You have to convert it into its textual representation. Displaying numbers with DOS has all the fine details about this conversion!
Next code allows the user to input a single-digit from 1 to 9
...
mov ah, 01h ; DOS.GetCharacter
int 21h ; -> AL = ["1","9"]
sub al, 48 ; -> AL = [1,9]
cbw ; -> AH = 0
mov cx, ax ; -> CX = [1,9]
xor ax, ax ; -> AX = 0
dec cx
jz PrintIt ; 1st Fib is 0
inc ax ; -> AX = 1
dec cx
jz PrintIt ; 2nd Fib is 1
cwd ; -> DX = 0
CalcIt: ; 3rd Fib and others
xchg ax, dx
add ax, dx
loop CalcIt
PrintIt: ; AX is at most 21 (because of the limited input)
aam
add ax, 3030h ; Conversion into text
xchg al, ah
cmp al, '0'
mov dh, 02h ; DOS.PrintCharacter
xchg ax, dx
je Ones
int 21h
Ones:
mov dl, dh
int 21h
Because in your program the output is very limited, I used a special code to display at most 2 digits. For the general case of outputting numbers see this Q/A.
I think this should be good:
.MODEL SMALL
.STACK 100h
.DATA
STRING0 DB 'Enter INDEX $'
STRING1 DB 'OUTPUT: $'
.CODE
MAIN PROC
MOV AX,#DATA
MOV DS,AX
LEA DX, STRING0
MOV AH,9
INT 21H
MOV AH, 2
MOV DL,0AH ;NEW LINE
INT 21H
MOV DL,0DH
INT 21H
MOV AH,1
INT 21H
SUB CX,CX
SUB AL,30H ;To convert char into digit value
MOV CL,AL
MOV SI,0
MOV AX,0
MOV BX,1
LOOP1:
PUSH BX
ADD BX,AX
POP AX
INC SI
LOOP LOOP1
MOV AH, 2
MOV DL,0AH ;NEW LINE
INT 21H
MOV DL,0DH
INT 21H
LEA DX, STRING1
MOV AH,9
INT 21H
;Print the result
MOV AX,BX
MOV SI,0
;Push digits from right to left into stack
LOOP2:
MOV DL,10
DIV DL
PUSH AX
MOV AH,0
INC SI
CMP AL,0
JNE LOOP2
;Pop digits from stack and print them
LOOP3:
POP DX
MOV DL,DH
MOV DH,0
ADD DL,30H ;To convert digit to char
MOV AH,2
INT 21H
DEC SI
CMP SI,0
JNE LOOP3
HLT
MAIN ENDP
END MAIN

Subtraction of Two Arrays and Stores Result in 3rd array and display the result on screen in Assembly language 8086

I have already written the code to add TWO arrays and Store the result in 3rd array. But the problem occurs while handling the NEGATIVE SIGN Numbers to display with (-) sign. Follow are the code listed below while subtracting the 6th element of array1 with array 2, result is GARBAGE value Need assistance immediately. After running executing's the code, all signed values are not displaying correctly.
org 100h
Array1 db 1,3,2,2,2,2,2,2,2,2
Array2 db 4,5,6,7,8,9,0,1,2,3
Array3 db 10 dup (?)
lea dx, msg1
mov ah, 9
int 21h
mov cx, 10
mov bx, 0
L1001:
mov al, Array1 [bx]
; Extend (unsigned) AL to AX (to print)
mov ah, 0
call printd
mov ah, 2
mov dl, 09 ;TAB Character
int 21h
inc bx
loop L1001 ;End Loop1
mov ah,2
mov dl,10
int 21h
mov dl,13
int 21h
; print msg2
lea dx, msg2
mov ah, 9
int 21h
; Use loop to print values of Array2
mov cx, 10
mov bx, 0
L1002:
mov al, Array2 [bx]
; Extend (unsigned) AL to AX (to print)
mov ah, 0
call printd
mov ah, 2
mov dl, 09 ;TAB Character
int 21h
inc bx
loop L1002 End Loop2
mov ah,2
mov dl,10
int 21h
mov dl,13
int 21h
; print msg3
lea dx, msg3
mov ah, 9
int 21h
mov cx,10
mov bx, 0
L1003: ; Main Addition
mov al, Array1 [bx]
sub al, Array2 [bx]
mov Array3 [bx], al
; Extend (unsigned) AL to AX (to print)
mov ah, 0
call printd
mov ah, 2
mov dl, 09 ;TAB Character
int 21h
inc bx
loop L1003 ; End of lOOP3
lea dx, pkey
mov ah, 9
int 21h ; output string at ds:dx
; wait for any key....
mov ah, 1
int 21h
mov ax, 4c00h ; exit to operating system.
int 21h
printd proc
; preserve used registers
push ax
push bx
push cx
push dx
; if negative value, print - and call again with -value
cmp ax, 0
jge L1
mov bx, ax
; print -
mov dl, '-'
mov ah, 2
int 21h
; call with -AX
mov ax, bx
neg ax
call printd
jmp L3
L1:
; divide ax by 10
; ( (dx=0:)ax / cx(= 10) )
mov dx, 0
mov cx, 10
div cx
; if quotient is zero, then print remainder
cmp ax, 0
jne L2
add dl, '0'
mov ah, 2
int 21h
jmp L3
L2:
; if the quotient is not zero, we first call
; printd again for the quotient, and then we
; print the remainder.
; call printd for quotient:
call printd
; print the remainder
add dl, '0'
mov ah, 2
int 21h
L3:
; recover used registers
pop dx
pop cx
pop bx
pop ax
ret
printd endp
printud proc ;Print Undecimal Numbers
push ax
push bx
push cx
push dx
mov dx, 0
mov cx, 10
div cx
cmp ax, 0
jne L4
add dl, '0'
mov ah, 2
int 21h
jmp L5
L4:
call printud
add dl, '0'
mov ah, 2
int 21h
L5:
pop dx
pop cx
pop bx
pop ax
ret
printud endp ;
ret
msg1 db "Array 1 = $"
msg2 db "Array 2 = $"
msg3 db "Array 3 = : $"
pkey db "press any key...$"
mov al, Array1 [bx]
sub al, Array2 [bx]
mov Array3 [bx], al
; Extend (unsigned) AL to AX (to print)
mov ah, 0
call printd
You say that your program is having trouble displaying the negative numbers, but your code is never feeding any negative number to the printd routine! Whatever the signed result of the subtraction in AL may be, the mov ah, 0 that follows will produce a positive number in AX and it is AX that printd processes...
You should replace mov ah, 0 by cbw.
But, what is terribly wrong is the placement of the 3 arrays. They can't be at the top of the program like that. The cpu is executing their bytes (data) as if it were instructions (code)!
Move those 3 lines towards the bottom of the source.
It surprised me to see these recursive solutions to display a decimal number. I believe they are correct with one exception though! If you feed printd the negative number -32768 then the program will fall into an infinite loop. This happens because the negation of that particular value is again -32768.
You might want to investigate Displaying numbers with DOS for info about the iterative solution that is surely faster (and could be improved further by outputting the digits all at once).

Printing an array but specific values highlighted {emu8086}

I want to print this array but also highlight specific characters from said array. This is my code:
include 'emu8086.inc'
.data
animales1 db 'BUBRPQYFODFZXIQ'
db 'MSVDJVQDTLOEATF'
db 'RCZPIFYGAZLPMFN'
db 'LVWKFFBKDXHFIUW'
db 'AOSEFQEMOOTGQUR'
db 'ELLWTGNJJKAJISJ'
db 'OVCOXLUEQTSDDSP'
db 'UEAEMTNYOLVYMGI'
db 'ORREPOMJZGYPHAI'
db 'IFTLCBJFVOYHLUB'
db 'WTOWZQFRAXQRLMR'
db 'KGNYIIHHHKFUKIJ'
db 'XMLSACGMVXEYSIT'
db 'TSOESQVSEQRFNPU'
db 'ODDQMDFWRGETDLY'
lenguajes2 db 'SLKFMBCULKVYUIM'
db 'TWCDQFYIVIKUXKB'
db 'GNIWEQBOSYEMDTJ'
db 'WDHFZZPUIEDERYQ'
db 'KMTGTKAKROMUSUV'
db 'BELBLLTUVJQHCRW'
db 'UPLUBYJKNUXORLF'
db 'SGMAOOEENBOGIWR'
db 'JVSTLPTEGPPNPJW'
db 'YINCASSEMBLYTTU'
db 'CHWTIOIWORDZDRV'
db 'BRZCNRAVRWAMUNU'
db 'KOMCOUKNGQEPQVS'
db 'XXRXJUJUBEXVGGA'
db 'MNKJQKZAACVCLDW'
char db 'a'
flag db 0
;Pez= 12,27,42
;Ave= 76,92,108
indx db 5,11,26,41,45 dup (' ')
.stack
.code
.start up
mov ax,0000h
mov bx,0000h
mov cx,0000h
mov dx,0000h
lea si, animales1
;call valueInArray
call printArrays
printArrays proc
mov bx,0000h
printArray:
mov dx,0000h
mov ah, 02h
mov dl,byte ptr[si+bx]
call valueinArray
cmp flag,1
jz printSpecial
int 21h
mov dl, 20h
int 21h
add bx, 1
add cl, 1
cmp cl,15
jz nextRow
jnz printArray
nextRow:
call nwLine
add ch,1
mov cl, 00h
cmp ch,15
jz finproc
jnz printArray
printSpecial:
lea di,char
mov byte ptr[di],dl
push ax
push bx
push cx
push dx
mov bp, offset char
mov dh,00h
mov al, 1
mov bh, 0
mov bl, 1111_0000b
mov cx, 1; calculate message size.
mov dx,0000h
mov ah, 13h
int 10h
mov dl, 20h
mov ah, 02h
int 21h
pop dx
pop cx
pop bx
pop ax
add bx, 1
add cl, 1
cmp cl,15
jz nextRow
jnz printArray
finproc:
ret
printArrays endp
nwLine PROC
MOV AH,02h
MOV DX,0Ah; imprime asscii 10 (nueva linea)
INT 21h
MOV DX,0Dh; imprime asscii 13 (retorno de carro)
INT 21h
RET
nwLine ENDP
valueInArray proc
mov flag, 0
mov di,0001h
iterar:
mov dh, indx[di]
cmp dh,20h
jz finvalueproc
cmp bl,dh
jz found
add di,1
jmp iterar
found:
mov flag,1
jmp finvalueproc:
finvalueproc:
ret
valueInArray endp
exit:
end
As you can see, the array 'indx' have the positions of the chars (The first number is the effective lenght of said array) that I want to highlight so I check if bx is in the position of said character to print it highlighted.
I have two problems at the moment, the first one is the highlighted characters are printing in a kinda random position and that messes up the rest, but I think I know why the position of the highlighted character that prints is wrong, because the interrupt that I use uses dh and dl as positioners but I do not know how to make it so it continues the flow of the rest. The second problem is that the character that prints is wrong, if you run it and check the variable char, it has an 'Z' but it prints a 'T'. I really need help. Pretty please. :(
indx db 5,11,26,41,45 dup (' ')
It could be that this line is not what you think it is!
Reading your explanation I think you really meant:
indx db 5, 11, 26, 41, 45, ' '
That is the length of the array which is 5, then followed by 4 offsets to the highlighted characters and 1 space character as a list terminator.
the first one is the highlighted characters are printing in a kinda random position and that messes up the rest, but I think I know why the position of the highlighted character that prints is wrong, because the interrupt that I use uses dh and dl as positioners but I do not know how to make it so it continues the flow of the rest.
Because your code to output the highlighted character uses mov dx,0000h, the BIOS function 13h places the character in the upperleft corner of the screen and the other, 'normal' characters will continue from there.
All you have to do is to ask BIOS where the cursor is at that moment using function 03h:
Replace
mov cx, 1; calculate message size.
mov dx,0000h
mov ah, 13h
int 10h
by
mov ah, 03h ; BIOS.GetCursorAndConfiguration
int 10h ; -> CX DX
mov cx, 1 ; message size
mov ah, 13h ; BIOS.WriteString
int 10h
Function 13h fetches from ES:BP. Did you setup the ES segment register?
The second problem is that the character that prints is wrong, if you run it and check the variable char, it has an 'Z' but it prints a 'T'.
Probably resolving the first problem will also resolve the second one.
There's a better, less convoluted way to output your highlighted character.
printSpecial:
push ax
push bx
push cx
mov cx, 1 ; ReplicationCount
mov bx, 00F0h ; DisplayPage 0, Attribute BlackOnBrightWhite (11110000b)
mov al, dl ; Character
mov ah, 09h ; BIOS.WriteCharacterAndAttribute
int 10h
mov ah, 0Eh ; BIOS.TeletypeCharacter
int 10h
pop cx
pop bx
pop ax
...
Function 09h will write your character with the colors that you need, and then function 0Eh will advance the cursor normally.

Sort 10 integer numbers read from keyboard and display in ascending order

I managed to write this code for turbo debugger in assembly language which is meant to sort 10 integer numbers read from the keyboard and display them in ascending order but it keeps looping B to infinite..
The code is :
.model small
.stack 100h
.data
strg1 DB 'Insert numbers: $'
strg2 DB 'Sorted numbers: $'
Arr Db 10 dup(?)
v dw ?
.code
main proc
mov ax,#data
mov ds,ax
mov ah,9
lea dx,strg1
int 21h
mov dl,0ah
mov ah,2
int 21h
;inputs
mov di,0
mov cx,10
Input_loop:
mov ah,1
int 21h
mov arr[di],al
mov dl,0ah
mov ah,2
int 21h
inc di
loop Input_loop
mov v,0
sort:
mov di,0
mov cx,10
sub cx,v
B:
mov al,Arr[di]
cmp al,Arr[di+1]
jng C
mov al,Arr[di]
xchg al,Arr[di+1]
mov Arr[di],al
c:
inc di
loop B
inc v
cmp v,10
jne sort
;Output
mov ah,9
lea dx,strg2
int 21h
mov dl,0ah
mov ah,2
int 21h
mov di,0
mov cx,10
Output_loop:
mov dl,Arr[di]
mov ah,2
int 21h
inc di
mov dl,0ah
mov ah,2
int 21h
loop output_loop
mov ah,4ch
int 21h
main endp
end main
It is running perfectly, I can enter my desired numbers to be sorted, and then when it reaches c: , it just keeps looping B to infinite and it really makes me mad . Do you have any idea what went wrong and how can I fix it ?
Arr Db 10 dup(?)
v dw ?
In an array that has 10 elements, you can do 9 pairwise comparisons at most.
Your code does 10 comparisons and will move whatever byte is stored after the array, and that is probably a zero, down in memory!
Initialize v at 1:
mov v, 1
sort:
This is the only modification that I made and your program ran perfectly in DOSBox. I assembled the source using TASM 4.1 followed by TLINK
A better BubbleSort
Don't use BubbleSort, better algorithms exist! :-)=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Better use a register like SI instead of a memory based variable v.
Use downcounting for the outer loop count.
Because your elements are byte-sized, you can read and write two elements together.
Keep addressing modes simplest/shortest (using [di] instead of Arr[di]).
Avoid the slow LOOP instruction.
Use meaningful names for your labels.
Avoid using XCHG between a register and memory.
Use unsigned conditional jumps after comparing unsigned quantities like characters "0" to "9" (using jna instead of jng).
mov si, 10-1
Outer:
mov di, offset Arr
mov cx, si
Inner:
mov ax, [di]
cmp al, ah
jna Skip
xchg al, ah
mov [di], ax
Skip:
inc di
dec cx
jnz Inner
dec si
jnz Outer

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

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

Resources