The flowchart below is used to sort in ascending order an array of length N = 100h starting at address [200h], following the principle:
Principle:
Sort each pair of successive values in the array (if they are not sorted in ascending order, swap them).
For each value of the secondary counter DX, the values to be sorted are pointed to by [SI] and [SI + 1]. Since the array has N values and the first pass is done comparing between the second-to-last and the last value, the primary counter CX will have to traverse (N - 1) values, i.e., CX = N - 1, N - 2, ..., 2, 1. This solution allows stopping the process when it is observed that the array is already sorted after one pass of the secondary counter DX through all its relevant values, even before reaching the limit of the primary counter (CX = 1).
For each pass (i) (meaning for each value of the primary counter CX = N - i), SI varies from its initial value (200h) to the value (200h + N - i - 1), giving (N - i) values. Therefore, the counter DX will take the following (N - i) values:
This translates to:
DX = N - i, N - i - 1, N - i - 2, ..., 2, 1
DX = CX, CX - 1, CX - 2, ..., 2, 1
The flowchart:
start
cx=n-1
etq:
dx=cx
si=200h
bl=0
al=[si]
bcl:
al<=[si+1]
if yes:
si=si+1
dx=dx-1
if no:
permute al,[si+1]
si=al
bl=bl+1
si=si+1
dx=dx-1
zf=1 ?
if yes:
bl=0?
if yes:
end
if no:
cx=cx-1
z=1?
if yes:
end
if no:
etq
if no:
bcl
i tried translating it to the code below:
; multi-segment executable file template.
data segment
tab db 30h,35h,23h,37h,38h,39h,31h
n dw 7
ends
stack segment
dw 128 dup(0)
ends
code segment
start:
; set segment registers:
mov ax, data
mov ds, ax
mov es, ax
sub n,1
mov cx,n
etq:
mov dx,cx
mov si,200h
mov bl,0
mov al,[si]
bcl:
cmp al,[si+1]
jbe con
mov dl,al
mov al,[si+1]
mov [si+1],dl
mov si,ax
inc bl
con:
inc si
dec dx
jnz bcl
cmp bl,0
je fin
dec cx
jnz bcl
fin:
mov ax, 4c00h ; exit to operating system.
int 21h
ends
end start ; set entry point and stop the assembler.
but it doesn't change anything.
Sort each pair of successive values in the array (if they are not sorted in ascending order, swap them).
Because you erroneously keep mov al,[si]
outside of the bcl loop, you are not processing pairs of successive values. You end up comparing between non-adjacent elements.
Sort each pair of successive values in the array (if they are not sorted in ascending order, swap them).
Because you erroneously use mov si,ax
based on an error in the pseudo code, the pointer SI gets destroyed and there's no telling what the results will be. The correct instruction is mov [si], al
.
dec cx jnz bcl
Here the pseudo code had it right, but you erroneously wrote bcl instead of etq. I find these names bcl (boucle) and etq (étiquette) a bit too generic. Might I suggest InnerLoop and OuterLoop ?
mov dl,al
You shouldn't use the DL register within the inner loop since you are already using DX as the inner loop counter. Remember that DL is the low byte of DX, just like DH is the high byte of DX.
dec n
mov cx, n
OuterLoop:
mov dx, cx
mov si, 0200h
mov bl, 0
InnerLoop:
mov ax, [si] ; Read two adjacent byte-sized elements
cmp al, ah ; Compare
jbe con
mov [si+1], al ; Swap low -> high
mov [si], ah ; Swap high -> low
mov bl, 1 ; Testify the swap
con:
inc si
dec dx
jnz InnerLoop
test bl, bl
jz fin
dec cx
jnz OuterLoop
fin:
I have replaced your inc bl
by mov bl, 1
. Both instructions are the same length, but the inc bl
could backfire on you (producing a so-called 'false positive') in case the number of swap operations happens to be a multiple of 256.
[edit]
The task description talks about an array located at address 200h, but the program that you have written has placed the array behind its own label and that happens to be at offset address 0 in the data segment
.
Either you satisfy the task description by adding a filler:
db 200h dup(0)
tab db 30h,35h,23h,37h,38h,39h,31h
n dw 7
or you don't add a filler and just replace mov si, 0200h
by mov si, OFFSET tab
.