sorting an array in emu8086

39 views Asked by At

I am trying to sort an array using a recherchemax proc (which allows me to find the maximum of an array), my idea consists of finding the maximum and then putting it in its right order everytime, I noticed that mov [si],max doesn't work and I don't know why. Here is the code I tried:


data segment
    tab db 30h,38h,35h,32h,37h,39h
    n dw 6
    max db ? 
    pos dw ?
ends

stack segment
    dw   128  dup(0)
ends

code segment
    recherchemax proc near
       mov di,0
       mov al,byte ptr tab[di]
       mov max,al
       mov pos,di
       inc di
       etq:
        mov al,byte ptr tab[di] 
        cmp al,max
        jbe negal  
        
        mov max,al
        mov pos,di
        negal:
        
        cmp di,n
        jae fin
        
        inc di
       jmp etq
        
    fin:    
    ret
start:
    mov ax, data
    mov ds, ax
    mov es, ax 
    
    mov cx,6
    mov si,offset tab
    boucle:
        call recherchemax
        mov al,max 
        add si,n 
        mov bl, byte ptr [si]
        mov byte ptr [si],al 
        mov si,0
        add si,pos
        mov byte ptr [si],bl 
        
        dec n      
    loop boucle
    
    mov ax, 4c00h 
    int 21h    
ends

end start 
1

There are 1 answers

0
Sep Roland On

I noticed that mov [si],max doesn't work and I don't know why.

The symbol max represents a byte in memory. For a MASM-style assembler like the one in emu8086, this instruction therefore is referring to 2 memory locations. That's not allowed in the 8086 instruction set. You need to transfer via an intermediate register like in: mov al, max mov [si], al.


The loop in the recherchemax proc runs for one time too many. On the first invocation eg. the index in the DI register must never be equal to the number of elements in the array. Since n is 6, the highest valid value for DI is 5. Do the inc di before the cmp di, n and if the condition stays 'below' then jump to etq. This also shaves off the extra unconditional jmp:

inc  di
cmp  di, n
jb   etq
ret

The boucle loop should not run 6 times. The recherchemax proc needs a minimum of 2 elements in order to work correctly. You may call it okay with n equal to {6, 5, 4, 3, 2} but not with n equal to 1. And because n evolves in sync with CX, you could choose to dismiss n from the program.


mov si,offset tab
boucle:
    mov al,max 
    add si,n 
    mov bl, byte ptr [si]
    mov byte ptr [si],al 
    mov si,0
    add si,pos
    mov byte ptr [si],bl 

The swapping of the elements is wrong in several ways:

  • add si, n accesses a byte outside of the array because n is too big at this moment, and on subsequent iterations of boucle the SI register is not pointing at the start of the array anymore. You need to move the label boucle: one line up.
  • mov si, 0 should be mov si, offset tab, but in this program it happens to work since tab is the very first item in the data section and therefore at offset zero.


All of the above comments should enable you to rewrite your program so it functions fine. Below is my alternative approach that is still very similar to what you were doing:

; IN (bx) OUT () MOD (al,di)
recherchemax:
    xor  di, di
    mov  al, tab[di]
    mov  max, al
    mov  pos, di
    inc  di
  etq:
    mov  al, tab[di] 
    cmp  al, max
    jbe  negal  
    mov  max, al
    mov  pos, di
  negal:
    inc  di        
    cmp  di, bx        ; BX={5,4,3,2,1}
    jbe  etq
    ret

start:
    mov  ax, data
    mov  ds, ax
    mov  es, ax 
    mov  bx, n         ; n is at least 2
    dec  bx
boucle:
    call recherchemax
    mov  al, max 
    mov  dl, tab[bx]   ; highest position in remaining array
    mov  tab[bx], al 
    mov  di, pos
    mov  tab[di], dl      
    dec  bx
    jnz  boucle
    mov  ax, 4C00h
    int  21h