Help with assembly language

cupcake
Hi, I wanna ask.. suppose I have an array and a constant called threshold in my data segments

array db 1,2,3,4,5,6
threshold equ 5

I want to compare my array elements with the constant, and only display/print the number which is less that the threshold, if there are none, display the none message

this is what I have done so far...

cmpr_thr:
mov dl,10d ;display line
mov ah,2h
int 21h
mov al,array[bx]
cmp al,threshold
jl print
inc bx ;increment index register
dec cl ;decrement counter
jnz cmpr_thr

print:
mov ah,2
mov dl,array[bx] ;display data on screen
int 21h
inc bx ;next piece
dec cl ;decrement counter
jnz print

can someone enlighten me?
it's not working as I expect

Mentor
Hi, I wanna ask.. suppose I have an array and a constant called threshold in my data segments

array db 1,2,3,4,5,6
threshold equ 5

I want to compare my array elements with the constant, and only display/print the number which is less that the threshold, if there are none, display the none message

this is what I have done so far...

cmpr_thr:
mov dl,10d ;display line
mov ah,2h
int 21h
mov al,array[bx]
cmp al,threshold
jl print
inc bx ;increment index register
dec cl ;decrement counter
jnz cmpr_thr

print:
mov ah,2
mov dl,array[bx] ;display data on screen
int 21h
inc bx ;next piece
dec cl ;decrement counter
jnz print

can someone enlighten me?
it's not working as I expect

In the code you show you are using bx for the index into the array, but I don't see that you have initialized it to zero anywhere. When you increment bx, if you start with a garbage value, incrementing it gives you garbage + 1, which is still garbage.

Also, I don't see that you have initialized cx anywhere, so decrementing cl also gives you a garbage value.

cupcake
1) how to initialized the array = 0??

I have initialized bx and cx above, sorry I didn't copy my whole code..

start:
mov ax,data ;initialise data segment
mov ds,ax

xor ch,ch ;initialize counter
mov cl,count
xor bx,bx ;initialize index register

It seems my cmp isn't working cause it is still printing the whole array

Mentor
1) how to initialized the array = 0??
You don't need to and you don't want to initialize the array to zero.
I have initialized bx and cx above, sorry I didn't copy my whole code..
Code:
start:
mov ax,data ;initialise data segment
mov ds,ax

xor	ch,ch		;initialize counter
mov	cl,count
xor	bx,bx		;initialize index register
You don't have to zero out CX if you store count in it, but I don't see where count is initialized.

Code:
      count dw 5 ; or whatever
.
.
.

mov cx, count  ; store count in CX

BTW, put [ code] and [ /code] tags (without the leading spaces) around your code to preserve your indentation.

If you're still having problems, be sure to include all of your code.

It seems my cmp isn't working cause it is still printing the whole array

Homework Helper
It looks to me like your print routine never jumps back to cmp_threshold. It just stays in print until count = 0.

Code:
print:
mov ah,2
mov dl,array[bx] ;display data on screen
int 21h
inc bx ;next piece
dec cl ;decrement counter
jnz print

Mentor
That's a good point. It seems to me that the print routine is trying to do too much. The only thing it should do is print one element in the array. When control is transferred to print: the bx register should have the index of the array element to be printed. It shouldn't be incrementing or decrementing any registers, and it should jump back to itself.

The main program should keep track of how many array elements are less than the threshold value. If there are none after all comparisons have been made, then the "none" message should be displayed.

cupcake
thanks you all for your inputs...
Here I post all my code to avoid the misunderstanding..
first half of the code, basically just printing the no of elements in array and display them..

Code:
stk	segment	stack
db	128 DUP(?)
stk	ends
;

data segment
prompt1 db 'Your array: $' array db 1,2,3,4,5,6 ;declare a byte array len equ$-array ;"$" means current address. thr_prompt db 'Your threshold number is:$'
msg db 'The number of elements of your array is:$' threshold equ 5 data ends code segment assume cs:code, ds:data, ss:stk count equ 6 start: mov ax,data ;initialise data segment mov ds,ax xor ch,ch ;initialize counter mov cl,count xor bx,bx ;initialize index register display_msg: lea dx, prompt1 mov ah,09 int 21h jmp key key: mov al,array[bx] ;store the number at the array mov ah,2 ;display the number at the screen mov dl,al add dl,30h int 21h inc bl ;increment index register dec cl ;decrement counter jnz key done: xor ch,ch ;initialize counter mov cl,count xor bx,bx ;initialize index register mov ah,2 ;sent space mov dl,20h int 21h jmp elements elements: mov dl,10d ;display line mov ah,2h int 21h mov ah,09 mov dx, offset msg int 21h mov ah,2 ;sent space mov dl,01h mov dl,20h int 21h mov dl,len add dl,30h ;convert the ascii value to integer number mov ah,2 int 21h thr_msg: mov dl,10d ;display line mov ah,2h int 21h mov ah,09 mov dx, offset thr_prompt int 21h mov ah,2 ;sent space mov dl,01h mov dl,20h int 21h mov dl,offset threshold add dl,30h mov ah,2h int 21h [COLOR="Red"]cmpr_thr: mov dl,10d ;display line mov ah,2h int 21h mov al,array[bx] ;mov bx,threshold cmp al,threshold jl print inc bx dec cl jnz cmpr_thr print: mov ah,2 mov al,array[bx] ;display data on screen add al, 30h int 21h inc bx ;next piece dec cl jnz print[/COLOR] exit1: mov ah,4ch int 21h code ends end start the red portions are where the problem is oke... 1) It looks to me like your print routine never jumps back to cmp_threshold. It just stays in print until count = 0. So, after decrementing the cl, I should jmp to cmp_threshold instead of jnz print? That's a good point. It seems to me that the print routine is trying to do too much. The only thing it should do is print one element in the array. When control is transferred to print: the bx register should have the index of the array element to be printed. It shouldn't be incrementing or decrementing any registers, and it should jump back to itself. Ok, so if bx should not incrementing or decrementing, so how do I traverse the array? firstly, I thought by incrementing bx, it will increment the index of the array -__- The main program should keep track of how many array elements are less than the threshold value. If there are none after all comparisons have been made, then the "none" message should be displayed. yes, theoretically I know this, but I don't know how to translate it into programing language :( Mentor Regarding the sections you have in red, here are some thoughts. 1) thr_msg is supposed to print Your threshold number is: 5 After this string is printed to the screen, execution flows to the cmpr_thr block. The cmp instruction compares each element of the array with 5. If al < threshold, the code jumps to the print section, but doesn't execute the statements following jl print; namely, inc bx, dec cl, and jnz cmpr_thr. One fix for this is to have the print section print only a single number, instead of having it printing all the elements of the array. I think this would work. Code:  cmp al, threshold jsr print . . . print: mov ah, 2 mov al, array[bx] add al, 30h int 21h ret Alternatively, if you don't know about JSR (jump to subroutine) and RET (return), you could jump to your print routine the way you did it (with jl print), and then after the int 21h instruction in your print routine, you could jump back (using jmp) to a label right after the jl print instruction. 2) In cmpr_thr, when CL is 0, execution flows into the first instruction after the print label. You don't want this to happen, since you have presumably already printed all the elements in your array. You can prevent this from happening by putting an unconditional jump (i.e., jmp exit) right after the jnz cmpr_thr instruction at the end of cmpr_thr. 3) To keep track of how many elements in the array are less than the threshold value, you could increment a new variable in your print routine. Be sure to initialize it to zero up in your data declaration section, and increment it in the print routine. Each time the print routine is executed, this variable would be incremented. When you're all done, print its value. Some other comments. You are using comments, which is a good thing. Keep it up. It's even more important to liberally comment your assembly code than it is for C or C++ or other higher-level code. Some of your comments aren't as helpful as they could be, though. Here are some examples: ; sent space -- you are actually printing a space character, not sending it. mov dl,10d ;display line -- Here you're about to print ASCII 10, which is a line feed, to start a new line. It would be more helpful to say which string you're printing. Some of your labels are pretty much indecipherable, such as thr_msg and cmpr_thr. It doesn't take that much more typing to make a label whose purpose is clear from its name. You have the same typo in two places Code:  mov dl,01h mov dl,20h After you move 1 to DL, you move 20h to DL, so the first mov instruction is wasted effort. Get rid of mov dl, 01h. This is in elements and thr_msg. You have a jmp statement to the next statement, like this: Code:  jmp elements elements: It's never a good idea to jump to the very next statement, since control will flow there naturally. Take out that jmp statement. cupcake Regarding the sections you have in red, here are some thoughts. 1) thr_msg is supposed to print Your threshold number is: 5 After this string is printed to the screen, execution flows to the cmpr_thr block. The cmp instruction compares each element of the array with 5. If al < threshold, the code jumps to the print section, but doesn't execute the statements following jl print; namely, inc bx, dec cl, and jnz cmpr_thr. One fix for this is to have the print section print only a single number, instead of having it printing all the elements of the array. I think this would work. Code:  cmp al, threshold jsr print . . . print: mov ah, 2 mov al, array[bx] add al, 30h int 21h ret Alternatively, if you don't know about JSR (jump to subroutine) and RET (return), you could jump to your print routine the way you did it (with jl print), and then after the int 21h instruction in your print routine, you could jump back (using jmp) to a label right after the jl print instruction. I don't know about JSR, and I think there's no such mnemonics like that? I have checked my textbook but there is no JSR.. so I go with JL.. here my revision, after I read your thought.. please tell me if I miss something Code: cmpr_thr: mov dl,10d ;display line mov ah,2h int 21h mov al,array[bx] cmp al,threshold jl print next: inc bx dec cl jnz cmpr_thr jmp exit1 print: mov ah,2 ;display the number at the screen mov al,array[bx] ;store the number at the array add al,30h int 21h jmp next inc bx dec cl jnz print But, it's still not working... it never print the array after the comparison 2) In cmpr_thr, when CL is 0, execution flows into the first instruction after the print label. You don't want this to happen, since you have presumably already printed all the elements in your array. You can prevent this from happening by putting an unconditional jump (i.e., jmp exit) right after the jnz cmpr_thr instruction at the end of cmpr_thr. I have edited my code above, did you meant something like that? I have put the conditional jump after jnz_cmpr 3) To keep track of how many elements in the array are less than the threshold value, you could increment a new variable in your print routine. Be sure to initialize it to zero up in your data declaration section, and increment it in the print routine. Each time the print routine is executed, this variable would be incremented. When you're all done, print its value. Ok, this one I'm not so sure how to do, especially how to incrementing it in the print routine and how to display it then.. and btw, what will the value be after I printed it? so, will it be print the number which is less than my threshold number? Some other comments. You are using comments, which is a good thing. Keep it up. It's even more important to liberally comment your assembly code than it is for C or C++ or other higher-level code. Some of your comments aren't as helpful as they could be, though. Here are some examples: ; sent space -- you are actually printing a space character, not sending it. mov dl,10d ;display line -- Here you're about to print ASCII 10, which is a line feed, to start a new line. It would be more helpful to say which string you're printing. Some of your labels are pretty much indecipherable, such as thr_msg and cmpr_thr. It doesn't take that much more typing to make a label whose purpose is clear from its name. You have the same typo in two places Code:  mov dl,01h mov dl,20h After you move 1 to DL, you move 20h to DL, so the first mov instruction is wasted effort. Get rid of mov dl, 01h. This is in elements and thr_msg. You have a jmp statement to the next statement, like this: Code:  jmp elements elements: It's never a good idea to jump to the very next statement, since control will flow there naturally. Take out that jmp statement. Noted, Thank you very much for your comments, it's very helpful since I just start learning assembly language this month...I will study more.. Mentor Regarding JSR - that's a Motorola 68000 instruction. The one I meant was CALL. Sorry about that. Here's what I had in mind. Code:  cmp al, threshold call print . . . print: mov ah, 2 mov al, array[bx] add al, 30h int 21h ret In your code, Code: cmpr_thr: mov dl,10d ;display line mov ah,2h int 21h mov al,array[bx] cmp al,threshold jl print next: inc bx dec cl jnz cmpr_thr jmp exit1 print: mov ah,2 ;display the number at the screen mov al,array[bx] ;store the number at the array add al,30h int 21h jmp next inc bx <--- take out dec cl <--- take out jnz print <--- take out the instructions after jmp next never execute, so why are they there? Also, the JMP instruction is an unconditional jump, unlike conditional jumps such as jl, jle, etc. Conditional jumps transfer control based on some condition. As far as what exactly should be printed, I think we have strayed from what you said in your original post. cupcake said: I want to compare my array elements with the constant, and only display/print the number which is less that the threshold, if there are none, display the none message According to what you said, you should NOT print every element in the array, but only those that are less than the threshold. And there is no need to print how many elements were less than the threshold, so disregard what I said about this in my earlier post. To print the elements in the array that are less than the threshold, loop through the array as you are doing, and when you come to an array element that is less than the threshold, jump to your print routine (jl print will do the job). The print routine should not increment or decrement anything. All it should do is print the array element at the current index. After the int 21h that prints the number, jump (unconditionally) to the statement right after jl print. The output should be 1 2 3 4 When you have gone completely through the array jump to some statement at the end of your program. cupcake To print the elements in the array that are less than the threshold, loop through the array as you are doing, and when you come to an array element that is less than the threshold, jump to your print routine (jl print will do the job). The print routine should not increment or decrement anything. All it should do is print the array element at the current index. After the int 21h that prints the number, jump (unconditionally) to the statement right after jl print. The output should be 1 2 3 4 When you have gone completely through the array jump to some statement at the end of your program. hmm..ok now, how to loop through the array? I should use loop instruction, shouldn't I? I'm not really sure how to do the looping.. here.. currently in my code, I have Code: mov al,array[bx] cmp al,threshold jl print so, I should do loop array after cmp, al threshold? Homework Helper I think the most useful way to write assembly code is to first write the code in a procedural language like Pascal, so that you get the structure right. Then translate it to assembly. It'll be easier translating individual language elements like if/then/else blocks than coding them in assembly from scratch. cupcake ok, wait.. I have successfully print the numbers which are less than threshold number.. but, my problem...is now about printing the message if there are none of numbers less than threshold.. where should I put the code, cause this one works only when there are no number less than threshold, if there is.. it will print number less than threshold but bad things is it also print the none message.. Code: stk segment stack db 128 DUP(?) stk ends ; data segment prompt1 db 'Your array:$'
array db 2,3,4,5,6,7 ;declare a byte array
len equ $-array ;"$" means current address.
thr_prompt db 'Your threshold number is: $' msg db 'The number of elements of your array is:$'
threshold equ 1
msg_thr db 'Numbers less than threshold: $' none_msg db 'There are no numbers less than threshold$'

data ends

code segment
assume cs:code, ds:data, ss:stk
count equ 6
start:
mov ax,data ;initialise data segment
mov ds,ax
xor	ch,ch		;initialize counter
mov	cl,count
xor	bx,bx		;initialize index register
xor dx,dx

display_msg:
lea dx, prompt1
mov ah,09
int 21h

key:
mov	al,array[bx]	;store the number at the array
mov	ah,2		;display the number at the screen
mov	dl,al
int	21h
inc	bl		;increment index register
dec	cl		;decrement counter
jnz	key

done1:
xor	ch,ch		;initialize counter
mov	cl,count
xor	bx,bx		;initialize index register
mov	ah,2		;printing a space
mov	dl,20h
int 21h

elements:
mov dl,10d ;display line
mov ah,2h
int 21h
mov ah,09
mov dx, offset msg
int 21h
mov ah,2 ;sent space
mov dl,01h
mov dl,20h
int 21h
mov dl,len
add dl,30h ;convert the ascii value to integer number
mov ah,2
int 21h

thr_msg:
mov dl,10d ;display line
mov ah,2h
int 21h
mov ah,09
mov dx, offset thr_prompt
int 21h
mov ah,2 ;sent space
mov dl,20h
int 21h
mov dl,offset threshold
mov ah,2h
int 21h

mov dl,10d ;display line
mov ah,2h
int 21h

cmpr_thr:
mov al,array[bx]
cmp al,threshold
jl print

next:
inc bl
dec cl
jnz cmpr_thr
jmp none_thr

print:
mov ah,2
mov	al,array[bx]	;store the number at the array;
mov dl, al
int	21h
jmp next

none_thr:
mov al,array[bx]
cmp al,threshold
jge print_none
jmp exit1

print_none:
mov ah,09
mov dx, offset none_msg
int 21h

exit1:
mov ah,4ch
int 21h

code ends

end start

Last edited:
cupcake
sorry double post

my current output:
for
Code:
array db 2,3,4,5,6,7
threshold number equ 5

it will print the output

Code:
2,3,4 there no number less than threshold

Mentor
You need another variable that keeps track of how many times you have printed a number that was less than threshold. Recall that the only time you enter the print section is when you have found a number less than threshold.

I would use a variable named threshold_count, adding a line to initialize it in the same place where you initialize count.

In your print routine, increment count like this:
Code:
print:
inc threshold_count
mov ah,2

After you have gone through the entire array and made your comparisons, check the value of threshold_count. If it is still zero, display your message that none of the array elements were less than threshold. If it is greater than zero, then you don't need to display that message, and you should be done.

You have a block of code whose purpose I don't understand.
Code:
none_thr:
mov al,array[bx]
cmp al,threshold
jge print_none
jmp exit1
I don't see the need for doing a comparison as you are in the first line above. All the comparisons should have been done in cmpr_thr.

cupcake
Ok, Thanks a lot~

I got it..

Last edited:
Mentor
There are still what look to be extra lines of code.

Code:
done1:
xor	ch,ch		;initialize counter
mov	cl,count
xor	bx,bx		;initialize index register
mov	ah,2		;printing a space
mov	dl,20h
int 21h

Why do you have the label done1? You don't jump to it from anywhere. Also, why are you initializing ch and moving count into cl? You don't seem to be doing anything with it. All that's happening in this block of code is that you are printing a space. If that's all you're doing, you don't need the extra code to intialize CX, and you don't need a label.

You also have a typo that I mentioned before, in the elements block.
Code:
	mov dl,01h
mov dl,20h

In the code above, you move 1 into DL, and then you move 20h into DL. You should remove the first of these two lines. It doesn't cause any harm to do this, but having it there is likely to cause confusion (including to you).

cupcake
There are still what look to be extra lines of code.

Code:
done1:
xor	ch,ch		;initialize counter
mov	cl,count
xor	bx,bx		;initialize index register
mov	ah,2		;printing a space
mov	dl,20h
int 21h

Why do you have the label done1? You don't jump to it from anywhere. Also, why are you initializing ch and moving count into cl? You don't seem to be doing anything with it. All that's happening in this block of code is that you are printing a space. If that's all you're doing, you don't need the extra code to intialize CX, and you don't need a label.

because, if I don't initialize it again, the output would be very strange, it prints out some strange characters (probably asciii) I have tried to remove it before, but the results became worse.. maybe I'll leave it as it is.. and come back again after I do all the questions.

You also have a typo that I mentioned before, in the elements block.
Code:
	mov dl,01h
mov dl,20h

In the code above, you move 1 into DL, and then you move 20h into DL. You should remove the first of these two lines. It doesn't cause any harm to do this, but having it there is likely to cause confusion (including to you).
Ok thanks.. I have removed it, I forgot to take it out before.. thanks

anyway, I have another question, so, the question says.. after I've done with threshold's problem, now I have to seek for even number in the array, count them and display the average result.. this is what I have done so far... my problem is a slightly the same with before, I don't know how to print the result.. and later compute the average..

Code:
stk	segment	stack
db	128 DUP(?)
stk	ends
;

data segment
prompt1 db 'Your array: $' array db 2,3,4,5,6,7 ;declare a byte array len equ$-array ;"$" means current address. thr_prompt db 'Your threshold number is:$'
threshold equ 5
threshold_count db 0
msg_thr db 'Numbers less than threshold: $' none_msg db 'There are no numbers less than threshold$'

data ends

code segment
assume cs:code, ds:data, ss:stk
count equ 6
start:
mov ax,data ;initialise data segment
mov ds,ax
xor	ch,ch		;initialize counter
mov	cl,count
xor	bx,bx		;initialize index register
xor dx,dx

display_msg:
lea dx, prompt1
mov ah,09
int 21h

key:
mov	al,array[bx]	;store the number at the array
mov	ah,2		;display the number at the screen
mov	dl,al
int	21h
inc	bl		;increment index register
dec	cl		;decrement counter
jnz	key

done1:
xor	ch,ch		;initialize counter
mov	cl,count
xor	bx,bx		;initialize index register
mov	ah,2		;printing a space
mov	dl,20h
int 21h

elements:
mov dl,10d ;display line
mov ah,2h
int 21h
mov ah,09
mov dx, offset msg
int 21h
mov ah,2 ;sent space
mov dl,01h
mov dl,20h
int 21h
mov dl,len
add dl,30h ;convert the ascii value to integer number
mov ah,2
int 21h

thr_msg:
mov dl,10d ;display line
mov ah,2h
int 21h
mov ah,09
mov dx, offset thr_prompt
int 21h
mov ah,2 ;sent space
mov dl,20h
int 21h
mov dl,offset threshold
mov ah,2h
int 21h

mov dl,10d ;display line
mov ah,2h
int 21h

cmpr_thr:
mov al,array[bx]
cmp al,threshold
jl print

next:
inc bl
dec cl
jnz cmpr_thr
mov al,threshold_count
cmp al,0
jz print_none
jmp exit1

print:
inc threshold_count
mov ah,2
mov	al,array[bx]	;store the number at the array;
mov dl, al
int	21h
jmp next

print_none:
mov ah,09
mov dx, offset none_msg
int 21h

[COLOR="Red"]check_even:
mov si,offset array

again:
mov ax,[si]
ror ax,01
jnc even_no ; CF=0 even number
inc bx
jmp next1

even_no:
inc dx
je print_even

next1:
dec cl
jnz again

print_even:
mov dl,10d ;display line
mov ah,2h
int 21h
mov ah,2
mov	al,array[bx]	;store the number at the array;
mov dl, al
int	21h
[/COLOR]
exit1:
mov ah,4ch
int 21h

code ends

end start

so, for example my array = 2,3,4,5,8
output will be 2+4+8 = 14 <- display 14

I need some advise again..in such a way should I print the result? thanks beforehand

Last edited:
Mentor
If your array contains 2, 3, 4, 5, 8, the output should be something like this:
3 numbers found
average is 4

I see that you have all of your code from the threshold problem. I would advise you get rid of nearly all of that old code, and keep only what you need.

Based on your description of what is required for this problem, you need to loop through the array only once. (I'm assuming that you don't need to print each element in the array.)

You need two variables: one to count the even numbers, and one to accumulate the total of the even numbers.

Here's the algorithm.
Code:
even_count = 0
total = 0

For each element in the array
If array[bx] is even
increment even_count
total = total + array[bx]
endif

print even_count
calculate average
print average

To calculate the average use the DIV instruction. Put the number to be divided (the dividend) into the AX register, and use the number to divide by as the operand.

I think this should work.

Code:
   mov ax, total
div even_count

After the DIV instruction executes, the quotient will be in AL and the remainder will be in AH. Here I'm assuming that total is a byte value.

If the operand is a word value, DIV divides the contents of DX:AX by what's in the operand, and stores the result in AX and the remainder in DX.

Mentor
By the way, DIV performs integer division, so 14/3 == 4. If you need floating point division, you'll have to use the floating point FDIV instruction, plus you need to check that there is actually a floating point unit (FPU) on the machine.

My guess is that integer division will be fine.

saniaa83
specially thanks to cupcake and to all other members.