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.
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.Because you erroneously use
mov si,axbased 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 ismov [si], al.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 ?
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.
One solution
I have replaced your
inc blbymov bl, 1. Both instructions are the same length, but theinc blcould 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:
or you don't add a filler and just replace
mov si, 0200hbymov si, OFFSET tab.