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

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

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

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...

Assembly80x86 filling array with user input(names), but no repeating them

I need to fill an array with names from user input, but keep out names that are already stored in the array(ex, john,jaina,tom,bob). I got this, but it's not working.
data segment
numbers db 0
names db 220 dup (?)
buffer db 10 dup (?)
code segment
start:
mov ah, 1;
int 21h
mov numbers, ax
mov cx, numbers
lea bx, [names]
names:
onename:
lea si, [buffer]
mov ah,1;character by character
int 21h
mov [bx], al
inc bx
mov [si], al
inc si
cmp al, ',' ;end of name
je compare;
loop onename
compare:;buffer with names
lea di, [names]
check:
lea si, [buffer]
cmp si, di
jne nextname
inc si
inc di
jmp check
nextname:
cmp di, ','
je check
inc di
jmp nextname
loop names
mov ah, 1;
int 21h
mov numbers, ax
You don't initialize the counter correctly. DOS function 01h only gives you an ASCII code in AL, but you treat it as a number in AX.
You've also defined the variable numbers of type byte but later on you process it as if it were a word.
The instruction loop onename should have been jmp onename
The label onename must be placed 1 line lower, just under the assignment to SI.

assembly program to sort in special way? help please?

8086 assembly language program that sorts an array as follows:
smallest value in the array should be placed in the first cell.
second smallest value in the last cell.
third smallest value in the second cell of the array.
fourth smallest value placed in the before-last cell of the
array.
• The above procedure continues until the array is fully sorted.
Note that in the above-described sorting technique, the large values in the initial array
will end up being placed at the middle part of the array
here is my code it sorting but in normal way :
org 100h
.MODEL SMALL
.DATA
TABLE DB 9,2,6,8,5,1
B DB 6 DUP(0)
VAL1 DB 5
NL DB ' ','$'
.CODE
MOV AX,#DATA
MOV DS,AX
LEA BX,TABLE
MOV DL,VAL1
LBL1:
LEA BX,TABLE
MOV CL,5
LBL2:
MOV AL,[BX]
MOV DL,[BX+1]
CMP AL,DL
JB LBL3
MOV [BX],DL
MOV [BX+1],AL
LBL3:
INC BX
LOOP LBL2
MOV DL,VAL1
DEC DL
MOV VAL1,DL
CMP DL,00
JNE LBL1
MOV CL,6
LEA BX,TABLE
DISPLAY:
LEA DX,NL
MOV AH,09H
INT 21H
MOV DL,[BX]
ADD DL,30H
MOV AH,02H
INT 21H
INC BX
INC BX
LOOP DISPLAY
MOV AH,4CH
INT 21H
ret
Replace:
mov cl, val1
by:
mov cl, [val1]
This way it moves the content of val1 (the number 5) to cl. In the code above, it would only move the offset of val1 to cl (the same as lea cl, val1).

How to loop in assembly language

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

Resources